| | 1 | import logging |
|---|
| | 2 | |
|---|
| | 3 | import ldap |
|---|
| | 4 | |
|---|
| | 5 | from soprovider import * |
|---|
| | 6 | |
|---|
| | 7 | log = logging.getLogger("turbogears.identity.soldapprovider") |
|---|
| | 8 | |
|---|
| | 9 | hub = PackageHub("turbogears.identity") |
|---|
| | 10 | __connection__ = hub |
|---|
| | 11 | |
|---|
| | 12 | # Global class references -- these will be set when the Provider is initialised. |
|---|
| | 13 | user_class= None |
|---|
| | 14 | group_class= None |
|---|
| | 15 | permission_class= None |
|---|
| | 16 | visit_class = None |
|---|
| | 17 | |
|---|
| | 18 | class SoLdapIdentityProvider(SqlObjectIdentityProvider): |
|---|
| | 19 | """ |
|---|
| | 20 | IdentityProvider that uses LDAP for authentication. |
|---|
| | 21 | """ |
|---|
| | 22 | |
|---|
| | 23 | def __init__(self): |
|---|
| | 24 | super(SoLdapIdentityProvider, self).__init__() |
|---|
| | 25 | get = turbogears.config.get |
|---|
| | 26 | |
|---|
| | 27 | global user_class, group_class, permission_class, visit_class |
|---|
| | 28 | |
|---|
| | 29 | user_class_path= get( "identity.soprovider.model.user", |
|---|
| | 30 | __name__ + ".TG_User" ) |
|---|
| | 31 | #log.debug('userclassp:%s'% user_class_path) |
|---|
| | 32 | #user_class_path = 'kronos.model.Person' |
|---|
| | 33 | user_class= load_class(user_class_path) |
|---|
| | 34 | if user_class: |
|---|
| | 35 | log.info("Succesfully loaded \"%s\"" % user_class_path) |
|---|
| | 36 | try: |
|---|
| | 37 | self.user_class_db_encoding= \ |
|---|
| | 38 | user_class.sqlmeta.columns['user_name'].dbEncoding |
|---|
| | 39 | except (KeyError, AttributeError): |
|---|
| | 40 | self.user_class_db_encoding= 'UTF-8' |
|---|
| | 41 | group_class_path= get( "identity.soprovider.model.group", |
|---|
| | 42 | __name__ + ".TG_Group" ) |
|---|
| | 43 | group_class= load_class(group_class_path) |
|---|
| | 44 | if group_class: |
|---|
| | 45 | log.info("Succesfully loaded \"%s\"" % group_class_path) |
|---|
| | 46 | |
|---|
| | 47 | permission_class_path= get( "identity.soprovider.model.permission", |
|---|
| | 48 | __name__ + ".TG_Permission" ) |
|---|
| | 49 | permission_class= load_class(permission_class_path) |
|---|
| | 50 | if permission_class: |
|---|
| | 51 | log.info("Succesfully loaded \"%s\"" % permission_class_path) |
|---|
| | 52 | |
|---|
| | 53 | visit_class_path= get( "visit.soprovider.model", |
|---|
| | 54 | __name__ + ".TG_VisitIdentity" ) |
|---|
| | 55 | visit_class= load_class(visit_class_path) |
|---|
| | 56 | if visit_class: |
|---|
| | 57 | log.info("Succesfully loaded \"%s\"" % visit_class_path) |
|---|
| | 58 | |
|---|
| | 59 | self.host = get("identity.soldapprovider.host", "localhost") |
|---|
| | 60 | self.port = get("identity.soldapprovider.port", 389) |
|---|
| | 61 | self.basedn = get("identity.soldapprovider.basedn", "dc=localhost") |
|---|
| | 62 | self.autocreate = get("identity.soldapprovider.autocreate", False) |
|---|
| | 63 | |
|---|
| | 64 | log.info("host :: %s" % self.host) |
|---|
| | 65 | log.info("port :: %d" % self.port) |
|---|
| | 66 | log.info("basedn :: %s" % self.basedn) |
|---|
| | 67 | log.info("autocreate :: %s" % self.autocreate) |
|---|
| | 68 | |
|---|
| | 69 | def validate_identity( self, user_name, password, visit_key ): |
|---|
| | 70 | ''' |
|---|
| | 71 | Look up the identity represented by user_name and determine whether the |
|---|
| | 72 | password is correct. |
|---|
| | 73 | |
|---|
| | 74 | Must return either None if the credentials weren't valid or an object |
|---|
| | 75 | with the following properties: |
|---|
| | 76 | user_name: original user name |
|---|
| | 77 | user: a provider dependant object (TG_User or similar) |
|---|
| | 78 | groups: a set of group IDs |
|---|
| | 79 | permissions: a set of permission IDs |
|---|
| | 80 | ''' |
|---|
| | 81 | |
|---|
| | 82 | ldapcon = ldap.open(self.host, self.port) |
|---|
| | 83 | filter = "(&(objectClass=inetOrgPerson)(uid=%s))" % user_name |
|---|
| | 84 | rc = ldapcon.search(self.basedn, ldap.SCOPE_SUBTREE, filter) |
|---|
| | 85 | |
|---|
| | 86 | objects = ldapcon.result(rc)[1] |
|---|
| | 87 | |
|---|
| | 88 | if(len(objects) == 0): |
|---|
| | 89 | log.warning("No such LDAP user: %s" % user_name) |
|---|
| | 90 | return False |
|---|
| | 91 | elif(len(objects) > 1): |
|---|
| | 92 | log.error("Too many users: %s" % user_name) |
|---|
| | 93 | return False |
|---|
| | 94 | |
|---|
| | 95 | dn = objects[0][0] |
|---|
| | 96 | |
|---|
| | 97 | try: |
|---|
| | 98 | rc = ldapcon.simple_bind(dn, password) |
|---|
| | 99 | ldapcon.result(rc) |
|---|
| | 100 | except ldap.INVALID_CREDENTIALS: |
|---|
| | 101 | log.error("Invalid password supplied for %s" % user_name) |
|---|
| | 102 | return None |
|---|
| | 103 | |
|---|
| | 104 | try: |
|---|
| | 105 | log.info("user_class.by_user_name(%s)" % user_name) |
|---|
| | 106 | user = user_class.by_user_name(user_name) |
|---|
| | 107 | except SQLObjectNotFound: |
|---|
| | 108 | if(self.autocreate): |
|---|
| | 109 | hub.begin() |
|---|
| | 110 | user = user_class(user_name=user_name) |
|---|
| | 111 | hub.commit() |
|---|
| | 112 | hub.end() |
|---|
| | 113 | else: |
|---|
| | 114 | log.error("No such database user: %s" % user_name) |
|---|
| | 115 | return None |
|---|
| | 116 | |
|---|
| | 117 | try: |
|---|
| | 118 | link= visit_class.by_visit_key(visit_key) |
|---|
| | 119 | link.user_id= user.id |
|---|
| | 120 | except SQLObjectNotFound: |
|---|
| | 121 | link= visit_class(visit_key=visit_key, user_id=user.id) |
|---|
| | 122 | return SqlObjectIdentity(visit_key, user) |
|---|
| | 123 | |