1c3283df0fde1ae12e61aa9b8cdb53f1e312bae4
[samba.git] / source3 / passdb / sampassldap.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0.
4    LDAP protocol helper functions for SAMBA
5    Copyright (C) Matthew Chapman 1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 */
22
23 #include "includes.h"
24
25 #ifdef WITH_LDAP
26
27 #include <lber.h>
28 #include <ldap.h>
29
30 extern int DEBUGLEVEL;
31
32 /* Internal state */
33 LDAP *ldap_struct;
34 LDAPMessage *ldap_results;
35 LDAPMessage *ldap_entry;
36
37
38 /*******************************************************************
39   NT name/RID search functions.
40  ******************************************************************/
41
42 BOOL ldap_search_by_rid(uint32 rid)
43 {
44         fstring filter;
45
46         slprintf(filter, sizeof(filter)-1,
47                  "(&(rid=%d)(objectclass=sambaAccount))", rid);
48         return ldap_search_for(filter);
49 }
50
51 BOOL ldap_search_by_ntname(const char *ntname)
52 {
53         fstring filter;
54
55         slprintf(filter, sizeof(filter)-1,
56                  "(&(ntuid=%s)(objectclass=sambaAccount))", ntname);
57         return ldap_search_for(filter);
58 }
59
60
61 /*******************************************************************
62   Store NTTIMEs as time_t's.
63  ******************************************************************/
64
65 static void ldap_save_time(LDAPMod ***modlist, int modop, char *attribute,
66                         NTTIME *nttime)
67 {
68         fstring tstr;
69         time_t t;
70
71         t = nt_time_to_unix(nttime);
72
73         if(t == -1)
74                 return;
75
76         slprintf(tstr, sizeof(tstr)-1, "%08X", t);
77         ldap_make_mod(modlist, modop, attribute, tstr);
78 }
79
80 static void ldap_read_time(char *attribute, NTTIME *nttime)
81 {
82         fstring timestr;
83         time_t t;
84
85         if(ldap_get_attribute(attribute, timestr))
86                 t = (time_t)strtol(timestr, NULL, 16);
87         else
88                 t = (time_t)(-1);
89
90         unix_to_nt_time(nttime, t);
91 }
92
93
94 /*******************************************************************
95   Contruct a sam_passwd structure.
96  ******************************************************************/
97
98 static struct sam_passwd *ldapsam_getsam()
99 {
100         static pstring full_name;
101         static pstring acct_desc;
102         static pstring home_dir;
103         static pstring home_drive;
104         static pstring logon_script;
105         static pstring profile_path;
106         static pstring workstations;
107         pstring temp;
108         struct sam_passwd *sam21;
109         struct smb_passwd *smbpw;
110
111         if(!ldap_entry)
112                 return NULL;
113
114         smbpw = ldap_getpw();
115         sam21 = pwdb_smb_to_sam(smbpw); 
116
117         if(ldap_get_attribute("gidNumber", temp))
118                 sam21->unix_gid = atoi(temp);
119         else
120                 sam21->unix_gid = (gid_t)(-1);
121         
122         if(ldap_get_attribute("grouprid", temp))
123                 sam21->group_rid = atoi(temp);
124         else
125                 sam21->group_rid = 0xFFFFFFFF;
126         
127         if(ldap_get_attribute("cn", full_name))
128                 sam21->full_name = full_name;
129         else
130                 sam21->full_name = NULL;
131
132         if(ldap_get_attribute("description", acct_desc))
133                 sam21->acct_desc = acct_desc;
134         else
135                 sam21->acct_desc = NULL;
136
137         if(ldap_get_attribute("smbHome", home_dir))
138                 sam21->home_dir = home_dir;
139         else
140                 sam21->home_dir = NULL;
141
142         if(ldap_get_attribute("homeDrive", home_drive))
143                 sam21->dir_drive = home_drive;
144         else
145                 sam21->dir_drive = NULL;
146
147         if(ldap_get_attribute("script", logon_script))
148                 sam21->logon_script = logon_script;
149         else
150                 sam21->logon_script = NULL;
151
152         if(ldap_get_attribute("profile", profile_path))
153                 sam21->profile_path = profile_path;
154         else
155                 sam21->profile_path = NULL;
156
157         if(ldap_get_attribute("workstations", workstations))
158                 sam21->workstations = workstations;
159         else
160                 sam21->workstations = NULL;
161
162         ldap_read_time("pwdCanChange", &sam21->pass_can_change_time);
163         ldap_read_time("pwdMustChange", &sam21->pass_must_change_time);
164         ldap_read_time("logonTime", &sam21->logon_time);
165         ldap_read_time("logoffTime", &sam21->logoff_time);
166         ldap_read_time("kickoffTime", &sam21->kickoff_time);
167
168         sam21->unknown_3 = 0xffffff; /* don't know */
169         sam21->logon_divs = 168; /* hours per week */
170         sam21->hours_len = 21; /* 21 times 8 bits = 168 */
171         memset(sam21->hours, 0xff, sam21->hours_len); /* all hours */
172         sam21->unknown_5 = 0x00020000; /* don't know */
173         sam21->unknown_6 = 0x000004ec; /* don't know */
174         sam21->unknown_str = NULL;
175         sam21->munged_dial = NULL;
176
177         return sam21;
178 }
179
180
181 /*******************************************************************
182   Contruct a sam_disp_info structure.
183   ******************************************************************/
184
185 static struct sam_disp_info *ldapsam_getdispinfo()
186 {
187         static struct sam_disp_info dispinfo;
188         static pstring nt_name;
189         static pstring full_name;
190         pstring temp;
191
192         if(!ldap_entry)
193                 return NULL;
194         
195         if(!ldap_get_attribute("ntuid", nt_name) &&
196                         !ldap_get_attribute("uid", nt_name)) {
197                 DEBUG(0,("Missing uid\n"));
198                 return NULL; }
199         dispinfo.nt_name = nt_name;
200
201         DEBUG(2,("Retrieving account [%s]\n",nt_name));
202
203         if(ldap_get_attribute("rid", temp))
204                 dispinfo.user_rid = atoi(temp);
205         else {
206                 DEBUG(0,("Missing rid\n"));
207                 return NULL; }
208
209         if(ldap_get_attribute("cn", full_name))
210                 dispinfo.full_name = full_name;
211         else
212                 dispinfo.full_name = NULL;
213
214         return &dispinfo;
215 }
216
217
218 /************************************************************************
219   Queues the necessary modifications to save a sam_passwd structure
220  ************************************************************************/
221
222 static void ldapsam_sammods(struct sam_passwd *newpwd, LDAPMod ***mods,
223                            int operation)
224 {
225         struct smb_passwd *smbpw;
226         pstring temp;
227
228         smbpw = pwdb_sam_to_smb(newpwd);
229         ldap_smbpwmods(smbpw, mods, operation);
230
231         slprintf(temp, sizeof(temp)-1, "%d", newpwd->unix_gid);
232         ldap_make_mod(mods, operation, "gidNumber", temp);
233
234         slprintf(temp, sizeof(temp)-1, "%d", newpwd->group_rid);
235         ldap_make_mod(mods, operation, "grouprid", temp);
236
237         ldap_make_mod(mods, operation, "cn", newpwd->full_name);
238         ldap_make_mod(mods, operation, "description", newpwd->acct_desc);
239         ldap_make_mod(mods, operation, "smbHome", newpwd->home_dir);
240         ldap_make_mod(mods, operation, "homeDrive", newpwd->dir_drive);
241         ldap_make_mod(mods, operation, "script", newpwd->logon_script);
242         ldap_make_mod(mods, operation, "profile", newpwd->profile_path);
243         ldap_make_mod(mods, operation, "workstations", newpwd->workstations);
244
245         ldap_save_time(mods, operation, "pwdCanChange",
246                         &newpwd->pass_can_change_time);
247         ldap_save_time(mods, operation, "pwdMustChange",
248                         &newpwd->pass_must_change_time);
249         ldap_save_time(mods, operation, "logonTime",
250                         &newpwd->logon_time);
251         ldap_save_time(mods, operation, "logoffTime",
252                         &newpwd->logoff_time);
253         ldap_save_time(mods, operation, "kickoffTime",
254                         &newpwd->kickoff_time);
255 }
256
257
258 /***************************************************************
259   Begin/end account enumeration.
260  ****************************************************************/
261
262 static void *ldapsam_enumfirst(BOOL update)
263 {
264         if (!ldap_open_connection(False))
265                 return NULL;
266
267         ldap_search_for("objectclass=sambaAccount");
268
269         return ldap_struct;
270 }
271
272 static void ldapsam_enumclose(void *vp)
273 {
274         ldap_close_connection();
275 }
276
277
278 /*************************************************************************
279   Save/restore the current position in a query
280  *************************************************************************/
281
282 static SMB_BIG_UINT ldapsam_getdbpos(void *vp)
283 {
284         return (SMB_BIG_UINT)((ulong)ldap_entry);
285 }
286
287 static BOOL ldapsam_setdbpos(void *vp, SMB_BIG_UINT tok)
288 {
289         ldap_entry = (LDAPMessage *)((ulong)tok);
290         return (True);
291 }
292
293
294 /*************************************************************************
295   Return sam_passwd information.
296  *************************************************************************/
297
298 static struct sam_passwd *ldapsam_getsambynam(const char *name)
299 {
300         struct sam_passwd *ret;
301
302         if(!ldap_open_connection(False))
303                 return NULL;
304
305         ldap_search_by_ntname(name);
306         ret = ldapsam_getsam();
307
308         ldap_close_connection();
309         return ret;
310 }
311
312 static struct sam_passwd *ldapsam_getsambyuid(uid_t userid)
313 {
314         struct sam_passwd *ret;
315
316         if(!ldap_open_connection(False))
317            return NULL;
318
319         ldap_search_by_uid(userid);
320         ret = ldapsam_getsam();
321
322         ldap_close_connection();
323         return ret;
324 }
325
326 static struct sam_passwd *ldapsam_getsambyrid(uint32 user_rid)
327 {
328         struct sam_passwd *ret;
329
330         if(!ldap_open_connection(False))
331            return NULL;
332
333         ldap_search_by_rid(user_rid);
334         ret = ldapsam_getsam();
335
336         ldap_close_connection();
337         return ret;
338 }
339
340 static struct sam_passwd *ldapsam_getcurrentsam(void *vp)
341 {
342         return ldapsam_getsam();
343 }
344
345
346 /************************************************************************
347   Modify user information given a sam_passwd struct.
348  *************************************************************************/
349
350 static BOOL ldapsam_addsam(struct sam_passwd *newpwd)
351 {       
352         LDAPMod **mods;
353
354         ldapsam_sammods(newpwd, &mods, LDAP_MOD_ADD);
355         return ldap_makemods("uid", newpwd->unix_name, mods, True);
356 }
357
358 static BOOL ldapsam_modsam(struct sam_passwd *pwd, BOOL override)
359 {
360         LDAPMod **mods;
361
362         ldapsam_sammods(pwd, &mods, LDAP_MOD_REPLACE);
363         return ldap_makemods("uid", pwd->unix_name, mods, False);
364 }
365
366
367 /*************************************************************************
368   Return sam_disp_info information.
369  *************************************************************************/
370
371 static struct sam_disp_info *ldapsam_getdispbynam(const char *name)
372 {
373         struct sam_disp_info *ret;
374
375         if(!ldap_open_connection(False))
376            return NULL;
377
378         ldap_search_by_ntname(name);
379         ret = ldapsam_getdispinfo();
380
381         ldap_close_connection();
382         return ret;
383 }
384
385 static struct sam_disp_info *ldapsam_getdispbyrid(uint32 user_rid)
386 {
387         struct sam_disp_info *ret;
388
389         if(!ldap_open_connection(False))
390            return NULL;
391
392         ldap_search_by_rid(user_rid);
393         ret = ldapsam_getdispinfo();
394
395         ldap_close_connection();
396         return ret;
397 }
398
399 static struct sam_disp_info *ldapsam_getcurrentdisp(void *vp)
400 {
401         return ldapsam_getdispinfo();
402 }
403
404
405
406 static struct sam_passdb_ops ldapsam_ops =
407 {
408         ldapsam_enumfirst,
409         ldapsam_enumclose,
410         ldapsam_getdbpos,
411         ldapsam_setdbpos,
412
413         ldapsam_getsambynam,
414         ldapsam_getsambyuid,
415         ldapsam_getsambyrid,
416         ldapsam_getcurrentsam,
417         ldapsam_addsam,
418         ldapsam_modsam,
419
420         ldapsam_getdispbynam,
421         ldapsam_getdispbyrid,
422         ldapsam_getcurrentdisp
423 };
424
425 struct sam_passdb_ops *ldap_initialise_sam_password_db(void)
426 {
427         return &ldapsam_ops;
428 }
429
430 #else
431  void sampassldap_dummy_function(void);
432  void sampassldap_dummy_function(void) { } /* stop some compilers complaining */
433 #endif