9936dd2293bcc2de54defb432644626e51e3d498
[samba.git] / source3 / passdb / passdb.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
29 /*
30  * NOTE. All these functions are abstracted into a structure
31  * that points to the correct function for the selected database. JRA.
32  *
33  * NOTE.  for the get/mod/add functions, there are two sets of functions.
34  * one supports struct sam_passwd, the other supports struct smb_passwd.
35  * for speed optimisation it is best to support both these sets.
36  * 
37  * it is, however, optional to support one set but not the other: there
38  * is conversion-capability built in to passdb.c, and run-time error
39  * detection for when neither are supported.
40  * 
41  * password database writers are recommended to implement the sam_passwd
42  * functions in a first pass, as struct sam_passwd contains more
43  * information, needed by the NT Domain support.
44  * 
45  * an API writer is expected to create either one set (struct smb_passwd) or
46  * the other (struct sam_passwd) OR both, and optionally also to write display
47  * info routines * (struct sam_disp_info).  functions which the API writer
48  * chooses NOT to write must be wrapped in conversion functions (pwdb_x_to_y)
49  * such that API users can call any function and still get valid results.
50  *
51  * the password API does NOT fill in the gaps if you set an API function
52  * to NULL: it will deliberately attempt to call the NULL function.
53  *
54  */
55
56 static struct smb_passdb_ops *pwdb_ops;
57
58 /***************************************************************
59  Initialise the password db operations.
60 ***************************************************************/
61
62 BOOL initialise_password_db(void)
63 {
64   if (pwdb_ops)
65   {
66     return True;
67   }
68
69 #ifdef WITH_NISPLUS
70   pwdb_ops =  nisplus_initialise_password_db();
71 #elif defined(WITH_LDAP)
72   pwdb_ops = ldap_initialise_password_db();
73 #elif defined(WITH_MYSQL) || defined(WITH_MYSQLSAM)
74   pwdb_ops = mysql_initialise_password_db();
75 #elif defined(USE_SMBPASS_DB)
76   pwdb_ops = file_initialise_password_db();
77 #endif 
78
79   return (pwdb_ops != NULL);
80 }
81
82 /*
83  * Functions that return/manipulate a struct smb_passwd.
84  */
85
86 /************************************************************************
87  Utility function to search smb passwd by uid.  use this if your database
88  does not have search facilities.
89 *************************************************************************/
90
91 struct smb_passwd *iterate_getsmbpwuid(uid_t unix_uid)
92 {
93         struct smb_passwd *pwd = NULL;
94         void *fp = NULL;
95
96         DEBUG(10, ("search by unix_uid: %x\n", (int)unix_uid));
97
98         /* Open the smb password database - not for update. */
99         fp = startsmbpwent(False);
100
101         if (fp == NULL)
102         {
103                 DEBUG(0, ("unable to open smb password database.\n"));
104                 return NULL;
105         }
106
107         while ((pwd = getsmbpwent(fp)) != NULL && pwd->unix_uid != unix_uid)
108         {
109         }
110
111         if (pwd != NULL)
112         {
113                 DEBUG(10, ("found by unix_uid: %x\n", (int)unix_uid));
114         }
115
116         endsmbpwent(fp);
117         return pwd;
118 }
119
120 /************************************************************************
121  Utility function to search smb passwd by name.  use this if your database
122  does not have search facilities.
123 *************************************************************************/
124
125 struct smb_passwd *iterate_getsmbpwnam(const char *name)
126 {
127         struct smb_passwd *pwd = NULL;
128         void *fp = NULL;
129
130         DEBUG(10, ("search by name: %s\n", name));
131
132         /* Open the sam password file - not for update. */
133         fp = startsmbpwent(False);
134
135         if (fp == NULL)
136         {
137                 DEBUG(0, ("unable to open smb password database.\n"));
138                 return NULL;
139         }
140
141         while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->unix_name, name))
142         {
143                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->unix_name, pwd->unix_uid));
144         }
145
146         if (pwd != NULL)
147         {
148                 DEBUG(10, ("found by name: %s\n", name));
149         }
150
151         endsmbpwent(fp);
152         return pwd;
153 }
154
155 /***************************************************************
156  Start to enumerate the smb or sam passwd list. Returns a void pointer
157  to ensure no modification outside this module.
158
159  Note that currently it is being assumed that a pointer returned
160  from this function may be used to enumerate struct sam_passwd
161  entries as well as struct smb_passwd entries. This may need
162  to change. JRA.
163
164 ****************************************************************/
165
166 void *startsmbpwent(BOOL update)
167 {
168   return pwdb_ops->startsmbpwent(update);
169 }
170
171 /***************************************************************
172  End enumeration of the smb or sam passwd list.
173
174  Note that currently it is being assumed that a pointer returned
175  from this function may be used to enumerate struct sam_passwd
176  entries as well as struct smb_passwd entries. This may need
177  to change. JRA.
178
179 ****************************************************************/
180
181 void endsmbpwent(void *vp)
182 {
183   pwdb_ops->endsmbpwent(vp);
184 }
185
186 SMB_BIG_UINT getsmbpwpos(void *vp)
187 {
188   return pwdb_ops->getsmbpwpos(vp);
189 }
190
191 BOOL setsmbpwpos(void *vp, SMB_BIG_UINT tok)
192 {
193   return pwdb_ops->setsmbpwpos(vp, tok);
194 }
195
196 /*************************************************************************
197  Routine to return the next entry in the smb passwd list.
198  *************************************************************************/
199
200 struct smb_passwd *getsmbpwent(void *vp)
201 {
202         return pwdb_smb_map_names(pwdb_ops->getsmbpwent(vp));
203 }
204
205 /************************************************************************
206  Routine to add an entry to the smb passwd file.
207 *************************************************************************/
208
209 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
210 {
211         return pwdb_ops->add_smbpwd_entry(pwdb_smb_map_names(newpwd));
212 }
213
214 /************************************************************************
215  Routine to search the smb passwd file for an entry matching the username.
216  and then modify its password entry. We can't use the startsampwent()/
217  getsampwent()/endsampwent() interfaces here as we depend on looking
218  in the actual file to decide how much room we have to write data.
219  override = False, normal
220  override = True, override XXXXXXXX'd out password or NO PASS
221 ************************************************************************/
222
223 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
224 {
225         return pwdb_ops->mod_smbpwd_entry(pwdb_smb_map_names(pwd), override);
226 }
227
228 /************************************************************************
229  Routine to search smb passwd by name.
230 *************************************************************************/
231
232 struct smb_passwd *getsmbpwnam(const char *name)
233 {
234         return pwdb_smb_map_names(pwdb_ops->getsmbpwnam(name));
235 }
236
237 /************************************************************************
238  Routine to search smb passwd by uid.
239 *************************************************************************/
240
241 struct smb_passwd *getsmbpwuid(uid_t unix_uid)
242 {
243         return pwdb_smb_map_names(pwdb_ops->getsmbpwuid(unix_uid));
244 }
245
246 /*************************************************************
247  initialises a struct smb_passwd.
248  **************************************************************/
249 void pwdb_init_smb(struct smb_passwd *user)
250 {
251         if (user == NULL) return;
252         bzero(user, sizeof(*user));
253         user->pass_last_set_time    = (time_t)-1;
254         user->unix_uid = (uid_t)-1;
255         user->user_rid = 0xffffffff;
256 }
257
258 /*************************************************************
259  fills in missing details.  one set of details _must_ exist.
260  **************************************************************/
261 struct smb_passwd *pwdb_smb_map_names(struct smb_passwd *smb)
262 {
263         DOM_NAME_MAP gmep;
264         BOOL found = False;
265         DOM_SID sid;
266         static fstring unix_name;
267         static fstring nt_name;
268
269         DEBUG(10,("pwdb_smb_map_names\n"));
270
271         if (smb == NULL)
272         {
273                 return NULL;
274         }
275
276         if (smb->unix_name == NULL && smb->nt_name == NULL &&
277             smb->unix_uid == (uid_t)-1 && smb->user_rid == 0xffffffff)
278         {
279                 return NULL;
280         }
281
282         if (!found && smb->unix_name != NULL)
283         {
284                 found = lookupsmbpwnam(smb->unix_name, &gmep);
285         }
286         if (!found && smb->unix_uid  != (uid_t)-1)
287         {
288                 found = lookupsmbpwuid(smb->unix_uid , &gmep);
289         }
290
291         if (!found)
292         {
293                 sid_copy(&sid, &global_sam_sid);
294                 sid_append_rid(&sid, smb->user_rid);
295         }
296
297         if (!found && smb->user_rid != 0xffffffff)
298         {
299                 found = lookupsmbpwsid  (&sid        , &gmep);
300         }
301         if (!found && smb->nt_name  != NULL)
302         {
303                 found = lookupsmbpwntnam(smb->nt_name, &gmep);
304         }
305
306         if (!found)
307         {
308                 return NULL;
309         }
310
311         if (!sid_front_equal(&global_sam_sid, &gmep.sid))
312         {
313                 fstring sid_str;
314                 sid_to_string(sid_str, &gmep.sid);
315                 DEBUG(0,("UNIX User %s Primary Group is in the wrong domain! %s\n",
316                           smb->unix_name, sid_str));
317                 return NULL;
318         }
319
320         fstrcpy(unix_name, gmep.unix_name);
321         fstrcpy(nt_name  , gmep.nt_name  );
322         if (smb->unix_name == NULL      ) smb->unix_name = unix_name;
323         if (smb->nt_name   == NULL      ) smb->nt_name   = nt_name  ;
324         if (smb->unix_uid  == (uid_t)-1 ) smb->unix_uid  = (uid_t)gmep.unix_id;
325         if (smb->user_rid  == 0xffffffff) sid_split_rid(&gmep.sid, &smb->user_rid);
326
327         return smb;
328 }