Package buildbot :: Package status :: Package web :: Module auth
[frames] | no frames]

Source Code for Module buildbot.status.web.auth

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16   
 17  import os 
 18  from zope.interface import Interface, Attribute, implements 
 19  from buildbot.status.web.base import HtmlResource, ActionResource 
 20  from buildbot.status.web.base import path_to_authfail 
 21   
 22  from buildbot.process.users import users 
 23   
24 -class IAuth(Interface):
25 """ 26 Represent an authentication method. 27 28 Note that each IAuth instance contains a link to the BuildMaster that 29 will be set once the IAuth instance is initialized. 30 """ 31 32 master = Attribute('master', "Link to BuildMaster, set when initialized") 33
34 - def authenticate(self, user, passwd):
35 """Check whether C{user} / C{passwd} are valid."""
36
37 - def getUserInfo(self, user):
38 """return dict with user info. 39 dict( fullName="", email="", groups=[]) 40 """
41
42 - def errmsg(self):
43 """Get the reason authentication failed."""
44
45 -class AuthBase:
46 master = None # set in status.web.baseweb 47 err = "" 48
49 - def errmsg(self):
50 return self.err
51
52 - def getUserInfo(self, user):
53 """default dummy impl""" 54 return dict(userName=user, fullName=user, email=user+"@localhost", groups=[ user ])
55
56 -class BasicAuth(AuthBase):
57 implements(IAuth) 58 """Implement basic authentication against a list of user/passwd.""" 59 60 userpass = [] 61 """List of user/pass tuples.""" 62
63 - def __init__(self, userpass):
64 """C{userpass} is a list of (user, passwd).""" 65 for item in userpass: 66 assert isinstance(item, tuple) or isinstance(item, list) 67 u, p = item 68 assert isinstance(u, str) 69 assert isinstance(p, str) 70 self.userpass = userpass
71
72 - def authenticate(self, user, passwd):
73 """Check that C{user}/C{passwd} is a valid user/pass tuple.""" 74 if not self.userpass: 75 self.err = "Bad self.userpass data" 76 return False 77 for u, p in self.userpass: 78 if user == u and passwd == p: 79 self.err = "" 80 return True 81 self.err = "Invalid username or password" 82 return False
83
84 -class HTPasswdAuth(AuthBase):
85 implements(IAuth) 86 """Implement authentication against an .htpasswd file.""" 87 88 file = "" 89 """Path to the .htpasswd file to use.""" 90
91 - def __init__(self, file):
92 """C{file} is a path to an .htpasswd file.""" 93 assert os.path.exists(file) 94 self.file = file
95
96 - def authenticate(self, user, passwd):
97 """Authenticate C{user} and C{passwd} against an .htpasswd file""" 98 if not os.path.exists(self.file): 99 self.err = "No such file: " + self.file 100 return False 101 # Fetch each line from the .htpasswd file and split it into a 102 # [user, passwd] array. 103 lines = [l.rstrip().split(':', 1) 104 for l in file(self.file).readlines()] 105 # Keep only the line for this login 106 lines = [l for l in lines if l[0] == user] 107 if not lines: 108 self.err = "Invalid user/passwd" 109 return False 110 # This is the DES-hash of the password. The first two characters are 111 # the salt used to introduce disorder in the DES algorithm. 112 hash = lines[0][1] 113 from crypt import crypt #@UnresolvedImport 114 res = hash == crypt(passwd, hash[0:2]) 115 if res: 116 self.err = "" 117 else: 118 self.err = "Invalid user/passwd" 119 return res
120
121 -class UsersAuth(AuthBase):
122 """Implement authentication against users in database""" 123 implements(IAuth) 124
125 - def authenticate(self, user, passwd):
126 """ 127 It checks for a matching uid in the database for the credentials 128 and return True if a match is found, False otherwise. 129 130 @param user: username portion of user credentials 131 @type user: string 132 133 @param passwd: password portion of user credentials 134 @type passwd: string 135 136 @returns: boolean via deferred. 137 """ 138 d = self.master.db.users.getUserByUsername(user) 139 def check_creds(user): 140 if user: 141 if users.check_passwd(passwd, user['bb_password']): 142 return True 143 self.err = "no user found with those credentials" 144 return False
145 d.addCallback(check_creds) 146 return d
147
148 -class AuthFailResource(HtmlResource):
149 pageTitle = "Authentication Failed" 150
151 - def content(self, request, cxt):
152 templates =request.site.buildbot_service.templates 153 template = templates.get_template("authfail.html") 154 return template.render(**cxt)
155
156 -class AuthzFailResource(HtmlResource):
157 pageTitle = "Authorization Failed" 158
159 - def content(self, request, cxt):
160 templates =request.site.buildbot_service.templates 161 template = templates.get_template("authzfail.html") 162 return template.render(**cxt)
163
164 -class LoginResource(ActionResource):
165
166 - def performAction(self, request):
167 authz = self.getAuthz(request) 168 d = authz.login(request) 169 def on_login(res): 170 if res: 171 status = request.site.buildbot_service.master.status 172 root = status.getBuildbotURL() 173 return request.requestHeaders.getRawHeaders('referer', 174 [root])[0] 175 else: 176 return path_to_authfail(request)
177 d.addBoth(on_login) 178 return d
179
180 -class LogoutResource(ActionResource):
181
182 - def performAction(self, request):
183 authz = self.getAuthz(request) 184 authz.logout(request) 185 status = request.site.buildbot_service.master.status 186 root = status.getBuildbotURL() 187 return request.requestHeaders.getRawHeaders('referer',[root])[0]
188