mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
ede95f0b57
(This used to be commit d4d2f3bd89
)
1410 lines
42 KiB
C
1410 lines
42 KiB
C
/*
|
|
* Unix SMB/CIFS implementation.
|
|
* SMB parameters and setup
|
|
* Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
|
|
* Copyright (C) Benny Holmgren 1998 <bigfoot@astrakan.hgs.se>
|
|
* Copyright (C) Luke Kenneth Casson Leighton 1996-1998.
|
|
* Copyright (C) Toomas Soome <tsoome@ut.ee> 2001
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc., 675
|
|
* Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "includes.h"
|
|
|
|
#ifdef WITH_NISPLUS_SAM
|
|
|
|
#ifdef BROKEN_NISPLUS_INCLUDE_FILES
|
|
|
|
/*
|
|
* The following lines are needed due to buggy include files
|
|
* in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
|
|
* also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
|
|
* Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
|
|
* an enum in /usr/include/rpcsvc/nis.h.
|
|
*/
|
|
|
|
#if defined(GROUP)
|
|
#undef GROUP
|
|
#endif
|
|
|
|
#if defined(GROUP_OBJ)
|
|
#undef GROUP_OBJ
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#include <rpcsvc/nis.h>
|
|
|
|
extern int DEBUGLEVEL;
|
|
|
|
struct nisp_enum_info
|
|
{
|
|
nis_result *result;
|
|
int enum_entry;
|
|
};
|
|
|
|
static struct nisp_enum_info global_nisp_ent;
|
|
static VOLATILE sig_atomic_t gotalarm;
|
|
|
|
/***************************************************************
|
|
|
|
the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are:
|
|
|
|
name=S,nogw=r
|
|
uid=S,nogw=r
|
|
user_rid=S,nogw=r
|
|
smb_grpid=,nw+r
|
|
group_rid=,nw+r
|
|
acb=,nw+r
|
|
|
|
lmpwd=C,nw=,g=r,o=rm
|
|
ntpwd=C,nw=,g=r,o=rm
|
|
|
|
logon_t=,nw+r
|
|
logoff_t=,nw+r
|
|
kick_t=,nw+r
|
|
pwdlset_t=,nw+r
|
|
pwdlchg_t=,nw+r
|
|
pwdmchg_t=,nw+r
|
|
|
|
full_name=,nw+r
|
|
home_dir=,nw+r
|
|
dir_drive=,nw+r
|
|
logon_script=,nw+r
|
|
profile_path=,nw+r
|
|
acct_desc=,nw+r
|
|
workstations=,nw+r
|
|
|
|
hours=,nw+r
|
|
|
|
****************************************************************/
|
|
|
|
#define NPF_NAME 0
|
|
#define NPF_UID 1
|
|
#define NPF_USER_RID 2
|
|
#define NPF_SMB_GRPID 3
|
|
#define NPF_GROUP_RID 4
|
|
#define NPF_ACB 5
|
|
#define NPF_LMPWD 6
|
|
#define NPF_NTPWD 7
|
|
#define NPF_LOGON_T 8
|
|
#define NPF_LOGOFF_T 9
|
|
#define NPF_KICK_T 10
|
|
#define NPF_PWDLSET_T 11
|
|
#define NPF_PWDCCHG_T 12
|
|
#define NPF_PWDMCHG_T 13
|
|
#define NPF_FULL_NAME 14
|
|
#define NPF_HOME_DIR 15
|
|
#define NPF_DIR_DRIVE 16
|
|
#define NPF_LOGON_SCRIPT 17
|
|
#define NPF_PROFILE_PATH 18
|
|
#define NPF_ACCT_DESC 19
|
|
#define NPF_WORKSTATIONS 20
|
|
#define NPF_HOURS 21
|
|
|
|
/***************************************************************
|
|
Signal function to tell us we timed out.
|
|
****************************************************************/
|
|
static void gotalarm_sig(void)
|
|
{
|
|
gotalarm = 1;
|
|
}
|
|
|
|
/***************************************************************
|
|
make_nisname_from_user_rid
|
|
****************************************************************/
|
|
static char *make_nisname_from_user_rid(uint32 rid, char *pfile)
|
|
{
|
|
static pstring nisname;
|
|
|
|
safe_strcpy(nisname, "[user_rid=", sizeof(nisname)-1);
|
|
slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, rid);
|
|
safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
|
|
safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
|
|
|
|
return nisname;
|
|
}
|
|
|
|
/***************************************************************
|
|
make_nisname_from_uid
|
|
****************************************************************/
|
|
static char *make_nisname_from_uid(int uid, char *pfile)
|
|
{
|
|
static pstring nisname;
|
|
|
|
safe_strcpy(nisname, "[uid=", sizeof(nisname)-1);
|
|
slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, uid);
|
|
safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
|
|
safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
|
|
|
|
return nisname;
|
|
}
|
|
|
|
/***************************************************************
|
|
make_nisname_from_name
|
|
****************************************************************/
|
|
static char *make_nisname_from_name(const char *user_name, char *pfile)
|
|
{
|
|
static pstring nisname;
|
|
|
|
safe_strcpy(nisname, "[name=", sizeof(nisname)-1);
|
|
safe_strcat(nisname, user_name, sizeof(nisname) - strlen(nisname) - 1);
|
|
safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
|
|
safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
|
|
|
|
return nisname;
|
|
}
|
|
|
|
/*************************************************************************
|
|
gets a NIS+ attribute
|
|
*************************************************************************/
|
|
static void get_single_attribute(const nis_object *new_obj, int col,
|
|
char *val, int len)
|
|
{
|
|
int entry_len;
|
|
|
|
if (new_obj == NULL || val == NULL) return;
|
|
|
|
entry_len = ENTRY_LEN(new_obj, col);
|
|
if (len > entry_len)
|
|
{
|
|
len = entry_len;
|
|
}
|
|
|
|
safe_strcpy(val, ENTRY_VAL(new_obj, col), len-1);
|
|
}
|
|
|
|
/************************************************************************
|
|
makes a struct sam_passwd from a NIS+ object.
|
|
************************************************************************/
|
|
static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, const nis_object *obj)
|
|
{
|
|
char *ptr;
|
|
pstring full_name; /* this must be translated to dos code page */
|
|
pstring acct_desc; /* this must be translated to dos code page */
|
|
pstring home_dir; /* set default value from smb.conf for user */
|
|
pstring home_drive; /* set default value from smb.conf for user */
|
|
pstring logon_script; /* set default value from smb.conf for user */
|
|
pstring profile_path; /* set default value from smb.conf for user */
|
|
pstring hours;
|
|
int hours_len;
|
|
unsigned char smbpwd[16];
|
|
unsigned char smbntpwd[16];
|
|
|
|
|
|
/*
|
|
* time values. note: this code assumes 32bit time_t!
|
|
*/
|
|
|
|
/* Don't change these timestamp settings without a good reason. They are
|
|
important for NT member server compatibility. */
|
|
|
|
pdb_set_logon_time(pw_buf, (time_t)0, True);
|
|
ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGON_T);
|
|
if(ptr && *ptr && (StrnCaseCmp(ptr, "LNT-", 4)==0)) {
|
|
int i;
|
|
ptr += 4;
|
|
for(i = 0; i < 8; i++) {
|
|
if(ptr[i] == '\0' || !isxdigit(ptr[i]))
|
|
break;
|
|
}
|
|
if(i == 8) {
|
|
pdb_set_logon_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
|
|
}
|
|
}
|
|
|
|
pdb_set_logoff_time(pw_buf, get_time_t_max(), True);
|
|
ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGOFF_T);
|
|
if(ptr && *ptr && (StrnCaseCmp(ptr, "LOT-", 4)==0)) {
|
|
int i;
|
|
ptr += 4;
|
|
for(i = 0; i < 8; i++) {
|
|
if(ptr[i] == '\0' || !isxdigit(ptr[i]))
|
|
break;
|
|
}
|
|
if(i == 8) {
|
|
pdb_set_logoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
|
|
}
|
|
}
|
|
|
|
pdb_set_kickoff_time(pw_buf, get_time_t_max(), True);
|
|
ptr = (uchar *)ENTRY_VAL(obj, NPF_KICK_T);
|
|
if(ptr && *ptr && (StrnCaseCmp(ptr, "KOT-", 4)==0)) {
|
|
int i;
|
|
ptr += 4;
|
|
for(i = 0; i < 8; i++) {
|
|
if(ptr[i] == '\0' || !isxdigit(ptr[i]))
|
|
break;
|
|
}
|
|
if(i == 8) {
|
|
pdb_set_kickoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
|
|
}
|
|
}
|
|
|
|
pdb_set_pass_last_set_time(pw_buf, (time_t)0);
|
|
ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDLSET_T);
|
|
if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) {
|
|
int i;
|
|
ptr += 4;
|
|
for(i = 0; i < 8; i++) {
|
|
if(ptr[i] == '\0' || !isxdigit(ptr[i]))
|
|
break;
|
|
}
|
|
if(i == 8) {
|
|
pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16));
|
|
}
|
|
}
|
|
|
|
pdb_set_pass_can_change_time(pw_buf, (time_t)0, True);
|
|
ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDCCHG_T);
|
|
if(ptr && *ptr && (StrnCaseCmp(ptr, "CCT-", 4)==0)) {
|
|
int i;
|
|
ptr += 4;
|
|
for(i = 0; i < 8; i++) {
|
|
if(ptr[i] == '\0' || !isxdigit(ptr[i]))
|
|
break;
|
|
}
|
|
if(i == 8) {
|
|
pdb_set_pass_can_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
|
|
}
|
|
}
|
|
|
|
pdb_set_pass_must_change_time(pw_buf, get_time_t_max(), True); /* Password never expires. */
|
|
ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDMCHG_T);
|
|
if(ptr && *ptr && (StrnCaseCmp(ptr, "MCT-", 4)==0)) {
|
|
int i;
|
|
ptr += 4;
|
|
for(i = 0; i < 8; i++) {
|
|
if(ptr[i] == '\0' || !isxdigit(ptr[i]))
|
|
break;
|
|
}
|
|
if(i == 8) {
|
|
pdb_set_pass_must_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
|
|
}
|
|
}
|
|
|
|
/* string values */
|
|
pdb_set_username(pw_buf, ENTRY_VAL(obj, NPF_NAME));
|
|
pdb_set_domain(pw_buf, lp_workgroup());
|
|
/* pdb_set_nt_username() -- cant set it here... */
|
|
|
|
get_single_attribute(obj, NPF_FULL_NAME, full_name, sizeof(pstring));
|
|
#if 0
|
|
unix_to_dos(full_name, True);
|
|
#endif
|
|
pdb_set_fullname(pw_buf, full_name);
|
|
|
|
pdb_set_acct_ctrl(pw_buf, pdb_decode_acct_ctrl(ENTRY_VAL(obj,
|
|
NPF_ACB)));
|
|
|
|
get_single_attribute(obj, NPF_ACCT_DESC, acct_desc, sizeof(pstring));
|
|
#if 0
|
|
unix_to_dos(acct_desc, True);
|
|
#endif
|
|
pdb_set_acct_desc(pw_buf, acct_desc);
|
|
|
|
pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS));
|
|
pdb_set_munged_dial(pw_buf, NULL);
|
|
|
|
pdb_set_uid(pw_buf, atoi(ENTRY_VAL(obj, NPF_UID)));
|
|
pdb_set_gid(pw_buf, atoi(ENTRY_VAL(obj, NPF_SMB_GRPID)));
|
|
pdb_set_user_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID)));
|
|
pdb_set_group_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID)));
|
|
|
|
/* values, must exist for user */
|
|
if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) {
|
|
|
|
get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring));
|
|
if( !(home_dir && *home_dir) ) {
|
|
pstrcpy(home_dir, lp_logon_home());
|
|
pdb_set_homedir(pw_buf, home_dir, False);
|
|
}
|
|
else
|
|
pdb_set_homedir(pw_buf, home_dir, True);
|
|
|
|
get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring));
|
|
if( !(home_drive && *home_drive) ) {
|
|
pstrcpy(home_drive, lp_logon_drive());
|
|
pdb_set_dir_drive(pw_buf, home_drive, False);
|
|
}
|
|
else
|
|
pdb_set_dir_drive(pw_buf, home_drive, True);
|
|
|
|
get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script,
|
|
sizeof(pstring));
|
|
if( !(logon_script && *logon_script) ) {
|
|
pstrcpy(logon_script, lp_logon_script());
|
|
}
|
|
else
|
|
pdb_set_logon_script(pw_buf, logon_script, True);
|
|
|
|
get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring));
|
|
if( !(profile_path && *profile_path) ) {
|
|
pstrcpy(profile_path, lp_logon_path());
|
|
pdb_set_profile_path(pw_buf, profile_path, False);
|
|
}
|
|
else
|
|
pdb_set_profile_path(pw_buf, profile_path, True);
|
|
|
|
}
|
|
else
|
|
{
|
|
/* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
|
|
pdb_set_group_rid (pw_buf, DOMAIN_GROUP_RID_USERS);
|
|
}
|
|
|
|
/* Check the lanman password column. */
|
|
ptr = (char *)ENTRY_VAL(obj, NPF_LMPWD);
|
|
if (!pdb_set_lanman_passwd(pw_buf, NULL))
|
|
return False;
|
|
|
|
if (!strncasecmp(ptr, "NO PASSWORD", 11)) {
|
|
pdb_set_acct_ctrl(pw_buf, pdb_get_acct_ctrl(pw_buf) | ACB_PWNOTREQ);
|
|
} else {
|
|
if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbpwd)) {
|
|
DEBUG(0, ("malformed LM pwd entry: %s.\n",
|
|
pdb_get_username(pw_buf)));
|
|
return False;
|
|
}
|
|
if (!pdb_set_lanman_passwd(pw_buf, smbpwd))
|
|
return False;
|
|
}
|
|
|
|
/* Check the NT password column. */
|
|
ptr = ENTRY_VAL(obj, NPF_NTPWD);
|
|
if (!pdb_set_nt_passwd(pw_buf, NULL))
|
|
return False;
|
|
|
|
if (!(pdb_get_acct_ctrl(pw_buf) & ACB_PWNOTREQ) &&
|
|
strncasecmp(ptr, "NO PASSWORD", 11)) {
|
|
if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbntpwd)) {
|
|
DEBUG(0, ("malformed NT pwd entry:\
|
|
uid = %d.\n",
|
|
pdb_get_uid(pw_buf)));
|
|
return False;
|
|
}
|
|
if (!pdb_set_nt_passwd(pw_buf, smbntpwd))
|
|
return False;
|
|
}
|
|
|
|
pdb_set_unknown_3(pw_buf, 0xffffff); /* don't know */
|
|
pdb_set_logon_divs(pw_buf, 168); /* hours per week */
|
|
|
|
if( (hours_len = ENTRY_LEN(obj, NPF_HOURS)) == 21 ) {
|
|
memcpy(hours, ENTRY_VAL(obj, NPF_HOURS), hours_len);
|
|
} else {
|
|
hours_len = 21; /* 21 times 8 bits = 168 */
|
|
/* available at all hours */
|
|
memset(hours, 0xff, hours_len);
|
|
}
|
|
pdb_set_hours_len(pw_buf, hours_len);
|
|
pdb_set_hours(pw_buf, hours);
|
|
|
|
pdb_set_unknown_5(pw_buf, 0x00020000); /* don't know */
|
|
pdb_set_unknown_6(pw_buf, 0x000004ec); /* don't know */
|
|
|
|
return True;
|
|
}
|
|
|
|
/************************************************************************
|
|
makes a struct sam_passwd from a NIS+ result.
|
|
************************************************************************/
|
|
static BOOL make_sam_from_nisresult(SAM_ACCOUNT *pw_buf, const nis_result *result)
|
|
{
|
|
if (pw_buf == NULL || result == NULL) return False;
|
|
|
|
if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND)
|
|
{
|
|
DEBUG(0, ("NIS+ lookup failure: %s\n",
|
|
nis_sperrno(result->status)));
|
|
return False;
|
|
}
|
|
|
|
/* User not found. */
|
|
if (NIS_RES_NUMOBJ(result) <= 0)
|
|
{
|
|
DEBUG(10, ("user not found in NIS+\n"));
|
|
return False;
|
|
}
|
|
|
|
if (NIS_RES_NUMOBJ(result) > 1)
|
|
{
|
|
DEBUG(10, ("WARNING: Multiple entries for user in NIS+ table!\n"));
|
|
}
|
|
|
|
/* Grab the first hit. */
|
|
return make_sam_from_nisp_object(pw_buf, &NIS_RES_OBJECT(result)[0]);
|
|
}
|
|
|
|
/*************************************************************************
|
|
sets a NIS+ attribute
|
|
*************************************************************************/
|
|
static void set_single_attribute(nis_object *new_obj, int col,
|
|
const char *val, int len, int flags)
|
|
{
|
|
if (new_obj == NULL) return;
|
|
|
|
ENTRY_VAL(new_obj, col) = val;
|
|
ENTRY_LEN(new_obj, col) = len+1;
|
|
|
|
if (flags != 0)
|
|
{
|
|
new_obj->EN_data.en_cols.en_cols_val[col].ec_flags = flags;
|
|
}
|
|
}
|
|
|
|
/***************************************************************
|
|
copy or modify nis object. this object is used to add or update
|
|
nisplus table entry.
|
|
****************************************************************/
|
|
static BOOL init_nisp_from_sam(nis_object *obj, const SAM_ACCOUNT *sampass,
|
|
nis_object *old)
|
|
{
|
|
/*
|
|
* Fill nis_object for entry add or update.
|
|
* if we are updateing, we have to find out differences and set
|
|
* EN_MODIFIED flag. also set need_to_modify to trigger
|
|
* nis_modify_entry() call in pdb_update_sam_account().
|
|
*
|
|
* TODO:
|
|
* get data from SAM
|
|
* if (modify) get data from nis_object, compare and store if
|
|
* different + set EN_MODIFIED and need_to_modify
|
|
* else
|
|
* store
|
|
*/
|
|
BOOL need_to_modify = False;
|
|
const char *name = pdb_get_username(sampass); /* from SAM */
|
|
/* these must be static or allocate and free entry columns! */
|
|
static fstring uid; /* from SAM */
|
|
static fstring user_rid; /* from SAM */
|
|
static fstring gid; /* from SAM */
|
|
static fstring group_rid; /* from SAM */
|
|
char *acb; /* from SAM */
|
|
static fstring smb_passwd; /* from SAM */
|
|
static fstring smb_nt_passwd; /* from SAM */
|
|
static fstring logon_t; /* from SAM */
|
|
static fstring logoff_t; /* from SAM */
|
|
static fstring kickoff_t; /* from SAM */
|
|
static fstring pwdlset_t; /* from SAM */
|
|
static fstring pwdlchg_t; /* from SAM */
|
|
static fstring pwdmchg_t; /* from SAM */
|
|
static fstring full_name; /* from SAM */
|
|
static fstring acct_desc; /* from SAM */
|
|
static char empty[1]; /* just an empty string */
|
|
|
|
slprintf(uid, sizeof(uid)-1, "%u", pdb_get_uid(sampass));
|
|
slprintf(user_rid, sizeof(user_rid)-1, "%u",
|
|
pdb_get_user_rid(sampass)? pdb_get_user_rid(sampass):
|
|
pdb_uid_to_user_rid(pdb_get_uid(sampass)));
|
|
slprintf(gid, sizeof(gid)-1, "%u", pdb_get_gid(sampass));
|
|
|
|
{
|
|
uint32 rid;
|
|
GROUP_MAP map;
|
|
|
|
rid=pdb_get_group_rid(sampass);
|
|
|
|
if (rid==0) {
|
|
if (get_group_map_from_gid(pdb_get_gid(sampass), &map, MAPPING_WITHOUT_PRIV)) {
|
|
sid_peek_rid(&map.sid, &rid);
|
|
} else
|
|
rid=pdb_gid_to_group_rid(pdb_get_gid(sampass));
|
|
}
|
|
|
|
slprintf(group_rid, sizeof(group_rid)-1, "%u", rid);
|
|
}
|
|
|
|
acb = pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sampass),
|
|
NEW_PW_FORMAT_SPACE_PADDED_LEN);
|
|
pdb_sethexpwd (smb_passwd, pdb_get_lanman_passwd(sampass),
|
|
pdb_get_acct_ctrl(sampass));
|
|
pdb_sethexpwd (smb_nt_passwd, pdb_get_nt_passwd(sampass),
|
|
pdb_get_acct_ctrl(sampass));
|
|
slprintf(logon_t, 13, "LNT-%08X",
|
|
(uint32)pdb_get_logon_time(sampass));
|
|
slprintf(logoff_t, 13, "LOT-%08X",
|
|
(uint32)pdb_get_logoff_time(sampass));
|
|
slprintf(kickoff_t, 13, "KOT-%08X",
|
|
(uint32)pdb_get_kickoff_time(sampass));
|
|
slprintf(pwdlset_t, 13, "LCT-%08X",
|
|
(uint32)pdb_get_pass_last_set_time(sampass));
|
|
slprintf(pwdlchg_t, 13, "CCT-%08X",
|
|
(uint32)pdb_get_pass_can_change_time(sampass));
|
|
slprintf(pwdmchg_t, 13, "MCT-%08X",
|
|
(uint32)pdb_get_pass_must_change_time(sampass));
|
|
safe_strcpy(full_name, pdb_get_fullname(sampass), sizeof(full_name)-1);
|
|
safe_strcpy(acct_desc, pdb_get_acct_desc(sampass), sizeof(acct_desc)-1);
|
|
|
|
#if 0
|
|
|
|
/* Not sure what to do with these guys. -tpot */
|
|
|
|
dos_to_unix(full_name, True);
|
|
dos_to_unix(acct_desc, True);
|
|
|
|
#endif
|
|
|
|
if( old ) {
|
|
/* name */
|
|
if(strcmp(ENTRY_VAL(old, NPF_NAME), name))
|
|
{
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_NAME, name, strlen(name),
|
|
EN_MODIFIED);
|
|
}
|
|
|
|
|
|
/* uid */
|
|
if(pdb_get_uid(sampass) != -1) {
|
|
if(!ENTRY_VAL(old, NPF_UID) || strcmp(ENTRY_VAL(old, NPF_UID), uid))
|
|
{
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_UID, uid,
|
|
strlen(uid), EN_MODIFIED);
|
|
}
|
|
}
|
|
|
|
/* user_rid */
|
|
if (pdb_get_user_rid(sampass)) {
|
|
if(!ENTRY_VAL(old, NPF_USER_RID) ||
|
|
strcmp(ENTRY_VAL(old, NPF_USER_RID), user_rid) ) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_USER_RID, user_rid,
|
|
strlen(user_rid), EN_MODIFIED);
|
|
}
|
|
}
|
|
|
|
/* smb_grpid */
|
|
if (pdb_get_gid(sampass) != -1) {
|
|
if(!ENTRY_VAL(old, NPF_SMB_GRPID) ||
|
|
strcmp(ENTRY_VAL(old, NPF_SMB_GRPID), gid) ) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_SMB_GRPID, gid,
|
|
strlen(gid), EN_MODIFIED);
|
|
}
|
|
}
|
|
|
|
/* group_rid */
|
|
if (pdb_get_group_rid(sampass)) {
|
|
if(!ENTRY_VAL(old, NPF_GROUP_RID) ||
|
|
strcmp(ENTRY_VAL(old, NPF_GROUP_RID), group_rid) ) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_GROUP_RID, group_rid,
|
|
strlen(group_rid), EN_MODIFIED);
|
|
}
|
|
}
|
|
|
|
/* acb */
|
|
if (!ENTRY_VAL(old, NPF_ACB) ||
|
|
strcmp(ENTRY_VAL(old, NPF_ACB), acb)) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_ACB, acb, strlen(acb), EN_MODIFIED);
|
|
}
|
|
|
|
/* lmpwd */
|
|
if(!ENTRY_VAL(old, NPF_LMPWD) ||
|
|
strcmp(ENTRY_VAL(old, NPF_LMPWD), smb_passwd) ) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_LMPWD, smb_passwd,
|
|
strlen(smb_passwd), EN_CRYPT|EN_MODIFIED);
|
|
}
|
|
|
|
/* ntpwd */
|
|
if(!ENTRY_VAL(old, NPF_NTPWD) ||
|
|
strcmp(ENTRY_VAL(old, NPF_NTPWD), smb_nt_passwd) ) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_NTPWD, smb_nt_passwd,
|
|
strlen(smb_nt_passwd), EN_CRYPT|EN_MODIFIED);
|
|
}
|
|
|
|
/* logon_t */
|
|
if( pdb_get_logon_time(sampass) &&
|
|
(!ENTRY_VAL(old, NPF_LOGON_T) ||
|
|
strcmp(ENTRY_VAL(old, NPF_LOGON_T), logon_t ))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_LOGON_T, logon_t,
|
|
strlen(logon_t), EN_MODIFIED);
|
|
}
|
|
|
|
/* logoff_t */
|
|
if( pdb_get_logoff_time(sampass) &&
|
|
(!ENTRY_VAL(old, NPF_LOGOFF_T) ||
|
|
strcmp(ENTRY_VAL(old, NPF_LOGOFF_T), logoff_t))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_LOGOFF_T, logoff_t,
|
|
strlen(logoff_t), EN_MODIFIED);
|
|
}
|
|
|
|
/* kick_t */
|
|
if( pdb_get_kickoff_time(sampass) &&
|
|
(!ENTRY_VAL(old, NPF_KICK_T) ||
|
|
strcmp(ENTRY_VAL(old, NPF_KICK_T), kickoff_t))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_KICK_T, kickoff_t,
|
|
strlen(kickoff_t), EN_MODIFIED);
|
|
}
|
|
|
|
/* pwdlset_t */
|
|
if( pdb_get_pass_last_set_time(sampass) &&
|
|
(!ENTRY_VAL(old, NPF_PWDLSET_T) ||
|
|
strcmp(ENTRY_VAL(old, NPF_PWDLSET_T), pwdlset_t))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_PWDLSET_T, pwdlset_t,
|
|
strlen(pwdlset_t), EN_MODIFIED);
|
|
}
|
|
|
|
/* pwdlchg_t */
|
|
if( pdb_get_pass_can_change_time(sampass) &&
|
|
(!ENTRY_VAL(old, NPF_PWDCCHG_T) ||
|
|
strcmp(ENTRY_VAL(old, NPF_PWDCCHG_T), pwdlchg_t))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_PWDCCHG_T, pwdlchg_t,
|
|
strlen(pwdlchg_t), EN_MODIFIED);
|
|
}
|
|
|
|
/* pwdmchg_t */
|
|
if( pdb_get_pass_must_change_time(sampass) &&
|
|
(!ENTRY_VAL(old, NPF_PWDMCHG_T) ||
|
|
strcmp(ENTRY_VAL(old, NPF_PWDMCHG_T), pwdmchg_t))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_PWDMCHG_T, pwdmchg_t,
|
|
strlen(pwdmchg_t), EN_MODIFIED);
|
|
}
|
|
|
|
/* full_name */
|
|
/* must support set, unset and change */
|
|
if ( (pdb_get_fullname(sampass) &&
|
|
!ENTRY_VAL(old, NPF_FULL_NAME)) ||
|
|
(ENTRY_VAL(old, NPF_FULL_NAME) &&
|
|
!pdb_get_fullname(sampass)) ||
|
|
(ENTRY_VAL(old, NPF_FULL_NAME) &&
|
|
pdb_get_fullname(sampass) &&
|
|
strcmp( ENTRY_VAL(old, NPF_FULL_NAME), full_name ))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_FULL_NAME, full_name,
|
|
strlen(full_name), EN_MODIFIED);
|
|
}
|
|
|
|
/* home_dir */
|
|
/* must support set, unset and change */
|
|
if( (pdb_get_homedir(sampass) &&
|
|
!ENTRY_VAL(old, NPF_HOME_DIR)) ||
|
|
(ENTRY_VAL(old, NPF_HOME_DIR) &&
|
|
!pdb_get_homedir(sampass)) ||
|
|
(ENTRY_VAL(old, NPF_HOME_DIR) &&
|
|
pdb_get_homedir(sampass) &&
|
|
strcmp( ENTRY_VAL(old, NPF_HOME_DIR),
|
|
pdb_get_homedir(sampass)))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_HOME_DIR, pdb_get_homedir(sampass),
|
|
strlen(pdb_get_homedir(sampass)), EN_MODIFIED);
|
|
}
|
|
|
|
/* dir_drive */
|
|
/* must support set, unset and change */
|
|
if( (pdb_get_dirdrive(sampass) &&
|
|
!ENTRY_VAL(old, NPF_DIR_DRIVE)) ||
|
|
(ENTRY_VAL(old, NPF_DIR_DRIVE) &&
|
|
!pdb_get_dirdrive(sampass)) ||
|
|
(ENTRY_VAL(old, NPF_DIR_DRIVE) &&
|
|
pdb_get_dirdrive(sampass) &&
|
|
strcmp( ENTRY_VAL(old, NPF_DIR_DRIVE),
|
|
pdb_get_dirdrive(sampass)))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_DIR_DRIVE, pdb_get_dirdrive(sampass),
|
|
strlen(pdb_get_dirdrive(sampass)), EN_MODIFIED);
|
|
}
|
|
|
|
/* logon_script */
|
|
/* must support set, unset and change */
|
|
if( (pdb_get_logon_script(sampass) &&
|
|
!ENTRY_VAL(old, NPF_LOGON_SCRIPT) ||
|
|
(ENTRY_VAL(old, NPF_LOGON_SCRIPT) &&
|
|
!pdb_get_logon_script(sampass)) ||
|
|
( ENTRY_VAL(old, NPF_LOGON_SCRIPT) &&
|
|
pdb_get_logon_script(sampass) &&
|
|
strcmp( ENTRY_VAL(old, NPF_LOGON_SCRIPT),
|
|
pdb_get_logon_script(sampass))))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_LOGON_SCRIPT,
|
|
pdb_get_logon_script(sampass),
|
|
strlen(pdb_get_logon_script(sampass)),
|
|
EN_MODIFIED);
|
|
}
|
|
|
|
/* profile_path */
|
|
/* must support set, unset and change */
|
|
if( (pdb_get_profile_path(sampass) &&
|
|
!ENTRY_VAL(old, NPF_PROFILE_PATH)) ||
|
|
(ENTRY_VAL(old, NPF_PROFILE_PATH) &&
|
|
!pdb_get_profile_path(sampass)) ||
|
|
(ENTRY_VAL(old, NPF_PROFILE_PATH) &&
|
|
pdb_get_profile_path(sampass) &&
|
|
strcmp( ENTRY_VAL(old, NPF_PROFILE_PATH),
|
|
pdb_get_profile_path(sampass) ) )) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_PROFILE_PATH,
|
|
pdb_get_profile_path(sampass),
|
|
strlen(pdb_get_profile_path(sampass)),
|
|
EN_MODIFIED);
|
|
}
|
|
|
|
/* acct_desc */
|
|
/* must support set, unset and change */
|
|
if( (pdb_get_acct_desc(sampass) &&
|
|
!ENTRY_VAL(old, NPF_ACCT_DESC)) ||
|
|
(ENTRY_VAL(old, NPF_ACCT_DESC) &&
|
|
!pdb_get_acct_desc(sampass)) ||
|
|
(ENTRY_VAL(old, NPF_ACCT_DESC) &&
|
|
pdb_get_acct_desc(sampass) &&
|
|
strcmp( ENTRY_VAL(old, NPF_ACCT_DESC), acct_desc ) )) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_ACCT_DESC, acct_desc,
|
|
strlen(acct_desc), EN_MODIFIED);
|
|
}
|
|
|
|
/* workstations */
|
|
/* must support set, unset and change */
|
|
if ( (pdb_get_workstations(sampass) &&
|
|
!ENTRY_VAL(old, NPF_WORKSTATIONS) ) ||
|
|
(ENTRY_VAL(old, NPF_WORKSTATIONS) &&
|
|
!pdb_get_workstations(sampass)) ||
|
|
(ENTRY_VAL(old, NPF_WORKSTATIONS) &&
|
|
pdb_get_workstations(sampass)) &&
|
|
strcmp( ENTRY_VAL(old, NPF_WORKSTATIONS),
|
|
pdb_get_workstations(sampass))) {
|
|
need_to_modify = True;
|
|
set_single_attribute(obj, NPF_WORKSTATIONS,
|
|
pdb_get_workstations(sampass),
|
|
strlen(pdb_get_workstations(sampass)),
|
|
EN_MODIFIED);
|
|
}
|
|
|
|
/* hours */
|
|
if ((pdb_get_hours_len(sampass) != ENTRY_LEN(old, NPF_HOURS)) ||
|
|
memcmp(pdb_get_hours(sampass), ENTRY_VAL(old, NPF_HOURS),
|
|
ENTRY_LEN(old, NPF_HOURS))) {
|
|
need_to_modify = True;
|
|
/* set_single_attribute will add 1 for len ... */
|
|
set_single_attribute(obj, NPF_HOURS, pdb_get_hours(sampass),
|
|
pdb_get_hours_len(sampass)-1, EN_MODIFIED);
|
|
}
|
|
} else {
|
|
const char *homedir, *dirdrive, *logon_script, *profile_path, *workstations;
|
|
|
|
*empty = '\0'; /* empty string */
|
|
|
|
set_single_attribute(obj, NPF_NAME, name, strlen(name), 0);
|
|
set_single_attribute(obj, NPF_UID, uid, strlen(uid), 0);
|
|
set_single_attribute(obj, NPF_USER_RID, user_rid,
|
|
strlen(user_rid), 0);
|
|
set_single_attribute(obj, NPF_SMB_GRPID, gid, strlen(gid), 0);
|
|
set_single_attribute(obj, NPF_GROUP_RID, group_rid,
|
|
strlen(group_rid), 0);
|
|
set_single_attribute(obj, NPF_ACB, acb, strlen(acb), 0);
|
|
set_single_attribute(obj, NPF_LMPWD, smb_passwd,
|
|
strlen(smb_passwd), EN_CRYPT);
|
|
set_single_attribute(obj, NPF_NTPWD, smb_nt_passwd,
|
|
strlen(smb_nt_passwd), EN_CRYPT);
|
|
set_single_attribute(obj, NPF_LOGON_T, logon_t,
|
|
strlen(logon_t), 0);
|
|
set_single_attribute(obj, NPF_LOGOFF_T, logoff_t,
|
|
strlen(logoff_t), 0);
|
|
set_single_attribute(obj, NPF_KICK_T, kickoff_t,
|
|
strlen(kickoff_t),0);
|
|
set_single_attribute(obj, NPF_PWDLSET_T, pwdlset_t,
|
|
strlen(pwdlset_t), 0);
|
|
set_single_attribute(obj, NPF_PWDCCHG_T, pwdlchg_t,
|
|
strlen(pwdlchg_t), 0);
|
|
set_single_attribute(obj, NPF_PWDMCHG_T, pwdmchg_t,
|
|
strlen(pwdmchg_t), 0);
|
|
set_single_attribute(obj, NPF_FULL_NAME ,
|
|
full_name, strlen(full_name), 0);
|
|
|
|
if(!(homedir = pdb_get_homedir(sampass)))
|
|
homedir = empty;
|
|
|
|
set_single_attribute(obj, NPF_HOME_DIR,
|
|
homedir, strlen(homedir), 0);
|
|
|
|
if(!(dirdrive = pdb_get_dirdrive(sampass)))
|
|
dirdrive = empty;
|
|
|
|
set_single_attribute(obj, NPF_DIR_DRIVE,
|
|
dirdrive, strlen(dirdrive), 0);
|
|
|
|
if(!(logon_script = pdb_get_logon_script(sampass)))
|
|
logon_script = empty;
|
|
|
|
set_single_attribute(obj, NPF_LOGON_SCRIPT,
|
|
logon_script, strlen(logon_script), 0);
|
|
|
|
if(!(profile_path = pdb_get_profile_path(sampass)))
|
|
profile_path = empty;
|
|
|
|
set_single_attribute(obj, NPF_PROFILE_PATH,
|
|
profile_path, strlen(profile_path), 0);
|
|
|
|
set_single_attribute(obj, NPF_ACCT_DESC,
|
|
acct_desc, strlen(acct_desc), 0);
|
|
|
|
if(!(workstations = pdb_get_workstations(sampass)))
|
|
workstations = empty;
|
|
|
|
set_single_attribute(obj, NPF_WORKSTATIONS,
|
|
workstations, strlen(workstations), 0);
|
|
|
|
/* set_single_attribute will add 1 for len ... */
|
|
set_single_attribute(obj, NPF_HOURS,
|
|
pdb_get_hours(sampass),
|
|
pdb_get_hours_len(sampass)-1, 0);
|
|
}
|
|
|
|
return need_to_modify;
|
|
}
|
|
|
|
/***************************************************************
|
|
calls nis_list, returns results.
|
|
****************************************************************/
|
|
static nis_result *nisp_get_nis_list(const char *nis_name, unsigned int flags)
|
|
{
|
|
nis_result *result;
|
|
int i;
|
|
|
|
if( ! flags)
|
|
flags = FOLLOW_LINKS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP;
|
|
|
|
for(i = 0; i<2;i++ ) {
|
|
alarm(60); /* hopefully ok for long searches */
|
|
result = nis_list(nis_name, flags,NULL,NULL);
|
|
|
|
alarm(0);
|
|
CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
|
|
|
|
if (gotalarm)
|
|
{
|
|
DEBUG(0,("NIS+ lookup time out\n"));
|
|
nis_freeresult(result);
|
|
return NULL;
|
|
}
|
|
if( !(flags & MASTER_ONLY) && NIS_RES_NUMOBJ(result) <= 0 ) {
|
|
/* nis replicas are not in sync perhaps?
|
|
* this can happen, if account was just added.
|
|
*/
|
|
DEBUG(10,("will try master only\n"));
|
|
nis_freeresult(result);
|
|
flags |= MASTER_ONLY;
|
|
} else
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/***************************************************************
|
|
Start to enumerate the nisplus passwd list.
|
|
****************************************************************/
|
|
BOOL pdb_setsampwent(BOOL update)
|
|
{
|
|
char *sp, * p = lp_smb_passwd_file();
|
|
pstring pfiletmp;
|
|
|
|
if( (sp = strrchr( p, '/' )) )
|
|
safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1);
|
|
else
|
|
safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
|
|
pdb_endsampwent(); /* just in case */
|
|
global_nisp_ent.result = nisp_get_nis_list( pfiletmp, 0 );
|
|
global_nisp_ent.enum_entry = 0;
|
|
return global_nisp_ent.result != NULL ? True : False;
|
|
}
|
|
|
|
/***************************************************************
|
|
End enumeration of the nisplus passwd list.
|
|
****************************************************************/
|
|
void pdb_endsampwent(void)
|
|
{
|
|
if( global_nisp_ent.result )
|
|
nis_freeresult(global_nisp_ent.result);
|
|
global_nisp_ent.result = NULL;
|
|
global_nisp_ent.enum_entry = 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
Routine to return the next entry in the nisplus passwd list.
|
|
*************************************************************************/
|
|
BOOL pdb_getsampwent(SAM_ACCOUNT *user)
|
|
{
|
|
int enum_entry = (int)(global_nisp_ent.enum_entry);
|
|
nis_result *result = global_nisp_ent.result;
|
|
|
|
if (user==NULL) {
|
|
DEBUG(0,("SAM_ACCOUNT is NULL.\n"));
|
|
return False;
|
|
}
|
|
|
|
if (result == NULL ||
|
|
enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ(result) - 1))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if(!make_sam_from_nisp_object(user, &NIS_RES_OBJECT(result)[enum_entry]) )
|
|
{
|
|
DEBUG(0,("Bad SAM_ACCOUNT entry returned from NIS+!\n"));
|
|
return False;
|
|
}
|
|
(int)(global_nisp_ent.enum_entry)++;
|
|
return True;
|
|
}
|
|
|
|
/*************************************************************************
|
|
Routine to search the nisplus passwd file for an entry matching the username
|
|
*************************************************************************/
|
|
BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname)
|
|
{
|
|
/* Static buffers we will return. */
|
|
nis_result *result = NULL;
|
|
pstring nisname;
|
|
BOOL ret;
|
|
char *pfile = lp_smb_passwd_file();
|
|
int i;
|
|
|
|
if (!*pfile)
|
|
{
|
|
DEBUG(0, ("No SMB password file set\n"));
|
|
return False;
|
|
}
|
|
if( strrchr( pfile, '/') )
|
|
pfile = strrchr( pfile, '/') + 1;
|
|
|
|
slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile);
|
|
DEBUG(10, ("search by nisname: %s\n", nisname));
|
|
|
|
/* Search the table. */
|
|
|
|
if(!(result = nisp_get_nis_list(nisname, 0)))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
ret = make_sam_from_nisresult(user, result);
|
|
nis_freeresult(result);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
Routine to search the nisplus passwd file for an entry matching the username
|
|
*************************************************************************/
|
|
BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
|
|
{
|
|
nis_result *result;
|
|
char *nisname;
|
|
BOOL ret;
|
|
char *sp, *p = lp_smb_passwd_file();
|
|
pstring pfiletmp;
|
|
|
|
if (!*p)
|
|
{
|
|
DEBUG(0, ("no SMB password file set\n"));
|
|
return False;
|
|
}
|
|
|
|
if( (sp = strrchr( p, '/' )) )
|
|
safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1);
|
|
else
|
|
safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
|
|
nisname = make_nisname_from_user_rid(rid, pfiletmp);
|
|
|
|
DEBUG(10, ("search by rid: %s\n", nisname));
|
|
|
|
/* Search the table. */
|
|
|
|
if(!(result = nisp_get_nis_list(nisname, 0)))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
ret = make_sam_from_nisresult(user, result);
|
|
nis_freeresult(result);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
Routine to remove entry from the nisplus smbpasswd table
|
|
*************************************************************************/
|
|
BOOL pdb_delete_sam_account(SAM_ACCOUNT * user)
|
|
{
|
|
const char *sname;
|
|
char *pfile = lp_smb_passwd_file();
|
|
pstring nisname;
|
|
nis_result *result, *delresult;
|
|
nis_object *obj;
|
|
int i;
|
|
|
|
if (!user) {
|
|
DEBUG(0, ("no SAM_ACCOUNT specified!\n"));
|
|
return False;
|
|
}
|
|
|
|
sname = pdb_get_username(user);
|
|
|
|
if (!*pfile)
|
|
{
|
|
DEBUG(0, ("no SMB password file set\n"));
|
|
return False;
|
|
}
|
|
if( strrchr( pfile, '/') )
|
|
pfile = strrchr( pfile, '/') + 1;
|
|
|
|
slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile);
|
|
|
|
/* Search the table. */
|
|
|
|
if( !(result = nisp_get_nis_list(nisname,
|
|
MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\
|
|
EXPAND_NAME|HARD_LOOKUP))) {
|
|
return False;
|
|
}
|
|
|
|
if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) {
|
|
/* User not found. */
|
|
DEBUG(0,("user not found in NIS+\n"));
|
|
nis_freeresult(result);
|
|
return False;
|
|
}
|
|
|
|
obj = NIS_RES_OBJECT(result);
|
|
slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", sname, obj->zo_name,
|
|
obj->zo_domain);
|
|
|
|
DEBUG(10, ("removing name: %s\n", nisname));
|
|
delresult = nis_remove_entry(nisname, obj,
|
|
MASTER_ONLY|REM_MULTIPLE|ALL_RESULTS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP);
|
|
|
|
nis_freeresult(result);
|
|
|
|
if(delresult->status != NIS_SUCCESS) {
|
|
DEBUG(0, ("NIS+ table update failed: %s %s\n",
|
|
nisname, nis_sperrno(delresult->status)));
|
|
nis_freeresult(delresult);
|
|
return False;
|
|
}
|
|
nis_freeresult(delresult);
|
|
return True;
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to add an entry to the nisplus passwd file.
|
|
*************************************************************************/
|
|
BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
|
|
{
|
|
int local_user = 0;
|
|
char *pfile;
|
|
pstring pfiletmp;
|
|
char *nisname;
|
|
nis_result *result = NULL,
|
|
*tblresult = NULL;
|
|
nis_object new_obj;
|
|
entry_col *ecol;
|
|
int ta_maxcol;
|
|
|
|
/*
|
|
* 1. find user domain.
|
|
* a. try nis search in passwd.org_dir - if found use domain from result.
|
|
* b. try getpwnam. this may be needed if user is defined
|
|
* in /etc/passwd file (or elsewere) and not in passwd.org_dir.
|
|
* if found, use host default domain.
|
|
* c. exit with False - no such user.
|
|
*
|
|
* 2. add user
|
|
* a. find smbpasswd table
|
|
* search pfile in user domain if not found, try host default
|
|
* domain.
|
|
* b. smbpasswd domain is found, fill data and add entry.
|
|
*
|
|
* pfile should contain ONLY table name, org_dir will be concated.
|
|
* so, at first we will clear path prefix from pfile, and
|
|
* then we will use pfiletmp as playground to put together full
|
|
* nisname string.
|
|
* such approach will make it possible to specify samba private dir
|
|
* AND still use NIS+ table. as all domain related data is normally
|
|
* stored in org_dir.DOMAIN, this should be ok do do.
|
|
*/
|
|
|
|
pfile = lp_smb_passwd_file();
|
|
if( strrchr( pfile, '/') )
|
|
pfile = strrchr( pfile, '/') + 1;
|
|
|
|
/*
|
|
* Check if user is already there.
|
|
*/
|
|
safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, ".org_dir",
|
|
sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
|
|
if(pdb_get_username(newpwd) != NULL) {
|
|
nisname = make_nisname_from_name(pdb_get_username(newpwd),
|
|
pfiletmp);
|
|
} else {
|
|
return False;
|
|
}
|
|
|
|
if(!(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\
|
|
FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) {
|
|
return False;
|
|
}
|
|
if (result->status != NIS_SUCCESS &&
|
|
result->status != NIS_NOTFOUND) {
|
|
DEBUG(3, ( "nis_list failure: %s: %s\n",
|
|
nisname, nis_sperrno(result->status)));
|
|
nis_freeresult(result);
|
|
return False;
|
|
}
|
|
|
|
if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0)
|
|
{
|
|
DEBUG(3, ("User already exists in NIS+ password db: %s\n",
|
|
pfile));
|
|
nis_freeresult(result);
|
|
return False;
|
|
}
|
|
|
|
nis_freeresult(result); /* no such user, free results */
|
|
|
|
/*
|
|
* check for user in unix password database. we need this to get
|
|
* domain, where smbpasswd entry should be stored.
|
|
*/
|
|
|
|
nisname = make_nisname_from_name(pdb_get_username(newpwd),
|
|
"passwd.org_dir");
|
|
|
|
result = nisp_get_nis_list(nisname,
|
|
MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\
|
|
EXPAND_NAME|HARD_LOOKUP);
|
|
|
|
if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0)
|
|
{
|
|
struct passwd *passwd;
|
|
DEBUG(3, ("nis_list failure: %s: %s\n",
|
|
nisname, nis_sperrno(result->status)));
|
|
nis_freeresult(result);
|
|
|
|
if (!(passwd = getpwnam_alloc(pdb_get_username(newpwd)))) {
|
|
/* no such user in system! */
|
|
return False;
|
|
}
|
|
passwd_free(&passwd);
|
|
|
|
/*
|
|
* user is defined, but not in passwd.org_dir.
|
|
*/
|
|
local_user = 1;
|
|
} else {
|
|
safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, NIS_RES_OBJECT(result)->zo_domain,
|
|
sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
nis_freeresult(result); /* not needed any more */
|
|
|
|
tblresult = nisp_get_nis_list(pfiletmp,
|
|
MASTER_ONLY|FOLLOW_LINKS|\
|
|
FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP);
|
|
}
|
|
|
|
if (local_user || tblresult->status != NIS_SUCCESS)
|
|
{
|
|
/*
|
|
* no user domain or
|
|
* smbpasswd table not found in user domain, fallback to
|
|
* default domain.
|
|
*/
|
|
if (!local_user) /* free previous failed search result */
|
|
nis_freeresult(tblresult);
|
|
|
|
safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, ".org_dir",
|
|
sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
tblresult = nis_lookup(pfiletmp, MASTER_ONLY|FOLLOW_LINKS|\
|
|
FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP);
|
|
if (tblresult->status != NIS_SUCCESS)
|
|
{
|
|
/* still nothing. bail out */
|
|
nis_freeresult(tblresult);
|
|
DEBUG(3, ( "nis_lookup failure: %s\n",
|
|
nis_sperrno(tblresult->status)));
|
|
return False;
|
|
}
|
|
/* we need full name for nis_add_entry() */
|
|
safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
safe_strcat(pfiletmp, NIS_RES_OBJECT(tblresult)->zo_domain,
|
|
sizeof(pfiletmp)-strlen(pfiletmp)-1);
|
|
}
|
|
|
|
memset((char *)&new_obj, 0, sizeof (new_obj));
|
|
/* fill entry headers */
|
|
/* we do not free these. */
|
|
new_obj.zo_name = NIS_RES_OBJECT(tblresult)->zo_name;
|
|
new_obj.zo_owner = NIS_RES_OBJECT(tblresult)->zo_owner;
|
|
new_obj.zo_group = NIS_RES_OBJECT(tblresult)->zo_group;
|
|
new_obj.zo_domain = NIS_RES_OBJECT(tblresult)->zo_domain;
|
|
/* uints */
|
|
new_obj.zo_access = NIS_RES_OBJECT(tblresult)->zo_access;
|
|
new_obj.zo_ttl = NIS_RES_OBJECT(tblresult)->zo_ttl;
|
|
|
|
new_obj.zo_data.zo_type = ENTRY_OBJ;
|
|
new_obj.EN_data.en_type =
|
|
NIS_RES_OBJECT(tblresult)->TA_data.ta_type;
|
|
|
|
ta_maxcol = NIS_RES_OBJECT(tblresult)->TA_data.ta_maxcol;
|
|
|
|
if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) {
|
|
DEBUG(0, ("memory allocation failure\n"));
|
|
nis_freeresult(tblresult);
|
|
return False;
|
|
}
|
|
|
|
memset((char *)ecol, 0, ta_maxcol*sizeof (entry_col));
|
|
new_obj.EN_data.en_cols.en_cols_val = ecol;
|
|
new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
|
|
|
|
init_nisp_from_sam(&new_obj, newpwd, NULL);
|
|
|
|
DEBUG(10, ( "add NIS+ entry: %s\n", nisname));
|
|
result = nis_add_entry(pfiletmp, &new_obj, 0);
|
|
|
|
free(ecol); /* free allocated entry space */
|
|
|
|
if (result->status != NIS_SUCCESS)
|
|
{
|
|
DEBUG(3, ( "NIS+ table update failed: %s\n",
|
|
nisname, nis_sperrno(result->status)));
|
|
nis_freeresult(tblresult);
|
|
nis_freeresult(result);
|
|
return False;
|
|
}
|
|
|
|
nis_freeresult(tblresult);
|
|
nis_freeresult(result);
|
|
|
|
return True;
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to modify the nisplus passwd entry.
|
|
************************************************************************/
|
|
BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd)
|
|
{
|
|
nis_result *result, *addresult;
|
|
nis_object *obj;
|
|
nis_object new_obj;
|
|
entry_col *ecol;
|
|
int ta_maxcol;
|
|
char *pfile = lp_smb_passwd_file();
|
|
pstring nisname;
|
|
int i;
|
|
|
|
if (!*pfile)
|
|
{
|
|
DEBUG(0, ("no SMB password file set\n"));
|
|
return False;
|
|
}
|
|
if( strrchr( pfile, '/') )
|
|
pfile = strrchr( pfile, '/') + 1;
|
|
|
|
slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir",
|
|
pdb_get_username(newpwd), pfile);
|
|
|
|
DEBUG(10, ("search by name: %s\n", nisname));
|
|
|
|
/* Search the table. */
|
|
|
|
if( !(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\
|
|
FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) {
|
|
return False;
|
|
}
|
|
|
|
if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) {
|
|
/* User not found. */
|
|
DEBUG(0,("user not found in NIS+\n"));
|
|
nis_freeresult(result);
|
|
return False;
|
|
}
|
|
|
|
obj = NIS_RES_OBJECT(result);
|
|
DEBUG(6,("entry found in %s\n", obj->zo_domain));
|
|
|
|
/* we must create new stub object with EN_MODIFIED flag.
|
|
this is because obj from result is going to be freed and
|
|
we do not want to break it or cause memory leaks or corruption.
|
|
*/
|
|
|
|
memmove((char *)&new_obj, obj, sizeof (new_obj));
|
|
ta_maxcol = obj->TA_data.ta_maxcol;
|
|
|
|
if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) {
|
|
DEBUG(0, ("memory allocation failure\n"));
|
|
nis_freeresult(result);
|
|
return False;
|
|
}
|
|
|
|
memmove((char *)ecol, obj->EN_data.en_cols.en_cols_val,
|
|
ta_maxcol*sizeof (entry_col));
|
|
new_obj.EN_data.en_cols.en_cols_val = ecol;
|
|
new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
|
|
|
|
if ( init_nisp_from_sam(&new_obj, newpwd, obj) == True ) {
|
|
slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s",
|
|
pdb_get_username(newpwd), pfile, obj->zo_domain);
|
|
|
|
DEBUG(10, ("NIS+ table update: %s\n", nisname));
|
|
addresult =
|
|
nis_modify_entry(nisname, &new_obj,
|
|
MOD_SAMEOBJ | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP);
|
|
|
|
if(addresult->status != NIS_SUCCESS) {
|
|
DEBUG(0, ("NIS+ table update failed: %s %s\n",
|
|
nisname, nis_sperrno(addresult->status)));
|
|
nis_freeresult(addresult);
|
|
nis_freeresult(result);
|
|
free(ecol);
|
|
return False;
|
|
}
|
|
|
|
DEBUG(6,("password changed\n"));
|
|
nis_freeresult(addresult);
|
|
} else {
|
|
DEBUG(6,("nothing to change!\n"));
|
|
}
|
|
|
|
free(ecol);
|
|
nis_freeresult(result);
|
|
|
|
return True;
|
|
}
|
|
|
|
#else
|
|
void nisplus_dummy_function(void);
|
|
void nisplus_dummy_function(void) { } /* stop some compilers complaining */
|
|
#endif /* WITH_NISPLUSSAM */
|