summaryrefslogtreecommitdiff
path: root/source4/passdb/pdb_nisplus.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/passdb/pdb_nisplus.c')
-rw-r--r--source4/passdb/pdb_nisplus.c1565
1 files changed, 1565 insertions, 0 deletions
diff --git a/source4/passdb/pdb_nisplus.c b/source4/passdb/pdb_nisplus.c
new file mode 100644
index 0000000000..0a42c36ea0
--- /dev/null
+++ b/source4/passdb/pdb_nisplus.c
@@ -0,0 +1,1565 @@
+
+/*
+ * 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 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>
+
+/***************************************************************
+
+ 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_uid (pw_buf, atoi (ENTRY_VAL (obj, NPF_UID)), PDB_SET);
+ pdb_set_gid (pw_buf, atoi (ENTRY_VAL (obj, NPF_SMB_GRPID)), PDB_SET);
+ 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:\
+ uid = %d.\n", pdb_get_uid (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 */
+
+ /* 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) :
+ fallback_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 (pdb_getgrgid(&map, pdb_get_gid (sampass),
+ MAPPING_WITHOUT_PRIV)) {
+ if (!sid_peek_check_rid
+ (get_global_sam_sid (), &map.sid, &rid))
+ return False;
+ } 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_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;
+}
+
+#else
+NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * c, PDB_METHODS ** m,
+ const char *l)
+{
+ DEBUG (0, ("nisplus sam not compiled in!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+}
+#endif /* WITH_NISPLUS_SAM */