r13545: A patch which I think it's time has come. VOlker, we can talk about
[samba.git] / source3 / passdb / pdb_get_set.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SAM_ACCOUNT access routines
4    Copyright (C) Jeremy Allison                 1996-2001
5    Copyright (C) Luke Kenneth Casson Leighton   1996-1998
6    Copyright (C) Gerald (Jerry) Carter          2000-2001
7    Copyright (C) Andrew Bartlett                2001-2002
8    Copyright (C) Stefan (metze) Metzmacher      2002
9       
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_PASSDB
29
30 /**
31  * @todo Redefine this to NULL, but this changes the API because
32  *       much of samba assumes that the pdb_get...() funtions 
33  *       return pstrings.  (ie not null-pointers).
34  *       See also pdb_fill_default_sam().
35  */
36
37 #define PDB_NOT_QUITE_NULL ""
38
39 /*********************************************************************
40  Collection of get...() functions for SAM_ACCOUNT.
41  ********************************************************************/
42
43 uint16 pdb_get_acct_ctrl (const SAM_ACCOUNT *sampass)
44 {
45         if (sampass)
46                 return (sampass->private_u.acct_ctrl);
47         else
48                 return (ACB_DISABLED);
49 }
50
51 time_t pdb_get_logon_time (const SAM_ACCOUNT *sampass)
52 {
53         if (sampass)
54                 return (sampass->private_u.logon_time);
55         else
56                 return (0);
57 }
58
59 time_t pdb_get_logoff_time (const SAM_ACCOUNT *sampass)
60 {
61         if (sampass)
62                 return (sampass->private_u.logoff_time);
63         else
64                 return (-1);
65 }
66
67 time_t pdb_get_kickoff_time (const SAM_ACCOUNT *sampass)
68 {
69         if (sampass)
70                 return (sampass->private_u.kickoff_time);
71         else
72                 return (-1);
73 }
74
75 time_t pdb_get_bad_password_time (const SAM_ACCOUNT *sampass)
76 {
77         if (sampass)
78                 return (sampass->private_u.bad_password_time);
79         else
80                 return (-1);
81 }
82
83 time_t pdb_get_pass_last_set_time (const SAM_ACCOUNT *sampass)
84 {
85         if (sampass)
86                 return (sampass->private_u.pass_last_set_time);
87         else
88                 return (-1);
89 }
90
91 time_t pdb_get_pass_can_change_time (const SAM_ACCOUNT *sampass)
92 {
93         if (sampass)
94                 return (sampass->private_u.pass_can_change_time);
95         else
96                 return (-1);
97 }
98
99 time_t pdb_get_pass_must_change_time (const SAM_ACCOUNT *sampass)
100 {
101         if (sampass)
102                 return (sampass->private_u.pass_must_change_time);
103         else
104                 return (-1);
105 }
106
107 uint16 pdb_get_logon_divs (const SAM_ACCOUNT *sampass)
108 {
109         if (sampass)
110                 return (sampass->private_u.logon_divs);
111         else
112                 return (-1);
113 }
114
115 uint32 pdb_get_hours_len (const SAM_ACCOUNT *sampass)
116 {
117         if (sampass)
118                 return (sampass->private_u.hours_len);
119         else
120                 return (-1);
121 }
122
123 const uint8* pdb_get_hours (const SAM_ACCOUNT *sampass)
124 {
125         if (sampass)
126                 return (sampass->private_u.hours);
127         else
128                 return (NULL);
129 }
130
131 const uint8* pdb_get_nt_passwd (const SAM_ACCOUNT *sampass)
132 {
133         if (sampass) {
134                 SMB_ASSERT((!sampass->private_u.nt_pw.data) 
135                            || sampass->private_u.nt_pw.length == NT_HASH_LEN);
136                 return ((uint8*)sampass->private_u.nt_pw.data);
137         }
138         else
139                 return (NULL);
140 }
141
142 const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass)
143 {
144         if (sampass) {
145                 SMB_ASSERT((!sampass->private_u.lm_pw.data) 
146                            || sampass->private_u.lm_pw.length == LM_HASH_LEN);
147                 return ((uint8*)sampass->private_u.lm_pw.data);
148         }
149         else
150                 return (NULL);
151 }
152
153 const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_hist_len)
154 {
155         if (sampass) {
156                 SMB_ASSERT((!sampass->private_u.nt_pw_his.data) 
157                    || ((sampass->private_u.nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0));
158                 *current_hist_len = sampass->private_u.nt_pw_his.length / PW_HISTORY_ENTRY_LEN;
159                 return ((uint8*)sampass->private_u.nt_pw_his.data);
160         } else {
161                 *current_hist_len = 0;
162                 return (NULL);
163         }
164 }
165
166 /* Return the plaintext password if known.  Most of the time
167    it isn't, so don't assume anything magic about this function.
168    
169    Used to pass the plaintext to passdb backends that might 
170    want to store more than just the NTLM hashes.
171 */
172 const char* pdb_get_plaintext_passwd (const SAM_ACCOUNT *sampass)
173 {
174         if (sampass) {
175                 return (sampass->private_u.plaintext_pw);
176         }
177         else
178                 return (NULL);
179 }
180 const DOM_SID *pdb_get_user_sid(const SAM_ACCOUNT *sampass)
181 {
182         if (sampass) 
183                 return &sampass->private_u.user_sid;
184         else
185                 return (NULL);
186 }
187
188 const DOM_SID *pdb_get_group_sid(const SAM_ACCOUNT *sampass)
189 {
190         if (sampass)
191                 return &sampass->private_u.group_sid;
192         else    
193                 return (NULL);
194 }       
195
196 /**
197  * Get flags showing what is initalised in the SAM_ACCOUNT
198  * @param sampass the SAM_ACCOUNT in question
199  * @return the flags indicating the members initialised in the struct.
200  **/
201  
202 enum pdb_value_state pdb_get_init_flags (const SAM_ACCOUNT *sampass, enum pdb_elements element)
203 {
204         enum pdb_value_state ret = PDB_DEFAULT;
205         
206         if (!sampass || !sampass->private_u.change_flags || !sampass->private_u.set_flags)
207                 return ret;
208                 
209         if (bitmap_query(sampass->private_u.set_flags, element)) {
210                 DEBUG(11, ("element %d: SET\n", element)); 
211                 ret = PDB_SET;
212         }
213                 
214         if (bitmap_query(sampass->private_u.change_flags, element)) {
215                 DEBUG(11, ("element %d: CHANGED\n", element)); 
216                 ret = PDB_CHANGED;
217         }
218
219         if (ret == PDB_DEFAULT) {
220                 DEBUG(11, ("element %d: DEFAULT\n", element)); 
221         }
222
223         return ret;
224 }
225
226 const char* pdb_get_username (const SAM_ACCOUNT *sampass)
227 {
228         if (sampass)
229                 return (sampass->private_u.username);
230         else
231                 return (NULL);
232 }
233
234 const char* pdb_get_domain (const SAM_ACCOUNT *sampass)
235 {
236         if (sampass)
237                 return (sampass->private_u.domain);
238         else
239                 return (NULL);
240 }
241
242 const char* pdb_get_nt_username (const SAM_ACCOUNT *sampass)
243 {
244         if (sampass)
245                 return (sampass->private_u.nt_username);
246         else
247                 return (NULL);
248 }
249
250 const char* pdb_get_fullname (const SAM_ACCOUNT *sampass)
251 {
252         if (sampass)
253                 return (sampass->private_u.full_name);
254         else
255                 return (NULL);
256 }
257
258 const char* pdb_get_homedir (const SAM_ACCOUNT *sampass)
259 {
260         if (sampass)
261                 return (sampass->private_u.home_dir);
262         else
263                 return (NULL);
264 }
265
266 const char* pdb_get_unix_homedir (const SAM_ACCOUNT *sampass)
267 {
268         if (sampass)
269                 return (sampass->private_u.unix_home_dir);
270         else
271                 return (NULL);
272 }
273
274 const char* pdb_get_dir_drive (const SAM_ACCOUNT *sampass)
275 {
276         if (sampass)
277                 return (sampass->private_u.dir_drive);
278         else
279                 return (NULL);
280 }
281
282 const char* pdb_get_logon_script (const SAM_ACCOUNT *sampass)
283 {
284         if (sampass)
285                 return (sampass->private_u.logon_script);
286         else
287                 return (NULL);
288 }
289
290 const char* pdb_get_profile_path (const SAM_ACCOUNT *sampass)
291 {
292         if (sampass)
293                 return (sampass->private_u.profile_path);
294         else
295                 return (NULL);
296 }
297
298 const char* pdb_get_acct_desc (const SAM_ACCOUNT *sampass)
299 {
300         if (sampass)
301                 return (sampass->private_u.acct_desc);
302         else
303                 return (NULL);
304 }
305
306 const char* pdb_get_workstations (const SAM_ACCOUNT *sampass)
307 {
308         if (sampass)
309                 return (sampass->private_u.workstations);
310         else
311                 return (NULL);
312 }
313
314 const char* pdb_get_unknown_str (const SAM_ACCOUNT *sampass)
315 {
316         if (sampass)
317                 return (sampass->private_u.unknown_str);
318         else
319                 return (NULL);
320 }
321
322 const char* pdb_get_munged_dial (const SAM_ACCOUNT *sampass)
323 {
324         if (sampass)
325                 return (sampass->private_u.munged_dial);
326         else
327                 return (NULL);
328 }
329
330 uint16 pdb_get_bad_password_count(const SAM_ACCOUNT *sampass)
331 {
332         if (sampass)
333                 return (sampass->private_u.bad_password_count);
334         else
335                 return 0;
336 }
337
338 uint16 pdb_get_logon_count(const SAM_ACCOUNT *sampass)
339 {
340         if (sampass)
341                 return (sampass->private_u.logon_count);
342         else
343                 return 0;
344 }
345
346 uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass)
347 {
348         if (sampass)
349                 return (sampass->private_u.unknown_6);
350         else
351                 return (-1);
352 }
353
354 void *pdb_get_backend_private_data (const SAM_ACCOUNT *sampass, const struct pdb_methods *my_methods)
355 {
356         if (sampass && my_methods == sampass->private_u.backend_private_methods)
357                 return sampass->private_u.backend_private_data;
358         else
359                 return NULL;
360 }
361
362 /*********************************************************************
363  Collection of set...() functions for SAM_ACCOUNT.
364  ********************************************************************/
365
366 BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 acct_ctrl, enum pdb_value_state flag)
367 {
368         if (!sampass)
369                 return False;
370                 
371         sampass->private_u.acct_ctrl = acct_ctrl;
372
373         return pdb_set_init_flags(sampass, PDB_ACCTCTRL, flag);
374 }
375
376 BOOL pdb_set_logon_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
377 {
378         if (!sampass)
379                 return False;
380
381         sampass->private_u.logon_time = mytime;
382
383         return pdb_set_init_flags(sampass, PDB_LOGONTIME, flag);
384 }
385
386 BOOL pdb_set_logoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
387 {
388         if (!sampass)
389                 return False;
390
391         sampass->private_u.logoff_time = mytime;
392
393         return pdb_set_init_flags(sampass, PDB_LOGOFFTIME, flag);
394 }
395
396 BOOL pdb_set_kickoff_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
397 {
398         if (!sampass)
399                 return False;
400
401         sampass->private_u.kickoff_time = mytime;
402
403         return pdb_set_init_flags(sampass, PDB_KICKOFFTIME, flag);
404 }
405
406 BOOL pdb_set_bad_password_time (SAM_ACCOUNT *sampass, time_t mytime, 
407                                 enum pdb_value_state flag)
408 {
409         if (!sampass)
410                 return False;
411
412         sampass->private_u.bad_password_time = mytime;
413
414         return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_TIME, flag);
415 }
416
417 BOOL pdb_set_pass_can_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
418 {
419         if (!sampass)
420                 return False;
421
422         sampass->private_u.pass_can_change_time = mytime;
423
424         return pdb_set_init_flags(sampass, PDB_CANCHANGETIME, flag);
425 }
426
427 BOOL pdb_set_pass_must_change_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
428 {
429         if (!sampass)
430                 return False;
431
432         sampass->private_u.pass_must_change_time = mytime;
433
434         return pdb_set_init_flags(sampass, PDB_MUSTCHANGETIME, flag);
435 }
436
437 BOOL pdb_set_pass_last_set_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
438 {
439         if (!sampass)
440                 return False;
441
442         sampass->private_u.pass_last_set_time = mytime;
443
444         return pdb_set_init_flags(sampass, PDB_PASSLASTSET, flag);
445 }
446
447 BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len, enum pdb_value_state flag)
448 {
449         if (!sampass)
450                 return False;
451
452         sampass->private_u.hours_len = len;
453
454         return pdb_set_init_flags(sampass, PDB_HOURSLEN, flag);
455 }
456
457 BOOL pdb_set_logon_divs (SAM_ACCOUNT *sampass, uint16 hours, enum pdb_value_state flag)
458 {
459         if (!sampass)
460                 return False;
461
462         sampass->private_u.logon_divs = hours;
463
464         return pdb_set_init_flags(sampass, PDB_LOGONDIVS, flag);
465 }
466
467 /**
468  * Set flags showing what is initalised in the SAM_ACCOUNT
469  * @param sampass the SAM_ACCOUNT in question
470  * @param flag The *new* flag to be set.  Old flags preserved
471  *             this flag is only added.  
472  **/
473  
474 BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum pdb_value_state value_flag)
475 {
476         if (!sampass || !sampass->mem_ctx)
477                 return False;
478
479         if (!sampass->private_u.set_flags) {
480                 if ((sampass->private_u.set_flags = 
481                         bitmap_talloc(sampass->mem_ctx, 
482                                         PDB_COUNT))==NULL) {
483                         DEBUG(0,("bitmap_talloc failed\n"));
484                         return False;
485                 }
486         }
487         if (!sampass->private_u.change_flags) {
488                 if ((sampass->private_u.change_flags = 
489                         bitmap_talloc(sampass->mem_ctx, 
490                                         PDB_COUNT))==NULL) {
491                         DEBUG(0,("bitmap_talloc failed\n"));
492                         return False;
493                 }
494         }
495         
496         switch(value_flag) {
497                 case PDB_CHANGED:
498                         if (!bitmap_set(sampass->private_u.change_flags, element)) {
499                                 DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
500                                 return False;
501                         }
502                         if (!bitmap_set(sampass->private_u.set_flags, element)) {
503                                 DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
504                                 return False;
505                         }
506                         DEBUG(11, ("element %d -> now CHANGED\n", element)); 
507                         break;
508                 case PDB_SET:
509                         if (!bitmap_clear(sampass->private_u.change_flags, element)) {
510                                 DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
511                                 return False;
512                         }
513                         if (!bitmap_set(sampass->private_u.set_flags, element)) {
514                                 DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
515                                 return False;
516                         }
517                         DEBUG(11, ("element %d -> now SET\n", element)); 
518                         break;
519                 case PDB_DEFAULT:
520                 default:
521                         if (!bitmap_clear(sampass->private_u.change_flags, element)) {
522                                 DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
523                                 return False;
524                         }
525                         if (!bitmap_clear(sampass->private_u.set_flags, element)) {
526                                 DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
527                                 return False;
528                         }
529                         DEBUG(11, ("element %d -> now DEFAULT\n", element)); 
530                         break;
531         }
532
533         return True;
534 }
535
536 BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, const DOM_SID *u_sid, enum pdb_value_state flag)
537 {
538         if (!sampass || !u_sid)
539                 return False;
540         
541         sid_copy(&sampass->private_u.user_sid, u_sid);
542
543         DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n", 
544                     sid_string_static(&sampass->private_u.user_sid)));
545
546         return pdb_set_init_flags(sampass, PDB_USERSID, flag);
547 }
548
549 BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb_value_state flag)
550 {
551         DOM_SID new_sid;
552         
553         if (!sampass || !u_sid)
554                 return False;
555
556         DEBUG(10, ("pdb_set_user_sid_from_string: setting user sid %s\n",
557                    u_sid));
558
559         if (!string_to_sid(&new_sid, u_sid)) { 
560                 DEBUG(1, ("pdb_set_user_sid_from_string: %s isn't a valid SID!\n", u_sid));
561                 return False;
562         }
563          
564         if (!pdb_set_user_sid(sampass, &new_sid, flag)) {
565                 DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", u_sid));
566                 return False;
567         }
568
569         return True;
570 }
571
572 BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, const DOM_SID *g_sid, enum pdb_value_state flag)
573 {
574         gid_t gid;
575
576         if (!sampass || !g_sid)
577                 return False;
578
579         /* if we cannot resolve the SID to gid, then just ignore it and 
580            store DOMAIN_USERS as the primary groupSID */
581
582         if ( sid_to_gid( g_sid, &gid ) ) {
583                 sid_copy(&sampass->private_u.group_sid, g_sid);
584         } else {
585                 sid_copy( &sampass->private_u.group_sid, get_global_sam_sid() );
586                 sid_append_rid( &sampass->private_u.group_sid, DOMAIN_GROUP_RID_USERS );
587         }
588
589         DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", 
590                     sid_string_static(&sampass->private_u.group_sid)));
591
592         return pdb_set_init_flags(sampass, PDB_GROUPSID, flag);
593 }
594
595 BOOL pdb_set_group_sid_from_string (SAM_ACCOUNT *sampass, fstring g_sid, enum pdb_value_state flag)
596 {
597         DOM_SID new_sid;
598         if (!sampass || !g_sid)
599                 return False;
600
601         DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n",
602                    g_sid));
603
604         if (!string_to_sid(&new_sid, g_sid)) { 
605                 DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid));
606                 return False;
607         }
608          
609         if (!pdb_set_group_sid(sampass, &new_sid, flag)) {
610                 DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", g_sid));
611                 return False;
612         }
613         return True;
614 }
615
616 /*********************************************************************
617  Set the user's UNIX name.
618  ********************************************************************/
619
620 BOOL pdb_set_username(SAM_ACCOUNT *sampass, const char *username, enum pdb_value_state flag)
621 {
622         if (!sampass)
623                 return False;
624  
625         if (username) { 
626                 DEBUG(10, ("pdb_set_username: setting username %s, was %s\n", username,
627                         (sampass->private_u.username)?(sampass->private_u.username):"NULL"));
628
629                 sampass->private_u.username = talloc_strdup(sampass->mem_ctx, username);
630
631                 if (!sampass->private_u.username) {
632                         DEBUG(0, ("pdb_set_username: talloc_strdup() failed!\n"));
633                         return False;
634                 }
635
636         } else {
637                 sampass->private_u.username = PDB_NOT_QUITE_NULL;
638         }
639         
640         return pdb_set_init_flags(sampass, PDB_USERNAME, flag);
641 }
642
643 /*********************************************************************
644  Set the domain name.
645  ********************************************************************/
646
647 BOOL pdb_set_domain(SAM_ACCOUNT *sampass, const char *domain, enum pdb_value_state flag)
648 {
649         if (!sampass)
650                 return False;
651
652         if (domain) { 
653                 DEBUG(10, ("pdb_set_domain: setting domain %s, was %s\n", domain,
654                         (sampass->private_u.domain)?(sampass->private_u.domain):"NULL"));
655
656                 sampass->private_u.domain = talloc_strdup(sampass->mem_ctx, domain);
657
658                 if (!sampass->private_u.domain) {
659                         DEBUG(0, ("pdb_set_domain: talloc_strdup() failed!\n"));
660                         return False;
661                 }
662
663         } else {
664                 sampass->private_u.domain = PDB_NOT_QUITE_NULL;
665         }
666
667         return pdb_set_init_flags(sampass, PDB_DOMAIN, flag);
668 }
669
670 /*********************************************************************
671  Set the user's NT name.
672  ********************************************************************/
673
674 BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, const char *nt_username, enum pdb_value_state flag)
675 {
676         if (!sampass)
677                 return False;
678
679         if (nt_username) { 
680                 DEBUG(10, ("pdb_set_nt_username: setting nt username %s, was %s\n", nt_username,
681                         (sampass->private_u.nt_username)?(sampass->private_u.nt_username):"NULL"));
682  
683                 sampass->private_u.nt_username = talloc_strdup(sampass->mem_ctx, nt_username);
684                 
685                 if (!sampass->private_u.nt_username) {
686                         DEBUG(0, ("pdb_set_nt_username: talloc_strdup() failed!\n"));
687                         return False;
688                 }
689
690         } else {
691                 sampass->private_u.nt_username = PDB_NOT_QUITE_NULL;
692         }
693
694         return pdb_set_init_flags(sampass, PDB_NTUSERNAME, flag);
695 }
696
697 /*********************************************************************
698  Set the user's full name.
699  ********************************************************************/
700
701 BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, const char *full_name, enum pdb_value_state flag)
702 {
703         if (!sampass)
704                 return False;
705
706         if (full_name) { 
707                 DEBUG(10, ("pdb_set_full_name: setting full name %s, was %s\n", full_name,
708                         (sampass->private_u.full_name)?(sampass->private_u.full_name):"NULL"));
709         
710                 sampass->private_u.full_name = talloc_strdup(sampass->mem_ctx, full_name);
711
712                 if (!sampass->private_u.full_name) {
713                         DEBUG(0, ("pdb_set_fullname: talloc_strdup() failed!\n"));
714                         return False;
715                 }
716
717         } else {
718                 sampass->private_u.full_name = PDB_NOT_QUITE_NULL;
719         }
720
721         return pdb_set_init_flags(sampass, PDB_FULLNAME, flag);
722 }
723
724 /*********************************************************************
725  Set the user's logon script.
726  ********************************************************************/
727
728 BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, enum pdb_value_state flag)
729 {
730         if (!sampass)
731                 return False;
732
733         if (logon_script) { 
734                 DEBUG(10, ("pdb_set_logon_script: setting logon script %s, was %s\n", logon_script,
735                         (sampass->private_u.logon_script)?(sampass->private_u.logon_script):"NULL"));
736  
737                 sampass->private_u.logon_script = talloc_strdup(sampass->mem_ctx, logon_script);
738
739                 if (!sampass->private_u.logon_script) {
740                         DEBUG(0, ("pdb_set_logon_script: talloc_strdup() failed!\n"));
741                         return False;
742                 }
743
744         } else {
745                 sampass->private_u.logon_script = PDB_NOT_QUITE_NULL;
746         }
747         
748         return pdb_set_init_flags(sampass, PDB_LOGONSCRIPT, flag);
749 }
750
751 /*********************************************************************
752  Set the user's profile path.
753  ********************************************************************/
754
755 BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, enum pdb_value_state flag)
756 {
757         if (!sampass)
758                 return False;
759
760         if (profile_path) { 
761                 DEBUG(10, ("pdb_set_profile_path: setting profile path %s, was %s\n", profile_path,
762                         (sampass->private_u.profile_path)?(sampass->private_u.profile_path):"NULL"));
763  
764                 sampass->private_u.profile_path = talloc_strdup(sampass->mem_ctx, profile_path);
765                 
766                 if (!sampass->private_u.profile_path) {
767                         DEBUG(0, ("pdb_set_profile_path: talloc_strdup() failed!\n"));
768                         return False;
769                 }
770
771         } else {
772                 sampass->private_u.profile_path = PDB_NOT_QUITE_NULL;
773         }
774
775         return pdb_set_init_flags(sampass, PDB_PROFILE, flag);
776 }
777
778 /*********************************************************************
779  Set the user's directory drive.
780  ********************************************************************/
781
782 BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, enum pdb_value_state flag)
783 {
784         if (!sampass)
785                 return False;
786
787         if (dir_drive) { 
788                 DEBUG(10, ("pdb_set_dir_drive: setting dir drive %s, was %s\n", dir_drive,
789                         (sampass->private_u.dir_drive)?(sampass->private_u.dir_drive):"NULL"));
790  
791                 sampass->private_u.dir_drive = talloc_strdup(sampass->mem_ctx, dir_drive);
792                 
793                 if (!sampass->private_u.dir_drive) {
794                         DEBUG(0, ("pdb_set_dir_drive: talloc_strdup() failed!\n"));
795                         return False;
796                 }
797
798         } else {
799                 sampass->private_u.dir_drive = PDB_NOT_QUITE_NULL;
800         }
801         
802         return pdb_set_init_flags(sampass, PDB_DRIVE, flag);
803 }
804
805 /*********************************************************************
806  Set the user's home directory.
807  ********************************************************************/
808
809 BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, enum pdb_value_state flag)
810 {
811         if (!sampass)
812                 return False;
813
814         if (home_dir) { 
815                 DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", home_dir,
816                         (sampass->private_u.home_dir)?(sampass->private_u.home_dir):"NULL"));
817  
818                 sampass->private_u.home_dir = talloc_strdup(sampass->mem_ctx, home_dir);
819                 
820                 if (!sampass->private_u.home_dir) {
821                         DEBUG(0, ("pdb_set_home_dir: talloc_strdup() failed!\n"));
822                         return False;
823                 }
824
825         } else {
826                 sampass->private_u.home_dir = PDB_NOT_QUITE_NULL;
827         }
828
829         return pdb_set_init_flags(sampass, PDB_SMBHOME, flag);
830 }
831
832 /*********************************************************************
833  Set the user's unix home directory.
834  ********************************************************************/
835
836 BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir, enum pdb_value_state flag)
837 {
838         if (!sampass)
839                 return False;
840
841         if (unix_home_dir) { 
842                 DEBUG(10, ("pdb_set_unix_homedir: setting home dir %s, was %s\n", unix_home_dir,
843                         (sampass->private_u.unix_home_dir)?(sampass->private_u.unix_home_dir):"NULL"));
844  
845                 sampass->private_u.unix_home_dir = talloc_strdup(sampass->mem_ctx, 
846                                                           unix_home_dir);
847                 
848                 if (!sampass->private_u.unix_home_dir) {
849                         DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n"));
850                         return False;
851                 }
852
853         } else {
854                 sampass->private_u.unix_home_dir = PDB_NOT_QUITE_NULL;
855         }
856
857         return pdb_set_init_flags(sampass, PDB_UNIXHOMEDIR, flag);
858 }
859
860 /*********************************************************************
861  Set the user's account description.
862  ********************************************************************/
863
864 BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, const char *acct_desc, enum pdb_value_state flag)
865 {
866         if (!sampass)
867                 return False;
868
869         if (acct_desc) { 
870                 sampass->private_u.acct_desc = talloc_strdup(sampass->mem_ctx, acct_desc);
871
872                 if (!sampass->private_u.acct_desc) {
873                         DEBUG(0, ("pdb_set_acct_desc: talloc_strdup() failed!\n"));
874                         return False;
875                 }
876
877         } else {
878                 sampass->private_u.acct_desc = PDB_NOT_QUITE_NULL;
879         }
880
881         return pdb_set_init_flags(sampass, PDB_ACCTDESC, flag);
882 }
883
884 /*********************************************************************
885  Set the user's workstation allowed list.
886  ********************************************************************/
887
888 BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, const char *workstations, enum pdb_value_state flag)
889 {
890         if (!sampass)
891                 return False;
892
893         if (workstations) { 
894                 DEBUG(10, ("pdb_set_workstations: setting workstations %s, was %s\n", workstations,
895                         (sampass->private_u.workstations)?(sampass->private_u.workstations):"NULL"));
896  
897                 sampass->private_u.workstations = talloc_strdup(sampass->mem_ctx, workstations);
898
899                 if (!sampass->private_u.workstations) {
900                         DEBUG(0, ("pdb_set_workstations: talloc_strdup() failed!\n"));
901                         return False;
902                 }
903
904         } else {
905                 sampass->private_u.workstations = PDB_NOT_QUITE_NULL;
906         }
907
908         return pdb_set_init_flags(sampass, PDB_WORKSTATIONS, flag);
909 }
910
911 /*********************************************************************
912  Set the user's 'unknown_str', whatever the heck this actually is...
913  ********************************************************************/
914
915 BOOL pdb_set_unknown_str (SAM_ACCOUNT *sampass, const char *unknown_str, enum pdb_value_state flag)
916 {
917         if (!sampass)
918                 return False;
919
920         if (unknown_str) { 
921                 sampass->private_u.unknown_str = talloc_strdup(sampass->mem_ctx, unknown_str);
922                 
923                 if (!sampass->private_u.unknown_str) {
924                         DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
925                         return False;
926                 }
927
928         } else {
929                 sampass->private_u.unknown_str = PDB_NOT_QUITE_NULL;
930         }
931
932         return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
933 }
934
935 /*********************************************************************
936  Set the user's dial string.
937  ********************************************************************/
938
939 BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, const char *munged_dial, enum pdb_value_state flag)
940 {
941         if (!sampass)
942                 return False;
943
944         if (munged_dial) { 
945                 sampass->private_u.munged_dial = talloc_strdup(sampass->mem_ctx, munged_dial);
946                 
947                 if (!sampass->private_u.munged_dial) {
948                         DEBUG(0, ("pdb_set_munged_dial: talloc_strdup() failed!\n"));
949                         return False;
950                 }
951
952         } else {
953                 sampass->private_u.munged_dial = PDB_NOT_QUITE_NULL;
954         }
955
956         return pdb_set_init_flags(sampass, PDB_MUNGEDDIAL, flag);
957 }
958
959 /*********************************************************************
960  Set the user's NT hash.
961  ********************************************************************/
962
963 BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum pdb_value_state flag)
964 {
965         if (!sampass)
966                 return False;
967
968         data_blob_clear_free(&sampass->private_u.nt_pw);
969         
970        if (pwd) {
971                sampass->private_u.nt_pw =
972                        data_blob_talloc(sampass->mem_ctx, pwd, NT_HASH_LEN);
973        } else {
974                sampass->private_u.nt_pw = data_blob(NULL, 0);
975        }
976
977         return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag);
978 }
979
980 /*********************************************************************
981  Set the user's LM hash.
982  ********************************************************************/
983
984 BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], enum pdb_value_state flag)
985 {
986         if (!sampass)
987                 return False;
988
989         data_blob_clear_free(&sampass->private_u.lm_pw);
990         
991        if (pwd) {
992                sampass->private_u.lm_pw =
993                        data_blob_talloc(sampass->mem_ctx, pwd, LM_HASH_LEN);
994        } else {
995                sampass->private_u.lm_pw = data_blob(NULL, 0);
996        }
997
998         return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag);
999 }
1000
1001 /*********************************************************************
1002  Set the user's password history hash. historyLen is the number of 
1003  PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN length
1004  entries to store in the history - this must match the size of the uint8 array
1005  in pwd.
1006 ********************************************************************/
1007
1008 BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag)
1009 {
1010         if (!sampass)
1011                 return False;
1012
1013         if (historyLen && pwd){
1014                 sampass->private_u.nt_pw_his = data_blob_talloc(sampass->mem_ctx,
1015                                                 pwd, historyLen*PW_HISTORY_ENTRY_LEN);
1016                 if (!sampass->private_u.nt_pw_his.length) {
1017                         DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n"));
1018                         return False;
1019                 }
1020         } else {
1021                 sampass->private_u.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0);
1022         }
1023
1024         return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag);
1025 }
1026
1027 /*********************************************************************
1028  Set the user's plaintext password only (base procedure, see helper
1029  below)
1030  ********************************************************************/
1031
1032 BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const char *password, enum pdb_value_state flag)
1033 {
1034         if (!sampass)
1035                 return False;
1036
1037         if (password) { 
1038                 if (sampass->private_u.plaintext_pw!=NULL) 
1039                         memset(sampass->private_u.plaintext_pw,'\0',strlen(sampass->private_u.plaintext_pw)+1);
1040
1041                 sampass->private_u.plaintext_pw = talloc_strdup(sampass->mem_ctx, password);
1042                 
1043                 if (!sampass->private_u.plaintext_pw) {
1044                         DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
1045                         return False;
1046                 }
1047
1048         } else {
1049                 sampass->private_u.plaintext_pw = NULL;
1050         }
1051
1052         return pdb_set_init_flags(sampass, PDB_PLAINTEXT_PW, flag);
1053 }
1054
1055 BOOL pdb_set_bad_password_count(SAM_ACCOUNT *sampass, uint16 bad_password_count, enum pdb_value_state flag)
1056 {
1057         if (!sampass)
1058                 return False;
1059
1060         sampass->private_u.bad_password_count = bad_password_count;
1061
1062         return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag);
1063 }
1064
1065 BOOL pdb_set_logon_count(SAM_ACCOUNT *sampass, uint16 logon_count, enum pdb_value_state flag)
1066 {
1067         if (!sampass)
1068                 return False;
1069
1070         sampass->private_u.logon_count = logon_count;
1071
1072         return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag);
1073 }
1074
1075 BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag)
1076 {
1077         if (!sampass)
1078                 return False;
1079
1080         sampass->private_u.unknown_6 = unkn;
1081
1082         return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
1083 }
1084
1085 BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
1086 {
1087         if (!sampass)
1088                 return False;
1089
1090         if (!hours) {
1091                 memset ((char *)sampass->private_u.hours, 0, MAX_HOURS_LEN);
1092                 return True;
1093         }
1094         
1095         memcpy (sampass->private_u.hours, hours, MAX_HOURS_LEN);
1096
1097         return pdb_set_init_flags(sampass, PDB_HOURS, flag);
1098 }
1099
1100 BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data, 
1101                                    void (*free_fn)(void **), 
1102                                    const struct pdb_methods *my_methods, 
1103                                    enum pdb_value_state flag)
1104 {
1105         if (!sampass)
1106                 return False;
1107
1108         if (sampass->private_u.backend_private_data &&
1109             sampass->private_u.backend_private_data_free_fn) {
1110                 sampass->private_u.backend_private_data_free_fn(
1111                         &sampass->private_u.backend_private_data);
1112         }
1113
1114         sampass->private_u.backend_private_data = private_data;
1115         sampass->private_u.backend_private_data_free_fn = free_fn;
1116         sampass->private_u.backend_private_methods = my_methods;
1117
1118         return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag);
1119 }
1120
1121
1122 /* Helpful interfaces to the above */
1123
1124 /*********************************************************************
1125  Sets the last changed times and must change times for a normal
1126  password change.
1127  ********************************************************************/
1128
1129 BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
1130 {
1131         uint32 expire;
1132         uint32 min_age;
1133
1134         if (!sampass)
1135                 return False;
1136         
1137         if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
1138                 return False;
1139
1140         if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) 
1141             || (expire==(uint32)-1) || (expire == 0)) {
1142                 if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
1143                         return False;
1144         } else {
1145                 if (!pdb_set_pass_must_change_time (sampass, 
1146                                                     pdb_get_pass_last_set_time(sampass)
1147                                                     + expire, PDB_CHANGED))
1148                         return False;
1149         }
1150         
1151         if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age) 
1152             || (min_age==(uint32)-1)) {
1153                 if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
1154                         return False;
1155         } else {
1156                 if (!pdb_set_pass_can_change_time (sampass, 
1157                                                     pdb_get_pass_last_set_time(sampass)
1158                                                     + min_age, PDB_CHANGED))
1159                         return False;
1160         }
1161         return True;
1162 }
1163
1164 /*********************************************************************
1165  Set the user's PLAINTEXT password.  Used as an interface to the above.
1166  Also sets the last change time to NOW.
1167  ********************************************************************/
1168
1169 BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
1170 {
1171         uchar new_lanman_p16[LM_HASH_LEN];
1172         uchar new_nt_p16[NT_HASH_LEN];
1173
1174         if (!sampass || !plaintext)
1175                 return False;
1176
1177         /* Calculate the MD4 hash (NT compatible) of the password */
1178         E_md4hash(plaintext, new_nt_p16);
1179
1180         if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) 
1181                 return False;
1182
1183         if (!E_deshash(plaintext, new_lanman_p16)) {
1184                 /* E_deshash returns false for 'long' passwords (> 14
1185                    DOS chars).  This allows us to match Win2k, which
1186                    does not store a LM hash for these passwords (which
1187                    would reduce the effective password length to 14 */
1188
1189                 if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) 
1190                         return False;
1191         } else {
1192                 if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) 
1193                         return False;
1194         }
1195
1196         if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) 
1197                 return False;
1198
1199         if (!pdb_set_pass_changed_now (sampass))
1200                 return False;
1201
1202         /* Store the password history. */
1203         if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
1204                 uchar *pwhistory;
1205                 uint32 pwHistLen;
1206                 pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
1207                 if (pwHistLen != 0){
1208                         uint32 current_history_len;
1209                         /* We need to make sure we don't have a race condition here - the
1210                            account policy history length can change between when the pw_history
1211                            was first loaded into the SAM_ACCOUNT struct and now.... JRA. */
1212                         pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);
1213
1214                         if (current_history_len != pwHistLen) {
1215                                 /* After closing and reopening SAM_ACCOUNT the history
1216                                         values will sync up. We can't do this here. */
1217
1218                                 /* current_history_len > pwHistLen is not a problem - we
1219                                         have more history than we need. */
1220
1221                                 if (current_history_len < pwHistLen) {
1222                                         /* Ensure we have space for the needed history. */
1223                                         uchar *new_history = TALLOC(sampass->mem_ctx,
1224                                                                 pwHistLen*PW_HISTORY_ENTRY_LEN);
1225                                         /* And copy it into the new buffer. */
1226                                         if (current_history_len) {
1227                                                 memcpy(new_history, pwhistory,
1228                                                         current_history_len*PW_HISTORY_ENTRY_LEN);
1229                                         }
1230                                         /* Clearing out any extra space. */
1231                                         memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN],
1232                                                 '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN);
1233                                         /* Finally replace it. */
1234                                         pwhistory = new_history;
1235                                 }
1236                         }
1237                         if (pwhistory && pwHistLen){
1238                                 /* Make room for the new password in the history list. */
1239                                 if (pwHistLen > 1) {
1240                                         memmove(&pwhistory[PW_HISTORY_ENTRY_LEN],
1241                                                 pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN );
1242                                 }
1243                                 /* Create the new salt as the first part of the history entry. */
1244                                 generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN);
1245
1246                                 /* Generate the md5 hash of the salt+new password as the second
1247                                         part of the history entry. */
1248
1249                                 E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]);
1250                                 pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);
1251                         } else {
1252                                 DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n"));
1253                         }
1254                 } else {
1255                         /* Set the history length to zero. */
1256                         pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
1257                 }
1258         }
1259
1260         return True;
1261 }
1262
1263 /* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */
1264 uint32 pdb_build_fields_present (SAM_ACCOUNT *sampass)
1265 {
1266         /* value set to all for testing */
1267         return 0x00ffffff;
1268 }