2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Jeremy Allison 1996-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int DEBUGLEVEL
;
27 extern DOM_SID global_sam_sid
;
28 extern fstring global_sam_name
;
30 extern DOM_SID global_member_sid
;
31 extern fstring global_myworkgroup
;
33 extern DOM_SID global_sid_S_1_5_20
;
35 extern pstring global_myname
;
38 * A list of the rids of well known BUILTIN and Domain users
42 rid_name builtin_alias_rids
[] =
44 { BUILTIN_ALIAS_RID_ADMINS
, "Administrators" },
45 { BUILTIN_ALIAS_RID_USERS
, "Users" },
46 { BUILTIN_ALIAS_RID_GUESTS
, "Guests" },
47 { BUILTIN_ALIAS_RID_POWER_USERS
, "Power Users" },
49 { BUILTIN_ALIAS_RID_ACCOUNT_OPS
, "Account Operators" },
50 { BUILTIN_ALIAS_RID_SYSTEM_OPS
, "System Operators" },
51 { BUILTIN_ALIAS_RID_PRINT_OPS
, "Print Operators" },
52 { BUILTIN_ALIAS_RID_BACKUP_OPS
, "Backup Operators" },
53 { BUILTIN_ALIAS_RID_REPLICATOR
, "Replicator" },
57 /* array lookup of well-known Domain RID users. */
58 rid_name domain_user_rids
[] =
60 { DOMAIN_USER_RID_ADMIN
, "Administrator" },
61 { DOMAIN_USER_RID_GUEST
, "Guest" },
65 /* array lookup of well-known Domain RID groups. */
66 rid_name domain_group_rids
[] =
68 { DOMAIN_GROUP_RID_ADMINS
, "Domain Admins" },
69 { DOMAIN_GROUP_RID_USERS
, "Domain Users" },
70 { DOMAIN_GROUP_RID_GUESTS
, "Domain Guests" },
75 /*******************************************************************
77 ********************************************************************/
78 uint32
lookup_wk_group_name(const char *group_name
, const char *domain
,
79 DOM_SID
*sid
, uint8
*type
)
82 int i
= -1; /* start do loop at -1 */
84 (*type
) = SID_NAME_WKN_GRP
;
86 if (strequal(domain
, global_sam_name
))
88 sid_copy(sid
, &global_sam_sid
);
90 else if (strequal(domain
, "BUILTIN"))
92 sid_copy(sid
, &global_sid_S_1_5_20
);
96 return 0xC0000000 | NT_STATUS_NONE_MAPPED
;
99 do /* find, if it exists, a group rid for the group name */
102 rid
= domain_group_rids
[i
].rid
;
103 grp_name
= domain_group_rids
[i
].name
;
105 if (strequal(grp_name
, group_name
))
107 sid_append_rid(sid
, rid
);
112 } while (grp_name
!= NULL
);
114 return 0xC0000000 | NT_STATUS_NONE_MAPPED
;
117 /*******************************************************************
119 ********************************************************************/
120 uint32
lookup_wk_user_name(const char *user_name
, const char *domain
,
121 DOM_SID
*sid
, uint8
*type
)
124 int i
= -1; /* start do loop at -1 */
125 (*type
) = SID_NAME_USER
;
127 if (strequal(domain
, global_sam_name
))
129 sid_copy(sid
, &global_sam_sid
);
131 else if (strequal(domain
, "BUILTIN"))
133 sid_copy(sid
, &global_sid_S_1_5_20
);
137 return 0xC0000000 | NT_STATUS_NONE_MAPPED
;
140 do /* find, if it exists, a alias rid for the alias name */
143 usr_name
= domain_user_rids
[i
].name
;
145 } while (usr_name
!= NULL
&& !strequal(usr_name
, user_name
));
147 if (usr_name
!= NULL
)
149 sid_append_rid(sid
, domain_user_rids
[i
].rid
);
153 return 0xC0000000 | NT_STATUS_NONE_MAPPED
;
156 /*******************************************************************
157 lookup_builtin_alias_name
158 ********************************************************************/
159 uint32
lookup_builtin_alias_name(const char *alias_name
, const char *domain
,
160 DOM_SID
*sid
, uint8
*type
)
166 if (strequal(domain
, "BUILTIN"))
170 sid_copy(sid
, &global_sid_S_1_5_20
);
175 return 0xC0000000 | NT_STATUS_NONE_MAPPED
;
178 do /* find, if it exists, a alias rid for the alias name*/
180 rid
= builtin_alias_rids
[i
].rid
;
181 als_name
= builtin_alias_rids
[i
].name
;
183 if (strequal(als_name
, alias_name
))
187 sid_append_rid(sid
, rid
);
192 (*type
) = SID_NAME_ALIAS
;
200 } while (als_name
!= NULL
);
202 return 0xC0000000 | NT_STATUS_NONE_MAPPED
;
204 /**********************************************************
205 Encode the account control bits into a string.
206 length = length of string to encode into (including terminating
207 null). length *MUST BE MORE THAN 2* !
208 **********************************************************/
210 char *pwdb_encode_acct_ctrl(uint16 acct_ctrl
, size_t length
)
212 static fstring acct_str
;
217 if (acct_ctrl
& ACB_PWNOTREQ
) acct_str
[i
++] = 'N';
218 if (acct_ctrl
& ACB_DISABLED
) acct_str
[i
++] = 'D';
219 if (acct_ctrl
& ACB_HOMDIRREQ
) acct_str
[i
++] = 'H';
220 if (acct_ctrl
& ACB_TEMPDUP
) acct_str
[i
++] = 'T';
221 if (acct_ctrl
& ACB_NORMAL
) acct_str
[i
++] = 'U';
222 if (acct_ctrl
& ACB_MNS
) acct_str
[i
++] = 'M';
223 if (acct_ctrl
& ACB_WSTRUST
) acct_str
[i
++] = 'W';
224 if (acct_ctrl
& ACB_SVRTRUST
) acct_str
[i
++] = 'S';
225 if (acct_ctrl
& ACB_AUTOLOCK
) acct_str
[i
++] = 'L';
226 if (acct_ctrl
& ACB_PWNOEXP
) acct_str
[i
++] = 'X';
227 if (acct_ctrl
& ACB_DOMTRUST
) acct_str
[i
++] = 'I';
229 for ( ; i
< length
- 2 ; i
++ )
236 acct_str
[i
++] = '\0';
241 /**********************************************************
242 Decode the account control bits from a string.
244 this function breaks coding standards minimum line width of 80 chars.
245 reason: vertical line-up code clarity - all case statements fit into
246 15 lines, which is more important.
247 **********************************************************/
249 uint16
pwdb_decode_acct_ctrl(const char *p
)
251 uint16 acct_ctrl
= 0;
252 BOOL finished
= False
;
255 * Check if the account type bits have been encoded after the
256 * NT password (in the form [NDHTUWSLXI]).
259 if (*p
!= '[') return 0;
261 for (p
++; *p
&& !finished
; p
++)
265 case 'N': { acct_ctrl
|= ACB_PWNOTREQ
; break; /* 'N'o password. */ }
266 case 'D': { acct_ctrl
|= ACB_DISABLED
; break; /* 'D'isabled. */ }
267 case 'H': { acct_ctrl
|= ACB_HOMDIRREQ
; break; /* 'H'omedir required. */ }
268 case 'T': { acct_ctrl
|= ACB_TEMPDUP
; break; /* 'T'emp account. */ }
269 case 'U': { acct_ctrl
|= ACB_NORMAL
; break; /* 'U'ser account (normal). */ }
270 case 'M': { acct_ctrl
|= ACB_MNS
; break; /* 'M'NS logon user account. What is this ? */ }
271 case 'W': { acct_ctrl
|= ACB_WSTRUST
; break; /* 'W'orkstation account. */ }
272 case 'S': { acct_ctrl
|= ACB_SVRTRUST
; break; /* 'S'erver account. */ }
273 case 'L': { acct_ctrl
|= ACB_AUTOLOCK
; break; /* 'L'ocked account. */ }
274 case 'X': { acct_ctrl
|= ACB_PWNOEXP
; break; /* No 'X'piry on password */ }
275 case 'I': { acct_ctrl
|= ACB_DOMTRUST
; break; /* 'I'nterdomain trust account. */ }
281 default: { finished
= True
; }
288 /*******************************************************************
289 gets password-database-format time from a string.
290 ********************************************************************/
292 static time_t get_time_from_string(const char *p
)
296 for (i
= 0; i
< 8; i
++)
298 if (p
[i
] == '\0' || !isxdigit((int)(p
[i
]&0xFF)))
306 * p points at 8 characters of hex digits -
307 * read into a time_t as the seconds since
308 * 1970 that the password was last changed.
310 return (time_t)strtol(p
, NULL
, 16);
315 /*******************************************************************
316 gets password last set time
317 ********************************************************************/
319 time_t pwdb_get_last_set_time(const char *p
)
321 if (*p
&& !StrnCaseCmp(p
, "LCT-", 4))
323 return get_time_from_string(p
+ 4);
329 /*******************************************************************
330 sets password-database-format time in a string.
331 ********************************************************************/
332 static void set_time_in_string(char *p
, int max_len
, char *type
, time_t t
)
334 slprintf(p
, max_len
, ":%s-%08X:", type
, (uint32
)t
);
337 /*******************************************************************
339 ********************************************************************/
340 void pwdb_set_logon_time(char *p
, int max_len
, time_t t
)
342 set_time_in_string(p
, max_len
, "LNT", t
);
345 /*******************************************************************
347 ********************************************************************/
348 void pwdb_set_logoff_time(char *p
, int max_len
, time_t t
)
350 set_time_in_string(p
, max_len
, "LOT", t
);
353 /*******************************************************************
355 ********************************************************************/
356 void pwdb_set_kickoff_time(char *p
, int max_len
, time_t t
)
358 set_time_in_string(p
, max_len
, "KOT", t
);
361 /*******************************************************************
362 sets password can change time
363 ********************************************************************/
364 void pwdb_set_can_change_time(char *p
, int max_len
, time_t t
)
366 set_time_in_string(p
, max_len
, "CCT", t
);
369 /*******************************************************************
370 sets password last set time
371 ********************************************************************/
372 void pwdb_set_must_change_time(char *p
, int max_len
, time_t t
)
374 set_time_in_string(p
, max_len
, "MCT", t
);
377 /*******************************************************************
378 sets password last set time
379 ********************************************************************/
380 void pwdb_set_last_set_time(char *p
, int max_len
, time_t t
)
382 set_time_in_string(p
, max_len
, "LCT", t
);
386 /*************************************************************
387 Routine to set 32 hex password characters from a 16 byte array.
388 **************************************************************/
389 void pwdb_sethexpwd(char *p
, const char *pwd
, uint16 acct_ctrl
)
394 for (i
= 0; i
< 16; i
++)
396 slprintf(&p
[i
*2], 33, "%02X", pwd
[i
]);
401 if (IS_BITS_SET_ALL(acct_ctrl
, ACB_PWNOTREQ
))
403 safe_strcpy(p
, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
407 safe_strcpy(p
, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
412 /*************************************************************
413 Routine to get the 32 hex characters and turn them
414 into a 16 byte array.
415 **************************************************************/
416 BOOL
pwdb_gethexpwd(const char *p
, char *pwd
)
418 return strhex_to_str(pwd
, 32, p
) == 16;
422 /*************************************************************
423 initialise password databases, domain names, domain sid.
424 **************************************************************/
425 BOOL
pwdb_initialise(BOOL is_server
)
427 get_sam_domain_name();
429 if (!init_myworkgroup())
434 generate_wellknown_sids();
438 if (!generate_sam_sid(global_sam_name
))
440 DEBUG(0,("ERROR: Samba cannot create a SAM SID for its domain (%s).\n",
447 if (!get_domain_sids(&global_member_sid
, &global_sam_sid
, global_myname
))
453 return initialise_password_db();