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