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