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 *ntname)
132 struct sam_passwd *pwd = NULL;
135 DEBUG(10, ("search by name: %s\n", ntname));
137 fstrcpy(nt_name, ntname);
139 /* Open the smb password database - not for update. */
140 fp = startsmbpwent(False);
144 DEBUG(0, ("unable to open sam password database.\n"));
148 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->nt_name, nt_name))
150 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
155 DEBUG(10, ("found by name: %s\n", nt_name));
162 /************************************************************************
163 Utility function to search sam passwd by rid. use this if your database
164 does not have search facilities.
166 search capability by both rid and uid are needed as the rid <-> uid
167 mapping may be non-monotonic.
169 *************************************************************************/
171 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
173 struct sam_passwd *pwd = NULL;
176 DEBUG(10, ("search by rid: %x\n", rid));
178 /* Open the smb password file - not for update. */
179 fp = startsmbpwent(False);
183 DEBUG(0, ("unable to open sam password database.\n"));
187 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
189 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
194 DEBUG(10, ("found by user_rid: %x\n", rid));
201 /************************************************************************
202 Utility function to search sam passwd by uid. use this if your database
203 does not have search facilities.
205 search capability by both rid and uid are needed as the rid <-> uid
206 mapping may be non-monotonic.
208 *************************************************************************/
210 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
212 struct sam_passwd *pwd = NULL;
215 DEBUG(10, ("search by uid: %x\n", (int)uid));
217 /* Open the smb password file - not for update. */
218 fp = startsmbpwent(False);
222 DEBUG(0, ("unable to open sam password database.\n"));
226 while ((pwd = getsam21pwent(fp)) != NULL && pwd->unix_uid != uid)
232 DEBUG(10, ("found by unix_uid: %x\n", (int)uid));
239 /*************************************************************************
240 Routine to return a display info structure, by rid
241 *************************************************************************/
242 struct sam_disp_info *getsamdisprid(uint32 rid)
244 return pwdb_ops->getsamdisprid(rid);
247 /************************************************************************
248 Routine to search sam passwd by name.
249 *************************************************************************/
251 struct sam_passwd *getsam21pwntnam(const char *name)
253 return pwdb_sam_map_names(pwdb_ops->getsam21pwntnam(name));
256 /************************************************************************
257 Routine to search sam passwd by rid.
258 *************************************************************************/
260 struct sam_passwd *getsam21pwrid(uint32 rid)
262 return pwdb_sam_map_names(pwdb_ops->getsam21pwrid(rid));
266 /**********************************************************
267 **********************************************************
269 utility routines which are likely to be useful to all password
272 **********************************************************
273 **********************************************************/
275 /*************************************************************
276 initialises a struct sam_disp_info.
277 **************************************************************/
279 static void pwdb_init_dispinfo(struct sam_disp_info *user)
281 if (user == NULL) return;
282 bzero(user, sizeof(*user));
283 user->user_rid = 0xffffffff;
286 /*************************************************************
287 initialises a struct sam_passwd.
288 **************************************************************/
289 void pwdb_init_sam(struct sam_passwd *user)
291 if (user == NULL) return;
292 bzero(user, sizeof(*user));
293 unix_to_nt_time(&user->logon_time , (time_t)-1);
294 unix_to_nt_time(&user->logoff_time , (time_t)-1);
295 unix_to_nt_time(&user->kickoff_time , (time_t)-1);
296 unix_to_nt_time(&user->pass_last_set_time , (time_t)-1);
297 unix_to_nt_time(&user->pass_can_change_time , (time_t)-1);
298 unix_to_nt_time(&user->pass_must_change_time , (time_t)-1);
300 user->unix_uid = (uid_t)-1;
301 user->unix_gid = (gid_t)-1;
302 user->user_rid = 0xffffffff;
303 user->group_rid = 0xffffffff;
306 /*************************************************************************
307 Routine to return the next entry in the sam passwd list.
308 *************************************************************************/
310 struct sam_disp_info *pwdb_sam_to_dispinfo(struct sam_passwd *user)
312 static struct sam_disp_info disp_info;
314 if (user == NULL) return NULL;
316 pwdb_init_dispinfo(&disp_info);
318 disp_info.nt_name = user->nt_name;
319 disp_info.full_name = user->full_name;
320 disp_info.user_rid = user->user_rid;
325 /*************************************************************
326 converts a sam_passwd structure to a smb_passwd structure.
327 **************************************************************/
329 struct smb_passwd *pwdb_sam_to_smb(struct sam_passwd *user)
331 static struct smb_passwd pw_buf;
332 static fstring nt_name;
333 static fstring unix_name;
335 if (user == NULL) return NULL;
337 pwdb_init_smb(&pw_buf);
339 fstrcpy(nt_name , user->nt_name);
340 fstrcpy(unix_name, user->unix_name);
341 pw_buf.nt_name = nt_name;
342 pw_buf.unix_name = unix_name;
343 pw_buf.unix_uid = user->unix_uid;
344 pw_buf.user_rid = user->user_rid;
345 pw_buf.smb_passwd = user->smb_passwd;
346 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
347 pw_buf.acct_ctrl = user->acct_ctrl;
348 pw_buf.pass_last_set_time = nt_time_to_unix(&user->pass_last_set_time);
354 /*************************************************************
355 converts a smb_passwd structure to a sam_passwd structure.
356 **************************************************************/
358 struct sam_passwd *pwdb_smb_to_sam(struct smb_passwd *user)
360 static struct sam_passwd pw_buf;
361 static fstring nt_name;
362 static fstring unix_name;
364 static int time_count = 0;
366 if (user == NULL) return NULL;
368 pwdb_init_sam(&pw_buf);
370 fstrcpy(nt_name , user->nt_name);
371 fstrcpy(unix_name, user->unix_name);
372 pw_buf.nt_name = nt_name;
373 pw_buf.unix_name = unix_name;
374 pw_buf.unix_uid = user->unix_uid;
375 pw_buf.user_rid = user->user_rid;
376 pw_buf.smb_passwd = user->smb_passwd;
377 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
378 pw_buf.acct_ctrl = user->acct_ctrl;
380 /* Just update the time counter every 1,000 times though this function */
381 switch (time_count) {
383 DEBUG(3, ("Called time() in smb_to_sam function\n"));
395 if ( user->pass_last_set_time == (time_t)-1 )
397 user->pass_last_set_time = t;
399 unix_to_nt_time(&pw_buf.pass_last_set_time, user->pass_last_set_time);
400 unix_to_nt_time(&pw_buf.pass_can_change_time , user->pass_last_set_time);
401 unix_to_nt_time(&pw_buf.pass_must_change_time, t+3628800);
407 static BOOL trust_account_warning_done = False;
409 /*************************************************************
410 fills in missing details. one set of details _must_ exist.
411 **************************************************************/
412 struct sam_passwd *pwdb_sam_map_names(struct sam_passwd *sam)
417 static fstring unix_name;
418 static fstring nt_name;
420 DEBUG(10,("pwdb_sam_map_names\n"));
431 if (!found && sam->unix_name != NULL)
433 found = lookupsmbpwnam(sam->unix_name, &gmep);
435 if (!found && sam->unix_uid != (uid_t)-1)
437 found = lookupsmbpwuid(sam->unix_uid , &gmep);
439 if (!found && sam->user_rid != 0xffffffff)
441 sid_copy(&sid, &global_sam_sid);
442 sid_append_rid(&sid, sam->user_rid);
443 found = lookupsmbpwsid (&sid , &gmep);
445 if (!found && sam->nt_name != NULL)
447 found = lookupsmbpwntnam(sam->nt_name, &gmep);
455 if (!sid_front_equal(&global_sam_sid, &gmep.sid))
460 fstrcpy(unix_name, gmep.unix_name);
461 fstrcpy(nt_name , gmep.nt_name );
462 if (sam->unix_name == NULL ) sam->unix_name = unix_name;
463 if (sam->nt_name == NULL ) sam->nt_name = nt_name ;
464 if (sam->unix_uid == (uid_t)-1 ) sam->unix_uid = (uid_t)gmep.unix_id;
465 if (sam->user_rid == 0xffffffff) sid_split_rid(&gmep.sid, &sam->user_rid);
467 DEBUG(10,("pwdb_sam_map_name: found unix user %s nt %s uid %d rid 0x%x\n",
468 sam->unix_name, sam->nt_name, sam->unix_uid, sam->user_rid));
476 if (sam->unix_gid != (gid_t)-1 && sam->group_rid != 0xffffffff)
481 if (sam->unix_gid == (gid_t)-1 && sam->group_rid == 0xffffffff)
483 struct passwd *pass = getpwnam(unix_name);
486 sam->unix_gid = pass->pw_gid;
490 DEBUG(0,("pwdb_sam_map_names: no unix password entry for %s\n",
495 if (!found && sam->unix_gid != (gid_t)-1)
497 found = lookupsmbgrpgid(sam->unix_gid , &gmep);
499 if (!found && sam->group_rid != 0xffffffff)
501 sid_copy(&sid, &global_sam_sid);
502 sid_append_rid(&sid, sam->group_rid);
503 found = lookupsmbgrpsid(&sid , &gmep);
508 if (IS_BITS_SET_SOME(sam->acct_ctrl, ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST))
510 if (!trust_account_warning_done)
512 trust_account_warning_done = True;
514 pwdb_sam_map_names: your unix password database appears to have difficulties\n\
515 resolving trust account %s, probably because it ends in a '$'.\n\
516 you will get this warning only once (for all trust accounts)\n", unix_name));
521 if (sam->unix_gid != (gid_t)-1)
523 sam->unix_gid = (gid_t)-1;
525 sam->group_rid = DOMAIN_GROUP_RID_USERS;
531 DEBUG(0, ("pwdb_sam_map_names: could not find Primary Group for %s\n",
537 if (!sid_front_equal(&global_sam_sid, &gmep.sid))
540 sid_to_string(sid_str, &gmep.sid);
541 DEBUG(0,("UNIX User %s Primary Group is in the wrong domain! %s\n",
542 sam->unix_name, sid_str));
546 if (sam->unix_gid == (gid_t)-1 ) sam->unix_gid = (gid_t)gmep.unix_id;
547 if (sam->group_rid == 0xffffffff) sid_split_rid(&gmep.sid, &sam->group_rid);
549 DEBUG(10,("pwdb_sam_map_name: found gid %d and group rid 0x%x for unix user %s\n",
550 sam->unix_gid, sam->group_rid, sam->unix_name));