"retired" two modules to preserve their cvs history.
[samba.git] / source / passdb / sampassdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Jeremy Allison 1996-1998
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
7       
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "nterr.h"
25
26 extern int DEBUGLEVEL;
27 extern DOM_SID global_sam_sid;
28
29 /*
30  * NOTE. All these functions are abstracted into a structure
31  * that points to the correct function for the selected database. JRA.
32  *
33  * NOTE.  for the get/mod/add functions, there are two sets of functions.
34  * one supports struct sam_passwd, the other supports struct smb_passwd.
35  * for speed optimisation it is best to support both these sets.
36  * 
37  * it is, however, optional to support one set but not the other: there
38  * is conversion-capability built in to passdb.c, and run-time error
39  * detection for when neither are supported.
40  * 
41  * password database writers are recommended to implement the sam_passwd
42  * functions in a first pass, as struct sam_passwd contains more
43  * information, needed by the NT Domain support.
44  * 
45  * an API writer is expected to create either one set (struct smb_passwd) or
46  * the other (struct sam_passwd) OR both, and optionally also to write display
47  * info routines * (struct sam_disp_info).  functions which the API writer
48  * chooses NOT to write must be wrapped in conversion functions (pwdb_x_to_y)
49  * such that API users can call any function and still get valid results.
50  *
51  * the password API does NOT fill in the gaps if you set an API function
52  * to NULL: it will deliberately attempt to call the NULL function.
53  *
54  */
55
56 static struct sam_passdb_ops *pwdb_ops;
57
58 /***************************************************************
59  Initialise the password db operations.
60 ***************************************************************/
61
62 BOOL initialise_sam_password_db(void)
63 {
64   if (pwdb_ops)
65   {
66     return True;
67   }
68
69 #ifdef WITH_NISPLUS
70   pwdb_ops =  nisplus_initialise_sam_password_db();
71 #elif defined(WITH_LDAP)
72   pwdb_ops = ldap_initialise_sam_password_db();
73 #elif defined(USE_SMBPASS_DB)
74   pwdb_ops = file_initialise_sam_password_db();
75 #endif 
76
77   return (pwdb_ops != NULL);
78 }
79
80 /*
81  * Functions that return/manipulate a struct sam_passwd.
82  */
83
84 /***************************************************************
85  Start to enumerate the smb or sam passwd list. Returns a void pointer
86  to ensure no modification outside this module.
87
88  Note that currently it is being assumed that a pointer returned
89  from this function may be used to enumerate struct sam_passwd
90  entries as well as struct smb_passwd entries. This may need
91  to change. JRA.
92
93 ****************************************************************/
94
95 void *startsam21pwent(BOOL update)
96 {
97   return pwdb_ops->startsam21pwent(update);
98 }
99
100 /***************************************************************
101  End enumeration of the sam passwd list.
102
103  Note that currently it is being assumed that a pointer returned
104  from this function may be used to enumerate struct sam_passwd
105  entries as well as struct smb_passwd entries. This may need
106  to change. JRA.
107
108 ****************************************************************/
109
110 void endsam21pwent(void *vp)
111 {
112   pwdb_ops->endsam21pwent(vp);
113 }
114
115 /*************************************************************************
116  Routine to return the next entry in the smb passwd list.
117  *************************************************************************/
118
119 struct sam_passwd *getsam21pwent(void *vp)
120 {
121         return pwdb_sam_map_names(pwdb_ops->getsam21pwent(vp));
122 }
123
124 /************************************************************************
125  Utility function to search sam passwd by name.  use this if your database
126  does not have search facilities.
127 *************************************************************************/
128
129 struct sam_passwd *iterate_getsam21pwntnam(const char *name)
130 {
131         struct sam_passwd *pwd = NULL;
132         void *fp = NULL;
133
134         DEBUG(10, ("search by name: %s\n", name));
135
136         /* Open the smb password database - not for update. */
137         fp = startsmbpwent(False);
138
139         if (fp == NULL)
140         {
141                 DEBUG(0, ("unable to open sam password database.\n"));
142                 return NULL;
143         }
144
145         while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->nt_name, name))
146         {
147                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
148         }
149
150         if (pwd != NULL)
151         {
152                 DEBUG(10, ("found by name: %s\n", name));
153         }
154
155         endsmbpwent(fp);
156         return pwd;
157 }
158
159 /************************************************************************
160  Utility function to search sam passwd by rid.  use this if your database
161  does not have search facilities.
162
163  search capability by both rid and uid are needed as the rid <-> uid
164  mapping may be non-monotonic.  
165
166 *************************************************************************/
167
168 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
169 {
170         struct sam_passwd *pwd = NULL;
171         void *fp = NULL;
172
173         DEBUG(10, ("search by rid: %x\n", rid));
174
175         /* Open the smb password file - not for update. */
176         fp = startsmbpwent(False);
177
178         if (fp == NULL)
179         {
180                 DEBUG(0, ("unable to open sam password database.\n"));
181                 return NULL;
182         }
183
184         while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
185         {
186                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
187         }
188
189         if (pwd != NULL)
190         {
191                 DEBUG(10, ("found by user_rid: %x\n", rid));
192         }
193
194         endsmbpwent(fp);
195         return pwd;
196 }
197
198 /************************************************************************
199  Utility function to search sam passwd by uid.  use this if your database
200  does not have search facilities.
201
202  search capability by both rid and uid are needed as the rid <-> uid
203  mapping may be non-monotonic.  
204
205 *************************************************************************/
206
207 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
208 {
209         struct sam_passwd *pwd = NULL;
210         void *fp = NULL;
211
212         DEBUG(10, ("search by uid: %x\n", (int)uid));
213
214         /* Open the smb password file - not for update. */
215         fp = startsmbpwent(False);
216
217         if (fp == NULL)
218         {
219                 DEBUG(0, ("unable to open sam password database.\n"));
220                 return NULL;
221         }
222
223         while ((pwd = getsam21pwent(fp)) != NULL && pwd->unix_uid != uid)
224         {
225         }
226
227         if (pwd != NULL)
228         {
229                 DEBUG(10, ("found by unix_uid: %x\n", (int)uid));
230         }
231
232         endsmbpwent(fp);
233         return pwd;
234 }
235
236 /*************************************************************************
237  Routine to return a display info structure, by rid
238  *************************************************************************/
239 struct sam_disp_info *getsamdisprid(uint32 rid)
240 {
241         return pwdb_ops->getsamdisprid(rid);
242 }
243
244 /************************************************************************
245  Routine to search sam passwd by name.
246 *************************************************************************/
247
248 struct sam_passwd *getsam21pwntnam(const char *name)
249 {
250         return pwdb_sam_map_names(pwdb_ops->getsam21pwntnam(name));
251 }
252
253 /************************************************************************
254  Routine to search sam passwd by rid.  
255 *************************************************************************/
256
257 struct sam_passwd *getsam21pwrid(uint32 rid)
258 {
259         return pwdb_sam_map_names(pwdb_ops->getsam21pwrid(rid));
260 }
261
262
263 /**********************************************************
264  **********************************************************
265
266  utility routines which are likely to be useful to all password
267  databases
268
269  **********************************************************
270  **********************************************************/
271
272 /*************************************************************
273  initialises a struct sam_disp_info.
274  **************************************************************/
275
276 static void pwdb_init_dispinfo(struct sam_disp_info *user)
277 {
278         if (user == NULL) return;
279         bzero(user, sizeof(*user));
280         user->user_rid = 0xffffffff;
281 }
282
283 /*************************************************************
284  initialises a struct sam_passwd.
285  **************************************************************/
286 void pwdb_init_sam(struct sam_passwd *user)
287 {
288         if (user == NULL) return;
289         bzero(user, sizeof(*user));
290         unix_to_nt_time(&user->logon_time            , (time_t)-1);
291         unix_to_nt_time(&user->logoff_time           , (time_t)-1);
292         unix_to_nt_time(&user->kickoff_time          , (time_t)-1);
293         unix_to_nt_time(&user->pass_last_set_time    , (time_t)-1);
294         unix_to_nt_time(&user->pass_can_change_time  , (time_t)-1);
295         unix_to_nt_time(&user->pass_must_change_time , (time_t)-1);
296
297         user->unix_uid = (uid_t)-1;
298         user->unix_gid = (gid_t)-1;
299         user->user_rid  = 0xffffffff;
300         user->group_rid = 0xffffffff;
301 }
302
303 /*************************************************************************
304  Routine to return the next entry in the sam passwd list.
305  *************************************************************************/
306
307 struct sam_disp_info *pwdb_sam_to_dispinfo(struct sam_passwd *user)
308 {
309         static struct sam_disp_info disp_info;
310
311         if (user == NULL) return NULL;
312
313         pwdb_init_dispinfo(&disp_info);
314
315         disp_info.nt_name   = user->nt_name;
316         disp_info.full_name = user->full_name;
317         disp_info.user_rid  = user->user_rid;
318
319         return &disp_info;
320 }
321
322 /*************************************************************
323  converts a sam_passwd structure to a smb_passwd structure.
324  **************************************************************/
325
326 struct smb_passwd *pwdb_sam_to_smb(struct sam_passwd *user)
327 {
328         static struct smb_passwd pw_buf;
329         static fstring nt_name;
330         static fstring unix_name;
331
332         if (user == NULL) return NULL;
333
334         pwdb_init_smb(&pw_buf);
335
336         fstrcpy(nt_name  , user->nt_name);
337         fstrcpy(unix_name, user->unix_name);
338         pw_buf.nt_name            = nt_name;
339         pw_buf.unix_name          = unix_name;
340         pw_buf.unix_uid           = user->unix_uid;
341         pw_buf.user_rid           = user->user_rid;
342         pw_buf.smb_passwd         = user->smb_passwd;
343         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
344         pw_buf.acct_ctrl          = user->acct_ctrl;
345         pw_buf.pass_last_set_time = nt_time_to_unix(&user->pass_last_set_time);
346
347         return &pw_buf;
348 }
349
350
351 /*************************************************************
352  converts a smb_passwd structure to a sam_passwd structure.
353  **************************************************************/
354
355 struct sam_passwd *pwdb_smb_to_sam(struct smb_passwd *user)
356 {
357         static struct sam_passwd pw_buf;
358         static fstring nt_name;
359         static fstring unix_name;
360
361         if (user == NULL) return NULL;
362
363         pwdb_init_sam(&pw_buf);
364
365         fstrcpy(nt_name  , user->nt_name);
366         fstrcpy(unix_name, user->unix_name);
367         pw_buf.nt_name            = nt_name;
368         pw_buf.unix_name          = unix_name;
369         pw_buf.unix_uid           = user->unix_uid;
370         pw_buf.user_rid           = user->user_rid;
371         pw_buf.smb_passwd         = user->smb_passwd;
372         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
373         pw_buf.acct_ctrl          = user->acct_ctrl;
374         unix_to_nt_time(&pw_buf.pass_last_set_time, user->pass_last_set_time);
375
376         return &pw_buf;
377 }
378
379 static BOOL trust_account_warning_done = False;
380
381 /*************************************************************
382  fills in missing details.  one set of details _must_ exist.
383  **************************************************************/
384 struct sam_passwd *pwdb_sam_map_names(struct sam_passwd *sam)
385 {
386         DOM_NAME_MAP gmep;
387         BOOL found = False;
388         DOM_SID sid;
389         static fstring unix_name;
390         static fstring nt_name;
391
392         DEBUG(10,("pwdb_sam_map_names\n"));
393
394         /*
395          * name details
396          */
397
398         if (sam == NULL)
399         {
400                 return NULL;
401         }
402
403         if (!found && sam->unix_name != NULL)
404         {
405                 found = lookupsmbpwnam(sam->unix_name, &gmep);
406         }
407         if (!found && sam->unix_uid  != (uid_t)-1)
408         {
409                 found = lookupsmbpwuid(sam->unix_uid , &gmep);
410         }
411         if (!found && sam->user_rid != 0xffffffff)
412         {
413                 sid_copy(&sid, &global_sam_sid);
414                 sid_append_rid(&sid, sam->user_rid);
415                 found = lookupsmbpwsid  (&sid        , &gmep);
416         }
417         if (!found && sam->nt_name  != NULL)
418         {
419                 found = lookupsmbpwntnam(sam->nt_name, &gmep);
420         }
421
422         if (!found)
423         {
424                 return NULL;
425         }
426
427         if (!sid_front_equal(&global_sam_sid, &gmep.sid))
428         {
429                 return NULL;
430         }
431
432         fstrcpy(unix_name, gmep.unix_name);
433         fstrcpy(nt_name  , gmep.nt_name  );
434         if (sam->unix_name == NULL      ) sam->unix_name = unix_name;
435         if (sam->nt_name   == NULL      ) sam->nt_name   = nt_name  ;
436         if (sam->unix_uid  == (uid_t)-1 ) sam->unix_uid  = (uid_t)gmep.unix_id;
437         if (sam->user_rid  == 0xffffffff) sid_split_rid(&gmep.sid, &sam->user_rid);
438
439         /*
440          * group details
441          */
442
443         found = False;
444
445         if (sam->unix_gid != (gid_t)-1 && sam->group_rid != 0xffffffff)
446         {
447                 return sam;
448         }
449
450         if (sam->unix_gid == (gid_t)-1 && sam->group_rid == 0xffffffff)
451         {
452                 struct passwd *pass = getpwnam(unix_name);
453                 if (pass != NULL)
454                 {
455                         sam->unix_gid = pass->pw_gid;
456                 }
457                 else
458                 {
459                         DEBUG(0,("pwdb_sam_map_names: no unix password entry for %s\n",
460                                   unix_name));
461                 }
462         }
463
464         if (!found && sam->unix_gid  != (gid_t)-1)
465         {
466                 found = lookupsmbgrpgid(sam->unix_gid , &gmep);
467         }
468         if (!found && sam->group_rid != 0xffffffff)
469         {
470                 sid_copy(&sid, &global_sam_sid);
471                 sid_append_rid(&sid, sam->group_rid);
472                 found = lookupsmbgrpsid(&sid        , &gmep);
473         }
474
475         if (!found)
476         {
477                 if (IS_BITS_SET_SOME(sam->acct_ctrl, ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST))
478                 {
479                         if (!trust_account_warning_done)
480                         {
481                                 trust_account_warning_done = True;
482                                 DEBUG(0, ("\
483 pwdb_sam_map_names: your unix password database appears to have difficulties\n\
484 resolving trust account %s, probably because it ends in a '$'.\n\
485 you will get this warning only once (for all trust accounts)\n", unix_name));
486                         }
487                         /*
488                          * oh, dear.
489                          */
490                         if (sam->unix_gid != (gid_t)-1)
491                         {
492                                 sam->unix_gid = (gid_t)-1;
493                         }
494                         sam->group_rid = DOMAIN_GROUP_RID_USERS;
495
496                         return sam;
497                 }
498                 else
499                 {
500                         DEBUG(0, ("pwdb_sam_map_names: could not find Primary Group for %s\n",
501                                    unix_name));
502                         return NULL;
503                 }
504         }
505
506         if (!sid_front_equal(&global_sam_sid, &gmep.sid))
507         {
508                 return NULL;
509         }
510
511         if (sam->unix_gid  == (gid_t)-1 ) sam->unix_gid  = (gid_t)gmep.unix_id;
512         if (sam->group_rid == 0xffffffff) sid_split_rid(&gmep.sid, &sam->group_rid);
513
514         return sam;
515 }