]>
Commit | Line | Data |
---|---|---|
940227cb | 1 | #!/usr/bin/python |
78fdedae | 2 | # encoding: utf-8 |
940227cb MT |
3 | |
4 | import hashlib | |
5 | import ldap | |
27066195 | 6 | import logging |
940227cb MT |
7 | import urllib |
8 | ||
a6dc0bad | 9 | from misc import Object |
940227cb | 10 | |
a6dc0bad | 11 | class Accounts(Object): |
a6dc0bad MT |
12 | def __init__(self, backend): |
13 | Object.__init__(self, backend) | |
940227cb MT |
14 | self.__db = None |
15 | ||
16 | self._init() | |
17 | ||
18 | @property | |
19 | def search_base(self): | |
9068dba1 | 20 | return self.settings.get("ldap_search_base") |
940227cb MT |
21 | |
22 | @property | |
23 | def db(self): | |
24 | if not self.__db: | |
27066195 | 25 | ldap_uri = self.settings.get("ldap_uri") |
940227cb MT |
26 | |
27 | self.__db = ldap.initialize(ldap_uri) | |
28 | ||
27066195 MT |
29 | bind_dn = self.settings.get("ldap_bind_dn") |
30 | ||
940227cb | 31 | if bind_dn: |
9068dba1 | 32 | bind_pw = self.settings.get("ldap_bind_pw", "") |
940227cb MT |
33 | |
34 | self.__db.simple_bind(bind_dn, bind_pw) | |
35 | ||
36 | return self.__db | |
37 | ||
38 | def get(self, dn): | |
39 | return self._accounts[dn] | |
40 | ||
41 | def _init(self): | |
42 | self._accounts = {} | |
43 | results = self.db.search_s(self.search_base, ldap.SCOPE_SUBTREE, | |
44 | "(objectClass=posixAccount)", ["loginShell"]) | |
45 | ||
46 | for dn, attrs in results: | |
47 | #if attrs["loginShell"] == ["/bin/bash"]: | |
a6dc0bad | 48 | self._accounts[dn] = Account(self.backend, dn) |
940227cb MT |
49 | |
50 | def list(self): | |
51 | return sorted(self._accounts.values()) | |
52 | ||
53 | def find(self, uid): | |
54 | for account in self.list(): | |
55 | if account.uid == uid: | |
56 | return account | |
57 | ||
58 | def delete(self, uid): | |
59 | account = self.find(uid) | |
60 | # XXX | |
61 | ||
62 | search = find | |
63 | ||
64 | ||
a6dc0bad MT |
65 | class Account(Object): |
66 | def __init__(self, backend, dn): | |
67 | Object.__init__(self, backend) | |
940227cb MT |
68 | self.dn = dn |
69 | ||
70 | self.__attributes = {} | |
71 | ||
72 | def __repr__(self): | |
73 | return "<%s %s>" % (self.__class__.__name__, self.dn) | |
74 | ||
75 | def __cmp__(self, other): | |
76 | return cmp(self.cn, other.cn) | |
77 | ||
78 | @property | |
79 | def db(self): | |
a6dc0bad | 80 | return self.accounts.db |
940227cb MT |
81 | |
82 | @property | |
83 | def attributes(self): | |
84 | if not self.__attributes: | |
85 | self.fetch_attributes() | |
86 | ||
87 | return self.__attributes | |
88 | ||
89 | def fetch_attributes(self): | |
90 | result = self.db.search_ext_s(self.dn, ldap.SCOPE_SUBTREE, sizelimit=1) | |
91 | dn, self.__attributes = result[0] | |
92 | ||
93 | def get(self, key): | |
94 | try: | |
95 | attribute = self.attributes[key] | |
96 | except KeyError: | |
97 | raise AttributeError(key) | |
98 | ||
99 | if len(attribute) == 1: | |
100 | return attribute[0] | |
101 | ||
102 | return attribute | |
103 | ||
104 | __getattr__ = get | |
105 | ||
106 | def set(self, key, value): | |
107 | mod_op = ldap.MOD_ADD | |
108 | if self.attributes.has_key(key): | |
109 | mod_op = ldap.MOD_REPLACE | |
110 | ||
111 | self._modify(mod_op, key, value) | |
112 | ||
113 | def _modify(self, op, key, value): | |
114 | modlist = [(op, key, value)] | |
115 | ||
116 | self.db.modify_s(self.dn, modlist) | |
117 | ||
118 | # Update local cache of attributes | |
119 | self.fetch_attributes() | |
120 | ||
121 | def delete(self, key, value=None): | |
122 | self._modify(ldap.MOD_DELETE, key, value) | |
123 | ||
124 | def check_password(self, password): | |
125 | """ | |
126 | Bind to the server with given credentials and return | |
127 | true if password is corrent and false if not. | |
128 | ||
129 | Raises exceptions from the server on any other errors. | |
130 | """ | |
131 | ||
132 | logging.debug("Checking credentials for %s" % self.dn) | |
133 | try: | |
60024cc8 | 134 | self.db.simple_bind_s(self.dn, password.encode("utf-8")) |
940227cb | 135 | except ldap.INVALID_CREDENTIALS: |
60024cc8 | 136 | logging.debug("Account credentials are invalid.") |
940227cb MT |
137 | return False |
138 | ||
60024cc8 | 139 | logging.debug("Successfully authenticated.") |
940227cb MT |
140 | return True |
141 | ||
142 | @property | |
143 | def is_admin(self): | |
144 | return True # XXX todo | |
145 | ||
a6dc0bad MT |
146 | @property |
147 | def name(self): | |
148 | return self.cn | |
149 | ||
940227cb MT |
150 | @property |
151 | def email(self): | |
152 | name = self.cn.lower() | |
153 | name = name.replace(" ", ".") | |
78fdedae MT |
154 | name = name.replace("Ä", "Ae") |
155 | name = name.replace("Ö", "Oe") | |
156 | name = name.replace("Ü", "Ue") | |
157 | name = name.replace("ä", "ae") | |
158 | name = name.replace("ö", "oe") | |
159 | name = name.replace("ü", "ue") | |
940227cb MT |
160 | |
161 | for mail in self.mail: | |
cc3b928d | 162 | if mail.startswith("%s@ipfire.org" % name): |
940227cb MT |
163 | return mail |
164 | ||
165 | raise Exception, "Cannot figure out email address" | |
166 | ||
167 | def gravatar_icon(self, size=128): | |
168 | # construct the url | |
169 | gravatar_url = "http://www.gravatar.com/avatar/" + \ | |
170 | hashlib.md5(self.email.lower()).hexdigest() + "?" | |
171 | gravatar_url += urllib.urlencode({'d': "mm", 's': str(size)}) | |
172 | ||
173 | return gravatar_url | |
174 | ||
60024cc8 | 175 | |
940227cb MT |
176 | if __name__ == "__main__": |
177 | a = Accounts() | |
178 | ||
179 | print a.list() |