2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
4 * Copyright (C) Benny Holmgren 1998 <bigfoot@astrakan.hgs.se>
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 675
19 * Mass Ave, Cambridge, MA 02139, USA.
25 #include <rpcsvc/nis.h>
27 extern int DEBUGLEVEL;
31 /***************************************************************
32 Signal function to tell us we timed out.
33 ****************************************************************/
35 static void gotalarm_sig(void)
40 /***************************************************************
41 Start to enumerate the nisplus passwd list. Returns a void pointer
42 to ensure no modification outside this module.
44 do not call this function directly. use passdb.c instead.
46 ****************************************************************/
47 void *startnisppwent(BOOL update)
52 /***************************************************************
53 End enumeration of the nisplus passwd list.
54 ****************************************************************/
55 void endnisppwent(void *vp)
59 /*************************************************************************
60 Routine to return the next entry in the nisplus passwd list.
61 this function is a nice, messy combination of reading:
62 - the nisplus passwd file
63 - the unix password database
64 - nisp.conf options (not done at present).
66 do not call this function directly. use passdb.c instead.
68 *************************************************************************/
69 struct sam_passwd *getnisp21pwent(void *vp)
74 /*************************************************************************
75 Routine to return the next entry in the nisplus passwd list.
77 do not call this function directly. use passdb.c instead.
79 *************************************************************************/
80 struct smb_passwd *getnisppwent(void *vp)
82 DEBUG(5,("getnisppwent: end of file reached.\n"));
86 /*************************************************************************
87 Return the current position in the nisplus passwd list as an unsigned long.
88 This must be treated as an opaque token.
90 do not call this function directly. use passdb.c instead.
92 *************************************************************************/
93 unsigned long getnisppwpos(void *vp)
98 /*************************************************************************
99 Set the current position in the nisplus passwd list from unsigned long.
100 This must be treated as an opaque token.
102 do not call this function directly. use passdb.c instead.
104 *************************************************************************/
105 BOOL setnisppwpos(void *vp, unsigned long tok)
110 /************************************************************************
111 Routine to add an entry to the nisplus passwd file.
113 do not call this function directly. use passdb.c instead.
115 *************************************************************************/
116 BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd)
120 /************************************************************************
121 Routine to add an entry to the nisplus passwd file.
123 do not call this function directly. use passdb.c instead.
125 *************************************************************************/
126 BOOL add_nisppwd_entry(struct smb_passwd *newpwd)
128 /* Static buffers we will return. */
129 static pstring user_name;
131 BOOL add_user = True;
134 nis_result *nis_user;
135 nis_result *result = NULL,
138 nis_object newobj, *obj, *user_obj;
139 char lmpwd[33], ntpwd[33];
141 pfile = lp_smb_passwd_file();
143 safe_strcpy(user_name, newpwd->smb_name, sizeof(user_name));
145 safe_strcpy(nisname, "[name=", sizeof(nisname));
146 safe_strcat(nisname, user_name, sizeof(nisname) - strlen(nisname) -1);
147 safe_strcat(nisname, "],passwd.org_dir", sizeof(nisname)-strlen(nisname)-1);
149 safe_strcpy(nisname, "[uid=", sizeof(nisname));
150 slprintf(nisname, sizeof(nisname), "%s%d", nisname, newpwd->smb_userid);
151 safe_strcat(nisname, "],passwd.org_dir", sizeof(nisname)-strlen(nisname)-1);
153 nis_user = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL);
155 if (nis_user->status != NIS_SUCCESS || NIS_RES_NUMOBJ(nis_user) <= 0)
157 DEBUG(3, ("add_nisppwd_entry: Unable to get NIS+ passwd entry for user: %s.\n",
158 nis_sperrno(nis_user->status)));
163 * Calculate the SMB (lanman) hash functions of both old and new passwords.
166 user_obj = NIS_RES_OBJECT(nis_user);
168 safe_strcpy(nisname, "[name=", sizeof(nisname));
169 safe_strcat(nisname, ENTRY_VAL(user_obj,0),sizeof(nisname)-strlen(nisname)-1);
170 safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
171 safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
173 result = nis_list(nisname, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP,NULL,NULL);
174 if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND)
176 DEBUG(3, ( "add_nisppwd_entry: nis_list failure: %s: %s\n",
177 nisname, nis_sperrno(result->status)));
178 nis_freeresult(nis_user);
179 nis_freeresult(result);
183 if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0)
185 DEBUG(3, ("add_nisppwd_entry: User already exists in NIS+ password db: %s\n",
187 nis_freeresult(result);
188 nis_freeresult(nis_user);
192 /* User not found. */
196 DEBUG(3, ("add_nisppwd_entry: User not found in NIS+ password db: %s\n",
198 nis_freeresult(result);
199 nis_freeresult(nis_user);
203 tblresult = nis_lookup(pfile, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP );
204 if (tblresult->status != NIS_SUCCESS)
206 nis_freeresult(result);
207 nis_freeresult(nis_user);
208 nis_freeresult(tblresult);
209 DEBUG(3, ( "add_nisppwd_entry: nis_lookup failure: %s\n",
210 nis_sperrno(tblresult->status)));
214 newobj.zo_name = NIS_RES_OBJECT(tblresult)->zo_name;
215 newobj.zo_domain = NIS_RES_OBJECT(tblresult)->zo_domain;
216 newobj.zo_owner = NIS_RES_OBJECT(nis_user)->zo_owner;
217 newobj.zo_group = NIS_RES_OBJECT(tblresult)->zo_group;
218 newobj.zo_access = NIS_RES_OBJECT(tblresult)->zo_access;
219 newobj.zo_ttl = NIS_RES_OBJECT(tblresult)->zo_ttl;
221 newobj.zo_data.zo_type = ENTRY_OBJ;
223 newobj.zo_data.objdata_u.en_data.en_type = NIS_RES_OBJECT(tblresult)->zo_data.objdata_u.ta_data.ta_type;
224 newobj.zo_data.objdata_u.en_data.en_cols.en_cols_len = NIS_RES_OBJECT(tblresult)->zo_data.objdata_u.ta_data.ta_maxcol;
225 newobj.zo_data.objdata_u.en_data.en_cols.en_cols_val = calloc(newobj.zo_data.objdata_u.en_data.en_cols.en_cols_len, sizeof(entry_col));
227 ENTRY_VAL(&newobj, 0) = ENTRY_VAL(user_obj, 0);
228 ENTRY_LEN(&newobj, 0) = ENTRY_LEN(user_obj, 0);
230 ENTRY_VAL(&newobj, 1) = ENTRY_VAL(user_obj, 2);
231 ENTRY_LEN(&newobj, 1) = ENTRY_LEN(user_obj, 2);
233 ENTRY_VAL(&newobj, 2) = lmpwd;
234 ENTRY_LEN(&newobj, 2) = strlen(lmpwd);
235 newobj.EN_data.en_cols.en_cols_val[2].ec_flags = EN_CRYPT;
237 ENTRY_VAL(&newobj, 3) = ntpwd;
238 ENTRY_LEN(&newobj, 3) = strlen(ntpwd);
239 newobj.EN_data.en_cols.en_cols_val[3].ec_flags = EN_CRYPT;
241 ENTRY_VAL(&newobj, 4) = ENTRY_VAL(user_obj, 4);
242 ENTRY_LEN(&newobj, 4) = ENTRY_LEN(user_obj, 4);
244 ENTRY_VAL(&newobj, 5) = ENTRY_VAL(user_obj, 5);
245 ENTRY_LEN(&newobj, 5) = ENTRY_LEN(user_obj, 5);
247 ENTRY_VAL(&newobj, 6) = ENTRY_VAL(user_obj, 6);
248 ENTRY_LEN(&newobj, 6) = ENTRY_LEN(user_obj, 6);
252 addresult = nis_add_entry(pfile, obj, ADD_OVERWRITE | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP);
254 nis_freeresult(nis_user);
257 nis_freeresult(tblresult);
260 if (addresult->status != NIS_SUCCESS)
262 DEBUG(3, ( "add_nisppwd_entry: NIS+ table update failed: %s\n",
263 nisname, nis_sperrno(addresult->status)));
264 nis_freeresult(addresult);
265 nis_freeresult(result);
269 nis_freeresult(addresult);
270 nis_freeresult(result);
275 /************************************************************************
276 Routine to search the nisplus passwd file for an entry matching the username.
277 and then modify its password entry. We can't use the startnisppwent()/
278 getnisppwent()/endnisppwent() interfaces here as we depend on looking
279 in the actual file to decide how much room we have to write data.
280 override = False, normal
281 override = True, override XXXXXXXX'd out password or NO PASS
283 do not call this function directly. use passdb.c instead.
285 ************************************************************************/
286 BOOL mod_nisp21pwd_entry(struct sam_passwd* pwd, BOOL override)
291 /************************************************************************
292 Routine to search the nisplus passwd file for an entry matching the username.
293 and then modify its password entry. We can't use the startnisppwent()/
294 getnisppwent()/endnisppwent() interfaces here as we depend on looking
295 in the actual file to decide how much room we have to write data.
296 override = False, normal
297 override = True, override XXXXXXXX'd out password or NO PASS
299 do not call this function directly. use passdb.c instead.
301 ************************************************************************/
302 BOOL mod_nisppwd_entry(struct smb_passwd* pwd, BOOL override)
307 /************************************************************************
308 makes a struct smb_passwd from a NIS+ result.
309 ************************************************************************/
310 static BOOL make_smb_from_nisp(struct smb_passwd *pw_buf, nis_result *result)
313 static pstring user_name;
314 static unsigned char smbpwd[16];
315 static unsigned char smbntpwd[16];
319 if (pw_buf == NULL || result == NULL) return False;
321 bzero(pw_buf, sizeof(*pw_buf));
323 if (result->status != NIS_SUCCESS)
325 DEBUG(0, ("make_smb_from_nisp: NIS+ lookup failure: %s\n",
326 nis_sperrno(result->status)));
330 /* User not found. */
331 if (NIS_RES_NUMOBJ(result) <= 0)
333 DEBUG(10, ("make_smb_from_nisp: user not found in NIS+\n"));
337 if (NIS_RES_NUMOBJ(result) > 1)
339 DEBUG(10, ("make_smb_from_nisp: WARNING: Multiple entries for user in NIS+ table!\n"));
342 /* Grab the first hit. */
343 obj = &NIS_RES_OBJECT(result)[0];
345 /* Check the lanman password column. */
346 p = (uchar *)ENTRY_VAL(obj, 2);
347 if (strlen((char *)p) != 32 || !pdb_gethexpwd((char *)p, (char *)smbpwd))
349 DEBUG(0, ("make_smb_from_nisp: malformed LM pwd entry.\n"));
353 /* Check the NT password column. */
354 p = (uchar *)ENTRY_VAL(obj, 3);
355 if (strlen((char *)p) != 32 || !pdb_gethexpwd((char *)p, (char *)smbntpwd))
357 DEBUG(0, ("make_smb_from_nisp: malformed NT pwd entry\n"));
361 strncpy(user_name, ENTRY_VAL(obj, 0), sizeof(user_name));
362 uidval = atoi(ENTRY_VAL(obj, 1));
364 pw_buf->smb_name = user_name;
365 pw_buf->smb_userid = uidval;
366 pw_buf->smb_passwd = smbpwd;
367 pw_buf->smb_nt_passwd = smbntpwd;
372 /*************************************************************************
373 Routine to search the nisplus passwd file for an entry matching the username
374 *************************************************************************/
375 struct smb_passwd *getnisppwnam(char *name)
377 /* Static buffers we will return. */
378 static struct smb_passwd pw_buf;
383 if (!*lp_smb_passwd_file())
385 DEBUG(0, ("No SMB password file set\n"));
389 DEBUG(10, ("getnisppwnam: search by name: %s\n", name));
390 DEBUG(10, ("getnisppwnam: using NIS+ table %s\n", lp_smb_passwd_file()));
392 slprintf(nisname, sizeof(nisname), "[name=%s],%s", name, lp_smb_passwd_file());
394 /* Search the table. */
396 signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
399 result = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL);
402 signal(SIGALRM, SIGNAL_CAST SIG_DFL);
406 DEBUG(0,("getnisppwnam: NIS+ lookup time out\n"));
407 nis_freeresult(result);
411 ret = make_smb_from_nisp(&pw_buf, result);
412 nis_freeresult(result);
414 return ret ? &pw_buf : NULL;
417 /*************************************************************************
418 Routine to search the nisplus passwd file for an entry matching the username
419 *************************************************************************/
420 struct smb_passwd *getnisppwuid(int smb_userid)
422 /* Static buffers we will return. */
423 static struct smb_passwd pw_buf;
428 if (!*lp_smb_passwd_file())
430 DEBUG(0, ("No SMB password file set\n"));
434 DEBUG(10, ("getnisppwuid: search by uid: %d\n", smb_userid));
435 DEBUG(10, ("getnisppwuid: using NIS+ table %s\n", lp_smb_passwd_file()));
437 slprintf(nisname, sizeof(nisname), "[uid=%d],%s", smb_userid, lp_smb_passwd_file());
439 /* Search the table. */
441 signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
444 result = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL);
447 signal(SIGALRM, SIGNAL_CAST SIG_DFL);
451 DEBUG(0,("getnisppwuid: NIS+ lookup time out\n"));
452 nis_freeresult(result);
456 ret = make_smb_from_nisp(&pw_buf, result);
457 nis_freeresult(result);
459 return ret ? &pw_buf : NULL;
463 static void dummy_function(void) { } /* stop some compilers complaining */
464 #endif /* USE_NISPLUS_DB */