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 if (user == NULL) return NULL;
366 pwdb_init_sam(&pw_buf);
368 fstrcpy(nt_name , user->nt_name);
369 fstrcpy(unix_name, user->unix_name);
370 pw_buf.nt_name = nt_name;
371 pw_buf.unix_name = unix_name;
372 pw_buf.unix_uid = user->unix_uid;
373 pw_buf.user_rid = user->user_rid;
374 pw_buf.smb_passwd = user->smb_passwd;
375 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
376 pw_buf.acct_ctrl = user->acct_ctrl;
377 unix_to_nt_time(&pw_buf.pass_last_set_time, user->pass_last_set_time);
382 static BOOL trust_account_warning_done = False;
384 /*************************************************************
385 fills in missing details. one set of details _must_ exist.
386 **************************************************************/
387 struct sam_passwd *pwdb_sam_map_names(struct sam_passwd *sam)
392 static fstring unix_name;
393 static fstring nt_name;
395 DEBUG(10,("pwdb_sam_map_names\n"));
406 if (!found && sam->unix_name != NULL)
408 found = lookupsmbpwnam(sam->unix_name, &gmep);
410 if (!found && sam->unix_uid != (uid_t)-1)
412 found = lookupsmbpwuid(sam->unix_uid , &gmep);
414 if (!found && sam->user_rid != 0xffffffff)
416 sid_copy(&sid, &global_sam_sid);
417 sid_append_rid(&sid, sam->user_rid);
418 found = lookupsmbpwsid (&sid , &gmep);
420 if (!found && sam->nt_name != NULL)
422 found = lookupsmbpwntnam(sam->nt_name, &gmep);
430 if (!sid_front_equal(&global_sam_sid, &gmep.sid))
435 fstrcpy(unix_name, gmep.unix_name);
436 fstrcpy(nt_name , gmep.nt_name );
437 if (sam->unix_name == NULL ) sam->unix_name = unix_name;
438 if (sam->nt_name == NULL ) sam->nt_name = nt_name ;
439 if (sam->unix_uid == (uid_t)-1 ) sam->unix_uid = (uid_t)gmep.unix_id;
440 if (sam->user_rid == 0xffffffff) sid_split_rid(&gmep.sid, &sam->user_rid);
442 DEBUG(10,("pwdb_sam_map_name: found unix user %s nt %s uid %d rid 0x%x\n",
443 sam->unix_name, sam->nt_name, sam->unix_uid, sam->user_rid));
451 if (sam->unix_gid != (gid_t)-1 && sam->group_rid != 0xffffffff)
456 if (sam->unix_gid == (gid_t)-1 && sam->group_rid == 0xffffffff)
458 struct passwd *pass = getpwnam(unix_name);
461 sam->unix_gid = pass->pw_gid;
465 DEBUG(0,("pwdb_sam_map_names: no unix password entry for %s\n",
470 if (!found && sam->unix_gid != (gid_t)-1)
472 found = lookupsmbgrpgid(sam->unix_gid , &gmep);
474 if (!found && sam->group_rid != 0xffffffff)
476 sid_copy(&sid, &global_sam_sid);
477 sid_append_rid(&sid, sam->group_rid);
478 found = lookupsmbgrpsid(&sid , &gmep);
483 if (IS_BITS_SET_SOME(sam->acct_ctrl, ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST))
485 if (!trust_account_warning_done)
487 trust_account_warning_done = True;
489 pwdb_sam_map_names: your unix password database appears to have difficulties\n\
490 resolving trust account %s, probably because it ends in a '$'.\n\
491 you will get this warning only once (for all trust accounts)\n", unix_name));
496 if (sam->unix_gid != (gid_t)-1)
498 sam->unix_gid = (gid_t)-1;
500 sam->group_rid = DOMAIN_GROUP_RID_USERS;
506 DEBUG(0, ("pwdb_sam_map_names: could not find Primary Group for %s\n",
512 if (!sid_front_equal(&global_sam_sid, &gmep.sid))
517 if (sam->unix_gid == (gid_t)-1 ) sam->unix_gid = (gid_t)gmep.unix_id;
518 if (sam->group_rid == 0xffffffff) sid_split_rid(&gmep.sid, &sam->group_rid);
520 DEBUG(10,("pwdb_sam_map_name: found gid %d and group rid 0x%x for unix user %s\n",
521 sam->unix_gid, sam->group_rid, sam->unix_name));