c526a175f20f3f03558ce27755bd1c4f6eac4fcb
[tprouty/samba.git] / source3 / passdb / passdb.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Jeremy Allison                 1996-2001
5    Copyright (C) Luke Kenneth Casson Leighton   1996-1998
6    Copyright (C) Gerald (Jerry) Carter          2000-2006
7    Copyright (C) Andrew Bartlett                2001-2002
8    Copyright (C) Simo Sorce                     2003
9    Copyright (C) Volker Lendecke                2006
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
29
30 /**********************************************************************
31 ***********************************************************************/
32
33 static int samu_destroy(struct samu *user) 
34 {
35         data_blob_clear_free( &user->lm_pw );
36         data_blob_clear_free( &user->nt_pw );
37
38         if ( user->plaintext_pw )
39                 memset( user->plaintext_pw, 0x0, strlen(user->plaintext_pw) );
40
41         return 0;
42 }
43
44 /**********************************************************************
45  generate a new struct samuser
46 ***********************************************************************/
47
48 struct samu *samu_new( TALLOC_CTX *ctx )
49 {
50         struct samu *user;
51
52         if ( !(user = TALLOC_ZERO_P( ctx, struct samu )) ) {
53                 DEBUG(0,("samuser_new: Talloc failed!\n"));
54                 return NULL;
55         }
56
57         talloc_set_destructor( user, samu_destroy );
58
59         /* no initial methods */
60
61         user->methods = NULL;
62
63         /* Don't change these timestamp settings without a good reason.
64            They are important for NT member server compatibility. */
65
66         user->logon_time            = (time_t)0;
67         user->pass_last_set_time    = (time_t)0;
68         user->pass_can_change_time  = (time_t)0;
69         user->logoff_time           = get_time_t_max();
70         user->kickoff_time          = get_time_t_max();
71         user->pass_must_change_time = get_time_t_max();
72         user->fields_present        = 0x00ffffff;
73         user->logon_divs = 168;         /* hours per week */
74         user->hours_len = 21;           /* 21 times 8 bits = 168 */
75         memset(user->hours, 0xff, user->hours_len); /* available at all hours */
76         user->bad_password_count = 0;
77         user->logon_count = 0;
78         user->unknown_6 = 0x000004ec; /* don't know */
79
80         /* Some parts of samba strlen their pdb_get...() returns, 
81            so this keeps the interface unchanged for now. */
82
83         user->username = "";
84         user->domain = "";
85         user->nt_username = "";
86         user->full_name = "";
87         user->home_dir = "";
88         user->logon_script = "";
89         user->profile_path = "";
90         user->acct_desc = "";
91         user->workstations = "";
92         user->comment = "";
93         user->munged_dial = "";
94
95         user->plaintext_pw = NULL;
96
97         /* Unless we know otherwise have a Account Control Bit
98            value of 'normal user'.  This helps User Manager, which
99            asks for a filtered list of users. */
100
101         user->acct_ctrl = ACB_NORMAL;
102
103         return user;
104 }
105
106 /*********************************************************************
107  Initialize a struct samu from a struct passwd including the user 
108  and group SIDs.  The *user structure is filled out with the Unix
109  attributes and a user SID.
110 *********************************************************************/
111
112 static NTSTATUS samu_set_unix_internal(struct samu *user, const struct passwd *pwd, bool create)
113 {
114         const char *guest_account = lp_guestaccount();
115         const char *domain = global_myname();
116         uint32 urid;
117
118         if ( !pwd ) {
119                 return NT_STATUS_NO_SUCH_USER;
120         }
121
122         /* Basic properties based upon the Unix account information */
123
124         pdb_set_username(user, pwd->pw_name, PDB_SET);
125         pdb_set_fullname(user, pwd->pw_gecos, PDB_SET);
126         pdb_set_domain (user, get_global_sam_name(), PDB_DEFAULT);
127 #if 0
128         /* This can lead to a primary group of S-1-22-2-XX which 
129            will be rejected by other parts of the Samba code. 
130            Rely on pdb_get_group_sid() to "Do The Right Thing" (TM)  
131            --jerry */
132
133         gid_to_sid(&group_sid, pwd->pw_gid);
134         pdb_set_group_sid(user, &group_sid, PDB_SET);
135 #endif
136
137         /* save the password structure for later use */
138
139         user->unix_pw = tcopy_passwd( user, pwd );
140
141         /* Special case for the guest account which must have a RID of 501 */
142
143         if ( strequal( pwd->pw_name, guest_account ) ) {
144                 if ( !pdb_set_user_sid_from_rid(user, DOMAIN_USER_RID_GUEST, PDB_DEFAULT)) {
145                         return NT_STATUS_NO_SUCH_USER;
146                 }
147                 return NT_STATUS_OK;
148         }
149
150         /* Non-guest accounts...Check for a workstation or user account */
151
152         if (pwd->pw_name[strlen(pwd->pw_name)-1] == '$') {
153                 /* workstation */
154
155                 if (!pdb_set_acct_ctrl(user, ACB_WSTRUST, PDB_DEFAULT)) {
156                         DEBUG(1, ("Failed to set 'workstation account' flags for user %s.\n", 
157                                 pwd->pw_name));
158                         return NT_STATUS_INVALID_COMPUTER_NAME;
159                 }       
160         } 
161         else {
162                 /* user */
163
164                 if (!pdb_set_acct_ctrl(user, ACB_NORMAL, PDB_DEFAULT)) {
165                         DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n", 
166                                 pwd->pw_name));
167                         return NT_STATUS_INVALID_ACCOUNT_NAME;
168                 }
169
170                 /* set some basic attributes */
171
172                 pdb_set_profile_path(user, talloc_sub_specified(user, 
173                         lp_logon_path(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), 
174                         PDB_DEFAULT);           
175                 pdb_set_homedir(user, talloc_sub_specified(user, 
176                         lp_logon_home(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
177                         PDB_DEFAULT);
178                 pdb_set_dir_drive(user, talloc_sub_specified(user, 
179                         lp_logon_drive(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid),
180                         PDB_DEFAULT);
181                 pdb_set_logon_script(user, talloc_sub_specified(user, 
182                         lp_logon_script(), pwd->pw_name, domain, pwd->pw_uid, pwd->pw_gid), 
183                         PDB_DEFAULT);
184         }
185
186         /* Now deal with the user SID.  If we have a backend that can generate 
187            RIDs, then do so.  But sometimes the caller just wanted a structure 
188            initialized and will fill in these fields later (such as from a 
189            netr_SamInfo3 structure) */
190
191         if ( create && !pdb_rid_algorithm() ) {
192                 uint32 user_rid;
193                 DOM_SID user_sid;
194
195                 if ( !pdb_new_rid( &user_rid ) ) {
196                         DEBUG(3, ("Could not allocate a new RID\n"));
197                         return NT_STATUS_ACCESS_DENIED;
198                 }
199
200                 sid_copy( &user_sid, get_global_sam_sid() );
201                 sid_append_rid( &user_sid, user_rid );
202
203                 if ( !pdb_set_user_sid(user, &user_sid, PDB_SET) ) {
204                         DEBUG(3, ("pdb_set_user_sid failed\n"));
205                         return NT_STATUS_INTERNAL_ERROR;
206                 }
207
208                 return NT_STATUS_OK;
209         }
210
211         /* generate a SID for the user with the RID algorithm */
212
213         urid = algorithmic_pdb_uid_to_user_rid( user->unix_pw->pw_uid );
214
215         if ( !pdb_set_user_sid_from_rid( user, urid, PDB_SET) ) {
216                 return NT_STATUS_INTERNAL_ERROR;
217         }
218
219         return NT_STATUS_OK;
220 }
221
222 /********************************************************************
223  Set the Unix user attributes
224 ********************************************************************/
225
226 NTSTATUS samu_set_unix(struct samu *user, const struct passwd *pwd)
227 {
228         return samu_set_unix_internal( user, pwd, False );
229 }
230
231 NTSTATUS samu_alloc_rid_unix(struct samu *user, const struct passwd *pwd)
232 {
233         return samu_set_unix_internal( user, pwd, True );
234 }
235
236 /**********************************************************
237  Encode the account control bits into a string.
238  length = length of string to encode into (including terminating
239  null). length *MUST BE MORE THAN 2* !
240  **********************************************************/
241
242 char *pdb_encode_acct_ctrl(uint32_t acct_ctrl, size_t length)
243 {
244         fstring acct_str;
245         char *result;
246
247         size_t i = 0;
248
249         SMB_ASSERT(length <= sizeof(acct_str));
250
251         acct_str[i++] = '[';
252
253         if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
254         if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
255         if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
256         if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
257         if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
258         if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
259         if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
260         if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
261         if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
262         if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
263         if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
264
265         for ( ; i < length - 2 ; i++ )
266                 acct_str[i] = ' ';
267
268         i = length - 2;
269         acct_str[i++] = ']';
270         acct_str[i++] = '\0';
271
272         result = talloc_strdup(talloc_tos(), acct_str);
273         SMB_ASSERT(result != NULL);
274         return result;
275 }     
276
277 /**********************************************************
278  Decode the account control bits from a string.
279  **********************************************************/
280
281 uint32_t pdb_decode_acct_ctrl(const char *p)
282 {
283         uint32_t acct_ctrl = 0;
284         bool finished = false;
285
286         /*
287          * Check if the account type bits have been encoded after the
288          * NT password (in the form [NDHTUWSLXI]).
289          */
290
291         if (*p != '[')
292                 return 0;
293
294         for (p++; *p && !finished; p++) {
295                 switch (*p) {
296                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
297                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
298                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
299                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
300                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
301                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
302                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
303                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
304                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
305                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
306                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
307             case ' ': { break; }
308                         case ':':
309                         case '\n':
310                         case '\0': 
311                         case ']':
312                         default:  { finished = true; }
313                 }
314         }
315
316         return acct_ctrl;
317 }
318
319 /*************************************************************
320  Routine to set 32 hex password characters from a 16 byte array.
321 **************************************************************/
322
323 void pdb_sethexpwd(char p[33], const unsigned char *pwd, uint32 acct_ctrl)
324 {
325         if (pwd != NULL) {
326                 int i;
327                 for (i = 0; i < 16; i++)
328                         slprintf(&p[i*2], 3, "%02X", pwd[i]);
329         } else {
330                 if (acct_ctrl & ACB_PWNOTREQ)
331                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 32);
332                 else
333                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 32);
334         }
335 }
336
337 /*************************************************************
338  Routine to get the 32 hex characters and turn them
339  into a 16 byte array.
340 **************************************************************/
341
342 bool pdb_gethexpwd(const char *p, unsigned char *pwd)
343 {
344         int i;
345         unsigned char   lonybble, hinybble;
346         const char      *hexchars = "0123456789ABCDEF";
347         char           *p1, *p2;
348
349         if (!p)
350                 return false;
351
352         for (i = 0; i < 32; i += 2) {
353                 hinybble = toupper_ascii(p[i]);
354                 lonybble = toupper_ascii(p[i + 1]);
355
356                 p1 = strchr(hexchars, hinybble);
357                 p2 = strchr(hexchars, lonybble);
358
359                 if (!p1 || !p2)
360                         return false;
361
362                 hinybble = PTR_DIFF(p1, hexchars);
363                 lonybble = PTR_DIFF(p2, hexchars);
364
365                 pwd[i / 2] = (hinybble << 4) | lonybble;
366         }
367         return true;
368 }
369
370 /*************************************************************
371  Routine to set 42 hex hours characters from a 21 byte array.
372 **************************************************************/
373
374 void pdb_sethexhours(char *p, const unsigned char *hours)
375 {
376         if (hours != NULL) {
377                 int i;
378                 for (i = 0; i < 21; i++) {
379                         slprintf(&p[i*2], 3, "%02X", hours[i]);
380                 }
381         } else {
382                 safe_strcpy(p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 43);
383         }
384 }
385
386 /*************************************************************
387  Routine to get the 42 hex characters and turn them
388  into a 21 byte array.
389 **************************************************************/
390
391 bool pdb_gethexhours(const char *p, unsigned char *hours)
392 {
393         int i;
394         unsigned char   lonybble, hinybble;
395         const char      *hexchars = "0123456789ABCDEF";
396         char           *p1, *p2;
397
398         if (!p) {
399                 return (False);
400         }
401
402         for (i = 0; i < 42; i += 2) {
403                 hinybble = toupper_ascii(p[i]);
404                 lonybble = toupper_ascii(p[i + 1]);
405
406                 p1 = strchr(hexchars, hinybble);
407                 p2 = strchr(hexchars, lonybble);
408
409                 if (!p1 || !p2) {
410                         return (False);
411                 }
412
413                 hinybble = PTR_DIFF(p1, hexchars);
414                 lonybble = PTR_DIFF(p2, hexchars);
415
416                 hours[i / 2] = (hinybble << 4) | lonybble;
417         }
418         return (True);
419 }
420
421 /********************************************************************
422 ********************************************************************/
423
424 int algorithmic_rid_base(void)
425 {
426         int rid_offset;
427
428         rid_offset = lp_algorithmic_rid_base();
429
430         if (rid_offset < BASE_RID) {  
431                 /* Try to prevent admin foot-shooting, we can't put algorithmic
432                    rids below 1000, that's the 'well known RIDs' on NT */
433                 DEBUG(0, ("'algorithmic rid base' must be equal to or above %ld\n", BASE_RID));
434                 rid_offset = BASE_RID;
435         }
436         if (rid_offset & 1) {
437                 DEBUG(0, ("algorithmic rid base must be even\n"));
438                 rid_offset += 1;
439         }
440         return rid_offset;
441 }
442
443 /*******************************************************************
444  Converts NT user RID to a UNIX uid.
445  ********************************************************************/
446
447 uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
448 {
449         int rid_offset = algorithmic_rid_base();
450         return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
451 }
452
453 uid_t max_algorithmic_uid(void)
454 {
455         return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
456 }
457
458 /*******************************************************************
459  converts UNIX uid to an NT User RID.
460  ********************************************************************/
461
462 uint32 algorithmic_pdb_uid_to_user_rid(uid_t uid)
463 {
464         int rid_offset = algorithmic_rid_base();
465         return (((((uint32)uid)*RID_MULTIPLIER) + rid_offset) | USER_RID_TYPE);
466 }
467
468 /*******************************************************************
469  Converts NT group RID to a UNIX gid.
470  ********************************************************************/
471
472 gid_t pdb_group_rid_to_gid(uint32 group_rid)
473 {
474         int rid_offset = algorithmic_rid_base();
475         return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
476 }
477
478 gid_t max_algorithmic_gid(void)
479 {
480         return pdb_group_rid_to_gid(0xffffffff);
481 }
482
483 /*******************************************************************
484  converts NT Group RID to a UNIX uid.
485  
486  warning: you must not call that function only
487  you must do a call to the group mapping first.
488  there is not anymore a direct link between the gid and the rid.
489  ********************************************************************/
490
491 uint32 algorithmic_pdb_gid_to_group_rid(gid_t gid)
492 {
493         int rid_offset = algorithmic_rid_base();
494         return (((((uint32)gid)*RID_MULTIPLIER) + rid_offset) | GROUP_RID_TYPE);
495 }
496
497 /*******************************************************************
498  Decides if a RID is a well known RID.
499  ********************************************************************/
500
501 static bool rid_is_well_known(uint32 rid)
502 {
503         /* Not using rid_offset here, because this is the actual
504            NT fixed value (1000) */
505
506         return (rid < BASE_RID);
507 }
508
509 /*******************************************************************
510  Decides if a RID is a user or group RID.
511  ********************************************************************/
512
513 bool algorithmic_pdb_rid_is_user(uint32 rid)
514 {
515         if ( rid_is_well_known(rid) ) {
516                 /*
517                  * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
518                  * and DOMAIN_USER_RID_GUEST.
519                  */
520                 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
521                         return True;
522         } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
523                 return True;
524         }
525         return False;
526 }
527
528 /*******************************************************************
529  Convert a name into a SID. Used in the lookup name rpc.
530  ********************************************************************/
531
532 bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
533                             enum lsa_SidType *type)
534 {
535         GROUP_MAP map;
536         bool ret;
537
538         /* Windows treats "MACHINE\None" as a special name for 
539            rid 513 on non-DCs.  You cannot create a user or group
540            name "None" on Windows.  You will get an error that 
541            the group already exists. */
542
543         if ( strequal( name, "None" ) ) {
544                 *rid = DOMAIN_GROUP_RID_USERS;
545                 *type = SID_NAME_DOM_GRP;
546
547                 return True;
548         }
549
550         /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
551          * correctly in the case where foo also exists as a user. If the flag
552          * is set, don't look for users at all. */
553
554         if ((flags & LOOKUP_NAME_GROUP) == 0) {
555                 struct samu *sam_account = NULL;
556                 DOM_SID user_sid;
557
558                 if ( !(sam_account = samu_new( NULL )) ) {
559                         return False;
560                 }
561
562                 become_root();
563                 ret =  pdb_getsampwnam(sam_account, name);
564                 unbecome_root();
565
566                 if (ret) {
567                         sid_copy(&user_sid, pdb_get_user_sid(sam_account));
568                 }
569
570                 TALLOC_FREE(sam_account);
571
572                 if (ret) {
573                         if (!sid_check_is_in_our_domain(&user_sid)) {
574                                 DEBUG(0, ("User %s with invalid SID %s in passdb\n",
575                                           name, sid_string_dbg(&user_sid)));
576                                 return False;
577                         }
578
579                         sid_peek_rid(&user_sid, rid);
580                         *type = SID_NAME_USER;
581                         return True;
582                 }
583         }
584
585         /*
586          * Maybe it is a group ?
587          */
588
589         become_root();
590         ret = pdb_getgrnam(&map, name);
591         unbecome_root();
592
593         if (!ret) {
594                 return False;
595         }
596
597         /* BUILTIN groups are looked up elsewhere */
598         if (!sid_check_is_in_our_domain(&map.sid)) {
599                 DEBUG(10, ("Found group %s (%s) not in our domain -- "
600                            "ignoring.", name, sid_string_dbg(&map.sid)));
601                 return False;
602         }
603
604         /* yes it's a mapped group */
605         sid_peek_rid(&map.sid, rid);
606         *type = map.sid_name_use;
607         return True;
608 }
609
610 /*************************************************************
611  Change a password entry in the local smbpasswd file.
612  *************************************************************/
613
614 NTSTATUS local_password_change(const char *user_name,
615                                 int local_flags,
616                                 const char *new_passwd, 
617                                 char **pp_err_str,
618                                 char **pp_msg_str)
619 {
620         struct samu *sam_pass=NULL;
621         uint32 other_acb;
622         NTSTATUS result;
623
624         *pp_err_str = NULL;
625         *pp_msg_str = NULL;
626
627         /* Get the smb passwd entry for this user */
628
629         if ( !(sam_pass = samu_new( NULL )) ) {
630                 return NT_STATUS_NO_MEMORY;
631         }
632
633         become_root();
634         if(!pdb_getsampwnam(sam_pass, user_name)) {
635                 unbecome_root();
636                 TALLOC_FREE(sam_pass);
637
638                 if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
639                         int tmp_debug = DEBUGLEVEL;
640                         struct passwd *pwd;
641
642                         /* Might not exist in /etc/passwd. */
643
644                         if (tmp_debug < 1) {
645                                 DEBUGLEVEL = 1;
646                         }
647
648                         if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), user_name)) ) {
649                                 return NT_STATUS_NO_SUCH_USER;
650                         }
651
652                         /* create the struct samu and initialize the basic Unix properties */
653
654                         if ( !(sam_pass = samu_new( NULL )) ) {
655                                 return NT_STATUS_NO_MEMORY;
656                         }
657
658                         result = samu_set_unix( sam_pass, pwd );
659
660                         DEBUGLEVEL = tmp_debug;
661
662                         TALLOC_FREE( pwd );
663
664                         if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
665                                 return result;
666                         }
667
668                         if (!NT_STATUS_IS_OK(result)) {
669                                 if (asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n",
670                                                 user_name, nt_errstr(result)) < 0) {
671                                         *pp_err_str = NULL;
672                                 }
673                                 return result;
674                         }
675                 } else {
676                         if (asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name) < 0) {
677                                 *pp_err_str = NULL;
678                         }
679                         return NT_STATUS_NO_SUCH_USER;
680                 }
681         } else {
682                 unbecome_root();
683                 /* the entry already existed */
684                 local_flags &= ~LOCAL_ADD_USER;
685         }
686
687         /* the 'other' acb bits not being changed here */
688         other_acb =  (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
689         if (local_flags & LOCAL_TRUST_ACCOUNT) {
690                 if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
691                         if (asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name) < 0) {
692                                 *pp_err_str = NULL;
693                         }
694                         TALLOC_FREE(sam_pass);
695                         return NT_STATUS_UNSUCCESSFUL;
696                 }
697         } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
698                 if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
699                         if (asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name) < 0) {
700                                 *pp_err_str = NULL;
701                         }
702                         TALLOC_FREE(sam_pass);
703                         return NT_STATUS_UNSUCCESSFUL;
704                 }
705         } else {
706                 if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
707                         if (asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name) < 0) {
708                                 *pp_err_str = NULL;
709                         }
710                         TALLOC_FREE(sam_pass);
711                         return NT_STATUS_UNSUCCESSFUL;
712                 }
713         }
714
715         /*
716          * We are root - just write the new password
717          * and the valid last change time.
718          */
719
720         if (local_flags & LOCAL_DISABLE_USER) {
721                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
722                         if (asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name) < 0) {
723                                 *pp_err_str = NULL;
724                         }
725                         TALLOC_FREE(sam_pass);
726                         return NT_STATUS_UNSUCCESSFUL;
727                 }
728         } else if (local_flags & LOCAL_ENABLE_USER) {
729                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
730                         if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
731                                 *pp_err_str = NULL;
732                         }
733                         TALLOC_FREE(sam_pass);
734                         return NT_STATUS_UNSUCCESSFUL;
735                 }
736         }
737
738         if (local_flags & LOCAL_SET_NO_PASSWORD) {
739                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
740                         if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) {
741                                 *pp_err_str = NULL;
742                         }
743                         TALLOC_FREE(sam_pass);
744                         return NT_STATUS_UNSUCCESSFUL;
745                 }
746         } else if (local_flags & LOCAL_SET_PASSWORD) {
747                 /*
748                  * If we're dealing with setting a completely empty user account
749                  * ie. One with a password of 'XXXX', but not set disabled (like
750                  * an account created from scratch) then if the old password was
751                  * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
752                  * We remove that as we're giving this user their first password
753                  * and the decision hasn't really been made to disable them (ie.
754                  * don't create them disabled). JRA.
755                  */
756                 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
757                         if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
758                                 if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
759                                         *pp_err_str = NULL;
760                                 }
761                                 TALLOC_FREE(sam_pass);
762                                 return NT_STATUS_UNSUCCESSFUL;
763                         }
764                 }
765                 if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
766                         if (asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name) < 0) {
767                                 *pp_err_str = NULL;
768                         }
769                         TALLOC_FREE(sam_pass);
770                         return NT_STATUS_UNSUCCESSFUL;
771                 }
772
773                 if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
774                         if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) {
775                                 *pp_err_str = NULL;
776                         }
777                         TALLOC_FREE(sam_pass);
778                         return NT_STATUS_UNSUCCESSFUL;
779                 }
780         }       
781
782         if (local_flags & LOCAL_ADD_USER) {
783                 if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
784                         if (asprintf(pp_msg_str, "Added user %s.\n", user_name) < 0) {
785                                 *pp_msg_str = NULL;
786                         }
787                         TALLOC_FREE(sam_pass);
788                         return NT_STATUS_OK;
789                 } else {
790                         if (asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name) < 0) {
791                                 *pp_err_str = NULL;
792                         }
793                         TALLOC_FREE(sam_pass);
794                         return NT_STATUS_UNSUCCESSFUL;
795                 }
796         } else if (local_flags & LOCAL_DELETE_USER) {
797                 if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
798                         if (asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name) < 0) {
799                                 *pp_err_str = NULL;
800                         }
801                         TALLOC_FREE(sam_pass);
802                         return NT_STATUS_UNSUCCESSFUL;
803                 }
804                 if (asprintf(pp_msg_str, "Deleted user %s.\n", user_name) < 0) {
805                         *pp_msg_str = NULL;
806                 }
807         } else {
808                 result = pdb_update_sam_account(sam_pass);
809                 if(!NT_STATUS_IS_OK(result)) {
810                         if (asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name) < 0) {
811                                 *pp_err_str = NULL;
812                         }
813                         TALLOC_FREE(sam_pass);
814                         return result;
815                 }
816                 if(local_flags & LOCAL_DISABLE_USER) {
817                         if (asprintf(pp_msg_str, "Disabled user %s.\n", user_name) < 0) {
818                                 *pp_msg_str = NULL;
819                         }
820                 } else if (local_flags & LOCAL_ENABLE_USER) {
821                         if (asprintf(pp_msg_str, "Enabled user %s.\n", user_name) < 0) {
822                                 *pp_msg_str = NULL;
823                         }
824                 } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
825                         if (asprintf(pp_msg_str, "User %s password set to none.\n", user_name) < 0) {
826                                 *pp_msg_str = NULL;
827                         }
828                 }
829         }
830
831         TALLOC_FREE(sam_pass);
832         return NT_STATUS_OK;
833 }
834
835 /**********************************************************************
836  Marshall/unmarshall struct samu structs.
837  *********************************************************************/
838
839 #define SAMU_BUFFER_FORMAT_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
840 #define SAMU_BUFFER_FORMAT_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
841 #define SAMU_BUFFER_FORMAT_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd"
842 #define SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd"
843 /* nothing changed between V3 and V4 */
844
845 /*********************************************************************
846 *********************************************************************/
847
848 static bool init_samu_from_buffer_v0(struct samu *sampass, uint8 *buf, uint32 buflen)
849 {
850
851         /* times are stored as 32bit integer
852            take care on system with 64bit wide time_t
853            --SSS */
854         uint32  logon_time,
855                 logoff_time,
856                 kickoff_time,
857                 pass_last_set_time,
858                 pass_can_change_time,
859                 pass_must_change_time;
860         char *username = NULL;
861         char *domain = NULL;
862         char *nt_username = NULL;
863         char *dir_drive = NULL;
864         char *unknown_str = NULL;
865         char *munged_dial = NULL;
866         char *fullname = NULL;
867         char *homedir = NULL;
868         char *logon_script = NULL;
869         char *profile_path = NULL;
870         char *acct_desc = NULL;
871         char *workstations = NULL;
872         uint32  username_len, domain_len, nt_username_len,
873                 dir_drive_len, unknown_str_len, munged_dial_len,
874                 fullname_len, homedir_len, logon_script_len,
875                 profile_path_len, acct_desc_len, workstations_len;
876
877         uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
878         uint16  acct_ctrl, logon_divs;
879         uint16  bad_password_count, logon_count;
880         uint8   *hours = NULL;
881         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
882         uint32          len = 0;
883         uint32          lm_pw_len, nt_pw_len, hourslen;
884         bool ret = True;
885
886         if(sampass == NULL || buf == NULL) {
887                 DEBUG(0, ("init_samu_from_buffer_v0: NULL parameters found!\n"));
888                 return False;
889         }
890
891 /* SAMU_BUFFER_FORMAT_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */
892
893         /* unpack the buffer into variables */
894         len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V0,
895                 &logon_time,                                            /* d */
896                 &logoff_time,                                           /* d */
897                 &kickoff_time,                                          /* d */
898                 &pass_last_set_time,                                    /* d */
899                 &pass_can_change_time,                                  /* d */
900                 &pass_must_change_time,                                 /* d */
901                 &username_len, &username,                               /* B */
902                 &domain_len, &domain,                                   /* B */
903                 &nt_username_len, &nt_username,                         /* B */
904                 &fullname_len, &fullname,                               /* B */
905                 &homedir_len, &homedir,                                 /* B */
906                 &dir_drive_len, &dir_drive,                             /* B */
907                 &logon_script_len, &logon_script,                       /* B */
908                 &profile_path_len, &profile_path,                       /* B */
909                 &acct_desc_len, &acct_desc,                             /* B */
910                 &workstations_len, &workstations,                       /* B */
911                 &unknown_str_len, &unknown_str,                         /* B */
912                 &munged_dial_len, &munged_dial,                         /* B */
913                 &user_rid,                                              /* d */
914                 &group_rid,                                             /* d */
915                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
916                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
917                 &acct_ctrl,                                             /* w */
918                 &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */
919                 &logon_divs,                                            /* w */
920                 &hours_len,                                             /* d */
921                 &hourslen, &hours,                                      /* B */
922                 &bad_password_count,                                    /* w */
923                 &logon_count,                                           /* w */
924                 &unknown_6);                                            /* d */
925
926         if (len == (uint32) -1)  {
927                 ret = False;
928                 goto done;
929         }
930
931         pdb_set_logon_time(sampass, logon_time, PDB_SET);
932         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
933         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
934         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
935         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
936         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
937
938         pdb_set_username(sampass, username, PDB_SET); 
939         pdb_set_domain(sampass, domain, PDB_SET);
940         pdb_set_nt_username(sampass, nt_username, PDB_SET);
941         pdb_set_fullname(sampass, fullname, PDB_SET);
942
943         if (homedir) {
944                 pdb_set_homedir(sampass, homedir, PDB_SET);
945         }
946         else {
947                 pdb_set_homedir(sampass, 
948                         talloc_sub_basic(sampass, username, domain,
949                                          lp_logon_home()),
950                         PDB_DEFAULT);
951         }
952
953         if (dir_drive)  
954                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
955         else {
956                 pdb_set_dir_drive(sampass, 
957                         talloc_sub_basic(sampass, username, domain,
958                                          lp_logon_drive()),
959                         PDB_DEFAULT);
960         }
961
962         if (logon_script) 
963                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
964         else {
965                 pdb_set_logon_script(sampass, 
966                         talloc_sub_basic(sampass, username, domain,
967                                          lp_logon_script()),
968                         PDB_DEFAULT);
969         }
970
971         if (profile_path) {     
972                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
973         } else {
974                 pdb_set_profile_path(sampass, 
975                         talloc_sub_basic(sampass, username, domain,
976                                          lp_logon_path()),
977                         PDB_DEFAULT);
978         }
979
980         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
981         pdb_set_workstations(sampass, workstations, PDB_SET);
982         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
983
984         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
985                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
986                         ret = False;
987                         goto done;
988                 }
989         }
990
991         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
992                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
993                         ret = False;
994                         goto done;
995                 }
996         }
997
998         pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
999         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1000         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1001         pdb_set_hours_len(sampass, hours_len, PDB_SET);
1002         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1003         pdb_set_logon_count(sampass, logon_count, PDB_SET);
1004         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1005         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1006         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1007         pdb_set_hours(sampass, hours, PDB_SET);
1008
1009 done:
1010
1011         SAFE_FREE(username);
1012         SAFE_FREE(domain);
1013         SAFE_FREE(nt_username);
1014         SAFE_FREE(fullname);
1015         SAFE_FREE(homedir);
1016         SAFE_FREE(dir_drive);
1017         SAFE_FREE(logon_script);
1018         SAFE_FREE(profile_path);
1019         SAFE_FREE(acct_desc);
1020         SAFE_FREE(workstations);
1021         SAFE_FREE(munged_dial);
1022         SAFE_FREE(unknown_str);
1023         SAFE_FREE(lm_pw_ptr);
1024         SAFE_FREE(nt_pw_ptr);
1025         SAFE_FREE(hours);
1026
1027         return ret;
1028 }
1029
1030 /*********************************************************************
1031 *********************************************************************/
1032
1033 static bool init_samu_from_buffer_v1(struct samu *sampass, uint8 *buf, uint32 buflen)
1034 {
1035
1036         /* times are stored as 32bit integer
1037            take care on system with 64bit wide time_t
1038            --SSS */
1039         uint32  logon_time,
1040                 logoff_time,
1041                 kickoff_time,
1042                 bad_password_time,
1043                 pass_last_set_time,
1044                 pass_can_change_time,
1045                 pass_must_change_time;
1046         char *username = NULL;
1047         char *domain = NULL;
1048         char *nt_username = NULL;
1049         char *dir_drive = NULL;
1050         char *unknown_str = NULL;
1051         char *munged_dial = NULL;
1052         char *fullname = NULL;
1053         char *homedir = NULL;
1054         char *logon_script = NULL;
1055         char *profile_path = NULL;
1056         char *acct_desc = NULL;
1057         char *workstations = NULL;
1058         uint32  username_len, domain_len, nt_username_len,
1059                 dir_drive_len, unknown_str_len, munged_dial_len,
1060                 fullname_len, homedir_len, logon_script_len,
1061                 profile_path_len, acct_desc_len, workstations_len;
1062
1063         uint32  user_rid, group_rid, remove_me, hours_len, unknown_6;
1064         uint16  acct_ctrl, logon_divs;
1065         uint16  bad_password_count, logon_count;
1066         uint8   *hours = NULL;
1067         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
1068         uint32          len = 0;
1069         uint32          lm_pw_len, nt_pw_len, hourslen;
1070         bool ret = True;
1071
1072         if(sampass == NULL || buf == NULL) {
1073                 DEBUG(0, ("init_samu_from_buffer_v1: NULL parameters found!\n"));
1074                 return False;
1075         }
1076
1077 /* SAMU_BUFFER_FORMAT_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */
1078
1079         /* unpack the buffer into variables */
1080         len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V1,
1081                 &logon_time,                                            /* d */
1082                 &logoff_time,                                           /* d */
1083                 &kickoff_time,                                          /* d */
1084                 /* Change from V0 is addition of bad_password_time field. */
1085                 &bad_password_time,                                     /* d */
1086                 &pass_last_set_time,                                    /* d */
1087                 &pass_can_change_time,                                  /* d */
1088                 &pass_must_change_time,                                 /* d */
1089                 &username_len, &username,                               /* B */
1090                 &domain_len, &domain,                                   /* B */
1091                 &nt_username_len, &nt_username,                         /* B */
1092                 &fullname_len, &fullname,                               /* B */
1093                 &homedir_len, &homedir,                                 /* B */
1094                 &dir_drive_len, &dir_drive,                             /* B */
1095                 &logon_script_len, &logon_script,                       /* B */
1096                 &profile_path_len, &profile_path,                       /* B */
1097                 &acct_desc_len, &acct_desc,                             /* B */
1098                 &workstations_len, &workstations,                       /* B */
1099                 &unknown_str_len, &unknown_str,                         /* B */
1100                 &munged_dial_len, &munged_dial,                         /* B */
1101                 &user_rid,                                              /* d */
1102                 &group_rid,                                             /* d */
1103                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
1104                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
1105                 &acct_ctrl,                                             /* w */
1106                 &remove_me,                                             /* d */
1107                 &logon_divs,                                            /* w */
1108                 &hours_len,                                             /* d */
1109                 &hourslen, &hours,                                      /* B */
1110                 &bad_password_count,                                    /* w */
1111                 &logon_count,                                           /* w */
1112                 &unknown_6);                                            /* d */
1113
1114         if (len == (uint32) -1)  {
1115                 ret = False;
1116                 goto done;
1117         }
1118
1119         pdb_set_logon_time(sampass, logon_time, PDB_SET);
1120         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1121         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1122
1123         /* Change from V0 is addition of bad_password_time field. */
1124         pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1125         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1126         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1127         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1128
1129         pdb_set_username(sampass, username, PDB_SET); 
1130         pdb_set_domain(sampass, domain, PDB_SET);
1131         pdb_set_nt_username(sampass, nt_username, PDB_SET);
1132         pdb_set_fullname(sampass, fullname, PDB_SET);
1133
1134         if (homedir) {
1135                 pdb_set_homedir(sampass, homedir, PDB_SET);
1136         }
1137         else {
1138                 pdb_set_homedir(sampass, 
1139                         talloc_sub_basic(sampass, username, domain,
1140                                          lp_logon_home()),
1141                         PDB_DEFAULT);
1142         }
1143
1144         if (dir_drive)  
1145                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1146         else {
1147                 pdb_set_dir_drive(sampass, 
1148                         talloc_sub_basic(sampass, username, domain,
1149                                          lp_logon_drive()),
1150                         PDB_DEFAULT);
1151         }
1152
1153         if (logon_script) 
1154                 pdb_set_logon_script(sampass, logon_script, PDB_SET);
1155         else {
1156                 pdb_set_logon_script(sampass, 
1157                         talloc_sub_basic(sampass, username, domain,
1158                                          lp_logon_script()),
1159                         PDB_DEFAULT);
1160         }
1161
1162         if (profile_path) {     
1163                 pdb_set_profile_path(sampass, profile_path, PDB_SET);
1164         } else {
1165                 pdb_set_profile_path(sampass, 
1166                         talloc_sub_basic(sampass, username, domain,
1167                                          lp_logon_path()),
1168                         PDB_DEFAULT);
1169         }
1170
1171         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1172         pdb_set_workstations(sampass, workstations, PDB_SET);
1173         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1174
1175         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1176                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1177                         ret = False;
1178                         goto done;
1179                 }
1180         }
1181
1182         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1183                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1184                         ret = False;
1185                         goto done;
1186                 }
1187         }
1188
1189         pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1190
1191         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1192         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1193         pdb_set_hours_len(sampass, hours_len, PDB_SET);
1194         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1195         pdb_set_logon_count(sampass, logon_count, PDB_SET);
1196         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1197         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1198         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1199         pdb_set_hours(sampass, hours, PDB_SET);
1200
1201 done:
1202
1203         SAFE_FREE(username);
1204         SAFE_FREE(domain);
1205         SAFE_FREE(nt_username);
1206         SAFE_FREE(fullname);
1207         SAFE_FREE(homedir);
1208         SAFE_FREE(dir_drive);
1209         SAFE_FREE(logon_script);
1210         SAFE_FREE(profile_path);
1211         SAFE_FREE(acct_desc);
1212         SAFE_FREE(workstations);
1213         SAFE_FREE(munged_dial);
1214         SAFE_FREE(unknown_str);
1215         SAFE_FREE(lm_pw_ptr);
1216         SAFE_FREE(nt_pw_ptr);
1217         SAFE_FREE(hours);
1218
1219         return ret;
1220 }
1221
1222 static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 buflen)
1223 {
1224
1225         /* times are stored as 32bit integer
1226            take care on system with 64bit wide time_t
1227            --SSS */
1228         uint32  logon_time,
1229                 logoff_time,
1230                 kickoff_time,
1231                 bad_password_time,
1232                 pass_last_set_time,
1233                 pass_can_change_time,
1234                 pass_must_change_time;
1235         char *username = NULL;
1236         char *domain = NULL;
1237         char *nt_username = NULL;
1238         char *dir_drive = NULL;
1239         char *unknown_str = NULL;
1240         char *munged_dial = NULL;
1241         char *fullname = NULL;
1242         char *homedir = NULL;
1243         char *logon_script = NULL;
1244         char *profile_path = NULL;
1245         char *acct_desc = NULL;
1246         char *workstations = NULL;
1247         uint32  username_len, domain_len, nt_username_len,
1248                 dir_drive_len, unknown_str_len, munged_dial_len,
1249                 fullname_len, homedir_len, logon_script_len,
1250                 profile_path_len, acct_desc_len, workstations_len;
1251
1252         uint32  user_rid, group_rid, hours_len, unknown_6;
1253         uint16  acct_ctrl, logon_divs;
1254         uint16  bad_password_count, logon_count;
1255         uint8   *hours = NULL;
1256         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1257         uint32          len = 0;
1258         uint32          lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1259         uint32 pwHistLen = 0;
1260         bool ret = True;
1261         fstring tmp_string;
1262         bool expand_explicit = lp_passdb_expand_explicit();
1263
1264         if(sampass == NULL || buf == NULL) {
1265                 DEBUG(0, ("init_samu_from_buffer_v2: NULL parameters found!\n"));
1266                 return False;
1267         }
1268
1269 /* SAMU_BUFFER_FORMAT_V2       "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */
1270
1271         /* unpack the buffer into variables */
1272         len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V2,
1273                 &logon_time,                                            /* d */
1274                 &logoff_time,                                           /* d */
1275                 &kickoff_time,                                          /* d */
1276                 &bad_password_time,                                     /* d */
1277                 &pass_last_set_time,                                    /* d */
1278                 &pass_can_change_time,                                  /* d */
1279                 &pass_must_change_time,                                 /* d */
1280                 &username_len, &username,                               /* B */
1281                 &domain_len, &domain,                                   /* B */
1282                 &nt_username_len, &nt_username,                         /* B */
1283                 &fullname_len, &fullname,                               /* B */
1284                 &homedir_len, &homedir,                                 /* B */
1285                 &dir_drive_len, &dir_drive,                             /* B */
1286                 &logon_script_len, &logon_script,                       /* B */
1287                 &profile_path_len, &profile_path,                       /* B */
1288                 &acct_desc_len, &acct_desc,                             /* B */
1289                 &workstations_len, &workstations,                       /* B */
1290                 &unknown_str_len, &unknown_str,                         /* B */
1291                 &munged_dial_len, &munged_dial,                         /* B */
1292                 &user_rid,                                              /* d */
1293                 &group_rid,                                             /* d */
1294                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
1295                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
1296                 /* Change from V1 is addition of password history field. */
1297                 &nt_pw_hist_len, &nt_pw_hist_ptr,                       /* B */
1298                 &acct_ctrl,                                             /* w */
1299                 /* Also "remove_me" field was removed. */
1300                 &logon_divs,                                            /* w */
1301                 &hours_len,                                             /* d */
1302                 &hourslen, &hours,                                      /* B */
1303                 &bad_password_count,                                    /* w */
1304                 &logon_count,                                           /* w */
1305                 &unknown_6);                                            /* d */
1306
1307         if (len == (uint32) -1)  {
1308                 ret = False;
1309                 goto done;
1310         }
1311
1312         pdb_set_logon_time(sampass, logon_time, PDB_SET);
1313         pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
1314         pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
1315         pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
1316         pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
1317         pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
1318         pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
1319
1320         pdb_set_username(sampass, username, PDB_SET); 
1321         pdb_set_domain(sampass, domain, PDB_SET);
1322         pdb_set_nt_username(sampass, nt_username, PDB_SET);
1323         pdb_set_fullname(sampass, fullname, PDB_SET);
1324
1325         if (homedir) {
1326                 fstrcpy( tmp_string, homedir );
1327                 if (expand_explicit) {
1328                         standard_sub_basic( username, domain, tmp_string,
1329                                             sizeof(tmp_string) );
1330                 }
1331                 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1332         }
1333         else {
1334                 pdb_set_homedir(sampass, 
1335                         talloc_sub_basic(sampass, username, domain,
1336                                          lp_logon_home()),
1337                         PDB_DEFAULT);
1338         }
1339
1340         if (dir_drive)  
1341                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1342         else
1343                 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1344
1345         if (logon_script) {
1346                 fstrcpy( tmp_string, logon_script );
1347                 if (expand_explicit) {
1348                         standard_sub_basic( username, domain, tmp_string,
1349                                             sizeof(tmp_string) );
1350                 }
1351                 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1352         }
1353         else {
1354                 pdb_set_logon_script(sampass, 
1355                         talloc_sub_basic(sampass, username, domain,
1356                                          lp_logon_script()),
1357                         PDB_DEFAULT);
1358         }
1359
1360         if (profile_path) {     
1361                 fstrcpy( tmp_string, profile_path );
1362                 if (expand_explicit) {
1363                         standard_sub_basic( username, domain, tmp_string,
1364                                             sizeof(tmp_string) );
1365                 }
1366                 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1367         } 
1368         else {
1369                 pdb_set_profile_path(sampass, 
1370                         talloc_sub_basic(sampass, username, domain,
1371                                          lp_logon_path()),
1372                         PDB_DEFAULT);
1373         }
1374
1375         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1376         pdb_set_workstations(sampass, workstations, PDB_SET);
1377         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1378
1379         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1380                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1381                         ret = False;
1382                         goto done;
1383                 }
1384         }
1385
1386         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1387                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1388                         ret = False;
1389                         goto done;
1390                 }
1391         }
1392
1393         /* Change from V1 is addition of password history field. */
1394         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1395         if (pwHistLen) {
1396                 uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN);
1397                 if (!pw_hist) {
1398                         ret = False;
1399                         goto done;
1400                 }
1401                 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1402                 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1403                         int i;
1404                         SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1405                         nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1406                         for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1407                                 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1408                                         &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1409                                         PW_HISTORY_ENTRY_LEN);
1410                         }
1411                 }
1412                 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1413                         SAFE_FREE(pw_hist);
1414                         ret = False;
1415                         goto done;
1416                 }
1417                 SAFE_FREE(pw_hist);
1418         } else {
1419                 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1420         }
1421
1422         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1423         pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET);
1424         pdb_set_hours_len(sampass, hours_len, PDB_SET);
1425         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1426         pdb_set_logon_count(sampass, logon_count, PDB_SET);
1427         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1428         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1429         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1430         pdb_set_hours(sampass, hours, PDB_SET);
1431
1432 done:
1433
1434         SAFE_FREE(username);
1435         SAFE_FREE(domain);
1436         SAFE_FREE(nt_username);
1437         SAFE_FREE(fullname);
1438         SAFE_FREE(homedir);
1439         SAFE_FREE(dir_drive);
1440         SAFE_FREE(logon_script);
1441         SAFE_FREE(profile_path);
1442         SAFE_FREE(acct_desc);
1443         SAFE_FREE(workstations);
1444         SAFE_FREE(munged_dial);
1445         SAFE_FREE(unknown_str);
1446         SAFE_FREE(lm_pw_ptr);
1447         SAFE_FREE(nt_pw_ptr);
1448         SAFE_FREE(nt_pw_hist_ptr);
1449         SAFE_FREE(hours);
1450
1451         return ret;
1452 }
1453
1454 /*********************************************************************
1455 *********************************************************************/
1456
1457 static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 buflen)
1458 {
1459
1460         /* times are stored as 32bit integer
1461            take care on system with 64bit wide time_t
1462            --SSS */
1463         uint32  logon_time,
1464                 logoff_time,
1465                 kickoff_time,
1466                 bad_password_time,
1467                 pass_last_set_time,
1468                 pass_can_change_time,
1469                 pass_must_change_time;
1470         char *username = NULL;
1471         char *domain = NULL;
1472         char *nt_username = NULL;
1473         char *dir_drive = NULL;
1474         char *unknown_str = NULL;
1475         char *munged_dial = NULL;
1476         char *fullname = NULL;
1477         char *homedir = NULL;
1478         char *logon_script = NULL;
1479         char *profile_path = NULL;
1480         char *acct_desc = NULL;
1481         char *workstations = NULL;
1482         uint32  username_len, domain_len, nt_username_len,
1483                 dir_drive_len, unknown_str_len, munged_dial_len,
1484                 fullname_len, homedir_len, logon_script_len,
1485                 profile_path_len, acct_desc_len, workstations_len;
1486
1487         uint32  user_rid, group_rid, hours_len, unknown_6, acct_ctrl;
1488         uint16  logon_divs;
1489         uint16  bad_password_count, logon_count;
1490         uint8   *hours = NULL;
1491         uint8   *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
1492         uint32          len = 0;
1493         uint32          lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
1494         uint32 pwHistLen = 0;
1495         bool ret = True;
1496         fstring tmp_string;
1497         bool expand_explicit = lp_passdb_expand_explicit();
1498
1499         if(sampass == NULL || buf == NULL) {
1500                 DEBUG(0, ("init_samu_from_buffer_v3: NULL parameters found!\n"));
1501                 return False;
1502         }
1503
1504 /* SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1505
1506         /* unpack the buffer into variables */
1507         len = tdb_unpack (buf, buflen, SAMU_BUFFER_FORMAT_V3,
1508                 &logon_time,                                            /* d */
1509                 &logoff_time,                                           /* d */
1510                 &kickoff_time,                                          /* d */
1511                 &bad_password_time,                                     /* d */
1512                 &pass_last_set_time,                                    /* d */
1513                 &pass_can_change_time,                                  /* d */
1514                 &pass_must_change_time,                                 /* d */
1515                 &username_len, &username,                               /* B */
1516                 &domain_len, &domain,                                   /* B */
1517                 &nt_username_len, &nt_username,                         /* B */
1518                 &fullname_len, &fullname,                               /* B */
1519                 &homedir_len, &homedir,                                 /* B */
1520                 &dir_drive_len, &dir_drive,                             /* B */
1521                 &logon_script_len, &logon_script,                       /* B */
1522                 &profile_path_len, &profile_path,                       /* B */
1523                 &acct_desc_len, &acct_desc,                             /* B */
1524                 &workstations_len, &workstations,                       /* B */
1525                 &unknown_str_len, &unknown_str,                         /* B */
1526                 &munged_dial_len, &munged_dial,                         /* B */
1527                 &user_rid,                                              /* d */
1528                 &group_rid,                                             /* d */
1529                 &lm_pw_len, &lm_pw_ptr,                                 /* B */
1530                 &nt_pw_len, &nt_pw_ptr,                                 /* B */
1531                 /* Change from V1 is addition of password history field. */
1532                 &nt_pw_hist_len, &nt_pw_hist_ptr,                       /* B */
1533                 /* Change from V2 is the uint32 acb_mask */
1534                 &acct_ctrl,                                             /* d */
1535                 /* Also "remove_me" field was removed. */
1536                 &logon_divs,                                            /* w */
1537                 &hours_len,                                             /* d */
1538                 &hourslen, &hours,                                      /* B */
1539                 &bad_password_count,                                    /* w */
1540                 &logon_count,                                           /* w */
1541                 &unknown_6);                                            /* d */
1542
1543         if (len == (uint32) -1)  {
1544                 ret = False;
1545                 goto done;
1546         }
1547
1548         pdb_set_logon_time(sampass, convert_uint32_to_time_t(logon_time), PDB_SET);
1549         pdb_set_logoff_time(sampass, convert_uint32_to_time_t(logoff_time), PDB_SET);
1550         pdb_set_kickoff_time(sampass, convert_uint32_to_time_t(kickoff_time), PDB_SET);
1551         pdb_set_bad_password_time(sampass, convert_uint32_to_time_t(bad_password_time), PDB_SET);
1552         pdb_set_pass_can_change_time(sampass, convert_uint32_to_time_t(pass_can_change_time), PDB_SET);
1553         pdb_set_pass_must_change_time(sampass, convert_uint32_to_time_t(pass_must_change_time), PDB_SET);
1554         pdb_set_pass_last_set_time(sampass, convert_uint32_to_time_t(pass_last_set_time), PDB_SET);
1555
1556         pdb_set_username(sampass, username, PDB_SET); 
1557         pdb_set_domain(sampass, domain, PDB_SET);
1558         pdb_set_nt_username(sampass, nt_username, PDB_SET);
1559         pdb_set_fullname(sampass, fullname, PDB_SET);
1560
1561         if (homedir) {
1562                 fstrcpy( tmp_string, homedir );
1563                 if (expand_explicit) {
1564                         standard_sub_basic( username, domain, tmp_string,
1565                                             sizeof(tmp_string) );
1566                 }
1567                 pdb_set_homedir(sampass, tmp_string, PDB_SET);
1568         }
1569         else {
1570                 pdb_set_homedir(sampass, 
1571                         talloc_sub_basic(sampass, username, domain,
1572                                          lp_logon_home()),
1573                         PDB_DEFAULT);
1574         }
1575
1576         if (dir_drive)  
1577                 pdb_set_dir_drive(sampass, dir_drive, PDB_SET);
1578         else
1579                 pdb_set_dir_drive(sampass, lp_logon_drive(), PDB_DEFAULT );
1580
1581         if (logon_script) {
1582                 fstrcpy( tmp_string, logon_script );
1583                 if (expand_explicit) {
1584                         standard_sub_basic( username, domain, tmp_string,
1585                                             sizeof(tmp_string) );
1586                 }
1587                 pdb_set_logon_script(sampass, tmp_string, PDB_SET);
1588         }
1589         else {
1590                 pdb_set_logon_script(sampass, 
1591                         talloc_sub_basic(sampass, username, domain,
1592                                          lp_logon_script()),
1593                         PDB_DEFAULT);
1594         }
1595
1596         if (profile_path) {     
1597                 fstrcpy( tmp_string, profile_path );
1598                 if (expand_explicit) {
1599                         standard_sub_basic( username, domain, tmp_string,
1600                                             sizeof(tmp_string) );
1601                 }
1602                 pdb_set_profile_path(sampass, tmp_string, PDB_SET);
1603         } 
1604         else {
1605                 pdb_set_profile_path(sampass, 
1606                         talloc_sub_basic(sampass, username, domain, lp_logon_path()),
1607                         PDB_DEFAULT);
1608         }
1609
1610         pdb_set_acct_desc(sampass, acct_desc, PDB_SET);
1611         pdb_set_workstations(sampass, workstations, PDB_SET);
1612         pdb_set_munged_dial(sampass, munged_dial, PDB_SET);
1613
1614         if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) {
1615                 if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) {
1616                         ret = False;
1617                         goto done;
1618                 }
1619         }
1620
1621         if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) {
1622                 if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) {
1623                         ret = False;
1624                         goto done;
1625                 }
1626         }
1627
1628         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1629         if (pwHistLen) {
1630                 uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
1631                 if (!pw_hist) {
1632                         ret = False;
1633                         goto done;
1634                 }
1635                 memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_LEN);
1636                 if (nt_pw_hist_ptr && nt_pw_hist_len) {
1637                         int i;
1638                         SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0);
1639                         nt_pw_hist_len /= PW_HISTORY_ENTRY_LEN;
1640                         for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) {
1641                                 memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN],
1642                                         &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN],
1643                                         PW_HISTORY_ENTRY_LEN);
1644                         }
1645                 }
1646                 if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) {
1647                         SAFE_FREE(pw_hist);
1648                         ret = False;
1649                         goto done;
1650                 }
1651                 SAFE_FREE(pw_hist);
1652         } else {
1653                 pdb_set_pw_history(sampass, NULL, 0, PDB_SET);
1654         }
1655
1656         pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
1657         pdb_set_hours_len(sampass, hours_len, PDB_SET);
1658         pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
1659         pdb_set_logon_count(sampass, logon_count, PDB_SET);
1660         pdb_set_unknown_6(sampass, unknown_6, PDB_SET);
1661         /* Change from V2 is the uint32 acct_ctrl */
1662         pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
1663         pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
1664         pdb_set_hours(sampass, hours, PDB_SET);
1665
1666 done:
1667
1668         SAFE_FREE(username);
1669         SAFE_FREE(domain);
1670         SAFE_FREE(nt_username);
1671         SAFE_FREE(fullname);
1672         SAFE_FREE(homedir);
1673         SAFE_FREE(dir_drive);
1674         SAFE_FREE(logon_script);
1675         SAFE_FREE(profile_path);
1676         SAFE_FREE(acct_desc);
1677         SAFE_FREE(workstations);
1678         SAFE_FREE(munged_dial);
1679         SAFE_FREE(unknown_str);
1680         SAFE_FREE(lm_pw_ptr);
1681         SAFE_FREE(nt_pw_ptr);
1682         SAFE_FREE(nt_pw_hist_ptr);
1683         SAFE_FREE(hours);
1684
1685         return ret;
1686 }
1687
1688 /*********************************************************************
1689 *********************************************************************/
1690
1691 static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool size_only)
1692 {
1693         size_t len, buflen;
1694
1695         /* times are stored as 32bit integer
1696            take care on system with 64bit wide time_t
1697            --SSS */
1698         uint32  logon_time,
1699                 logoff_time,
1700                 kickoff_time,
1701                 bad_password_time,
1702                 pass_last_set_time,
1703                 pass_can_change_time,
1704                 pass_must_change_time;
1705
1706         uint32  user_rid, group_rid;
1707
1708         const char *username;
1709         const char *domain;
1710         const char *nt_username;
1711         const char *dir_drive;
1712         const char *unknown_str;
1713         const char *munged_dial;
1714         const char *fullname;
1715         const char *homedir;
1716         const char *logon_script;
1717         const char *profile_path;
1718         const char *acct_desc;
1719         const char *workstations;
1720         uint32  username_len, domain_len, nt_username_len,
1721                 dir_drive_len, unknown_str_len, munged_dial_len,
1722                 fullname_len, homedir_len, logon_script_len,
1723                 profile_path_len, acct_desc_len, workstations_len;
1724
1725         const uint8 *lm_pw;
1726         const uint8 *nt_pw;
1727         const uint8 *nt_pw_hist;
1728         uint32  lm_pw_len = 16;
1729         uint32  nt_pw_len = 16;
1730         uint32  nt_pw_hist_len;
1731         uint32 pwHistLen = 0;
1732
1733         *buf = NULL;
1734         buflen = 0;
1735
1736         logon_time = convert_time_t_to_uint32(pdb_get_logon_time(sampass));
1737         logoff_time = convert_time_t_to_uint32(pdb_get_logoff_time(sampass));
1738         kickoff_time = convert_time_t_to_uint32(pdb_get_kickoff_time(sampass));
1739         bad_password_time = convert_time_t_to_uint32(pdb_get_bad_password_time(sampass));
1740         pass_can_change_time = convert_time_t_to_uint32(pdb_get_pass_can_change_time_noncalc(sampass));
1741         pass_must_change_time = convert_time_t_to_uint32(pdb_get_pass_must_change_time(sampass));
1742         pass_last_set_time = convert_time_t_to_uint32(pdb_get_pass_last_set_time(sampass));
1743
1744         user_rid = pdb_get_user_rid(sampass);
1745         group_rid = pdb_get_group_rid(sampass);
1746
1747         username = pdb_get_username(sampass);
1748         if (username) {
1749                 username_len = strlen(username) +1;
1750         } else {
1751                 username_len = 0;
1752         }
1753
1754         domain = pdb_get_domain(sampass);
1755         if (domain) {
1756                 domain_len = strlen(domain) +1;
1757         } else {
1758                 domain_len = 0;
1759         }
1760
1761         nt_username = pdb_get_nt_username(sampass);
1762         if (nt_username) {
1763                 nt_username_len = strlen(nt_username) +1;
1764         } else {
1765                 nt_username_len = 0;
1766         }
1767
1768         fullname = pdb_get_fullname(sampass);
1769         if (fullname) {
1770                 fullname_len = strlen(fullname) +1;
1771         } else {
1772                 fullname_len = 0;
1773         }
1774
1775         /*
1776          * Only updates fields which have been set (not defaults from smb.conf)
1777          */
1778
1779         if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) {
1780                 dir_drive = pdb_get_dir_drive(sampass);
1781         } else {
1782                 dir_drive = NULL;
1783         }
1784         if (dir_drive) {
1785                 dir_drive_len = strlen(dir_drive) +1;
1786         } else {
1787                 dir_drive_len = 0;
1788         }
1789
1790         if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) {
1791                 homedir = pdb_get_homedir(sampass);
1792         } else {
1793                 homedir = NULL;
1794         }
1795         if (homedir) {
1796                 homedir_len = strlen(homedir) +1;
1797         } else {
1798                 homedir_len = 0;
1799         }
1800
1801         if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) {
1802                 logon_script = pdb_get_logon_script(sampass);
1803         } else {
1804                 logon_script = NULL;
1805         }
1806         if (logon_script) {
1807                 logon_script_len = strlen(logon_script) +1;
1808         } else {
1809                 logon_script_len = 0;
1810         }
1811
1812         if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) {
1813                 profile_path = pdb_get_profile_path(sampass);
1814         } else {
1815                 profile_path = NULL;
1816         }
1817         if (profile_path) {
1818                 profile_path_len = strlen(profile_path) +1;
1819         } else {
1820                 profile_path_len = 0;
1821         }
1822
1823         lm_pw = pdb_get_lanman_passwd(sampass);
1824         if (!lm_pw) {
1825                 lm_pw_len = 0;
1826         }
1827
1828         nt_pw = pdb_get_nt_passwd(sampass);
1829         if (!nt_pw) {
1830                 nt_pw_len = 0;
1831         }
1832
1833         pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1834         nt_pw_hist =  pdb_get_pw_history(sampass, &nt_pw_hist_len);
1835         if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
1836                 nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
1837         } else {
1838                 nt_pw_hist_len = 0;
1839         }
1840
1841         acct_desc = pdb_get_acct_desc(sampass);
1842         if (acct_desc) {
1843                 acct_desc_len = strlen(acct_desc) +1;
1844         } else {
1845                 acct_desc_len = 0;
1846         }
1847
1848         workstations = pdb_get_workstations(sampass);
1849         if (workstations) {
1850                 workstations_len = strlen(workstations) +1;
1851         } else {
1852                 workstations_len = 0;
1853         }
1854
1855         unknown_str = NULL;
1856         unknown_str_len = 0;
1857
1858         munged_dial = pdb_get_munged_dial(sampass);
1859         if (munged_dial) {
1860                 munged_dial_len = strlen(munged_dial) +1;
1861         } else {
1862                 munged_dial_len = 0;    
1863         }
1864
1865 /* SAMU_BUFFER_FORMAT_V3       "dddddddBBBBBBBBBBBBddBBBdwdBwwd" */
1866
1867         /* one time to get the size needed */
1868         len = tdb_pack(NULL, 0,  SAMU_BUFFER_FORMAT_V3,
1869                 logon_time,                             /* d */
1870                 logoff_time,                            /* d */
1871                 kickoff_time,                           /* d */
1872                 bad_password_time,                      /* d */
1873                 pass_last_set_time,                     /* d */
1874                 pass_can_change_time,                   /* d */
1875                 pass_must_change_time,                  /* d */
1876                 username_len, username,                 /* B */
1877                 domain_len, domain,                     /* B */
1878                 nt_username_len, nt_username,           /* B */
1879                 fullname_len, fullname,                 /* B */
1880                 homedir_len, homedir,                   /* B */
1881                 dir_drive_len, dir_drive,               /* B */
1882                 logon_script_len, logon_script,         /* B */
1883                 profile_path_len, profile_path,         /* B */
1884                 acct_desc_len, acct_desc,               /* B */
1885                 workstations_len, workstations,         /* B */
1886                 unknown_str_len, unknown_str,           /* B */
1887                 munged_dial_len, munged_dial,           /* B */
1888                 user_rid,                               /* d */
1889                 group_rid,                              /* d */
1890                 lm_pw_len, lm_pw,                       /* B */
1891                 nt_pw_len, nt_pw,                       /* B */
1892                 nt_pw_hist_len, nt_pw_hist,             /* B */
1893                 pdb_get_acct_ctrl(sampass),             /* d */
1894                 pdb_get_logon_divs(sampass),            /* w */
1895                 pdb_get_hours_len(sampass),             /* d */
1896                 MAX_HOURS_LEN, pdb_get_hours(sampass),  /* B */
1897                 pdb_get_bad_password_count(sampass),    /* w */
1898                 pdb_get_logon_count(sampass),           /* w */
1899                 pdb_get_unknown_6(sampass));            /* d */
1900
1901         if (size_only) {
1902                 return buflen;
1903         }
1904
1905         /* malloc the space needed */
1906         if ( (*buf=(uint8*)SMB_MALLOC(len)) == NULL) {
1907                 DEBUG(0,("init_buffer_from_samu_v3: Unable to malloc() memory for buffer!\n"));
1908                 return (-1);
1909         }
1910
1911         /* now for the real call to tdb_pack() */
1912         buflen = tdb_pack(*buf, len,  SAMU_BUFFER_FORMAT_V3,
1913                 logon_time,                             /* d */
1914                 logoff_time,                            /* d */
1915                 kickoff_time,                           /* d */
1916                 bad_password_time,                      /* d */
1917                 pass_last_set_time,                     /* d */
1918                 pass_can_change_time,                   /* d */
1919                 pass_must_change_time,                  /* d */
1920                 username_len, username,                 /* B */
1921                 domain_len, domain,                     /* B */
1922                 nt_username_len, nt_username,           /* B */
1923                 fullname_len, fullname,                 /* B */
1924                 homedir_len, homedir,                   /* B */
1925                 dir_drive_len, dir_drive,               /* B */
1926                 logon_script_len, logon_script,         /* B */
1927                 profile_path_len, profile_path,         /* B */
1928                 acct_desc_len, acct_desc,               /* B */
1929                 workstations_len, workstations,         /* B */
1930                 unknown_str_len, unknown_str,           /* B */
1931                 munged_dial_len, munged_dial,           /* B */
1932                 user_rid,                               /* d */
1933                 group_rid,                              /* d */
1934                 lm_pw_len, lm_pw,                       /* B */
1935                 nt_pw_len, nt_pw,                       /* B */
1936                 nt_pw_hist_len, nt_pw_hist,             /* B */
1937                 pdb_get_acct_ctrl(sampass),             /* d */
1938                 pdb_get_logon_divs(sampass),            /* w */
1939                 pdb_get_hours_len(sampass),             /* d */
1940                 MAX_HOURS_LEN, pdb_get_hours(sampass),  /* B */
1941                 pdb_get_bad_password_count(sampass),    /* w */
1942                 pdb_get_logon_count(sampass),           /* w */
1943                 pdb_get_unknown_6(sampass));            /* d */
1944
1945         /* check to make sure we got it correct */
1946         if (buflen != len) {
1947                 DEBUG(0, ("init_buffer_from_samu_v3: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", 
1948                           (unsigned long)buflen, (unsigned long)len));  
1949                 /* error */
1950                 SAFE_FREE (*buf);
1951                 return (-1);
1952         }
1953
1954         return (buflen);
1955 }
1956
1957 static bool init_samu_from_buffer_v4(struct samu *sampass, uint8 *buf, uint32 buflen)
1958 {
1959         /* nothing changed between V3 and V4 */
1960         return init_samu_from_buffer_v3(sampass, buf, buflen);
1961 }
1962
1963 static uint32 init_buffer_from_samu_v4(uint8 **buf, struct samu *sampass, bool size_only)
1964 {
1965         /* nothing changed between V3 and V4 */
1966         return init_buffer_from_samu_v3(buf, sampass, size_only);
1967 }
1968
1969 /**********************************************************************
1970  Intialize a struct samu struct from a BYTE buffer of size len
1971  *********************************************************************/
1972
1973 bool init_samu_from_buffer(struct samu *sampass, uint32_t level,
1974                            uint8 *buf, uint32 buflen)
1975 {
1976         switch (level) {
1977         case SAMU_BUFFER_V0:
1978                 return init_samu_from_buffer_v0(sampass, buf, buflen);
1979         case SAMU_BUFFER_V1:
1980                 return init_samu_from_buffer_v1(sampass, buf, buflen);
1981         case SAMU_BUFFER_V2:
1982                 return init_samu_from_buffer_v2(sampass, buf, buflen);
1983         case SAMU_BUFFER_V3:
1984                 return init_samu_from_buffer_v3(sampass, buf, buflen);
1985         case SAMU_BUFFER_V4:
1986                 return init_samu_from_buffer_v4(sampass, buf, buflen);
1987         }
1988
1989         return false;
1990 }
1991
1992 /**********************************************************************
1993  Intialize a BYTE buffer from a struct samu struct
1994  *********************************************************************/
1995
1996 uint32 init_buffer_from_samu (uint8 **buf, struct samu *sampass, bool size_only)
1997 {
1998         return init_buffer_from_samu_v4(buf, sampass, size_only);
1999 }
2000
2001 /*********************************************************************
2002 *********************************************************************/
2003
2004 bool pdb_copy_sam_account(struct samu *dst, struct samu *src )
2005 {
2006         uint8 *buf = NULL;
2007         int len;
2008
2009         len = init_buffer_from_samu(&buf, src, False);
2010         if (len == -1 || !buf) {
2011                 SAFE_FREE(buf);
2012                 return False;
2013         }
2014
2015         if (!init_samu_from_buffer( dst, SAMU_BUFFER_LATEST, buf, len )) {
2016                 free(buf);
2017                 return False;
2018         }
2019
2020         dst->methods = src->methods;
2021
2022         if ( src->unix_pw ) {
2023                 dst->unix_pw = tcopy_passwd( dst, src->unix_pw );
2024                 if (!dst->unix_pw) {
2025                         free(buf);
2026                         return False;
2027                 }
2028         }
2029
2030         free(buf);
2031         return True;
2032 }
2033
2034 /*********************************************************************
2035  Update the bad password count checking the AP_RESET_COUNT_TIME 
2036 *********************************************************************/
2037
2038 bool pdb_update_bad_password_count(struct samu *sampass, bool *updated)
2039 {
2040         time_t LastBadPassword;
2041         uint16 BadPasswordCount;
2042         uint32 resettime; 
2043         bool res;
2044
2045         BadPasswordCount = pdb_get_bad_password_count(sampass);
2046         if (!BadPasswordCount) {
2047                 DEBUG(9, ("No bad password attempts.\n"));
2048                 return True;
2049         }
2050
2051         become_root();
2052         res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime);
2053         unbecome_root();
2054
2055         if (!res) {
2056                 DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
2057                 return False;
2058         }
2059
2060         /* First, check if there is a reset time to compare */
2061         if ((resettime == (uint32) -1) || (resettime == 0)) {
2062                 DEBUG(9, ("No reset time, can't reset bad pw count\n"));
2063                 return True;
2064         }
2065
2066         LastBadPassword = pdb_get_bad_password_time(sampass);
2067         DEBUG(7, ("LastBadPassword=%d, resettime=%d, current time=%d.\n", 
2068                    (uint32) LastBadPassword, resettime, (uint32)time(NULL)));
2069         if (time(NULL) > (LastBadPassword + convert_uint32_to_time_t(resettime)*60)){
2070                 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2071                 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2072                 if (updated) {
2073                         *updated = True;
2074                 }
2075         }
2076
2077         return True;
2078 }
2079
2080 /*********************************************************************
2081  Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION 
2082 *********************************************************************/
2083
2084 bool pdb_update_autolock_flag(struct samu *sampass, bool *updated)
2085 {
2086         uint32 duration;
2087         time_t LastBadPassword;
2088         bool res;
2089
2090         if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) {
2091                 DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n",
2092                         pdb_get_username(sampass)));
2093                 return True;
2094         }
2095
2096         become_root();
2097         res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration);
2098         unbecome_root();
2099
2100         if (!res) {
2101                 DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
2102                 return False;
2103         }
2104
2105         /* First, check if there is a duration to compare */
2106         if ((duration == (uint32) -1)  || (duration == 0)) {
2107                 DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n"));
2108                 return True;
2109         }
2110
2111         LastBadPassword = pdb_get_bad_password_time(sampass);
2112         DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n",
2113                   pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL)));
2114
2115         if (LastBadPassword == (time_t)0) {
2116                 DEBUG(1,("pdb_update_autolock_flag: Account %s "
2117                          "administratively locked out with no bad password "
2118                          "time. Leaving locked out.\n",
2119                          pdb_get_username(sampass) ));
2120                 return True;
2121         }
2122
2123         if ((time(NULL) > (LastBadPassword + convert_uint32_to_time_t(duration) * 60))) {
2124                 pdb_set_acct_ctrl(sampass,
2125                                   pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
2126                                   PDB_CHANGED);
2127                 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
2128                 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
2129                 if (updated) {
2130                         *updated = True;
2131                 }
2132         }
2133
2134         return True;
2135 }
2136
2137 /*********************************************************************
2138  Increment the bad_password_count 
2139 *********************************************************************/
2140
2141 bool pdb_increment_bad_password_count(struct samu *sampass)
2142 {
2143         uint32 account_policy_lockout;
2144         bool autolock_updated = False, badpw_updated = False;
2145         bool ret;
2146
2147         /* Retrieve the account lockout policy */
2148         become_root();
2149         ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
2150         unbecome_root();
2151         if ( !ret ) {
2152                 DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
2153                 return False;
2154         }
2155
2156         /* If there is no policy, we don't need to continue checking */
2157         if (!account_policy_lockout) {
2158                 DEBUG(9, ("No lockout policy, don't track bad passwords\n"));
2159                 return True;
2160         }
2161
2162         /* Check if the autolock needs to be cleared */
2163         if (!pdb_update_autolock_flag(sampass, &autolock_updated))
2164                 return False;
2165
2166         /* Check if the badpw count needs to be reset */
2167         if (!pdb_update_bad_password_count(sampass, &badpw_updated))
2168                 return False;
2169
2170         /*
2171           Ok, now we can assume that any resetting that needs to be 
2172           done has been done, and just get on with incrementing
2173           and autolocking if necessary
2174         */
2175
2176         pdb_set_bad_password_count(sampass, 
2177                                    pdb_get_bad_password_count(sampass)+1,
2178                                    PDB_CHANGED);
2179         pdb_set_bad_password_time(sampass, time(NULL), PDB_CHANGED);
2180
2181
2182         if (pdb_get_bad_password_count(sampass) < account_policy_lockout) 
2183                 return True;
2184
2185         if (!pdb_set_acct_ctrl(sampass,
2186                                pdb_get_acct_ctrl(sampass) | ACB_AUTOLOCK,
2187                                PDB_CHANGED)) {
2188                 DEBUG(1, ("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n")); 
2189                 return False;
2190         }
2191
2192         return True;
2193 }
2194
2195 bool is_dc_trusted_domain_situation(const char *domain_name)
2196 {
2197         return IS_DC && !strequal(domain_name, lp_workgroup());
2198 }
2199
2200 /*******************************************************************
2201  Wrapper around retrieving the clear text trust account password.
2202  appropriate account name is stored in account_name.
2203  Caller must free password, but not account_name.
2204 *******************************************************************/
2205
2206 bool get_trust_pw_clear(const char *domain, char **ret_pwd,
2207                         const char **account_name, uint32 *channel)
2208 {
2209         char *pwd;
2210         time_t last_set_time;
2211
2212         /* if we are a DC and this is not our domain, then lookup an account
2213          * for the domain trust */
2214
2215         if (is_dc_trusted_domain_situation(domain)) {
2216                 if (!lp_allow_trusted_domains()) {
2217                         return false;
2218                 }
2219
2220                 if (!pdb_get_trusteddom_pw(domain, ret_pwd, NULL,
2221                                            &last_set_time))
2222                 {
2223                         DEBUG(0, ("get_trust_pw: could not fetch trust "
2224                                 "account password for trusted domain %s\n",
2225                                 domain));
2226                         return false;
2227                 }
2228
2229                 if (channel != NULL) {
2230                         *channel = SEC_CHAN_DOMAIN;
2231                 }
2232
2233                 if (account_name != NULL) {
2234                         *account_name = lp_workgroup();
2235                 }
2236
2237                 return true;
2238         }
2239
2240         /*
2241          * Since we can only be member of one single domain, we are now
2242          * in a member situation:
2243          *
2244          *  -  Either we are a DC (selfjoined) and the domain is our
2245          *     own domain.
2246          *  -  Or we are on a member and the domain is our own or some
2247          *     other (potentially trusted) domain.
2248          *
2249          * In both cases, we can only get the machine account password
2250          * for our own domain to connect to our own dc. (For a member,
2251          * request to trusted domains are performed through our dc.)
2252          *
2253          * So we simply use our own domain name to retrieve the
2254          * machine account passowrd and ignore the request domain here.
2255          */
2256
2257         pwd = secrets_fetch_machine_password(lp_workgroup(), &last_set_time, channel);
2258
2259         if (pwd != NULL) {
2260                 *ret_pwd = pwd;
2261                 if (account_name != NULL) {
2262                         *account_name = global_myname();
2263                 }
2264
2265                 return true;
2266         }
2267
2268         DEBUG(5, ("get_trust_pw_clear: could not fetch clear text trust "
2269                   "account password for domain %s\n", domain));
2270         return false;
2271 }
2272
2273 /*******************************************************************
2274  Wrapper around retrieving the trust account password.
2275  appropriate account name is stored in account_name.
2276 *******************************************************************/
2277
2278 bool get_trust_pw_hash(const char *domain, uint8 ret_pwd[16],
2279                        const char **account_name, uint32 *channel)
2280 {
2281         char *pwd = NULL;
2282         time_t last_set_time;
2283
2284         if (get_trust_pw_clear(domain, &pwd, account_name, channel)) {
2285                 E_md4hash(pwd, ret_pwd);
2286                 SAFE_FREE(pwd);
2287                 return true;
2288         } else if (is_dc_trusted_domain_situation(domain)) {
2289                 return false;
2290         }
2291
2292         /* as a fallback, try to get the hashed pwd directly from the tdb... */
2293
2294         if (secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
2295                                                         &last_set_time,
2296                                                         channel))
2297         {
2298                 if (account_name != NULL) {
2299                         *account_name = global_myname();
2300                 }
2301
2302                 return true;
2303         }
2304
2305         DEBUG(5, ("get_trust_pw_hash: could not fetch trust account "
2306                 "password for domain %s\n", domain));
2307         return False;
2308 }
2309
2310 struct samr_LogonHours get_logon_hours_from_pdb(TALLOC_CTX *mem_ctx,
2311                                                 struct samu *pw)
2312 {
2313         struct samr_LogonHours hours;
2314         const int units_per_week = 168;
2315
2316         ZERO_STRUCT(hours);
2317         hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
2318         if (!hours.bits) {
2319                 return hours;
2320         }
2321
2322         hours.units_per_week = units_per_week;
2323         memset(hours.bits, 0xFF, units_per_week);
2324
2325         if (pdb_get_hours(pw)) {
2326                 memcpy(hours.bits, pdb_get_hours(pw),
2327                        MIN(pdb_get_hours_len(pw), units_per_week));
2328         }
2329
2330         return hours;
2331 }
2332