"retired" two modules to preserve their cvs history.
[samba.git] / source / lib / util_pwdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Jeremy Allison 1996-1998
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
7       
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.
12    
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.
17    
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.
21 */
22
23 #include "includes.h"
24 #include "nterr.h"
25
26 extern int DEBUGLEVEL;
27 extern DOM_SID global_sam_sid;
28 extern fstring global_sam_name;
29 extern DOM_SID global_sid_S_1_5_20;
30 extern fstring global_myworkgroup;
31
32 /*
33  * A list of the rids of well known BUILTIN and Domain users
34  * and groups.
35  */
36
37 rid_name builtin_alias_rids[] =
38 {  
39     { BUILTIN_ALIAS_RID_ADMINS       , "Administrators" },
40     { BUILTIN_ALIAS_RID_USERS        , "Users" },
41     { BUILTIN_ALIAS_RID_GUESTS       , "Guests" },
42     { BUILTIN_ALIAS_RID_POWER_USERS  , "Power Users" },
43    
44     { BUILTIN_ALIAS_RID_ACCOUNT_OPS  , "Account Operators" },
45     { BUILTIN_ALIAS_RID_SYSTEM_OPS   , "System Operators" },
46     { BUILTIN_ALIAS_RID_PRINT_OPS    , "Print Operators" },
47     { BUILTIN_ALIAS_RID_BACKUP_OPS   , "Backup Operators" },
48     { BUILTIN_ALIAS_RID_REPLICATOR   , "Replicator" },
49     { 0                             , NULL }
50 };
51
52 /* array lookup of well-known Domain RID users. */
53 rid_name domain_user_rids[] =
54 {  
55     { DOMAIN_USER_RID_ADMIN         , "Administrator" },
56     { DOMAIN_USER_RID_GUEST         , "Guest" },
57     { 0                             , NULL }
58 };
59
60 /* array lookup of well-known Domain RID groups. */
61 rid_name domain_group_rids[] =
62 {  
63     { DOMAIN_GROUP_RID_ADMINS       , "Domain Admins" },
64     { DOMAIN_GROUP_RID_USERS        , "Domain Users" },
65     { DOMAIN_GROUP_RID_GUESTS       , "Domain Guests" },
66     { 0                             , NULL }
67 };
68
69
70 /*******************************************************************
71  lookup_wk_group_name
72  ********************************************************************/
73 uint32 lookup_wk_group_name(const char *group_name, const char *domain,
74                                 DOM_SID *sid, uint8 *type)
75 {
76         char *grp_name;
77         int i = -1; /* start do loop at -1 */
78         uint32 rid;
79         (*type) = SID_NAME_WKN_GRP;
80
81         if (strequal(domain, global_sam_name))
82         {
83                 sid_copy(sid, &global_sam_sid);
84         }
85         else if (strequal(domain, "BUILTIN"))
86         {
87                 sid_copy(sid, &global_sid_S_1_5_20);
88         }
89         else
90         {
91                 return 0xC0000000 | NT_STATUS_NONE_MAPPED;
92         }
93
94         do /* find, if it exists, a group rid for the group name */
95         {
96                 i++;
97                 rid      = domain_group_rids[i].rid;
98                 grp_name = domain_group_rids[i].name;
99
100                 if (strequal(grp_name, group_name))
101                 {
102                         sid_append_rid(sid, rid);
103
104                         return 0x0;
105                 }
106                         
107         } while (grp_name != NULL);
108
109         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
110 }
111
112 /*******************************************************************
113  lookup_wk_user_name
114  ********************************************************************/
115 uint32 lookup_wk_user_name(const char *user_name, const char *domain,
116                                 DOM_SID *sid, uint8 *type)
117 {
118         char *usr_name;
119         int i = -1; /* start do loop at -1 */
120         (*type) = SID_NAME_USER;
121
122         if (strequal(domain, global_sam_name))
123         {
124                 sid_copy(sid, &global_sam_sid);
125         }
126         else if (strequal(domain, "BUILTIN"))
127         {
128                 sid_copy(sid, &global_sid_S_1_5_20);
129         }
130         else
131         {
132                 return 0xC0000000 | NT_STATUS_NONE_MAPPED;
133         }
134
135         do /* find, if it exists, a alias rid for the alias name */
136         {
137                 i++;
138                 usr_name = domain_user_rids[i].name;
139
140         } while (usr_name != NULL && !strequal(usr_name, user_name));
141
142         if (usr_name != NULL)
143         {
144                 sid_copy(sid, &global_sid_S_1_5_20);
145                 sid_append_rid(sid, domain_user_rids[i].rid);
146                 return 0;
147         }
148
149         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
150 }
151
152 /*******************************************************************
153  lookup_builtin_alias_name
154  ********************************************************************/
155 uint32 lookup_builtin_alias_name(const char *alias_name, const char *domain,
156                                 DOM_SID *sid, uint8 *type)
157 {
158         char *als_name;
159         int i = 0;
160         uint32 rid;
161
162         if (strequal(domain, "BUILTIN"))
163         {
164                 if (sid != NULL)
165                 {
166                         sid_copy(sid, &global_sid_S_1_5_20);
167                 }
168         }
169         else
170         {
171                 return 0xC0000000 | NT_STATUS_NONE_MAPPED;
172         }
173
174         do /* find, if it exists, a alias rid for the alias name*/
175         {
176                 rid      = builtin_alias_rids[i].rid;
177                 als_name = builtin_alias_rids[i].name;
178
179                 i++;
180
181                 if (strequal(als_name, alias_name))
182                 {
183                         if (sid != NULL)
184                         {
185                                 sid_append_rid(sid, rid);
186                         }
187
188                         if (type != NULL)
189                         {
190                                 (*type) = SID_NAME_ALIAS;
191                         }
192
193                         return 0x0;
194                 }
195                         
196         } while (als_name != NULL);
197
198         return 0xC0000000 | NT_STATUS_NONE_MAPPED;
199 }
200 /**********************************************************
201  Encode the account control bits into a string.
202  length = length of string to encode into (including terminating
203  null). length *MUST BE MORE THAN 2* !
204  **********************************************************/
205
206 char *pwdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
207 {
208         static fstring acct_str;
209         size_t i = 0;
210
211         acct_str[i++] = '[';
212
213         if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
214         if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
215         if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
216         if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
217         if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
218         if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
219         if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
220         if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
221         if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
222         if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
223         if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
224
225         for ( ; i < length - 2 ; i++ )
226         {
227                 acct_str[i] = ' ';
228         }
229
230         i = length - 2;
231         acct_str[i++] = ']';
232         acct_str[i++] = '\0';
233
234         return acct_str;
235 }     
236
237 /**********************************************************
238  Decode the account control bits from a string.
239
240  this function breaks coding standards minimum line width of 80 chars.
241  reason: vertical line-up code clarity - all case statements fit into
242  15 lines, which is more important.
243  **********************************************************/
244
245 uint16 pwdb_decode_acct_ctrl(const char *p)
246 {
247         uint16 acct_ctrl = 0;
248         BOOL finished = False;
249
250         /*
251          * Check if the account type bits have been encoded after the
252          * NT password (in the form [NDHTUWSLXI]).
253          */
254
255         if (*p != '[') return 0;
256
257         for (p++; *p && !finished; p++)
258         {
259                 switch (*p)
260                 {
261                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
262                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
263                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
264                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
265                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
266                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
267                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
268                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
269                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
270                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
271                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
272                         case ' ': { break; }
273                         case ':':
274                         case '\n':
275                         case '\0': 
276                         case ']':
277                         default:  { finished = True; }
278                 }
279         }
280
281         return acct_ctrl;
282 }
283
284 /*******************************************************************
285  gets password-database-format time from a string.
286  ********************************************************************/
287
288 static time_t get_time_from_string(const char *p)
289 {
290         int i;
291
292         for (i = 0; i < 8; i++)
293         {
294                 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
295                 {
296                         break;
297                 }
298         }
299         if (i == 8)
300         {
301                 /*
302                  * p points at 8 characters of hex digits - 
303                  * read into a time_t as the seconds since
304                  * 1970 that the password was last changed.
305                  */
306                 return (time_t)strtol(p, NULL, 16);
307         }
308         return (time_t)-1;
309 }
310
311 /*******************************************************************
312  gets password last set time
313  ********************************************************************/
314
315 time_t pwdb_get_last_set_time(const char *p)
316 {
317         if (*p && StrnCaseCmp(p, "LCT-", 4))
318         {
319                 return get_time_from_string(p + 4);
320         }
321         return (time_t)-1;
322 }
323
324
325 /*******************************************************************
326  sets password-database-format time in a string.
327  ********************************************************************/
328 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
329 {
330         slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
331 }
332
333 /*******************************************************************
334  sets logon time
335  ********************************************************************/
336 void pwdb_set_logon_time(char *p, int max_len, time_t t)
337 {
338         set_time_in_string(p, max_len, "LNT", t);
339 }
340
341 /*******************************************************************
342  sets logoff time
343  ********************************************************************/
344 void pwdb_set_logoff_time(char *p, int max_len, time_t t)
345 {
346         set_time_in_string(p, max_len, "LOT", t);
347 }
348
349 /*******************************************************************
350  sets kickoff time
351  ********************************************************************/
352 void pwdb_set_kickoff_time(char *p, int max_len, time_t t)
353 {
354         set_time_in_string(p, max_len, "KOT", t);
355 }
356
357 /*******************************************************************
358  sets password can change time
359  ********************************************************************/
360 void pwdb_set_can_change_time(char *p, int max_len, time_t t)
361 {
362         set_time_in_string(p, max_len, "CCT", t);
363 }
364
365 /*******************************************************************
366  sets password last set time
367  ********************************************************************/
368 void pwdb_set_must_change_time(char *p, int max_len, time_t t)
369 {
370         set_time_in_string(p, max_len, "MCT", t);
371 }
372
373 /*******************************************************************
374  sets password last set time
375  ********************************************************************/
376 void pwdb_set_last_set_time(char *p, int max_len, time_t t)
377 {
378         set_time_in_string(p, max_len, "LCT", t);
379 }
380
381
382 /*************************************************************
383  Routine to set 32 hex password characters from a 16 byte array.
384 **************************************************************/
385 void pwdb_sethexpwd(char *p, const char *pwd, uint16 acct_ctrl)
386 {
387         if (pwd != NULL)
388         {
389                 int i;
390                 for (i = 0; i < 16; i++)
391                 {
392                         slprintf(&p[i*2], 33, "%02X", pwd[i]);
393                 }
394         }
395         else
396         {
397                 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
398                 {
399                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
400                 }
401                 else
402                 {
403                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
404                 }
405         }
406 }
407
408 /*************************************************************
409  Routine to get the 32 hex characters and turn them
410  into a 16 byte array.
411 **************************************************************/
412 BOOL pwdb_gethexpwd(const char *p, char *pwd)
413 {
414         return strhex_to_str(pwd, 32, p) == 16;
415 }
416
417 /*************************************************************
418  initialise password databases, domain names, domain sid.
419 **************************************************************/
420 BOOL pwdb_initialise(void)
421 {
422         fstrcpy(global_myworkgroup, lp_workgroup());
423
424         if (strequal(global_myworkgroup,"*"))
425         {
426                 DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
427                 return False;
428         }
429
430         get_sam_domain_name();
431
432         generate_wellknown_sids();
433
434         if (!generate_sam_sid())
435         {
436                 DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n"));
437                 return False;
438         }
439
440         if(!initialise_password_db())
441                 return False;
442
443         return True;
444 }