first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[nivanova/samba-autobuild/.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         {
87                 t = (time_t)strtol(timestr, NULL, 16);
88                 unix_to_nt_time(nttime, t);
89         }
90 }
91
92
93 /*******************************************************************
94   Contruct a sam_passwd structure.
95  ******************************************************************/
96
97 static struct sam_passwd *ldapsam_getsam()
98 {
99         static pstring full_name;
100         static pstring acct_desc;
101         static pstring home_dir;
102         static pstring home_drive;
103         static pstring logon_script;
104         static pstring profile_path;
105         static pstring workstations;
106         pstring temp;
107         struct sam_passwd *sam21;
108         struct smb_passwd *smbpw;
109
110         if(!ldap_entry)
111                 return NULL;
112
113         smbpw = ldap_getpw();
114         sam21 = pwdb_smb_to_sam(smbpw); 
115
116         if(ldap_get_attribute("gidNumber", temp))
117                 sam21->unix_gid = atoi(temp);
118         
119         if(ldap_get_attribute("grouprid", temp))
120                 sam21->group_rid = strtol(temp, NULL, 16);
121         
122         if(ldap_get_attribute("cn", full_name))
123                 sam21->full_name = full_name;
124
125         if(ldap_get_attribute("description", acct_desc))
126                 sam21->acct_desc = acct_desc;
127
128         if(ldap_get_attribute("smbHome", home_dir))
129                 sam21->home_dir = home_dir;
130
131         if(ldap_get_attribute("homeDrive", home_drive))
132                 sam21->dir_drive = home_drive;
133
134         if(ldap_get_attribute("script", logon_script))
135                 sam21->logon_script = logon_script;
136
137         if(ldap_get_attribute("profile", profile_path))
138                 sam21->profile_path = profile_path;
139
140         if(ldap_get_attribute("workstations", workstations))
141                 sam21->workstations = workstations;
142
143         ldap_read_time("pwdCanChange", &sam21->pass_can_change_time);
144         ldap_read_time("pwdMustChange", &sam21->pass_must_change_time);
145         ldap_read_time("logonTime", &sam21->logon_time);
146         ldap_read_time("logoffTime", &sam21->logoff_time);
147         ldap_read_time("kickoffTime", &sam21->kickoff_time);
148
149         sam21->unknown_3 = 0xffffff; /* don't know */
150         sam21->logon_divs = 168; /* hours per week */
151         sam21->hours_len = 21; /* 21 times 8 bits = 168 */
152         memset(sam21->hours, 0xff, sam21->hours_len); /* all hours */
153         sam21->unknown_5 = 0x00020000; /* don't know */
154         sam21->unknown_6 = 0x000004ec; /* don't know */
155         sam21->unknown_str = NULL;
156         sam21->munged_dial = NULL;
157
158         ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
159         return sam21;
160 }
161
162
163 /*******************************************************************
164   Contruct a sam_disp_info structure.
165   ******************************************************************/
166
167 static struct sam_disp_info *ldapsam_getdispinfo()
168 {
169         static struct sam_disp_info dispinfo;
170         static pstring nt_name;
171         static pstring full_name;
172         pstring temp;
173
174         if(!ldap_entry)
175                 return NULL;
176         
177         if(!ldap_get_attribute("ntuid", nt_name) &&
178                         !ldap_get_attribute("uid", nt_name)) {
179                 DEBUG(0,("Missing uid\n"));
180                 return NULL; }
181         dispinfo.nt_name = nt_name;
182
183         DEBUG(2,("Retrieving account [%s]\n",nt_name));
184
185         if(ldap_get_attribute("rid", temp))
186                 dispinfo.user_rid = strtol(temp, NULL, 16);
187         else {
188                 DEBUG(0,("Missing rid\n"));
189                 return NULL; }
190
191         if(ldap_get_attribute("cn", full_name))
192                 dispinfo.full_name = full_name;
193         else
194                 dispinfo.full_name = NULL;
195
196         ldap_entry = ldap_next_entry(ldap_struct, ldap_entry);
197         return &dispinfo;
198 }
199
200
201 /************************************************************************
202   Queues the necessary modifications to save a sam_passwd structure
203  ************************************************************************/
204
205 static void ldapsam_sammods(struct sam_passwd *newpwd, LDAPMod ***mods,
206                            int operation)
207 {
208         struct smb_passwd *smbpw;
209         pstring temp;
210
211         smbpw = pwdb_sam_to_smb(newpwd);
212         ldap_smbpwmods(smbpw, mods, operation);
213
214         slprintf(temp, sizeof(temp)-1, "%d", newpwd->unix_gid);
215         ldap_make_mod(mods, operation, "gidNumber", temp);
216
217         slprintf(temp, sizeof(temp)-1, "%x", newpwd->group_rid);
218         ldap_make_mod(mods, operation, "grouprid", temp);
219
220         ldap_make_mod(mods, operation, "cn", newpwd->full_name);
221         ldap_make_mod(mods, operation, "description", newpwd->acct_desc);
222         ldap_make_mod(mods, operation, "smbHome", newpwd->home_dir);
223         ldap_make_mod(mods, operation, "homeDrive", newpwd->dir_drive);
224         ldap_make_mod(mods, operation, "script", newpwd->logon_script);
225         ldap_make_mod(mods, operation, "profile", newpwd->profile_path);
226         ldap_make_mod(mods, operation, "workstations", newpwd->workstations);
227
228         ldap_save_time(mods, operation, "pwdCanChange",
229                         &newpwd->pass_can_change_time);
230         ldap_save_time(mods, operation, "pwdMustChange",
231                         &newpwd->pass_must_change_time);
232         ldap_save_time(mods, operation, "logonTime",
233                         &newpwd->logon_time);
234         ldap_save_time(mods, operation, "logoffTime",
235                         &newpwd->logoff_time);
236         ldap_save_time(mods, operation, "kickoffTime",
237                         &newpwd->kickoff_time);
238 }
239
240
241 /***************************************************************
242   Begin/end account enumeration.
243  ****************************************************************/
244
245 static void *ldapsam_enumfirst(BOOL update)
246 {
247         if (!ldap_connect())
248                 return NULL;
249
250         ldap_search_for("objectclass=sambaAccount");
251
252         return ldap_struct;
253 }
254
255 static void ldapsam_enumclose(void *vp)
256 {
257         ldap_disconnect();
258 }
259
260
261 /*************************************************************************
262   Save/restore the current position in a query
263  *************************************************************************/
264
265 static SMB_BIG_UINT ldapsam_getdbpos(void *vp)
266 {
267         return (SMB_BIG_UINT)((ulong)ldap_entry);
268 }
269
270 static BOOL ldapsam_setdbpos(void *vp, SMB_BIG_UINT tok)
271 {
272         ldap_entry = (LDAPMessage *)((ulong)tok);
273         return (True);
274 }
275
276
277 /*************************************************************************
278   Return sam_passwd information.
279  *************************************************************************/
280
281 static struct sam_passwd *ldapsam_getsambynam(const char *name)
282 {
283         struct sam_passwd *ret;
284
285         if(!ldap_connect())
286                 return NULL;
287
288         ldap_search_by_ntname(name);
289         ret = ldapsam_getsam();
290
291         ldap_disconnect();
292         return ret;
293 }
294
295 static struct sam_passwd *ldapsam_getsambyuid(uid_t userid)
296 {
297         struct sam_passwd *ret;
298
299         if(!ldap_connect())
300            return NULL;
301
302         ldap_search_by_uid(userid);
303         ret = ldapsam_getsam();
304
305         ldap_disconnect();
306         return ret;
307 }
308
309 static struct sam_passwd *ldapsam_getsambyrid(uint32 user_rid)
310 {
311         struct sam_passwd *ret;
312
313         if(!ldap_connect())
314            return NULL;
315
316         ldap_search_by_rid(user_rid);
317         ret = ldapsam_getsam();
318
319         ldap_disconnect();
320         return ret;
321 }
322
323 static struct sam_passwd *ldapsam_getcurrentsam(void *vp)
324 {
325         return ldapsam_getsam();
326 }
327
328
329 /************************************************************************
330   Modify user information given a sam_passwd struct.
331  *************************************************************************/
332
333 static BOOL ldapsam_addsam(struct sam_passwd *newpwd)
334 {       
335         LDAPMod **mods;
336
337         if (!newpwd || !ldap_allocaterid(&newpwd->user_rid))
338                 return (False);
339
340         ldapsam_sammods(newpwd, &mods, LDAP_MOD_ADD);
341         return ldap_makemods("uid", newpwd->unix_name, mods, True);
342 }
343
344 static BOOL ldapsam_modsam(struct sam_passwd *pwd, BOOL override)
345 {
346         LDAPMod **mods;
347
348         if (!pwd)
349                 return (False);
350
351         ldapsam_sammods(pwd, &mods, LDAP_MOD_REPLACE);
352         return ldap_makemods("uid", pwd->unix_name, mods, False);
353 }
354
355
356 /*************************************************************************
357   Return sam_disp_info information.
358  *************************************************************************/
359
360 static struct sam_disp_info *ldapsam_getdispbynam(const char *name)
361 {
362         struct sam_disp_info *ret;
363
364         if(!ldap_connect())
365            return NULL;
366
367         ldap_search_by_ntname(name);
368         ret = ldapsam_getdispinfo();
369
370         ldap_disconnect();
371         return ret;
372 }
373
374 static struct sam_disp_info *ldapsam_getdispbyrid(uint32 user_rid)
375 {
376         struct sam_disp_info *ret;
377
378         if(!ldap_connect())
379            return NULL;
380
381         ldap_search_by_rid(user_rid);
382         ret = ldapsam_getdispinfo();
383
384         ldap_disconnect();
385         return ret;
386 }
387
388 static struct sam_disp_info *ldapsam_getcurrentdisp(void *vp)
389 {
390         return ldapsam_getdispinfo();
391 }
392
393
394
395 static struct sam_passdb_ops ldapsam_ops =
396 {
397         ldapsam_enumfirst,
398         ldapsam_enumclose,
399         ldapsam_getdbpos,
400         ldapsam_setdbpos,
401
402         ldapsam_getsambynam,
403         ldapsam_getsambyuid,
404         ldapsam_getsambyrid,
405         ldapsam_getcurrentsam,
406         ldapsam_addsam,
407         ldapsam_modsam,
408
409         ldapsam_getdispbynam,
410         ldapsam_getdispbyrid,
411         ldapsam_getcurrentdisp
412 };
413
414 struct sam_passdb_ops *ldap_initialise_sam_password_db(void)
415 {
416         return &ldapsam_ops;
417 }
418
419 #else
420  void sampassldap_dummy_function(void);
421  void sampassldap_dummy_function(void) { } /* stop some compilers complaining */
422 #endif