Package ldaptor :: Module entry
[hide private]
[frames] | no frames]

Source Code for Module ldaptor.entry

  1  import random, base64 
  2  from zope.interface import implements 
  3  from twisted.internet import defer 
  4  from twisted.python.util import InsensitiveDict 
  5  from ldaptor import interfaces, attributeset, delta 
  6  from ldaptor.protocols.ldap import distinguishedname, ldif, ldaperrors 
  7   
  8  try: 
  9      from hashlib import sha1 
 10  except ImportError: 
 11      from sha import sha as sha1 
 12   
 13   
14 -def sshaDigest(passphrase, salt=None):
15 if salt is None: 16 salt = '' 17 for i in range(8): 18 salt += chr(random.randint(0, 255)) 19 20 s = sha1() 21 s.update(passphrase) 22 s.update(salt) 23 encoded = base64.encodestring(s.digest()+salt).rstrip() 24 crypt = '{SSHA}' + encoded 25 return crypt
26
27 -class BaseLDAPEntry(object):
28 implements(interfaces.ILDAPEntry) 29 dn = None 30
31 - def __init__(self, dn, attributes={}):
32 """ 33 34 Initialize the object. 35 36 @param dn: Distinguished Name of the object, as a string. 37 38 @param attributes: Attributes of the object. A dictionary of 39 attribute types to list of attribute values. 40 41 """ 42 self._attributes=InsensitiveDict() 43 self.dn = distinguishedname.DistinguishedName(dn) 44 45 for k,vs in attributes.items(): 46 if k not in self._attributes: 47 self._attributes[k] = [] 48 self._attributes[k].extend(vs) 49 50 for k,vs in self._attributes.items(): 51 self._attributes[k] = self.buildAttributeSet(k, vs)
52
53 - def buildAttributeSet(self, key, values):
54 return attributeset.LDAPAttributeSet(key, values)
55
56 - def __getitem__(self, key):
57 return self._attributes[key]
58
59 - def get(self, key, default=None):
60 return self._attributes.get(key, default)
61
62 - def has_key(self, key):
63 return key in self._attributes
64
65 - def __contains__(self, key):
66 return self.has_key(key)
67
68 - def keys(self):
69 return self._attributes.keys()
70
71 - def items(self):
72 return self._attributes.items()
73
74 - def __str__(self):
75 a=[] 76 77 objectClasses = list(self.get('objectClass', [])) 78 objectClasses.sort() 79 a.append(('objectClass', objectClasses)) 80 81 l=list(self.items()) 82 l.sort() 83 for key, values in l: 84 if key.lower() != 'objectclass': 85 vs = list(values) 86 vs.sort() 87 a.append((key, vs)) 88 return ldif.asLDIF(self.dn, a)
89
90 - def __eq__(self, other):
91 if not isinstance(other, BaseLDAPEntry): 92 return 0 93 if self.dn != other.dn: 94 return 0 95 96 my=self.keys() 97 my.sort() 98 its=other.keys() 99 its.sort() 100 if my!=its: 101 return 0 102 for key in my: 103 myAttr=self[key] 104 itsAttr=other[key] 105 if myAttr!=itsAttr: 106 return 0 107 return 1
108
109 - def __ne__(self, other):
110 return not self==other
111
112 - def __len__(self):
113 return len(self.keys())
114
115 - def __nonzero__(self):
116 return True
117
118 - def __repr__(self):
119 x={} 120 for key in self.keys(): 121 x[key]=self[key] 122 keys=self.keys() 123 keys.sort() 124 a=[] 125 for key in keys: 126 a.append('%s: %s' % (repr(key), repr(list(self[key])))) 127 attributes=', '.join(a) 128 return '%s(%s, {%s})' % ( 129 self.__class__.__name__, 130 repr(str(self.dn)), 131 attributes)
132
133 - def diff(self, other):
134 """ 135 Compute differences between this and another LDAP entry. 136 137 @param other: An LDAPEntry to compare to. 138 139 @return: None if equal, otherwise a ModifyOp that would make 140 this entry look like other. 141 """ 142 assert self.dn == other.dn 143 if self == other: 144 return None 145 146 r = [] 147 148 myKeys = set(self.keys()) 149 otherKeys = set(other.keys()) 150 151 addedKeys = list(otherKeys - myKeys) 152 addedKeys.sort() # for reproducability only 153 for added in addedKeys: 154 r.append(delta.Add(added, other[added])) 155 156 deletedKeys = list(myKeys - otherKeys) 157 deletedKeys.sort() # for reproducability only 158 for deleted in deletedKeys: 159 r.append(delta.Delete(deleted, self[deleted])) 160 161 sharedKeys = list(myKeys & otherKeys) 162 sharedKeys.sort() # for reproducability only 163 for shared in sharedKeys: 164 165 addedValues = list(other[shared] - self[shared]) 166 if addedValues: 167 addedValues.sort() # for reproducability only 168 r.append(delta.Add(shared, addedValues)) 169 170 deletedValues = list(self[shared] - other[shared]) 171 if deletedValues: 172 deletedValues.sort() # for reproducability only 173 r.append(delta.Delete(shared, deletedValues)) 174 175 return delta.ModifyOp(dn=self.dn, modifications=r)
176
177 - def bind(self, password):
178 return defer.maybeDeferred(self._bind, password)
179
180 - def _bind(self, password):
181 for digest in self.get('userPassword', ()): 182 if digest.startswith('{SSHA}'): 183 raw = base64.decodestring(digest[len('{SSHA}'):]) 184 salt = raw[20:] 185 got = sshaDigest(password, salt) 186 if got == digest: 187 return self 188 raise ldaperrors.LDAPInvalidCredentials
189
190 - def hasMember(self, dn):
191 for memberDN in self.get('member', []): 192 if memberDN == dn: 193 return True 194 return False
195
196 - def __hash__(self):
197 return hash(self.dn)
198
199 -class EditableLDAPEntry(BaseLDAPEntry):
200 implements(interfaces.IEditableLDAPEntry) 201
202 - def __setitem__(self, key, value):
203 new=self.buildAttributeSet(key, value) 204 self._attributes[key] = new
205
206 - def __delitem__(self, key):
207 del self._attributes[key]
208
209 - def undo(self):
210 raise NotImplementedError
211
212 - def commit(self):
213 raise NotImplementedError
214
215 - def move(self, newDN):
216 raise NotImplementedError
217
218 - def delete(self):
219 raise NotImplementedError
220
221 - def setPassword(self, newPasswd, salt=None):
222 crypt = sshaDigest(newPasswd, salt) 223 self['userPassword'] = [crypt]
224