/* * 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); }