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