Mercurial > p > roundup > code
comparison roundup/hyperdb.py @ 4480:1613754d2646
Fix first part of Password handling security issue2550688
(thanks Joseph Myers for reporting and Eli Collins for fixing)
Small change against original patch: We still accept plaintext passwords
(in known_schemes) when parsing encrypted password (e.g. from database).
This way existing databases with plaintext passwords continue to work (I
don't know of any, this would need patching on the users side) and all
regression tests pass.
| author | Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net> |
|---|---|
| date | Thu, 14 Apr 2011 12:24:59 +0000 |
| parents | 34dce76bb202 |
| children | 9bbf3758c16a |
comparison
equal
deleted
inserted
replaced
| 4479:0bdcb1e7f7ce | 4480:1613754d2646 |
|---|---|
| 70 class Password(_Type): | 70 class Password(_Type): |
| 71 """An object designating a Password property.""" | 71 """An object designating a Password property.""" |
| 72 def from_raw(self, value, **kw): | 72 def from_raw(self, value, **kw): |
| 73 if not value: | 73 if not value: |
| 74 return None | 74 return None |
| 75 m = password.Password.pwre.match(value) | 75 try: |
| 76 if m: | 76 return password.Password(encrypted=value, strict=True) |
| 77 # password is being given to us encrypted | 77 except password.PasswordValueError, message: |
| 78 p = password.Password() | 78 raise HyperdbValueError, \ |
| 79 p.scheme = m.group(1) | 79 _('property %s: %s')%(kw['propname'], message) |
| 80 if p.scheme not in 'SHA crypt plaintext'.split(): | 80 |
| 81 raise HyperdbValueError, \ | |
| 82 ('property %s: unknown encryption scheme %r') %\ | |
| 83 (kw['propname'], p.scheme) | |
| 84 p.password = m.group(2) | |
| 85 value = p | |
| 86 else: | |
| 87 try: | |
| 88 value = password.Password(value) | |
| 89 except password.PasswordValueError, message: | |
| 90 raise HyperdbValueError, \ | |
| 91 _('property %s: %s')%(kw['propname'], message) | |
| 92 return value | |
| 93 def sort_repr (self, cls, val, name): | 81 def sort_repr (self, cls, val, name): |
| 94 if not val: | 82 if not val: |
| 95 return val | 83 return val |
| 96 return str(val) | 84 return str(val) |
| 97 | 85 |
| 1305 elif isinstance(prop, Date): | 1293 elif isinstance(prop, Date): |
| 1306 value = date.Date(value) | 1294 value = date.Date(value) |
| 1307 elif isinstance(prop, Interval): | 1295 elif isinstance(prop, Interval): |
| 1308 value = date.Interval(value) | 1296 value = date.Interval(value) |
| 1309 elif isinstance(prop, Password): | 1297 elif isinstance(prop, Password): |
| 1310 pwd = password.Password() | 1298 value = password.Password(encrypted=value) |
| 1311 pwd.unpack(value) | |
| 1312 value = pwd | |
| 1313 params[propname] = value | 1299 params[propname] = value |
| 1314 elif action == 'create' and params: | 1300 elif action == 'create' and params: |
| 1315 # old tracker with data stored in the create! | 1301 # old tracker with data stored in the create! |
| 1316 params = {} | 1302 params = {} |
| 1317 r.append((nodeid, date.Date(jdate), user, action, params)) | 1303 r.append((nodeid, date.Date(jdate), user, action, params)) |
| 1335 node = self.db.getnode(self.classname, nodeid) | 1321 node = self.db.getnode(self.classname, nodeid) |
| 1336 return iter_roles(node['roles']) | 1322 return iter_roles(node['roles']) |
| 1337 | 1323 |
| 1338 def has_role(self, nodeid, *roles): | 1324 def has_role(self, nodeid, *roles): |
| 1339 '''See if this node has any roles that appear in roles. | 1325 '''See if this node has any roles that appear in roles. |
| 1340 | 1326 |
| 1341 For convenience reasons we take a list. | 1327 For convenience reasons we take a list. |
| 1342 In standard schemas only a user has a roles property but | 1328 In standard schemas only a user has a roles property but |
| 1343 this may be different in customized schemas. | 1329 this may be different in customized schemas. |
| 1344 ''' | 1330 ''' |
| 1345 roles = dict.fromkeys ([r.strip().lower() for r in roles]) | 1331 roles = dict.fromkeys ([r.strip().lower() for r in roles]) |
