ldap back-end database development
[kai/samba.git] / source3 / passdb / passdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Andrew Tridgell 1992-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
28 /**********************************************************
29  **********************************************************
30
31  low-level redirection routines:
32
33         startsampwent()
34         endsampwent()
35         getsampwent()
36         getsam21pwent()
37         getsampwpos()
38         setsampwpos()
39
40         add_sampwd_entry()
41         mod_sampwd_entry()
42         add_sam21pwd_entry()
43         mod_sam21pwd_entry()
44
45  **********************************************************
46  **********************************************************/
47
48 /***************************************************************
49  Start to enumerate the sam passwd list. Returns a void pointer
50  to ensure no modification outside this module.
51 ****************************************************************/
52 void *startsampwent(BOOL update)
53 {
54 #ifdef USE_LDAP
55   return startldappwent(update);
56 #else
57   return startsmbpwent(update);
58 #endif /* USE_LDAP */
59 }
60
61 /***************************************************************
62  End enumeration of the sam passwd list.
63 ****************************************************************/
64 void endsampwent(void *vp)
65 {
66 #ifdef USE_LDAP
67   endldappwent(vp);
68 #else
69   endsmbpwent(vp);
70 #endif /* USE_LDAP */
71 }
72
73 /*************************************************************************
74  Routine to return the next entry in the sam passwd list.
75  *************************************************************************/
76 struct smb_passwd *getsampwent(void *vp)
77 {
78 #ifdef USE_LDAP
79   return getldappwent(vp);
80 #else
81   return getsmbpwent(vp);
82 #endif /* USE_LDAP */
83 }
84
85 /*************************************************************************
86  Routine to return the next entry in the sam passwd list.
87  *************************************************************************/
88 struct sam_passwd *getsam21pwent(void *vp)
89 {
90 #if 0
91 #ifdef USE_LDAP
92   return getldap21pwent(vp);
93 #else
94   return getsmb21pwent(vp);
95 #endif /* USE_LDAP */
96 #else
97         DEBUG(0,("getsam21pwent: under development\n"));
98         return NULL;
99 #endif
100 }
101
102 /*************************************************************************
103  Return the current position in the sam passwd list as an unsigned long.
104  This must be treated as an opaque token.
105  *************************************************************************/
106 unsigned long getsampwpos(void *vp)
107 {
108 #ifdef USE_LDAP
109   return getldappwpos(vp);
110 #else
111   return getsmbpwpos(vp);
112 #endif /* USE_LDAP */
113 }
114
115 /*************************************************************************
116  Set the current position in the sam passwd list from unsigned long.
117  This must be treated as an opaque token.
118  *************************************************************************/
119 BOOL setsampwpos(void *vp, unsigned long tok)
120 {
121 #ifdef USE_LDAP
122   return setldappwpos(vp, tok);
123 #else
124   return setsmbpwpos(vp, tok);
125 #endif /* USE_LDAP */
126 }
127
128 /************************************************************************
129  Routine to add an entry to the sam passwd file.
130 *************************************************************************/
131 BOOL add_sampwd_entry(struct smb_passwd *newpwd)
132 {
133 #ifdef USE_LDAP
134   return add_ldappwd_entry(newpwd);
135 #else
136   return add_smbpwd_entry(newpwd);
137 #endif /* USE_LDAP */
138 }
139
140 /************************************************************************
141  Routine to add an entry to the sam passwd file.
142 *************************************************************************/
143 BOOL add_sam21pwd_entry(struct sam_passwd *newpwd)
144 {
145 #if 0
146 #ifdef USE_LDAP
147   return add_ldappwd_entry(newpwd);
148 #else
149   return add_smbpwd_entry(newpwd);
150 #endif /* USE_LDAP */
151 #else
152         DEBUG(0,("add_sam21pwd_entry() - under development\n"));
153         return False;
154 #endif
155 }
156
157 /************************************************************************
158  Routine to search the sam passwd file for an entry matching the username.
159  and then modify its password entry. We can't use the startsampwent()/
160  getsampwent()/endsampwent() interfaces here as we depend on looking
161  in the actual file to decide how much room we have to write data.
162  override = False, normal
163  override = True, override XXXXXXXX'd out password or NO PASS
164 ************************************************************************/
165 BOOL mod_sampwd_entry(struct smb_passwd* pwd, BOOL override)
166 {
167 #ifdef USE_LDAP
168   return mod_ldappwd_entry(pwd, override);
169 #else
170   return mod_smbpwd_entry(pwd, override);
171 #endif /* USE_LDAP */
172 }
173
174 /************************************************************************
175  Routine to search the sam passwd file for an entry matching the username.
176  and then modify its password entry. We can't use the startsampwent()/
177  getsampwent()/endsampwent() interfaces here as we depend on looking
178  in the actual file to decide how much room we have to write data.
179  override = False, normal
180  override = True, override XXXXXXXX'd out password or NO PASS
181 ************************************************************************/
182 BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override)
183 {
184 #if 0
185 #ifdef USE_LDAP
186   return mod_ldappwd_entry(pwd, override);
187 #else
188   return mod_smbpwd_entry(pwd, override);
189 #endif /* USE_LDAP */
190 #else
191         DEBUG(0,("mod_sam21pwd_entry() - under development\n"));
192         return False;
193 #endif
194 }
195
196 /**********************************************************
197  **********************************************************
198
199  high-level database routines:
200         getsampwnam()
201         getsampwuid()
202         getsam21pwnam()
203         getsam21pwuid()
204
205  **********************************************************
206  **********************************************************/
207
208 /************************************************************************
209  Routine to search sam passwd by name.
210 *************************************************************************/
211 struct smb_passwd *getsampwnam(char *name)
212 {
213         struct smb_passwd *pwd = NULL;
214         void *fp = NULL;
215
216         DEBUG(10, ("getsampwnam: search by name: %s\n", name));
217
218         /* Open the sam password file - not for update. */
219         fp = startsampwent(False);
220
221         if (fp == NULL)
222         {
223                 DEBUG(0, ("getsampwnam: unable to open sam password database.\n"));
224                 return NULL;
225         }
226
227         while ((pwd = getsampwent(fp)) != NULL && !strequal(pwd->smb_name, name));
228
229         if (pwd != NULL)
230         {
231                 DEBUG(10, ("getsampwnam: found by name: %s\n", name));
232         }
233
234         endsampwent(fp);
235         return pwd;
236 }
237
238 /************************************************************************
239  Routine to search sam passwd by name.
240 *************************************************************************/
241 struct sam_passwd *getsam21pwnam(char *name)
242 {
243         struct sam_passwd *pwd = NULL;
244         void *fp = NULL;
245
246         DEBUG(10, ("getsam21pwnam: search by name: %s\n", name));
247
248         /* Open the sam password file - not for update. */
249         fp = startsampwent(False);
250
251         if (fp == NULL)
252         {
253                 DEBUG(0, ("getsam21pwnam: unable to open sam password database.\n"));
254                 return NULL;
255         }
256
257         while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name));
258
259         if (pwd != NULL)
260         {
261                 DEBUG(10, ("getsam21pwnam: found by name: %s\n", name));
262         }
263
264         endsampwent(fp);
265         return pwd;
266 }
267
268 /************************************************************************
269  Routine to search sam passwd by uid.
270 *************************************************************************/
271 struct smb_passwd *getsampwuid(uid_t smb_userid)
272 {
273         struct smb_passwd *pwd = NULL;
274         void *fp = NULL;
275
276         DEBUG(10, ("getsampwuid: search by smb_userid: %x\n", smb_userid));
277
278         /* Open the sam password file - not for update. */
279         fp = startsampwent(False);
280
281         if (fp == NULL)
282         {
283                 DEBUG(0, ("getsampwuid: unable to open sam password database.\n"));
284                 return NULL;
285         }
286
287         while ((pwd = getsampwent(fp)) != NULL && pwd->smb_userid != smb_userid);
288
289         if (pwd != NULL)
290         {
291                 DEBUG(10, ("getsampwuid: found by smb_userid: %x\n", smb_userid));
292         }
293
294         endsmbpwent(fp);
295         return pwd;
296 }
297
298 /************************************************************************
299  Routine to search sam passwd by rid.
300 *************************************************************************/
301 struct sam_passwd *getsam21pwrid(uint32 rid)
302 {
303         struct sam_passwd *pwd = NULL;
304         void *fp = NULL;
305
306         DEBUG(10, ("getsam21pwrid: search by rid: %x\n", rid));
307
308         /* Open the sam password file - not for update. */
309         fp = startsampwent(False);
310
311         if (fp == NULL)
312         {
313                 DEBUG(0, ("getsam21pwrid: unable to open sam password database.\n"));
314                 return NULL;
315         }
316
317         while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid);
318
319         if (pwd != NULL)
320         {
321                 DEBUG(10, ("getsam21pwrid: found by smb_userid: %x\n", rid));
322         }
323
324         endsmbpwent(fp);
325         return pwd;
326 }
327
328
329 /**********************************************************
330  **********************************************************
331
332  utility routines which are likely to be useful to all password
333  databases
334
335  **********************************************************
336  **********************************************************/
337
338 /**********************************************************
339  Encode the account control bits into a string.
340  **********************************************************/
341 char *encode_acct_ctrl(uint16 acct_ctrl)
342 {
343   static fstring acct_str;
344   char *p = acct_str;
345  
346   *p++ = '[';
347
348   if (acct_ctrl & ACB_HOMDIRREQ) *p++ = 'H';
349   if (acct_ctrl & ACB_TEMPDUP  ) *p++ = 'T'; 
350   if (acct_ctrl & ACB_NORMAL   ) *p++ = 'U';
351   if (acct_ctrl & ACB_MNS      ) *p++ = 'M';
352   if (acct_ctrl & ACB_WSTRUST  ) *p++ = 'W';
353   if (acct_ctrl & ACB_SVRTRUST ) *p++ = 'S';
354   if (acct_ctrl & ACB_AUTOLOCK ) *p++ = 'L';
355   if (acct_ctrl & ACB_PWNOEXP  ) *p++ = 'X';
356   if (acct_ctrl & ACB_DOMTRUST ) *p++ = 'I';
357       
358   *p++ = ']';
359   *p = '\0';
360   return acct_str;
361 }     
362
363 /**********************************************************
364  Decode the account control bits from a string.
365
366  this function breaks coding standards minimum line width of 80 chars.
367  reason: vertical line-up code clarity - all case statements fit into
368  15 lines, which is more important.
369  **********************************************************/
370 uint16 decode_acct_ctrl(char *p)
371 {
372         uint16 acct_ctrl = 0;
373         BOOL finished = False;
374
375         /*
376          * Check if the account type bits have been encoded after the
377          * NT password (in the form [NDHTUWSLXI]).
378          */
379
380         if (*p != '[') return 0;
381
382         for (p++; *p && !finished; p++)
383         {
384                 switch (*p)
385                 {
386 #if 0
387                         /*
388                          * Hmmm. Don't allow these to be set/read independently
389                          * of the actual password fields. We don't want a mismatch.
390                          * JRA.
391                          */
392                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
393                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
394 #endif 
395                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
396                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
397                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
398                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
399                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
400                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
401                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
402                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
403                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
404
405                         case ':':
406                         case '\n':
407                         case '\0': 
408                         case ']':
409                         default:  { finished = True; }
410                 }
411         }
412
413         return acct_ctrl;
414 }
415
416 /*************************************************************
417  Routine to get the next 32 hex characters and turn them
418  into a 16 byte array.
419 **************************************************************/
420 int gethexpwd(char *p, char *pwd)
421 {
422   int i;
423   unsigned char   lonybble, hinybble;
424   char           *hexchars = "0123456789ABCDEF";
425   char           *p1, *p2;
426
427   for (i = 0; i < 32; i += 2) {
428     hinybble = toupper(p[i]);
429     lonybble = toupper(p[i + 1]);
430  
431     p1 = strchr(hexchars, hinybble);
432     p2 = strchr(hexchars, lonybble);
433     if (!p1 || !p2)
434       return (False);
435     hinybble = PTR_DIFF(p1, hexchars);
436     lonybble = PTR_DIFF(p2, hexchars);
437  
438     pwd[i / 2] = (hinybble << 4) | lonybble;
439   }
440   return (True);
441 }
442
443 /*******************************************************************
444  Group and User RID username mapping function
445  ********************************************************************/
446 BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
447 {
448     struct passwd *pw = Get_Pwnam(user_name, False);
449
450         if (u_rid == NULL || g_rid == NULL || user_name == NULL)
451         {
452                 return False;
453         }
454
455     if (!pw)
456         {
457       DEBUG(1,("Username %s is invalid on this system\n", user_name));
458       return False;
459     }
460
461         if (user_in_list(user_name, lp_domain_guest_users()))
462         {
463                 *u_rid = DOMAIN_USER_RID_GUEST;
464         }
465         else if (user_in_list(user_name, lp_domain_admin_users()))
466         {
467                 *u_rid = DOMAIN_USER_RID_ADMIN;
468         }
469         else
470         {
471                 /* turn the unix UID into a Domain RID.  this is what the posix
472                    sub-system does (adds 1000 to the uid) */
473                 *u_rid = uid_to_user_rid(pw->pw_uid);
474         }
475
476         /* absolutely no idea what to do about the unix GID to Domain RID mapping */
477         *g_rid = gid_to_group_rid(pw->pw_gid);
478
479         return True;
480 }
481
482 /*******************************************************************
483  XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
484  INSIDE smbpass.c
485
486  converts NT User RID to a UNIX uid.
487  ********************************************************************/
488 uid_t user_rid_to_uid(uint32 u_rid)
489 {
490         return (uid_t)(u_rid - 1000);
491 }
492
493 /*******************************************************************
494  XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
495  INSIDE smbpass.c
496
497  converts NT Group RID to a UNIX uid.
498  ********************************************************************/
499 uid_t group_rid_to_uid(uint32 u_gid)
500 {
501         return (uid_t)(u_gid - 1000);
502 }
503
504 /*******************************************************************
505  XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
506  INSIDE smbpass.c
507
508  converts UNIX uid to an NT User RID.
509  ********************************************************************/
510 uint32 uid_to_user_rid(uint32 uid)
511 {
512         return (uint32)(uid + 1000);
513 }
514
515 /*******************************************************************
516  XXXX THIS FUNCTION SHOULD NOT BE HERE: IT SHOULD BE A STATIC FUNCTION
517  INSIDE smbpass.c
518
519  converts NT Group RID to a UNIX uid.
520  ********************************************************************/
521 uint32 gid_to_group_rid(uint32 gid)
522 {
523         return (uint32)(gid + 1000);
524 }
525