Finally committing my LDAP changes.
[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 extern LDAP *ldap_struct;
34 extern LDAPMessage *ldap_results;
35 extern 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=%x)(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 = strtol(temp, NULL, 16);
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         ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
178         return sam21;
179 }
180
181
182 /*******************************************************************
183   Contruct a sam_disp_info structure.
184   ******************************************************************/
185
186 static struct sam_disp_info *ldapsam_getdispinfo()
187 {
188         static struct sam_disp_info dispinfo;
189         static pstring nt_name;
190         static pstring full_name;
191         pstring temp;
192
193         if(!ldap_entry)
194                 return NULL;
195         
196         if(!ldap_get_attribute("ntuid", nt_name) &&
197                         !ldap_get_attribute("uid", nt_name)) {
198                 DEBUG(0,("Missing uid\n"));
199                 return NULL; }
200         dispinfo.nt_name = nt_name;
201
202         DEBUG(2,("Retrieving account [%s]\n",nt_name));
203
204         if(ldap_get_attribute("rid", temp))
205                 dispinfo.user_rid = strtol(temp, NULL, 16);
206         else {
207                 DEBUG(0,("Missing rid\n"));
208                 return NULL; }
209
210         if(ldap_get_attribute("cn", full_name))
211                 dispinfo.full_name = full_name;
212         else
213                 dispinfo.full_name = NULL;
214
215         ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
216         return &dispinfo;
217 }
218
219
220 /************************************************************************
221   Queues the necessary modifications to save a sam_passwd structure
222  ************************************************************************/
223
224 static void ldapsam_sammods(struct sam_passwd *newpwd, LDAPMod ***mods,
225                            int operation)
226 {
227         struct smb_passwd *smbpw;
228         pstring temp;
229
230         smbpw = pwdb_sam_to_smb(newpwd);
231         ldap_smbpwmods(smbpw, mods, operation);
232
233         slprintf(temp, sizeof(temp)-1, "%d", newpwd->unix_gid);
234         ldap_make_mod(mods, operation, "gidNumber", temp);
235
236         slprintf(temp, sizeof(temp)-1, "%x", newpwd->group_rid);
237         ldap_make_mod(mods, operation, "grouprid", temp);
238
239         ldap_make_mod(mods, operation, "cn", newpwd->full_name);
240         ldap_make_mod(mods, operation, "description", newpwd->acct_desc);
241         ldap_make_mod(mods, operation, "smbHome", newpwd->home_dir);
242         ldap_make_mod(mods, operation, "homeDrive", newpwd->dir_drive);
243         ldap_make_mod(mods, operation, "script", newpwd->logon_script);
244         ldap_make_mod(mods, operation, "profile", newpwd->profile_path);
245         ldap_make_mod(mods, operation, "workstations", newpwd->workstations);
246
247         ldap_save_time(mods, operation, "pwdCanChange",
248                         &newpwd->pass_can_change_time);
249         ldap_save_time(mods, operation, "pwdMustChange",
250                         &newpwd->pass_must_change_time);
251         ldap_save_time(mods, operation, "logonTime",
252                         &newpwd->logon_time);
253         ldap_save_time(mods, operation, "logoffTime",
254                         &newpwd->logoff_time);
255         ldap_save_time(mods, operation, "kickoffTime",
256                         &newpwd->kickoff_time);
257 }
258
259
260 /***************************************************************
261   Begin/end account enumeration.
262  ****************************************************************/
263
264 static void *ldapsam_enumfirst(BOOL update)
265 {
266         if (!ldap_connect())
267                 return NULL;
268
269         ldap_search_for("objectclass=sambaAccount");
270
271         return ldap_struct;
272 }
273
274 static void ldapsam_enumclose(void *vp)
275 {
276         ldap_disconnect();
277 }
278
279
280 /*************************************************************************
281   Save/restore the current position in a query
282  *************************************************************************/
283
284 static SMB_BIG_UINT ldapsam_getdbpos(void *vp)
285 {
286         return (SMB_BIG_UINT)((ulong)ldap_entry);
287 }
288
289 static BOOL ldapsam_setdbpos(void *vp, SMB_BIG_UINT tok)
290 {
291         ldap_entry = (LDAPMessage *)((ulong)tok);
292         return (True);
293 }
294
295
296 /*************************************************************************
297   Return sam_passwd information.
298  *************************************************************************/
299
300 static struct sam_passwd *ldapsam_getsambynam(const char *name)
301 {
302         struct sam_passwd *ret;
303
304         if(!ldap_connect())
305                 return NULL;
306
307         ldap_search_by_ntname(name);
308         ret = ldapsam_getsam();
309
310         ldap_disconnect();
311         return ret;
312 }
313
314 static struct sam_passwd *ldapsam_getsambyuid(uid_t userid)
315 {
316         struct sam_passwd *ret;
317
318         if(!ldap_connect())
319            return NULL;
320
321         ldap_search_by_uid(userid);
322         ret = ldapsam_getsam();
323
324         ldap_disconnect();
325         return ret;
326 }
327
328 static struct sam_passwd *ldapsam_getsambyrid(uint32 user_rid)
329 {
330         struct sam_passwd *ret;
331
332         if(!ldap_connect())
333            return NULL;
334
335         ldap_search_by_rid(user_rid);
336         ret = ldapsam_getsam();
337
338         ldap_disconnect();
339         return ret;
340 }
341
342 static struct sam_passwd *ldapsam_getcurrentsam(void *vp)
343 {
344         return ldapsam_getsam();
345 }
346
347
348 /************************************************************************
349   Modify user information given a sam_passwd struct.
350  *************************************************************************/
351
352 static BOOL ldapsam_addsam(struct sam_passwd *newpwd)
353 {       
354         LDAPMod **mods;
355
356         if (!newpwd || !ldap_allocaterid(&newpwd->user_rid))
357                 return (False);
358
359         ldapsam_sammods(newpwd, &mods, LDAP_MOD_ADD);
360         return ldap_makemods("uid", newpwd->unix_name, mods, True);
361 }
362
363 static BOOL ldapsam_modsam(struct sam_passwd *pwd, BOOL override)
364 {
365         LDAPMod **mods;
366
367         if (!pwd)
368                 return (False);
369
370         ldapsam_sammods(pwd, &mods, LDAP_MOD_REPLACE);
371         return ldap_makemods("uid", pwd->unix_name, mods, False);
372 }
373
374
375 /*************************************************************************
376   Return sam_disp_info information.
377  *************************************************************************/
378
379 static struct sam_disp_info *ldapsam_getdispbynam(const char *name)
380 {
381         struct sam_disp_info *ret;
382
383         if(!ldap_connect())
384            return NULL;
385
386         ldap_search_by_ntname(name);
387         ret = ldapsam_getdispinfo();
388
389         ldap_disconnect();
390         return ret;
391 }
392
393 static struct sam_disp_info *ldapsam_getdispbyrid(uint32 user_rid)
394 {
395         struct sam_disp_info *ret;
396
397         if(!ldap_connect())
398            return NULL;
399
400         ldap_search_by_rid(user_rid);
401         ret = ldapsam_getdispinfo();
402
403         ldap_disconnect();
404         return ret;
405 }
406
407 static struct sam_disp_info *ldapsam_getcurrentdisp(void *vp)
408 {
409         return ldapsam_getdispinfo();
410 }
411
412
413
414 static struct sam_passdb_ops ldapsam_ops =
415 {
416         ldapsam_enumfirst,
417         ldapsam_enumclose,
418         ldapsam_getdbpos,
419         ldapsam_setdbpos,
420
421         ldapsam_getsambynam,
422         ldapsam_getsambyuid,
423         ldapsam_getsambyrid,
424         ldapsam_getcurrentsam,
425         ldapsam_addsam,
426         ldapsam_modsam,
427
428         ldapsam_getdispbynam,
429         ldapsam_getdispbyrid,
430         ldapsam_getcurrentdisp
431 };
432
433 struct sam_passdb_ops *ldap_initialise_sam_password_db(void)
434 {
435         return &ldapsam_ops;
436 }
437
438 #else
439  void sampassldap_dummy_function(void);
440  void sampassldap_dummy_function(void) { } /* stop some compilers complaining */
441 #endif