2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Jeremy Allison 1996-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
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.
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.
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.
26 extern int DEBUGLEVEL;
27 extern DOM_SID global_sam_sid;
30 * NOTE. All these functions are abstracted into a structure
31 * that points to the correct function for the selected database. JRA.
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.
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.
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.
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.
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.
56 static struct sam_passdb_ops *pwdb_ops;
58 /***************************************************************
59 Initialise the password db operations.
60 ***************************************************************/
62 BOOL initialise_sam_password_db(void)
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();
77 return (pwdb_ops != NULL);
81 * Functions that return/manipulate a struct sam_passwd.
84 /***************************************************************
85 Start to enumerate the smb or sam passwd list. Returns a void pointer
86 to ensure no modification outside this module.
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
93 ****************************************************************/
95 void *startsam21pwent(BOOL update)
97 return pwdb_ops->startsam21pwent(update);
100 /***************************************************************
101 End enumeration of the sam passwd list.
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
108 ****************************************************************/
110 void endsam21pwent(void *vp)
112 pwdb_ops->endsam21pwent(vp);
115 /*************************************************************************
116 Routine to return the next entry in the smb passwd list.
117 *************************************************************************/
119 struct sam_passwd *getsam21pwent(void *vp)
121 return pwdb_sam_map_names(pwdb_ops->getsam21pwent(vp));
124 /************************************************************************
125 Utility function to search sam passwd by name. use this if your database
126 does not have search facilities.
127 *************************************************************************/
129 struct sam_passwd *iterate_getsam21pwntnam(const char *name)
131 struct sam_passwd *pwd = NULL;
134 DEBUG(10, ("search by name: %s\n", name));
136 /* Open the smb password database - not for update. */
137 fp = startsmbpwent(False);
141 DEBUG(0, ("unable to open sam password database.\n"));
145 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->nt_name, name))
147 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
152 DEBUG(10, ("found by name: %s\n", name));
159 /************************************************************************
160 Utility function to search sam passwd by rid. use this if your database
161 does not have search facilities.
163 search capability by both rid and uid are needed as the rid <-> uid
164 mapping may be non-monotonic.
166 *************************************************************************/
168 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
170 struct sam_passwd *pwd = NULL;
173 DEBUG(10, ("search by rid: %x\n", rid));
175 /* Open the smb password file - not for update. */
176 fp = startsmbpwent(False);
180 DEBUG(0, ("unable to open sam password database.\n"));
184 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
186 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
191 DEBUG(10, ("found by user_rid: %x\n", rid));
198 /************************************************************************
199 Utility function to search sam passwd by uid. use this if your database
200 does not have search facilities.
202 search capability by both rid and uid are needed as the rid <-> uid
203 mapping may be non-monotonic.
205 *************************************************************************/
207 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
209 struct sam_passwd *pwd = NULL;
212 DEBUG(10, ("search by uid: %x\n", (int)uid));
214 /* Open the smb password file - not for update. */
215 fp = startsmbpwent(False);
219 DEBUG(0, ("unable to open sam password database.\n"));
223 while ((pwd = getsam21pwent(fp)) != NULL && pwd->unix_uid != uid)
229 DEBUG(10, ("found by unix_uid: %x\n", (int)uid));
236 /*************************************************************************
237 Routine to return a display info structure, by rid
238 *************************************************************************/
239 struct sam_disp_info *getsamdisprid(uint32 rid)
241 return pwdb_ops->getsamdisprid(rid);
244 /************************************************************************
245 Routine to search sam passwd by name.
246 *************************************************************************/
248 struct sam_passwd *getsam21pwntnam(const char *name)
250 return pwdb_sam_map_names(pwdb_ops->getsam21pwntnam(name));
253 /************************************************************************
254 Routine to search sam passwd by rid.
255 *************************************************************************/
257 struct sam_passwd *getsam21pwrid(uint32 rid)
259 return pwdb_sam_map_names(pwdb_ops->getsam21pwrid(rid));
263 /**********************************************************
264 **********************************************************
266 utility routines which are likely to be useful to all password
269 **********************************************************
270 **********************************************************/
272 /*************************************************************
273 initialises a struct sam_disp_info.
274 **************************************************************/
276 static void pwdb_init_dispinfo(struct sam_disp_info *user)
278 if (user == NULL) return;
279 bzero(user, sizeof(*user));
280 user->user_rid = 0xffffffff;
283 /*************************************************************
284 initialises a struct sam_passwd.
285 **************************************************************/
286 void pwdb_init_sam(struct sam_passwd *user)
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);
297 user->unix_uid = (uid_t)-1;
298 user->unix_gid = (gid_t)-1;
299 user->user_rid = 0xffffffff;
300 user->group_rid = 0xffffffff;
303 /*************************************************************************
304 Routine to return the next entry in the sam passwd list.
305 *************************************************************************/
307 struct sam_disp_info *pwdb_sam_to_dispinfo(struct sam_passwd *user)
309 static struct sam_disp_info disp_info;
311 if (user == NULL) return NULL;
313 pwdb_init_dispinfo(&disp_info);
315 disp_info.nt_name = user->nt_name;
316 disp_info.full_name = user->full_name;
317 disp_info.user_rid = user->user_rid;
322 /*************************************************************
323 converts a sam_passwd structure to a smb_passwd structure.
324 **************************************************************/
326 struct smb_passwd *pwdb_sam_to_smb(struct sam_passwd *user)
328 static struct smb_passwd pw_buf;
329 static fstring nt_name;
330 static fstring unix_name;
332 if (user == NULL) return NULL;
334 pwdb_init_smb(&pw_buf);
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);
351 /*************************************************************
352 converts a smb_passwd structure to a sam_passwd structure.
353 **************************************************************/
355 struct sam_passwd *pwdb_smb_to_sam(struct smb_passwd *user)
357 static struct sam_passwd pw_buf;
358 static fstring nt_name;
359 static fstring unix_name;
361 if (user == NULL) return NULL;
363 pwdb_init_sam(&pw_buf);
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);
379 static BOOL trust_account_warning_done = False;
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)
389 static fstring unix_name;
390 static fstring nt_name;
392 DEBUG(10,("pwdb_sam_map_names\n"));
403 if (!found && sam->unix_name != NULL)
405 found = lookupsmbpwnam(sam->unix_name, &gmep);
407 if (!found && sam->unix_uid != (uid_t)-1)
409 found = lookupsmbpwuid(sam->unix_uid , &gmep);
411 if (!found && sam->user_rid != 0xffffffff)
413 sid_copy(&sid, &global_sam_sid);
414 sid_append_rid(&sid, sam->user_rid);
415 found = lookupsmbpwsid (&sid , &gmep);
417 if (!found && sam->nt_name != NULL)
419 found = lookupsmbpwntnam(sam->nt_name, &gmep);
427 if (!sid_front_equal(&global_sam_sid, &gmep.sid))
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);
445 if (sam->unix_gid != (gid_t)-1 && sam->group_rid != 0xffffffff)
450 if (sam->unix_gid == (gid_t)-1 && sam->group_rid == 0xffffffff)
452 struct passwd *pass = getpwnam(unix_name);
455 sam->unix_gid = pass->pw_gid;
459 DEBUG(0,("pwdb_sam_map_names: no unix password entry for %s\n",
464 if (!found && sam->unix_gid != (gid_t)-1)
466 found = lookupsmbgrpgid(sam->unix_gid , &gmep);
468 if (!found && sam->group_rid != 0xffffffff)
470 sid_copy(&sid, &global_sam_sid);
471 sid_append_rid(&sid, sam->group_rid);
472 found = lookupsmbgrpsid(&sid , &gmep);
477 if (IS_BITS_SET_SOME(sam->acct_ctrl, ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST))
479 if (!trust_account_warning_done)
481 trust_account_warning_done = True;
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));
490 if (sam->unix_gid != (gid_t)-1)
492 sam->unix_gid = (gid_t)-1;
494 sam->group_rid = DOMAIN_GROUP_RID_USERS;
500 DEBUG(0, ("pwdb_sam_map_names: could not find Primary Group for %s\n",
506 if (!sid_front_equal(&global_sam_sid, &gmep.sid))
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);