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 /***************************************************************
33 the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are:
62 ****************************************************************/
66 #define NPF_USER_RID 2
67 #define NPF_SMB_GRPID 3
68 #define NPF_GROUP_RID 4
73 #define NPF_LOGOFF_T 9
74 #define NPF_PWDLSET_T 10
75 #define NPF_PWDLCHG_T 11
76 #define NPF_PWDMCHG_T 12
77 #define NPF_FULL_NAME 13
78 #define NPF_HOME_DIR 14
79 #define NPF_DIR_DRIVE 15
80 #define NPF_LOGON_SCRIPT 16
81 #define NPF_PROFILE_PATH 17
82 #define NPF_ACCT_DESC 18
83 #define NPF_WORKSTATIONS 19
86 /***************************************************************
87 Signal function to tell us we timed out.
88 ****************************************************************/
89 static void gotalarm_sig(void)
94 /***************************************************************
95 make_nisname_from_user_rid
96 ****************************************************************/
97 static char *make_nisname_from_user_rid(uint32 rid)
99 static pstring nisname;
101 safe_strcpy(nisname, "[user_rid=", sizeof(nisname)-1);
102 slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, rid);
103 safe_strcat(nisname, "], passwd.org_dir", sizeof(nisname)-strlen(nisname)-1);
108 /***************************************************************
109 make_nisname_from_uid
110 ****************************************************************/
111 static char *make_nisname_from_uid(int uid)
113 static pstring nisname;
115 safe_strcpy(nisname, "[uid=", sizeof(nisname)-1);
116 slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, uid);
117 safe_strcat(nisname, "], passwd.org_dir", sizeof(nisname)-strlen(nisname)-1);
122 /***************************************************************
123 make_nisname_from_name
124 ****************************************************************/
125 static char *make_nisname_from_name(char *user_name)
127 static pstring nisname;
129 safe_strcpy(nisname, "[name=", sizeof(nisname)-1);
130 safe_strcat(nisname, user_name, sizeof(nisname) - strlen(nisname) - 1);
131 safe_strcat(nisname, "], passwd.org_dir", sizeof(nisname) - strlen(nisname) - 1);
136 /***************************************************************
137 Start to enumerate the nisplus passwd list. Returns a void pointer
138 to ensure no modification outside this module.
140 do not call this function directly. use passdb.c instead.
142 ****************************************************************/
143 void *startnisppwent(BOOL update)
148 /***************************************************************
149 End enumeration of the nisplus passwd list.
150 ****************************************************************/
151 void endnisppwent(void *vp)
155 /*************************************************************************
156 Routine to return the next entry in the nisplus passwd list.
157 this function is a nice, messy combination of reading:
158 - the nisplus passwd file
159 - the unix password database
160 - nisp.conf options (not done at present).
162 do not call this function directly. use passdb.c instead.
164 *************************************************************************/
165 struct sam_passwd *getnisp21pwent(void *vp)
170 /*************************************************************************
171 Return the current position in the nisplus passwd list as an unsigned long.
172 This must be treated as an opaque token.
174 do not call this function directly. use passdb.c instead.
176 *************************************************************************/
177 unsigned long getnisppwpos(void *vp)
182 /*************************************************************************
183 Set the current position in the nisplus passwd list from unsigned long.
184 This must be treated as an opaque token.
186 do not call this function directly. use passdb.c instead.
188 *************************************************************************/
189 BOOL setnisppwpos(void *vp, unsigned long tok)
194 /************************************************************************
195 Routine to add an entry to the nisplus passwd file.
197 do not call this function directly. use passdb.c instead.
199 *************************************************************************/
200 BOOL add_nisp21pwd_entry(struct sam_passwd *newpwd)
202 /* Static buffers we will return. */
203 static pstring user_name;
205 BOOL add_user = True;
208 nis_result *nis_user;
209 nis_result *result = NULL,
212 nis_object newobj, *obj, *user_obj;
213 char lmpwd[33], ntpwd[33];
215 pfile = lp_smb_passwd_file();
217 safe_strcpy(user_name, newpwd->smb_name, sizeof(user_name)-1);
219 nisname = make_nisname_from_name(user_name);
221 nis_user = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL);
223 if (nis_user->status != NIS_SUCCESS || NIS_RES_NUMOBJ(nis_user) <= 0)
225 DEBUG(3, ("add_nisppwd_entry: Unable to get NIS+ passwd entry for user: %s.\n",
226 nis_sperrno(nis_user->status)));
230 user_obj = NIS_RES_OBJECT(nis_user);
232 safe_strcpy(nisname, "[name=", sizeof(nisname)-1);
233 safe_strcat(nisname, ENTRY_VAL(user_obj,0),sizeof(nisname)-strlen(nisname)-1);
234 safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
235 safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
237 result = nis_list(nisname, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP,NULL,NULL);
238 if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND)
240 DEBUG(3, ( "add_nisppwd_entry: nis_list failure: %s: %s\n",
241 nisname, nis_sperrno(result->status)));
242 nis_freeresult(nis_user);
243 nis_freeresult(result);
247 if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0)
249 DEBUG(3, ("add_nisppwd_entry: User already exists in NIS+ password db: %s\n",
251 nis_freeresult(result);
252 nis_freeresult(nis_user);
256 /* User not found. */
260 DEBUG(3, ("add_nisppwd_entry: User not found in NIS+ password db: %s\n",
262 nis_freeresult(result);
263 nis_freeresult(nis_user);
267 tblresult = nis_lookup(pfile, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP );
268 if (tblresult->status != NIS_SUCCESS)
270 nis_freeresult(result);
271 nis_freeresult(nis_user);
272 nis_freeresult(tblresult);
273 DEBUG(3, ( "add_nisppwd_entry: nis_lookup failure: %s\n",
274 nis_sperrno(tblresult->status)));
278 newobj.zo_name = NIS_RES_OBJECT(tblresult)->zo_name;
279 newobj.zo_domain = NIS_RES_OBJECT(tblresult)->zo_domain;
280 newobj.zo_owner = NIS_RES_OBJECT(nis_user)->zo_owner;
281 newobj.zo_group = NIS_RES_OBJECT(tblresult)->zo_group;
282 newobj.zo_access = NIS_RES_OBJECT(tblresult)->zo_access;
283 newobj.zo_ttl = NIS_RES_OBJECT(tblresult)->zo_ttl;
285 newobj.zo_data.zo_type = ENTRY_OBJ;
287 newobj.zo_data.objdata_u.en_data.en_type = NIS_RES_OBJECT(tblresult)->zo_data.objdata_u.ta_data.ta_type;
288 newobj.zo_data.objdata_u.en_data.en_cols.en_cols_len = NIS_RES_OBJECT(tblresult)->zo_data.objdata_u.ta_data.ta_maxcol;
289 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));
291 ENTRY_VAL(&newobj, 0) = ENTRY_VAL(user_obj, 0);
292 ENTRY_LEN(&newobj, 0) = ENTRY_LEN(user_obj, 0);
294 ENTRY_VAL(&newobj, 1) = ENTRY_VAL(user_obj, 2);
295 ENTRY_LEN(&newobj, 1) = ENTRY_LEN(user_obj, 2);
297 ENTRY_VAL(&newobj, 2) = lmpwd;
298 ENTRY_LEN(&newobj, 2) = strlen(lmpwd);
299 newobj.EN_data.en_cols.en_cols_val[2].ec_flags = EN_CRYPT;
301 ENTRY_VAL(&newobj, 3) = ntpwd;
302 ENTRY_LEN(&newobj, 3) = strlen(ntpwd);
303 newobj.EN_data.en_cols.en_cols_val[3].ec_flags = EN_CRYPT;
305 ENTRY_VAL(&newobj, 4) = ENTRY_VAL(user_obj, 4);
306 ENTRY_LEN(&newobj, 4) = ENTRY_LEN(user_obj, 4);
308 ENTRY_VAL(&newobj, 5) = ENTRY_VAL(user_obj, 5);
309 ENTRY_LEN(&newobj, 5) = ENTRY_LEN(user_obj, 5);
311 ENTRY_VAL(&newobj, 6) = ENTRY_VAL(user_obj, 6);
312 ENTRY_LEN(&newobj, 6) = ENTRY_LEN(user_obj, 6);
316 addresult = nis_add_entry(pfile, obj, ADD_OVERWRITE | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP);
318 nis_freeresult(nis_user);
321 nis_freeresult(tblresult);
324 if (addresult->status != NIS_SUCCESS)
326 DEBUG(3, ( "add_nisppwd_entry: NIS+ table update failed: %s\n",
327 nisname, nis_sperrno(addresult->status)));
328 nis_freeresult(addresult);
329 nis_freeresult(result);
333 nis_freeresult(addresult);
334 nis_freeresult(result);
339 /************************************************************************
340 Routine to search the nisplus passwd file for an entry matching the username.
341 and then modify its password entry. We can't use the startnisppwent()/
342 getnisppwent()/endnisppwent() interfaces here as we depend on looking
343 in the actual file to decide how much room we have to write data.
344 override = False, normal
345 override = True, override XXXXXXXX'd out password or NO PASS
347 do not call this function directly. use passdb.c instead.
349 ************************************************************************/
350 BOOL mod_nisp21pwd_entry(struct sam_passwd* pwd, BOOL override)
355 /************************************************************************
356 makes a struct sam_passwd from a NIS+ result.
357 ************************************************************************/
358 static BOOL make_sam_from_nisp(struct sam_passwd *pw_buf, nis_result *result)
361 static pstring user_name;
362 static unsigned char smbpwd[16];
363 static unsigned char smbntpwd[16];
367 if (pw_buf == NULL || result == NULL) return False;
369 pdb_init_sam(pw_buf);
371 if (result->status != NIS_SUCCESS)
373 DEBUG(0, ("make_smb_from_nisp: NIS+ lookup failure: %s\n",
374 nis_sperrno(result->status)));
378 /* User not found. */
379 if (NIS_RES_NUMOBJ(result) <= 0)
381 DEBUG(10, ("make_smb_from_nisp: user not found in NIS+\n"));
385 if (NIS_RES_NUMOBJ(result) > 1)
387 DEBUG(10, ("make_smb_from_nisp: WARNING: Multiple entries for user in NIS+ table!\n"));
390 /* Grab the first hit. */
391 obj = &NIS_RES_OBJECT(result)[0];
393 /* Check the lanman password column. */
394 p = (uchar *)ENTRY_VAL(obj, NPF_LMPWD);
395 if (strlen((char *)p) != 32 || !pdb_gethexpwd((char *)p, (char *)smbpwd))
397 DEBUG(0, ("make_smb_from_nisp: malformed LM pwd entry.\n"));
401 /* Check the NT password column. */
402 p = (uchar *)ENTRY_VAL(obj, NPF_NTPWD);
403 if (strlen((char *)p) != 32 || !pdb_gethexpwd((char *)p, (char *)smbntpwd))
405 DEBUG(0, ("make_smb_from_nisp: malformed NT pwd entry\n"));
409 strncpy(user_name, ENTRY_VAL(obj, NPF_NAME), sizeof(user_name));
410 uidval = atoi(ENTRY_VAL(obj, NPF_UID));
412 pw_buf->smb_name = user_name;
413 pw_buf->smb_userid = uidval;
414 pw_buf->smb_passwd = smbpwd;
415 pw_buf->smb_nt_passwd = smbntpwd;
420 /*************************************************************************
421 Routine to search the nisplus passwd file for an entry matching the username
422 *************************************************************************/
423 struct sam_passwd *getnisp21pwnam(char *name)
425 /* Static buffers we will return. */
426 static struct sam_passwd pw_buf;
431 if (!*lp_smb_passwd_file())
433 DEBUG(0, ("No SMB password file set\n"));
437 DEBUG(10, ("getnisppwnam: search by name: %s\n", name));
438 DEBUG(10, ("getnisppwnam: using NIS+ table %s\n", lp_smb_passwd_file()));
440 slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s", name, lp_smb_passwd_file());
442 /* Search the table. */
444 signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
447 result = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL);
450 signal(SIGALRM, SIGNAL_CAST SIG_DFL);
454 DEBUG(0,("getnisppwnam: NIS+ lookup time out\n"));
455 nis_freeresult(result);
459 ret = make_sam_from_nisp(&pw_buf, result);
460 nis_freeresult(result);
462 return ret ? &pw_buf : NULL;
465 /*************************************************************************
466 Routine to search the nisplus passwd file for an entry matching the username
467 *************************************************************************/
468 struct sam_passwd *getnisp21pwuid(int smb_userid)
470 /* Static buffers we will return. */
471 static struct sam_passwd pw_buf;
476 if (!*lp_smb_passwd_file())
478 DEBUG(0, ("No SMB password file set\n"));
482 DEBUG(10, ("getnisppwuid: search by uid: %d\n", smb_userid));
483 DEBUG(10, ("getnisppwuid: using NIS+ table %s\n", lp_smb_passwd_file()));
485 slprintf(nisname, sizeof(nisname)-1, "[uid=%d],%s", smb_userid, lp_smb_passwd_file());
487 /* Search the table. */
489 signal(SIGALRM, SIGNAL_CAST gotalarm_sig);
492 result = nis_list(nisname, FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP, NULL, NULL);
495 signal(SIGALRM, SIGNAL_CAST SIG_DFL);
499 DEBUG(0,("getnisppwuid: NIS+ lookup time out\n"));
500 nis_freeresult(result);
504 ret = make_sam_from_nisp(&pw_buf, result);
505 nis_freeresult(result);
507 return ret ? &pw_buf : NULL;
511 void nisplus_dummy_function(void) { } /* stop some compilers complaining */
512 #endif /* USE_NISPLUS_DB */