2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Andrew Tridgell 1992-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;
28 /**********************************************************
29 **********************************************************
31 low-level redirection routines:
45 **********************************************************
46 **********************************************************/
48 /***************************************************************
49 Start to enumerate the sam passwd list. Returns a void pointer
50 to ensure no modification outside this module.
51 ****************************************************************/
52 void *startsampwent(BOOL update)
55 return startldappwent(update);
57 return startsmbpwent(update);
61 /***************************************************************
62 End enumeration of the sam passwd list.
63 ****************************************************************/
64 void endsampwent(void *vp)
73 /*************************************************************************
74 Routine to return the next entry in the sam passwd list.
75 *************************************************************************/
76 struct smb_passwd *getsampwent(void *vp)
79 return getldappwent(vp);
81 return getsmbpwent(vp);
85 /*************************************************************************
86 Routine to return the next entry in the sam passwd list.
87 *************************************************************************/
88 struct sam_passwd *getsam21pwent(void *vp)
92 return getldap21pwent(vp);
94 return getsmb21pwent(vp);
97 DEBUG(0,("getsam21pwent: under development\n"));
102 /*************************************************************************
103 Return the current position in the sam passwd list as an unsigned long.
104 This must be treated as an opaque token.
105 *************************************************************************/
106 unsigned long getsampwpos(void *vp)
109 return getldappwpos(vp);
111 return getsmbpwpos(vp);
112 #endif /* USE_LDAP */
115 /*************************************************************************
116 Set the current position in the sam passwd list from unsigned long.
117 This must be treated as an opaque token.
118 *************************************************************************/
119 BOOL setsampwpos(void *vp, unsigned long tok)
122 return setldappwpos(vp, tok);
124 return setsmbpwpos(vp, tok);
125 #endif /* USE_LDAP */
128 /************************************************************************
129 Routine to add an entry to the sam passwd file.
130 *************************************************************************/
131 BOOL add_sampwd_entry(struct smb_passwd *newpwd)
134 return add_ldappwd_entry(newpwd);
136 return add_smbpwd_entry(newpwd);
137 #endif /* USE_LDAP */
140 /************************************************************************
141 Routine to add an entry to the sam passwd file.
142 *************************************************************************/
143 BOOL add_sam21pwd_entry(struct sam_passwd *newpwd)
147 return add_ldappwd_entry(newpwd);
149 return add_smbpwd_entry(newpwd);
150 #endif /* USE_LDAP */
152 DEBUG(0,("add_sam21pwd_entry() - under development\n"));
157 /************************************************************************
158 Routine to search the sam passwd file for an entry matching the username.
159 and then modify its password entry. We can't use the startsampwent()/
160 getsampwent()/endsampwent() interfaces here as we depend on looking
161 in the actual file to decide how much room we have to write data.
162 override = False, normal
163 override = True, override XXXXXXXX'd out password or NO PASS
164 ************************************************************************/
165 BOOL mod_sampwd_entry(struct smb_passwd* pwd, BOOL override)
168 return mod_ldappwd_entry(pwd, override);
170 return mod_smbpwd_entry(pwd, override);
171 #endif /* USE_LDAP */
174 /************************************************************************
175 Routine to search the sam passwd file for an entry matching the username.
176 and then modify its password entry. We can't use the startsampwent()/
177 getsampwent()/endsampwent() interfaces here as we depend on looking
178 in the actual file to decide how much room we have to write data.
179 override = False, normal
180 override = True, override XXXXXXXX'd out password or NO PASS
181 ************************************************************************/
182 BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override)
186 return mod_ldappwd_entry(pwd, override);
188 return mod_smbpwd_entry(pwd, override);
189 #endif /* USE_LDAP */
191 DEBUG(0,("mod_sam21pwd_entry() - under development\n"));
196 /**********************************************************
197 **********************************************************
199 high-level database routines:
205 **********************************************************
206 **********************************************************/
208 /************************************************************************
209 Routine to search sam passwd by name.
210 *************************************************************************/
211 struct smb_passwd *getsampwnam(char *name)
213 struct smb_passwd *pwd = NULL;
216 DEBUG(10, ("getsampwnam: search by name: %s\n", name));
218 /* Open the sam password file - not for update. */
219 fp = startsampwent(False);
223 DEBUG(0, ("getsampwnam: unable to open sam password database.\n"));
227 while ((pwd = getsampwent(fp)) != NULL && !strequal(pwd->smb_name, name));
231 DEBUG(10, ("getsampwnam: found by name: %s\n", name));
238 /************************************************************************
239 Routine to search sam passwd by name.
240 *************************************************************************/
241 struct sam_passwd *getsam21pwnam(char *name)
243 struct sam_passwd *pwd = NULL;
246 DEBUG(10, ("getsam21pwnam: search by name: %s\n", name));
248 /* Open the sam password file - not for update. */
249 fp = startsampwent(False);
253 DEBUG(0, ("getsam21pwnam: unable to open sam password database.\n"));
257 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name));
261 DEBUG(10, ("getsam21pwnam: found by name: %s\n", name));
268 /************************************************************************
269 Routine to search sam passwd by uid.
270 *************************************************************************/
271 struct smb_passwd *getsampwuid(uid_t smb_userid)
273 struct smb_passwd *pwd = NULL;
276 DEBUG(10, ("getsampwuid: search by smb_userid: %x\n", smb_userid));
278 /* Open the sam password file - not for update. */
279 fp = startsampwent(False);
283 DEBUG(0, ("getsampwuid: unable to open sam password database.\n"));
287 while ((pwd = getsampwent(fp)) != NULL && pwd->smb_userid != smb_userid);
291 DEBUG(10, ("getsampwuid: found by smb_userid: %x\n", smb_userid));
298 /************************************************************************
299 Routine to search sam passwd by rid.
300 *************************************************************************/
301 struct sam_passwd *getsam21pwrid(uint32 rid)
303 struct sam_passwd *pwd = NULL;
306 DEBUG(10, ("getsam21pwrid: search by rid: %x\n", rid));
308 /* Open the sam password file - not for update. */
309 fp = startsampwent(False);
313 DEBUG(0, ("getsam21pwrid: unable to open sam password database.\n"));
317 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid);
321 DEBUG(10, ("getsam21pwrid: found by smb_userid: %x\n", rid));
329 /**********************************************************
330 **********************************************************
332 utility routines which are likely to be useful to all password
335 **********************************************************
336 **********************************************************/
338 /**********************************************************
339 Encode the account control bits into a string.
340 **********************************************************/
341 char *encode_acct_ctrl(uint16 acct_ctrl)
343 static fstring acct_str;
348 if (acct_ctrl & ACB_HOMDIRREQ) *p++ = 'H';
349 if (acct_ctrl & ACB_TEMPDUP ) *p++ = 'T';
350 if (acct_ctrl & ACB_NORMAL ) *p++ = 'U';
351 if (acct_ctrl & ACB_MNS ) *p++ = 'M';
352 if (acct_ctrl & ACB_WSTRUST ) *p++ = 'W';
353 if (acct_ctrl & ACB_SVRTRUST ) *p++ = 'S';
354 if (acct_ctrl & ACB_AUTOLOCK ) *p++ = 'L';
355 if (acct_ctrl & ACB_PWNOEXP ) *p++ = 'X';
356 if (acct_ctrl & ACB_DOMTRUST ) *p++ = 'I';
363 /**********************************************************
364 Decode the account control bits from a string.
366 this function breaks coding standards minimum line width of 80 chars.
367 reason: vertical line-up code clarity - all case statements fit into
368 15 lines, which is more important.
369 **********************************************************/
370 uint16 decode_acct_ctrl(char *p)
372 uint16 acct_ctrl = 0;
373 BOOL finished = False;
376 * Check if the account type bits have been encoded after the
377 * NT password (in the form [NDHTUWSLXI]).
380 if (*p != '[') return 0;
382 for (p++; *p && !finished; p++)
388 * Hmmm. Don't allow these to be set/read independently
389 * of the actual password fields. We don't want a mismatch.
392 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
393 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
395 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
396 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
397 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
398 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
399 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
400 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
401 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
402 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
403 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
409 default: { finished = True; }
416 /*************************************************************
417 Routine to get the next 32 hex characters and turn them
418 into a 16 byte array.
419 **************************************************************/
420 int gethexpwd(char *p, char *pwd)
423 unsigned char lonybble, hinybble;
424 char *hexchars = "0123456789ABCDEF";
427 for (i = 0; i < 32; i += 2) {
428 hinybble = toupper(p[i]);
429 lonybble = toupper(p[i + 1]);
431 p1 = strchr(hexchars, hinybble);
432 p2 = strchr(hexchars, lonybble);
435 hinybble = PTR_DIFF(p1, hexchars);
436 lonybble = PTR_DIFF(p2, hexchars);
438 pwd[i / 2] = (hinybble << 4) | lonybble;
443 /*******************************************************************
444 Group and User RID username mapping function
445 ********************************************************************/
446 BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
448 struct passwd *pw = Get_Pwnam(user_name, False);
450 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
457 DEBUG(1,("Username %s is invalid on this system\n", user_name));
461 if (user_in_list(user_name, lp_domain_guest_users()))
463 *u_rid = DOMAIN_USER_RID_GUEST;
465 else if (user_in_list(user_name, lp_domain_admin_users()))
467 *u_rid = DOMAIN_USER_RID_ADMIN;
471 /* turn the unix UID into a Domain RID. this is what the posix
472 sub-system does (adds 1000 to the uid) */
473 *u_rid = uid_to_user_rid(pw->pw_uid);
476 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
477 *g_rid = gid_to_group_rid(pw->pw_gid);
482 /*******************************************************************
483 XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
486 converts NT User RID to a UNIX uid.
487 ********************************************************************/
488 uid_t user_rid_to_uid(uint32 u_rid)
490 return (uid_t)(u_rid - 1000);
493 /*******************************************************************
494 XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
497 converts NT Group RID to a UNIX uid.
498 ********************************************************************/
499 uid_t group_rid_to_uid(uint32 u_gid)
501 return (uid_t)(u_gid - 1000);
504 /*******************************************************************
505 XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
508 converts UNIX uid to an NT User RID.
509 ********************************************************************/
510 uint32 uid_to_user_rid(uint32 uid)
512 return (uint32)(uid + 1000);
515 /*******************************************************************
516 XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
519 converts NT Group RID to a UNIX uid.
520 ********************************************************************/
521 uint32 gid_to_group_rid(uint32 gid)
523 return (uint32)(gid + 1000);