1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import ldap, ldap.schema
22
23
24 from Crypto.Hash import MD4
25 from Crypto.Cipher import DES
26
27 import easyLDAP_defaults
28 from easyLDAP_exceptions import *
29
30 from easyLDAP_utils import *
31 from easyLDAP_utils import _attrtype, _attropt, _attrdesc, _unique
32 from easyLDAP_bind import *
33 from easyLDAP_class_base import *
34 from easyLDAP_class_cache import *
35
37
38 _ldap_cacheobject = None
39 _init_dn = ''
40
58
59 - def __init__(self, dn_or_cacheobject, bind_dn=None, bind_pw=None, config_defaults=EASY_LDAP, update_schema_cache=False, use_cache_history=True, ldapsession=None):
74
76 """Creates a deepcopy of the easyLDAP object class."""
77 result = self.__class__(self.get_object_dn())
78 memo[id(self)] = result
79
80 result._ldap_cacheobject = copy.deepcopy(self._ldap_cacheobject,memo)
81
82 result.LDAPuri = self.LDAPuri
83 result.LDAPserver = self.LDAPserver
84 result.BindDN = self.BindDN
85 result.BindPW = self.BindPW
86 result.BaseDN = self.BaseDN
87 result.AdminDN = self.AdminDN
88 result.PeopleBaseDN = self.PeopleBaseDN
89 result.GroupBaseDN = self.GroupsBaseDN
90 result.HostsBaseDN = self.HostsBaseDN
91 result.MailAliasesBaseDN = self.MailAliasesBaseDN
92 result.AutomountBaseDN = self.AutomountBaseDN
93 result.LDAPServerCharsetEncoding = self.LDAPServerCharsetEncoding
94 result.posix_availableUidNumbers = self.posix_availableUidNumbers
95 result.posix_availableGidNumbers = self.posix_availableGidNumbers
96 if (self.BindDN != 'anonymous') and self.has_dn(self.BindDN):
97 result.bind_norefresh(self.BindDN, self.BindPW)
98
99 result.objectClasses=self.objectClasses
100 result.attributeTypes=self.attributeTypes
101 result.matchingRules=self.matchingRules
102 result.ldapSyntaxes=self.ldapSyntaxes
103
104 return result
105
108
109
112
113
117
118
121
122
125
126
129
130
134
135
138
139
141 """
142 thisClass.get_object_rdn()
143
144 returns the relative DN of the cached easyLDAPobject
145 (i.e. the first protion of the object's DN).
146 """
147 return string.split(self.get_object_dn(), ',')[0]
148
149
151 """
152 """
153 attrdescs_list = to_list_of_strings(attrdescs)
154
155 oid_based_attrdescs = []
156 for attrdesc in attrdescs_list:
157 oid = self.map_attrtypes2oids(_attrtype(attrdesc))[0]
158 oid_based_attrtypes = self.map_oid2attrtypes(oid)
159
160 oid_based_attrdesc = None
161 intersection = intersect(oid_based_attrtypes, self.get_used_attrtypes())
162 if intersection:
163
164 attrtype = intersection[0]
165 if _attropt(attrdesc):
166 oid_based_attrdesc = '%s;%s' % (attrtype, _attropt(attrdesc))
167 else:
168 oid_based_attrdesc = attrtype
169 if capitalize:
170 oid_based_attrdesc = self._rewrite_attrtype_names(oid_based_attrdesc)
171
172 if not oid_based_attrdesc:
173 raise easyLDAP_exceptions.ATTRDESC_NOT_SET
174
175 if type(attrdescs) is types.StringType:
176
177 return oid_based_attrdesc
178
179 else:
180 oid_based_attrdescs.append(oid_based_attrdesc)
181
182 return oid_based_attrdescs
183
184
185
194
195
196
198 """
199 get_attrtype_values('myATTRTYPE')
200
201 returns a dictionary that contains all attribute descriptions
202 in the easyLDAP object cache that contain the attribute type
203 'myATTRTYPE'.
204
205 This method is handy for e.g. viewing all attribute type's
206 translations.
207
208 On failure, the method returns an empty dictionary.
209 """
210 from easyLDAP_utils import _attrtype
211 value_dict = {}
212 if self.map_attrtype2oid(_attrtype(attrtype))[0] in self.get_used_attrtype_oids():
213 for option in self.get_used_attropt(_attrtype(attrtype)):
214 if option:
215 value_dict['%s;%s' %(_attrtype(attrtype),option)] = self.get_attrdesc_values('%s;%s' % (_attrtype(attrtype),option))
216 else:
217 value_dict[_attrtype(attrtype)] = self.get_attrdesc_values(_attrtype(attrtype))
218 return value_dict
219
220 return {}
221
222
225
226
229
230
233
234
237
238
240 """
241 thisClass.get_usedobjectclasses([mySINGLELDAPOBJECT])
242
243 returns a list of objectClasses that are used in the current easyLDAP
244 object. If - by some reason - the cache is empty, an empty list
245 is returned.
246
247 Another LDAP object than the one currently cached
248 can be analyzed by passing 'mySINGLELDAPOBJECT'. The
249 lengths of the passed LDAP object has to be 1.
250 """
251 try:
252 return self._ldap_cacheobject.get_cacheobject_attrdesc('objectClass')
253 except easyLDAP_exceptions.ATTRDESC_NOT_SET:
254 return []
255
256
258 """
259 thisClass.get_used_attrdescs()
260
261 returns a list of all attribute descriptions that are used in the current easyLDAP
262 object.
263 """
264 from easyLDAP_utils import _attrtype, _attropt
265 return [ self._rewrite_attrtype_names(attrdesc) for attrdesc in self._get_object_data().keys() ]
266
267
269 """
270 thisClass.has_objectclass_set('myOBJECTCLASS'):
271
272 returns True, if the objectClass 'myOBJECTCLASS' is set
273 in the cached easyLDAP object.
274 """
275 return (objectclass.lower() in [ obc.lower() for obc in self.get_used_objectclasses() ])
276
277
279 """
280 thisClass.has_attrtype_set('myATTRTYPE'):
281
282 returns True, if the attribute type 'myATTRTYPE' is set
283 in the cached easyLDAP object. The attribute type
284 is checked on an OID basis.
285 """
286 return (attrtype.lower() in self.get_used_attrtypes())
287
288
290 """
291 thisClass.has_attrdesc_set('myATTRDESC'):
292
293 returns True, if the attribute 'myATTRDESC' is set
294 in the cached easyLDAP object. The attribute type
295 is checked on an OID basis.
296 """
297 try:
298 dummy = self.get_attrdesc_values(attrdesc)
299 return True
300 except easyLDAP_exceptions.ATTRDESC_NOT_SET:
301 return False
302
303
305 """
306 thisClass.has_value('myVALUE'):
307
308 returns True, if the value 'myVALUE' is set
309 in the cached easyLDAP object, regardless from
310 the attribute it is set for.
311 """
312 for checkAttribute, checkValue in self._get_object_data().items():
313 if value in checkValue:
314 return True
315 return False
316
317
319 """
320 thisClass.has_attrdesc_values_set('myATTRDESC', 'myVALUE'):
321
322 returns True, if the list of values 'myVALUES'
323 is identical to those found in the cached easyLDAP
324 object's attribute description 'myATTRDESC'.
325 """
326 if self.has_attrdesc_set(attrdesc):
327 attributeOIDs = self.map_attrtypes2oids(attrdesc)
328 for checkAttribute in self.get_used_attrtypes():
329 if (attributeOIDs == self.map_attrtypes2oids(checkAttribute)) and (self.get_attrdesc_values(checkAttribute) == values):
330 return True
331 return False
332
333
335 """
336 thisClass.has_attrdesc_value_set_in_values('myVALUE','myATTRDESC'):
337
338 returns True, if the value 'myVALUE' is set
339 in the cached easyLDAP object's attribute description
340 'myATTRDESC' (amongst other possible values).
341 """
342 if self.has_attrdesc_set(attrdesc):
343
344
345 attrOIDsinFunctionParam = self.map_attrtypes2oids(_attrtype(attrdesc))
346 for checkAttributeDesc in self.get_used_attrtypes():
347 attrOIDsinObject = self.map_attrtypes2oids(checkAttributeDesc)
348 if (attrOIDsinFunctionParam == attrOIDsinObject) and (_attropt(checkAttributeDesc) == _attropt(attrdesc)):
349 if value in self.get_attrdesc_values(checkAttributeDesc):
350 return True
351
352 return False
353
354
356 """
357 thisClass.refresh_cache()
358
359 loads/refreshes the easyLDAP object cache. This method should be the only
360 easyLDAP module code that performs a read operation on the actual
361 LDAP directory server.
362
363 BEWARE: This method is called, when thisClass is initiated.
364
365 If the given DN (at __init__ time) exists in the LDAP directory,
366 this method:
367
368 - reads the DN\'s data LDAP directory from the LDAP directory,
369 - checks and repairs objectClass dependencies violations,
370 - moves the data in the easyLDAP cache.
371
372 If the given DN is new to the LDAP directory, this method:
373
374 - creates an empty easyLDAP object cache,
375 - marks the object as a new object, so the first
376 thisClass.flush_cache() operation will be 'ldap.add_s'
377 as opposed to 'ldap.modify_s'
378
379 Once the easyLDAP cache is filled with the DN data all modification
380 will be performed in the easyLDAP object cache. Once you are done,
381 use thisClass.flush_cache() to update the LDAP directory\'s
382 data.
383
384 WARNING: this method tries to repair buggy LDAP objects. If it finds an
385 attribute that does not have an objectClass set, the method will
386 try to find a usable objectClass (it will take the first it finds,
387 which might not be wanted). If there is no such objectClass
388 in the server\'s LDAP schema, the invalid attributes will be purged
389 from the object. This is a repair functionality and should not come to
390 use...
391 """
392 from easyLDAP_utils import _attrtype
393
394
395
396 try:
397
398
399 ldap_import = ldapDictionaryDecode(self.ldapsession.search_s(self.get_object_dn(), ldap.SCOPE_BASE, 'objectClass=*'), config_defaults=self.CONFIG)
400 self._rewrite_names_to_fit_ldapschema(ldap_import)
401
402 if self._ldap_cacheobject is None:
403 self._new_object(ldap_import)
404 else:
405
406
407 self._ldap_cacheobject.set_cacheobject(ldap_import)
408
409 self._ldap_cacheobject.disable_cache_history()
410
411
412 if not 'ABSTRACT' in self.get_used_objectclasses():
413 self.add_objectclasses(self.get_used_objectclasses())
414
415
416
417
418
419
420
421 for attrdesc in self.get_used_attrdescs():
422 if attrdesc != 'objectClass':
423 possibleObjectClasses = [ o.lower() for o in self.map_attrtype2objectclasses(_attrtype(attrdesc)) ]
424 if possibleObjectClasses and not intersect([o.lower() for o in self.get_used_objectclasses() ], possibleObjectClasses):
425 if len(possibleObjectClasses) == 1:
426 self.add_objectclasses(possibleObjectClasses)
427 else:
428 self.del_attrdesc(attrdesc)
429
430 self.push_cache_history()
431
432 except ldap.NO_SUCH_OBJECT:
433
434
435 if self._ldap_cacheobject is None:
436 self._new_object([(self.get_object_dn(), {})])
437 else:
438
439
440 self._ldap_cacheobject.set_cacheobject([(self.get_object_dn(), {})])
441 self.push_cache_history()
442
443 except ldap.SERVER_DOWN:
444
445
446 raise easyLDAP_exceptions.SERVER_UNAVAILABLE
447
448 self._ldap_cacheobject.enable_cache_history()
449
450
452 """
453 thisClass.map_diff2modlist()
454
455 returns a list of changes that have been applied to
456 the easyLDAP object chache. The format of this list
457 is conformant with the modlist structure in python-
458 ldap that is used for the methods
459
460 ldap.modify() / ldap.modify_s()
461 """
462 return generate_modlist(self.get_cache_reference(dn=self.get_object_dn(), scope=ldap.SCOPE_BASE), copy.deepcopy(self.get_object()))
463
464
466 """
467 thisClass.map_diff2modlist()
468
469 returns a list of changes applied to the easyLDAP
470 object cache that these changes can be undone with.
471 The format of this list is conformant with the modlist
472 structure in python-ldap that is used for the methods
473
474 ldap.modify() / ldap.modify_s()
475 """
476 return self.generate_modlist(copy.deepcopy(self.get_object()),self.get_cache_reference(dn=self.get_object_dn(), scope=ldap.SCOPE_BASE))
477
478
480 """
481 thisClass.map_diff2ldif()
482
483 returns the changes applied to the easyLDAP object cache in
484 ldif format. The method returns a python list in which each
485 item represents a line of the text base ldif format.
486 """
487 return self.generate_ldif(self.get_cache_reference(dn=self.get_object_dn(), scope=ldap.SCOPE_BASE), copy.deepcopy(self.get_object()))
488
489
491 """
492 thisClass.map_diff2ldif()
493
494 returns ldif output that can undo the changes applied to the
495 easyLDAP object cache. The method returns a python list in which
496 each item represents a line of the text base ldif format.
497 """
498 return self.generate_ldif(copy.deepcopy(self.get_object()), self.get_cache_reference(dn=self.get_object_dn(), scope=ldap.SCOPE_BASE))
499
500
502 """
503 thisClass.flush_cache()
504
505 writes the easyLDAP object cache to the LDAP directory. This method
506 should be the only easyLDAP module code that performs a write operation
507 on the actual LDAP directory server.
508
509 If the given DN existed in the LDAP directory at __init__ time,
510 this method:
511
512 - checks, if the cached DN still exists in the LDAP directory
513 (otherwise, it switches to object creation mode).
514 - flushes modifications and additions to the easyLDAP object
515 cache to the server's LDAP directory.
516
517 If the given DN was new to the LDAP directory at __init__ time,
518 this method:
519
520 - checks, if the cached DN is still new to the LDAP directory
521 (otherwise, it switches to object modification mode).
522 - checks, if the underlying DN still exists in the directory. If
523 not the flush_cache() operation will fail.
524 - adds easyLDAP object cache to the LDAP directory.
525
526 If the easyLDAP object cache does not need a flush_cache() operation
527 (as it is up-to-date), the flush will not be performed (i.e. fail).
528 """
529
530
531
532
533
534
535
536
537 if (self._get_object_data() == {}) and self.has_dn(self.get_object_dn()):
538 try:
539 self.ldapsession.delete_s(self.get_object_dn())
540 return True
541
542 except ldap.INSUFFICIENT_ACCESS:
543 raise easyLDAP_exceptions.INSUFFICIENT_ACCESS
544
545
546 else:
547
548 modlist = self.map_diff2modlist()
549
550 if modlist != []:
551 try:
552 if not self.has_dn(self.get_object_dn()):
553 addlist = []
554 for mod in modlist:
555 addlist.append((mod[1], mod[2]))
556 self.ldapsession.add_s(self.get_object_dn(), addlist)
557 else:
558 self.ldapsession.modify_s(self.get_object_dn(), modlist)
559 return True
560
561 except ldap.INSUFFICIENT_ACCESS:
562 raise easyLDAP_exceptions.INSUFFICIENT_ACCESS
563 else:
564
565 return True
566
567
569 """
570 thisClass.add_objectclass('myOBJECTCLASS'|['myOBJECTCLASS1',
571 'myOBJECTCLASS2', ...])
572
573 adds one ore more objectClass(es) and all needed SUPerior
574 objectClasses to the cached easyLDAP object. Attributes
575 that - according to the server's LDAP schema - MUST be
576 present will be set to default values regarding their
577 proposed syntaxes in thisClass.LDAPSyntaxes.
578
579 The default values are stored in thisClass.templateLDAPSyntaxValues.
580 """
581 if type(objectclasses) is types.StringType:
582 objectclasses = [objectclasses]
583
584
585 objectclasses = [ objcl.lower() for objcl in self.check_objectclass_dependencies(objectclasses) ]
586
587
588
589 for this_objectClass in objectclasses:
590
591
592 if (not self.has_attrdesc_set('objectClass') or (this_objectClass not in self.get_attrdesc_values('objectClass'))):
593
594 if self.objectClassesDict.has_key(this_objectClass):
595
596
597 for mustSetAttr in self.objectClassesDict[this_objectClass]['MUST']:
598
599 if mustSetAttr != 'objectclass':
600
601 try:
602
603 if self.attributeTypesDict[mustSetAttr]['OID'] not in self.get_used_attrtype_oids():
604 mustUseAttrSyntaxOID = self.map_attrtype2ldapsyntaxoid(mustSetAttr) or 'NO SPECIFIED SYNTAX'
605 self._ldap_cacheobject.set_cacheobject_attrdesc(self._rewrite_attrtype_names(mustSetAttr), self.ldapSyntaxesDict[mustUseAttrSyntaxOID]['DEFAULT'])
606 except KeyError:
607
608
609 raise easyLDAP_exceptions.NO_SUCH_ATTRIBUTE
610
611
612 if self.has_attrdesc_set('objectClass'):
613 self.add_attrdesc_values('objectClass', this_objectClass)
614 else:
615 self.set_attrdesc('objectClass', this_objectClass)
616
617 else:
618
619
620 raise easyLDAP_exceptions.NO_SUCH_OBJECTCLASS
621
622
623 self.push_cache_history()
624
625 return True
626
627
629 """
630 thisClass.get_used_attrtype_oids()
631
632 returns a list of those attribute OIDs, that are used the
633 LDAP object 'mySINGLEOBJECT'. This list is taken from
634 the server's LDAP schema.
635 """
636 from easyLDAP_utils import _attrtype
637 oidList=[]
638 for key in self._get_object_data().keys():
639 oidList.append(self.attributeTypesDict[_attrtype(key).lower()]['OID'])
640
641 return _unique(oidList)
642
643
645 """
646 thisClass.has_oid_set('myOID')
647
648 checks if the given OID 'myOID' is set in the
649 LDAP object 'mySINGLELDAPOBJECT'. If so, the method's
650 result is True.
651 """
652 if oid in self.get_used_attrtype_oids():
653 return True
654
655 return False
656
657
659 """
660 thisClass.del_objectclass('myOBJECTCLASS'|['myOBJECTCLASS1',
661 'myOBJECTCLASS2', ...])
662
663 deletes one ore more objectClass(es) from the cached
664 easyLDAP object. All attributes that only occur in the
665 deleted objectClass(es) are also removed - so be careful!
666
667 The method will abort ...
668
669 if one of the given objectClass names are not set in
670 the easyLDAP object cache.
671
672 The method ignores ...
673
674 objectClasses that are to be deleted, but are needed
675 as a SUPerior objectClass by another objectClass.
676 """
677
678 if type (del_these_objectClasses) is not types.ListType:
679 del_these_objectClasses = [del_these_objectClasses]
680 del_these_objectClasses = [ o.lower() for o in del_these_objectClasses ]
681
682
683
684
685 setObjectClasses = [ o.lower() for o in self.get_attrdesc_values('objectClass') ]
686 for delObjectClass in del_these_objectClasses:
687
688 try:
689
690
691 delObjectClassIndex = setObjectClasses.index(delObjectClass)
692 if delObjectClass in setObjectClasses:
693 del setObjectClasses[delObjectClassIndex]
694
695 except ValueError:
696
697
698 raise easyLDAP_exceptions.NO_SUCH_OBJECTCLASS_SET
699
700
701 modifiedObjectClasses = self.check_objectclass_dependencies(setObjectClasses)
702
703
704 self.set_attrdesc('objectClass', modifiedObjectClasses)
705
706
707 for delObjectClass in del_these_objectClasses:
708 allowedOIDs = []
709
710
711 for remainingObjectClass in [ o.lower() for o in self.get_attrdesc_values('objectClass') ]:
712
713
714 allowedOIDs = allowedOIDs + self.map_attrtypes2oids(self.objectClassesDict[remainingObjectClass]['MUST'] +
715 self.objectClassesDict[remainingObjectClass]['MAY'])
716
717
718 checkAttributes = self.objectClassesDict[delObjectClass]['MUST']+self.objectClassesDict[delObjectClass]['MAY']
719
720
721 for checkAttr in checkAttributes:
722 checkAttrOID = self.map_attrtypes2oids(checkAttr)
723 if (checkAttrOID == []) or (checkAttrOID[0] not in allowedOIDs):
724 if self._get_object_data().has_key(self._rewrite_attrtype_names(checkAttr)):
725 self.del_attrtype(checkAttr)
726
727
728 self.push_cache_history()
729
730 return True
731
732
734 """
735 thisClass.modify_attrdesc('myATTRDESC',
736 'myVAL'|['myVAL1', 'myVAL2', ...]
737 easyLDAP_ADDATTR|easyLDAP_REPLACEATTR
738 )
739
740 modifies attributes of an easyLDAP object in the cache. The operations
741 easyLDAP_ADDATTR and easyLDAP_REPLACEATTR have several meanings, depending
742 on the situation:
743
744 easyLDAP_ADDATTR:
745 - attribute is not yet set: attribute is added and given values
746 are set for this attribute,
747 - attribute is already set: values are added to the already
748 existing values, if possible (cf. singleValues in LDAP schemas),
749 - if one of the given values is already set the method will ignore
750 it (unlike python-ldap).
751 easyLDAP_REPLACEATTR:
752 - attribute is set: completely replace old values by given values
753 - attribute is not set: set attribute with given values
754 """
755 from easyLDAP_utils import _attrtype, _attropt, ia5string
756
757 if type(attrdesc) is not types.StringType:
758 raise TypeError
759
760 attrdesc = self._rewrite_attrtype_names(attrdesc)
761
762 attrtype_syntax = self.map_attrtype2ldapsyntax(_attrtype(attrdesc))
763 attrtype_maxlen = self.map_attrtype2valuemaxlen(_attrtype(attrdesc))
764 attrtype_value_pattern = attrtype_syntax['REGEXP']
765 for val in to_list_of_strings(values):
766 if not re.match(attrtype_value_pattern, val):
767 raise easyLDAP_exceptions.INVALID_VALUE_SYNTAX
768 if attrtype_maxlen and len(val) > attrtype_maxlen:
769 raise easyLDAP_exceptions.VALUE_TOO_LONG
770
771
772 if self.has_valid_attrtype(_attrtype(attrdesc)):
773
774
775 if type(values) is types.StringType:
776 values = [values]
777
778
779
780 if self.map_attrtype2ldapsyntaxoid(attrdesc) == '1.3.6.1.4.1.1466.115.121.1.26':
781 values = [ ia5string(value) for value in values ]
782
783
784
785 if _attrtype(attrdesc).lower() == 'objectclass':
786 values = self._rewrite_objectclass_names(values)
787
788
789 if _attrtype(attrdesc).lower() != 'objectclass' and self.attrtype_needs_objectclass(_attrtype(attrdesc)):
790
791 neededObjectClasses = self.map_attrtype2objectclasses(_attrtype(attrdesc))
792
793 ok = [ oc for oc in self.get_used_objectclasses() if oc.lower() in neededObjectClasses ]
794
795 if not ok:
796
797
798 if (len(neededObjectClasses) == 1):
799 self.add_objectclasses(neededObjectClasses[0])
800 else:
801
802 raise easyLDAP_exceptions.ATTRIBUTE_NEEDS_OBJECTCLASS
803
804
805
806 attrOID = self.map_attrtypes2oids(_attrtype(attrdesc))[0]
807 if attrOID not in self.get_used_attrtype_oids():
808 self._ldap_cacheobject.set_cacheobject_attrdesc(self._rewrite_attrtype_names(attrdesc), [])
809
810
811
812 elif _attropt(attrdesc) and (_attropt(attrdesc) not in self.get_used_attroptions(_attrtype(attrdesc))):
813 self._ldap_cacheobject.set_cacheobject_attrdesc(self._rewrite_attrtype_names(attrdesc), [])
814
815
816 else:
817 pass
818
819 if mod_type == easyLDAP_REPLACEATTR:
820
821
822
823
824
825
826 for mappedAttrType in self.map_oid2attrtypes(self.map_attrtype2oid(attrdesc)[0]):
827 if mappedAttrType in self.get_used_attrtypes():
828 break
829
830
831 mappedAttrDesc = _attrdesc(mappedAttrType,_attropt(attrdesc))
832
833
834 if self.is_singlevalueattr(mappedAttrType) and len(values) > 1:
835
836 raise easyLDAP_exceptions.SINGLE_VALUE
837
838 else:
839 self._ldap_cacheobject.set_cacheobject_attrdesc(self._rewrite_attrtype_names(mappedAttrDesc), values)
840
841 if mod_type == easyLDAP_ADDATTR:
842
843
844 _set_attrdesc_values = self.get_attrdesc_values(attrdesc)
845 if self.is_singlevalueattr(_attrtype(attrdesc)) and len(_set_attrdesc_values ) >= 1:
846
847
848
849 raise easyLDAP_exceptions.SINGLE_VALUE
850
851 else:
852 for value in values:
853
854
855
856 if value not in _set_attrdesc_values:
857 _set_attrdesc_values = _set_attrdesc_values + [value]
858 self._ldap_cacheobject.set_cacheobject_attrdesc(attrdesc, _set_attrdesc_values)
859
860 return True
861 else:
862
863 raise easyLDAP_exceptions.NO_SUCH_ATTRIBUTE
864
865
867 """
868 thisClass.del_attrdesc_value('myATTRDESC', 'myVALUE' ignore_case={True|FALSE})
869
870 deletes the value 'myVALUE' from the LDAP attribute description 'myATTRDESC' in the
871 currently cached object.
872
873 If 'myVALUE' is the only value for 'myATTRDESC', the whole attribute
874 is removed from the cached easyLDAP object.
875
876 The method returns True on successful deletion.
877 """
878
879 attrdesc = self._rewrite_attrtype_names(attrdesc)
880 if self.has_attrdesc_set(attrdesc):
881
882 try:
883 self._ldap_cacheobject.del_cacheobject_attrdesc_values(attrdesc, value, ignore_case=ignore_case)
884
885
886 except ValueError:
887
888 raise easyLDAP_exceptions.VALUE_NOT_SET
889
890 else:
891
892 raise easyLDAP_exceptions.NO_SUCH_ATTRIBUTE_SET
893
894
912
913
915 """
916 thisClass.del_attrtype('myATTRTYPE')
917
918 deletes all entries for attribute type 'myATTRTYPE'
919 from the cached easyLDAP object. Be aware that all subentries
920 of the attribute type 'myATTRTYPE' will be removed (e.g.
921 all language options with one shot).
922
923 The method returns True on successful deletion.
924 """
925 from easyLDAP_utils import _attrtype
926
927
928 if by_oid:
929 attrtypes = self.get_attrtype_aliases(attrtype)
930 else:
931 attrtypes = [attrtype]
932
933 attrtypes = self._rewrite_attrtype_names(attrtypes)
934
935 self._ldap_cacheobject._temp_disable_cache_history()
936
937
938 no_attrdesc_found = True
939 for this_attrtype in attrtypes:
940 if self.has_attrtype_set(this_attrtype):
941 for attrDesc in self.get_used_attrdescs():
942 if _attrtype(this_attrtype) == _attrtype(attrDesc):
943 self._ldap_cacheobject.del_cacheobject_attrdesc(attrDesc)
944 no_attrdesc_found = False
945
946 if no_attrdesc_found:
947
948 raise easyLDAP_exceptions.NO_SUCH_ATTRIBUTE_SET
949
950 self._ldap_cacheobject._temp_enable_cache_history()
951 self._ldap_cacheobject._push_cache_history()
952
953
955 """
956 thisClass.set_attr('myLDAP_ATTRDESC',
957 'myVALUE'|['myVALUE1', 'myVALUE2', ...])
958
959 is a wrapper for
960
961 thisClass._modify_attrdesc('myLDAP_ATTRDESC',
962 'myVALUE'|['myVALUE1', 'myVALUE2', ...],
963 easyLDAP_REPLACEATTR)
964
965 or
966
967 thisClass.del_attrdesc('myLDAP_ATTRIBUTE')
968
969 depending on the attribute description's context...
970 """
971
972 if (value == '') or (value == ['']):
973 if self.has_attrdesc_set(attrdesc):
974 return self.del_attrdesc(attrdesc)
975
976
977 else:
978 retval= self._modify_attrdesc(attrdesc, value, easyLDAP_REPLACEATTR)
979 if self.is_naming_attrdesc(attrdesc):
980 self.set_naming_attrdesc(attrdesc)
981 return retval
982
983
985 """
986 thisClass.set_attr('myATTRDESCDICT)
987
988 helps copy+pasting a whole attribute type from one easyLDAP object
989 into another easyLDAP object.
990
991 Little HOWTO:
992
993 o connect to two easyLDAP objects. Let's call them ,,source" and ,,target".
994 o retrieve all attribute descriptions (including all subentries) of a certain
995 attribute type 'myATTRTYPE' from easyLDAPobject ,,source" with
996
997 my_attrtype = source.get_attrtype_values('myATTRTYPE')
998
999 o paste the retrieved data (a python dictionary) into easyLDAPobject
1000 ,,target" with
1001
1002 target.set_attrtype(my_attrtype)
1003
1004 o flush the easyLDAP object cache of ,,target" with
1005
1006 target.flush_cache()
1007
1008 If necessary objectClasses can be detected automagically they will be
1009 added silently. If not, the method returns a list of possible objectClasses
1010 that all provide the attribute type of your interest.
1011
1012 The structure of myATTRDESCDICT is expected to be an excerpt from
1013 a python-ldap object
1014
1015 {
1016 'attrtype;attropt1': ['val1','val2'],
1017 'attrtype;attropt2': [...],
1018 ...
1019 }
1020
1021 Keys of myATTRDESCDICT must alwasy have the same attribute type.
1022 The attribute options must be supported by LDAPv3 protocol. Attribute
1023 description values must be given as multi-valued or single-valued
1024 lists (depending on the attribute's properties in the server's schema).
1025 """
1026 from easyLDAP_utils import _attrtype
1027
1028 try:
1029
1030
1031 attrType = _attrtype(attrtype_dict.keys()[0])
1032
1033
1034 for attrDesc in self._rewrite_attrtype_names(this_attrtype_dict.keys()):
1035 if _attrtype(attrDesc) != attrType:
1036
1037 raise easyLDAP_exceptions.INVALID_ATTRIBUTETYPE
1038
1039
1040 for attrTypeAlias in self.get_attrtype_aliases(attrType):
1041 self.del_attrtype(attrTypeAlias)
1042
1043 retval = True
1044
1045 for attrDesc in attrtype_dict.keys():
1046 retval = retval and self._modify_attrdesc(attrDesc, attrtype_dict[attrDesc], mod_type=easyLDAP_REPLACEATTR)
1047
1048 if not retval:
1049 raise easyLDAP_exceptions.SET_ATTRIBUTE_ERROR
1050
1051 except:
1052
1053 raise easyLDAP_exceptions.SET_ATTRIBUTE_ERROR
1054
1055
1057 """
1058 thisClass.add_attrdesc('myLDAP_ATTRDESC',
1059 'myVALUE'|['myVALUE1', 'myVALUE2', ...])
1060
1061 is a wrapper for
1062
1063 thisClass._modify_attrdesc('myLDAP_ATTRDESC',
1064 'myVALUE'|['myVALUE1', 'myVALUE2', ...],
1065 easyLDAP_ADDATTR)
1066 """
1067 return self._modify_attrdesc(attrdesc, value, easyLDAP_ADDATTR)
1068
1070
1071 self._ldap_cacheobject._push_cache_history()
1072
1074 """
1075 thisClass.show_cache()
1076
1077 will display the cached easyLDAP object just like the console
1078 tool 'ldapsearch' does... unset but possible attributes are not
1079 listed.
1080 """
1081 self._ldap_cacheobject()
1082
1083
1086
1087
1088 - def new_object(self, objectclasses, attrdesc_dict):
1089 """
1090 thisClass.new_object(['myOBJ_CLASS1', 'myOBJ_CLASS2'],
1091 {
1092 'myATTR1': ['myVAL1_1', 'myVAL1_2', ...],
1093 'myATTR2': ['myVAL2_1', 'myVAL2_2', ...], '
1094 ...
1095 }
1096 )
1097
1098 creates an empty object in the easyLDAP object cache. The object
1099 will only be uploaded to the LDAP directory, until the method
1100 thisClass.flush_cash() is evoked.
1101
1102 This action overwrites the current easyLDAP object cache and
1103 creates a new cache object if the used DN was not existent in
1104 the LDAP directory at the time of thisClass.__init__ ('myDN').
1105
1106 This newly created object can be modified by several easyLDAP methods.
1107 Use dir(thisClass).
1108
1109 To view the contents of the new easyLDAP object cache, use
1110 thisClass.show().
1111 """
1112 self._new_object(self.get_object_dn())
1113 if type (objectclasses) is types.StringType:
1114 objectclasses = [objectclasses]
1115
1116 self.add_objectclasses(objectclasses)
1117
1118 for myAttribute, myValue in attrdesc_dict.items ():
1119 if type(myValue) is types.StringType:
1120 myValue = [myValue]
1121 self._modify_attrdesc(myAttribute,myValue,easyLDAP_REPLACEATTR)
1122
1123 return True
1124
1128
1132
1134 """
1135 thisClass.set_userPassword('myUNIXPASSWORD','myHASH')
1136
1137 sets the user's unix password to 'myUNIXPASSWORD'.
1138 As encryption hash 'myHASH' you can additionally pass
1139
1140 CLEAR
1141 CRYPT
1142
1143 The default hash is 'CRYPT'.
1144
1145 If the easyLDAP object has the shadowAccount objectclass
1146 set, the attribute shadowLastChange will be set to the
1147 current date (in days since 1970).
1148 """
1149 if pw is None:
1150 pw = genpasswd()
1151
1152 _do_encryption = {
1153 'CRYPT': 'crypthash(pw)',
1154 'CLEAR': 'pw',
1155 'SASL': '"{SASL}%s" % pw'
1156 }
1157 _known_crypt_methods = _do_encryption.keys()
1158
1159 if HASH in _known_crypt_methods:
1160 crypted_pw = eval (_do_encryption.get(HASH))
1161 else:
1162 raise easyLDAP_exceptions.UNKNOWN_CRYPT_ALGORITHM
1163
1164 try:
1165 self.set_attrdesc('userPassword', crypted_pw)
1166 if self.has_objectclass_set('shadowAccount'):
1167
1168 self.set_attrdesc('shadowLastChange', str(days_since_1970()) )
1169
1170 except:
1171
1172 raise easyLDAP_exceptions.FAILED_TO_SET_PASSWORD
1173
1174
1185
1186
1188 """
1189 """
1190 return self.get_object_dn().startswith('%s=' % _attrtype(naming_attrdesc))
1191
1192
1193
1194 easyLDAPobject = easyLDAP_object
1195
1196
1197
1198
1199
1200
1201
1202 if __name__=='__main__':
1203 pass
1204