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.
26 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
29 * The following lines are needed due to buggy include files
30 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
31 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
32 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
33 * an enum in /usr/include/rpcsvc/nis.h.
40 #if defined(GROUP_OBJ)
46 #include <rpcsvc/nis.h>
48 extern int DEBUGLEVEL
;
49 extern pstring samlogon_user
;
50 extern BOOL sam_logon_in_ssb
;
52 static VOLATILE SIG_ATOMIC_T gotalarm
;
54 /***************************************************************
56 the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are:
85 ****************************************************************/
89 #define NPF_USER_RID 2
90 #define NPF_SMB_GRPID 3
91 #define NPF_GROUP_RID 4
96 #define NPF_LOGOFF_T 9
98 #define NPF_PWDLSET_T 11
99 #define NPF_PWDLCHG_T 12
100 #define NPF_PWDMCHG_T 13
101 #define NPF_FULL_NAME 14
102 #define NPF_HOME_DIR 15
103 #define NPF_DIR_DRIVE 16
104 #define NPF_LOGON_SCRIPT 17
105 #define NPF_PROFILE_PATH 18
106 #define NPF_ACCT_DESC 19
107 #define NPF_WORKSTATIONS 20
110 /***************************************************************
111 Signal function to tell us we timed out.
112 ****************************************************************/
113 static void gotalarm_sig(void)
118 /***************************************************************
119 make_nisname_from_user_rid
120 ****************************************************************/
121 static char *make_nisname_from_user_rid(uint32 rid
, char *pfile
)
123 static pstring nisname
;
125 safe_strcpy(nisname
, "[user_rid=", sizeof(nisname
)-1);
126 slprintf(nisname
, sizeof(nisname
)-1, "%s%d", nisname
, rid
);
127 safe_strcat(nisname
, "],", sizeof(nisname
)-strlen(nisname
)-1);
128 safe_strcat(nisname
, pfile
, sizeof(nisname
)-strlen(nisname
)-1);
133 /***************************************************************
134 make_nisname_from_uid
135 ****************************************************************/
136 static char *make_nisname_from_uid(int uid
, char *pfile
)
138 static pstring nisname
;
140 safe_strcpy(nisname
, "[uid=", sizeof(nisname
)-1);
141 slprintf(nisname
, sizeof(nisname
)-1, "%s%d", nisname
, uid
);
142 safe_strcat(nisname
, "],", sizeof(nisname
)-strlen(nisname
)-1);
143 safe_strcat(nisname
, pfile
, sizeof(nisname
)-strlen(nisname
)-1);
148 /***************************************************************
149 make_nisname_from_name
150 ****************************************************************/
151 static char *make_nisname_from_name(char *user_name
, char *pfile
)
153 static pstring nisname
;
155 safe_strcpy(nisname
, "[name=", sizeof(nisname
)-1);
156 safe_strcat(nisname
, user_name
, sizeof(nisname
) - strlen(nisname
) - 1);
157 safe_strcat(nisname
, "],", sizeof(nisname
)-strlen(nisname
)-1);
158 safe_strcat(nisname
, pfile
, sizeof(nisname
)-strlen(nisname
)-1);
163 /*************************************************************************
164 gets a NIS+ attribute
165 *************************************************************************/
166 static void get_single_attribute(nis_object
*new_obj
, int col
,
171 if (new_obj
== NULL
|| val
== NULL
) return;
173 entry_len
= ENTRY_LEN(new_obj
, col
);
176 DEBUG(10,("get_single_attribute: entry length truncated\n"));
180 safe_strcpy(val
, ENTRY_VAL(new_obj
, col
), len
-1);
183 /************************************************************************
184 makes a struct sam_passwd from a NIS+ object.
185 ************************************************************************/
186 static BOOL
make_sam_from_nisp_object(struct sam_passwd
*pw_buf
, nis_object
*obj
)
189 static pstring user_name
;
190 static pstring full_name
;
191 static pstring home_dir
;
192 static pstring home_drive
;
193 static pstring logon_script
;
194 static pstring profile_path
;
195 static pstring acct_desc
;
196 static pstring workstations
;
198 static unsigned char smbpwd
[16];
199 static unsigned char smbntpwd
[16];
203 pdb_init_sam(pw_buf
);
204 pw_buf
->acct_ctrl
= ACB_NORMAL
;
206 pstrcpy(user_name
, ENTRY_VAL(obj
, NPF_NAME
));
207 pw_buf
->smb_name
= user_name
;
209 uidval
= atoi(ENTRY_VAL(obj
, NPF_UID
));
210 pw_buf
->smb_userid
= uidval
;
212 /* Check the lanman password column. */
213 p
= (char *)ENTRY_VAL(obj
, NPF_LMPWD
);
214 if (*p
== '*' || *p
== 'X') {
215 /* Password deliberately invalid - end here. */
216 DEBUG(10, ("make_sam_from_nisp_object: entry invalidated for user %s\n", user_name
));
217 pw_buf
->smb_nt_passwd
= NULL
;
218 pw_buf
->smb_passwd
= NULL
;
219 pw_buf
->acct_ctrl
|= ACB_DISABLED
;
222 if (!strncasecmp(p
, "NO PASSWORD", 11)) {
223 pw_buf
->smb_passwd
= NULL
;
224 pw_buf
->acct_ctrl
|= ACB_PWNOTREQ
;
226 if (strlen(p
) != 32 || !pdb_gethexpwd(p
, smbpwd
))
228 DEBUG(0, ("make_sam_from_nisp_object: malformed LM pwd entry.\n"));
233 pw_buf
->smb_passwd
= smbpwd
;
235 /* Check the NT password column. */
236 p
= ENTRY_VAL(obj
, NPF_NTPWD
);
237 if (*p
!= '*' && *p
!= 'X') {
238 if (strlen(p
) != 32 || !pdb_gethexpwd(p
, smbntpwd
))
240 DEBUG(0, ("make_smb_from_nisp_object: malformed NT pwd entry\n"));
243 pw_buf
->smb_nt_passwd
= smbntpwd
;
246 p
= (char *)ENTRY_VAL(obj
, NPF_ACB
);
249 pw_buf
->acct_ctrl
= pdb_decode_acct_ctrl(p
);
251 /* Must have some account type set. */
252 if(pw_buf
->acct_ctrl
== 0)
253 pw_buf
->acct_ctrl
= ACB_NORMAL
;
255 /* Now try and get the last change time. */
260 if(*p
&& (StrnCaseCmp(p
, "LCT-", 4)==0)) {
263 for(i
= 0; i
< 8; i
++) {
264 if(p
[i
] == '\0' || !isxdigit(p
[i
]))
269 * p points at 8 characters of hex digits -
270 * read into a time_t as the seconds since
271 * 1970 that the password was last changed.
273 pw_buf
->pass_last_set_time
= (time_t)strtol(p
, NULL
, 16);
278 /* 'Old' style file. Fake up based on user name. */
280 * Currently trust accounts are kept in the same
281 * password file as 'normal accounts'. If this changes
282 * we will have to fix this code. JRA.
284 if(pw_buf
->smb_name
[strlen(pw_buf
->smb_name
) - 1] == '$') {
285 pw_buf
->acct_ctrl
&= ~ACB_NORMAL
;
286 pw_buf
->acct_ctrl
|= ACB_WSTRUST
;
290 get_single_attribute(obj
, NPF_SMB_GRPID
, temp
, sizeof(pstring
));
291 pw_buf
->smb_grpid
= atoi(temp
);
293 get_single_attribute(obj
, NPF_USER_RID
, temp
, sizeof(pstring
));
294 pw_buf
->user_rid
= (strlen(temp
) > 0) ?
295 strtol(temp
, NULL
, 16) : pdb_uid_to_user_rid (pw_buf
->smb_userid
);
297 if (pw_buf
->smb_name
[strlen(pw_buf
->smb_name
)-1] != '$') {
299 /* XXXX hack to get standard_sub_basic() to use sam logon username */
300 /* possibly a better way would be to do a become_user() call */
301 pstrcpy(samlogon_user
, pw_buf
->smb_name
);
302 sam_logon_in_ssb
= True
;
304 get_single_attribute(obj
, NPF_GROUP_RID
, temp
, sizeof(pstring
));
305 pw_buf
->group_rid
= (strlen(temp
) > 0) ?
306 strtol(temp
, NULL
, 16) : pdb_gid_to_group_rid (pw_buf
->smb_grpid
);
308 get_single_attribute(obj
, NPF_FULL_NAME
, full_name
, sizeof(pstring
));
310 /* It seems correct to use the global values - but in that case why
311 * do we want these NIS+ entries anyway ??
313 pstrcpy(logon_script
, lp_logon_script ());
314 pstrcpy(profile_path
, lp_logon_path ());
315 pstrcpy(home_drive
, lp_logon_drive ());
316 pstrcpy(home_dir
, lp_logon_home ());
318 get_single_attribute(obj
, NPF_LOGON_SCRIPT
, logon_script
, sizeof(pstring
));
319 get_single_attribute(obj
, NPF_PROFILE_PATH
, profile_path
, sizeof(pstring
));
320 get_single_attribute(obj
, NPF_DIR_DRIVE
, home_drive
, sizeof(pstring
));
321 get_single_attribute(obj
, NPF_HOME_DIR
, home_dir
, sizeof(pstring
));
323 get_single_attribute(obj
, NPF_ACCT_DESC
, acct_desc
, sizeof(pstring
));
324 get_single_attribute(obj
, NPF_WORKSTATIONS
, workstations
, sizeof(pstring
));
326 sam_logon_in_ssb
= False
;
330 pw_buf
->group_rid
= DOMAIN_GROUP_RID_USERS
; /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
332 pstrcpy(full_name
, "");
333 pstrcpy(logon_script
, "");
334 pstrcpy(profile_path
, "");
335 pstrcpy(home_drive
, "");
336 pstrcpy(home_dir
, "");
337 pstrcpy(acct_desc
, "");
338 pstrcpy(workstations
, "");
341 pw_buf
->full_name
= full_name
;
342 pw_buf
->home_dir
= home_dir
;
343 pw_buf
->dir_drive
= home_drive
;
344 pw_buf
->logon_script
= logon_script
;
345 pw_buf
->profile_path
= profile_path
;
346 pw_buf
->acct_desc
= acct_desc
;
347 pw_buf
->workstations
= workstations
;
349 pw_buf
->unknown_str
= NULL
; /* don't know, yet! */
350 pw_buf
->munged_dial
= NULL
; /* "munged" dial-back telephone number */
352 pw_buf
->unknown_3
= 0xffffff; /* don't know */
353 pw_buf
->logon_divs
= 168; /* hours per week */
354 pw_buf
->hours_len
= 21; /* 21 times 8 bits = 168 */
355 memset(pw_buf
->hours
, 0xff, pw_buf
->hours_len
); /* available at all hours */
356 pw_buf
->unknown_5
= 0x00020000; /* don't know */
357 pw_buf
->unknown_6
= 0x000004ec; /* don't know */
362 /************************************************************************
363 makes a struct sam_passwd from a NIS+ result.
364 ************************************************************************/
365 static BOOL
make_sam_from_nisresult(struct sam_passwd
*pw_buf
, nis_result
*result
)
367 if (pw_buf
== NULL
|| result
== NULL
) return False
;
369 if (result
->status
!= NIS_SUCCESS
&& result
->status
!= NIS_NOTFOUND
)
371 DEBUG(0, ("make_sam_from_nisresult: NIS+ lookup failure: %s\n",
372 nis_sperrno(result
->status
)));
376 /* User not found. */
377 if (NIS_RES_NUMOBJ(result
) <= 0)
379 DEBUG(10, ("make_sam_from_nisresult: user not found in NIS+\n"));
383 if (NIS_RES_NUMOBJ(result
) > 1)
385 DEBUG(10, ("make_sam_from_nisresult: WARNING: Multiple entries for user in NIS+ table!\n"));
388 /* Grab the first hit. */
389 return make_sam_from_nisp_object(pw_buf
, &NIS_RES_OBJECT(result
)[0]);
392 /***************************************************************
393 calls nis_list, returns results.
394 ****************************************************************/
395 static nis_result
*nisp_get_nis_list(char *nis_name
)
398 result
= nis_list(nis_name
, FOLLOW_PATH
|EXPAND_NAME
|HARD_LOOKUP
,NULL
,NULL
);
401 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_DFL
);
405 DEBUG(0,("nisp_get_nis_list: NIS+ lookup time out\n"));
406 nis_freeresult(result
);
414 struct nisp_enum_info
420 /***************************************************************
421 Start to enumerate the nisplus passwd list. Returns a void pointer
422 to ensure no modification outside this module.
424 do not call this function directly. use passdb.c instead.
426 ****************************************************************/
427 static void *startnisppwent(BOOL update
)
429 static struct nisp_enum_info res
;
430 res
.result
= nisp_get_nis_list(lp_smb_passwd_file());
432 return res
.result
!= NULL
? &res
: NULL
;
435 /***************************************************************
436 End enumeration of the nisplus passwd list.
437 ****************************************************************/
438 static void endnisppwent(void *vp
)
440 struct nisp_enum_info
*res
= (struct nisp_enum_info
*)vp
;
441 nis_freeresult(res
->result
);
442 DEBUG(7,("endnisppwent: freed enumeration list\n"));
445 /*************************************************************************
446 Routine to return the next entry in the nisplus passwd list.
448 do not call this function directly. use passdb.c instead.
450 *************************************************************************/
451 static struct sam_passwd
*getnisp21pwent(void *vp
)
453 struct nisp_enum_info
*res
= (struct nisp_enum_info
*)vp
;
454 static struct sam_passwd pw_buf
;
458 if (res
== NULL
|| (int)(res
->enum_entry
) < 0 ||
459 (int)(res
->enum_entry
) > (NIS_RES_NUMOBJ(res
->result
) - 1)) {
462 which
= (int)(res
->enum_entry
);
463 ret
= make_sam_from_nisp_object(&pw_buf
,
464 &NIS_RES_OBJECT(res
->result
)[which
]);
465 if (ret
&& which
< (NIS_RES_NUMOBJ(res
->result
) - 1))
466 (int)(res
->enum_entry
)++;
469 return ret
? &pw_buf
: NULL
;
472 /*************************************************************************
473 Return the current position in the nisplus passwd list as an SMB_BIG_UINT.
474 This must be treated as an opaque token.
476 do not call this function directly. use passdb.c instead.
478 *************************************************************************/
479 static SMB_BIG_UINT
getnisppwpos(void *vp
)
481 struct nisp_enum_info
*res
= (struct nisp_enum_info
*)vp
;
482 return (SMB_BIG_UINT
)(res
->enum_entry
);
485 /*************************************************************************
486 Set the current position in the nisplus passwd list from SMB_BIG_UINT.
487 This must be treated as an opaque token.
489 do not call this function directly. use passdb.c instead.
491 *************************************************************************/
492 static BOOL
setnisppwpos(void *vp
, SMB_BIG_UINT tok
)
494 struct nisp_enum_info
*res
= (struct nisp_enum_info
*)vp
;
495 if (tok
< (NIS_RES_NUMOBJ(res
->result
) - 1)) {
496 res
->enum_entry
= tok
;
503 /*************************************************************************
504 sets a NIS+ attribute
505 *************************************************************************/
506 static void set_single_attribute(nis_object
*new_obj
, int col
,
507 char *val
, int len
, int flags
)
509 if (new_obj
== NULL
) return;
511 ENTRY_VAL(new_obj
, col
) = val
;
512 ENTRY_LEN(new_obj
, col
) = len
+1;
516 new_obj
->EN_data
.en_cols
.en_cols_val
[col
].ec_flags
= flags
;
520 /************************************************************************
521 Routine to add an entry to the nisplus passwd file.
523 do not call this function directly. use passdb.c instead.
525 *************************************************************************/
526 static BOOL
add_nisp21pwd_entry(struct sam_passwd
*newpwd
)
530 nis_result
*nis_user
;
531 nis_result
*result
= NULL
,
534 nis_object new_obj
, *obj
;
543 fstring smb_nt_passwd
;
552 memset((char *)logon_t
, '\0', sizeof(logon_t
));
553 memset((char *)logoff_t
, '\0', sizeof(logoff_t
));
554 memset((char *)kickoff_t
, '\0', sizeof(kickoff_t
));
555 memset((char *)pwdlset_t
, '\0', sizeof(pwdlset_t
));
556 memset((char *)pwdlchg_t
, '\0', sizeof(pwdlchg_t
));
557 memset((char *)pwdmchg_t
, '\0', sizeof(pwdmchg_t
));
559 pfile
= lp_smb_passwd_file();
561 nisname
= make_nisname_from_name(newpwd
->smb_name
, pfile
);
562 result
= nisp_get_nis_list(nisname
);
563 if (result
->status
!= NIS_SUCCESS
&& result
->status
!= NIS_NOTFOUND
)
565 DEBUG(3, ( "add_nis21ppwd_entry: nis_list failure: %s: %s\n",
566 nisname
, nis_sperrno(result
->status
)));
567 nis_freeresult(result
);
571 if (result
->status
== NIS_SUCCESS
&& NIS_RES_NUMOBJ(result
) > 0)
573 DEBUG(3, ("add_nisp21pwd_entry: User already exists in NIS+ password db: %s\n",
575 nis_freeresult(result
);
580 /* User not found. */
583 DEBUG(3, ("add_nisp21pwd_entry: User not found in NIS+ password db: %s\n",
585 nis_freeresult(result
);
591 tblresult
= nis_lookup(pfile
, FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
);
592 if (tblresult
->status
!= NIS_SUCCESS
)
594 nis_freeresult(result
);
595 nis_freeresult(tblresult
);
596 DEBUG(3, ( "add_nisp21pwd_entry: nis_lookup failure: %s\n",
597 nis_sperrno(tblresult
->status
)));
601 new_obj
.zo_name
= NIS_RES_OBJECT(tblresult
)->zo_name
;
602 new_obj
.zo_domain
= NIS_RES_OBJECT(tblresult
)->zo_domain
;
603 new_obj
.zo_owner
= NIS_RES_OBJECT(tblresult
)->zo_owner
;
604 new_obj
.zo_group
= NIS_RES_OBJECT(tblresult
)->zo_group
;
605 new_obj
.zo_access
= NIS_RES_OBJECT(tblresult
)->zo_access
;
606 new_obj
.zo_ttl
= NIS_RES_OBJECT(tblresult
)->zo_ttl
;
608 new_obj
.zo_data
.zo_type
= ENTRY_OBJ
;
610 new_obj
.zo_data
.objdata_u
.en_data
.en_type
= NIS_RES_OBJECT(tblresult
)->zo_data
.objdata_u
.ta_data
.ta_type
;
611 new_obj
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_len
= NIS_RES_OBJECT(tblresult
)->zo_data
.objdata_u
.ta_data
.ta_maxcol
;
612 new_obj
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_val
= calloc(new_obj
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_len
, sizeof(entry_col
));
614 if (new_obj
.zo_data
.objdata_u
.en_data
.en_cols
.en_cols_val
== NULL
)
616 DEBUG(0, ("add_nisp21pwd_entry: memory allocation failure\n"));
617 nis_freeresult(result
);
618 nis_freeresult(tblresult
);
622 pdb_sethexpwd(smb_passwd
, newpwd
->smb_passwd
, newpwd
->acct_ctrl
);
623 pdb_sethexpwd(smb_nt_passwd
, newpwd
->smb_nt_passwd
, newpwd
->acct_ctrl
);
625 newpwd
->pass_last_set_time
= (time_t)time(NULL
);
626 newpwd
->logon_time
= (time_t)-1;
627 newpwd
->logoff_time
= (time_t)-1;
628 newpwd
->kickoff_time
= (time_t)-1;
629 newpwd
->pass_can_change_time
= (time_t)-1;
630 newpwd
->pass_must_change_time
= (time_t)-1;
632 slprintf(logon_t
, 13, "LNT-%08X", (uint32
)newpwd
->logon_time
);
633 slprintf(logoff_t
, 13, "LOT-%08X", (uint32
)newpwd
->logoff_time
);
634 slprintf(kickoff_t
, 13, "KOT-%08X", (uint32
)newpwd
->kickoff_time
);
635 slprintf(pwdlset_t
, 13, "LCT-%08X", (uint32
)newpwd
->pass_last_set_time
);
636 slprintf(pwdlchg_t
, 13, "CCT-%08X", (uint32
)newpwd
->pass_can_change_time
);
637 slprintf(pwdmchg_t
, 13, "MCT-%08X", (uint32
)newpwd
->pass_must_change_time
);
639 slprintf(uid
, sizeof(uid
), "%u", newpwd
->smb_userid
);
640 slprintf(user_rid
, sizeof(user_rid
), "0x%x", newpwd
->user_rid
);
641 slprintf(smb_grpid
, sizeof(smb_grpid
), "%u", newpwd
->smb_grpid
);
642 slprintf(group_rid
, sizeof(group_rid
), "0x%x", newpwd
->group_rid
);
644 safe_strcpy(acb
, pdb_encode_acct_ctrl(newpwd
->acct_ctrl
, NEW_PW_FORMAT_SPACE_PADDED_LEN
), sizeof(acb
)-1);
646 set_single_attribute(&new_obj
, NPF_NAME
, newpwd
->smb_name
, strlen(newpwd
->smb_name
) , 0);
647 set_single_attribute(&new_obj
, NPF_UID
, uid
, strlen(uid
) , 0);
648 set_single_attribute(&new_obj
, NPF_USER_RID
, user_rid
, strlen(user_rid
) , 0);
649 set_single_attribute(&new_obj
, NPF_SMB_GRPID
, smb_grpid
, strlen(smb_grpid
) , 0);
650 set_single_attribute(&new_obj
, NPF_GROUP_RID
, group_rid
, strlen(group_rid
) , 0);
651 set_single_attribute(&new_obj
, NPF_ACB
, acb
, strlen(acb
) , 0);
652 set_single_attribute(&new_obj
, NPF_LMPWD
, smb_passwd
, strlen(smb_passwd
) , EN_CRYPT
);
653 set_single_attribute(&new_obj
, NPF_NTPWD
, smb_nt_passwd
, strlen(smb_nt_passwd
) , EN_CRYPT
);
654 set_single_attribute(&new_obj
, NPF_LOGON_T
, logon_t
, strlen(logon_t
) , 0);
655 set_single_attribute(&new_obj
, NPF_LOGOFF_T
, logoff_t
, strlen(logoff_t
) , 0);
656 set_single_attribute(&new_obj
, NPF_KICK_T
, kickoff_t
, strlen(kickoff_t
) , 0);
657 set_single_attribute(&new_obj
, NPF_PWDLSET_T
, pwdlset_t
, strlen(pwdlset_t
) , 0);
658 set_single_attribute(&new_obj
, NPF_PWDLCHG_T
, pwdlchg_t
, strlen(pwdlchg_t
) , 0);
659 set_single_attribute(&new_obj
, NPF_PWDMCHG_T
, pwdmchg_t
, strlen(pwdmchg_t
) , 0);
661 set_single_attribute(&new_obj
, NPF_FULL_NAME
, newpwd
->full_name
, strlen(newpwd
->full_name
) , 0);
662 set_single_attribute(&new_obj
, NPF_HOME_DIR
, newpwd
->home_dir
, strlen(newpwd
->home_dir
) , 0);
663 set_single_attribute(&new_obj
, NPF_DIR_DRIVE
, newpwd
->dir_drive
, strlen(newpwd
->dir_drive
) , 0);
664 set_single_attribute(&new_obj
, NPF_LOGON_SCRIPT
, newpwd
->logon_script
, strlen(newpwd
->logon_script
) , 0);
665 set_single_attribute(&new_obj
, NPF_PROFILE_PATH
, newpwd
->profile_path
, strlen(newpwd
->profile_path
) , 0);
666 set_single_attribute(&new_obj
, NPF_ACCT_DESC
, newpwd
->acct_desc
, strlen(newpwd
->acct_desc
) , 0);
667 set_single_attribute(&new_obj
, NPF_WORKSTATIONS
, newpwd
->workstations
, strlen(newpwd
->workstations
) , 0);
668 set_single_attribute(&new_obj
, NPF_HOURS
, newpwd
->hours
, newpwd
->hours_len
, 0);
673 addresult
= nis_add_entry(pfile
, obj
, ADD_OVERWRITE
| FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
);
676 if (addresult
->status
!= NIS_SUCCESS
)
678 DEBUG(3, ( "add_nisp21pwd_entry: NIS+ table update failed: %s\n",
679 nisname
, nis_sperrno(addresult
->status
)));
680 nis_freeresult(tblresult
);
681 nis_freeresult(addresult
);
682 nis_freeresult(result
);
686 nis_freeresult(tblresult
);
687 nis_freeresult(addresult
);
688 nis_freeresult(result
);
693 /************************************************************************
694 Routine to search the nisplus passwd file for an entry matching the username.
695 and then modify its password entry. We can't use the startnisppwent()/
696 getnisppwent()/endnisppwent() interfaces here as we depend on looking
697 in the actual file to decide how much room we have to write data.
698 override = False, normal
699 override = True, override XXXXXXXX'd out password or NO PASS
701 do not call this function directly. use passdb.c instead.
703 ************************************************************************/
704 static BOOL
mod_nisp21pwd_entry(struct sam_passwd
* pwd
, BOOL override
)
706 char *oldnislmpwd
, *oldnisntpwd
, *oldnisacb
, *oldnislct
, *user_name
;
707 char lmpwd
[33], ntpwd
[33], lct
[13];
708 nis_result
*result
, *addresult
;
712 BOOL got_pass_last_set_time
, ret
;
715 if (!*lp_smb_passwd_file())
717 DEBUG(0, ("mod_getnisp21pwd_entry: no SMB password file set\n"));
721 DEBUG(10, ("mod_getnisp21pwd_entry: search by name: %s\n", pwd
->smb_name
));
722 DEBUG(10, ("mod_getnisp21pwd_entry: using NIS+ table %s\n", lp_smb_passwd_file()));
724 slprintf(nisname
, sizeof(nisname
)-1, "[name=%s],%s", pwd
->smb_name
, lp_smb_passwd_file());
726 /* Search the table. */
728 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
731 result
= nis_list(nisname
, FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
, NULL
, NULL
);
734 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_DFL
);
738 DEBUG(0,("mod_getnisp21pwd_entry: NIS+ lookup time out\n"));
739 nis_freeresult(result
);
743 if(result
->status
!= NIS_SUCCESS
|| NIS_RES_NUMOBJ(result
) <= 0) {
744 /* User not found. */
745 DEBUG(0,("mod_getnisp21pwd_entry: user not found in NIS+\n"));
746 nis_freeresult(result
);
750 DEBUG(6,("mod_getnisp21pwd_entry: entry exists\n"));
752 obj
= NIS_RES_OBJECT(result
);
754 user_name
= ENTRY_VAL(obj
, NPF_NAME
);
755 oldnislmpwd
= ENTRY_VAL(obj
, NPF_LMPWD
);
756 oldnisntpwd
= ENTRY_VAL(obj
, NPF_NTPWD
);
757 oldnisacb
= ENTRY_VAL(obj
, NPF_ACB
);
758 oldnislct
= ENTRY_VAL(obj
, NPF_PWDLSET_T
);
761 if (!override
&& (*oldnislmpwd
== '*' || *oldnislmpwd
== 'X' ||
762 *oldnisntpwd
== '*' || *oldnisntpwd
== 'X')) {
763 /* Password deliberately invalid - end here. */
764 DEBUG(10, ("mod_nisp21pwd_entry: entry invalidated for user %s\n", user_name
));
765 nis_freeresult(result
);
769 if (strlen(oldnislmpwd
) != 32 || strlen(oldnisntpwd
) != 32) {
770 DEBUG(0, ("mod_nisp21pwd_entry: malformed password entry (incorrect length)\n"));
771 nis_freeresult(result
);
778 * Now check if the account info and the password last
779 * change time is available.
783 * If both NT and lanman passwords are provided - reset password
787 if(pwd
->smb_passwd
!= NULL
|| pwd
->smb_nt_passwd
!= NULL
) {
788 /* Require password in the future (should ACB_DISABLED also be reset?) */
789 pwd
->acct_ctrl
&= ~(ACB_PWNOTREQ
);
792 if (*oldnisacb
== '[') {
795 acb
[i
++] = oldnisacb
[i
];
796 while(i
< (sizeof(fstring
) - 2) && (oldnisacb
[i
] != ']'))
797 acb
[i
] = oldnisacb
[i
++];
802 if (i
== NEW_PW_FORMAT_SPACE_PADDED_LEN
) {
804 * We are using a new format, space padded
805 * acct ctrl field. Encode the given acct ctrl
808 fstrcpy(acb
, pdb_encode_acct_ctrl(pwd
->acct_ctrl
, NEW_PW_FORMAT_SPACE_PADDED_LEN
));
811 * If using the old format and the ACB_DISABLED or
812 * ACB_PWNOTREQ are set then set the lanman and NT passwords to NULL
813 * here as we have no space to encode the change.
815 if(pwd
->acct_ctrl
& (ACB_DISABLED
|ACB_PWNOTREQ
)) {
816 pwd
->smb_passwd
= NULL
;
817 pwd
->smb_nt_passwd
= NULL
;
821 /* Now do the LCT stuff. */
822 if (StrnCaseCmp(oldnislct
, "LCT-", 4) == 0) {
824 for(i
= 0; i
< 8; i
++) {
825 if(oldnislct
[i
+4] == '\0' || !isxdigit(oldnislct
[i
+4]))
830 * p points at 8 characters of hex digits -
831 * read into a time_t as the seconds since
832 * 1970 that the password was last changed.
834 got_pass_last_set_time
= True
;
836 } /* StrnCaseCmp() */
840 /* Entry is correctly formed. */
844 /* Create the 32 byte representation of the new p16 */
845 if(pwd
->smb_passwd
!= NULL
) {
846 for (i
= 0; i
< 16; i
++) {
847 slprintf(&lmpwd
[i
*2], 32, "%02X", (uchar
) pwd
->smb_passwd
[i
]);
850 if(pwd
->acct_ctrl
& ACB_PWNOTREQ
)
851 fstrcpy(lmpwd
, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
853 fstrcpy(lmpwd
, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
856 /* Add on the NT md4 hash */
857 if (pwd
->smb_nt_passwd
!= NULL
) {
858 for (i
= 0; i
< 16; i
++) {
859 slprintf(&ntpwd
[i
*2], 32, "%02X", (uchar
) pwd
->smb_nt_passwd
[i
]);
862 if(pwd
->acct_ctrl
& ACB_PWNOTREQ
)
863 fstrcpy(ntpwd
, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
865 fstrcpy(ntpwd
, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
868 pwd
->pass_last_set_time
= time(NULL
);
870 if(got_pass_last_set_time
) {
871 slprintf(lct
, 12, "LCT-%08X", (uint32
)pwd
->pass_last_set_time
);
874 set_single_attribute(obj
, NPF_LMPWD
, lmpwd
, strlen(lmpwd
), EN_CRYPT
);
875 set_single_attribute(obj
, NPF_NTPWD
, ntpwd
, strlen(ntpwd
), EN_CRYPT
);
876 set_single_attribute(obj
, NPF_ACB
, acb
, strlen(acb
), 0);
877 set_single_attribute(obj
, NPF_PWDLSET_T
, lct
, strlen(lct
), 0);
880 nis_add_entry(lp_smb_passwd_file(), obj
,
881 ADD_OVERWRITE
| FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
);
883 if(addresult
->status
!= NIS_SUCCESS
) {
884 DEBUG(0, ("mod_nisp21pwd_entry: NIS+ table update failed: %s %s\n", nisname
, nis_sperrno(addresult
->status
)));
885 nis_freeresult(addresult
);
886 nis_freeresult(result
);
890 DEBUG(6,("mod_nisp21pwd_entry: password changed\n"));
892 nis_freeresult(addresult
);
893 nis_freeresult(result
);
899 /*************************************************************************
900 Routine to search the nisplus passwd file for an entry matching the username
901 *************************************************************************/
902 static struct sam_passwd
*getnisp21pwnam(char *name
)
904 /* Static buffers we will return. */
905 static struct sam_passwd pw_buf
;
910 if (!*lp_smb_passwd_file())
912 DEBUG(0, ("No SMB password file set\n"));
916 DEBUG(10, ("getnisp21pwnam: search by name: %s\n", name
));
917 DEBUG(10, ("getnisp21pwnam: using NIS+ table %s\n", lp_smb_passwd_file()));
919 slprintf(nisname
, sizeof(nisname
)-1, "[name=%s],%s", name
, lp_smb_passwd_file());
921 /* Search the table. */
923 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
926 result
= nis_list(nisname
, FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
, NULL
, NULL
);
929 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_DFL
);
933 DEBUG(0,("getnisp21pwnam: NIS+ lookup time out\n"));
934 nis_freeresult(result
);
938 ret
= make_sam_from_nisresult(&pw_buf
, result
);
939 nis_freeresult(result
);
941 return ret
? &pw_buf
: NULL
;
944 /*************************************************************************
945 Routine to search the nisplus passwd file for an entry matching the username
946 *************************************************************************/
947 static struct sam_passwd
*getnisp21pwrid(uint32 rid
)
949 /* Static buffers we will return. */
950 static struct sam_passwd pw_buf
;
955 if (!*lp_smb_passwd_file())
957 DEBUG(0, ("getnisp21pwrid: no SMB password file set\n"));
961 DEBUG(10, ("getnisp21pwrid: search by rid: %x\n", rid
));
962 DEBUG(10, ("getnisp21pwrid: using NIS+ table %s\n", lp_smb_passwd_file()));
964 nisname
= make_nisname_from_user_rid(rid
, lp_smb_passwd_file());
966 /* Search the table. */
968 CatchSignal(SIGALRM
, SIGNAL_CAST gotalarm_sig
);
971 result
= nis_list(nisname
, FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
, NULL
, NULL
);
974 CatchSignal(SIGALRM
, SIGNAL_CAST SIG_DFL
);
978 DEBUG(0,("getnisp21pwrid: NIS+ lookup time out\n"));
979 nis_freeresult(result
);
983 ret
= make_sam_from_nisresult(&pw_buf
, result
);
984 nis_freeresult(result
);
986 return ret
? &pw_buf
: NULL
;
990 * Derived functions for NIS+.
993 static struct smb_passwd
*getnisppwent(void *vp
)
995 return pdb_sam_to_smb(getnisp21pwent(vp
));
998 static BOOL
add_nisppwd_entry(struct smb_passwd
*newpwd
)
1000 return add_nisp21pwd_entry(pdb_smb_to_sam(newpwd
));
1003 static BOOL
mod_nisppwd_entry(struct smb_passwd
* pwd
, BOOL override
)
1005 return mod_nisp21pwd_entry(pdb_smb_to_sam(pwd
), override
);
1008 static BOOL
del_nisppwd_entry(const char *name
)
1010 return False
; /* Dummy. */
1013 static struct smb_passwd
*getnisppwnam(char *name
)
1015 return pdb_sam_to_smb(getnisp21pwnam(name
));
1018 static struct sam_passwd
*getnisp21pwuid(uid_t smb_userid
)
1020 return getnisp21pwrid(pdb_uid_to_user_rid(smb_userid
));
1023 static struct smb_passwd
*getnisppwrid(uint32 user_rid
)
1025 return pdb_sam_to_smb(getnisp21pwuid(pdb_user_rid_to_uid(user_rid
)));
1028 static struct smb_passwd
*getnisppwuid(uid_t smb_userid
)
1030 return pdb_sam_to_smb(getnisp21pwuid(smb_userid
));
1033 static struct sam_disp_info
*getnispdispnam(char *name
)
1035 return pdb_sam_to_dispinfo(getnisp21pwnam(name
));
1038 static struct sam_disp_info
*getnispdisprid(uint32 rid
)
1040 return pdb_sam_to_dispinfo(getnisp21pwrid(rid
));
1043 static struct sam_disp_info
*getnispdispent(void *vp
)
1045 return pdb_sam_to_dispinfo(getnisp21pwent(vp
));
1048 static struct passdb_ops nispasswd_ops
= {
1064 add_nisp21pwd_entry
,
1065 mod_nisp21pwd_entry
,
1071 struct passdb_ops
*nisplus_initialize_password_db(void)
1073 return &nispasswd_ops
;
1077 void nisplus_dummy_function(void);
1078 void nisplus_dummy_function(void) { } /* stop some compilers complaining */
1079 #endif /* WITH_NISPLUS */
1081 /* useful code i can't bring myself to delete */
1083 static void useful_code(void) {
1084 /* checks user in unix password database. don't want to do that, here. */
1085 nisname
= make_nisname_from_name(newpwd
->smb_name
, "passwd.org_dir");
1087 nis_user
= nis_list(nisname
, FOLLOW_PATH
| EXPAND_NAME
| HARD_LOOKUP
, NULL
, NULL
);
1089 if (nis_user
->status
!= NIS_SUCCESS
|| NIS_RES_NUMOBJ(nis_user
) <= 0)
1091 DEBUG(3, ("useful_code: Unable to get NIS+ passwd entry for user: %s.\n",
1092 nis_sperrno(nis_user
->status
)));
1096 user_obj
= NIS_RES_OBJECT(nis_user
);
1097 make_nisname_from_name(ENTRY_VAL(user_obj
,0), pfile
);