Add a new interface pdb_set_plaintext_passwd() to the passdb. This simply
[kai/samba.git] / source3 / passdb / passdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Jeremy Allison                 1996-2001
6    Copyright (C) Luke Kenneth Casson Leighton   1996-1998
7    Copyright (C) Gerald (Jerry) Carter          2000-2001
8       
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern int DEBUGLEVEL;
27
28 /*
29  * This is set on startup - it defines the SID for this
30  * machine, and therefore the SAM database for which it is
31  * responsible.
32  */
33
34 extern DOM_SID global_sam_sid;
35
36 struct passdb_ops *pdb_ops;
37
38 #if 0   /* JERRY */
39 static void* pdb_handle = NULL;
40 #endif
41
42 /***************************************************************
43  Initialize the password db operations.
44 ***************************************************************/
45
46 BOOL initialize_password_db(BOOL reload)
47 {       
48         /* 
49          * This function is unfinished right now, so just 
50          * ignore the details and always return True.  It 
51          * is here only as a placeholder          --jerry 
52          */
53         return True;
54         
55 }
56
57 /*************************************************************
58  Initialises a struct sam_disp_info.
59  **************************************************************/
60
61 static void pdb_init_dispinfo(struct sam_disp_info *user)
62 {
63         if (user == NULL) 
64                 return;
65         ZERO_STRUCTP(user);
66 }
67
68 /*************************************************************
69  Alloc memory and initialises a struct sam_passwd.
70  ************************************************************/
71
72 BOOL pdb_init_sam(SAM_ACCOUNT **user)
73 {
74         if (*user != NULL) {
75                 DEBUG(0,("pdb_init_sam: SAM_ACCOUNT was non NULL\n"));
76 #if 0
77                 smb_panic("NULL pointer passed to pdb_init_sam\n");
78 #endif
79                 return False;
80         }
81         
82         *user=(SAM_ACCOUNT *)malloc(sizeof(SAM_ACCOUNT));
83         
84         if (*user==NULL) {
85                 DEBUG(0,("pdb_init_sam: error while allocating memory\n"));
86                 return False;
87         }
88         
89         ZERO_STRUCTP(*user);
90
91         (*user)->logon_time            = (time_t)0;
92         (*user)->logoff_time           = (time_t)-1;
93         (*user)->kickoff_time          = (time_t)-1;
94         (*user)->pass_last_set_time    = (time_t)-1;
95         (*user)->pass_can_change_time  = (time_t)-1;
96         (*user)->pass_must_change_time = (time_t)-1;
97
98         (*user)->unknown_3 = 0x00ffffff;        /* don't know */
99         (*user)->logon_divs = 168;      /* hours per week */
100         (*user)->hours_len = 21;                /* 21 times 8 bits = 168 */
101         memset((*user)->hours, 0xff, (*user)->hours_len); /* available at all hours */
102         (*user)->unknown_5 = 0x00000000; /* don't know */
103         (*user)->unknown_6 = 0x000004ec; /* don't know */
104         
105         return True;
106 }
107
108 /************************************************************
109  Free the SAM_ACCOUNT and the NT/LM hashes.
110  ***********************************************************/
111
112 BOOL pdb_free_sam(SAM_ACCOUNT *user)
113 {
114         if (user == NULL) {
115                 DEBUG(0,("pdb_free_sam: SAM_ACCOUNT was NULL\n"));
116 #if 0
117                 smb_panic("NULL pointer passed to pdb_free_sam\n");
118 #endif
119                 return False;
120         }
121
122         SAFE_FREE(user->nt_pw);
123         SAFE_FREE(user->lm_pw);
124         SAFE_FREE(user);
125         
126         return True;    
127 }
128
129 /************************************************************
130  Reset the SAM_ACCOUNT and the NT/LM hashes.
131  ***********************************************************/
132
133 BOOL pdb_reset_sam(SAM_ACCOUNT *user)
134 {
135         if (user == NULL) {
136                 DEBUG(0,("pdb_reset_sam: SAM_ACCOUNT was NULL\n"));
137                 return False;
138         }
139         
140         SAFE_FREE(user->nt_pw);
141         SAFE_FREE(user->lm_pw);
142         ZERO_STRUCTP(user);
143
144         return True;
145 }
146
147 /*************************************************************************
148  Routine to return the next entry in the sam passwd list.
149  *************************************************************************/
150
151 struct sam_disp_info *pdb_sam_to_dispinfo(SAM_ACCOUNT *user)
152 {
153         static struct sam_disp_info disp_info;
154
155         if (user == NULL) 
156                 return NULL;
157
158         pdb_init_dispinfo(&disp_info);
159
160         disp_info.smb_name  = user->username;
161         disp_info.full_name = user->full_name;
162         disp_info.user_rid  = user->user_rid;
163
164         return &disp_info;
165 }
166
167 /**********************************************************
168  Encode the account control bits into a string.
169  length = length of string to encode into (including terminating
170  null). length *MUST BE MORE THAN 2* !
171  **********************************************************/
172
173 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
174 {
175         static fstring acct_str;
176         size_t i = 0;
177
178         acct_str[i++] = '[';
179
180         if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
181         if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
182         if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
183         if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
184         if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
185         if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
186         if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
187         if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
188         if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
189         if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
190         if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
191
192         for ( ; i < length - 2 ; i++ )
193                 acct_str[i] = ' ';
194
195         i = length - 2;
196         acct_str[i++] = ']';
197         acct_str[i++] = '\0';
198
199         return acct_str;
200 }     
201
202 /**********************************************************
203  Decode the account control bits from a string.
204  **********************************************************/
205
206 uint16 pdb_decode_acct_ctrl(const char *p)
207 {
208         uint16 acct_ctrl = 0;
209         BOOL finished = False;
210
211         /*
212          * Check if the account type bits have been encoded after the
213          * NT password (in the form [NDHTUWSLXI]).
214          */
215
216         if (*p != '[')
217                 return 0;
218
219         for (p++; *p && !finished; p++) {
220                 switch (*p) {
221                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
222                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
223                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
224                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
225                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
226                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
227                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
228                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
229                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
230                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
231                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
232             case ' ': { break; }
233                         case ':':
234                         case '\n':
235                         case '\0': 
236                         case ']':
237                         default:  { finished = True; }
238                 }
239         }
240
241         return acct_ctrl;
242 }
243
244 /*************************************************************
245  Routine to set 32 hex password characters from a 16 byte array.
246 **************************************************************/
247
248 void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl)
249 {
250         if (pwd != NULL) {
251                 int i;
252                 for (i = 0; i < 16; i++)
253                         slprintf(&p[i*2], 3, "%02X", pwd[i]);
254         } else {
255                 if (acct_ctrl & ACB_PWNOTREQ)
256                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
257                 else
258                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
259         }
260 }
261
262 /*************************************************************
263  Routine to get the 32 hex characters and turn them
264  into a 16 byte array.
265 **************************************************************/
266
267 BOOL pdb_gethexpwd(char *p, unsigned char *pwd)
268 {
269         int i;
270         unsigned char   lonybble, hinybble;
271         char           *hexchars = "0123456789ABCDEF";
272         char           *p1, *p2;
273         
274         if (!p)
275                 return (False);
276         
277         for (i = 0; i < 32; i += 2) {
278                 hinybble = toupper(p[i]);
279                 lonybble = toupper(p[i + 1]);
280
281                 p1 = strchr(hexchars, hinybble);
282                 p2 = strchr(hexchars, lonybble);
283
284                 if (!p1 || !p2)
285                         return (False);
286
287                 hinybble = PTR_DIFF(p1, hexchars);
288                 lonybble = PTR_DIFF(p2, hexchars);
289
290                 pwd[i / 2] = (hinybble << 4) | lonybble;
291         }
292         return (True);
293 }
294
295 /*******************************************************************
296  Group and User RID username mapping function
297  ********************************************************************/
298
299 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
300 {
301         struct passwd *pw = Get_Pwnam(user_name, False);
302
303         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
304                 return False;
305
306         if (!pw) {
307                 DEBUG(1,("Username %s is invalid on this system\n", user_name));
308                 return False;
309         }
310
311         /* turn the unix UID into a Domain RID.  this is what the posix
312            sub-system does (adds 1000 to the uid) */
313         *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
314
315         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
316         *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
317
318         return True;
319 }
320
321 /*******************************************************************
322  Converts NT user RID to a UNIX uid.
323  ********************************************************************/
324
325 uid_t pdb_user_rid_to_uid(uint32 user_rid)
326 {
327         return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
328 }
329
330 /*******************************************************************
331  Converts NT user RID to a UNIX gid.
332  ********************************************************************/
333
334 gid_t pdb_user_rid_to_gid(uint32 user_rid)
335 {
336         return (uid_t)(((user_rid & (~GROUP_RID_TYPE))- 1000)/RID_MULTIPLIER);
337 }
338
339 /*******************************************************************
340  converts UNIX uid to an NT User RID.
341  ********************************************************************/
342
343 uint32 pdb_uid_to_user_rid(uid_t uid)
344 {
345         return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
346 }
347
348 /*******************************************************************
349  converts NT Group RID to a UNIX uid.
350  ********************************************************************/
351
352 uint32 pdb_gid_to_group_rid(gid_t gid)
353 {
354   return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
355 }
356
357 /*******************************************************************
358  Decides if a RID is a well known RID.
359  ********************************************************************/
360
361 static BOOL pdb_rid_is_well_known(uint32 rid)
362 {
363   return (rid < 1000);
364 }
365
366 /*******************************************************************
367  Decides if a RID is a user or group RID.
368  ********************************************************************/
369
370 BOOL pdb_rid_is_user(uint32 rid)
371 {
372   /* lkcl i understand that NT attaches an enumeration to a RID
373    * such that it can be identified as either a user, group etc
374    * type.  there are 5 such categories, and they are documented.
375    */
376    if(pdb_rid_is_well_known(rid)) {
377       /*
378        * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
379        * and DOMAIN_USER_RID_GUEST.
380        */
381      if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
382        return True;
383    } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {
384      return True;
385    }
386    return False;
387 }
388
389 /*******************************************************************
390  Convert a rid into a name. Used in the lookup SID rpc.
391  ********************************************************************/
392
393 BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
394 {
395         BOOL is_user = pdb_rid_is_user(rid);
396
397         DEBUG(5,("local_lookup_rid: looking up %s RID %u.\n", is_user ? "user" :
398                         "group", (unsigned int)rid));
399
400         if(is_user) {
401                 if(rid == DOMAIN_USER_RID_ADMIN) {
402                         pstring admin_users;
403                         char *p = admin_users;
404                         if(!next_token(&p, name, NULL, sizeof(fstring)))
405                                 fstrcpy(name, "Administrator");
406                 } else if (rid == DOMAIN_USER_RID_GUEST) {
407                         pstring guest_users;
408                         char *p = guest_users;
409                         if(!next_token(&p, name, NULL, sizeof(fstring)))
410                                 fstrcpy(name, "Guest");
411                 } else {
412                         uid_t uid;
413                         struct passwd *pass;
414                         
415                         /*
416                          * Don't try to convert the rid to a name if 
417                          * running in appliance mode
418                          */
419                         if (lp_hide_local_users())
420                                 return False;
421                         
422                         uid = pdb_user_rid_to_uid(rid);
423                         pass = sys_getpwuid(uid);
424
425                         *psid_name_use = SID_NAME_USER;
426
427                         DEBUG(5,("local_lookup_rid: looking up uid %u %s\n", (unsigned int)uid,
428                                 pass ? "succeeded" : "failed" ));
429
430                         if(!pass) {
431                                 slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid);
432                                 return True;
433                         }
434
435                         fstrcpy(name, pass->pw_name);
436
437                         DEBUG(5,("local_lookup_rid: found user %s for rid %u\n", name,
438                                 (unsigned int)rid ));
439                 }
440
441         } else {
442                 gid_t gid;
443                 struct group *gr; 
444
445                 /* 
446                  * Don't try to convert the rid to a name if running
447                  * in appliance mode
448                  */
449                 
450                 if (lp_hide_local_users()) 
451                         return False;
452                 
453                 gid = pdb_user_rid_to_gid(rid);
454                 gr = getgrgid(gid);
455
456                 *psid_name_use = SID_NAME_ALIAS;
457
458                 DEBUG(5,("local_local_rid: looking up gid %u %s\n", (unsigned int)gid,
459                         gr ? "succeeded" : "failed" ));
460
461                 if(!gr) {
462                         slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid);
463                         return True;
464                 }
465
466                 fstrcpy( name, gr->gr_name);
467
468                 DEBUG(5,("local_lookup_rid: found group %s for rid %u\n", name,
469                         (unsigned int)rid ));
470         }
471
472         return True;
473 }
474
475 /*******************************************************************
476  Convert a name into a SID. Used in the lookup name rpc.
477  ********************************************************************/
478
479 BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psid_name_use)
480 {
481         extern DOM_SID global_sid_World_Domain;
482         struct passwd *pass = NULL;
483         DOM_SID local_sid;
484         fstring user;
485         fstring domain;
486
487         /*
488          * domain and user may be quoted const strings, and map_username and
489          * friends can modify them. Make a modifiable copy. JRA.
490          */
491
492         fstrcpy(domain, c_domain);
493         fstrcpy(user, c_user);
494
495         sid_copy(&local_sid, &global_sam_sid);
496
497         /*
498          * Special case for MACHINE\Everyone. Map to the world_sid.
499          */
500
501         if(strequal(user, "Everyone")) {
502                 sid_copy( psid, &global_sid_World_Domain);
503                 sid_append_rid(psid, 0);
504                 *psid_name_use = SID_NAME_ALIAS;
505                 return True;
506         }
507
508         /* 
509          * Don't lookup local unix users if running in appliance mode
510          */
511         if (lp_hide_local_users()) 
512                 return False;
513
514         (void)map_username(user);
515
516         if((pass = Get_Pwnam(user, False))) {
517                 sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
518                 *psid_name_use = SID_NAME_USER;
519         } else {
520                 /*
521                  * Maybe it was a group ?
522                  */
523                 struct group *grp = getgrnam(user);
524
525                 if(!grp)
526                         return False;
527
528                 sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid));
529                 *psid_name_use = SID_NAME_ALIAS;
530         }
531
532         sid_copy( psid, &local_sid);
533
534         return True;
535 }
536
537 /****************************************************************************
538  Convert a uid to SID - locally.
539 ****************************************************************************/
540
541 DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
542 {
543         extern DOM_SID global_sam_sid;
544
545         sid_copy(psid, &global_sam_sid);
546         sid_append_rid(psid, pdb_uid_to_user_rid(uid));
547
548         return psid;
549 }
550
551 /****************************************************************************
552  Convert a SID to uid - locally.
553 ****************************************************************************/
554
555 BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type)
556 {
557         extern DOM_SID global_sam_sid;
558
559         DOM_SID dom_sid;
560         uint32 rid;
561         fstring str;
562         struct passwd *pass;
563
564         *name_type = SID_NAME_UNKNOWN;
565
566         sid_copy(&dom_sid, psid);
567         sid_split_rid(&dom_sid, &rid);
568
569         if (!pdb_rid_is_user(rid))
570                 return False;
571
572         /*
573          * We can only convert to a uid if this is our local
574          * Domain SID (ie. we are the controling authority).
575          */
576         if (!sid_equal(&global_sam_sid, &dom_sid))
577                 return False;
578
579         *puid = pdb_user_rid_to_uid(rid);
580
581         /*
582          * Ensure this uid really does exist.
583          */
584         if(!(pass = sys_getpwuid(*puid)))
585                 return False;
586
587         DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid),
588                 (unsigned int)*puid, pass->pw_name ));
589
590         return True;
591 }
592
593 /****************************************************************************
594  Convert a gid to SID - locally.
595 ****************************************************************************/
596
597 DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
598 {
599     extern DOM_SID global_sam_sid;
600
601         sid_copy(psid, &global_sam_sid);
602         sid_append_rid(psid, pdb_gid_to_group_rid(gid));
603
604         return psid;
605 }
606
607 /****************************************************************************
608  Convert a SID to gid - locally.
609 ****************************************************************************/
610
611 BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type)
612 {
613     extern DOM_SID global_sam_sid;
614         DOM_SID dom_sid;
615         uint32 rid;
616         fstring str;
617         struct group *grp;
618
619         *name_type = SID_NAME_UNKNOWN;
620
621         sid_copy(&dom_sid, psid);
622         sid_split_rid(&dom_sid, &rid);
623
624         /*
625          * We can only convert to a gid if this is our local
626          * Domain SID (ie. we are the controling authority).
627          */
628
629         if (!sid_equal(&global_sam_sid, &dom_sid))
630                 return False;
631
632         if (pdb_rid_is_user(rid))
633                 return False;
634
635         *pgid = pdb_user_rid_to_gid(rid);
636
637         /*
638          * Ensure this gid really does exist.
639          */
640
641         if(!(grp = getgrgid(*pgid)))
642                 return False;
643
644         DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u) (%s).\n", sid_to_string( str, psid),
645                 (unsigned int)*pgid, grp->gr_name ));
646
647         return True;
648 }
649
650 static void select_name(pstring string, const UNISTR2 *from)
651 {
652         if (from->buffer != 0)
653                 unistr2_to_ascii(string, from, sizeof(*string));
654 }
655
656 /*************************************************************
657  Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
658  **************************************************************/
659
660 void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
661 {
662
663         if (from == NULL || to == NULL) 
664                 return;
665
666         to->logon_time = nt_time_to_unix(&from->logon_time);
667         to->logoff_time = nt_time_to_unix(&from->logoff_time);
668         to->kickoff_time = nt_time_to_unix(&from->kickoff_time);
669         to->pass_last_set_time = nt_time_to_unix(&from->pass_last_set_time);
670         to->pass_can_change_time = nt_time_to_unix(&from->pass_can_change_time);
671         to->pass_must_change_time = nt_time_to_unix(&from->pass_must_change_time);
672
673         select_name(to->username    , &from->uni_user_name   );
674         select_name(to->full_name   , &from->uni_full_name   );
675         select_name(to->home_dir    , &from->uni_home_dir    );
676         select_name(to->dir_drive   , &from->uni_dir_drive   );
677         select_name(to->logon_script, &from->uni_logon_script);
678         select_name(to->profile_path, &from->uni_profile_path);
679         select_name(to->acct_desc   , &from->uni_acct_desc   );
680         select_name(to->workstations, &from->uni_workstations);
681         select_name(to->unknown_str , &from->uni_unknown_str );
682         select_name(to->munged_dial , &from->uni_munged_dial );
683
684         to->user_rid = from->user_rid;
685         to->group_rid = from->group_rid;
686
687         to->acct_ctrl = from->acb_info;
688         to->unknown_3 = from->unknown_3;
689
690         to->logon_divs = from->logon_divs;
691         to->hours_len = from->logon_hrs.len;
692         memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN);
693
694         to->unknown_5 = from->unknown_5;
695         to->unknown_6 = from->unknown_6;
696 }
697
698 /*************************************************************
699  Copies a sam passwd.
700  **************************************************************/
701
702 void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
703 {
704         if (from == NULL || to == NULL) 
705                 return;
706
707         to->logon_time = nt_time_to_unix(&from->logon_time);
708         to->logoff_time = nt_time_to_unix(&from->logoff_time);
709         to->kickoff_time = nt_time_to_unix(&from->kickoff_time);
710         to->pass_last_set_time = nt_time_to_unix(&from->pass_last_set_time);
711         to->pass_can_change_time = nt_time_to_unix(&from->pass_can_change_time);
712         to->pass_must_change_time = nt_time_to_unix(&from->pass_must_change_time);
713
714         select_name(to->username    , &from->uni_user_name   );
715         select_name(to->full_name   , &from->uni_full_name   );
716         select_name(to->home_dir    , &from->uni_home_dir    );
717         select_name(to->dir_drive   , &from->uni_dir_drive   );
718         select_name(to->logon_script, &from->uni_logon_script);
719         select_name(to->profile_path, &from->uni_profile_path);
720         select_name(to->acct_desc   , &from->uni_acct_desc   );
721         select_name(to->workstations, &from->uni_workstations);
722         select_name(to->unknown_str , &from->uni_unknown_str );
723         select_name(to->munged_dial , &from->uni_munged_dial );
724
725         to->user_rid = from->user_rid;
726         to->group_rid = from->group_rid;
727         
728         /* FIXME!!  Do we need to copy the passwords here as well?
729            I don't know.  Need to figure this out   --jerry */
730
731         to->acct_ctrl = from->acb_info;
732         to->unknown_3 = from->unknown_3;
733
734         to->logon_divs = from->logon_divs;
735         to->hours_len = from->logon_hrs.len;
736         memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN);
737
738         to->unknown_5 = from->unknown_5;
739         to->unknown_6 = from->unknown_6;
740 }
741
742 /*************************************************************
743  Copies a SAM_ACCOUNT.
744  **************************************************************/
745
746 void copy_sam_passwd(SAM_ACCOUNT *to, const SAM_ACCOUNT *from)
747 {
748         if (!from || !to)
749                 return;
750
751         memcpy(to, from, sizeof(SAM_ACCOUNT));
752 }
753
754 /*************************************************************
755  Change a password entry in the local smbpasswd file.
756
757  FIXME!!  The function needs to be abstracted into the
758  passdb interface or something.  It is currently being called
759  by _api_samr_create_user() in rpc_server/srv_samr.c
760  
761  --jerry
762  *************************************************************/
763
764 BOOL local_password_change(char *user_name, int local_flags,
765                            char *new_passwd, 
766                            char *err_str, size_t err_str_len,
767                            char *msg_str, size_t msg_str_len)
768 {
769         struct passwd  *pwd = NULL;
770         SAM_ACCOUNT     *sam_pass=NULL;
771         SAM_ACCOUNT     *new_sam_acct=NULL;
772
773         *err_str = '\0';
774         *msg_str = '\0';
775
776         if (local_flags & LOCAL_ADD_USER) {
777         
778                 /*
779                  * Check for a local account - if we're adding only.
780                  */
781         
782                 if(!(pwd = sys_getpwnam(user_name))) {
783                         slprintf(err_str, err_str_len - 1, "User %s does not \
784 exist in system password file (usually /etc/passwd). Cannot add \
785 account without a valid local system user.\n", user_name);
786                         return False;
787                 }
788         }
789
790         /* Get the smb passwd entry for this user */
791         pdb_init_sam(&sam_pass);
792         if(!pdb_getsampwnam(sam_pass, user_name)) {
793                 pdb_free_sam(sam_pass);
794                 
795                 if(!(local_flags & LOCAL_ADD_USER)) {
796                         slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
797                         return False;
798                 }
799
800                 /* create the SAM_ACCOUNT struct and call pdb_add_sam_account.
801                    Because the new_sam_pwd only exists in the scope of this function
802                    we will not allocate memory for members */
803                 pdb_init_sam(&new_sam_acct);
804                 pdb_set_username(new_sam_acct, user_name);
805                 pdb_set_fullname(new_sam_acct, pwd->pw_gecos);
806                 pdb_set_uid(new_sam_acct, pwd->pw_uid);
807                 pdb_set_gid(new_sam_acct, pwd->pw_gid);
808                 pdb_set_pass_last_set_time(new_sam_acct, time(NULL));
809                 pdb_set_profile_path(new_sam_acct, lp_logon_path());
810                 pdb_set_homedir(new_sam_acct, lp_logon_home());
811                 pdb_set_dir_drive(new_sam_acct, lp_logon_drive());
812                 pdb_set_logon_script(new_sam_acct, lp_logon_script());
813
814                 /* set account flags */
815                 pdb_set_acct_ctrl(new_sam_acct,((local_flags & LOCAL_TRUST_ACCOUNT) ? ACB_WSTRUST : ACB_NORMAL) );
816
817                 if (local_flags & LOCAL_DISABLE_USER)
818                         pdb_set_acct_ctrl (new_sam_acct, pdb_get_acct_ctrl(new_sam_acct)|ACB_DISABLED);
819
820                 if (local_flags & LOCAL_SET_NO_PASSWORD)
821                         pdb_set_acct_ctrl (new_sam_acct, pdb_get_acct_ctrl(new_sam_acct)|ACB_PWNOTREQ);
822                 else {
823                         /* set the passwords here.  if we get to here it means
824                            we have a valid, active account */
825                         pdb_set_plaintext_passwd (new_sam_acct, new_passwd);
826                 }
827
828                 if (pdb_add_sam_account(new_sam_acct)) {
829                         slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
830                         pdb_free_sam(new_sam_acct);
831                         return True;
832                 } else {
833                         slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
834                         pdb_free_sam(new_sam_acct);
835                         return False;
836                 }
837         } else {
838                 /* the entry already existed */
839                 local_flags &= ~LOCAL_ADD_USER;
840         }
841
842         /*
843          * We are root - just write the new password
844          * and the valid last change time.
845          */
846
847         if(local_flags & LOCAL_DISABLE_USER) {
848                 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED);
849         } else if (local_flags & LOCAL_ENABLE_USER) {
850                 if(pdb_get_lanman_passwd(sam_pass) == NULL) {
851                         pdb_set_plaintext_passwd (new_sam_acct, new_passwd);
852                 }
853                 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED));
854         } else if (local_flags & LOCAL_SET_NO_PASSWORD) {
855                 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ);
856                 
857                 /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */
858                 pdb_set_lanman_passwd (sam_pass, NULL);
859                 pdb_set_nt_passwd     (sam_pass, NULL);
860         } else {
861                 /*
862                  * If we're dealing with setting a completely empty user account
863                  * ie. One with a password of 'XXXX', but not set disabled (like
864                  * an account created from scratch) then if the old password was
865                  * 'XX's then getsmbpwent will have set the ACB_DISABLED flag.
866                  * We remove that as we're giving this user their first password
867                  * and the decision hasn't really been made to disable them (ie.
868                  * don't create them disabled). JRA.
869                  */
870                 if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED))
871                         pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED));
872                 pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ));
873                 pdb_set_plaintext_passwd (new_sam_acct, new_passwd);
874         }
875         
876         if(local_flags & LOCAL_DELETE_USER) {
877                 if (!pdb_delete_sam_account(user_name)) {
878                         slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
879                         pdb_free_sam(sam_pass);
880                         return False;
881                 }
882                 slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
883         } else {
884                 if(!pdb_update_sam_account(sam_pass, True)) {
885                         slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
886                         pdb_free_sam(sam_pass);
887                         return False;
888                 }
889                 if(local_flags & LOCAL_DISABLE_USER)
890                         slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
891                 else if (local_flags & LOCAL_ENABLE_USER)
892                         slprintf(msg_str, msg_str_len-1, "Enabled user %s.\n", user_name);
893                 else if (local_flags & LOCAL_SET_NO_PASSWORD)
894                         slprintf(msg_str, msg_str_len-1, "User %s password set to none.\n", user_name);
895         }
896
897         pdb_free_sam(sam_pass);
898         return True;
899 }
900
901 /*********************************************************************
902  Collection of get...() functions for SAM_ACCOUNT_INFO.
903  ********************************************************************/
904
905 uint16 pdb_get_acct_ctrl (SAM_ACCOUNT *sampass)
906 {
907         if (sampass)
908                 return (sampass->acct_ctrl);
909         else
910                 return (ACB_DISABLED);
911 }
912
913 time_t pdb_get_logon_time (SAM_ACCOUNT *sampass)
914 {
915         if (sampass)
916                 return (sampass->logon_time);
917         else
918                 return (0);
919 }
920
921 time_t pdb_get_logoff_time (SAM_ACCOUNT *sampass)
922 {
923         if (sampass)
924                 return (sampass->logoff_time);
925         else
926                 return (-1);
927 }
928
929 time_t pdb_get_kickoff_time (SAM_ACCOUNT *sampass)
930 {
931         if (sampass)
932                 return (sampass->kickoff_time);
933         else
934                 return (-1);
935 }
936
937 time_t pdb_get_pass_last_set_time (SAM_ACCOUNT *sampass)
938 {
939         if (sampass)
940                 return (sampass->pass_last_set_time);
941         else
942                 return (-1);
943 }
944
945 time_t pdb_get_pass_can_change_time (SAM_ACCOUNT *sampass)
946 {
947         if (sampass)
948                 return (sampass->pass_can_change_time);
949         else
950                 return (-1);
951 }
952
953 time_t pdb_get_pass_must_change_time (SAM_ACCOUNT *sampass)
954 {
955         if (sampass)
956                 return (sampass->pass_must_change_time);
957         else
958                 return (-1);
959 }
960
961 uint16 pdb_get_logon_divs (SAM_ACCOUNT *sampass)
962 {
963         if (sampass)
964                 return (sampass->logon_divs);
965         else
966                 return (-1);
967 }
968
969 uint32 pdb_get_hours_len (SAM_ACCOUNT *sampass)
970 {
971         if (sampass)
972                 return (sampass->hours_len);
973         else
974                 return (-1);
975 }
976
977 uint8* pdb_get_hours (SAM_ACCOUNT *sampass)
978 {
979         if (sampass)
980                 return (sampass->hours);
981         else
982                 return (NULL);
983 }
984
985 uint8* pdb_get_nt_passwd (SAM_ACCOUNT *sampass)
986 {
987         if (sampass)
988                 return (sampass->nt_pw);
989         else
990                 return (NULL);
991 }
992
993 uint8* pdb_get_lanman_passwd (SAM_ACCOUNT *sampass)
994 {
995         if (sampass)
996                 return (sampass->lm_pw);
997         else
998                 return (NULL);
999 }
1000
1001 uint32 pdb_get_user_rid (SAM_ACCOUNT *sampass)
1002 {
1003         if (sampass)
1004                 return (sampass->user_rid);
1005         else
1006                 return (-1);
1007 }
1008
1009 uint32 pdb_get_group_rid (SAM_ACCOUNT *sampass)
1010 {
1011         if (sampass)
1012                 return (sampass->group_rid);
1013         else
1014                 return (-1);
1015 }
1016
1017 uid_t pdb_get_uid (SAM_ACCOUNT *sampass)
1018 {
1019         if (sampass)
1020                 return (sampass->uid);
1021         else
1022                 return ((uid_t)-1);
1023 }
1024
1025 gid_t pdb_get_gid (SAM_ACCOUNT *sampass)
1026 {
1027         if (sampass)
1028                 return (sampass->gid);
1029         else
1030                 return ((gid_t)-1);
1031 }
1032
1033 char* pdb_get_username (SAM_ACCOUNT *sampass)
1034 {
1035         if (sampass)
1036                 return (sampass->username);
1037         else
1038                 return (NULL);
1039 }
1040
1041 char* pdb_get_domain (SAM_ACCOUNT *sampass)
1042 {
1043         if (sampass)
1044                 return (sampass->domain);
1045         else
1046                 return (NULL);
1047 }
1048
1049 char* pdb_get_nt_username (SAM_ACCOUNT *sampass)
1050 {
1051         if (sampass)
1052                 return (sampass->nt_username);
1053         else
1054                 return (NULL);
1055 }
1056
1057 char* pdb_get_fullname (SAM_ACCOUNT *sampass)
1058 {
1059         if (sampass)
1060                 return (sampass->full_name);
1061         else
1062                 return (NULL);
1063 }
1064
1065 char* pdb_get_homedir (SAM_ACCOUNT *sampass)
1066 {
1067         if (sampass)
1068                 return (sampass->home_dir);
1069         else
1070                 return (NULL);
1071 }
1072
1073 char* pdb_get_dirdrive (SAM_ACCOUNT *sampass)
1074 {
1075         if (sampass)
1076                 return (sampass->dir_drive);
1077         else
1078                 return (NULL);
1079 }
1080
1081 char* pdb_get_logon_script (SAM_ACCOUNT *sampass)
1082 {
1083         if (sampass)
1084                 return (sampass->logon_script);
1085         else
1086                 return (NULL);
1087 }
1088
1089 char* pdb_get_profile_path (SAM_ACCOUNT *sampass)
1090 {
1091         if (sampass)
1092                 return (sampass->profile_path);
1093         else
1094                 return (NULL);
1095 }
1096
1097 char* pdb_get_acct_desc (SAM_ACCOUNT *sampass)
1098 {
1099         if (sampass)
1100                 return (sampass->acct_desc);
1101         else
1102                 return (NULL);
1103 }
1104
1105 char* pdb_get_workstations (SAM_ACCOUNT *sampass)
1106 {
1107         if (sampass)
1108                 return (sampass->workstations);
1109         else
1110                 return (NULL);
1111 }
1112
1113 char* pdb_get_munged_dial (SAM_ACCOUNT *sampass)
1114 {
1115         if (sampass)
1116                 return (sampass->munged_dial);
1117         else
1118                 return (NULL);
1119 }
1120
1121 uint32 pdb_get_unknown3 (SAM_ACCOUNT *sampass)
1122 {
1123         if (sampass)
1124                 return (sampass->unknown_3);
1125         else
1126                 return (-1);
1127 }
1128
1129 uint32 pdb_get_unknown5 (SAM_ACCOUNT *sampass)
1130 {
1131         if (sampass)
1132                 return (sampass->unknown_5);
1133         else
1134                 return (-1);
1135 }
1136
1137 uint32 pdb_get_unknown6 (SAM_ACCOUNT *sampass)
1138 {
1139         if (sampass)
1140                 return (sampass->unknown_6);
1141         else
1142                 return (-1);
1143 }
1144
1145 /*********************************************************************
1146  Collection of set...() functions for SAM_ACCOUNT_INFO.
1147  ********************************************************************/
1148
1149 BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 flags)
1150 {
1151         if (!sampass)
1152                 return False;
1153                 
1154         if (sampass) {
1155                 sampass->acct_ctrl = flags;
1156                 return True;
1157         }
1158         
1159         return False;
1160 }
1161
1162 BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime)
1163 {
1164         if (!sampass)
1165                 return False;
1166
1167         sampass->logon_time = mytime;
1168         return True;
1169 }
1170
1171 BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime)
1172 {
1173         if (!sampass)
1174                 return False;
1175
1176         sampass->logoff_time = mytime;
1177         return True;
1178 }
1179
1180 BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime)
1181 {
1182         if (!sampass)
1183                 return False;
1184
1185         sampass->kickoff_time = mytime;
1186         return True;
1187 }
1188
1189 BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime)
1190 {
1191         if (!sampass)
1192                 return False;
1193
1194         sampass->pass_can_change_time = mytime;
1195         return True;
1196 }
1197
1198 BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime)
1199 {
1200         if (!sampass)
1201                 return False;
1202
1203         sampass->pass_must_change_time = mytime;
1204         return True;
1205 }
1206
1207 BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime)
1208 {
1209         if (!sampass)
1210                 return False;
1211
1212         sampass->pass_last_set_time = mytime;
1213         return True;
1214 }
1215
1216 BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len)
1217 {
1218         if (!sampass)
1219                 return False;
1220
1221         sampass->hours_len = len;
1222         return True;
1223 }
1224
1225 BOOL pdb_set_logons_divs (SAM_ACCOUNT *sampass, uint16 hours)
1226 {
1227         if (!sampass)
1228                 return False;
1229
1230         sampass->logon_divs = hours;
1231         return True;
1232 }
1233
1234 BOOL pdb_set_uid (SAM_ACCOUNT *sampass, uid_t uid)
1235 {
1236         if (!sampass)
1237                 return False;
1238
1239         sampass->uid = uid;
1240         return True;
1241 }
1242
1243 BOOL pdb_set_gid (SAM_ACCOUNT *sampass, gid_t gid)
1244 {
1245         if (!sampass)
1246                 return False;
1247
1248         sampass->gid = gid;
1249         return True;
1250 }
1251
1252 BOOL pdb_set_user_rid (SAM_ACCOUNT *sampass, uint32 rid)
1253 {
1254         if (!sampass)
1255                 return False;
1256
1257         sampass->user_rid = rid;
1258         return True;
1259 }
1260
1261 BOOL pdb_set_group_rid (SAM_ACCOUNT *sampass, uint32 grid)
1262 {
1263         if (!sampass)
1264                 return False;
1265
1266         sampass->group_rid = grid;
1267         return True;
1268 }
1269
1270 /*********************************************************************
1271  Set the user's UNIX name.
1272  ********************************************************************/
1273
1274 BOOL pdb_set_username(SAM_ACCOUNT *sampass, char *username)
1275 {       
1276         if (!sampass)
1277                 return False;
1278         *sampass->username = '\0';
1279         if (!username)
1280                 return False;
1281
1282         StrnCpy (sampass->username, username, strlen(username));
1283
1284         return True;
1285 }
1286
1287 /*********************************************************************
1288  Set the domain name.
1289  ********************************************************************/
1290
1291 BOOL pdb_set_domain(SAM_ACCOUNT *sampass, char *domain)
1292 {       
1293         if (!sampass)
1294                 return False;
1295         *sampass->domain = '\0';
1296         if (!domain)
1297                 return False;
1298
1299         StrnCpy (sampass->domain, domain, strlen(domain));
1300
1301         return True;
1302 }
1303
1304 /*********************************************************************
1305  Set the user's NT name.
1306  ********************************************************************/
1307
1308 BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, char *nt_username)
1309 {
1310         if (!sampass)
1311                 return False;
1312         *sampass->nt_username = '\0';
1313         if (!nt_username)
1314                 return False;
1315
1316         StrnCpy (sampass->nt_username, nt_username, strlen(nt_username));
1317
1318         return True;
1319 }
1320
1321 /*********************************************************************
1322  Set the user's full name.
1323  ********************************************************************/
1324
1325 BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, char *fullname)
1326 {
1327         if (!sampass)
1328                 return False;
1329         *sampass->full_name = '\0';
1330         if (!fullname)
1331                 return False;
1332
1333         StrnCpy (sampass->full_name, fullname, strlen(fullname));
1334
1335         return True;
1336 }
1337
1338 /*********************************************************************
1339  Set the user's logon script.
1340  ********************************************************************/
1341
1342 BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, char *logon_script)
1343 {
1344         if (!sampass)
1345                 return False;
1346         *sampass->logon_script = '\0';
1347         if (!logon_script)
1348                 return False;
1349
1350         StrnCpy (sampass->logon_script, logon_script, strlen(logon_script));
1351
1352         return True;
1353 }
1354
1355 /*********************************************************************
1356  Set the user's profile path.
1357  ********************************************************************/
1358
1359 BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, char *profile_path)
1360 {
1361         if (!sampass)
1362                 return False;
1363         *sampass->profile_path = '\0';
1364         if (!profile_path)
1365                 return False;
1366         
1367         StrnCpy (sampass->profile_path, profile_path, strlen(profile_path));
1368         
1369         return True;
1370 }
1371
1372 /*********************************************************************
1373  Set the user's directory drive.
1374  ********************************************************************/
1375
1376 BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, char *dir_drive)
1377 {
1378         if (!sampass)
1379                 return False;
1380         *sampass->dir_drive = '\0';
1381         if (!dir_drive)
1382                 return False;
1383
1384         StrnCpy (sampass->dir_drive, dir_drive, strlen(dir_drive));
1385
1386         return True;
1387 }
1388
1389 /*********************************************************************
1390  Set the user's home directory.
1391  ********************************************************************/
1392
1393 BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, char *homedir)
1394 {
1395         if (!sampass)
1396                 return False;
1397         *sampass->home_dir = '\0';
1398         if (!homedir)
1399                 return False;
1400         
1401         StrnCpy (sampass->home_dir, homedir, strlen(homedir));
1402
1403         return True;
1404 }
1405
1406 /*********************************************************************
1407  Set the user's account description.
1408  ********************************************************************/
1409
1410 BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, char *acct_desc)
1411 {
1412         if (!sampass)
1413                 return False;
1414         *sampass->acct_desc = '\0';
1415         if (!acct_desc)
1416                 return False;
1417         
1418         StrnCpy (sampass->acct_desc, acct_desc, strlen(acct_desc));
1419
1420         return True;
1421 }
1422
1423 /*********************************************************************
1424  Set the user's workstation allowed list.
1425  ********************************************************************/
1426
1427 BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, char *workstations)
1428 {
1429         if (!sampass)
1430                 return False;
1431         *sampass->workstations = '\0';
1432         if (!workstations)
1433                 return False;
1434
1435         StrnCpy (sampass->workstations, workstations, strlen(workstations));
1436
1437         return True;
1438 }
1439
1440 /*********************************************************************
1441  Set the user's dial string.
1442  ********************************************************************/
1443
1444 BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, char *munged_dial)
1445 {
1446         if (!sampass)
1447                 return False;
1448         *sampass->munged_dial = '\0';
1449         if (!munged_dial)
1450                 return False;
1451
1452         StrnCpy (sampass->munged_dial, munged_dial, strlen(munged_dial));
1453
1454         return True;
1455 }
1456
1457 /*********************************************************************
1458  Set the user's NT hash.
1459  ********************************************************************/
1460
1461 BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, uint8 *pwd)
1462 {
1463         if (!sampass || !pwd)
1464                 return False;
1465         
1466         if (sampass->nt_pw!=NULL)
1467                 DEBUG(4,("pdb_set_nt_passwd: NT hash non NULL overwritting ?\n"));
1468         else
1469                 sampass->nt_pw=(unsigned char *)malloc(sizeof(unsigned char)*16);
1470         
1471         if (sampass->nt_pw==NULL)
1472                 return False;
1473
1474         memcpy (sampass->nt_pw, pwd, 16);
1475
1476         return True;
1477 }
1478
1479 /*********************************************************************
1480  Set the user's LM hash.
1481  ********************************************************************/
1482
1483 BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, uint8 *pwd)
1484 {
1485         if (!sampass || !pwd)
1486                 return False;
1487         
1488         if (sampass->lm_pw!=NULL)
1489                 DEBUG(4,("pdb_set_lanman_passwd: LM hash non NULL overwritting ?\n"));
1490         else
1491                 sampass->lm_pw=(unsigned char *)malloc(sizeof(unsigned char)*16);
1492         
1493         if (sampass->lm_pw==NULL)
1494                 return False;
1495
1496         memcpy (sampass->lm_pw, pwd, 16);
1497
1498         return True;
1499 }
1500
1501 /*********************************************************************
1502  Set the user's PLAINTEXT password.  Used as an interface to the above.
1503  ********************************************************************/
1504
1505 BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, char *plaintext)
1506 {
1507         uchar new_lanman_p16[16];
1508         uchar new_nt_p16[16];
1509
1510         if (!sampass || !plaintext)
1511                 return False;
1512         
1513         nt_lm_owf_gen (plaintext, new_nt_p16, new_lanman_p16);
1514
1515         if (!pdb_set_nt_passwd (sampass, new_nt_p16)) 
1516                 return False;
1517
1518         if (!pdb_set_lanman_passwd (sampass, new_lanman_p16)) 
1519                 return False;
1520
1521         return True;
1522 }
1523
1524 BOOL pdb_set_unknown_3 (SAM_ACCOUNT *sampass, uint32 unkn)
1525 {
1526         if (!sampass)
1527                 return False;
1528
1529         sampass->unknown_3 = unkn;
1530         return True;
1531 }
1532
1533 BOOL pdb_set_unknown_5 (SAM_ACCOUNT *sampass, uint32 unkn)
1534 {
1535         if (!sampass)
1536                 return False;
1537
1538         sampass->unknown_5 = unkn;
1539         return True;
1540 }
1541
1542 BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn)
1543 {
1544         if (!sampass)
1545                 return False;
1546
1547         sampass->unknown_6 = unkn;
1548         return True;
1549 }
1550
1551 BOOL pdb_set_hours (SAM_ACCOUNT *sampass, uint8 *hours)
1552 {
1553         if (!sampass)
1554                 return False;
1555
1556         if (!hours) {
1557                 memset ((char *)sampass->hours, 0, MAX_HOURS_LEN);
1558                 return True;
1559         }
1560         
1561         memcpy (sampass->hours, hours, MAX_HOURS_LEN);
1562
1563         return True;
1564 }