4b59b5fdf95a171a055ed064f1cc3c8b6c8832e7
[samba.git] / source / 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.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.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.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.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.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.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.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.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.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.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.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.nt_pw.data) 
135                            || sampass->private.nt_pw.length == NT_HASH_LEN);
136                 return ((uint8*)sampass->private.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.lm_pw.data) 
146                            || sampass->private.lm_pw.length == LM_HASH_LEN);
147                 return ((uint8*)sampass->private.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.nt_pw_his.data) 
157                    || ((sampass->private.nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0));
158                 *current_hist_len = sampass->private.nt_pw_his.length / PW_HISTORY_ENTRY_LEN;
159                 return ((uint8*)sampass->private.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.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.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.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.change_flags || !sampass->private.set_flags)
207                 return ret;
208                 
209         if (bitmap_query(sampass->private.set_flags, element)) {
210                 DEBUG(11, ("element %d: SET\n", element)); 
211                 ret = PDB_SET;
212         }
213                 
214         if (bitmap_query(sampass->private.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.backend_private_methods)
357                 return sampass->private.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.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.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.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.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.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.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.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.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.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.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.set_flags) {
480                 if ((sampass->private.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.change_flags) {
488                 if ((sampass->private.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.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.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.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.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.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.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.user_sid, u_sid);
542
543         DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n", 
544                     sid_string_static(&sampass->private.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         if (!sampass || !g_sid)
575                 return False;
576
577         sid_copy(&sampass->private.group_sid, g_sid);
578
579         DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", 
580                     sid_string_static(&sampass->private.group_sid)));
581
582         return pdb_set_init_flags(sampass, PDB_GROUPSID, flag);
583 }
584
585 BOOL pdb_set_group_sid_from_string (SAM_ACCOUNT *sampass, fstring g_sid, enum pdb_value_state flag)
586 {
587         DOM_SID new_sid;
588         if (!sampass || !g_sid)
589                 return False;
590
591         DEBUG(10, ("pdb_set_group_sid_from_string: setting group sid %s\n",
592                    g_sid));
593
594         if (!string_to_sid(&new_sid, g_sid)) { 
595                 DEBUG(1, ("pdb_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid));
596                 return False;
597         }
598          
599         if (!pdb_set_group_sid(sampass, &new_sid, flag)) {
600                 DEBUG(1, ("pdb_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT!\n", g_sid));
601                 return False;
602         }
603         return True;
604 }
605
606 /*********************************************************************
607  Set the user's UNIX name.
608  ********************************************************************/
609
610 BOOL pdb_set_username(SAM_ACCOUNT *sampass, const char *username, enum pdb_value_state flag)
611 {
612         if (!sampass)
613                 return False;
614  
615         if (username) { 
616                 DEBUG(10, ("pdb_set_username: setting username %s, was %s\n", username,
617                         (sampass->private.username)?(sampass->private.username):"NULL"));
618
619                 sampass->private.username = talloc_strdup(sampass->mem_ctx, username);
620
621                 if (!sampass->private.username) {
622                         DEBUG(0, ("pdb_set_username: talloc_strdup() failed!\n"));
623                         return False;
624                 }
625
626         } else {
627                 sampass->private.username = PDB_NOT_QUITE_NULL;
628         }
629         
630         return pdb_set_init_flags(sampass, PDB_USERNAME, flag);
631 }
632
633 /*********************************************************************
634  Set the domain name.
635  ********************************************************************/
636
637 BOOL pdb_set_domain(SAM_ACCOUNT *sampass, const char *domain, enum pdb_value_state flag)
638 {
639         if (!sampass)
640                 return False;
641
642         if (domain) { 
643                 DEBUG(10, ("pdb_set_domain: setting domain %s, was %s\n", domain,
644                         (sampass->private.domain)?(sampass->private.domain):"NULL"));
645
646                 sampass->private.domain = talloc_strdup(sampass->mem_ctx, domain);
647
648                 if (!sampass->private.domain) {
649                         DEBUG(0, ("pdb_set_domain: talloc_strdup() failed!\n"));
650                         return False;
651                 }
652
653         } else {
654                 sampass->private.domain = PDB_NOT_QUITE_NULL;
655         }
656
657         return pdb_set_init_flags(sampass, PDB_DOMAIN, flag);
658 }
659
660 /*********************************************************************
661  Set the user's NT name.
662  ********************************************************************/
663
664 BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, const char *nt_username, enum pdb_value_state flag)
665 {
666         if (!sampass)
667                 return False;
668
669         if (nt_username) { 
670                 DEBUG(10, ("pdb_set_nt_username: setting nt username %s, was %s\n", nt_username,
671                         (sampass->private.nt_username)?(sampass->private.nt_username):"NULL"));
672  
673                 sampass->private.nt_username = talloc_strdup(sampass->mem_ctx, nt_username);
674                 
675                 if (!sampass->private.nt_username) {
676                         DEBUG(0, ("pdb_set_nt_username: talloc_strdup() failed!\n"));
677                         return False;
678                 }
679
680         } else {
681                 sampass->private.nt_username = PDB_NOT_QUITE_NULL;
682         }
683
684         return pdb_set_init_flags(sampass, PDB_NTUSERNAME, flag);
685 }
686
687 /*********************************************************************
688  Set the user's full name.
689  ********************************************************************/
690
691 BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, const char *full_name, enum pdb_value_state flag)
692 {
693         if (!sampass)
694                 return False;
695
696         if (full_name) { 
697                 DEBUG(10, ("pdb_set_full_name: setting full name %s, was %s\n", full_name,
698                         (sampass->private.full_name)?(sampass->private.full_name):"NULL"));
699         
700                 sampass->private.full_name = talloc_strdup(sampass->mem_ctx, full_name);
701
702                 if (!sampass->private.full_name) {
703                         DEBUG(0, ("pdb_set_fullname: talloc_strdup() failed!\n"));
704                         return False;
705                 }
706
707         } else {
708                 sampass->private.full_name = PDB_NOT_QUITE_NULL;
709         }
710
711         return pdb_set_init_flags(sampass, PDB_FULLNAME, flag);
712 }
713
714 /*********************************************************************
715  Set the user's logon script.
716  ********************************************************************/
717
718 BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, const char *logon_script, enum pdb_value_state flag)
719 {
720         if (!sampass)
721                 return False;
722
723         if (logon_script) { 
724                 DEBUG(10, ("pdb_set_logon_script: setting logon script %s, was %s\n", logon_script,
725                         (sampass->private.logon_script)?(sampass->private.logon_script):"NULL"));
726  
727                 sampass->private.logon_script = talloc_strdup(sampass->mem_ctx, logon_script);
728
729                 if (!sampass->private.logon_script) {
730                         DEBUG(0, ("pdb_set_logon_script: talloc_strdup() failed!\n"));
731                         return False;
732                 }
733
734         } else {
735                 sampass->private.logon_script = PDB_NOT_QUITE_NULL;
736         }
737         
738         return pdb_set_init_flags(sampass, PDB_LOGONSCRIPT, flag);
739 }
740
741 /*********************************************************************
742  Set the user's profile path.
743  ********************************************************************/
744
745 BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, const char *profile_path, enum pdb_value_state flag)
746 {
747         if (!sampass)
748                 return False;
749
750         if (profile_path) { 
751                 DEBUG(10, ("pdb_set_profile_path: setting profile path %s, was %s\n", profile_path,
752                         (sampass->private.profile_path)?(sampass->private.profile_path):"NULL"));
753  
754                 sampass->private.profile_path = talloc_strdup(sampass->mem_ctx, profile_path);
755                 
756                 if (!sampass->private.profile_path) {
757                         DEBUG(0, ("pdb_set_profile_path: talloc_strdup() failed!\n"));
758                         return False;
759                 }
760
761         } else {
762                 sampass->private.profile_path = PDB_NOT_QUITE_NULL;
763         }
764
765         return pdb_set_init_flags(sampass, PDB_PROFILE, flag);
766 }
767
768 /*********************************************************************
769  Set the user's directory drive.
770  ********************************************************************/
771
772 BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, const char *dir_drive, enum pdb_value_state flag)
773 {
774         if (!sampass)
775                 return False;
776
777         if (dir_drive) { 
778                 DEBUG(10, ("pdb_set_dir_drive: setting dir drive %s, was %s\n", dir_drive,
779                         (sampass->private.dir_drive)?(sampass->private.dir_drive):"NULL"));
780  
781                 sampass->private.dir_drive = talloc_strdup(sampass->mem_ctx, dir_drive);
782                 
783                 if (!sampass->private.dir_drive) {
784                         DEBUG(0, ("pdb_set_dir_drive: talloc_strdup() failed!\n"));
785                         return False;
786                 }
787
788         } else {
789                 sampass->private.dir_drive = PDB_NOT_QUITE_NULL;
790         }
791         
792         return pdb_set_init_flags(sampass, PDB_DRIVE, flag);
793 }
794
795 /*********************************************************************
796  Set the user's home directory.
797  ********************************************************************/
798
799 BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, const char *home_dir, enum pdb_value_state flag)
800 {
801         if (!sampass)
802                 return False;
803
804         if (home_dir) { 
805                 DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", home_dir,
806                         (sampass->private.home_dir)?(sampass->private.home_dir):"NULL"));
807  
808                 sampass->private.home_dir = talloc_strdup(sampass->mem_ctx, home_dir);
809                 
810                 if (!sampass->private.home_dir) {
811                         DEBUG(0, ("pdb_set_home_dir: talloc_strdup() failed!\n"));
812                         return False;
813                 }
814
815         } else {
816                 sampass->private.home_dir = PDB_NOT_QUITE_NULL;
817         }
818
819         return pdb_set_init_flags(sampass, PDB_SMBHOME, flag);
820 }
821
822 /*********************************************************************
823  Set the user's unix home directory.
824  ********************************************************************/
825
826 BOOL pdb_set_unix_homedir (SAM_ACCOUNT *sampass, const char *unix_home_dir, enum pdb_value_state flag)
827 {
828         if (!sampass)
829                 return False;
830
831         if (unix_home_dir) { 
832                 DEBUG(10, ("pdb_set_unix_homedir: setting home dir %s, was %s\n", unix_home_dir,
833                         (sampass->private.unix_home_dir)?(sampass->private.unix_home_dir):"NULL"));
834  
835                 sampass->private.unix_home_dir = talloc_strdup(sampass->mem_ctx, 
836                                                           unix_home_dir);
837                 
838                 if (!sampass->private.unix_home_dir) {
839                         DEBUG(0, ("pdb_set_unix_home_dir: talloc_strdup() failed!\n"));
840                         return False;
841                 }
842
843         } else {
844                 sampass->private.unix_home_dir = PDB_NOT_QUITE_NULL;
845         }
846
847         return pdb_set_init_flags(sampass, PDB_UNIXHOMEDIR, flag);
848 }
849
850 /*********************************************************************
851  Set the user's account description.
852  ********************************************************************/
853
854 BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, const char *acct_desc, enum pdb_value_state flag)
855 {
856         if (!sampass)
857                 return False;
858
859         if (acct_desc) { 
860                 sampass->private.acct_desc = talloc_strdup(sampass->mem_ctx, acct_desc);
861
862                 if (!sampass->private.acct_desc) {
863                         DEBUG(0, ("pdb_set_acct_desc: talloc_strdup() failed!\n"));
864                         return False;
865                 }
866
867         } else {
868                 sampass->private.acct_desc = PDB_NOT_QUITE_NULL;
869         }
870
871         return pdb_set_init_flags(sampass, PDB_ACCTDESC, flag);
872 }
873
874 /*********************************************************************
875  Set the user's workstation allowed list.
876  ********************************************************************/
877
878 BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, const char *workstations, enum pdb_value_state flag)
879 {
880         if (!sampass)
881                 return False;
882
883         if (workstations) { 
884                 DEBUG(10, ("pdb_set_workstations: setting workstations %s, was %s\n", workstations,
885                         (sampass->private.workstations)?(sampass->private.workstations):"NULL"));
886  
887                 sampass->private.workstations = talloc_strdup(sampass->mem_ctx, workstations);
888
889                 if (!sampass->private.workstations) {
890                         DEBUG(0, ("pdb_set_workstations: talloc_strdup() failed!\n"));
891                         return False;
892                 }
893
894         } else {
895                 sampass->private.workstations = PDB_NOT_QUITE_NULL;
896         }
897
898         return pdb_set_init_flags(sampass, PDB_WORKSTATIONS, flag);
899 }
900
901 /*********************************************************************
902  Set the user's 'unknown_str', whatever the heck this actually is...
903  ********************************************************************/
904
905 BOOL pdb_set_unknown_str (SAM_ACCOUNT *sampass, const char *unknown_str, enum pdb_value_state flag)
906 {
907         if (!sampass)
908                 return False;
909
910         if (unknown_str) { 
911                 sampass->private.unknown_str = talloc_strdup(sampass->mem_ctx, unknown_str);
912                 
913                 if (!sampass->private.unknown_str) {
914                         DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
915                         return False;
916                 }
917
918         } else {
919                 sampass->private.unknown_str = PDB_NOT_QUITE_NULL;
920         }
921
922         return pdb_set_init_flags(sampass, PDB_UNKNOWNSTR, flag);
923 }
924
925 /*********************************************************************
926  Set the user's dial string.
927  ********************************************************************/
928
929 BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, const char *munged_dial, enum pdb_value_state flag)
930 {
931         if (!sampass)
932                 return False;
933
934         if (munged_dial) { 
935                 sampass->private.munged_dial = talloc_strdup(sampass->mem_ctx, munged_dial);
936                 
937                 if (!sampass->private.munged_dial) {
938                         DEBUG(0, ("pdb_set_munged_dial: talloc_strdup() failed!\n"));
939                         return False;
940                 }
941
942         } else {
943                 sampass->private.munged_dial = PDB_NOT_QUITE_NULL;
944         }
945
946         return pdb_set_init_flags(sampass, PDB_MUNGEDDIAL, flag);
947 }
948
949 /*********************************************************************
950  Set the user's NT hash.
951  ********************************************************************/
952
953 BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum pdb_value_state flag)
954 {
955         if (!sampass)
956                 return False;
957
958         data_blob_clear_free(&sampass->private.nt_pw);
959         
960        if (pwd) {
961                sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN);
962        } else {
963                sampass->private.nt_pw = data_blob(NULL, 0);
964        }
965
966         return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag);
967 }
968
969 /*********************************************************************
970  Set the user's LM hash.
971  ********************************************************************/
972
973 BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], enum pdb_value_state flag)
974 {
975         if (!sampass)
976                 return False;
977
978         data_blob_clear_free(&sampass->private.lm_pw);
979         
980        if (pwd) {
981                sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN);
982        } else {
983                sampass->private.lm_pw = data_blob(NULL, 0);
984        }
985
986         return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag);
987 }
988
989 /*********************************************************************
990  Set the user's password history hash. historyLen is the number of 
991  PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN length
992  entries to store in the history - this must match the size of the uint8 array
993  in pwd.
994 ********************************************************************/
995
996 BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag)
997 {
998         if (!sampass)
999                 return False;
1000
1001         if (historyLen && pwd){
1002                 sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx,
1003                                                 pwd, historyLen*PW_HISTORY_ENTRY_LEN);
1004                 if (!sampass->private.nt_pw_his.length) {
1005                         DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n"));
1006                         return False;
1007                 }
1008         } else {
1009                 sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0);
1010         }
1011
1012         return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag);
1013 }
1014
1015 /*********************************************************************
1016  Set the user's plaintext password only (base procedure, see helper
1017  below)
1018  ********************************************************************/
1019
1020 BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const char *password, enum pdb_value_state flag)
1021 {
1022         if (!sampass)
1023                 return False;
1024
1025         if (password) { 
1026                 if (sampass->private.plaintext_pw!=NULL) 
1027                         memset(sampass->private.plaintext_pw,'\0',strlen(sampass->private.plaintext_pw)+1);
1028
1029                 sampass->private.plaintext_pw = talloc_strdup(sampass->mem_ctx, password);
1030                 
1031                 if (!sampass->private.plaintext_pw) {
1032                         DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
1033                         return False;
1034                 }
1035
1036         } else {
1037                 sampass->private.plaintext_pw = NULL;
1038         }
1039
1040         return pdb_set_init_flags(sampass, PDB_PLAINTEXT_PW, flag);
1041 }
1042
1043 BOOL pdb_set_bad_password_count(SAM_ACCOUNT *sampass, uint16 bad_password_count, enum pdb_value_state flag)
1044 {
1045         if (!sampass)
1046                 return False;
1047
1048         sampass->private.bad_password_count = bad_password_count;
1049
1050         return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag);
1051 }
1052
1053 BOOL pdb_set_logon_count(SAM_ACCOUNT *sampass, uint16 logon_count, enum pdb_value_state flag)
1054 {
1055         if (!sampass)
1056                 return False;
1057
1058         sampass->private.logon_count = logon_count;
1059
1060         return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag);
1061 }
1062
1063 BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag)
1064 {
1065         if (!sampass)
1066                 return False;
1067
1068         sampass->private.unknown_6 = unkn;
1069
1070         return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
1071 }
1072
1073 BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
1074 {
1075         if (!sampass)
1076                 return False;
1077
1078         if (!hours) {
1079                 memset ((char *)sampass->private.hours, 0, MAX_HOURS_LEN);
1080                 return True;
1081         }
1082         
1083         memcpy (sampass->private.hours, hours, MAX_HOURS_LEN);
1084
1085         return pdb_set_init_flags(sampass, PDB_HOURS, flag);
1086 }
1087
1088 BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data, 
1089                                    void (*free_fn)(void **), 
1090                                    const struct pdb_methods *my_methods, 
1091                                    enum pdb_value_state flag)
1092 {
1093         if (!sampass)
1094                 return False;
1095
1096         if (sampass->private.backend_private_data && sampass->private.backend_private_data_free_fn) {
1097                 sampass->private.backend_private_data_free_fn(&sampass->private.backend_private_data);
1098         }
1099
1100         sampass->private.backend_private_data = private_data;
1101         sampass->private.backend_private_data_free_fn = free_fn;
1102         sampass->private.backend_private_methods = my_methods;
1103
1104         return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag);
1105 }
1106
1107
1108 /* Helpful interfaces to the above */
1109
1110 /*********************************************************************
1111  Sets the last changed times and must change times for a normal
1112  password change.
1113  ********************************************************************/
1114
1115 BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
1116 {
1117         uint32 expire;
1118         uint32 min_age;
1119
1120         if (!sampass)
1121                 return False;
1122         
1123         if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
1124                 return False;
1125
1126         if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) 
1127             || (expire==(uint32)-1) || (expire == 0)) {
1128                 if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
1129                         return False;
1130         } else {
1131                 if (!pdb_set_pass_must_change_time (sampass, 
1132                                                     pdb_get_pass_last_set_time(sampass)
1133                                                     + expire, PDB_CHANGED))
1134                         return False;
1135         }
1136         
1137         if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age) 
1138             || (min_age==(uint32)-1)) {
1139                 if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
1140                         return False;
1141         } else {
1142                 if (!pdb_set_pass_can_change_time (sampass, 
1143                                                     pdb_get_pass_last_set_time(sampass)
1144                                                     + min_age, PDB_CHANGED))
1145                         return False;
1146         }
1147         return True;
1148 }
1149
1150 /*********************************************************************
1151  Set the user's PLAINTEXT password.  Used as an interface to the above.
1152  Also sets the last change time to NOW.
1153  ********************************************************************/
1154
1155 BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
1156 {
1157         uchar new_lanman_p16[LM_HASH_LEN];
1158         uchar new_nt_p16[NT_HASH_LEN];
1159
1160         if (!sampass || !plaintext)
1161                 return False;
1162
1163         /* Calculate the MD4 hash (NT compatible) of the password */
1164         E_md4hash(plaintext, new_nt_p16);
1165
1166         if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) 
1167                 return False;
1168
1169         if (!E_deshash(plaintext, new_lanman_p16)) {
1170                 /* E_deshash returns false for 'long' passwords (> 14
1171                    DOS chars).  This allows us to match Win2k, which
1172                    does not store a LM hash for these passwords (which
1173                    would reduce the effective password length to 14 */
1174
1175                 if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) 
1176                         return False;
1177         } else {
1178                 if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) 
1179                         return False;
1180         }
1181
1182         if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) 
1183                 return False;
1184
1185         if (!pdb_set_pass_changed_now (sampass))
1186                 return False;
1187
1188         /* Store the password history. */
1189         if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
1190                 uchar *pwhistory;
1191                 uint32 pwHistLen;
1192                 account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
1193                 if (pwHistLen != 0){
1194                         uint32 current_history_len;
1195                         /* We need to make sure we don't have a race condition here - the
1196                            account policy history length can change between when the pw_history
1197                            was first loaded into the SAM_ACCOUNT struct and now.... JRA. */
1198                         pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);
1199
1200                         if (current_history_len != pwHistLen) {
1201                                 /* After closing and reopening SAM_ACCOUNT the history
1202                                         values will sync up. We can't do this here. */
1203
1204                                 /* current_history_len > pwHistLen is not a problem - we
1205                                         have more history than we need. */
1206
1207                                 if (current_history_len < pwHistLen) {
1208                                         /* Ensure we have space for the needed history. */
1209                                         uchar *new_history = TALLOC(sampass->mem_ctx,
1210                                                                 pwHistLen*PW_HISTORY_ENTRY_LEN);
1211                                         /* And copy it into the new buffer. */
1212                                         if (current_history_len) {
1213                                                 memcpy(new_history, pwhistory,
1214                                                         current_history_len*PW_HISTORY_ENTRY_LEN);
1215                                         }
1216                                         /* Clearing out any extra space. */
1217                                         memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN],
1218                                                 '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN);
1219                                         /* Finally replace it. */
1220                                         pwhistory = new_history;
1221                                 }
1222                         }
1223                         if (pwhistory && pwHistLen){
1224                                 /* Make room for the new password in the history list. */
1225                                 if (pwHistLen > 1) {
1226                                         memmove(&pwhistory[PW_HISTORY_ENTRY_LEN],
1227                                                 pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN );
1228                                 }
1229                                 /* Create the new salt as the first part of the history entry. */
1230                                 generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN);
1231
1232                                 /* Generate the md5 hash of the salt+new password as the second
1233                                         part of the history entry. */
1234
1235                                 E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]);
1236                                 pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);
1237                         } else {
1238                                 DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n"));
1239                         }
1240                 } else {
1241                         /* Set the history length to zero. */
1242                         pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
1243                 }
1244         }
1245
1246         return True;
1247 }
1248
1249 /* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */
1250 uint32 pdb_build_fields_present (SAM_ACCOUNT *sampass)
1251 {
1252         /* value set to all for testing */
1253         return 0x00ffffff;
1254 }