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