mirror of
https://github.com/samba-team/samba.git
synced 2025-01-29 21:47:30 +03:00
c823b191ab
We really need idmap_ldap to have a good solution with ldapsam, porting it from the prvious code is beeing made, the code is really simple to do so I am confident it is not a problem to commit this code in. Not committing it would have been worst. I really would have been able to finish also the group code, maybe we can put it into a followin release after 3.0.0 even if it may be an upgrade problem. The code has been tested and seem to work right, more testing is needed for corner cases. Currently winbind pdc (working only for users and not for groups) is disabled as I was not able to make a complete group code replacement that works somewhat in a week (I have a complete patch, but there are bugs) Simo. (This used to be commit 0e58085978f984436815114a2ec347cf7899a89d)
1520 lines
45 KiB
C
1520 lines
45 KiB
C
|
|
/*
|
|
* NIS+ Passdb Backend
|
|
* 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
|
|
* Copyright (C) Jelmer Vernooij 2002
|
|
*
|
|
* 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 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>
|
|
|
|
/***************************************************************
|
|
|
|
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
|
|
|
|
struct nisplus_private_info {
|
|
nis_result *result;
|
|
int enum_entry;
|
|
char *location;
|
|
};
|
|
|
|
static char *make_nisname_from_user_rid (uint32 rid, char *pfile);
|
|
static char *make_nisname_from_name (const char *user_name, char *pfile);
|
|
static void get_single_attribute (const nis_object * new_obj, int col,
|
|
char *val, int len);;
|
|
static BOOL make_sam_from_nisp_object (SAM_ACCOUNT * pw_buf,
|
|
const nis_object * obj);
|
|
static BOOL make_sam_from_nisresult (SAM_ACCOUNT * pw_buf,
|
|
const nis_result * result);;
|
|
static void set_single_attribute (nis_object * new_obj, int col,
|
|
const char *val, int len, int flags);
|
|
static BOOL init_nisp_from_sam (nis_object * obj, const SAM_ACCOUNT * sampass,
|
|
nis_object * old);
|
|
static nis_result *nisp_get_nis_list (const char *nisname,
|
|
unsigned int flags);
|
|
|
|
/***************************************************************
|
|
Start enumeration of the passwd list.
|
|
****************************************************************/
|
|
|
|
static NTSTATUS nisplussam_setsampwent (struct pdb_methods *methods, BOOL update)
|
|
{
|
|
struct nisplus_private_info *private =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
|
|
char *sp;
|
|
pstring pfiletmp;
|
|
|
|
if ((sp = strrchr (private->location, '/')))
|
|
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;
|
|
if (global_nisp_ent->result != NULL)
|
|
return NT_STATUS_UNSUCCESSFUL;
|
|
else
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/***************************************************************
|
|
End enumeration of the passwd list.
|
|
****************************************************************/
|
|
|
|
static void nisplussam_endsampwent (struct pdb_methods *methods)
|
|
{
|
|
struct nisplus_private_info *global_nisp_ent =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
if (global_nisp_ent->result)
|
|
nis_freeresult (global_nisp_ent->result);
|
|
global_nisp_ent->result = NULL;
|
|
global_nisp_ent->enum_entry = 0;
|
|
}
|
|
|
|
/*****************************************************************
|
|
Get one SAM_ACCOUNT from the list (next in line)
|
|
*****************************************************************/
|
|
|
|
static NTSTATUS nisplussam_getsampwent (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * user)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
struct nisplus_private_info *global_nisp_ent =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
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 nt_status;
|
|
}
|
|
|
|
if (result == NULL || enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ (result) - 1)) {
|
|
return nt_status;
|
|
}
|
|
|
|
if (!make_sam_from_nisp_object(user, &NIS_RES_OBJECT (result)[enum_entry])) {
|
|
DEBUG (0, ("Bad SAM_ACCOUNT entry returned from NIS+!\n"));
|
|
return nt_status;
|
|
}
|
|
(int) (global_nisp_ent->enum_entry)++;
|
|
|
|
return nt_status;
|
|
}
|
|
|
|
/******************************************************************
|
|
Lookup a name in the SAM database
|
|
******************************************************************/
|
|
|
|
static NTSTATUS nisplussam_getsampwnam (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * user, const char *sname)
|
|
{
|
|
/* Static buffers we will return. */
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
nis_result *result = NULL;
|
|
pstring nisname;
|
|
BOOL ret;
|
|
struct nisplus_private_info *private =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
|
|
if (!private->location || !(*private->location)) {
|
|
DEBUG (0, ("No SMB password file set\n"));
|
|
return nt_status;
|
|
}
|
|
if (strrchr (private->location, '/'))
|
|
private->location = strrchr (private->location, '/') + 1;
|
|
|
|
slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
|
|
sname, private->location);
|
|
DEBUG (10, ("search by nisname: %s\n", nisname));
|
|
|
|
/* Search the table. */
|
|
|
|
if (!(result = nisp_get_nis_list (nisname, 0))) {
|
|
return nt_status;
|
|
}
|
|
|
|
ret = make_sam_from_nisresult (user, result);
|
|
nis_freeresult (result);
|
|
|
|
if (ret) nt_status = NT_STATUS_OK;
|
|
|
|
return nt_status;
|
|
}
|
|
|
|
/***************************************************************************
|
|
Search by sid
|
|
**************************************************************************/
|
|
|
|
static NTSTATUS nisplussam_getsampwrid (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * user, uint32 rid)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
nis_result *result;
|
|
char *nisname;
|
|
BOOL ret;
|
|
char *sp;
|
|
pstring pfiletmp;
|
|
struct nisplus_private_info *private =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
|
|
if (!private->location || !(*private->location)) {
|
|
DEBUG (0, ("no SMB password file set\n"));
|
|
return nt_status;
|
|
}
|
|
|
|
if ((sp = strrchr (private->location, '/')))
|
|
safe_strcpy (pfiletmp, sp + 1, sizeof (pfiletmp) - 1);
|
|
else
|
|
safe_strcpy (pfiletmp, private->location, 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 nt_status;
|
|
}
|
|
|
|
ret = make_sam_from_nisresult (user, result);
|
|
nis_freeresult (result);
|
|
|
|
if (ret) nt_status = NT_STATUS_OK;
|
|
|
|
return nt_status;
|
|
}
|
|
|
|
static NTSTATUS nisplussam_getsampwsid (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * user, const DOM_SID * sid)
|
|
{
|
|
uint32 rid;
|
|
|
|
if (!sid_peek_check_rid (get_global_sam_sid (), sid, &rid))
|
|
return NT_STATUS_UNSUCCESSFUL;
|
|
return nisplussam_getsampwrid (methods, user, rid);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
Delete a SAM_ACCOUNT
|
|
****************************************************************************/
|
|
|
|
static NTSTATUS nisplussam_delete_sam_account (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * user)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
const char *sname;
|
|
pstring nisname;
|
|
nis_result *result, *delresult;
|
|
nis_object *obj;
|
|
struct nisplus_private_info *private =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
|
|
if (!user) {
|
|
DEBUG (0, ("no SAM_ACCOUNT specified!\n"));
|
|
return nt_status;
|
|
}
|
|
|
|
sname = pdb_get_username (user);
|
|
|
|
if (!private->location || !(*private->location)) {
|
|
DEBUG (0, ("no SMB password file set\n"));
|
|
return nt_status;
|
|
}
|
|
|
|
if (strrchr (private->location, '/'))
|
|
private->location = strrchr (private->location, '/') + 1;
|
|
|
|
slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
|
|
sname, private->location);
|
|
|
|
/* Search the table. */
|
|
|
|
if (!(result = nisp_get_nis_list (nisname,
|
|
MASTER_ONLY | FOLLOW_LINKS |
|
|
FOLLOW_PATH | EXPAND_NAME |
|
|
HARD_LOOKUP))) {
|
|
return nt_status;
|
|
}
|
|
|
|
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 nt_status;
|
|
}
|
|
|
|
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 nt_status;
|
|
}
|
|
nis_freeresult (delresult);
|
|
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/***************************************************************************
|
|
Modifies an existing SAM_ACCOUNT
|
|
****************************************************************************/
|
|
|
|
static NTSTATUS nisplussam_update_sam_account (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * newpwd)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
nis_result *result, *addresult;
|
|
nis_object *obj;
|
|
nis_object new_obj;
|
|
entry_col *ecol;
|
|
int ta_maxcol;
|
|
struct nisplus_private_info *private =
|
|
(struct nisplus_private_info *) methods->private_data;
|
|
pstring nisname;
|
|
|
|
if (!private->location || !(*private->location)) {
|
|
DEBUG (0, ("no SMB password file set\n"));
|
|
return nt_status;
|
|
}
|
|
if (strrchr (private->location, '/'))
|
|
private->location = strrchr (private->location, '/') + 1;
|
|
|
|
slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
|
|
pdb_get_username (newpwd), private->location);
|
|
|
|
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 ne_status;
|
|
}
|
|
|
|
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 nt_status;
|
|
}
|
|
|
|
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 nt_status;
|
|
}
|
|
|
|
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), private->location, 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 nt_status;
|
|
}
|
|
|
|
DEBUG (6, ("password changed\n"));
|
|
nis_freeresult (addresult);
|
|
} else {
|
|
DEBUG (6, ("nothing to change!\n"));
|
|
}
|
|
|
|
free (ecol);
|
|
nis_freeresult (result);
|
|
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/***************************************************************************
|
|
Adds an existing SAM_ACCOUNT
|
|
****************************************************************************/
|
|
|
|
static NTSTATUS nisplussam_add_sam_account (struct pdb_methods *methods,
|
|
SAM_ACCOUNT * newpwd)
|
|
{
|
|
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
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 = private->location;
|
|
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 nt_status;
|
|
}
|
|
|
|
if (!
|
|
(result =
|
|
nisp_get_nis_list (nisname,
|
|
MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
|
|
EXPAND_NAME | HARD_LOOKUP))) {
|
|
return nt_status;
|
|
}
|
|
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 nt_status;
|
|
}
|
|
|
|
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 nt_status;
|
|
}
|
|
|
|
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 nt_status;
|
|
}
|
|
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 nt_status;
|
|
}
|
|
/* 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 nt_status;
|
|
}
|
|
|
|
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,%s\n",
|
|
nisname, nis_sperrno (result->status)));
|
|
nis_freeresult (tblresult);
|
|
nis_freeresult (result);
|
|
return nt_status;
|
|
}
|
|
|
|
nis_freeresult (tblresult);
|
|
nis_freeresult (result);
|
|
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
/***************************************************************
|
|
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_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, PDB_DEFAULT);
|
|
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),
|
|
PDB_SET);
|
|
}
|
|
}
|
|
|
|
pdb_set_logoff_time (pw_buf, get_time_t_max (), PDB_DEFAULT);
|
|
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),
|
|
PDB_SET);
|
|
}
|
|
}
|
|
|
|
pdb_set_kickoff_time (pw_buf, get_time_t_max (), PDB_DEFAULT);
|
|
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),
|
|
PDB_SET);
|
|
}
|
|
}
|
|
|
|
pdb_set_pass_last_set_time (pw_buf, (time_t) 0, PDB_DEFAULT);
|
|
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);
|
|
}
|
|
}
|
|
|
|
pdb_set_pass_can_change_time (pw_buf, (time_t) 0, PDB_DEFAULT);
|
|
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),
|
|
PDB_SET);
|
|
}
|
|
}
|
|
|
|
pdb_set_pass_must_change_time (pw_buf, get_time_t_max (), PDB_DEFAULT); /* 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),
|
|
PDB_SET);
|
|
}
|
|
}
|
|
|
|
/* string values */
|
|
pdb_set_username (pw_buf, ENTRY_VAL (obj, NPF_NAME), PDB_SET);
|
|
pdb_set_domain (pw_buf, lp_workgroup (), PDB_DEFAULT);
|
|
/* 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);
|
|
|
|
pdb_set_acct_ctrl (pw_buf, pdb_decode_acct_ctrl (ENTRY_VAL (obj,
|
|
NPF_ACB), PDB_SET));
|
|
|
|
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);
|
|
|
|
pdb_set_workstations (pw_buf, ENTRY_VAL (obj, NPF_WORKSTATIONS), PDB_SET);
|
|
pdb_set_munged_dial (pw_buf, NULL, PDB_DEFAULT);
|
|
|
|
pdb_set_user_sid_from_rid (pw_buf,
|
|
atoi (ENTRY_VAL (obj, NPF_USER_RID)), PDB_SET);
|
|
pdb_set_group_sid_from_rid (pw_buf,
|
|
atoi (ENTRY_VAL (obj, NPF_GROUP_RID)), PDB_SET);
|
|
|
|
/* 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, PDB_DEFAULT);
|
|
} else
|
|
pdb_set_homedir (pw_buf, home_dir, PDB_SET);
|
|
|
|
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, PDB_DEFAULT);
|
|
} else
|
|
pdb_set_dir_drive (pw_buf, home_drive, PDB_SET);
|
|
|
|
get_single_attribute (obj, NPF_LOGON_SCRIPT, logon_script,
|
|
sizeof (pstring));
|
|
if (!(logon_script && *logon_script)) {
|
|
pstrcpy (logon_script, lp_logon_script ());
|
|
pdb_set_logon_script (pw_buf, logon_script, PDB_DEFAULT);
|
|
} else
|
|
pdb_set_logon_script (pw_buf, logon_script, PDB_SET);
|
|
|
|
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, PDB_DEFAULT);
|
|
} else
|
|
pdb_set_profile_path (pw_buf, profile_path, PDB_SET);
|
|
|
|
} else {
|
|
/* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
|
|
pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT);
|
|
}
|
|
|
|
/* Check the lanman password column. */
|
|
ptr = (char *) ENTRY_VAL (obj, NPF_LMPWD);
|
|
if (!pdb_set_lanman_passwd (pw_buf, NULL, PDB_DEFAULT))
|
|
return False;
|
|
|
|
if (!strncasecmp (ptr, "NO PASSWORD", 11)) {
|
|
pdb_set_acct_ctrl (pw_buf,
|
|
pdb_get_acct_ctrl (pw_buf) | ACB_PWNOTREQ, PDB_SET);
|
|
} 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, PDB_SET))
|
|
return False;
|
|
}
|
|
|
|
/* Check the NT password column. */
|
|
ptr = ENTRY_VAL (obj, NPF_NTPWD);
|
|
if (!pdb_set_nt_passwd (pw_buf, NULL, PDB_DEFAULT))
|
|
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:\ %s.\n",
|
|
pdb_get_username (pw_buf)));
|
|
return False;
|
|
}
|
|
if (!pdb_set_nt_passwd (pw_buf, smbntpwd, PDB_SET))
|
|
return False;
|
|
}
|
|
|
|
pdb_set_unknown_3 (pw_buf, 0xffffff, PDB_DEFAULT); /* don't know */
|
|
pdb_set_logon_divs (pw_buf, 168, PDB_DEFAULT); /* 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);
|
|
pdb_set_hours (pw_buf, hours, PDB_SET);
|
|
|
|
pdb_set_unknown_5 (pw_buf, 0x00020000, PDB_DEFAULT); /* don't know */
|
|
pdb_set_unknown_6 (pw_buf, 0x000004ec, PDB_DEFAULT); /* 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 */
|
|
|
|
uint32 u_rid;
|
|
uint32 g_rid;
|
|
/* 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 */
|
|
|
|
if (!(u_rid = pdb_get_user_rid (sampass)))
|
|
return False;
|
|
if (!(g_rid = pdb_get_group_rid (sampass)))
|
|
return False;
|
|
|
|
slprintf (uid, sizeof (uid) - 1, "%u", fallback_pdb_user_rid_to_uid (u_rid));
|
|
slprintf (user_rid, sizeof (user_rid) - 1, "%u", u_rid);
|
|
slprintf (gid, sizeof (gid) - 1, "%u", fallback_pdb_group_rid_to_uid (g_rid));
|
|
slprintf (group_rid, sizeof (group_rid) - 1, "%u", g_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 (!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 (!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 (!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 (!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_dir_drive (sampass) &&
|
|
!ENTRY_VAL (old, NPF_DIR_DRIVE)) ||
|
|
(ENTRY_VAL (old, NPF_DIR_DRIVE) &&
|
|
!pdb_get_dir_drive (sampass)) ||
|
|
(ENTRY_VAL (old, NPF_DIR_DRIVE) &&
|
|
pdb_get_dir_drive (sampass) &&
|
|
strcmp (ENTRY_VAL (old, NPF_DIR_DRIVE),
|
|
pdb_get_dir_drive (sampass)))) {
|
|
need_to_modify = True;
|
|
set_single_attribute (obj, NPF_DIR_DRIVE,
|
|
pdb_get_dir_drive (sampass),
|
|
strlen (pdb_get_dir_drive
|
|
(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_dir_drive (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 *nisname, 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 (nisname, flags, NULL, NULL);
|
|
|
|
alarm (0);
|
|
CatchSignal (SIGALRM, SIGNAL_CAST SIG_DFL);
|
|
|
|
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;
|
|
}
|
|
|
|
static void free_private_data(void **vp)
|
|
{
|
|
struct nisplus_private_info **private = (struct nisplus_private_info **)vp;
|
|
|
|
if ((*private)->result) {
|
|
nis_freeresult ((*private)->result);
|
|
}
|
|
|
|
free(*private);
|
|
|
|
/* No need to free any further, as it is talloc()ed */
|
|
}
|
|
|
|
NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * pdb_context,
|
|
PDB_METHODS ** pdb_method, const char *location)
|
|
{
|
|
NTSTATUS nt_status;
|
|
struct nisplus_private_info *private = malloc (sizeof (struct nisplus_private_info));
|
|
|
|
ZERO_STRUCT(private);
|
|
p->location = talloc_strdup(pdb_context->mem_ctx, location);
|
|
|
|
if (!NT_STATUS_IS_OK
|
|
(nt_status =
|
|
make_pdb_methods (pdb_context->mem_ctx, pdb_method))) {
|
|
return nt_status;
|
|
}
|
|
|
|
(*pdb_method)->name = "nisplussam";
|
|
|
|
/* Functions your pdb module doesn't provide should be set
|
|
* to NULL */
|
|
|
|
(*pdb_method)->setsampwent = nisplussam_setsampwent;
|
|
(*pdb_method)->endsampwent = nisplussam_endsampwent;
|
|
(*pdb_method)->getsampwent = nisplussam_getsampwent;
|
|
(*pdb_method)->getsampwnam = nisplussam_getsampwnam;
|
|
(*pdb_method)->getsampwsid = nisplussam_getsampwsid;
|
|
(*pdb_method)->add_sam_account = nisplussam_add_sam_account;
|
|
(*pdb_method)->update_sam_account = nisplussam_update_sam_account;
|
|
(*pdb_method)->delete_sam_account = nisplussam_delete_sam_account;
|
|
(*pdb_method)->free_private_data = free_private_data;
|
|
(*pdb_method)->private_data = private;
|
|
|
|
return NT_STATUS_OK;
|
|
}
|
|
|
|
NTSTATUS pdb_nisplus_init(void)
|
|
{
|
|
return smb_register_passdb(PASSDB_INTERFACE_VERSION, "nisplussam", pdb_init_nisplussam);
|
|
}
|