From 2e01bef42db414b61e696829603c5e1c8a36aac5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 20 Aug 2002 20:56:10 +0000 Subject: pdb_nisplus converted to the new passdb system API's (This used to be commit 72e9a5cd340d6a912e274dc0d6f2a22a922d4b03) --- source3/passdb/pdb_interface.c | 1 + source3/passdb/pdb_nisplus.c | 2326 ++++++++++++++++++++-------------------- 2 files changed, 1177 insertions(+), 1150 deletions(-) (limited to 'source3/passdb') diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index f311223d77..f5926e54f1 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -34,6 +34,7 @@ const struct pdb_init_function_entry builtin_pdb_init_functions[] = { { "ldapsam", pdb_init_ldapsam }, { "ldapsam_nua", pdb_init_ldapsam_nua }, { "unixsam", pdb_init_unixsam }, + { "nisplussam", pdb_init_nisplussam }, { "plugin", pdb_init_plugin }, { NULL, NULL} }; diff --git a/source3/passdb/pdb_nisplus.c b/source3/passdb/pdb_nisplus.c index 2d37c3b8fb..c302691bec 100644 --- a/source3/passdb/pdb_nisplus.c +++ b/source3/passdb/pdb_nisplus.c @@ -1,10 +1,10 @@ /* - * Unix SMB/CIFS implementation. - * SMB parameters and setup + * Test password backend for samba * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. * Copyright (C) Benny Holmgren 1998 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998. * Copyright (C) Toomas Soome 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 @@ -35,6 +35,7 @@ * an enum in /usr/include/rpcsvc/nis.h. */ + #if defined(GROUP) #undef GROUP #endif @@ -47,17 +48,6 @@ #include -extern int DEBUGLEVEL; - -struct nisp_enum_info -{ - nis_result *result; - int enum_entry; -}; - -static struct nisp_enum_info global_nisp_ent; -static SIG_ATOMIC_T gotalarm; - /*************************************************************** the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are: @@ -114,1325 +104,1361 @@ static SIG_ATOMIC_T gotalarm; #define NPF_WORKSTATIONS 20 #define NPF_HOURS 21 +struct nisp_enum_info +{ + nis_result *result; + int enum_entry; +}; -/******************************************************************* - Converts NT user RID to a UNIX uid. - ********************************************************************/ +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 uid_t pdb_user_rid_to_uid(uint32 user_rid) +static BOOL nisplussam_setsampwent(struct pdb_methods *methods, BOOL update) { - return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER); -} + struct nisp_enum_info *global_nisp_ent = (struct nisp_enum_info *)methods->private_data; -/******************************************************************* - converts UNIX uid to an NT User RID. - ********************************************************************/ + char *sp, * p = lp_smb_passwd_file(); + pstring pfiletmp; -static uint32 pdb_uid_to_user_rid(uid_t uid) -{ - return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); + if( (sp = strrchr( p, '/' )) ) + safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); + else + safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); + + pdb_endsampwent(); /* just in case */ + global_nisp_ent->result = nisp_get_nis_list( pfiletmp, 0 ); + global_nisp_ent->enum_entry = 0; + return global_nisp_ent->result != NULL ? True : False; } /*************************************************************** - Signal function to tell us we timed out. + End enumeration of the passwd list. ****************************************************************/ -static void gotalarm_sig(void) + +static void nisplussam_endsampwent(struct pdb_methods *methods) { - gotalarm = 1; + struct nisp_enum_info *global_nisp_ent = (struct nisp_enum_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; } -/*************************************************************** - make_nisname_from_user_rid - ****************************************************************/ -static char *make_nisname_from_user_rid(uint32 rid, char *pfile) +/***************************************************************** + Get one SAM_ACCOUNT from the list (next in line) +*****************************************************************/ + +static BOOL nisplussam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *user) { - 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); + struct nisp_enum_info *global_nisp_ent = (struct nisp_enum_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 False; + } - return nisname; + if (result == NULL || + enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ(result) - 1)) + { + return False; + } + + if(!make_sam_from_nisp_object(user, &NIS_RES_OBJECT(result)[enum_entry]) ) + { + DEBUG(0,("Bad SAM_ACCOUNT entry returned from NIS+!\n")); + return False; + } + (int)(global_nisp_ent->enum_entry)++; + return True; + DEBUG(10, ("nisplussam_getsampwent called\n")); + return False; } -/*************************************************************** - make_nisname_from_uid - ****************************************************************/ -static char *make_nisname_from_uid(int uid, char *pfile) +/****************************************************************** + Lookup a name in the SAM database +******************************************************************/ + +static BOOL nisplussam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname) { - static pstring nisname; + /* Static buffers we will return. */ + nis_result *result = NULL; + pstring nisname; + BOOL ret; + char *pfile = lp_smb_passwd_file(); - safe_strcpy(nisname, "[uid=", sizeof(nisname)-1); - slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, uid); - safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1); - safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1); + if (!*pfile) + { + DEBUG(0, ("No SMB password file set\n")); + return False; + } + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; - return nisname; -} + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile); + DEBUG(10, ("search by nisname: %s\n", nisname)); -/*************************************************************** - make_nisname_from_name - ****************************************************************/ -static char *make_nisname_from_name(const char *user_name, char *pfile) -{ - static pstring nisname; + /* Search the table. */ - 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); + if(!(result = nisp_get_nis_list(nisname, 0))) + { + return False; + } - return nisname; + ret = make_sam_from_nisresult(user, result); + nis_freeresult(result); + + return ret; + + DEBUG(10, ("nisplussam_getsampwnam called\n")); + return False; } -/************************************************************************* - gets a NIS+ attribute - *************************************************************************/ -static void get_single_attribute(const nis_object *new_obj, int col, - char *val, int len) +/*************************************************************************** + Search by sid + **************************************************************************/ + +static BOOL nisplussam_getsampwrid (struct pdb_methods *methods, SAM_ACCOUNT *user, uint32 rid) { - int entry_len; + nis_result *result; + char *nisname; + BOOL ret; + char *sp, *p = lp_smb_passwd_file(); + pstring pfiletmp; - if (new_obj == NULL || val == NULL) return; - - entry_len = ENTRY_LEN(new_obj, col); - if (len > entry_len) + if (!*p) { - len = entry_len; + DEBUG(0, ("no SMB password file set\n")); + return False; } - safe_strcpy(val, ENTRY_VAL(new_obj, col), len-1); + if( (sp = strrchr( p, '/' )) ) + safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); + else + safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); + + nisname = make_nisname_from_user_rid(rid, pfiletmp); + + DEBUG(10, ("search by rid: %s\n", nisname)); + + /* Search the table. */ + + if(!(result = nisp_get_nis_list(nisname, 0))) + { + return False; + } + + ret = make_sam_from_nisresult(user, result); + nis_freeresult(result); + + return ret; + + DEBUG(10, ("nisplussam_getsampwsid called\n")); + return False; } -/************************************************************************ - makes a struct sam_passwd from a NIS+ object. - ************************************************************************/ -static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, const nis_object *obj) +static BOOL nisplussam_getsampwsid (struct pdb_methods *methods, SAM_ACCOUNT *user, const DOM_SID *sid) { - 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]; - + uint32 rid; + if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) return False; + return nisplussam_getsampwrid(methods, user, rid); +} - /* - * time values. note: this code assumes 32bit time_t! - */ - /* Don't change these timestamp settings without a good reason. They are - important for NT member server compatibility. */ - pdb_set_logon_time(pw_buf, (time_t)0, True); - ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGON_T); - if(ptr && *ptr && (StrnCaseCmp(ptr, "LNT-", 4)==0)) { - int i; - ptr += 4; - for(i = 0; i < 8; i++) { - if(ptr[i] == '\0' || !isxdigit(ptr[i])) - break; - } - if(i == 8) { - pdb_set_logon_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); - } - } +/*************************************************************************** + Delete a SAM_ACCOUNT +****************************************************************************/ - pdb_set_logoff_time(pw_buf, get_time_t_max(), True); - ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGOFF_T); - if(ptr && *ptr && (StrnCaseCmp(ptr, "LOT-", 4)==0)) { - int i; - ptr += 4; - for(i = 0; i < 8; i++) { - if(ptr[i] == '\0' || !isxdigit(ptr[i])) - break; - } - if(i == 8) { - pdb_set_logoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); - } - } +static BOOL nisplussam_delete_sam_account(struct pdb_methods *methods, SAM_ACCOUNT *user) +{ - pdb_set_kickoff_time(pw_buf, get_time_t_max(), True); - ptr = (uchar *)ENTRY_VAL(obj, NPF_KICK_T); - if(ptr && *ptr && (StrnCaseCmp(ptr, "KOT-", 4)==0)) { - int i; - ptr += 4; - for(i = 0; i < 8; i++) { - if(ptr[i] == '\0' || !isxdigit(ptr[i])) - break; - } - if(i == 8) { - pdb_set_kickoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); - } + const char *sname; + char *pfile = lp_smb_passwd_file(); + pstring nisname; + nis_result *result, *delresult; + nis_object *obj; + + if (!user) { + DEBUG(0, ("no SAM_ACCOUNT specified!\n")); + return False; } - pdb_set_pass_last_set_time(pw_buf, (time_t)0); - ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDLSET_T); - if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) { - int i; - ptr += 4; - for(i = 0; i < 8; i++) { - if(ptr[i] == '\0' || !isxdigit(ptr[i])) - break; - } - if(i == 8) { - pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); + sname = pdb_get_username(user); + + if (!*pfile) + { + DEBUG(0, ("no SMB password file set\n")); + return False; } + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; + + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile); + + /* Search the table. */ + + if( !(result = nisp_get_nis_list(nisname, + MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\ + EXPAND_NAME|HARD_LOOKUP))) { + return False; } - pdb_set_pass_can_change_time(pw_buf, (time_t)0, True); - ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDCCHG_T); - if(ptr && *ptr && (StrnCaseCmp(ptr, "CCT-", 4)==0)) { - int i; - ptr += 4; - for(i = 0; i < 8; i++) { - if(ptr[i] == '\0' || !isxdigit(ptr[i])) - break; - } - if(i == 8) { - pdb_set_pass_can_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); - } - } - - pdb_set_pass_must_change_time(pw_buf, get_time_t_max(), True); /* Password never expires. */ - ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDMCHG_T); - if(ptr && *ptr && (StrnCaseCmp(ptr, "MCT-", 4)==0)) { - int i; - ptr += 4; - for(i = 0; i < 8; i++) { - if(ptr[i] == '\0' || !isxdigit(ptr[i])) - break; - } - if(i == 8) { - pdb_set_pass_must_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); - } + if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { + /* User not found. */ + DEBUG(0,("user not found in NIS+\n")); + nis_freeresult(result); + return False; } - /* string values */ - pdb_set_username(pw_buf, ENTRY_VAL(obj, NPF_NAME)); - pdb_set_domain(pw_buf, lp_workgroup()); - /* pdb_set_nt_username() -- cant set it here... */ - - get_single_attribute(obj, NPF_FULL_NAME, full_name, sizeof(pstring)); -#if 0 - unix_to_dos(full_name, True); -#endif - pdb_set_fullname(pw_buf, full_name); - - pdb_set_acct_ctrl(pw_buf, pdb_decode_acct_ctrl(ENTRY_VAL(obj, - NPF_ACB))); - - get_single_attribute(obj, NPF_ACCT_DESC, acct_desc, sizeof(pstring)); -#if 0 - unix_to_dos(acct_desc, True); -#endif - pdb_set_acct_desc(pw_buf, acct_desc); + obj = NIS_RES_OBJECT(result); + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", sname, obj->zo_name, + obj->zo_domain); - pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS)); - pdb_set_munged_dial(pw_buf, NULL); + 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); - pdb_set_uid(pw_buf, atoi(ENTRY_VAL(obj, NPF_UID))); - pdb_set_gid(pw_buf, atoi(ENTRY_VAL(obj, NPF_SMB_GRPID))); - pdb_set_user_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID))); - pdb_set_group_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID))); + if(delresult->status != NIS_SUCCESS) { + DEBUG(0, ("NIS+ table update failed: %s %s\n", + nisname, nis_sperrno(delresult->status))); + nis_freeresult(delresult); + return False; + } + nis_freeresult(delresult); + return True; + DEBUG(10, ("nisplussam_delete_sam_account called\n")); + return False; +} - /* values, must exist for user */ - if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) { - - get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring)); - if( !(home_dir && *home_dir) ) { - pstrcpy(home_dir, lp_logon_home()); - pdb_set_homedir(pw_buf, home_dir, False); - } - else - pdb_set_homedir(pw_buf, home_dir, True); +/*************************************************************************** + Modifies an existing SAM_ACCOUNT +****************************************************************************/ - get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring)); - if( !(home_drive && *home_drive) ) { - pstrcpy(home_drive, lp_logon_drive()); - pdb_set_dir_drive(pw_buf, home_drive, False); - } - else - pdb_set_dir_drive(pw_buf, home_drive, True); +static BOOL nisplussam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd) +{ + nis_result *result, *addresult; + nis_object *obj; + nis_object new_obj; + entry_col *ecol; + int ta_maxcol; + char *pfile = lp_smb_passwd_file(); + pstring nisname; - get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script, - sizeof(pstring)); - if( !(logon_script && *logon_script) ) { - pstrcpy(logon_script, lp_logon_script()); + if (!*pfile) + { + DEBUG(0, ("no SMB password file set\n")); + return False; } - else - pdb_set_logon_script(pw_buf, logon_script, True); + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; + + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", + pdb_get_username(newpwd), pfile); + + DEBUG(10, ("search by name: %s\n", nisname)); + + /* Search the table. */ + + if( !(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) { + return False; + } + + if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { + /* User not found. */ + DEBUG(0,("user not found in NIS+\n")); + nis_freeresult(result); + return False; + } - get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring)); - if( !(profile_path && *profile_path) ) { - pstrcpy(profile_path, lp_logon_path()); - pdb_set_profile_path(pw_buf, profile_path, False); - } - else - pdb_set_profile_path(pw_buf, profile_path, True); + obj = NIS_RES_OBJECT(result); + DEBUG(6,("entry found in %s\n", obj->zo_domain)); - } - else - { - /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ - pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS); + /* we must create new stub object with EN_MODIFIED flag. + this is because obj from result is going to be freed and + we do not want to break it or cause memory leaks or corruption. + */ + + memmove((char *)&new_obj, obj, sizeof (new_obj)); + ta_maxcol = obj->TA_data.ta_maxcol; + + if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) { + DEBUG(0, ("memory allocation failure\n")); + nis_freeresult(result); + return False; } - /* Check the lanman password column. */ - ptr = (char *)ENTRY_VAL(obj, NPF_LMPWD); - if (!pdb_set_lanman_passwd(pw_buf, NULL)) - return False; + memmove((char *)ecol, obj->EN_data.en_cols.en_cols_val, + ta_maxcol*sizeof (entry_col)); + new_obj.EN_data.en_cols.en_cols_val = ecol; + new_obj.EN_data.en_cols.en_cols_len = ta_maxcol; - if (!strncasecmp(ptr, "NO PASSWORD", 11)) { - pdb_set_acct_ctrl(pw_buf, pdb_get_acct_ctrl(pw_buf) | ACB_PWNOTREQ); - } else { - if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbpwd)) { - DEBUG(0, ("malformed LM pwd entry: %s.\n", - pdb_get_username(pw_buf))); - return False; - } - if (!pdb_set_lanman_passwd(pw_buf, smbpwd)) - return False; - } - - /* Check the NT password column. */ - ptr = ENTRY_VAL(obj, NPF_NTPWD); - if (!pdb_set_nt_passwd(pw_buf, NULL)) - return False; + if ( init_nisp_from_sam(&new_obj, newpwd, obj) == True ) { + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", + pdb_get_username(newpwd), pfile, obj->zo_domain); + + DEBUG(10, ("NIS+ table update: %s\n", nisname)); + addresult = + nis_modify_entry(nisname, &new_obj, + MOD_SAMEOBJ | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP); - if (!(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))); + if(addresult->status != NIS_SUCCESS) { + DEBUG(0, ("NIS+ table update failed: %s %s\n", + nisname, nis_sperrno(addresult->status))); + nis_freeresult(addresult); + nis_freeresult(result); + free(ecol); return False; } - if (!pdb_set_nt_passwd(pw_buf, smbntpwd)) - return False; - } - - pdb_set_unknown_3(pw_buf, 0xffffff); /* don't know */ - pdb_set_logon_divs(pw_buf, 168); /* hours per week */ - - if( (hours_len = ENTRY_LEN(obj, NPF_HOURS)) == 21 ) { - memcpy(hours, ENTRY_VAL(obj, NPF_HOURS), hours_len); + + DEBUG(6,("password changed\n")); + nis_freeresult(addresult); } else { - hours_len = 21; /* 21 times 8 bits = 168 */ - /* available at all hours */ - memset(hours, 0xff, hours_len); + DEBUG(6,("nothing to change!\n")); } - pdb_set_hours_len(pw_buf, hours_len); - pdb_set_hours(pw_buf, hours); - - pdb_set_unknown_5(pw_buf, 0x00020000); /* don't know */ - pdb_set_unknown_6(pw_buf, 0x000004ec); /* don't know */ + free(ecol); + nis_freeresult(result); + 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]); + DEBUG(10, ("nisplussam_update_sam_account called\n")); + return False; } -/************************************************************************* - 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; - } -} +/*************************************************************************** + Adds an existing SAM_ACCOUNT +****************************************************************************/ -/*************************************************************** - 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) +static BOOL nisplussam_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd) { + int local_user = 0; + char *pfile; + pstring pfiletmp; + char *nisname; + nis_result *result = NULL, + *tblresult = NULL; + nis_object new_obj; + entry_col *ecol; + int ta_maxcol; + /* - * 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(). + * 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. * - * 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 + * 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. */ - BOOL need_to_modify = False; - const char *name = pdb_get_username(sampass); /* from SAM */ - /* these must be static or allocate and free entry columns! */ - static fstring uid; /* from SAM */ - static fstring user_rid; /* from SAM */ - static fstring gid; /* from SAM */ - static fstring group_rid; /* from SAM */ - char *acb; /* from SAM */ - static fstring smb_passwd; /* from SAM */ - static fstring smb_nt_passwd; /* from SAM */ - static fstring logon_t; /* from SAM */ - static fstring logoff_t; /* from SAM */ - static fstring kickoff_t; /* from SAM */ - static fstring pwdlset_t; /* from SAM */ - static fstring pwdlchg_t; /* from SAM */ - static fstring pwdmchg_t; /* from SAM */ - static fstring full_name; /* from SAM */ - static fstring acct_desc; /* from SAM */ - static char empty[1]; /* just an empty string */ - slprintf(uid, sizeof(uid)-1, "%u", pdb_get_uid(sampass)); - slprintf(user_rid, sizeof(user_rid)-1, "%u", - pdb_get_user_rid(sampass)? pdb_get_user_rid(sampass): - pdb_uid_to_user_rid(pdb_get_uid(sampass))); - slprintf(gid, sizeof(gid)-1, "%u", pdb_get_gid(sampass)); + pfile = lp_smb_passwd_file(); + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; - { - uint32 rid; - GROUP_MAP map; - - rid=pdb_get_group_rid(sampass); + /* + * Check if user is already there. + */ + safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", + sizeof(pfiletmp)-strlen(pfiletmp)-1); - if (rid==0) { - if (get_group_map_from_gid(pdb_get_gid(sampass), &map, 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)); - } + if(pdb_get_username(newpwd) != NULL) { + nisname = make_nisname_from_name(pdb_get_username(newpwd), + pfiletmp); + } else { + return False; + } - 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(!(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) { + return False; + } + if (result->status != NIS_SUCCESS && + result->status != NIS_NOTFOUND) { + DEBUG(3, ( "nis_list failure: %s: %s\n", + nisname, nis_sperrno(result->status))); + nis_freeresult(result); + return False; + } -#if 0 + if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0) + { + DEBUG(3, ("User already exists in NIS+ password db: %s\n", + pfile)); + nis_freeresult(result); + return False; + } - /* Not sure what to do with these guys. -tpot */ + nis_freeresult(result); /* no such user, free results */ - dos_to_unix(full_name, True); - dos_to_unix(acct_desc, True); + /* + * check for user in unix password database. we need this to get + * domain, where smbpasswd entry should be stored. + */ -#endif + 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( 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); + if (!(passwd = getpwnam_alloc(pdb_get_username(newpwd)))) { + /* no such user in system! */ + return False; } + passwd_free(&passwd); + + /* + * user is defined, but not in passwd.org_dir. + */ + local_user = 1; + } else { + safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1); + safe_strcat(pfiletmp, NIS_RES_OBJECT(result)->zo_domain, + sizeof(pfiletmp)-strlen(pfiletmp)-1); + nis_freeresult(result); /* not needed any more */ + tblresult = nisp_get_nis_list(pfiletmp, + MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); + } - /* uid */ - if(pdb_get_uid(sampass) != -1) { - if(!ENTRY_VAL(old, NPF_UID) || strcmp(ENTRY_VAL(old, NPF_UID), uid)) + 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) { - need_to_modify = True; - set_single_attribute(obj, NPF_UID, uid, - strlen(uid), EN_MODIFIED); + /* still nothing. bail out */ + nis_freeresult(tblresult); + DEBUG(3, ( "nis_lookup failure: %s\n", + nis_sperrno(tblresult->status))); + return False; } - } - - /* 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); - } + /* 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); } - /* 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); - } - } + 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; - /* 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); - } + new_obj.zo_data.zo_type = ENTRY_OBJ; + new_obj.EN_data.en_type = + NIS_RES_OBJECT(tblresult)->TA_data.ta_type; - /* 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); - } + ta_maxcol = NIS_RES_OBJECT(tblresult)->TA_data.ta_maxcol; + + if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) { + DEBUG(0, ("memory allocation failure\n")); + nis_freeresult(tblresult); + return False; + } + + memset((char *)ecol, 0, ta_maxcol*sizeof (entry_col)); + new_obj.EN_data.en_cols.en_cols_val = ecol; + new_obj.EN_data.en_cols.en_cols_len = ta_maxcol; + + init_nisp_from_sam(&new_obj, newpwd, NULL); + + DEBUG(10, ( "add NIS+ entry: %s\n", nisname)); + result = nis_add_entry(pfiletmp, &new_obj, 0); - /* 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); + 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 False; } + + nis_freeresult(tblresult); + nis_freeresult(result); + + return True; - /* 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); - } + DEBUG(10, ("nisplussam_add_sam_account called\n")); + return False; +} - /* 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); +NTSTATUS pdb_init_nisplussam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + NTSTATUS nt_status; + + 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)->private_data = malloc(sizeof(struct nisp_enum_info)); + + return NT_STATUS_OK; +} + + +/******************************************************************* + converts UNIX uid to an NT User RID. + ********************************************************************/ + +static uint32 pdb_uid_to_user_rid(uid_t uid) +{ + return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE); +} + +/*************************************************************** + 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, True); + ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGON_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "LNT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; } - - /* 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); + if(i == 8) { + pdb_set_logon_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); } + } - /* 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); + pdb_set_logoff_time(pw_buf, get_time_t_max(), True); + ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGOFF_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "LOT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; + } + if(i == 8) { + pdb_set_logoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); } + } - /* 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); + pdb_set_kickoff_time(pw_buf, get_time_t_max(), True); + ptr = (uchar *)ENTRY_VAL(obj, NPF_KICK_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "KOT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; } - - /* 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); + if(i == 8) { + pdb_set_kickoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); } - - /* 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); + } + + pdb_set_pass_last_set_time(pw_buf, (time_t)0); + ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDLSET_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; } - - /* 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); + if(i == 8) { + pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); } - - /* 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); + } + + pdb_set_pass_can_change_time(pw_buf, (time_t)0, True); + ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDCCHG_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "CCT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; } - - /* 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); + if(i == 8) { + pdb_set_pass_can_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); } - - /* 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); + } + + pdb_set_pass_must_change_time(pw_buf, get_time_t_max(), True); /* Password never expires. */ + ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDMCHG_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "MCT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; } - - /* 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); + if(i == 8) { + pdb_set_pass_must_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True); } - - /* 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 */ + /* string values */ + pdb_set_username(pw_buf, ENTRY_VAL(obj, NPF_NAME)); + pdb_set_domain(pw_buf, lp_workgroup()); + /* pdb_set_nt_username() -- cant set it here... */ - 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); + 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); - if(!(homedir = pdb_get_homedir(sampass))) - homedir = empty; + pdb_set_acct_ctrl(pw_buf, pdb_decode_acct_ctrl(ENTRY_VAL(obj, + NPF_ACB))); - 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; + 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); - 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; -} + pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS)); + pdb_set_munged_dial(pw_buf, NULL); -/*************************************************************** - calls nis_list, returns results. - ****************************************************************/ -static nis_result *nisp_get_nis_list(const char *nis_name, unsigned int flags) -{ - nis_result *result; - int i; + pdb_set_uid(pw_buf, atoi(ENTRY_VAL(obj, NPF_UID))); + pdb_set_gid(pw_buf, atoi(ENTRY_VAL(obj, NPF_SMB_GRPID))); + pdb_set_user_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID))); + pdb_set_group_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID))); - if( ! flags) - flags = FOLLOW_LINKS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP; + /* values, must exist for user */ + if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) { + + get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring)); + if( !(home_dir && *home_dir) ) { + pstrcpy(home_dir, lp_logon_home()); + pdb_set_homedir(pw_buf, home_dir, False); + } + else + pdb_set_homedir(pw_buf, home_dir, True); - for(i = 0; i<2;i++ ) { - alarm(60); /* hopefully ok for long searches */ - result = nis_list(nis_name, flags,NULL,NULL); + get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring)); + if( !(home_drive && *home_drive) ) { + pstrcpy(home_drive, lp_logon_drive()); + pdb_set_dir_drive(pw_buf, home_drive, False); + } + else + pdb_set_dir_drive(pw_buf, home_drive, True); - alarm(0); - CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL); + get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script, + sizeof(pstring)); + if( !(logon_script && *logon_script) ) { + pstrcpy(logon_script, lp_logon_script()); + } + else + pdb_set_logon_script(pw_buf, logon_script, True); - if (gotalarm) - { - DEBUG(0,("NIS+ lookup time out\n")); - nis_freeresult(result); - return NULL; - } - if( !(flags & MASTER_ONLY) && NIS_RES_NUMOBJ(result) <= 0 ) { - /* nis replicas are not in sync perhaps? - * this can happen, if account was just added. - */ - DEBUG(10,("will try master only\n")); - nis_freeresult(result); - flags |= MASTER_ONLY; - } else - break; - } - return result; -} - -/*************************************************************** - Start to enumerate the nisplus passwd list. - ****************************************************************/ -BOOL pdb_setsampwent(BOOL update) -{ - char *sp, * p = lp_smb_passwd_file(); - pstring pfiletmp; - - if( (sp = strrchr( p, '/' )) ) - safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); - else - safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); - safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); + get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring)); + if( !(profile_path && *profile_path) ) { + pstrcpy(profile_path, lp_logon_path()); + pdb_set_profile_path(pw_buf, profile_path, False); + } + else + pdb_set_profile_path(pw_buf, profile_path, True); - pdb_endsampwent(); /* just in case */ - global_nisp_ent.result = nisp_get_nis_list( pfiletmp, 0 ); - global_nisp_ent.enum_entry = 0; - return global_nisp_ent.result != NULL ? True : False; -} + } + else + { + /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ + pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS); + } -/*************************************************************** - End enumeration of the nisplus passwd list. -****************************************************************/ -void pdb_endsampwent(void) -{ - if( global_nisp_ent.result ) - nis_freeresult(global_nisp_ent.result); - global_nisp_ent.result = NULL; - global_nisp_ent.enum_entry = 0; -} + /* Check the lanman password column. */ + ptr = (char *)ENTRY_VAL(obj, NPF_LMPWD); + if (!pdb_set_lanman_passwd(pw_buf, NULL)) + return False; -/************************************************************************* - Routine to return the next entry in the nisplus passwd list. - *************************************************************************/ -BOOL pdb_getsampwent(SAM_ACCOUNT *user) -{ - int enum_entry = (int)(global_nisp_ent.enum_entry); - nis_result *result = global_nisp_ent.result; + if (!strncasecmp(ptr, "NO PASSWORD", 11)) { + pdb_set_acct_ctrl(pw_buf, pdb_get_acct_ctrl(pw_buf) | ACB_PWNOTREQ); + } else { + if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbpwd)) { + DEBUG(0, ("malformed LM pwd entry: %s.\n", + pdb_get_username(pw_buf))); + return False; + } + if (!pdb_set_lanman_passwd(pw_buf, smbpwd)) + return False; + } - if (user==NULL) { - DEBUG(0,("SAM_ACCOUNT is NULL.\n")); + /* Check the NT password column. */ + ptr = ENTRY_VAL(obj, NPF_NTPWD); + if (!pdb_set_nt_passwd(pw_buf, NULL)) return False; + + if (!(pdb_get_acct_ctrl(pw_buf) & ACB_PWNOTREQ) && + strncasecmp(ptr, "NO PASSWORD", 11)) { + if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbntpwd)) { + DEBUG(0, ("malformed NT pwd entry:\ + uid = %d.\n", + pdb_get_uid(pw_buf))); + return False; + } + if (!pdb_set_nt_passwd(pw_buf, smbntpwd)) + return False; + } + + pdb_set_unknown_3(pw_buf, 0xffffff); /* don't know */ + pdb_set_logon_divs(pw_buf, 168); /* hours per week */ + + if( (hours_len = ENTRY_LEN(obj, NPF_HOURS)) == 21 ) { + memcpy(hours, ENTRY_VAL(obj, NPF_HOURS), hours_len); + } else { + hours_len = 21; /* 21 times 8 bits = 168 */ + /* available at all hours */ + memset(hours, 0xff, hours_len); } + pdb_set_hours_len(pw_buf, hours_len); + pdb_set_hours(pw_buf, hours); - if (result == NULL || - enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ(result) - 1)) - { - return False; - } + pdb_set_unknown_5(pw_buf, 0x00020000); /* don't know */ + pdb_set_unknown_6(pw_buf, 0x000004ec); /* don't know */ - if(!make_sam_from_nisp_object(user, &NIS_RES_OBJECT(result)[enum_entry]) ) - { - DEBUG(0,("Bad SAM_ACCOUNT entry returned from NIS+!\n")); - return False; - } - (int)(global_nisp_ent.enum_entry)++; return True; } -/************************************************************************* - Routine to search the nisplus passwd file for an entry matching the username - *************************************************************************/ -BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname) +/************************************************************************ + makes a struct sam_passwd from a NIS+ result. + ************************************************************************/ +static BOOL make_sam_from_nisresult(SAM_ACCOUNT *pw_buf, const nis_result *result) { - /* Static buffers we will return. */ - nis_result *result = NULL; - pstring nisname; - BOOL ret; - char *pfile = lp_smb_passwd_file(); - int i; + if (pw_buf == NULL || result == NULL) return False; - if (!*pfile) + if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) { - DEBUG(0, ("No SMB password file set\n")); + DEBUG(0, ("NIS+ lookup failure: %s\n", + nis_sperrno(result->status))); return False; } - if( strrchr( pfile, '/') ) - pfile = strrchr( pfile, '/') + 1; - - slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile); - DEBUG(10, ("search by nisname: %s\n", nisname)); - - /* Search the table. */ - if(!(result = nisp_get_nis_list(nisname, 0))) + /* User not found. */ + if (NIS_RES_NUMOBJ(result) <= 0) { + DEBUG(10, ("user not found in NIS+\n")); return False; - } + } - ret = make_sam_from_nisresult(user, result); - nis_freeresult(result); + if (NIS_RES_NUMOBJ(result) > 1) + { + DEBUG(10, ("WARNING: Multiple entries for user in NIS+ table!\n")); + } - return ret; + /* Grab the first hit. */ + return make_sam_from_nisp_object(pw_buf, &NIS_RES_OBJECT(result)[0]); } /************************************************************************* - Routine to search the nisplus passwd file for an entry matching the username + sets a NIS+ attribute *************************************************************************/ - -BOOL pdb_getsampwsid(SAM_ACCOUNT * user, const DOM_SID *sid) +static void set_single_attribute(nis_object *new_obj, int col, + const char *val, int len, int flags) { - uint32 rid; - if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) - return False; - return pdb_getsampwrid(user, rid); -} + if (new_obj == NULL) return; -static BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) -{ - nis_result *result; - char *nisname; - BOOL ret; - char *sp, *p = lp_smb_passwd_file(); - pstring pfiletmp; + ENTRY_VAL(new_obj, col) = val; + ENTRY_LEN(new_obj, col) = len+1; - if (!*p) + if (flags != 0) { - DEBUG(0, ("no SMB password file set\n")); - return False; + new_obj->EN_data.en_cols.en_cols_val[col].ec_flags = flags; } +} - if( (sp = strrchr( p, '/' )) ) - safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); - else - safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); - safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); +/*************************************************************** + 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 */ - nisname = make_nisname_from_user_rid(rid, pfiletmp); + slprintf(uid, sizeof(uid)-1, "%u", pdb_get_uid(sampass)); + slprintf(user_rid, sizeof(user_rid)-1, "%u", + pdb_get_user_rid(sampass)? pdb_get_user_rid(sampass): + pdb_uid_to_user_rid(pdb_get_uid(sampass))); + slprintf(gid, sizeof(gid)-1, "%u", pdb_get_gid(sampass)); - DEBUG(10, ("search by rid: %s\n", nisname)); + { + uint32 rid; + GROUP_MAP map; + + rid=pdb_get_group_rid(sampass); - /* Search the table. */ + if (rid==0) { + if (get_group_map_from_gid(pdb_get_gid(sampass), &map, 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)); + } - if(!(result = nisp_get_nis_list(nisname, 0))) - { - return False; + 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); - ret = make_sam_from_nisresult(user, result); - nis_freeresult(result); +#if 0 - return ret; -} + /* Not sure what to do with these guys. -tpot */ -/************************************************************************* - Routine to remove entry from the nisplus smbpasswd table - *************************************************************************/ -BOOL pdb_delete_sam_account(SAM_ACCOUNT * user) -{ - const char *sname; - char *pfile = lp_smb_passwd_file(); - pstring nisname; - nis_result *result, *delresult; - nis_object *obj; - int i; - - if (!user) { - DEBUG(0, ("no SAM_ACCOUNT specified!\n")); - return False; - } - - sname = pdb_get_username(user); - - if (!*pfile) - { - DEBUG(0, ("no SMB password file set\n")); - return False; - } - if( strrchr( pfile, '/') ) - pfile = strrchr( pfile, '/') + 1; - - slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile); - - /* Search the table. */ - - if( !(result = nisp_get_nis_list(nisname, - MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\ - EXPAND_NAME|HARD_LOOKUP))) { - return False; - } - - if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { - /* User not found. */ - DEBUG(0,("user not found in NIS+\n")); - nis_freeresult(result); - return False; - } - - obj = NIS_RES_OBJECT(result); - slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", sname, obj->zo_name, - obj->zo_domain); - - DEBUG(10, ("removing name: %s\n", nisname)); - delresult = nis_remove_entry(nisname, obj, - MASTER_ONLY|REM_MULTIPLE|ALL_RESULTS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); - - nis_freeresult(result); - - if(delresult->status != NIS_SUCCESS) { - DEBUG(0, ("NIS+ table update failed: %s %s\n", - nisname, nis_sperrno(delresult->status))); - nis_freeresult(delresult); - return False; - } - nis_freeresult(delresult); - return True; -} - -/************************************************************************ - Routine to add an entry to the nisplus passwd file. -*************************************************************************/ -BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) -{ - int local_user = 0; - char *pfile; - pstring pfiletmp; - char *nisname; - nis_result *result = NULL, - *tblresult = NULL; - nis_object new_obj; - entry_col *ecol; - int ta_maxcol; - - /* - * 1. find user domain. - * a. try nis search in passwd.org_dir - if found use domain from result. - * b. try getpwnam. this may be needed if user is defined - * in /etc/passwd file (or elsewere) and not in passwd.org_dir. - * if found, use host default domain. - * c. exit with False - no such user. - * - * 2. add user - * a. find smbpasswd table - * search pfile in user domain if not found, try host default - * domain. - * b. smbpasswd domain is found, fill data and add entry. - * - * pfile should contain ONLY table name, org_dir will be concated. - * so, at first we will clear path prefix from pfile, and - * then we will use pfiletmp as playground to put together full - * nisname string. - * such approach will make it possible to specify samba private dir - * AND still use NIS+ table. as all domain related data is normally - * stored in org_dir.DOMAIN, this should be ok do do. - */ + dos_to_unix(full_name, True); + dos_to_unix(acct_desc, True); - pfile = lp_smb_passwd_file(); - if( strrchr( pfile, '/') ) - pfile = strrchr( pfile, '/') + 1; +#endif - /* - * Check if user is already there. - */ - safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); - safe_strcat(pfiletmp, ".org_dir", - sizeof(pfiletmp)-strlen(pfiletmp)-1); + 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); + } - if(pdb_get_username(newpwd) != NULL) { - nisname = make_nisname_from_name(pdb_get_username(newpwd), - pfiletmp); - } else { - return False; - } - if(!(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\ - FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) { - return False; - } - if (result->status != NIS_SUCCESS && - result->status != NIS_NOTFOUND) { - DEBUG(3, ( "nis_list failure: %s: %s\n", - nisname, nis_sperrno(result->status))); - nis_freeresult(result); - return False; - } + /* 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); + } + } - if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0) - { - DEBUG(3, ("User already exists in NIS+ password db: %s\n", - pfile)); - nis_freeresult(result); - return False; + /* 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); + } } - nis_freeresult(result); /* no such user, free results */ + /* 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); + } - /* - * check for user in unix password database. we need this to get - * domain, where smbpasswd entry should be stored. - */ + /* 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); + } - 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); + /* 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); + } - if (!(passwd = getpwnam_alloc(pdb_get_username(newpwd)))) { - /* no such user in system! */ - return False; - } - passwd_free(&passwd); + /* 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); + } - /* - * 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 */ + /* 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); + } - tblresult = nisp_get_nis_list(pfiletmp, - MASTER_ONLY|FOLLOW_LINKS|\ - FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); + /* 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); } - if (local_user || tblresult->status != NIS_SUCCESS) - { - /* - * no user domain or - * smbpasswd table not found in user domain, fallback to - * default domain. - */ - if (!local_user) /* free previous failed search result */ - nis_freeresult(tblresult); - - safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); - safe_strcat(pfiletmp, ".org_dir", - sizeof(pfiletmp)-strlen(pfiletmp)-1); - tblresult = nis_lookup(pfiletmp, MASTER_ONLY|FOLLOW_LINKS|\ - FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); - if (tblresult->status != NIS_SUCCESS) - { - /* still nothing. bail out */ - nis_freeresult(tblresult); - DEBUG(3, ( "nis_lookup failure: %s\n", - nis_sperrno(tblresult->status))); - return False; - } - /* we need full name for nis_add_entry() */ - safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); - safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1); - safe_strcat(pfiletmp, NIS_RES_OBJECT(tblresult)->zo_domain, - sizeof(pfiletmp)-strlen(pfiletmp)-1); + /* 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); } - 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; + /* 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; - new_obj.zo_data.zo_type = ENTRY_OBJ; - new_obj.EN_data.en_type = - NIS_RES_OBJECT(tblresult)->TA_data.ta_type; + *empty = '\0'; /* empty string */ - ta_maxcol = NIS_RES_OBJECT(tblresult)->TA_data.ta_maxcol; - - if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) { - DEBUG(0, ("memory allocation failure\n")); - nis_freeresult(tblresult); - return False; - } - - memset((char *)ecol, 0, ta_maxcol*sizeof (entry_col)); - new_obj.EN_data.en_cols.en_cols_val = ecol; - new_obj.EN_data.en_cols.en_cols_len = ta_maxcol; - - init_nisp_from_sam(&new_obj, newpwd, NULL); - - DEBUG(10, ( "add NIS+ entry: %s\n", nisname)); - result = nis_add_entry(pfiletmp, &new_obj, 0); + 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); - free(ecol); /* free allocated entry space */ - - if (result->status != NIS_SUCCESS) - { - DEBUG(3, ( "NIS+ table update failed: %s\n", - nisname, nis_sperrno(result->status))); - nis_freeresult(tblresult); - nis_freeresult(result); - return False; - } - - nis_freeresult(tblresult); - nis_freeresult(result); - - return True; -} + if(!(homedir = pdb_get_homedir(sampass))) + homedir = empty; -/************************************************************************ - Routine to modify the nisplus passwd entry. -************************************************************************/ -BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd) -{ - nis_result *result, *addresult; - nis_object *obj; - nis_object new_obj; - entry_col *ecol; - int ta_maxcol; - char *pfile = lp_smb_passwd_file(); - pstring nisname; - int i; + 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; - if (!*pfile) - { - DEBUG(0, ("no SMB password file set\n")); - return False; - } - if( strrchr( pfile, '/') ) - pfile = strrchr( pfile, '/') + 1; - - slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", - pdb_get_username(newpwd), pfile); - - DEBUG(10, ("search by name: %s\n", nisname)); - - /* Search the table. */ - - if( !(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\ - FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) { - return False; + 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); } - if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { - /* User not found. */ - DEBUG(0,("user not found in NIS+\n")); - nis_freeresult(result); - return False; - } + return need_to_modify; +} - obj = NIS_RES_OBJECT(result); - DEBUG(6,("entry found in %s\n", obj->zo_domain)); +/*************************************************************** + calls nis_list, returns results. + ****************************************************************/ +static nis_result *nisp_get_nis_list(const char *nisname, unsigned int flags) +{ + nis_result *result; + int i; - /* we must create new stub object with EN_MODIFIED flag. - this is because obj from result is going to be freed and - we do not want to break it or cause memory leaks or corruption. - */ - - memmove((char *)&new_obj, obj, sizeof (new_obj)); - ta_maxcol = obj->TA_data.ta_maxcol; - - if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) { - DEBUG(0, ("memory allocation failure\n")); - nis_freeresult(result); - return False; - } + if( ! flags) + flags = FOLLOW_LINKS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP; - 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; + for(i = 0; i<2;i++ ) { + alarm(60); /* hopefully ok for long searches */ + result = nis_list(nisname, flags,NULL,NULL); - if ( init_nisp_from_sam(&new_obj, newpwd, obj) == True ) { - slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", - pdb_get_username(newpwd), pfile, obj->zo_domain); + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL); - DEBUG(10, ("NIS+ table update: %s\n", nisname)); - addresult = - nis_modify_entry(nisname, &new_obj, - MOD_SAMEOBJ | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP); - - if(addresult->status != NIS_SUCCESS) { - DEBUG(0, ("NIS+ table update failed: %s %s\n", - nisname, nis_sperrno(addresult->status))); - nis_freeresult(addresult); - nis_freeresult(result); - free(ecol); - return False; - } - - DEBUG(6,("password changed\n")); - nis_freeresult(addresult); - } else { - DEBUG(6,("nothing to change!\n")); - } + 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; +} - free(ecol); - nis_freeresult(result); - - return True; +#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; } - -#else - void nisplus_dummy_function(void); - void nisplus_dummy_function(void) { } /* stop some compilers complaining */ -#endif /* WITH_NISPLUSSAM */ +#endif /* WITH_NISPLUS_SAM */ -- cgit