/src/samba/source3/passdb/pdb_get_set.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | struct samu 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-2006 |
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 3 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, see <http://www.gnu.org/licenses/>. |
22 | | */ |
23 | | |
24 | | #include "includes.h" |
25 | | #include "passdb.h" |
26 | | #include "../libcli/auth/libcli_auth.h" |
27 | | #include "../libcli/security/security.h" |
28 | | #include "../lib/util/bitmap.h" |
29 | | |
30 | | #undef DBGC_CLASS |
31 | 0 | #define DBGC_CLASS DBGC_PASSDB |
32 | | |
33 | | /** |
34 | | * @todo Redefine this to NULL, but this changes the API because |
35 | | * much of samba assumes that the pdb_get...() functions |
36 | | * return strings. (ie not null-pointers). |
37 | | * See also pdb_fill_default_sam(). |
38 | | */ |
39 | | |
40 | 0 | #define PDB_NOT_QUITE_NULL "" |
41 | | |
42 | | /********************************************************************* |
43 | | Test if a change time is a max value. Copes with old and new values |
44 | | of max. |
45 | | ********************************************************************/ |
46 | | |
47 | | bool pdb_is_password_change_time_max(time_t test_time) |
48 | 0 | { |
49 | 0 | if (test_time == get_time_t_max()) { |
50 | 0 | return true; |
51 | 0 | } |
52 | 0 | #if (defined(SIZEOF_TIME_T) && (SIZEOF_TIME_T == 8)) |
53 | 0 | if (test_time == 0x7FFFFFFFFFFFFFFFLL) { |
54 | 0 | return true; |
55 | 0 | } |
56 | 0 | #endif |
57 | 0 | if (test_time == 0x7FFFFFFF) { |
58 | 0 | return true; |
59 | 0 | } |
60 | 0 | return false; |
61 | 0 | } |
62 | | |
63 | | /********************************************************************* |
64 | | Return an unchanging version of max password change time - 0x7FFFFFFF. |
65 | | ********************************************************************/ |
66 | | |
67 | | static time_t pdb_password_change_time_max(void) |
68 | 0 | { |
69 | 0 | return 0x7FFFFFFF; |
70 | 0 | } |
71 | | |
72 | | /********************************************************************* |
73 | | Collection of get...() functions for struct samu. |
74 | | ********************************************************************/ |
75 | | |
76 | | uint32_t pdb_get_acct_ctrl(const struct samu *sampass) |
77 | 0 | { |
78 | 0 | return sampass->acct_ctrl; |
79 | 0 | } |
80 | | |
81 | | time_t pdb_get_logon_time(const struct samu *sampass) |
82 | 0 | { |
83 | 0 | return sampass->logon_time; |
84 | 0 | } |
85 | | |
86 | | time_t pdb_get_logoff_time(const struct samu *sampass) |
87 | 0 | { |
88 | 0 | return sampass->logoff_time; |
89 | 0 | } |
90 | | |
91 | | time_t pdb_get_kickoff_time(const struct samu *sampass) |
92 | 0 | { |
93 | 0 | return sampass->kickoff_time; |
94 | 0 | } |
95 | | |
96 | | time_t pdb_get_bad_password_time(const struct samu *sampass) |
97 | 0 | { |
98 | 0 | return sampass->bad_password_time; |
99 | 0 | } |
100 | | |
101 | | time_t pdb_get_pass_last_set_time(const struct samu *sampass) |
102 | 0 | { |
103 | 0 | return sampass->pass_last_set_time; |
104 | 0 | } |
105 | | |
106 | | time_t pdb_get_pass_can_change_time(const struct samu *sampass) |
107 | 0 | { |
108 | 0 | uint32_t allow; |
109 | | |
110 | | /* if the last set time is zero, it means the user cannot |
111 | | change their password, and this time must be zero. jmcd |
112 | | */ |
113 | 0 | if (sampass->pass_last_set_time == 0) |
114 | 0 | return (time_t) 0; |
115 | | |
116 | | /* if the time is max, and the field has been changed, |
117 | | we're trying to update this real value from the sampass |
118 | | to indicate that the user cannot change their password. jmcd |
119 | | */ |
120 | 0 | if (pdb_is_password_change_time_max(sampass->pass_can_change_time) && |
121 | 0 | IS_SAM_CHANGED(sampass, PDB_CANCHANGETIME)) |
122 | 0 | return sampass->pass_can_change_time; |
123 | | |
124 | 0 | if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &allow)) |
125 | 0 | allow = 0; |
126 | | |
127 | | /* in normal cases, just calculate it from policy */ |
128 | 0 | return sampass->pass_last_set_time + allow; |
129 | 0 | } |
130 | | |
131 | | /* we need this for loading from the backend, so that we don't overwrite |
132 | | non-changed max times, otherwise the pass_can_change checking won't work */ |
133 | | time_t pdb_get_pass_can_change_time_noncalc(const struct samu *sampass) |
134 | 0 | { |
135 | 0 | return sampass->pass_can_change_time; |
136 | 0 | } |
137 | | |
138 | | time_t pdb_get_pass_must_change_time(const struct samu *sampass) |
139 | 0 | { |
140 | 0 | uint32_t expire; |
141 | |
|
142 | 0 | if (sampass->pass_last_set_time == 0) |
143 | 0 | return (time_t) 0; |
144 | | |
145 | 0 | if (sampass->acct_ctrl & ACB_PWNOEXP) |
146 | 0 | return pdb_password_change_time_max(); |
147 | | |
148 | 0 | if (!pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &expire) |
149 | 0 | || expire == (uint32_t)-1 || expire == 0) |
150 | 0 | return get_time_t_max(); |
151 | | |
152 | 0 | return sampass->pass_last_set_time + expire; |
153 | 0 | } |
154 | | |
155 | | bool pdb_get_pass_can_change(const struct samu *sampass) |
156 | 0 | { |
157 | 0 | if (pdb_is_password_change_time_max(sampass->pass_can_change_time)) |
158 | 0 | return False; |
159 | 0 | return True; |
160 | 0 | } |
161 | | |
162 | | uint16_t pdb_get_logon_divs(const struct samu *sampass) |
163 | 0 | { |
164 | 0 | return sampass->logon_divs; |
165 | 0 | } |
166 | | |
167 | | uint32_t pdb_get_hours_len(const struct samu *sampass) |
168 | 0 | { |
169 | 0 | return sampass->hours_len; |
170 | 0 | } |
171 | | |
172 | | const uint8_t *pdb_get_hours(const struct samu *sampass) |
173 | 0 | { |
174 | 0 | return (sampass->hours); |
175 | 0 | } |
176 | | |
177 | | const uint8_t *pdb_get_nt_passwd(const struct samu *sampass) |
178 | 0 | { |
179 | 0 | SMB_ASSERT((!sampass->nt_pw.data) |
180 | 0 | || sampass->nt_pw.length == NT_HASH_LEN); |
181 | 0 | return (uint8_t *)sampass->nt_pw.data; |
182 | 0 | } |
183 | | |
184 | | const uint8_t *pdb_get_lanman_passwd(const struct samu *sampass) |
185 | 0 | { |
186 | 0 | SMB_ASSERT((!sampass->lm_pw.data) |
187 | 0 | || sampass->lm_pw.length == LM_HASH_LEN); |
188 | 0 | return (uint8_t *)sampass->lm_pw.data; |
189 | 0 | } |
190 | | |
191 | | const uint8_t *pdb_get_pw_history(const struct samu *sampass, uint32_t *current_hist_len) |
192 | 0 | { |
193 | 0 | SMB_ASSERT((!sampass->nt_pw_his.data) |
194 | 0 | || ((sampass->nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0)); |
195 | 0 | *current_hist_len = sampass->nt_pw_his.length / PW_HISTORY_ENTRY_LEN; |
196 | 0 | return (uint8_t *)sampass->nt_pw_his.data; |
197 | 0 | } |
198 | | |
199 | | /* Return the plaintext password if known. Most of the time |
200 | | it isn't, so don't assume anything magic about this function. |
201 | | |
202 | | Used to pass the plaintext to passdb backends that might |
203 | | want to store more than just the NTLM hashes. |
204 | | */ |
205 | | const char *pdb_get_plaintext_passwd(const struct samu *sampass) |
206 | 0 | { |
207 | 0 | return sampass->plaintext_pw; |
208 | 0 | } |
209 | | |
210 | | const struct dom_sid *pdb_get_user_sid(const struct samu *sampass) |
211 | 0 | { |
212 | 0 | return &sampass->user_sid; |
213 | 0 | } |
214 | | |
215 | | const struct dom_sid *pdb_get_group_sid(struct samu *sampass) |
216 | 0 | { |
217 | 0 | NTSTATUS status; |
218 | | |
219 | | /* Return the cached group SID if we have that */ |
220 | 0 | if (sampass->group_sid) { |
221 | 0 | return sampass->group_sid; |
222 | 0 | } |
223 | | |
224 | | /* No algorithmic mapping, meaning that we have to figure out the |
225 | | primary group SID according to group mapping and the user SID must |
226 | | be a newly allocated one. We rely on the user's Unix primary gid. |
227 | | We have no choice but to fail if we can't find it. */ |
228 | 0 | status = get_primary_group_sid(sampass, |
229 | 0 | pdb_get_username(sampass), |
230 | 0 | &sampass->unix_pw, |
231 | 0 | &sampass->group_sid); |
232 | 0 | if (!NT_STATUS_IS_OK(status)) { |
233 | 0 | return NULL; |
234 | 0 | } |
235 | | |
236 | 0 | return sampass->group_sid; |
237 | 0 | } |
238 | | |
239 | | /** |
240 | | * Get flags showing what is initialised in the struct samu |
241 | | * @param sampass the struct samu in question |
242 | | * @return the flags indicating the members initialised in the struct. |
243 | | **/ |
244 | | |
245 | | enum pdb_value_state pdb_get_init_flags(const struct samu *sampass, enum pdb_elements element) |
246 | 0 | { |
247 | 0 | enum pdb_value_state ret = PDB_DEFAULT; |
248 | |
|
249 | 0 | if (!sampass->change_flags || !sampass->set_flags) |
250 | 0 | return ret; |
251 | | |
252 | 0 | if (bitmap_query(sampass->set_flags, element)) { |
253 | 0 | DEBUG(11, ("element %d: SET\n", element)); |
254 | 0 | ret = PDB_SET; |
255 | 0 | } |
256 | |
|
257 | 0 | if (bitmap_query(sampass->change_flags, element)) { |
258 | 0 | DEBUG(11, ("element %d: CHANGED\n", element)); |
259 | 0 | ret = PDB_CHANGED; |
260 | 0 | } |
261 | |
|
262 | 0 | if (ret == PDB_DEFAULT) { |
263 | 0 | DEBUG(11, ("element %d: DEFAULT\n", element)); |
264 | 0 | } |
265 | |
|
266 | 0 | return ret; |
267 | 0 | } |
268 | | |
269 | | const char *pdb_get_username(const struct samu *sampass) |
270 | 0 | { |
271 | 0 | return sampass->username; |
272 | 0 | } |
273 | | |
274 | | const char *pdb_get_domain(const struct samu *sampass) |
275 | 0 | { |
276 | 0 | return sampass->domain; |
277 | 0 | } |
278 | | |
279 | | const char *pdb_get_nt_username(const struct samu *sampass) |
280 | 0 | { |
281 | 0 | return sampass->nt_username; |
282 | 0 | } |
283 | | |
284 | | const char *pdb_get_fullname(const struct samu *sampass) |
285 | 0 | { |
286 | 0 | return sampass->full_name; |
287 | 0 | } |
288 | | |
289 | | const char *pdb_get_homedir(const struct samu *sampass) |
290 | 0 | { |
291 | 0 | return sampass->home_dir; |
292 | 0 | } |
293 | | |
294 | | const char *pdb_get_dir_drive(const struct samu *sampass) |
295 | 0 | { |
296 | 0 | return sampass->dir_drive; |
297 | 0 | } |
298 | | |
299 | | const char *pdb_get_logon_script(const struct samu *sampass) |
300 | 0 | { |
301 | 0 | return sampass->logon_script; |
302 | 0 | } |
303 | | |
304 | | const char *pdb_get_profile_path(const struct samu *sampass) |
305 | 0 | { |
306 | 0 | return sampass->profile_path; |
307 | 0 | } |
308 | | |
309 | | const char *pdb_get_acct_desc(const struct samu *sampass) |
310 | 0 | { |
311 | 0 | return sampass->acct_desc; |
312 | 0 | } |
313 | | |
314 | | const char *pdb_get_workstations(const struct samu *sampass) |
315 | 0 | { |
316 | 0 | return sampass->workstations; |
317 | 0 | } |
318 | | |
319 | | const char *pdb_get_comment(const struct samu *sampass) |
320 | 0 | { |
321 | 0 | return sampass->comment; |
322 | 0 | } |
323 | | |
324 | | const char *pdb_get_munged_dial(const struct samu *sampass) |
325 | 0 | { |
326 | 0 | return sampass->munged_dial; |
327 | 0 | } |
328 | | |
329 | | uint16_t pdb_get_bad_password_count(const struct samu *sampass) |
330 | 0 | { |
331 | 0 | return sampass->bad_password_count; |
332 | 0 | } |
333 | | |
334 | | uint16_t pdb_get_logon_count(const struct samu *sampass) |
335 | 0 | { |
336 | 0 | return sampass->logon_count; |
337 | 0 | } |
338 | | |
339 | | uint16_t pdb_get_country_code(const struct samu *sampass) |
340 | 0 | { |
341 | 0 | return sampass->country_code; |
342 | 0 | } |
343 | | |
344 | | uint16_t pdb_get_code_page(const struct samu *sampass) |
345 | 0 | { |
346 | 0 | return sampass->code_page; |
347 | 0 | } |
348 | | |
349 | | uint32_t pdb_get_unknown_6(const struct samu *sampass) |
350 | 0 | { |
351 | 0 | return sampass->unknown_6; |
352 | 0 | } |
353 | | |
354 | | void *pdb_get_backend_private_data(const struct samu *sampass, const struct pdb_methods *my_methods) |
355 | 0 | { |
356 | 0 | if (my_methods == sampass->backend_private_methods) { |
357 | 0 | return sampass->backend_private_data; |
358 | 0 | } else { |
359 | 0 | return NULL; |
360 | 0 | } |
361 | 0 | } |
362 | | |
363 | | /********************************************************************* |
364 | | Collection of set...() functions for struct samu. |
365 | | ********************************************************************/ |
366 | | |
367 | | bool pdb_set_acct_ctrl(struct samu *sampass, uint32_t acct_ctrl, enum pdb_value_state flag) |
368 | 0 | { |
369 | 0 | sampass->acct_ctrl = acct_ctrl; |
370 | 0 | return pdb_set_init_flags(sampass, PDB_ACCTCTRL, flag); |
371 | 0 | } |
372 | | |
373 | | bool pdb_set_logon_time(struct samu *sampass, time_t mytime, enum pdb_value_state flag) |
374 | 0 | { |
375 | 0 | sampass->logon_time = mytime; |
376 | 0 | return pdb_set_init_flags(sampass, PDB_LOGONTIME, flag); |
377 | 0 | } |
378 | | |
379 | | bool pdb_set_logoff_time(struct samu *sampass, time_t mytime, enum pdb_value_state flag) |
380 | 0 | { |
381 | 0 | sampass->logoff_time = mytime; |
382 | 0 | return pdb_set_init_flags(sampass, PDB_LOGOFFTIME, flag); |
383 | 0 | } |
384 | | |
385 | | bool pdb_set_kickoff_time(struct samu *sampass, time_t mytime, enum pdb_value_state flag) |
386 | 0 | { |
387 | 0 | sampass->kickoff_time = mytime; |
388 | 0 | return pdb_set_init_flags(sampass, PDB_KICKOFFTIME, flag); |
389 | 0 | } |
390 | | |
391 | | bool pdb_set_bad_password_time(struct samu *sampass, time_t mytime, enum pdb_value_state flag) |
392 | 0 | { |
393 | 0 | sampass->bad_password_time = mytime; |
394 | 0 | return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_TIME, flag); |
395 | 0 | } |
396 | | |
397 | | bool pdb_set_pass_can_change_time(struct samu *sampass, time_t mytime, enum pdb_value_state flag) |
398 | 0 | { |
399 | 0 | sampass->pass_can_change_time = mytime; |
400 | 0 | return pdb_set_init_flags(sampass, PDB_CANCHANGETIME, flag); |
401 | 0 | } |
402 | | |
403 | | bool pdb_set_pass_last_set_time(struct samu *sampass, time_t mytime, enum pdb_value_state flag) |
404 | 0 | { |
405 | 0 | sampass->pass_last_set_time = mytime; |
406 | 0 | return pdb_set_init_flags(sampass, PDB_PASSLASTSET, flag); |
407 | 0 | } |
408 | | |
409 | | bool pdb_set_hours_len(struct samu *sampass, uint32_t len, enum pdb_value_state flag) |
410 | 0 | { |
411 | 0 | sampass->hours_len = len; |
412 | 0 | return pdb_set_init_flags(sampass, PDB_HOURSLEN, flag); |
413 | 0 | } |
414 | | |
415 | | bool pdb_set_logon_divs(struct samu *sampass, uint16_t hours, enum pdb_value_state flag) |
416 | 0 | { |
417 | 0 | sampass->logon_divs = hours; |
418 | 0 | return pdb_set_init_flags(sampass, PDB_LOGONDIVS, flag); |
419 | 0 | } |
420 | | |
421 | | /** |
422 | | * Set flags showing what is initialised in the struct samu |
423 | | * @param sampass the struct samu in question |
424 | | * @param flag The *new* flag to be set. Old flags preserved |
425 | | * this flag is only added. |
426 | | **/ |
427 | | |
428 | | bool pdb_set_init_flags(struct samu *sampass, enum pdb_elements element, enum pdb_value_state value_flag) |
429 | 0 | { |
430 | 0 | if (!sampass->set_flags) { |
431 | 0 | if ((sampass->set_flags = |
432 | 0 | bitmap_talloc(sampass, |
433 | 0 | PDB_COUNT))==NULL) { |
434 | 0 | DEBUG(0,("bitmap_talloc failed\n")); |
435 | 0 | return False; |
436 | 0 | } |
437 | 0 | } |
438 | 0 | if (!sampass->change_flags) { |
439 | 0 | if ((sampass->change_flags = |
440 | 0 | bitmap_talloc(sampass, |
441 | 0 | PDB_COUNT))==NULL) { |
442 | 0 | DEBUG(0,("bitmap_talloc failed\n")); |
443 | 0 | return False; |
444 | 0 | } |
445 | 0 | } |
446 | | |
447 | 0 | switch(value_flag) { |
448 | 0 | case PDB_CHANGED: |
449 | 0 | if (!bitmap_set(sampass->change_flags, element)) { |
450 | 0 | DEBUG(0,("Can't set flag: %d in change_flags.\n",element)); |
451 | 0 | return False; |
452 | 0 | } |
453 | 0 | if (!bitmap_set(sampass->set_flags, element)) { |
454 | 0 | DEBUG(0,("Can't set flag: %d in set_flags.\n",element)); |
455 | 0 | return False; |
456 | 0 | } |
457 | 0 | DEBUG(11, ("element %d -> now CHANGED\n", element)); |
458 | 0 | break; |
459 | 0 | case PDB_SET: |
460 | 0 | if (!bitmap_clear(sampass->change_flags, element)) { |
461 | 0 | DEBUG(0,("Can't set flag: %d in change_flags.\n",element)); |
462 | 0 | return False; |
463 | 0 | } |
464 | 0 | if (!bitmap_set(sampass->set_flags, element)) { |
465 | 0 | DEBUG(0,("Can't set flag: %d in set_flags.\n",element)); |
466 | 0 | return False; |
467 | 0 | } |
468 | 0 | DEBUG(11, ("element %d -> now SET\n", element)); |
469 | 0 | break; |
470 | 0 | case PDB_DEFAULT: |
471 | 0 | default: |
472 | 0 | if (!bitmap_clear(sampass->change_flags, element)) { |
473 | 0 | DEBUG(0,("Can't set flag: %d in change_flags.\n",element)); |
474 | 0 | return False; |
475 | 0 | } |
476 | 0 | if (!bitmap_clear(sampass->set_flags, element)) { |
477 | 0 | DEBUG(0,("Can't set flag: %d in set_flags.\n",element)); |
478 | 0 | return False; |
479 | 0 | } |
480 | 0 | DEBUG(11, ("element %d -> now DEFAULT\n", element)); |
481 | 0 | break; |
482 | 0 | } |
483 | | |
484 | 0 | return True; |
485 | 0 | } |
486 | | |
487 | | bool pdb_set_user_sid(struct samu *sampass, const struct dom_sid *u_sid, enum pdb_value_state flag) |
488 | 0 | { |
489 | 0 | struct dom_sid_buf buf; |
490 | |
|
491 | 0 | if (!u_sid) |
492 | 0 | return False; |
493 | | |
494 | 0 | sid_copy(&sampass->user_sid, u_sid); |
495 | |
|
496 | 0 | DEBUG(10, ("pdb_set_user_sid: setting user sid %s\n", |
497 | 0 | dom_sid_str_buf(&sampass->user_sid, &buf))); |
498 | |
|
499 | 0 | return pdb_set_init_flags(sampass, PDB_USERSID, flag); |
500 | 0 | } |
501 | | |
502 | | bool pdb_set_user_sid_from_string(struct samu *sampass, const char *u_sid, enum pdb_value_state flag) |
503 | 0 | { |
504 | 0 | struct dom_sid new_sid; |
505 | |
|
506 | 0 | if (!u_sid) |
507 | 0 | return False; |
508 | | |
509 | 0 | DEBUG(10, ("pdb_set_user_sid_from_string: setting user sid %s\n", |
510 | 0 | u_sid)); |
511 | |
|
512 | 0 | if (!string_to_sid(&new_sid, u_sid)) { |
513 | 0 | DEBUG(1, ("pdb_set_user_sid_from_string: %s isn't a valid SID!\n", u_sid)); |
514 | 0 | return False; |
515 | 0 | } |
516 | | |
517 | 0 | if (!pdb_set_user_sid(sampass, &new_sid, flag)) { |
518 | 0 | DEBUG(1, ("pdb_set_user_sid_from_string: could not set sid %s on struct samu!\n", u_sid)); |
519 | 0 | return False; |
520 | 0 | } |
521 | | |
522 | 0 | return True; |
523 | 0 | } |
524 | | |
525 | | /******************************************************************** |
526 | | We never fill this in from a passdb backend but rather set is |
527 | | based on the user's primary group membership. However, the |
528 | | struct samu* is overloaded and reused in domain memship code |
529 | | as well and built from the netr_SamInfo3 or PAC so we |
530 | | have to allow the explicitly setting of a group SID here. |
531 | | ********************************************************************/ |
532 | | |
533 | | bool pdb_set_group_sid(struct samu *sampass, const struct dom_sid *g_sid, enum pdb_value_state flag) |
534 | 0 | { |
535 | 0 | gid_t gid; |
536 | 0 | struct dom_sid dug_sid; |
537 | 0 | struct dom_sid_buf buf; |
538 | |
|
539 | 0 | if (!g_sid) |
540 | 0 | return False; |
541 | | |
542 | 0 | if ( !(sampass->group_sid = talloc( sampass, struct dom_sid )) ) { |
543 | 0 | return False; |
544 | 0 | } |
545 | | |
546 | | /* if we cannot resolve the SID to gid, then just ignore it and |
547 | | store DOMAIN_USERS as the primary groupSID */ |
548 | | |
549 | 0 | sid_compose(&dug_sid, get_global_sam_sid(), DOMAIN_RID_USERS); |
550 | |
|
551 | 0 | if (dom_sid_equal(&dug_sid, g_sid)) { |
552 | 0 | sid_copy(sampass->group_sid, &dug_sid); |
553 | 0 | } else if (sid_to_gid( g_sid, &gid ) ) { |
554 | 0 | sid_copy(sampass->group_sid, g_sid); |
555 | 0 | } else { |
556 | 0 | sid_copy(sampass->group_sid, &dug_sid); |
557 | 0 | } |
558 | |
|
559 | 0 | DEBUG(10, ("pdb_set_group_sid: setting group sid %s\n", |
560 | 0 | dom_sid_str_buf(sampass->group_sid, &buf))); |
561 | |
|
562 | 0 | return pdb_set_init_flags(sampass, PDB_GROUPSID, flag); |
563 | 0 | } |
564 | | |
565 | | /********************************************************************* |
566 | | Set the user's UNIX name. |
567 | | ********************************************************************/ |
568 | | |
569 | | bool pdb_set_username(struct samu *sampass, const char *username, enum pdb_value_state flag) |
570 | 0 | { |
571 | 0 | if (username) { |
572 | 0 | DEBUG(10, ("pdb_set_username: setting username %s, was %s\n", username, |
573 | 0 | (sampass->username)?(sampass->username):"NULL")); |
574 | |
|
575 | 0 | sampass->username = talloc_strdup(sampass, username); |
576 | |
|
577 | 0 | if (!sampass->username) { |
578 | 0 | DEBUG(0, ("pdb_set_username: talloc_strdup() failed!\n")); |
579 | 0 | return False; |
580 | 0 | } |
581 | 0 | } else { |
582 | 0 | sampass->username = PDB_NOT_QUITE_NULL; |
583 | 0 | } |
584 | | |
585 | 0 | return pdb_set_init_flags(sampass, PDB_USERNAME, flag); |
586 | 0 | } |
587 | | |
588 | | /********************************************************************* |
589 | | Set the domain name. |
590 | | ********************************************************************/ |
591 | | |
592 | | bool pdb_set_domain(struct samu *sampass, const char *domain, enum pdb_value_state flag) |
593 | 0 | { |
594 | 0 | if (domain) { |
595 | 0 | DEBUG(10, ("pdb_set_domain: setting domain %s, was %s\n", domain, |
596 | 0 | (sampass->domain)?(sampass->domain):"NULL")); |
597 | |
|
598 | 0 | sampass->domain = talloc_strdup(sampass, domain); |
599 | |
|
600 | 0 | if (!sampass->domain) { |
601 | 0 | DEBUG(0, ("pdb_set_domain: talloc_strdup() failed!\n")); |
602 | 0 | return False; |
603 | 0 | } |
604 | 0 | } else { |
605 | 0 | sampass->domain = PDB_NOT_QUITE_NULL; |
606 | 0 | } |
607 | | |
608 | 0 | return pdb_set_init_flags(sampass, PDB_DOMAIN, flag); |
609 | 0 | } |
610 | | |
611 | | /********************************************************************* |
612 | | Set the user's NT name. |
613 | | ********************************************************************/ |
614 | | |
615 | | bool pdb_set_nt_username(struct samu *sampass, const char *nt_username, enum pdb_value_state flag) |
616 | 0 | { |
617 | 0 | if (nt_username) { |
618 | 0 | DEBUG(10, ("pdb_set_nt_username: setting nt username %s, was %s\n", nt_username, |
619 | 0 | (sampass->nt_username)?(sampass->nt_username):"NULL")); |
620 | |
|
621 | 0 | sampass->nt_username = talloc_strdup(sampass, nt_username); |
622 | |
|
623 | 0 | if (!sampass->nt_username) { |
624 | 0 | DEBUG(0, ("pdb_set_nt_username: talloc_strdup() failed!\n")); |
625 | 0 | return False; |
626 | 0 | } |
627 | 0 | } else { |
628 | 0 | sampass->nt_username = PDB_NOT_QUITE_NULL; |
629 | 0 | } |
630 | | |
631 | 0 | return pdb_set_init_flags(sampass, PDB_NTUSERNAME, flag); |
632 | 0 | } |
633 | | |
634 | | /********************************************************************* |
635 | | Set the user's full name. |
636 | | ********************************************************************/ |
637 | | |
638 | | bool pdb_set_fullname(struct samu *sampass, const char *full_name, enum pdb_value_state flag) |
639 | 0 | { |
640 | 0 | if (full_name) { |
641 | 0 | DEBUG(10, ("pdb_set_full_name: setting full name %s, was %s\n", full_name, |
642 | 0 | (sampass->full_name)?(sampass->full_name):"NULL")); |
643 | |
|
644 | 0 | sampass->full_name = talloc_strdup(sampass, full_name); |
645 | |
|
646 | 0 | if (!sampass->full_name) { |
647 | 0 | DEBUG(0, ("pdb_set_fullname: talloc_strdup() failed!\n")); |
648 | 0 | return False; |
649 | 0 | } |
650 | 0 | } else { |
651 | 0 | sampass->full_name = PDB_NOT_QUITE_NULL; |
652 | 0 | } |
653 | | |
654 | 0 | return pdb_set_init_flags(sampass, PDB_FULLNAME, flag); |
655 | 0 | } |
656 | | |
657 | | /********************************************************************* |
658 | | Set the user's logon script. |
659 | | ********************************************************************/ |
660 | | |
661 | | bool pdb_set_logon_script(struct samu *sampass, const char *logon_script, enum pdb_value_state flag) |
662 | 0 | { |
663 | 0 | if (logon_script) { |
664 | 0 | DEBUG(10, ("pdb_set_logon_script: setting logon script %s, was %s\n", logon_script, |
665 | 0 | (sampass->logon_script)?(sampass->logon_script):"NULL")); |
666 | |
|
667 | 0 | sampass->logon_script = talloc_strdup(sampass, logon_script); |
668 | |
|
669 | 0 | if (!sampass->logon_script) { |
670 | 0 | DEBUG(0, ("pdb_set_logon_script: talloc_strdup() failed!\n")); |
671 | 0 | return False; |
672 | 0 | } |
673 | 0 | } else { |
674 | 0 | sampass->logon_script = PDB_NOT_QUITE_NULL; |
675 | 0 | } |
676 | | |
677 | 0 | return pdb_set_init_flags(sampass, PDB_LOGONSCRIPT, flag); |
678 | 0 | } |
679 | | |
680 | | /********************************************************************* |
681 | | Set the user's profile path. |
682 | | ********************************************************************/ |
683 | | |
684 | | bool pdb_set_profile_path(struct samu *sampass, const char *profile_path, enum pdb_value_state flag) |
685 | 0 | { |
686 | 0 | if (profile_path) { |
687 | 0 | DEBUG(10, ("pdb_set_profile_path: setting profile path %s, was %s\n", profile_path, |
688 | 0 | (sampass->profile_path)?(sampass->profile_path):"NULL")); |
689 | |
|
690 | 0 | sampass->profile_path = talloc_strdup(sampass, profile_path); |
691 | |
|
692 | 0 | if (!sampass->profile_path) { |
693 | 0 | DEBUG(0, ("pdb_set_profile_path: talloc_strdup() failed!\n")); |
694 | 0 | return False; |
695 | 0 | } |
696 | 0 | } else { |
697 | 0 | sampass->profile_path = PDB_NOT_QUITE_NULL; |
698 | 0 | } |
699 | | |
700 | 0 | return pdb_set_init_flags(sampass, PDB_PROFILE, flag); |
701 | 0 | } |
702 | | |
703 | | /********************************************************************* |
704 | | Set the user's directory drive. |
705 | | ********************************************************************/ |
706 | | |
707 | | bool pdb_set_dir_drive(struct samu *sampass, const char *dir_drive, enum pdb_value_state flag) |
708 | 0 | { |
709 | 0 | if (dir_drive) { |
710 | 0 | DEBUG(10, ("pdb_set_dir_drive: setting dir drive %s, was %s\n", dir_drive, |
711 | 0 | (sampass->dir_drive)?(sampass->dir_drive):"NULL")); |
712 | |
|
713 | 0 | sampass->dir_drive = talloc_strdup(sampass, dir_drive); |
714 | |
|
715 | 0 | if (!sampass->dir_drive) { |
716 | 0 | DEBUG(0, ("pdb_set_dir_drive: talloc_strdup() failed!\n")); |
717 | 0 | return False; |
718 | 0 | } |
719 | |
|
720 | 0 | } else { |
721 | 0 | sampass->dir_drive = PDB_NOT_QUITE_NULL; |
722 | 0 | } |
723 | | |
724 | 0 | return pdb_set_init_flags(sampass, PDB_DRIVE, flag); |
725 | 0 | } |
726 | | |
727 | | /********************************************************************* |
728 | | Set the user's home directory. |
729 | | ********************************************************************/ |
730 | | |
731 | | bool pdb_set_homedir(struct samu *sampass, const char *home_dir, enum pdb_value_state flag) |
732 | 0 | { |
733 | 0 | if (home_dir) { |
734 | 0 | DEBUG(10, ("pdb_set_homedir: setting home dir %s, was %s\n", home_dir, |
735 | 0 | (sampass->home_dir)?(sampass->home_dir):"NULL")); |
736 | |
|
737 | 0 | sampass->home_dir = talloc_strdup(sampass, home_dir); |
738 | |
|
739 | 0 | if (!sampass->home_dir) { |
740 | 0 | DEBUG(0, ("pdb_set_home_dir: talloc_strdup() failed!\n")); |
741 | 0 | return False; |
742 | 0 | } |
743 | 0 | } else { |
744 | 0 | sampass->home_dir = PDB_NOT_QUITE_NULL; |
745 | 0 | } |
746 | | |
747 | 0 | return pdb_set_init_flags(sampass, PDB_SMBHOME, flag); |
748 | 0 | } |
749 | | |
750 | | /********************************************************************* |
751 | | Set the user's account description. |
752 | | ********************************************************************/ |
753 | | |
754 | | bool pdb_set_acct_desc(struct samu *sampass, const char *acct_desc, enum pdb_value_state flag) |
755 | 0 | { |
756 | 0 | if (acct_desc) { |
757 | 0 | sampass->acct_desc = talloc_strdup(sampass, acct_desc); |
758 | |
|
759 | 0 | if (!sampass->acct_desc) { |
760 | 0 | DEBUG(0, ("pdb_set_acct_desc: talloc_strdup() failed!\n")); |
761 | 0 | return False; |
762 | 0 | } |
763 | 0 | } else { |
764 | 0 | sampass->acct_desc = PDB_NOT_QUITE_NULL; |
765 | 0 | } |
766 | | |
767 | 0 | return pdb_set_init_flags(sampass, PDB_ACCTDESC, flag); |
768 | 0 | } |
769 | | |
770 | | /********************************************************************* |
771 | | Set the user's workstation allowed list. |
772 | | ********************************************************************/ |
773 | | |
774 | | bool pdb_set_workstations(struct samu *sampass, const char *workstations, enum pdb_value_state flag) |
775 | 0 | { |
776 | 0 | if (workstations) { |
777 | 0 | DEBUG(10, ("pdb_set_workstations: setting workstations %s, was %s\n", workstations, |
778 | 0 | (sampass->workstations)?(sampass->workstations):"NULL")); |
779 | |
|
780 | 0 | sampass->workstations = talloc_strdup(sampass, workstations); |
781 | |
|
782 | 0 | if (!sampass->workstations) { |
783 | 0 | DEBUG(0, ("pdb_set_workstations: talloc_strdup() failed!\n")); |
784 | 0 | return False; |
785 | 0 | } |
786 | 0 | } else { |
787 | 0 | sampass->workstations = PDB_NOT_QUITE_NULL; |
788 | 0 | } |
789 | | |
790 | 0 | return pdb_set_init_flags(sampass, PDB_WORKSTATIONS, flag); |
791 | 0 | } |
792 | | |
793 | | /********************************************************************* |
794 | | ********************************************************************/ |
795 | | |
796 | | bool pdb_set_comment(struct samu *sampass, const char *comment, enum pdb_value_state flag) |
797 | 0 | { |
798 | 0 | if (comment) { |
799 | 0 | sampass->comment = talloc_strdup(sampass, comment); |
800 | |
|
801 | 0 | if (!sampass->comment) { |
802 | 0 | DEBUG(0, ("pdb_set_comment: talloc_strdup() failed!\n")); |
803 | 0 | return False; |
804 | 0 | } |
805 | 0 | } else { |
806 | 0 | sampass->comment = PDB_NOT_QUITE_NULL; |
807 | 0 | } |
808 | | |
809 | 0 | return pdb_set_init_flags(sampass, PDB_COMMENT, flag); |
810 | 0 | } |
811 | | |
812 | | /********************************************************************* |
813 | | Set the user's dial string. |
814 | | ********************************************************************/ |
815 | | |
816 | | bool pdb_set_munged_dial(struct samu *sampass, const char *munged_dial, enum pdb_value_state flag) |
817 | 0 | { |
818 | 0 | if (munged_dial) { |
819 | 0 | sampass->munged_dial = talloc_strdup(sampass, munged_dial); |
820 | |
|
821 | 0 | if (!sampass->munged_dial) { |
822 | 0 | DEBUG(0, ("pdb_set_munged_dial: talloc_strdup() failed!\n")); |
823 | 0 | return False; |
824 | 0 | } |
825 | 0 | } else { |
826 | 0 | sampass->munged_dial = PDB_NOT_QUITE_NULL; |
827 | 0 | } |
828 | | |
829 | 0 | return pdb_set_init_flags(sampass, PDB_MUNGEDDIAL, flag); |
830 | 0 | } |
831 | | |
832 | | /********************************************************************* |
833 | | Set the user's NT hash. |
834 | | ********************************************************************/ |
835 | | |
836 | | bool pdb_set_nt_passwd(struct samu *sampass, const uint8_t pwd[NT_HASH_LEN], enum pdb_value_state flag) |
837 | 0 | { |
838 | 0 | data_blob_clear_free(&sampass->nt_pw); |
839 | |
|
840 | 0 | if (pwd) { |
841 | 0 | sampass->nt_pw = |
842 | 0 | data_blob_talloc(sampass, pwd, NT_HASH_LEN); |
843 | 0 | } else { |
844 | 0 | sampass->nt_pw = data_blob_null; |
845 | 0 | } |
846 | |
|
847 | 0 | return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag); |
848 | 0 | } |
849 | | |
850 | | /********************************************************************* |
851 | | Set the user's LM hash. |
852 | | ********************************************************************/ |
853 | | |
854 | | bool pdb_set_lanman_passwd(struct samu *sampass, const uint8_t pwd[LM_HASH_LEN], enum pdb_value_state flag) |
855 | 0 | { |
856 | 0 | data_blob_clear_free(&sampass->lm_pw); |
857 | | |
858 | | /* on keep the password if we are allowing LANMAN authentication */ |
859 | |
|
860 | 0 | if (pwd && (flag != PDB_CHANGED || lp_lanman_auth())) { |
861 | 0 | sampass->lm_pw = data_blob_talloc(sampass, pwd, LM_HASH_LEN); |
862 | 0 | } else { |
863 | 0 | sampass->lm_pw = data_blob_null; |
864 | 0 | } |
865 | |
|
866 | 0 | return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag); |
867 | 0 | } |
868 | | |
869 | | /********************************************************************* |
870 | | Set the user's password history hash. historyLen is the number of |
871 | | PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN length |
872 | | entries to store in the history - this must match the size of the uint8_t array |
873 | | in pwd. |
874 | | ********************************************************************/ |
875 | | |
876 | | bool pdb_set_pw_history(struct samu *sampass, const uint8_t *pwd, uint32_t historyLen, enum pdb_value_state flag) |
877 | 0 | { |
878 | 0 | DATA_BLOB new_nt_pw_his = {}; |
879 | |
|
880 | 0 | if (historyLen && pwd){ |
881 | 0 | new_nt_pw_his = data_blob_talloc(sampass, |
882 | 0 | pwd, historyLen*PW_HISTORY_ENTRY_LEN); |
883 | 0 | if (new_nt_pw_his.length == 0) { |
884 | 0 | DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n")); |
885 | 0 | return False; |
886 | 0 | } |
887 | 0 | } |
888 | | |
889 | 0 | data_blob_clear_free(&sampass->nt_pw_his); |
890 | 0 | sampass->nt_pw_his = new_nt_pw_his; |
891 | |
|
892 | 0 | return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag); |
893 | 0 | } |
894 | | |
895 | | /********************************************************************* |
896 | | Set the user's plaintext password only (base procedure, see helper |
897 | | below) |
898 | | ********************************************************************/ |
899 | | |
900 | | bool pdb_set_plaintext_pw_only(struct samu *sampass, const char *password, enum pdb_value_state flag) |
901 | 0 | { |
902 | 0 | BURN_STR(sampass->plaintext_pw); |
903 | |
|
904 | 0 | if (password != NULL) { |
905 | 0 | sampass->plaintext_pw = talloc_strdup(sampass, password); |
906 | |
|
907 | 0 | if (!sampass->plaintext_pw) { |
908 | 0 | DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n")); |
909 | 0 | return False; |
910 | 0 | } |
911 | 0 | } else { |
912 | 0 | sampass->plaintext_pw = NULL; |
913 | 0 | } |
914 | | |
915 | 0 | return pdb_set_init_flags(sampass, PDB_PLAINTEXT_PW, flag); |
916 | 0 | } |
917 | | |
918 | | bool pdb_set_bad_password_count(struct samu *sampass, uint16_t bad_password_count, enum pdb_value_state flag) |
919 | 0 | { |
920 | 0 | sampass->bad_password_count = bad_password_count; |
921 | 0 | return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag); |
922 | 0 | } |
923 | | |
924 | | bool pdb_set_logon_count(struct samu *sampass, uint16_t logon_count, enum pdb_value_state flag) |
925 | 0 | { |
926 | 0 | sampass->logon_count = logon_count; |
927 | 0 | return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag); |
928 | 0 | } |
929 | | |
930 | | bool pdb_set_country_code(struct samu *sampass, uint16_t country_code, |
931 | | enum pdb_value_state flag) |
932 | 0 | { |
933 | 0 | sampass->country_code = country_code; |
934 | 0 | return pdb_set_init_flags(sampass, PDB_COUNTRY_CODE, flag); |
935 | 0 | } |
936 | | |
937 | | bool pdb_set_code_page(struct samu *sampass, uint16_t code_page, |
938 | | enum pdb_value_state flag) |
939 | 0 | { |
940 | 0 | sampass->code_page = code_page; |
941 | 0 | return pdb_set_init_flags(sampass, PDB_CODE_PAGE, flag); |
942 | 0 | } |
943 | | |
944 | | bool pdb_set_unknown_6(struct samu *sampass, uint32_t unkn, enum pdb_value_state flag) |
945 | 0 | { |
946 | 0 | sampass->unknown_6 = unkn; |
947 | 0 | return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag); |
948 | 0 | } |
949 | | |
950 | | bool pdb_set_hours(struct samu *sampass, const uint8_t *hours, int hours_len, |
951 | | enum pdb_value_state flag) |
952 | 0 | { |
953 | 0 | if (hours_len > sizeof(sampass->hours)) { |
954 | 0 | return false; |
955 | 0 | } |
956 | | |
957 | 0 | if (!hours) { |
958 | 0 | memset ((char *)sampass->hours, 0, hours_len); |
959 | 0 | } else { |
960 | 0 | memcpy (sampass->hours, hours, hours_len); |
961 | 0 | } |
962 | |
|
963 | 0 | return pdb_set_init_flags(sampass, PDB_HOURS, flag); |
964 | 0 | } |
965 | | |
966 | | bool pdb_set_backend_private_data(struct samu *sampass, void *private_data, |
967 | | void (*free_fn)(void **), |
968 | | const struct pdb_methods *my_methods, |
969 | | enum pdb_value_state flag) |
970 | 0 | { |
971 | 0 | if (sampass->backend_private_data && |
972 | 0 | sampass->backend_private_data_free_fn) { |
973 | 0 | sampass->backend_private_data_free_fn( |
974 | 0 | &sampass->backend_private_data); |
975 | 0 | } |
976 | |
|
977 | 0 | sampass->backend_private_data = private_data; |
978 | 0 | sampass->backend_private_data_free_fn = free_fn; |
979 | 0 | sampass->backend_private_methods = my_methods; |
980 | |
|
981 | 0 | return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag); |
982 | 0 | } |
983 | | |
984 | | |
985 | | /* Helpful interfaces to the above */ |
986 | | |
987 | | bool pdb_set_pass_can_change(struct samu *sampass, bool canchange) |
988 | 0 | { |
989 | 0 | return pdb_set_pass_can_change_time(sampass, |
990 | 0 | canchange ? 0 : pdb_password_change_time_max(), |
991 | 0 | PDB_CHANGED); |
992 | 0 | } |
993 | | |
994 | | |
995 | | /********************************************************************* |
996 | | Set the user's PLAINTEXT password. Used as an interface to the above. |
997 | | Also sets the last change time to NOW. |
998 | | ********************************************************************/ |
999 | | |
1000 | | bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) |
1001 | 0 | { |
1002 | 0 | uchar new_lanman_p16[LM_HASH_LEN]; |
1003 | 0 | uchar new_nt_p16[NT_HASH_LEN]; |
1004 | 0 | bool ok; |
1005 | |
|
1006 | 0 | if (!plaintext) |
1007 | 0 | return False; |
1008 | | |
1009 | | /* Calculate the MD4 hash (NT compatible) of the password */ |
1010 | 0 | E_md4hash(plaintext, new_nt_p16); |
1011 | |
|
1012 | 0 | if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) { |
1013 | 0 | ZERO_STRUCT(new_nt_p16); |
1014 | 0 | return False; |
1015 | 0 | } |
1016 | | |
1017 | 0 | if (!E_deshash(plaintext, new_lanman_p16)) { |
1018 | | /* E_deshash returns false for 'long' passwords (> 14 |
1019 | | DOS chars). This allows us to match Win2k, which |
1020 | | does not store a LM hash for these passwords (which |
1021 | | would reduce the effective password length to 14 */ |
1022 | |
|
1023 | 0 | if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) { |
1024 | 0 | ZERO_STRUCT(new_nt_p16); |
1025 | 0 | ZERO_STRUCT(new_lanman_p16); |
1026 | 0 | return False; |
1027 | 0 | } |
1028 | 0 | } else { |
1029 | 0 | if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) { |
1030 | 0 | ZERO_STRUCT(new_nt_p16); |
1031 | 0 | ZERO_STRUCT(new_lanman_p16); |
1032 | 0 | return False; |
1033 | 0 | } |
1034 | 0 | } |
1035 | 0 | ZERO_STRUCT(new_lanman_p16); |
1036 | |
|
1037 | 0 | if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) { |
1038 | 0 | ZERO_STRUCT(new_nt_p16); |
1039 | 0 | return False; |
1040 | 0 | } |
1041 | | |
1042 | 0 | if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) { |
1043 | 0 | ZERO_STRUCT(new_nt_p16); |
1044 | 0 | return False; |
1045 | 0 | } |
1046 | | |
1047 | 0 | ok = pdb_update_history(sampass, new_nt_p16); |
1048 | 0 | ZERO_STRUCT(new_nt_p16); |
1049 | 0 | return ok; |
1050 | 0 | } |
1051 | | |
1052 | | /********************************************************************* |
1053 | | Update password history after change |
1054 | | ********************************************************************/ |
1055 | | |
1056 | | bool pdb_update_history(struct samu *sampass, const uint8_t new_nt[NT_HASH_LEN]) |
1057 | 0 | { |
1058 | 0 | uchar *pwhistory; |
1059 | 0 | uint32_t pwHistLen; |
1060 | 0 | uint32_t current_history_len; |
1061 | 0 | const uint8_t *current_history; |
1062 | |
|
1063 | 0 | if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) { |
1064 | | /* |
1065 | | * No password history for non-user accounts |
1066 | | */ |
1067 | 0 | return true; |
1068 | 0 | } |
1069 | | |
1070 | 0 | pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); |
1071 | |
|
1072 | 0 | if (pwHistLen == 0) { |
1073 | | /* Set the history length to zero. */ |
1074 | 0 | pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); |
1075 | 0 | return true; |
1076 | 0 | } |
1077 | | |
1078 | | /* |
1079 | | * We need to make sure we don't have a race condition here - |
1080 | | * the account policy history length can change between when |
1081 | | * the pw_history was first loaded into the struct samu struct |
1082 | | * and now.... JRA. |
1083 | | */ |
1084 | 0 | current_history = pdb_get_pw_history(sampass, ¤t_history_len); |
1085 | 0 | if ((current_history_len != 0) && (current_history == NULL)) { |
1086 | 0 | DEBUG(1, ("pdb_update_history: pwhistory == NULL!\n")); |
1087 | 0 | return false; |
1088 | 0 | } |
1089 | | |
1090 | | /* |
1091 | | * Ensure we have space for the needed history. This |
1092 | | * also takes care of an account which did not have |
1093 | | * any history at all so far, i.e. pwhistory==NULL |
1094 | | */ |
1095 | 0 | pwhistory = talloc_zero_array( |
1096 | 0 | sampass, uchar, |
1097 | 0 | pwHistLen*PW_HISTORY_ENTRY_LEN); |
1098 | 0 | if (!pwhistory) { |
1099 | 0 | return false; |
1100 | 0 | } |
1101 | | |
1102 | 0 | memcpy(pwhistory, current_history, |
1103 | 0 | current_history_len*PW_HISTORY_ENTRY_LEN); |
1104 | | |
1105 | | /* |
1106 | | * Make room for the new password in the history list. |
1107 | | */ |
1108 | 0 | if (pwHistLen > 1) { |
1109 | 0 | memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], pwhistory, |
1110 | 0 | (pwHistLen-1)*PW_HISTORY_ENTRY_LEN ); |
1111 | 0 | } |
1112 | | |
1113 | | /* |
1114 | | * Fill the salt area with 0-s: this indicates that |
1115 | | * a plain nt hash is stored in the has area. |
1116 | | * The old format was to store a 16 byte salt and |
1117 | | * then an md5hash of the nt_hash concatenated with |
1118 | | * the salt. |
1119 | | */ |
1120 | 0 | memset(pwhistory, 0, PW_HISTORY_SALT_LEN); |
1121 | | |
1122 | | /* |
1123 | | * Store the plain nt hash in the second 16 bytes. |
1124 | | * The old format was to store the md5 hash of |
1125 | | * the salt+newpw. |
1126 | | */ |
1127 | 0 | memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt, SALTED_MD5_HASH_LEN); |
1128 | |
|
1129 | 0 | pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); |
1130 | |
|
1131 | 0 | return True; |
1132 | |
|
1133 | 0 | } |
1134 | | |
1135 | | /* check for any PDB_SET/CHANGED field and fill the appropriate mask bit */ |
1136 | | uint32_t pdb_build_fields_present(struct samu *sampass) |
1137 | 0 | { |
1138 | | /* value set to all for testing */ |
1139 | 0 | return 0x00ffffff; |
1140 | 0 | } |
1141 | | |
1142 | | /********************************************************************** |
1143 | | Helper function to determine for update_sam_account whether |
1144 | | we need LDAP modification. |
1145 | | *********************************************************************/ |
1146 | | |
1147 | | bool pdb_element_is_changed(const struct samu *sampass, |
1148 | | enum pdb_elements element) |
1149 | 0 | { |
1150 | 0 | return IS_SAM_CHANGED(sampass, element); |
1151 | 0 | } |
1152 | | |
1153 | | /********************************************************************** |
1154 | | Helper function to determine for update_sam_account whether |
1155 | | we need LDAP modification. |
1156 | | *********************************************************************/ |
1157 | | |
1158 | | bool pdb_element_is_set_or_changed(const struct samu *sampass, |
1159 | | enum pdb_elements element) |
1160 | 0 | { |
1161 | 0 | return (IS_SAM_SET(sampass, element) || |
1162 | 0 | IS_SAM_CHANGED(sampass, element)); |
1163 | 0 | } |