couple of minor typos noticed by Toomas
[Samba.git] / source / passdb / passdb.c
blob1e8c47845eab13f02282de5b9bdf29911b6df75d
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Password and authentication handling
5 Copyright (C) Jeremy Allison 1996-2001
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
7 Copyright (C) Gerald (Jerry) Carter 2000-2001
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern int DEBUGLEVEL;
29 * This is set on startup - it defines the SID for this
30 * machine, and therefore the SAM database for which it is
31 * responsible.
34 extern DOM_SID global_sam_sid;
36 struct passdb_ops *pdb_ops;
38 #if 0 /* JERRY */
39 static void* pdb_handle = NULL;
40 #endif
42 /***************************************************************
43 Initialize the password db operations.
44 ***************************************************************/
46 BOOL initialize_password_db(BOOL reload)
48 /*
49 * This function is unfinished right now, so just
50 * ignore the details and always return True. It
51 * is here only as a placeholder --jerry
53 return True;
57 /*************************************************************
58 Initialises a struct sam_disp_info.
59 **************************************************************/
61 static void pdb_init_dispinfo(struct sam_disp_info *user)
63 if (user == NULL)
64 return;
65 ZERO_STRUCTP(user);
68 /*************************************************************
69 Alloc memory and initialises a struct sam_passwd.
70 ************************************************************/
72 BOOL pdb_init_sam(SAM_ACCOUNT **user)
74 if (*user != NULL) {
75 DEBUG(0,("pdb_init_sam: SAM_ACCOUNT was non NULL\n"));
76 #if 0
77 smb_panic("NULL pointer passed to pdb_init_sam\n");
78 #endif
79 return False;
82 *user=(SAM_ACCOUNT *)malloc(sizeof(SAM_ACCOUNT));
84 if (*user==NULL) {
85 DEBUG(0,("pdb_init_sam: error while allocating memory\n"));
86 return False;
89 ZERO_STRUCTP(*user);
91 (*user)->logon_time = (time_t)0;
92 (*user)->logoff_time = (time_t)-1;
93 (*user)->kickoff_time = (time_t)-1;
94 (*user)->pass_last_set_time = (time_t)-1;
95 (*user)->pass_can_change_time = (time_t)-1;
96 (*user)->pass_must_change_time = (time_t)-1;
98 (*user)->unknown_3 = 0x00ffffff; /* don't know */
99 (*user)->logon_divs = 168; /* hours per week */
100 (*user)->hours_len = 21; /* 21 times 8 bits = 168 */
101 memset((*user)->hours, 0xff, (*user)->hours_len); /* available at all hours */
102 (*user)->unknown_5 = 0x00000000; /* don't know */
103 (*user)->unknown_6 = 0x000004ec; /* don't know */
105 return True;
108 /************************************************************
109 Free the SAM_ACCOUNT and the NT/LM hashes.
110 ***********************************************************/
112 BOOL pdb_free_sam(SAM_ACCOUNT *user)
114 if (user == NULL) {
115 DEBUG(0,("pdb_free_sam: SAM_ACCOUNT was NULL\n"));
116 #if 0
117 smb_panic("NULL pointer passed to pdb_free_sam\n");
118 #endif
119 return False;
122 SAFE_FREE(user->nt_pw);
123 SAFE_FREE(user->lm_pw);
124 SAFE_FREE(user);
126 return True;
129 /************************************************************
130 Reset the SAM_ACCOUNT and the NT/LM hashes.
131 ***********************************************************/
133 BOOL pdb_reset_sam(SAM_ACCOUNT *user)
135 if (user == NULL) {
136 DEBUG(0,("pdb_reset_sam: SAM_ACCOUNT was NULL\n"));
137 return False;
140 SAFE_FREE(user->nt_pw);
141 SAFE_FREE(user->lm_pw);
142 ZERO_STRUCTP(user);
144 return True;
147 /*************************************************************************
148 Routine to return the next entry in the sam passwd list.
149 *************************************************************************/
151 struct sam_disp_info *pdb_sam_to_dispinfo(SAM_ACCOUNT *user)
153 static struct sam_disp_info disp_info;
155 if (user == NULL)
156 return NULL;
158 pdb_init_dispinfo(&disp_info);
160 disp_info.smb_name = user->username;
161 disp_info.full_name = user->full_name;
162 disp_info.user_rid = user->user_rid;
164 return &disp_info;
167 /**********************************************************
168 Encode the account control bits into a string.
169 length = length of string to encode into (including terminating
170 null). length *MUST BE MORE THAN 2* !
171 **********************************************************/
173 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
175 static fstring acct_str;
176 size_t i = 0;
178 acct_str[i++] = '[';
180 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
181 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
182 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
183 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
184 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
185 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
186 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
187 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
188 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
189 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
190 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
192 for ( ; i < length - 2 ; i++ )
193 acct_str[i] = ' ';
195 i = length - 2;
196 acct_str[i++] = ']';
197 acct_str[i++] = '\0';
199 return acct_str;
202 /**********************************************************
203 Decode the account control bits from a string.
204 **********************************************************/
206 uint16 pdb_decode_acct_ctrl(const char *p)
208 uint16 acct_ctrl = 0;
209 BOOL finished = False;
212 * Check if the account type bits have been encoded after the
213 * NT password (in the form [NDHTUWSLXI]).
216 if (*p != '[')
217 return 0;
219 for (p++; *p && !finished; p++) {
220 switch (*p) {
221 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
222 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
223 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
224 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
225 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
226 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
227 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
228 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
229 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
230 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
231 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
232 case ' ': { break; }
233 case ':':
234 case '\n':
235 case '\0':
236 case ']':
237 default: { finished = True; }
241 return acct_ctrl;
244 /*************************************************************
245 Routine to set 32 hex password characters from a 16 byte array.
246 **************************************************************/
248 void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl)
250 if (pwd != NULL) {
251 int i;
252 for (i = 0; i < 16; i++)
253 slprintf(&p[i*2], 3, "%02X", pwd[i]);
254 } else {
255 if (acct_ctrl & ACB_PWNOTREQ)
256 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
257 else
258 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
262 /*************************************************************
263 Routine to get the 32 hex characters and turn them
264 into a 16 byte array.
265 **************************************************************/
267 BOOL pdb_gethexpwd(char *p, unsigned char *pwd)
269 int i;
270 unsigned char lonybble, hinybble;
271 char *hexchars = "0123456789ABCDEF";
272 char *p1, *p2;
274 if (!p)
275 return (False);
277 for (i = 0; i < 32; i += 2) {
278 hinybble = toupper(p[i]);
279 lonybble = toupper(p[i + 1]);
281 p1 = strchr(hexchars, hinybble);
282 p2 = strchr(hexchars, lonybble);
284 if (!p1 || !p2)
285 return (False);
287 hinybble = PTR_DIFF(p1, hexchars);
288 lonybble = PTR_DIFF(p2, hexchars);
290 pwd[i / 2] = (hinybble << 4) | lonybble;
292 return (True);
295 /*******************************************************************
296 Group and User RID username mapping function
297 ********************************************************************/
299 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
301 struct passwd *pw = Get_Pwnam(user_name, False);
303 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
304 return False;
306 if (!pw) {
307 DEBUG(1,("Username %s is invalid on this system\n", user_name));
308 return False;
311 /* turn the unix UID into a Domain RID. this is what the posix
312 sub-system does (adds 1000 to the uid) */
313 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
315 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
316 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
318 return True;
321 /*******************************************************************
322 Converts NT user RID to a UNIX uid.
323 ********************************************************************/
325 uid_t pdb_user_rid_to_uid(uint32 user_rid)
327 return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
330 /*******************************************************************
331 Converts NT user RID to a UNIX gid.
332 ********************************************************************/
334 gid_t pdb_user_rid_to_gid(uint32 user_rid)
336 return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
339 /*******************************************************************
340 converts UNIX uid to an NT User RID.
341 ********************************************************************/
343 uint32 pdb_uid_to_user_rid(uid_t uid)
345 return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
348 /*******************************************************************
349 converts NT Group RID to a UNIX uid.
350 ********************************************************************/
352 uint32 pdb_gid_to_group_rid(gid_t gid)
354 return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
357 /*******************************************************************
358 Decides if a RID is a well known RID.
359 ********************************************************************/
361 static BOOL pdb_rid_is_well_known(uint32 rid)
363 return (rid < 1000);
366 /*******************************************************************
367 Decides if a RID is a user or group RID.
368 ********************************************************************/
370 BOOL pdb_rid_is_user(uint32 rid)
372 /* lkcl i understand that NT attaches an enumeration to a RID
373 * such that it can be identified as either a user, group etc
374 * type. there are 5 such categories, and they are documented.
376 if(pdb_rid_is_well_known(rid)) {
378 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
379 * and DOMAIN_USER_RID_GUEST.
381 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
382 return True;
383 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
384 return True;
386 return False;
389 /*******************************************************************
390 Convert a rid into a name. Used in the lookup SID rpc.
391 ********************************************************************/
393 BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
395 BOOL is_user = pdb_rid_is_user(rid);
397 DEBUG(5,("local_lookup_rid: looking up %s RID %u.\n", is_user ? "user" :
398 "group", (unsigned int)rid));
400 if(is_user) {
401 if(rid == DOMAIN_USER_RID_ADMIN) {
402 pstring admin_users;
403 char *p = admin_users;
404 if(!next_token(&p, name, NULL, sizeof(fstring)))
405 fstrcpy(name, "Administrator");
406 } else if (rid == DOMAIN_USER_RID_GUEST) {
407 pstring guest_users;
408 char *p = guest_users;
409 if(!next_token(&p, name, NULL, sizeof(fstring)))
410 fstrcpy(name, "Guest");
411 } else {
412 uid_t uid;
413 struct passwd *pass;
416 * Don't try to convert the rid to a name if
417 * running in appliance mode
419 if (lp_hide_local_users())
420 return False;
422 uid = pdb_user_rid_to_uid(rid);
423 pass = sys_getpwuid(uid);
425 *psid_name_use = SID_NAME_USER;
427 DEBUG(5,("local_lookup_rid: looking up uid %u %s\n", (unsigned int)uid,
428 pass ? "succeeded" : "failed" ));
430 if(!pass) {
431 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
432 return True;
435 fstrcpy(name, pass->pw_name);
437 DEBUG(5,("local_lookup_rid: found user %s for rid %u\n", name,
438 (unsigned int)rid ));
441 } else {
442 gid_t gid;
443 struct group *gr;
446 * Don't try to convert the rid to a name if running
447 * in appliance mode
450 if (lp_hide_local_users())
451 return False;
453 gid = pdb_user_rid_to_gid(rid);
454 gr = getgrgid(gid);
456 *psid_name_use = SID_NAME_ALIAS;
458 DEBUG(5,("local_local_rid: looking up gid %u %s\n", (unsigned int)gid,
459 gr ? "succeeded" : "failed" ));
461 if(!gr) {
462 slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
463 return True;
466 fstrcpy( name, gr->gr_name);
468 DEBUG(5,("local_lookup_rid: found group %s for rid %u\n", name,
469 (unsigned int)rid ));
472 return True;
475 /*******************************************************************
476 Convert a name into a SID. Used in the lookup name rpc.
477 ********************************************************************/
479 BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use)
481 extern DOM_SID global_sid_World_Domain;
482 struct passwd *pass = NULL;
483 DOM_SID local_sid;
484 fstring user;
485 fstring domain;
488 * domain and user may be quoted const strings, and map_username and
489 * friends can modify them. Make a modifiable copy. JRA.
492 fstrcpy(domain, c_domain);
493 fstrcpy(user, c_user);
495 sid_copy(&local_sid, &global_sam_sid);
498 * Special case for MACHINE\Everyone. Map to the world_sid.
501 if(strequal(user, "Everyone")) {
502 sid_copy( psid, &global_sid_World_Domain);
503 sid_append_rid(psid, 0);
504 *psid_name_use = SID_NAME_ALIAS;
505 return True;
509 * Don't lookup local unix users if running in appliance mode
511 if (lp_hide_local_users())
512 return False;
514 (void)map_username(user);
516 if((pass = Get_Pwnam(user, True))) {
517 sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
518 *psid_name_use = SID_NAME_USER;
519 } else {
521 * Maybe it was a group ?
523 struct group *grp = getgrnam(user);
525 if(!grp)
526 return False;
528 sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
529 *psid_name_use = SID_NAME_ALIAS;
532 sid_copy( psid, &local_sid);
534 return True;
537 /****************************************************************************
538 Convert a uid to SID - locally.
539 ****************************************************************************/
541 DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
543 extern DOM_SID global_sam_sid;
545 sid_copy(psid, &global_sam_sid);
546 sid_append_rid(psid, pdb_uid_to_user_rid(uid));
548 return psid;
551 /****************************************************************************
552 Convert a SID to uid - locally.
553 ****************************************************************************/
555 BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
557 extern DOM_SID global_sam_sid;
559 DOM_SID dom_sid;
560 uint32 rid;
561 fstring str;
562 struct passwd *pass;
564 *name_type = SID_NAME_UNKNOWN;
566 sid_copy(&dom_sid, psid);
567 sid_split_rid(&dom_sid, &rid);
569 if (!pdb_rid_is_user(rid))
570 return False;
573 * We can only convert to a uid if this is our local
574 * Domain SID (ie. we are the controling authority).
576 if (!sid_equal(&global_sam_sid, &dom_sid))
577 return False;
579 *puid = pdb_user_rid_to_uid(rid);
582 * Ensure this uid really does exist.
584 if(!(pass = sys_getpwuid(*puid)))
585 return False;
587 DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid),
588 (unsigned int)*puid, pass->pw_name ));
590 return True;
593 /****************************************************************************
594 Convert a gid to SID - locally.
595 ****************************************************************************/
597 DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
599 extern DOM_SID global_sam_sid;
601 sid_copy(psid, &global_sam_sid);
602 sid_append_rid(psid, pdb_gid_to_group_rid(gid));
604 return psid;
607 /****************************************************************************
608 Convert a SID to gid - locally.
609 ****************************************************************************/
611 BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
613 extern DOM_SID global_sam_sid;
614 DOM_SID dom_sid;
615 uint32 rid;
616 fstring str;
617 struct group *grp;
619 *name_type = SID_NAME_UNKNOWN;
621 sid_copy(&dom_sid, psid);
622 sid_split_rid(&dom_sid, &rid);
625 * We can only convert to a gid if this is our local
626 * Domain SID (ie. we are the controling authority).
629 if (!sid_equal(&global_sam_sid, &dom_sid))
630 return False;
632 if (pdb_rid_is_user(rid))
633 return False;
635 *pgid = pdb_user_rid_to_gid(rid);
638 * Ensure this gid really does exist.
641 if(!(grp = getgrgid(*pgid)))
642 return False;
644 DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid),
645 (unsigned int)*pgid, grp->gr_name ));
647 return True;
650 static void select_name(pstring string, const UNISTR2 *from)
652 if (from->buffer != 0)
653 unistr2_to_ascii(string, from, sizeof(pstring));
656 /*************************************************************
657 Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
658 **************************************************************/
660 void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
663 if (from == NULL || to == NULL)
664 return;
666 to->logon_time = nt_time_to_unix(&from->logon_time);
667 to->logoff_time = nt_time_to_unix(&from->logoff_time);
668 to->kickoff_time = nt_time_to_unix(&from->kickoff_time);
669 to->pass_last_set_time = nt_time_to_unix(&from->pass_last_set_time);
670 to->pass_can_change_time = nt_time_to_unix(&from->pass_can_change_time);
671 to->pass_must_change_time = nt_time_to_unix(&from->pass_must_change_time);
673 select_name(to->username , &from->uni_user_name );
674 select_name(to->full_name , &from->uni_full_name );
675 select_name(to->home_dir , &from->uni_home_dir );
676 select_name(to->dir_drive , &from->uni_dir_drive );
677 select_name(to->logon_script, &from->uni_logon_script);
678 select_name(to->profile_path, &from->uni_profile_path);
679 select_name(to->acct_desc , &from->uni_acct_desc );
680 select_name(to->workstations, &from->uni_workstations);
681 select_name(to->unknown_str , &from->uni_unknown_str );
682 select_name(to->munged_dial , &from->uni_munged_dial );
684 to->user_rid = from->user_rid;
685 to->group_rid = from->group_rid;
687 to->acct_ctrl = from->acb_info;
688 to->unknown_3 = from->unknown_3;
690 to->logon_divs = from->logon_divs;
691 to->hours_len = from->logon_hrs.len;
692 memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN);
694 to->unknown_5 = from->unknown_5;
695 to->unknown_6 = from->unknown_6;
698 /*************************************************************
699 Copies a sam passwd.
700 **************************************************************/
702 void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
704 if (from == NULL || to == NULL)
705 return;
707 to->logon_time = nt_time_to_unix(&from->logon_time);
708 to->logoff_time = nt_time_to_unix(&from->logoff_time);
709 to->kickoff_time = nt_time_to_unix(&from->kickoff_time);
710 to->pass_last_set_time = nt_time_to_unix(&from->pass_last_set_time);
711 to->pass_can_change_time = nt_time_to_unix(&from->pass_can_change_time);
712 to->pass_must_change_time = nt_time_to_unix(&from->pass_must_change_time);
714 select_name(to->username , &from->uni_user_name );
715 select_name(to->full_name , &from->uni_full_name );
716 select_name(to->home_dir , &from->uni_home_dir );
717 select_name(to->dir_drive , &from->uni_dir_drive );
718 select_name(to->logon_script, &from->uni_logon_script);
719 select_name(to->profile_path, &from->uni_profile_path);
720 select_name(to->acct_desc , &from->uni_acct_desc );
721 select_name(to->workstations, &from->uni_workstations);
722 select_name(to->unknown_str , &from->uni_unknown_str );
723 select_name(to->munged_dial , &from->uni_munged_dial );
725 to->user_rid = from->user_rid;
726 to->group_rid = from->group_rid;
728 /* FIXME!! Do we need to copy the passwords here as well?
729 I don't know. Need to figure this out --jerry */
731 to->acct_ctrl = from->acb_info;
732 to->unknown_3 = from->unknown_3;
734 to->logon_divs = from->logon_divs;
735 to->hours_len = from->logon_hrs.len;
736 memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN);
738 to->unknown_5 = from->unknown_5;
739 to->unknown_6 = from->unknown_6;
742 /*************************************************************
743 Copies a SAM_ACCOUNT.
744 **************************************************************/
746 void copy_sam_passwd(SAM_ACCOUNT *to, const SAM_ACCOUNT *from)
748 if (!from || !to)
749 return;
751 memcpy(to, from, sizeof(SAM_ACCOUNT));
754 /*************************************************************
755 Change a password entry in the local smbpasswd file.
757 FIXME!! The function needs to be abstracted into the
758 passdb interface or something. It is currently being called
759 by _api_samr_create_user() in rpc_server/srv_samr.c
761 --jerry
762 *************************************************************/
764 BOOL local_password_change(char *user_name, int local_flags,
765 char *new_passwd,
766 char *err_str, size_t err_str_len,
767 char *msg_str, size_t msg_str_len)
769 struct passwd *pwd = NULL;
770 SAM_ACCOUNT *sam_pass=NULL;
771 SAM_ACCOUNT *new_sam_acct=NULL;
772 uchar new_p16[16];
773 uchar new_nt_p16[16];
775 *err_str = '\0';
776 *msg_str = '\0';
778 if (local_flags & LOCAL_ADD_USER) {
781 * Check for a local account - if we're adding only.
784 if(!(pwd = sys_getpwnam(user_name))) {
785 slprintf(err_str, err_str_len - 1, "User %s does not \
786 exist in system password file (usually /etc/passwd). Cannot add \
787 account without a valid local system user.\n", user_name);
788 return False;
792 /* Calculate the MD4 hash (NT compatible) of the new password. */
793 nt_lm_owf_gen(new_passwd, new_nt_p16, new_p16);
795 /* Get the smb passwd entry for this user */
796 pdb_init_sam(&sam_pass);
797 if(!pdb_getsampwnam(sam_pass, user_name)) {
798 pdb_free_sam(sam_pass);
800 if(!(local_flags & LOCAL_ADD_USER)) {
801 slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
802 return False;
805 /* create the SAM_ACCOUNT struct and call pdb_add_sam_account.
806 Because the new_sam_pwd only exists in the scope of this function
807 we will not allocate memory for members */
808 pdb_init_sam(&new_sam_acct);
809 pdb_set_username(new_sam_acct, user_name);
810 pdb_set_fullname(new_sam_acct, pwd->pw_gecos);
811 pdb_set_uid(new_sam_acct, pwd->pw_uid);
812 pdb_set_gid(new_sam_acct, pwd->pw_gid);
813 pdb_set_pass_last_set_time(new_sam_acct, time(NULL));
814 pdb_set_profile_path(new_sam_acct, lp_logon_path());
815 pdb_set_homedir(new_sam_acct, lp_logon_home());
816 pdb_set_dir_drive(new_sam_acct, lp_logon_drive());
817 pdb_set_logon_script(new_sam_acct, lp_logon_script());
819 /* set account flags */
820 pdb_set_acct_ctrl(new_sam_acct,((local_flags & LOCAL_TRUST_ACCOUNT) ? ACB_WSTRUST : ACB_NORMAL) );
822 if (local_flags & LOCAL_DISABLE_USER)
823 pdb_set_acct_ctrl (new_sam_acct, pdb_get_acct_ctrl(new_sam_acct)|ACB_DISABLED);
825 if (local_flags & LOCAL_SET_NO_PASSWORD)
826 pdb_set_acct_ctrl (new_sam_acct, pdb_get_acct_ctrl(new_sam_acct)|ACB_PWNOTREQ);
827 else {
828 /* set the passwords here. if we get to here it means
829 we have a valid, active account */
830 pdb_set_lanman_passwd (new_sam_acct, new_p16);
831 pdb_set_nt_passwd (new_sam_acct, new_nt_p16);
834 if (pdb_add_sam_account(new_sam_acct)) {
835 slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
836 pdb_free_sam(new_sam_acct);
837 return True;
838 } else {
839 slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
840 pdb_free_sam(new_sam_acct);
841 return False;
843 } else {
844 /* the entry already existed */
845 local_flags &= ~LOCAL_ADD_USER;
849 * We are root - just write the new password
850 * and the valid last change time.
853 if(local_flags & LOCAL_DISABLE_USER) {
854 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED);
855 } else if (local_flags & LOCAL_ENABLE_USER) {
856 if(pdb_get_lanman_passwd(sam_pass) == NULL) {
857 pdb_set_lanman_passwd (sam_pass, new_p16);
858 pdb_set_nt_passwd (sam_pass, new_nt_p16);
860 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED));
861 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
862 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ);
864 /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */
865 pdb_set_lanman_passwd (sam_pass, NULL);
866 pdb_set_nt_passwd (sam_pass, NULL);
867 } else {
869 * If we're dealing with setting a completely empty user account
870 * ie. One with a password of 'XXXX', but not set disabled (like
871 * an account created from scratch) then if the old password was
872 * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
873 * We remove that as we're giving this user their first password
874 * and the decision hasn't really been made to disable them (ie.
875 * don't create them disabled). JRA.
877 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED))
878 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED));
879 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ));
880 pdb_set_lanman_passwd (sam_pass, new_p16);
881 pdb_set_nt_passwd (sam_pass, new_nt_p16);
884 if(local_flags & LOCAL_DELETE_USER) {
885 if (!pdb_delete_sam_account(user_name)) {
886 slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
887 pdb_free_sam(sam_pass);
888 return False;
890 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
891 } else {
892 if(!pdb_update_sam_account(sam_pass, True)) {
893 slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
894 pdb_free_sam(sam_pass);
895 return False;
897 if(local_flags & LOCAL_DISABLE_USER)
898 slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
899 else if (local_flags & LOCAL_ENABLE_USER)
900 slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
901 else if (local_flags & LOCAL_SET_NO_PASSWORD)
902 slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
905 pdb_free_sam(sam_pass);
906 return True;
909 /*********************************************************************
910 Collection of get...() functions for SAM_ACCOUNT_INFO.
911 ********************************************************************/
913 uint16 pdb_get_acct_ctrl (SAM_ACCOUNT *sampass)
915 if (sampass)
916 return (sampass->acct_ctrl);
917 else
918 return (ACB_DISABLED);
921 time_t pdb_get_logon_time (SAM_ACCOUNT *sampass)
923 if (sampass)
924 return (sampass->logon_time);
925 else
926 return (0);
929 time_t pdb_get_logoff_time (SAM_ACCOUNT *sampass)
931 if (sampass)
932 return (sampass->logoff_time);
933 else
934 return (-1);
937 time_t pdb_get_kickoff_time (SAM_ACCOUNT *sampass)
939 if (sampass)
940 return (sampass->kickoff_time);
941 else
942 return (-1);
945 time_t pdb_get_pass_last_set_time (SAM_ACCOUNT *sampass)
947 if (sampass)
948 return (sampass->pass_last_set_time);
949 else
950 return (-1);
953 time_t pdb_get_pass_can_change_time (SAM_ACCOUNT *sampass)
955 if (sampass)
956 return (sampass->pass_can_change_time);
957 else
958 return (-1);
961 time_t pdb_get_pass_must_change_time (SAM_ACCOUNT *sampass)
963 if (sampass)
964 return (sampass->pass_must_change_time);
965 else
966 return (-1);
969 uint16 pdb_get_logon_divs (SAM_ACCOUNT *sampass)
971 if (sampass)
972 return (sampass->logon_divs);
973 else
974 return (-1);
977 uint32 pdb_get_hours_len (SAM_ACCOUNT *sampass)
979 if (sampass)
980 return (sampass->hours_len);
981 else
982 return (-1);
985 uint8* pdb_get_hours (SAM_ACCOUNT *sampass)
987 if (sampass)
988 return (sampass->hours);
989 else
990 return (NULL);
993 uint8* pdb_get_nt_passwd (SAM_ACCOUNT *sampass)
995 if (sampass)
996 return (sampass->nt_pw);
997 else
998 return (NULL);
1001 uint8* pdb_get_lanman_passwd (SAM_ACCOUNT *sampass)
1003 if (sampass)
1004 return (sampass->lm_pw);
1005 else
1006 return (NULL);
1009 uint32 pdb_get_user_rid (SAM_ACCOUNT *sampass)
1011 if (sampass)
1012 return (sampass->user_rid);
1013 else
1014 return (-1);
1017 uint32 pdb_get_group_rid (SAM_ACCOUNT *sampass)
1019 if (sampass)
1020 return (sampass->group_rid);
1021 else
1022 return (-1);
1025 uid_t pdb_get_uid (SAM_ACCOUNT *sampass)
1027 if (sampass)
1028 return (sampass->uid);
1029 else
1030 return ((uid_t)-1);
1033 gid_t pdb_get_gid (SAM_ACCOUNT *sampass)
1035 if (sampass)
1036 return (sampass->gid);
1037 else
1038 return ((gid_t)-1);
1041 char* pdb_get_username (SAM_ACCOUNT *sampass)
1043 if (sampass)
1044 return (sampass->username);
1045 else
1046 return (NULL);
1049 char* pdb_get_domain (SAM_ACCOUNT *sampass)
1051 if (sampass)
1052 return (sampass->domain);
1053 else
1054 return (NULL);
1057 char* pdb_get_nt_username (SAM_ACCOUNT *sampass)
1059 if (sampass)
1060 return (sampass->nt_username);
1061 else
1062 return (NULL);
1065 char* pdb_get_fullname (SAM_ACCOUNT *sampass)
1067 if (sampass)
1068 return (sampass->full_name);
1069 else
1070 return (NULL);
1073 char* pdb_get_homedir (SAM_ACCOUNT *sampass)
1075 if (sampass)
1076 return (sampass->home_dir);
1077 else
1078 return (NULL);
1081 char* pdb_get_dirdrive (SAM_ACCOUNT *sampass)
1083 if (sampass)
1084 return (sampass->dir_drive);
1085 else
1086 return (NULL);
1089 char* pdb_get_logon_script (SAM_ACCOUNT *sampass)
1091 if (sampass)
1092 return (sampass->logon_script);
1093 else
1094 return (NULL);
1097 char* pdb_get_profile_path (SAM_ACCOUNT *sampass)
1099 if (sampass)
1100 return (sampass->profile_path);
1101 else
1102 return (NULL);
1105 char* pdb_get_acct_desc (SAM_ACCOUNT *sampass)
1107 if (sampass)
1108 return (sampass->acct_desc);
1109 else
1110 return (NULL);
1113 char* pdb_get_workstations (SAM_ACCOUNT *sampass)
1115 if (sampass)
1116 return (sampass->workstations);
1117 else
1118 return (NULL);
1121 char* pdb_get_munged_dial (SAM_ACCOUNT *sampass)
1123 if (sampass)
1124 return (sampass->munged_dial);
1125 else
1126 return (NULL);
1129 uint32 pdb_get_unknown3 (SAM_ACCOUNT *sampass)
1131 if (sampass)
1132 return (sampass->unknown_3);
1133 else
1134 return (-1);
1137 uint32 pdb_get_unknown5 (SAM_ACCOUNT *sampass)
1139 if (sampass)
1140 return (sampass->unknown_5);
1141 else
1142 return (-1);
1145 uint32 pdb_get_unknown6 (SAM_ACCOUNT *sampass)
1147 if (sampass)
1148 return (sampass->unknown_6);
1149 else
1150 return (-1);
1153 /*********************************************************************
1154 Collection of set...() functions for SAM_ACCOUNT_INFO.
1155 ********************************************************************/
1157 BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 flags)
1159 if (!sampass)
1160 return False;
1162 if (sampass) {
1163 sampass->acct_ctrl = flags;
1164 return True;
1167 return False;
1170 BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime)
1172 if (!sampass)
1173 return False;
1175 sampass->logon_time = mytime;
1176 return True;
1179 BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime)
1181 if (!sampass)
1182 return False;
1184 sampass->logoff_time = mytime;
1185 return True;
1188 BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime)
1190 if (!sampass)
1191 return False;
1193 sampass->kickoff_time = mytime;
1194 return True;
1197 BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime)
1199 if (!sampass)
1200 return False;
1202 sampass->pass_can_change_time = mytime;
1203 return True;
1206 BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime)
1208 if (!sampass)
1209 return False;
1211 sampass->pass_must_change_time = mytime;
1212 return True;
1215 BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime)
1217 if (!sampass)
1218 return False;
1220 sampass->pass_last_set_time = mytime;
1221 return True;
1224 BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len)
1226 if (!sampass)
1227 return False;
1229 sampass->hours_len = len;
1230 return True;
1233 BOOL pdb_set_logons_divs (SAM_ACCOUNT *sampass, uint16 hours)
1235 if (!sampass)
1236 return False;
1238 sampass->logon_divs = hours;
1239 return True;
1242 BOOL pdb_set_uid (SAM_ACCOUNT *sampass, uid_t uid)
1244 if (!sampass)
1245 return False;
1247 sampass->uid = uid;
1248 return True;
1251 BOOL pdb_set_gid (SAM_ACCOUNT *sampass, gid_t gid)
1253 if (!sampass)
1254 return False;
1256 sampass->gid = gid;
1257 return True;
1260 BOOL pdb_set_user_rid (SAM_ACCOUNT *sampass, uint32 rid)
1262 if (!sampass)
1263 return False;
1265 sampass->user_rid = rid;
1266 return True;
1269 BOOL pdb_set_group_rid (SAM_ACCOUNT *sampass, uint32 grid)
1271 if (!sampass)
1272 return False;
1274 sampass->group_rid = grid;
1275 return True;
1278 /*********************************************************************
1279 Set the user's UNIX name.
1280 ********************************************************************/
1282 BOOL pdb_set_username(SAM_ACCOUNT *sampass, char *username)
1284 if (!sampass)
1285 return False;
1286 *sampass->username = '\0';
1287 if (!username)
1288 return False;
1290 StrnCpy (sampass->username, username, strlen(username));
1292 return True;
1295 /*********************************************************************
1296 Set the domain name.
1297 ********************************************************************/
1299 BOOL pdb_set_domain(SAM_ACCOUNT *sampass, char *domain)
1301 if (!sampass)
1302 return False;
1303 *sampass->domain = '\0';
1304 if (!domain)
1305 return False;
1307 StrnCpy (sampass->domain, domain, strlen(domain));
1309 return True;
1312 /*********************************************************************
1313 Set the user's NT name.
1314 ********************************************************************/
1316 BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, char *nt_username)
1318 if (!sampass)
1319 return False;
1320 *sampass->nt_username = '\0';
1321 if (!nt_username)
1322 return False;
1324 StrnCpy (sampass->nt_username, nt_username, strlen(nt_username));
1326 return True;
1329 /*********************************************************************
1330 Set the user's full name.
1331 ********************************************************************/
1333 BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, char *fullname)
1335 if (!sampass)
1336 return False;
1337 *sampass->full_name = '\0';
1338 if (!fullname)
1339 return False;
1341 StrnCpy (sampass->full_name, fullname, strlen(fullname));
1343 return True;
1346 /*********************************************************************
1347 Set the user's logon script.
1348 ********************************************************************/
1350 BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, char *logon_script)
1352 if (!sampass)
1353 return False;
1354 *sampass->logon_script = '\0';
1355 if (!logon_script)
1356 return False;
1358 StrnCpy (sampass->logon_script, logon_script, strlen(logon_script));
1360 return True;
1363 /*********************************************************************
1364 Set the user's profile path.
1365 ********************************************************************/
1367 BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, char *profile_path)
1369 if (!sampass)
1370 return False;
1371 *sampass->profile_path = '\0';
1372 if (!profile_path)
1373 return False;
1375 StrnCpy (sampass->profile_path, profile_path, strlen(profile_path));
1377 return True;
1380 /*********************************************************************
1381 Set the user's directory drive.
1382 ********************************************************************/
1384 BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, char *dir_drive)
1386 if (!sampass)
1387 return False;
1388 *sampass->dir_drive = '\0';
1389 if (!dir_drive)
1390 return False;
1392 StrnCpy (sampass->dir_drive, dir_drive, strlen(dir_drive));
1394 return True;
1397 /*********************************************************************
1398 Set the user's home directory.
1399 ********************************************************************/
1401 BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, char *homedir)
1403 if (!sampass)
1404 return False;
1405 *sampass->home_dir = '\0';
1406 if (!homedir)
1407 return False;
1409 StrnCpy (sampass->home_dir, homedir, strlen(homedir));
1411 return True;
1414 /*********************************************************************
1415 Set the user's account description.
1416 ********************************************************************/
1418 BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, char *acct_desc)
1420 if (!sampass)
1421 return False;
1422 *sampass->acct_desc = '\0';
1423 if (!acct_desc)
1424 return False;
1426 StrnCpy (sampass->acct_desc, acct_desc, strlen(acct_desc));
1428 return True;
1431 /*********************************************************************
1432 Set the user's workstation allowed list.
1433 ********************************************************************/
1435 BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, char *workstations)
1437 if (!sampass)
1438 return False;
1439 *sampass->workstations = '\0';
1440 if (!workstations)
1441 return False;
1443 StrnCpy (sampass->workstations, workstations, strlen(workstations));
1445 return True;
1448 /*********************************************************************
1449 Set the user's dial string.
1450 ********************************************************************/
1452 BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, char *munged_dial)
1454 if (!sampass)
1455 return False;
1456 *sampass->munged_dial = '\0';
1457 if (!munged_dial)
1458 return False;
1460 StrnCpy (sampass->munged_dial, munged_dial, strlen(munged_dial));
1462 return True;
1465 /*********************************************************************
1466 Set the user's NT hash.
1467 ********************************************************************/
1469 BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, uint8 *pwd)
1471 if (!sampass || !pwd)
1472 return False;
1474 if (sampass->nt_pw!=NULL)
1475 DEBUG(4,("pdb_set_nt_passwd: NT hash non NULL overwritting ?\n"));
1476 else
1477 sampass->nt_pw=(unsigned char *)malloc(sizeof(unsigned char)*16);
1479 if (sampass->nt_pw==NULL)
1480 return False;
1482 memcpy (sampass->nt_pw, pwd, 16);
1484 return True;
1487 /*********************************************************************
1488 Set the user's LM hash.
1489 ********************************************************************/
1491 BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, uint8 *pwd)
1493 if (!sampass || !pwd)
1494 return False;
1496 if (sampass->lm_pw!=NULL)
1497 DEBUG(4,("pdb_set_lanman_passwd: LM hash non NULL overwritting ?\n"));
1498 else
1499 sampass->lm_pw=(unsigned char *)malloc(sizeof(unsigned char)*16);
1501 if (sampass->lm_pw==NULL)
1502 return False;
1504 memcpy (sampass->lm_pw, pwd, 16);
1506 return True;
1509 BOOL pdb_set_unknown_3 (SAM_ACCOUNT *sampass, uint32 unkn)
1511 if (!sampass)
1512 return False;
1514 sampass->unknown_3 = unkn;
1515 return True;
1518 BOOL pdb_set_unknown_5 (SAM_ACCOUNT *sampass, uint32 unkn)
1520 if (!sampass)
1521 return False;
1523 sampass->unknown_5 = unkn;
1524 return True;
1527 BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn)
1529 if (!sampass)
1530 return False;
1532 sampass->unknown_6 = unkn;
1533 return True;
1536 BOOL pdb_set_hours (SAM_ACCOUNT *sampass, uint8 *hours)
1538 if (!sampass)
1539 return False;
1541 if (!hours) {
1542 memset ((char *)sampass->hours, 0, MAX_HOURS_LEN);
1543 return True;
1546 memcpy (sampass->hours, hours, MAX_HOURS_LEN);
1548 return True;