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