From 611bf806d569b70edabbc04a2f5408142370a550 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 25 Sep 2001 20:21:21 +0000 Subject: Fixup passdb stuff to add new nisplus and ldap backends. Jeremy. --- source/passdb/passdb.c | 428 ++++++++----- source/passdb/pdb_ldap.c | 1014 +++++++++++++++++++++++++++++ source/passdb/pdb_nisplus.c | 1401 +++++++++++++++++++++++++++++++++++++++++ source/passdb/pdb_smbpasswd.c | 34 +- source/passdb/pdb_tdb.c | 243 +++---- 5 files changed, 2824 insertions(+), 296 deletions(-) create mode 100644 source/passdb/pdb_ldap.c create mode 100644 source/passdb/pdb_nisplus.c (limited to 'source/passdb') diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index 7d133fdda83..2ecbee274fc 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -2,7 +2,7 @@ Unix SMB/Netbios implementation. Version 1.9. Password and authentication handling - Copyright (C) Jeremy Allison 1996-1998 + Copyright (C) Jeremy Allison 1996-2001 Copyright (C) Luke Kenneth Casson Leighton 1996-1998 Copyright (C) Gerald (Jerry) Carter 2000-2001 @@ -35,62 +35,29 @@ extern DOM_SID global_sam_sid; struct passdb_ops *pdb_ops; +#if 0 /* JERRY */ static void* pdb_handle = NULL; +#endif /*************************************************************** Initialize the password db operations. ***************************************************************/ + BOOL initialize_password_db(BOOL reload) -{ - /* This function is unfinished right now, so just - ignore the details and always return True. It is here - only as a placeholder --jerry */ +{ + /* + * This function is unfinished right now, so just + * ignore the details and always return True. It + * is here only as a placeholder --jerry + */ return True; - -#if _NOT_YET_ - char* modulename = lp_passdb_module_path(); - /* load another module? */ - if (reload && pdb_handle) - { - sys_dlclose (pdb_handle); - pdb_handle = NULL; - } - - /* do we have a module defined or use the default? */ - if (strlen (modulename) != 0) - { - if ((pdb_handle=sys_dlopen (modulename, RTLD_LAZY)) == NULL) - { - DEBUG(0,("initialize_password_db: ERROR - Unable to open passdb module \"%s\"!\n%s\n", - modulename, sys_dlerror())); - } - else - DEBUG(1,("initialize_password_db: passdb module \"%s\" loaded successfully\n", modulename)); - } - - /* either no module name defined or the one that was failed - to open. Let's try the default */ - if (pdb_handle == NULL) - { - if ((pdb_handle=sys_dlopen ("libpdbfile.so", RTLD_LAZY)) == NULL) - { - DEBUG(0,("initialize_password_db: ERROR - Unable to open \"libpdbfile.so\" passdb module! No user authentication possible!\n%s\n", - sys_dlerror())); - return False; - } - else - DEBUG(1,("initialize_password_db: passdb module \"libpdbfile.so\" loaded successfully\n")); - } - - - return (pdb_handle != NULL); -#endif } /************************************************************* - initialises a struct sam_disp_info. + Initialises a struct sam_disp_info. **************************************************************/ + static void pdb_init_dispinfo(struct sam_disp_info *user) { if (user == NULL) @@ -99,8 +66,9 @@ static void pdb_init_dispinfo(struct sam_disp_info *user) } /************************************************************* - alloc memory and initialises a struct sam_passwd. + Alloc memory and initialises a struct sam_passwd. ************************************************************/ + BOOL pdb_init_sam(SAM_ACCOUNT **user) { if (*user != NULL) { @@ -138,8 +106,9 @@ BOOL pdb_init_sam(SAM_ACCOUNT **user) } /************************************************************ - free the SAM_ACCOUNT and the NT/LM hashes. + Free the SAM_ACCOUNT and the NT/LM hashes. ***********************************************************/ + BOOL pdb_free_sam(SAM_ACCOUNT *user) { if (user == NULL) { @@ -158,7 +127,7 @@ BOOL pdb_free_sam(SAM_ACCOUNT *user) } /************************************************************ - reset the SAM_ACCOUNT and the NT/LM hashes. + Reset the SAM_ACCOUNT and the NT/LM hashes. ***********************************************************/ BOOL pdb_reset_sam(SAM_ACCOUNT *user) @@ -169,7 +138,7 @@ BOOL pdb_reset_sam(SAM_ACCOUNT *user) } SAFE_FREE(user->nt_pw); - SAFE_FREE(user->lm_pw); + SAFE_FREE(user->lm_pw); ZERO_STRUCTP(user); return True; @@ -178,6 +147,7 @@ BOOL pdb_reset_sam(SAM_ACCOUNT *user) /************************************************************************* Routine to return the next entry in the sam passwd list. *************************************************************************/ + struct sam_disp_info *pdb_sam_to_dispinfo(SAM_ACCOUNT *user) { static struct sam_disp_info disp_info; @@ -194,20 +164,146 @@ struct sam_disp_info *pdb_sam_to_dispinfo(SAM_ACCOUNT *user) return &disp_info; } +/********************************************************** + Encode the account control bits into a string. + length = length of string to encode into (including terminating + null). length *MUST BE MORE THAN 2* ! + **********************************************************/ + +char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length) +{ + static fstring acct_str; + size_t i = 0; + + acct_str[i++] = '['; + + if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N'; + if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D'; + if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H'; + if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T'; + if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U'; + if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M'; + if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W'; + if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S'; + if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L'; + if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X'; + if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I'; + + for ( ; i < length - 2 ; i++ ) + acct_str[i] = ' '; + + i = length - 2; + acct_str[i++] = ']'; + acct_str[i++] = '\0'; + + return acct_str; +} + +/********************************************************** + Decode the account control bits from a string. + **********************************************************/ + +uint16 pdb_decode_acct_ctrl(const char *p) +{ + uint16 acct_ctrl = 0; + BOOL finished = False; + + /* + * Check if the account type bits have been encoded after the + * NT password (in the form [NDHTUWSLXI]). + */ + + if (*p != '[') + return 0; + + for (p++; *p && !finished; p++) { + switch (*p) { + case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ } + case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ } + case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ } + case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ } + case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ } + case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ } + case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ } + case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } + case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } + case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ } + case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ } + case ' ': { break; } + case ':': + case '\n': + case '\0': + case ']': + default: { finished = True; } + } + } + + return acct_ctrl; +} + +/************************************************************* + Routine to set 32 hex password characters from a 16 byte array. +**************************************************************/ + +void pdb_sethexpwd(char *p, unsigned char *pwd, uint16 acct_ctrl) +{ + if (pwd != NULL) { + int i; + for (i = 0; i < 16; i++) + slprintf(&p[i*2], 3, "%02X", pwd[i]); + } else { + if (acct_ctrl & ACB_PWNOTREQ) + safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33); + else + safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33); + } +} + +/************************************************************* + Routine to get the 32 hex characters and turn them + into a 16 byte array. +**************************************************************/ + +BOOL pdb_gethexpwd(char *p, unsigned char *pwd) +{ + int i; + unsigned char lonybble, hinybble; + char *hexchars = "0123456789ABCDEF"; + char *p1, *p2; + + if (!p) + return (False); + + for (i = 0; i < 32; i += 2) { + hinybble = toupper(p[i]); + lonybble = toupper(p[i + 1]); + + p1 = strchr(hexchars, hinybble); + p2 = strchr(hexchars, lonybble); + + if (!p1 || !p2) + return (False); + + hinybble = PTR_DIFF(p1, hexchars); + lonybble = PTR_DIFF(p2, hexchars); + + pwd[i / 2] = (hinybble << 4) | lonybble; + } + return (True); +} + /******************************************************************* Group and User RID username mapping function ********************************************************************/ + BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid) { struct passwd *pw = Get_Pwnam(user_name, False); if (u_rid == NULL || g_rid == NULL || user_name == NULL) - { return False; - } - if (!pw) - { + if (!pw) { DEBUG(1,("Username %s is invalid on this system\n", user_name)); return False; } @@ -225,6 +321,7 @@ BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid) /******************************************************************* Converts NT user RID to a UNIX uid. ********************************************************************/ + uid_t pdb_user_rid_to_uid(uint32 user_rid) { return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER); @@ -269,6 +366,7 @@ static BOOL pdb_rid_is_well_known(uint32 rid) /******************************************************************* Decides if a RID is a user or group RID. ********************************************************************/ + BOOL pdb_rid_is_user(uint32 rid) { /* lkcl i understand that NT attaches an enumeration to a RID @@ -291,9 +389,9 @@ BOOL pdb_rid_is_user(uint32 rid) /******************************************************************* Convert a rid into a name. Used in the lookup SID rpc. ********************************************************************/ + BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) { - BOOL is_user = pdb_rid_is_user(rid); DEBUG(5,("local_lookup_rid: looking up %s RID %u.\n", is_user ? "user" : @@ -341,10 +439,9 @@ BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) } } else { - gid_t gid=-1; + gid_t gid; struct group *gr; - GROUP_MAP map; - DOM_SID sid; + /* * Don't try to convert the rid to a name if running * in appliance mode @@ -353,30 +450,11 @@ BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) if (lp_hide_local_users()) return False; - /* - * First try the TDB. If the RID exists and is mapped to a unix group, - * return the NT name and the type. - */ - - sid_copy(&sid, &global_sam_sid); - sid_append_rid(&sid, rid); - if (get_group_map_from_sid(sid, &map) && map.gid!=-1) { - *psid_name_use = map.sid_name_use; - fstrcpy(name, map.nt_name); - - DEBUG(5,("local_lookup_rid: found NT group %s mapped to Unix gid %u for rid %u\n", - name, (unsigned int)map.gid, (unsigned int)rid )); - - if(!getgrgid(map.gid)) - return False; - else - return True; - } - - *psid_name_use = SID_NAME_ALIAS; gid = pdb_user_rid_to_gid(rid); - gr = getgrgid(gid); + + *psid_name_use = SID_NAME_ALIAS; + DEBUG(5,("local_local_rid: looking up gid %u %s\n", (unsigned int)gid, gr ? "succeeded" : "failed" )); @@ -387,7 +465,8 @@ BOOL local_lookup_rid(uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) fstrcpy( name, gr->gr_name); - DEBUG(5,("local_lookup_rid: found group %s for rid %u\n", name, (unsigned int)rid )); + DEBUG(5,("local_lookup_rid: found group %s for rid %u\n", name, + (unsigned int)rid )); } return True; @@ -441,27 +520,13 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, /* * Maybe it was a group ? */ - GROUP_MAP map; - struct group *grp = NULL; - - /* It can be a mapped group */ - if (get_group_map_from_ntname(user, &map) && map.gid!=-1) { - - grp=getgrgid(map.gid); - if (!grp) - return False; + struct group *grp = getgrnam(user); - sid_copy(&local_sid, &map.sid); - *psid_name_use = map.sid_name_use; - } else { - /* It wasn't mapped, it can be a Unix group */ - grp=getgrnam(user); - if(!grp) - return False; + if(!grp) + return False; - sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); - *psid_name_use = SID_NAME_ALIAS; - } + sid_append_rid( &local_sid, pdb_gid_to_group_rid(grp->gr_gid)); + *psid_name_use = SID_NAME_ALIAS; } sid_copy( psid, &local_sid); @@ -472,6 +537,7 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid, /**************************************************************************** Convert a uid to SID - locally. ****************************************************************************/ + DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) { extern DOM_SID global_sam_sid; @@ -482,10 +548,10 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) return psid; } - /**************************************************************************** Convert a SID to uid - locally. ****************************************************************************/ + BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern DOM_SID global_sam_sid; @@ -527,6 +593,7 @@ BOOL local_sid_to_uid(uid_t *puid, DOM_SID *psid, enum SID_NAME_USE *name_type) /**************************************************************************** Convert a gid to SID - locally. ****************************************************************************/ + DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) { extern DOM_SID global_sam_sid; @@ -540,6 +607,7 @@ DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) /**************************************************************************** Convert a SID to gid - locally. ****************************************************************************/ + BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) { extern DOM_SID global_sam_sid; @@ -582,12 +650,13 @@ BOOL local_sid_to_gid(gid_t *pgid, DOM_SID *psid, enum SID_NAME_USE *name_type) static void select_name(pstring string, const UNISTR2 *from) { if (from->buffer != 0) - unistr2_to_ascii(string, from, sizeof(string)); + unistr2_to_ascii(string, from, sizeof(*string)); } /************************************************************* - copies a SAM_USER_INFO_23 to a SAM_ACCOUNT + Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT **************************************************************/ + void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) { @@ -627,8 +696,9 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) } /************************************************************* - copies a sam passwd. + Copies a sam passwd. **************************************************************/ + void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) { if (from == NULL || to == NULL) @@ -669,19 +739,20 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) to->unknown_6 = from->unknown_6; } - /************************************************************* - copies a sam passwd. + Copies a SAM_ACCOUNT. **************************************************************/ + void copy_sam_passwd(SAM_ACCOUNT *to, const SAM_ACCOUNT *from) { - if (!from || !to) return; + if (!from || !to) + return; memcpy(to, from, sizeof(SAM_ACCOUNT)); } /************************************************************* - change a password entry in the local smbpasswd file + Change a password entry in the local smbpasswd file. FIXME!! The function needs to be abstracted into the passdb interface or something. It is currently being called @@ -723,8 +794,7 @@ account without a valid local system user.\n", user_name); /* Get the smb passwd entry for this user */ pdb_init_sam(&sam_pass); - if(!pdb_getsampwnam(sam_pass, user_name)) - { + if(!pdb_getsampwnam(sam_pass, user_name)) { pdb_free_sam(sam_pass); if(!(local_flags & LOCAL_ADD_USER)) { @@ -780,25 +850,21 @@ account without a valid local system user.\n", user_name); * and the valid last change time. */ - if(local_flags & LOCAL_DISABLE_USER) + if(local_flags & LOCAL_DISABLE_USER) { pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED); - else if (local_flags & LOCAL_ENABLE_USER) - { + } else if (local_flags & LOCAL_ENABLE_USER) { if(pdb_get_lanman_passwd(sam_pass) == NULL) { pdb_set_lanman_passwd (sam_pass, new_p16); pdb_set_nt_passwd (sam_pass, new_nt_p16); } pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED)); - } - else if (local_flags & LOCAL_SET_NO_PASSWORD) { + } else if (local_flags & LOCAL_SET_NO_PASSWORD) { pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ); /* This is needed to preserve ACB_PWNOTREQ in mod_smbfilepwd_entry */ pdb_set_lanman_passwd (sam_pass, NULL); pdb_set_nt_passwd (sam_pass, NULL); - } - else - { + } else { /* * If we're dealing with setting a completely empty user account * ie. One with a password of 'XXXX', but not set disabled (like @@ -822,9 +888,7 @@ account without a valid local system user.\n", user_name); return False; } slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name); - } - else - { + } else { if(!pdb_update_sam_account(sam_pass, True)) { slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name); pdb_free_sam(sam_pass); @@ -842,10 +906,10 @@ account without a valid local system user.\n", user_name); return True; } - /********************************************************************* - collection of get...() functions for SAM_ACCOUNT_INFO + Collection of get...() functions for SAM_ACCOUNT_INFO. ********************************************************************/ + uint16 pdb_get_acct_ctrl (SAM_ACCOUNT *sampass) { if (sampass) @@ -942,7 +1006,6 @@ uint8* pdb_get_lanman_passwd (SAM_ACCOUNT *sampass) return (NULL); } - uint32 pdb_get_user_rid (SAM_ACCOUNT *sampass) { if (sampass) @@ -1088,15 +1151,15 @@ uint32 pdb_get_unknown6 (SAM_ACCOUNT *sampass) } /********************************************************************* - collection of set...() functions for SAM_ACCOUNT_INFO + Collection of set...() functions for SAM_ACCOUNT_INFO. ********************************************************************/ + BOOL pdb_set_acct_ctrl (SAM_ACCOUNT *sampass, uint16 flags) { if (!sampass) return False; - if (sampass) - { + if (sampass) { sampass->acct_ctrl = flags; return True; } @@ -1213,11 +1276,15 @@ BOOL pdb_set_group_rid (SAM_ACCOUNT *sampass, uint32 grid) } /********************************************************************* - set the user's UNIX name + Set the user's UNIX name. ********************************************************************/ + BOOL pdb_set_username(SAM_ACCOUNT *sampass, char *username) { - if (!sampass || !username) + if (!sampass) + return False; + *sampass->username = '\0'; + if (!username) return False; StrnCpy (sampass->username, username, strlen(username)); @@ -1226,11 +1293,15 @@ BOOL pdb_set_username(SAM_ACCOUNT *sampass, char *username) } /********************************************************************* - set the domain name + Set the domain name. ********************************************************************/ + BOOL pdb_set_domain(SAM_ACCOUNT *sampass, char *domain) { - if (!sampass || !domain) + if (!sampass) + return False; + *sampass->domain = '\0'; + if (!domain) return False; StrnCpy (sampass->domain, domain, strlen(domain)); @@ -1239,11 +1310,15 @@ BOOL pdb_set_domain(SAM_ACCOUNT *sampass, char *domain) } /********************************************************************* - set the user's NT name + Set the user's NT name. ********************************************************************/ + BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, char *nt_username) { - if (!sampass || !nt_username) + if (!sampass) + return False; + *sampass->nt_username = '\0'; + if (!nt_username) return False; StrnCpy (sampass->nt_username, nt_username, strlen(nt_username)); @@ -1252,11 +1327,15 @@ BOOL pdb_set_nt_username(SAM_ACCOUNT *sampass, char *nt_username) } /********************************************************************* - set the user's full name + Set the user's full name. ********************************************************************/ + BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, char *fullname) { - if (!sampass || !fullname) + if (!sampass) + return False; + *sampass->full_name = '\0'; + if (!fullname) return False; StrnCpy (sampass->full_name, fullname, strlen(fullname)); @@ -1265,11 +1344,15 @@ BOOL pdb_set_fullname(SAM_ACCOUNT *sampass, char *fullname) } /********************************************************************* - set the user's logon script + Set the user's logon script. ********************************************************************/ + BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, char *logon_script) { - if (!sampass || !logon_script) + if (!sampass) + return False; + *sampass->logon_script = '\0'; + if (!logon_script) return False; StrnCpy (sampass->logon_script, logon_script, strlen(logon_script)); @@ -1278,11 +1361,15 @@ BOOL pdb_set_logon_script(SAM_ACCOUNT *sampass, char *logon_script) } /********************************************************************* - set the user's profile path + Set the user's profile path. ********************************************************************/ + BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, char *profile_path) { - if (!sampass || !profile_path) + if (!sampass) + return False; + *sampass->profile_path = '\0'; + if (!profile_path) return False; StrnCpy (sampass->profile_path, profile_path, strlen(profile_path)); @@ -1291,11 +1378,15 @@ BOOL pdb_set_profile_path (SAM_ACCOUNT *sampass, char *profile_path) } /********************************************************************* - set the user's directory drive + Set the user's directory drive. ********************************************************************/ + BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, char *dir_drive) { - if (!sampass || !dir_drive) + if (!sampass) + return False; + *sampass->dir_drive = '\0'; + if (!dir_drive) return False; StrnCpy (sampass->dir_drive, dir_drive, strlen(dir_drive)); @@ -1304,11 +1395,15 @@ BOOL pdb_set_dir_drive (SAM_ACCOUNT *sampass, char *dir_drive) } /********************************************************************* - set the user's home directory + Set the user's home directory. ********************************************************************/ + BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, char *homedir) { - if (!sampass || !homedir) + if (!sampass) + return False; + *sampass->home_dir = '\0'; + if (!homedir) return False; StrnCpy (sampass->home_dir, homedir, strlen(homedir)); @@ -1317,11 +1412,15 @@ BOOL pdb_set_homedir (SAM_ACCOUNT *sampass, char *homedir) } /********************************************************************* - set the user's account description + Set the user's account description. ********************************************************************/ + BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, char *acct_desc) { - if (!sampass || !acct_desc) + if (!sampass) + return False; + *sampass->acct_desc = '\0'; + if (!acct_desc) return False; StrnCpy (sampass->acct_desc, acct_desc, strlen(acct_desc)); @@ -1330,11 +1429,16 @@ BOOL pdb_set_acct_desc (SAM_ACCOUNT *sampass, char *acct_desc) } /********************************************************************* - set the user's workstation allowed list + Set the user's workstation allowed list. ********************************************************************/ + BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, char *workstations) { - if (!sampass || !workstations) return False; + if (!sampass) + return False; + *sampass->workstations = '\0'; + if (!workstations) + return False; StrnCpy (sampass->workstations, workstations, strlen(workstations)); @@ -1342,11 +1446,16 @@ BOOL pdb_set_workstations (SAM_ACCOUNT *sampass, char *workstations) } /********************************************************************* - set the user's dial string + Set the user's dial string. ********************************************************************/ + BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, char *munged_dial) { - if (!sampass || !munged_dial) return False; + if (!sampass) + return False; + *sampass->munged_dial = '\0'; + if (!munged_dial) + return False; StrnCpy (sampass->munged_dial, munged_dial, strlen(munged_dial)); @@ -1354,14 +1463,16 @@ BOOL pdb_set_munged_dial (SAM_ACCOUNT *sampass, char *munged_dial) } /********************************************************************* - set the user's NT hash + Set the user's NT hash. ********************************************************************/ + BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, uint8 *pwd) { - if (!sampass || !pwd) return False; + if (!sampass || !pwd) + return False; if (sampass->nt_pw!=NULL) - DEBUG(0,("pdb_set_nt_passwd: NT hash non NULL overwriting ?\n")); + DEBUG(4,("pdb_set_nt_passwd: NT hash non NULL overwritting ?\n")); else sampass->nt_pw=(unsigned char *)malloc(sizeof(unsigned char)*16); @@ -1374,14 +1485,16 @@ BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, uint8 *pwd) } /********************************************************************* - set the user's LM hash + Set the user's LM hash. ********************************************************************/ + BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, uint8 *pwd) { - if (!sampass || !pwd) return False; + if (!sampass || !pwd) + return False; if (sampass->lm_pw!=NULL) - DEBUG(0,("pdb_set_lanman_passwd: LM hash non NULL overwriting ?\n")); + DEBUG(4,("pdb_set_lanman_passwd: LM hash non NULL overwritting ?\n")); else sampass->lm_pw=(unsigned char *)malloc(sizeof(unsigned char)*16); @@ -1422,10 +1535,10 @@ BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn) BOOL pdb_set_hours (SAM_ACCOUNT *sampass, uint8 *hours) { - if (!sampass) return False; + if (!sampass) + return False; - if (!hours) - { + if (!hours) { memset ((char *)sampass->hours, 0, MAX_HOURS_LEN); return True; } @@ -1434,4 +1547,3 @@ BOOL pdb_set_hours (SAM_ACCOUNT *sampass, uint8 *hours) return True; } - diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c new file mode 100644 index 00000000000..f4ed014efe0 --- /dev/null +++ b/source/passdb/pdb_ldap.c @@ -0,0 +1,1014 @@ +/* + Unix SMB/Netbios implementation. + Version 2.9. + LDAP protocol helper functions for SAMBA + Copyright (C) Shahms King 2001 + Copyright (C) Jean François Micouleau 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" + +#ifdef WITH_LDAP_SAM +/* TODO: +* persistent connections: if using NSS LDAP, many connections are made +* however, using only one within Samba would be nice +* +* Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK +* +* Other LDAP based login attributes: accountExpires, etc. +* (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT +* structures don't have fields for some of these attributes) +* +* SSL is done, but can't get the certificate based authentication to work +* against on my test platform (Linux 2.4, OpenLDAP 2.x) +*/ + +/* NOTE: this will NOT work against an Active Directory server +* due to the fact that the two password fields cannot be retrieved +* from a server; recommend using security = domain in this situation +* and/or winbind +*/ + +#include +#include + +#ifndef SAM_ACCOUNT +#define SAM_ACCOUNT struct sam_passwd +#endif + +extern int DEBUGLEVEL; + +struct ldap_enum_info +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; +}; + +static struct ldap_enum_info global_ldap_ent; + + +/******************************************************************* + open a connection to the ldap server. +******************************************************************/ +static BOOL +ldap_open_connection (LDAP ** ldap_struct) +{ + int port; + int version, rc; + int tls = LDAP_OPT_X_TLS_HARD; + + if (lp_ldap_ssl() == LDAP_SSL_ON && lp_ldap_port() == 389) { + port = 636; + } + else { + port = lp_ldap_port(); + } + + if ((*ldap_struct = ldap_init(lp_ldap_server(), port)) == NULL) { + DEBUG(0, ("The LDAP server is not responding !\n")); + return (False); + } + + /* Connect to older servers using SSL and V2 rather than Start TLS */ + if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) + { + if (version != LDAP_VERSION2) + { + version = LDAP_VERSION2; + ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version); + } + } + + switch (lp_ldap_ssl()) + { + case LDAP_SSL_START_TLS: + if (ldap_get_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, + &version) == LDAP_OPT_SUCCESS) + { + if (version < LDAP_VERSION3) + { + version = LDAP_VERSION3; + ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, + &version); + } + } + if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) + { + DEBUG(0, + ("Failed to issue the StartTLS instruction: %s\n", + ldap_err2string(rc))); + return False; + } + DEBUG (2, ("StartTLS issued: using a TLS connection\n")); + break; + case LDAP_SSL_ON: + if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) + { + DEBUG(0, ("Failed to setup a TLS session\n")); + } + break; + case LDAP_SSL_OFF: + default: + } + + DEBUG(2, ("ldap_open_connection: connection opened\n")); + return (True); +} + +/******************************************************************* + connect to the ldap server under system privilege. +******************************************************************/ +static BOOL ldap_connect_system(LDAP * ldap_struct) +{ + int rc; + static BOOL got_pw = False; + static pstring ldap_secret; + + /* get the password if we don't have it already */ + if (!got_pw && !(got_pw=fetch_ldap_pw(lp_ldap_admin_dn(), ldap_secret, sizeof(pstring)))) + { + DEBUG(0, ("ldap_connect_system: Failed to retrieve password for %s from secrets.tdb\n", + lp_ldap_admin_dn())); + return False; + } + + /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite + (OpenLDAP) doesnt' seem to support it */ + if ((rc = ldap_simple_bind_s(ldap_struct, lp_ldap_admin_dn(), + ldap_secret)) != LDAP_SUCCESS) + { + DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc))); + return (False); + } + + DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n")); + return (True); +} + +/******************************************************************* + run the search by name. +******************************************************************/ +static int ldap_search_one_user (LDAP * ldap_struct, const char *filter, LDAPMessage ** result) +{ + int scope = LDAP_SCOPE_SUBTREE; + int rc; + + DEBUG(2, ("ldap_search_one_user: searching for:[%s]\n", filter)); + + rc = ldap_search_s (ldap_struct, lp_ldap_suffix (), scope, + filter, NULL, 0, result); + + if (rc != LDAP_SUCCESS) { + DEBUG(0,("ldap_search_one_user: Problem during the LDAP search: %s\n", + ldap_err2string (rc))); + DEBUG(3,("ldap_search_one_user: Query was: %s, %s\n", lp_ldap_suffix(), + filter)); + } + return (rc); +} + +/******************************************************************* + run the search by name. +******************************************************************/ +static int ldap_search_one_user_by_name (LDAP * ldap_struct, const char *user, + LDAPMessage ** result) +{ + pstring filter; + + /* + in the filter expression, replace %u with the real name + so in ldap filter, %u MUST exist :-) + */ + pstrcpy(filter, lp_ldap_filter()); + + /* have to use this here because $ is filtered out + * in pstring_sub + */ + all_string_sub(filter, "%u", user, sizeof(pstring)); + + return ldap_search_one_user(ldap_struct, filter, result); +} + +/******************************************************************* + run the search by uid. +******************************************************************/ +static int ldap_search_one_user_by_uid(LDAP * ldap_struct, int uid, + LDAPMessage ** result) +{ + struct passwd *user; + pstring filter; + + /* Get the username from the system and look that up in the LDAP */ + user = sys_getpwuid(uid); + pstrcpy(filter, lp_ldap_filter()); + all_string_sub(filter, "%u", user->pw_name, sizeof(pstring)); + + return ldap_search_one_user(ldap_struct, filter, result); +} + +/******************************************************************* + run the search by rid. +******************************************************************/ +static int ldap_search_one_user_by_rid (LDAP * ldap_struct, uint32 rid, + LDAPMessage ** result) +{ + pstring filter; + int rc; + + /* check if the user rid exsists, if not, try searching on the uid */ + snprintf(filter, sizeof(filter) - 1, "rid=%i", rid); + rc = ldap_search_one_user(ldap_struct, filter, result); + + if (rc != LDAP_SUCCESS) + rc = ldap_search_one_user_by_uid(ldap_struct, + pdb_user_rid_to_uid(rid), result); + + return rc; +} + +/******************************************************************* +search an attribute and return the first value found. +******************************************************************/ +static void get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, + char *attribute, char *value) +{ + char **valeurs; + + if ((valeurs = ldap_get_values (ldap_struct, entry, attribute)) != NULL) { + pstrcpy(value, valeurs[0]); + ldap_value_free(valeurs); + DEBUG (2, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); + } + else { + value = NULL; + DEBUG (2, ("get_single_attribute: [%s] = [NULL]\n", attribute)); + } +} + +/************************************************************************ +Routine to manage the LDAPMod structure array +manage memory used by the array, by each struct, and values + +************************************************************************/ +static void make_a_mod (LDAPMod *** modlist, int modop, char *attribute, char *value) +{ + LDAPMod **mods; + int i; + int j; + + mods = *modlist; + + if (attribute == NULL || *attribute == '\0') + return; + + if (value == NULL || *value == '\0') + return; + + if (mods == NULL) + { + mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); + if (mods == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[0] = NULL; + } + + for (i = 0; mods[i] != NULL; ++i) { + if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) + break; + } + + if (mods[i] == NULL) + { + mods = (LDAPMod **) realloc (mods, (i + 2) * sizeof (LDAPMod *)); + if (mods == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); + if (mods[i] == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i]->mod_op = modop; + mods[i]->mod_values = NULL; + mods[i]->mod_type = strdup(attribute); + mods[i + 1] = NULL; + } + + if (value != NULL) + { + j = 0; + if (mods[i]->mod_values != NULL) { + for (; mods[i]->mod_values[j] != NULL; j++); + } + mods[i]->mod_values = (char **)realloc(mods[i]->mod_values, + (j + 2) * sizeof (char *)); + + if (mods[i]->mod_values == NULL) { + DEBUG (0, ("make_a_mod: Memory allocation failure!\n")); + return; + } + mods[i]->mod_values[j] = strdup(value); + mods[i]->mod_values[j + 1] = NULL; + } + *modlist = mods; +} + +/* New Interface is being implemented here */ + +/********************************************************************** +Initialize SAM_ACCOUNT from an LDAP query +(Based on init_sam_from_buffer in pdb_tdb.c) +*********************************************************************/ +static BOOL init_sam_from_ldap (SAM_ACCOUNT * sampass, + LDAP * ldap_struct, LDAPMessage * entry) +{ + time_t logon_time, + logoff_time, + kickoff_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time; + static pstring username; + static pstring domain; + static pstring nt_username; + static pstring fullname; + static pstring homedir; + static pstring dir_drive; + static pstring logon_script; + static pstring profile_path; + static pstring acct_desc; + static pstring munged_dial; + static pstring workstations; + struct passwd *sys_user; + uint32 user_rid, group_rid; + static uint8 smblmpwd[16]; + static uint8 smbntpwd[16]; + uint16 acct_ctrl, logon_divs; + uint32 hours_len; + uint8 *hours; + pstring temp; + + get_single_attribute(ldap_struct, entry, "uid", username); + DEBUG(2, ("Entry found for user: %s\n", username)); + + /* not sure about this for nt_username */ + get_single_attribute (ldap_struct, entry, "sAMAccountName", nt_username); + if (!nt_username) + pstrcpy(nt_username, username); + + get_single_attribute(ldap_struct, entry, "sambaDomain", domain); + if (!domain) + pstrcpy(domain, lp_workgroup()); + + get_single_attribute(ldap_struct, entry, "pwdLastSet", temp); + pass_last_set_time = (time_t) strtol(temp, NULL, 16); + + get_single_attribute(ldap_struct, entry, "logonTime", temp); + logon_time = (time_t) strtol(temp, NULL, 16); + + get_single_attribute(ldap_struct, entry, "logoffTime", temp); + logoff_time = (time_t) strtol(temp, NULL, 16); + + get_single_attribute(ldap_struct, entry, "kickoffTime", temp); + kickoff_time = (time_t) strtol(temp, NULL, 16); + + get_single_attribute(ldap_struct, entry, "pwdCanChange", temp); + pass_can_change_time = (time_t) strtol(temp, NULL, 16); + + get_single_attribute(ldap_struct, entry, "pwdMustChange", temp); + pass_must_change_time = (time_t) strtol(temp, NULL, 16); + + /* recommend that 'gecos' and 'displayName' should refer to the same + * attribute OID. userFullName depreciated, only used by Samba + * primary rules of LDAP: don't make a new attribute when one is already defined + * that fits your needs; using gecos then displayName then cn rather than 'userFullName' + */ + + get_single_attribute(ldap_struct, entry, "gecos", fullname); + + if (!fullname) { + get_single_attribute(ldap_struct, entry, "displayName", fullname); + get_single_attribute(ldap_struct, entry, "cn", fullname); + } + + get_single_attribute(ldap_struct, entry, "homeDrive", dir_drive); + get_single_attribute(ldap_struct, entry, "scriptPath", logon_script); + get_single_attribute(ldap_struct, entry, "profilePath", profile_path); + get_single_attribute(ldap_struct, entry, "description", acct_desc); + get_single_attribute (ldap_struct, entry, "userWorkstations", workstations); + + get_single_attribute(ldap_struct, entry, "rid", temp); + user_rid = (uint32)strtol(temp, NULL, 16); + get_single_attribute(ldap_struct, entry, "primaryGroupID", temp); + group_rid = (uint32)strtol(temp, NULL, 16); + + + /* These values MAY be in LDAP, but they can also be retrieved through + * sys_getpw*() which is how we're doing it (if you use nss_ldap, then + * these values will be stored in LDAP as well, but if not, we want the + * local values to override the LDAP for this anyway + * homeDirectory attribute + */ + sys_user = sys_getpwnam(username); + if (sys_user == NULL) + return False; + pstrcpy(homedir, sys_user->pw_dir); + + + /* FIXME: hours stuff should be cleaner */ + logon_divs = 168; + hours_len = 21; + hours = malloc(sizeof(hours) * hours_len); + memset(hours, 0xff, hours_len); + + get_single_attribute (ldap_struct, entry, "lmPassword", temp); + pdb_gethexpwd(temp, smblmpwd); + memset((char *)temp, '\0', sizeof(temp)); + get_single_attribute (ldap_struct, entry, "ntPassword", temp); + pdb_gethexpwd(temp, smbntpwd); + memset((char *)temp, '\0', sizeof(temp)); + get_single_attribute (ldap_struct, entry, "acctFlags", temp); + acct_ctrl = pdb_decode_acct_ctrl(temp); + + if (acct_ctrl == 0) + acct_ctrl |= ACB_NORMAL; + + + pdb_set_acct_ctrl(sampass, acct_ctrl); + pdb_set_logon_time(sampass, logon_time); + pdb_set_logoff_time(sampass, logoff_time); + pdb_set_kickoff_time(sampass, kickoff_time); + pdb_set_pass_can_change_time(sampass, pass_can_change_time); + pdb_set_pass_must_change_time(sampass, pass_must_change_time); + pdb_set_pass_last_set_time(sampass, pass_last_set_time); + + pdb_set_hours_len(sampass, hours_len); + pdb_set_logons_divs(sampass, logon_divs); + + pdb_set_uid(sampass, sys_user->pw_uid); + pdb_set_gid(sampass, sys_user->pw_gid); + pdb_set_user_rid(sampass, user_rid); + pdb_set_group_rid(sampass, group_rid); + + pdb_set_username(sampass, username); + + pdb_set_domain(sampass, domain); + pdb_set_nt_username(sampass, nt_username); + + pdb_set_fullname(sampass, fullname); + + pdb_set_logon_script(sampass, logon_script); + pdb_set_profile_path(sampass, profile_path); + pdb_set_dir_drive(sampass, dir_drive); + pdb_set_homedir(sampass, homedir); + pdb_set_acct_desc(sampass, acct_desc); + pdb_set_workstations(sampass, workstations); + pdb_set_munged_dial(sampass, munged_dial); + pdb_set_nt_passwd(sampass, smbntpwd); + pdb_set_lanman_passwd(sampass, smblmpwd); + + /* pdb_set_unknown_3(sampass, unknown3); */ + /* pdb_set_unknown_5(sampass, unknown5); */ + /* pdb_set_unknown_6(sampass, unknown6); */ + + pdb_set_hours(sampass, hours); + + return True; +} + +/********************************************************************** +Initialize SAM_ACCOUNT from an LDAP query +(Based on init_buffer_from_sam in pdb_tdb.c) +*********************************************************************/ +static BOOL init_ldap_from_sam (LDAPMod *** mods, int ldap_state, SAM_ACCOUNT * sampass) +{ + pstring temp; + + *mods = NULL; + + /* + * took out adding "objectclass: sambaAccount" + * do this on a per-mod basis + */ + + + make_a_mod(mods, ldap_state, "uid", pdb_get_username(sampass)); + DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass))); + + /* not sure about using this for the nt_username */ + make_a_mod (mods, ldap_state, "sAMAccountName", pdb_get_nt_username(sampass)); + make_a_mod(mods, ldap_state, "sambaDomain", pdb_get_domain(sampass)); + + slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_uid(sampass)); + make_a_mod(mods, ldap_state, "uidNumber", temp); + + slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass)); + make_a_mod(mods, ldap_state, "pwdLastSet", temp); + + slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass)); + make_a_mod(mods, ldap_state, "logonTime", temp); + + slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass)); + make_a_mod(mods, ldap_state, "logoffTime", temp); + + slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass)); + make_a_mod(mods, ldap_state, "kickoffTime", temp); + + slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass)); + make_a_mod(mods, ldap_state, "pwdCanChange", temp); + + slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass)); + make_a_mod(mods, ldap_state, "pwdMustChange", temp); + + /* displayName, cn, and gecos should all be the same + * most easily accomplished by giving them the same OID + * gecos isn't set here b/c it should be handled by the + * add-user script + */ + + make_a_mod(mods, ldap_state, "displayName", pdb_get_fullname(sampass)); + make_a_mod(mods, ldap_state, "cn", pdb_get_fullname(sampass)); + + make_a_mod(mods, ldap_state, "homeDirectory", pdb_get_homedir(sampass)); + make_a_mod(mods, ldap_state, "homeDrive", pdb_get_dirdrive(sampass)); + make_a_mod(mods, ldap_state, "scriptPath", pdb_get_logon_script(sampass)); + make_a_mod(mods, ldap_state, "profilePath", pdb_get_profile_path(sampass)); + make_a_mod(mods, ldap_state, "description", pdb_get_acct_desc(sampass)); + make_a_mod(mods, ldap_state, "userWorkstations", pdb_get_workstations(sampass)); + + slprintf(temp, sizeof(temp) - 1, "%i", sampass->user_rid); + make_a_mod(mods, ldap_state, "rid", temp); + + slprintf(temp, sizeof(temp) - 1, "%i", sampass->group_rid); + make_a_mod(mods, ldap_state, "primaryGroupID", temp); + + /* FIXME: Hours stuff goes in LDAP */ + pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass)); + make_a_mod (mods, ldap_state, "lmPassword", temp); + pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass)); + make_a_mod (mods, ldap_state, "ntPassword", temp); + make_a_mod (mods, ldap_state, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), + NEW_PW_FORMAT_SPACE_PADDED_LEN)); + + return True; +} + +/********************************************************************** +Connect to LDAP server for password enumeration +*********************************************************************/ +BOOL pdb_setsampwent(BOOL update) +{ + int rc; + pstring filter; + + if (!ldap_open_connection(&global_ldap_ent.ldap_struct)) + { + return False; + } + if (!ldap_connect_system(global_ldap_ent.ldap_struct)) + { + ldap_unbind(global_ldap_ent.ldap_struct); + return False; + } + + pstrcpy(filter, lp_ldap_filter()); + all_string_sub(filter, "%u", "*", sizeof(pstring)); + + rc = ldap_search_s(global_ldap_ent.ldap_struct, lp_ldap_suffix(), + LDAP_SCOPE_SUBTREE, filter, NULL, 0, + &global_ldap_ent.result); + + if (rc != LDAP_SUCCESS) + { + DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); + ldap_msgfree(global_ldap_ent.result); + ldap_unbind(global_ldap_ent.ldap_struct); + global_ldap_ent.ldap_struct = NULL; + global_ldap_ent.result = NULL; + return False; + } + + DEBUG(2, ("pdb_setsampwent: %d entries in the base!\n", + ldap_count_entries(global_ldap_ent.ldap_struct, + global_ldap_ent.result))); + + global_ldap_ent.entry = ldap_first_entry(global_ldap_ent.ldap_struct, + global_ldap_ent.result); + + return True; +} + +/********************************************************************** +End enumeration of the LDAP password list +*********************************************************************/ +void pdb_endsampwent(void) +{ + if (global_ldap_ent.ldap_struct && global_ldap_ent.result) + { + ldap_msgfree(global_ldap_ent.result); + ldap_unbind(global_ldap_ent.ldap_struct); + global_ldap_ent.ldap_struct = NULL; + global_ldap_ent.result = NULL; + } +} + +/********************************************************************** +Get the next entry in the LDAP password database +*********************************************************************/ +BOOL pdb_getsampwent(SAM_ACCOUNT * user) +{ + if (!global_ldap_ent.entry) + return False; + + global_ldap_ent.entry = ldap_next_entry(global_ldap_ent.ldap_struct, + global_ldap_ent.entry); + + if (global_ldap_ent.entry != NULL) + { + return init_sam_from_ldap(user, global_ldap_ent.ldap_struct, + global_ldap_ent.entry); + } + return False; +} + +/********************************************************************** +Get SAM_ACCOUNT entry from LDAP by username +*********************************************************************/ +BOOL pdb_getsampwnam(SAM_ACCOUNT * user, char *sname) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + + if (!ldap_open_connection(&ldap_struct)) + return False; + if (!ldap_connect_system(ldap_struct)) + { + ldap_unbind(ldap_struct); + return False; + } + if (ldap_search_one_user_by_name(ldap_struct, sname, &result) != + LDAP_SUCCESS) + { + ldap_unbind(ldap_struct); + return False; + } + if (ldap_count_entries(ldap_struct, result) < 1) + { + DEBUG(0, + ("We don't find this user [%s] count=%d\n", sname, + ldap_count_entries(ldap_struct, result))); + ldap_unbind(ldap_struct); + return False; + } + entry = ldap_first_entry(ldap_struct, result); + if (entry) + { + init_sam_from_ldap(user, ldap_struct, entry); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return True; + } + else + { + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } +} + +/********************************************************************** +Get SAM_ACCOUNT entry from LDAP by rid +*********************************************************************/ +BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + + if (!ldap_open_connection(&ldap_struct)) + return False; + + if (!ldap_connect_system(ldap_struct)) + { + ldap_unbind(ldap_struct); + return False; + } + if (ldap_search_one_user_by_rid(ldap_struct, rid, &result) != + LDAP_SUCCESS) + { + ldap_unbind(ldap_struct); + return False; + } + + if (ldap_count_entries(ldap_struct, result) < 1) + { + DEBUG(0, + ("We don't find this rid [%i] count=%d\n", rid, + ldap_count_entries(ldap_struct, result))); + ldap_unbind(ldap_struct); + return False; + } + + entry = ldap_first_entry(ldap_struct, result); + if (entry) + { + init_sam_from_ldap(user, ldap_struct, entry); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return True; + } + else + { + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } +} + +/********************************************************************** + Get SAM_ACCOUNT entry from LDAP by uid +*********************************************************************/ +BOOL pdb_getsampwuid(SAM_ACCOUNT * user, uid_t uid) +{ + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + + if (!ldap_open_connection(&ldap_struct)) + return False; + + if (!ldap_connect_system(ldap_struct)) + { + ldap_unbind(ldap_struct); + return False; + } + if (ldap_search_one_user_by_uid(ldap_struct, uid, &result) != + LDAP_SUCCESS) + { + ldap_unbind(ldap_struct); + return False; + } + + if (ldap_count_entries(ldap_struct, result) < 1) + { + DEBUG(0, + ("We don't find this uid [%i] count=%d\n", uid, + ldap_count_entries(ldap_struct, result))); + ldap_unbind(ldap_struct); + return False; + } + entry = ldap_first_entry(ldap_struct, result); + if (entry) + { + init_sam_from_ldap(user, ldap_struct, entry); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return True; + } + else + { + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } +} + + +/********************************************************************** +Delete entry from LDAP for username +*********************************************************************/ +BOOL pdb_delete_sam_account(char *sname) +{ + int rc; + char *dn; + LDAP *ldap_struct; + LDAPMessage *entry; + LDAPMessage *result; + + if (!ldap_open_connection (&ldap_struct)) + return False; + + DEBUG (3, ("Deleting user %s from LDAP.\n", sname)); + + if (!ldap_connect_system (ldap_struct)) { + ldap_unbind (ldap_struct); + DEBUG(0, ("Failed to delete user %s from LDAP.\n", sname)); + return False; + } + + rc = ldap_search_one_user_by_name (ldap_struct, sname, &result); + if (ldap_count_entries (ldap_struct, result) == 0) { + DEBUG (0, ("User doesn't exit!\n")); + ldap_msgfree (result); + ldap_unbind (ldap_struct); + return False; + } + + entry = ldap_first_entry (ldap_struct, result); + dn = ldap_get_dn (ldap_struct, entry); + + rc = ldap_delete_s (ldap_struct, dn); + + ldap_memfree (dn); + if (rc != LDAP_SUCCESS) { + char *ld_error; + ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG (0,("failed to delete user with uid = %s with: %s\n\t%s\n", + sname, ldap_err2string (rc), ld_error)); + free (ld_error); + ldap_unbind (ldap_struct); + return False; + } + + DEBUG (2,("successfully deleted uid = %s from the LDAP database\n", sname)); + ldap_unbind (ldap_struct); + return True; +} + +/********************************************************************** +Update SAM_ACCOUNT +*********************************************************************/ +BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd, BOOL override) +{ + int rc; + char *dn; + LDAP *ldap_struct; + LDAPMessage *result; + LDAPMessage *entry; + LDAPMod **mods; + + if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + return False; + + if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + { + ldap_unbind(ldap_struct); + return False; + } + + rc = ldap_search_one_user_by_name(ldap_struct, + pdb_get_username(newpwd), &result); + + if (ldap_count_entries(ldap_struct, result) == 0) + { + DEBUG(0, ("No user to modify!\n")); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } + + init_ldap_from_sam(&mods, LDAP_MOD_REPLACE, newpwd); + + entry = ldap_first_entry(ldap_struct, result); + dn = ldap_get_dn(ldap_struct, entry); + + rc = ldap_modify_s(ldap_struct, dn, mods); + + if (rc != LDAP_SUCCESS) + { + char *ld_error; + ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + DEBUG(0, + ("failed to modify user with uid = %s with: %s\n\t%s\n", + pdb_get_username(newpwd), ldap_err2string(rc), + ld_error)); + free(ld_error); + ldap_unbind(ldap_struct); + return False; + } + + DEBUG(2, + ("successfully modified uid = %s in the LDAP database\n", + pdb_get_username(newpwd))); + ldap_mods_free(mods, 1); + ldap_unbind(ldap_struct); + return True; +} + +/********************************************************************** +Add SAM_ACCOUNT to LDAP +*********************************************************************/ +BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) +{ + int rc; + pstring filter; + LDAP *ldap_struct; + LDAPMessage *result; + pstring dn; + LDAPMod **mods; + int ldap_op = LDAP_MOD_ADD; + + if (!ldap_open_connection(&ldap_struct)) /* open a connection to the server */ + { + return False; + } + + if (!ldap_connect_system(ldap_struct)) /* connect as system account */ + { + ldap_unbind(ldap_struct); + return False; + } + + if (pdb_get_username(newpwd) != NULL) { + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", + pdb_get_username(newpwd), lp_ldap_suffix ()); + } + else + { + return False; + } + + + rc = ldap_search_one_user_by_name (ldap_struct, pdb_get_username(newpwd), &result); + + if (ldap_count_entries(ldap_struct, result) != 0) + { + DEBUG(0,("User already in the base, with samba properties\n")); + ldap_msgfree(result); + ldap_unbind(ldap_struct); + return False; + } + ldap_msgfree(result); + + slprintf (filter, sizeof (filter) - 1, "uid=%s", pdb_get_username(newpwd)); + rc = ldap_search_one_user(ldap_struct, filter, &result); + if (ldap_count_entries(ldap_struct, result) == 1) + { + char *tmp; + LDAPMessage *entry; + DEBUG(3,("User exists without samba properties: adding them\n")); + ldap_op = LDAP_MOD_REPLACE; + entry = ldap_first_entry (ldap_struct, result); + tmp = ldap_get_dn (ldap_struct, entry); + slprintf (dn, sizeof (dn) - 1, "%s", tmp); + ldap_memfree (tmp); + } + else + { + DEBUG (3, ("More than one user with that uid exists: bailing out!\n")); + return False; + } + + ldap_msgfree(result); + + init_ldap_from_sam(&mods, ldap_op, newpwd); + make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount"); + + if (ldap_op == LDAP_MOD_REPLACE) { + rc = ldap_modify_s(ldap_struct, dn, mods); + } + else { + rc = ldap_add_s(ldap_struct, dn, mods); + } + + if (rc != LDAP_SUCCESS) + { + char *ld_error; + + ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(0,("failed to modify user with uid = %s with: %s\n\t%s\n", + pdb_get_username(newpwd), ldap_err2string (rc), ld_error)); + free(ld_error); + ldap_mods_free(mods, 1); + ldap_unbind(ldap_struct); + return False; + } + + DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd))); + ldap_mods_free(mods, 1); + ldap_unbind(ldap_struct); + return True; +} + +#else +void dummy_function(void); +void +dummy_function (void) +{ +} /* stop some compilers complaining */ +#endif diff --git a/source/passdb/pdb_nisplus.c b/source/passdb/pdb_nisplus.c new file mode 100644 index 00000000000..368fb3dc49d --- /dev/null +++ b/source/passdb/pdb_nisplus.c @@ -0,0 +1,1401 @@ +/* + * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup + * 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 Soomea 2001 + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#ifdef WITH_NISPLUS_SAM + +#ifdef BROKEN_NISPLUS_INCLUDE_FILES + +/* + * The following lines are needed due to buggy include files + * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and + * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. + * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as + * an enum in /usr/include/rpcsvc/nis.h. + */ + +#if defined(GROUP) +#undef GROUP +#endif + +#if defined(GROUP_OBJ) +#undef GROUP_OBJ +#endif + +#endif + +#include + +extern int DEBUGLEVEL; +extern pstring samlogon_user; +extern BOOL sam_logon_in_ssb; + +struct nisp_enum_info +{ + nis_result *result; + int enum_entry; +}; + +static struct nisp_enum_info global_nisp_ent; +static VOLATILE sig_atomic_t gotalarm; + +/*************************************************************** + + the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are: + + name=S,nogw=r + uid=S,nogw=r + user_rid=S,nogw=r + smb_grpid=,nw+r + group_rid=,nw+r + acb=,nw+r + + lmpwd=C,nw=,g=r,o=rm + ntpwd=C,nw=,g=r,o=rm + + logon_t=,nw+r + logoff_t=,nw+r + kick_t=,nw+r + pwdlset_t=,nw+r + pwdlchg_t=,nw+r + pwdmchg_t=,nw+r + + full_name=,nw+r + home_dir=,nw+r + dir_drive=,nw+r + logon_script=,nw+r + profile_path=,nw+r + acct_desc=,nw+r + workstations=,nw+r + + hours=,nw+r + +****************************************************************/ + +#define NPF_NAME 0 +#define NPF_UID 1 +#define NPF_USER_RID 2 +#define NPF_SMB_GRPID 3 +#define NPF_GROUP_RID 4 +#define NPF_ACB 5 +#define NPF_LMPWD 6 +#define NPF_NTPWD 7 +#define NPF_LOGON_T 8 +#define NPF_LOGOFF_T 9 +#define NPF_KICK_T 10 +#define NPF_PWDLSET_T 11 +#define NPF_PWDCCHG_T 12 +#define NPF_PWDMCHG_T 13 +#define NPF_FULL_NAME 14 +#define NPF_HOME_DIR 15 +#define NPF_DIR_DRIVE 16 +#define NPF_LOGON_SCRIPT 17 +#define NPF_PROFILE_PATH 18 +#define NPF_ACCT_DESC 19 +#define NPF_WORKSTATIONS 20 +#define NPF_HOURS 21 + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +/*************************************************************** + make_nisname_from_user_rid + ****************************************************************/ +static char *make_nisname_from_user_rid(uint32 rid, char *pfile) +{ + static pstring nisname; + + safe_strcpy(nisname, "[user_rid=", sizeof(nisname)-1); + slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, rid); + safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1); + safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1); + + return nisname; +} + +/*************************************************************** + make_nisname_from_uid + ****************************************************************/ +static char *make_nisname_from_uid(int uid, char *pfile) +{ + static pstring nisname; + + safe_strcpy(nisname, "[uid=", sizeof(nisname)-1); + slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, uid); + safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1); + safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1); + + return nisname; +} + +/*************************************************************** + make_nisname_from_name + ****************************************************************/ +static char *make_nisname_from_name(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(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, 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! + */ + + pdb_set_logon_time(pw_buf, -1); + 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_logoff_time(pw_buf, -1); + 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_kickoff_time(pw_buf, -1); + 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_pass_last_set_time(pw_buf, -1); + ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDLSET_T); + if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) { + int i; + ptr += 4; + for(i = 0; i < 8; i++) { + if(ptr[i] == '\0' || !isxdigit(ptr[i])) + break; + } + if(i == 8) { + pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16)); + } + } + + pdb_set_pass_can_change_time(pw_buf, -1); + 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_pass_must_change_time(pw_buf, -1); + 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)); + } + } + + /* 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)); + unix_to_dos(full_name, True); + 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)); + unix_to_dos(acct_desc, True); + pdb_set_acct_desc(pw_buf, acct_desc); + + pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS)); + pdb_set_munged_dial(pw_buf, NULL); + + pdb_set_uid(pw_buf, atoi(ENTRY_VAL(obj, NPF_UID))); + pdb_set_gid(pw_buf, atoi(ENTRY_VAL(obj, NPF_SMB_GRPID))); + pdb_set_user_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID))); + pdb_set_group_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID))); + + /* values, must exist for user */ + if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) { + /* FIXME!! This doesn't belong here. + Should be set in net_sam_logon() + --jerry */ + pstrcpy(samlogon_user, pdb_get_username(pw_buf)); + + 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); + + 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); + + 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); + + 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); + } else { + /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ + pdb_set_group_rid (pw_buf, DOMAIN_GROUP_RID_USERS); + } + + /* Check the lanman password column. */ + ptr = (char *)ENTRY_VAL(obj, NPF_LMPWD); + pdb_set_lanman_passwd(pw_buf, NULL); + + 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; + } + pdb_set_lanman_passwd(pw_buf, smbpwd); + } + + /* Check the NT password column. */ + ptr = ENTRY_VAL(obj, NPF_NTPWD); + pdb_set_nt_passwd(pw_buf, NULL); + + 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; + } + pdb_set_nt_passwd(pw_buf, smbntpwd); + } + + pdb_set_unknown_3(pw_buf, 0xffffff); /* don't know */ + pdb_set_logons_divs(pw_buf, 168); /* hours per week */ + + if( (hours_len = ENTRY_LEN(obj, NPF_HOURS)) == 21 ) { + memcpy(hours, ENTRY_VAL(obj, NPF_HOURS), hours_len); + } else { + hours_len = 21; /* 21 times 8 bits = 168 */ + /* available at all hours */ + memset(hours, 0xff, hours_len); + } + pdb_set_hours_len(pw_buf, hours_len); + pdb_set_hours(pw_buf, hours); + + pdb_set_unknown_5(pw_buf, 0x00020000); /* don't know */ + pdb_set_unknown_6(pw_buf, 0x000004ec); /* don't know */ + + return True; +} + +/************************************************************************ + makes a struct sam_passwd from a NIS+ result. + ************************************************************************/ +static BOOL make_sam_from_nisresult(SAM_ACCOUNT *pw_buf, 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, + 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, 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; + char *name; /* 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 */ + + + name = pdb_get_username(sampass); + 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)); + slprintf(group_rid, sizeof(group_rid)-1, "%u", + pdb_get_group_rid(sampass)? pdb_get_group_rid(sampass): + pdb_gid_to_group_rid(pdb_get_gid(sampass))); + 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); + dos_to_unix(full_name, True); + safe_strcpy(acct_desc, pdb_get_acct_desc(sampass), sizeof(acct_desc)-1); + dos_to_unix(acct_desc, True); + + if( old ) { + /* name */ + if(strcmp(ENTRY_VAL(old, NPF_NAME), name)) + { + need_to_modify = True; + set_single_attribute(obj, NPF_NAME, name, strlen(name), + EN_MODIFIED); + } + + + /* uid */ + if(pdb_get_uid(sampass) != -1) { + if(!ENTRY_VAL(old, NPF_UID) || strcmp(ENTRY_VAL(old, NPF_UID), uid)) + { + need_to_modify = True; + set_single_attribute(obj, NPF_UID, uid, + strlen(uid), EN_MODIFIED); + } + } + + /* user_rid */ + if (pdb_get_user_rid(sampass)) { + if(!ENTRY_VAL(old, NPF_USER_RID) || + strcmp(ENTRY_VAL(old, NPF_USER_RID), user_rid) ) { + need_to_modify = True; + set_single_attribute(obj, NPF_USER_RID, user_rid, + strlen(user_rid), EN_MODIFIED); + } + } + + /* smb_grpid */ + if (pdb_get_gid(sampass) != -1) { + if(!ENTRY_VAL(old, NPF_SMB_GRPID) || + strcmp(ENTRY_VAL(old, NPF_SMB_GRPID), gid) ) { + need_to_modify = True; + set_single_attribute(obj, NPF_SMB_GRPID, gid, + strlen(gid), EN_MODIFIED); + } + } + + /* group_rid */ + if (pdb_get_group_rid(sampass)) { + if(!ENTRY_VAL(old, NPF_GROUP_RID) || + strcmp(ENTRY_VAL(old, NPF_GROUP_RID), group_rid) ) { + need_to_modify = True; + set_single_attribute(obj, NPF_GROUP_RID, group_rid, + strlen(group_rid), EN_MODIFIED); + } + } + + /* acb */ + if (!ENTRY_VAL(old, NPF_ACB) || + strcmp(ENTRY_VAL(old, NPF_ACB), acb)) { + need_to_modify = True; + set_single_attribute(obj, NPF_ACB, acb, strlen(acb), EN_MODIFIED); + } + + /* lmpwd */ + if(!ENTRY_VAL(old, NPF_LMPWD) || + strcmp(ENTRY_VAL(old, NPF_LMPWD), smb_passwd) ) { + need_to_modify = True; + set_single_attribute(obj, NPF_LMPWD, smb_passwd, + strlen(smb_passwd), EN_CRYPT|EN_MODIFIED); + } + + /* ntpwd */ + if(!ENTRY_VAL(old, NPF_NTPWD) || + strcmp(ENTRY_VAL(old, NPF_NTPWD), smb_nt_passwd) ) { + need_to_modify = True; + set_single_attribute(obj, NPF_NTPWD, smb_nt_passwd, + strlen(smb_nt_passwd), EN_CRYPT|EN_MODIFIED); + } + + /* logon_t */ + if( pdb_get_logon_time(sampass) && + (!ENTRY_VAL(old, NPF_LOGON_T) || + strcmp(ENTRY_VAL(old, NPF_LOGON_T), logon_t ))) { + need_to_modify = True; + set_single_attribute(obj, NPF_LOGON_T, logon_t, + strlen(logon_t), EN_MODIFIED); + } + + /* logoff_t */ + if( pdb_get_logoff_time(sampass) && + (!ENTRY_VAL(old, NPF_LOGOFF_T) || + strcmp(ENTRY_VAL(old, NPF_LOGOFF_T), logoff_t))) { + need_to_modify = True; + set_single_attribute(obj, NPF_LOGOFF_T, logoff_t, + strlen(logoff_t), EN_MODIFIED); + } + + /* kick_t */ + if( pdb_get_kickoff_time(sampass) && + (!ENTRY_VAL(old, NPF_KICK_T) || + strcmp(ENTRY_VAL(old, NPF_KICK_T), kickoff_t))) { + need_to_modify = True; + set_single_attribute(obj, NPF_KICK_T, kickoff_t, + strlen(kickoff_t), EN_MODIFIED); + } + + /* pwdlset_t */ + if( pdb_get_pass_last_set_time(sampass) && + (!ENTRY_VAL(old, NPF_PWDLSET_T) || + strcmp(ENTRY_VAL(old, NPF_PWDLSET_T), pwdlset_t))) { + need_to_modify = True; + set_single_attribute(obj, NPF_PWDLSET_T, pwdlset_t, + strlen(pwdlset_t), EN_MODIFIED); + } + + /* pwdlchg_t */ + if( pdb_get_pass_can_change_time(sampass) && + (!ENTRY_VAL(old, NPF_PWDCCHG_T) || + strcmp(ENTRY_VAL(old, NPF_PWDCCHG_T), pwdlchg_t))) { + need_to_modify = True; + set_single_attribute(obj, NPF_PWDCCHG_T, pwdlchg_t, + strlen(pwdlchg_t), EN_MODIFIED); + } + + /* pwdmchg_t */ + if( pdb_get_pass_must_change_time(sampass) && + (!ENTRY_VAL(old, NPF_PWDMCHG_T) || + strcmp(ENTRY_VAL(old, NPF_PWDMCHG_T), pwdmchg_t))) { + need_to_modify = True; + set_single_attribute(obj, NPF_PWDMCHG_T, pwdmchg_t, + strlen(pwdmchg_t), EN_MODIFIED); + } + + /* full_name */ + /* must support set, unset and change */ + if ( (pdb_get_fullname(sampass) && + !ENTRY_VAL(old, NPF_FULL_NAME)) || + (ENTRY_VAL(old, NPF_FULL_NAME) && + !pdb_get_fullname(sampass)) || + (ENTRY_VAL(old, NPF_FULL_NAME) && + pdb_get_fullname(sampass) && + strcmp( ENTRY_VAL(old, NPF_FULL_NAME), full_name ))) { + need_to_modify = True; + set_single_attribute(obj, NPF_FULL_NAME, full_name, + strlen(full_name), EN_MODIFIED); + } + + /* home_dir */ + /* must support set, unset and change */ + if( (pdb_get_homedir(sampass) && + !ENTRY_VAL(old, NPF_HOME_DIR)) || + (ENTRY_VAL(old, NPF_HOME_DIR) && + !pdb_get_homedir(sampass)) || + (ENTRY_VAL(old, NPF_HOME_DIR) && + pdb_get_homedir(sampass) && + strcmp( ENTRY_VAL(old, NPF_HOME_DIR), + pdb_get_homedir(sampass)))) { + need_to_modify = True; + set_single_attribute(obj, NPF_HOME_DIR, pdb_get_homedir(sampass), + strlen(pdb_get_homedir(sampass)), EN_MODIFIED); + } + + /* dir_drive */ + /* must support set, unset and change */ + if( (pdb_get_dirdrive(sampass) && + !ENTRY_VAL(old, NPF_DIR_DRIVE)) || + (ENTRY_VAL(old, NPF_DIR_DRIVE) && + !pdb_get_dirdrive(sampass)) || + (ENTRY_VAL(old, NPF_DIR_DRIVE) && + pdb_get_dirdrive(sampass) && + strcmp( ENTRY_VAL(old, NPF_DIR_DRIVE), + pdb_get_dirdrive(sampass)))) { + need_to_modify = True; + set_single_attribute(obj, NPF_DIR_DRIVE, pdb_get_dirdrive(sampass), + strlen(pdb_get_dirdrive(sampass)), EN_MODIFIED); + } + + /* logon_script */ + /* must support set, unset and change */ + if( (pdb_get_logon_script(sampass) && + !ENTRY_VAL(old, NPF_LOGON_SCRIPT) || + (ENTRY_VAL(old, NPF_LOGON_SCRIPT) && + !pdb_get_logon_script(sampass)) || + ( ENTRY_VAL(old, NPF_LOGON_SCRIPT) && + pdb_get_logon_script(sampass) && + strcmp( ENTRY_VAL(old, NPF_LOGON_SCRIPT), + pdb_get_logon_script(sampass))))) { + need_to_modify = True; + set_single_attribute(obj, NPF_LOGON_SCRIPT, + pdb_get_logon_script(sampass), + strlen(pdb_get_logon_script(sampass)), + EN_MODIFIED); + } + + /* profile_path */ + /* must support set, unset and change */ + if( (pdb_get_profile_path(sampass) && + !ENTRY_VAL(old, NPF_PROFILE_PATH)) || + (ENTRY_VAL(old, NPF_PROFILE_PATH) && + !pdb_get_profile_path(sampass)) || + (ENTRY_VAL(old, NPF_PROFILE_PATH) && + pdb_get_profile_path(sampass) && + strcmp( ENTRY_VAL(old, NPF_PROFILE_PATH), + pdb_get_profile_path(sampass) ) )) { + need_to_modify = True; + set_single_attribute(obj, NPF_PROFILE_PATH, + pdb_get_profile_path(sampass), + strlen(pdb_get_profile_path(sampass)), + EN_MODIFIED); + } + + /* acct_desc */ + /* must support set, unset and change */ + if( (pdb_get_acct_desc(sampass) && + !ENTRY_VAL(old, NPF_ACCT_DESC)) || + (ENTRY_VAL(old, NPF_ACCT_DESC) && + !pdb_get_acct_desc(sampass)) || + (ENTRY_VAL(old, NPF_ACCT_DESC) && + pdb_get_acct_desc(sampass) && + strcmp( ENTRY_VAL(old, NPF_ACCT_DESC), acct_desc ) )) { + need_to_modify = True; + set_single_attribute(obj, NPF_ACCT_DESC, acct_desc, + strlen(acct_desc), EN_MODIFIED); + } + + /* workstations */ + /* must support set, unset and change */ + if ( (pdb_get_workstations(sampass) && + !ENTRY_VAL(old, NPF_WORKSTATIONS) ) || + (ENTRY_VAL(old, NPF_WORKSTATIONS) && + !pdb_get_workstations(sampass)) || + (ENTRY_VAL(old, NPF_WORKSTATIONS) && + pdb_get_workstations(sampass)) && + strcmp( ENTRY_VAL(old, NPF_WORKSTATIONS), + pdb_get_workstations(sampass))) { + need_to_modify = True; + set_single_attribute(obj, NPF_WORKSTATIONS, + pdb_get_workstations(sampass), + strlen(pdb_get_workstations(sampass)), + EN_MODIFIED); + } + + /* hours */ + if ((pdb_get_hours_len(sampass) != ENTRY_LEN(old, NPF_HOURS)) || + memcmp(pdb_get_hours(sampass), ENTRY_VAL(old, NPF_HOURS), + ENTRY_LEN(old, NPF_HOURS))) { + need_to_modify = True; + /* set_single_attribute will add 1 for len ... */ + set_single_attribute(obj, NPF_HOURS, pdb_get_hours(sampass), + pdb_get_hours_len(sampass)-1, EN_MODIFIED); + } + } else { + char empty[1]; + char *homedir, *dirdrive, *logon_script, *profile_path, *workstations; + + *empty = '\0'; /* empty string */ + + set_single_attribute(obj, NPF_NAME, name, strlen(name), 0); + set_single_attribute(obj, NPF_UID, uid, strlen(uid), 0); + set_single_attribute(obj, NPF_USER_RID, user_rid, + strlen(user_rid), 0); + set_single_attribute(obj, NPF_SMB_GRPID, gid, strlen(gid), 0); + set_single_attribute(obj, NPF_GROUP_RID, group_rid, + strlen(group_rid), 0); + set_single_attribute(obj, NPF_ACB, acb, strlen(acb), 0); + set_single_attribute(obj, NPF_LMPWD, smb_passwd, + strlen(smb_passwd), EN_CRYPT); + set_single_attribute(obj, NPF_NTPWD, smb_nt_passwd, + strlen(smb_nt_passwd), EN_CRYPT); + set_single_attribute(obj, NPF_LOGON_T, logon_t, + strlen(logon_t), 0); + set_single_attribute(obj, NPF_LOGOFF_T, logoff_t, + strlen(logoff_t), 0); + set_single_attribute(obj, NPF_KICK_T, kickoff_t, + strlen(kickoff_t),0); + set_single_attribute(obj, NPF_PWDLSET_T, pwdlset_t, + strlen(pwdlset_t), 0); + set_single_attribute(obj, NPF_PWDCCHG_T, pwdlchg_t, + strlen(pwdlchg_t), 0); + set_single_attribute(obj, NPF_PWDMCHG_T, pwdmchg_t, + strlen(pwdmchg_t), 0); + set_single_attribute(obj, NPF_FULL_NAME , + full_name, strlen(full_name), 0); + + if(!(homedir = pdb_get_homedir(sampass))) + homedir = empty; + + set_single_attribute(obj, NPF_HOME_DIR, + homedir, strlen(homedir), 0); + + if(!(dirdrive = pdb_get_dirdrive(sampass))) + dirdrive = empty; + + set_single_attribute(obj, NPF_DIR_DRIVE, + dirdrive, strlen(dirdrive), 0); + + if(!(logon_script = pdb_get_logon_script(sampass))) + logon_script = empty; + + set_single_attribute(obj, NPF_LOGON_SCRIPT, + logon_script, strlen(logon_script), 0); + + if(!(profile_path = pdb_get_profile_path(sampass))) + profile_path = empty; + + set_single_attribute(obj, NPF_PROFILE_PATH, + profile_path, strlen(profile_path), 0); + + set_single_attribute(obj, NPF_ACCT_DESC, + acct_desc, strlen(acct_desc), 0); + + if(!(workstations = pdb_get_workstations(sampass))) + workstations = empty; + + set_single_attribute(obj, NPF_WORKSTATIONS, + workstations, strlen(workstations), 0); + + /* set_single_attribute will add 1 for len ... */ + set_single_attribute(obj, NPF_HOURS, + pdb_get_hours(sampass), + pdb_get_hours_len(sampass)-1, 0); + } + + return need_to_modify; +} + +/*************************************************************** + calls nis_list, returns results. + ****************************************************************/ +static nis_result *nisp_get_nis_list(char *nis_name, uint_t flags) +{ + nis_result *result; + int i; + + if( ! flags) + flags = FOLLOW_LINKS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP; + + for(i = 0; i<2;i++ ) { + alarm(60); /* hopefully ok for long searches */ + result = nis_list(nis_name, flags,NULL,NULL); + + alarm(0); + CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL); + + if (gotalarm) + { + DEBUG(0,("NIS+ lookup time out\n")); + nis_freeresult(result); + return NULL; + } + if( !(flags & MASTER_ONLY) && NIS_RES_NUMOBJ(result) <= 0 ) { + /* nis replicas are not in sync perhaps? + * this can happen, if account was just added. + */ + DEBUG(10,("will try master only\n")); + nis_freeresult(result); + flags |= MASTER_ONLY; + } else + break; + } + return result; +} + +/*************************************************************** + Start to enumerate the nisplus passwd list. + ****************************************************************/ +BOOL pdb_setsampwent(BOOL update) +{ + char *sp, * p = lp_smb_passwd_file(); + pstring pfiletmp; + + if( (sp = strrchr( p, '/' )) ) + safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); + else + safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); + + pdb_endsampwent(); /* just in case */ + global_nisp_ent.result = nisp_get_nis_list( pfiletmp, 0 ); + global_nisp_ent.enum_entry = 0; + return global_nisp_ent.result != NULL ? True : False; +} + +/*************************************************************** + End enumeration of the nisplus passwd list. +****************************************************************/ +void pdb_endsampwent(void) +{ + if( global_nisp_ent.result ) + nis_freeresult(global_nisp_ent.result); + global_nisp_ent.result = NULL; + global_nisp_ent.enum_entry = 0; +} + +/************************************************************************* + Routine to return the next entry in the nisplus passwd list. + *************************************************************************/ +BOOL pdb_getsampwent(SAM_ACCOUNT *user) +{ + int enum_entry = (int)(global_nisp_ent.enum_entry); + nis_result *result = global_nisp_ent.result; + + if (user==NULL) { + DEBUG(0,("SAM_ACCOUNT is NULL.\n")); + return False; + } + + if (result == NULL || + enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ(result) - 1)) + { + return False; + } + + if(!make_sam_from_nisp_object(user, &NIS_RES_OBJECT(result)[enum_entry]) ) + { + DEBUG(0,("Bad SAM_ACCOUNT entry returned from NIS+!\n")); + return False; + } + (int)(global_nisp_ent.enum_entry)++; + return True; +} + +/************************************************************************* + Routine to search the nisplus passwd file for an entry matching the username + *************************************************************************/ +BOOL pdb_getsampwnam(SAM_ACCOUNT * user, char *sname) +{ + /* Static buffers we will return. */ + nis_result *result = NULL; + pstring nisname; + BOOL ret; + char *pfile = lp_smb_passwd_file(); + int i; + + if (!*pfile) + { + DEBUG(0, ("No SMB password file set\n")); + return False; + } + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; + + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile); + DEBUG(10, ("search by nisname: %s\n", nisname)); + + /* Search the table. */ + + if(!(result = nisp_get_nis_list(nisname, 0))) + { + return False; + } + + ret = make_sam_from_nisresult(user, result); + nis_freeresult(result); + + return ret; +} + +/************************************************************************* + Routine to search the nisplus passwd file for an entry matching the username + *************************************************************************/ +BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid) +{ + nis_result *result; + char *nisname; + BOOL ret; + char *sp, *p = lp_smb_passwd_file(); + pstring pfiletmp; + + if (!*p) + { + DEBUG(0, ("no SMB password file set\n")); + return False; + } + + if( (sp = strrchr( p, '/' )) ) + safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); + else + safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); + + nisname = make_nisname_from_user_rid(rid, pfiletmp); + + DEBUG(10, ("search by rid: %s\n", nisname)); + + /* Search the table. */ + + if(!(result = nisp_get_nis_list(nisname, 0))) + { + return False; + } + + ret = make_sam_from_nisresult(user, result); + nis_freeresult(result); + + return ret; +} + +/************************************************************************* + Routine to search the nisplus passwd file for an entry matching the username + *************************************************************************/ +BOOL pdb_getsampwuid(SAM_ACCOUNT * user, uid_t uid) +{ + nis_result *result; + char *nisname; + BOOL ret; + char *sp, *p = lp_smb_passwd_file(); + pstring pfiletmp; + + if (!*p) + { + DEBUG(0, ("no SMB password file set\n")); + return False; + } + + if( (sp = strrchr( p, '/' )) ) + safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1); + else + safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1); + + nisname = make_nisname_from_uid(uid, pfiletmp); + + DEBUG(10, ("search by uid: %s\n", nisname)); + + /* Search the table. */ + + if(!(result = nisp_get_nis_list(nisname, 0))) + { + return False; + } + + ret = make_sam_from_nisresult(user, result); + nis_freeresult(result); + + return ret; +} + +/************************************************************************* + Routine to remove entry from the nisplus smbpasswd table + *************************************************************************/ +BOOL pdb_delete_sam_account(char *sname) +{ + char *pfile = lp_smb_passwd_file(); + pstring nisname; + nis_result *result, *delresult; + nis_object *obj; + int i; + + if (!*pfile) + { + DEBUG(0, ("no SMB password file set\n")); + return False; + } + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; + + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile); + + /* Search the table. */ + + if( !(result = nisp_get_nis_list(nisname, + MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\ + EXPAND_NAME|HARD_LOOKUP))) { + return False; + } + + if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { + /* User not found. */ + DEBUG(0,("user not found in NIS+\n")); + nis_freeresult(result); + return False; + } + + obj = NIS_RES_OBJECT(result); + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", sname, obj->zo_name, + obj->zo_domain); + + DEBUG(10, ("removing name: %s\n", nisname)); + delresult = nis_remove_entry(nisname, obj, + MASTER_ONLY|REM_MULTIPLE|ALL_RESULTS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); + + nis_freeresult(result); + + if(delresult->status != NIS_SUCCESS) { + DEBUG(0, ("NIS+ table update failed: %s %s\n", + nisname, nis_sperrno(delresult->status))); + nis_freeresult(delresult); + return False; + } + nis_freeresult(delresult); + return True; +} + +/************************************************************************ + Routine to add an entry to the nisplus passwd file. +*************************************************************************/ +BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd) +{ + int local_user = 0; + char *pfile; + pstring pfiletmp; + char *nisname; + nis_result *result = NULL, + *tblresult = NULL; + nis_object new_obj; + entry_col *ecol; + int ta_maxcol; + + /* + * 1. find user domain. + * a. try nis search in passwd.org_dir - if found use domain from result. + * b. try getpwnam. this may be needed if user is defined + * in /etc/passwd file (or elsewere) and not in passwd.org_dir. + * if found, use host default domain. + * c. exit with False - no such user. + * + * 2. add user + * a. find smbpasswd table + * search pfile in user domain if not found, try host default + * domain. + * b. smbpasswd domain is found, fill data and add entry. + * + * pfile should contain ONLY table name, org_dir will be concated. + * so, at first we will clear path prefix from pfile, and + * then we will use pfiletmp as playground to put together full + * nisname string. + * such approach will make it possible to specify samba private dir + * AND still use NIS+ table. as all domain related data is normally + * stored in org_dir.DOMAIN, this should be ok do do. + */ + + pfile = lp_smb_passwd_file(); + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; + + /* + * Check if user is already there. + */ + safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", + sizeof(pfiletmp)-strlen(pfiletmp)-1); + + if(pdb_get_username(newpwd) != NULL) { + nisname = make_nisname_from_name(pdb_get_username(newpwd), + pfiletmp); + } else { + return False; + } + + if(!(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) { + return False; + } + if (result->status != NIS_SUCCESS && + result->status != NIS_NOTFOUND) { + DEBUG(3, ( "nis_list failure: %s: %s\n", + nisname, nis_sperrno(result->status))); + nis_freeresult(result); + return False; + } + + if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0) + { + DEBUG(3, ("User already exists in NIS+ password db: %s\n", + pfile)); + nis_freeresult(result); + return False; + } + + nis_freeresult(result); /* no such user, free results */ + + /* + * check for user in unix password database. we need this to get + * domain, where smbpasswd entry should be stored. + */ + + nisname = make_nisname_from_name(pdb_get_username(newpwd), + "passwd.org_dir"); + + result = nisp_get_nis_list(nisname, + MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\ + EXPAND_NAME|HARD_LOOKUP); + + if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) + { + DEBUG(3, ("nis_list failure: %s: %s\n", + nisname, nis_sperrno(result->status))); + nis_freeresult(result); + + if (!sys_getpwnam(pdb_get_username(newpwd))) { + /* no such user in system! */ + return False; + } + /* + * user is defined, but not in passwd.org_dir. + */ + local_user = 1; + } else { + safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1); + safe_strcat(pfiletmp, NIS_RES_OBJECT(result)->zo_domain, + sizeof(pfiletmp)-strlen(pfiletmp)-1); + nis_freeresult(result); /* not needed any more */ + + tblresult = nisp_get_nis_list(pfiletmp, + MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); + } + + if (local_user || tblresult->status != NIS_SUCCESS) + { + /* + * no user domain or + * smbpasswd table not found in user domain, fallback to + * default domain. + */ + if (!local_user) /* free previous failed search result */ + nis_freeresult(tblresult); + + safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".org_dir", + sizeof(pfiletmp)-strlen(pfiletmp)-1); + tblresult = nis_lookup(pfiletmp, MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); + if (tblresult->status != NIS_SUCCESS) + { + /* still nothing. bail out */ + nis_freeresult(tblresult); + DEBUG(3, ( "nis_lookup failure: %s\n", + nis_sperrno(tblresult->status))); + return False; + } + /* we need full name for nis_add_entry() */ + safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1); + safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1); + safe_strcat(pfiletmp, NIS_RES_OBJECT(tblresult)->zo_domain, + sizeof(pfiletmp)-strlen(pfiletmp)-1); + } + + memset((char *)&new_obj, 0, sizeof (new_obj)); + /* fill entry headers */ + /* we do not free these. */ + new_obj.zo_name = NIS_RES_OBJECT(tblresult)->zo_name; + new_obj.zo_owner = NIS_RES_OBJECT(tblresult)->zo_owner; + new_obj.zo_group = NIS_RES_OBJECT(tblresult)->zo_group; + new_obj.zo_domain = NIS_RES_OBJECT(tblresult)->zo_domain; + /* uints */ + new_obj.zo_access = NIS_RES_OBJECT(tblresult)->zo_access; + new_obj.zo_ttl = NIS_RES_OBJECT(tblresult)->zo_ttl; + + new_obj.zo_data.zo_type = ENTRY_OBJ; + new_obj.EN_data.en_type = + NIS_RES_OBJECT(tblresult)->TA_data.ta_type; + + ta_maxcol = NIS_RES_OBJECT(tblresult)->TA_data.ta_maxcol; + + if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) { + DEBUG(0, ("memory allocation failure\n")); + nis_freeresult(tblresult); + return False; + } + + memset((char *)ecol, 0, ta_maxcol*sizeof (entry_col)); + new_obj.EN_data.en_cols.en_cols_val = ecol; + new_obj.EN_data.en_cols.en_cols_len = ta_maxcol; + + init_nisp_from_sam(&new_obj, newpwd, NULL); + + DEBUG(10, ( "add NIS+ entry: %s\n", nisname)); + result = nis_add_entry(pfiletmp, &new_obj, 0); + + free(ecol); /* free allocated entry space */ + + if (result->status != NIS_SUCCESS) + { + DEBUG(3, ( "NIS+ table update failed: %s\n", + nisname, nis_sperrno(result->status))); + nis_freeresult(tblresult); + nis_freeresult(result); + return False; + } + + nis_freeresult(tblresult); + nis_freeresult(result); + + return True; +} + +/************************************************************************ + Routine to modify the nisplus passwd entry. +************************************************************************/ +BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd, BOOL override) +{ + nis_result *result, *addresult; + nis_object *obj; + nis_object new_obj; + entry_col *ecol; + int ta_maxcol; + char *pfile = lp_smb_passwd_file(); + pstring nisname; + int i; + + if (!*pfile) + { + DEBUG(0, ("no SMB password file set\n")); + return False; + } + if( strrchr( pfile, '/') ) + pfile = strrchr( pfile, '/') + 1; + + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", + pdb_get_username(newpwd), pfile); + + DEBUG(10, ("search by name: %s\n", nisname)); + + /* Search the table. */ + + if( !(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\ + FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) { + return False; + } + + if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) { + /* User not found. */ + DEBUG(0,("user not found in NIS+\n")); + nis_freeresult(result); + return False; + } + + obj = NIS_RES_OBJECT(result); + DEBUG(6,("entry found in %s\n", obj->zo_domain)); + + /* we must create new stub object with EN_MODIFIED flag. + this is because obj from result is going to be freed and + we do not want to break it or cause memory leaks or corruption. + */ + + memmove((char *)&new_obj, obj, sizeof (new_obj)); + ta_maxcol = obj->TA_data.ta_maxcol; + + if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) { + DEBUG(0, ("memory allocation failure\n")); + nis_freeresult(result); + return False; + } + + memmove((char *)ecol, obj->EN_data.en_cols.en_cols_val, + ta_maxcol*sizeof (entry_col)); + new_obj.EN_data.en_cols.en_cols_val = ecol; + new_obj.EN_data.en_cols.en_cols_len = ta_maxcol; + + if ( init_nisp_from_sam(&new_obj, newpwd, obj) == True ) { + slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", + pdb_get_username(newpwd), pfile, obj->zo_domain); + + DEBUG(10, ("NIS+ table update: %s\n", nisname)); + addresult = + nis_modify_entry(nisname, &new_obj, + MOD_SAMEOBJ | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP); + + if(addresult->status != NIS_SUCCESS) { + DEBUG(0, ("NIS+ table update failed: %s %s\n", + nisname, nis_sperrno(addresult->status))); + nis_freeresult(addresult); + nis_freeresult(result); + free(ecol); + return False; + } + + DEBUG(6,("password changed\n")); + nis_freeresult(addresult); + } else { + DEBUG(6,("nothing to change!\n")); + } + + free(ecol); + nis_freeresult(result); + + return True; +} + +#else + void nisplus_dummy_function(void); + void nisplus_dummy_function(void) { } /* stop some compilers complaining */ +#endif /* WITH_NISPLUSSAM */ + diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c index 7c95feb8ca6..bca7541782a 100644 --- a/source/passdb/pdb_smbpasswd.c +++ b/source/passdb/pdb_smbpasswd.c @@ -22,7 +22,7 @@ #include "includes.h" -#ifdef USE_SMBPASS_DB +#ifdef WITH_SMBPASSWD_SAM /* @@ -54,10 +54,6 @@ extern struct passdb_ops pdb_ops; static int pw_file_lock_depth; static void *global_vp; -/* static memory area used by all passdb search functions - in this module */ -/*static SAM_ACCOUNT global_sam_pass;*/ - enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE }; @@ -414,7 +410,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp) pw_buf.smb_passwd = NULL; pw_buf.acct_ctrl |= ACB_PWNOTREQ; } else { - if (!smbpasswd_gethexpwd((char *)p, smbpwd)) { + if (!pdb_gethexpwd((char *)p, smbpwd)) { DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n")); continue; } @@ -431,7 +427,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp) the lanman password. */ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { if (*p != '*' && *p != 'X') { - if(smbpasswd_gethexpwd((char *)p,smbntpwd)) + if(pdb_gethexpwd((char *)p,smbntpwd)) pw_buf.smb_nt_passwd = smbntpwd; } p += 33; /* Move to the first character of the line after @@ -444,7 +440,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp) if (*p == '[') { unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']'); - pw_buf.acct_ctrl = smbpasswd_decode_acb_info((char*)p); + pw_buf.acct_ctrl = pdb_decode_acct_ctrl((char*)p); /* Must have some account type set. */ if(pw_buf.acct_ctrl == 0) @@ -545,8 +541,8 @@ static char *format_new_smbpasswd_entry(struct smb_passwd *newpwd) *p++ = ':'; /* Add the account encoding and the last change time. */ - slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n", - smbpasswd_encode_acb_info(newpwd->acct_ctrl), + slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n", + pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)newpwd->pass_last_set_time); return new_entry; @@ -640,11 +636,11 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n", } endsmbfilepwent(fp, &pw_file_lock_depth); - SAFE_FREE(new_entry); + free(new_entry); return False; } - SAFE_FREE(new_entry); + free(new_entry); endsmbfilepwent(fp, &pw_file_lock_depth); return True; } @@ -903,7 +899,7 @@ static BOOL mod_smbfilepwd_entry(struct smb_passwd* pwd, BOOL override) * acct ctrl field. Encode the given acct ctrl * bits into it. */ - fstrcpy(encode_bits, smbpasswd_encode_acb_info(pwd->acct_ctrl)); + fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN)); } else { /* * If using the old format and the ACB_DISABLED or @@ -1121,11 +1117,11 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); unlink(pfile2); endsmbfilepwent(fp, &pw_file_lock_depth); endsmbfilepwent(fp_write, &pfile2_lockdepth); - SAFE_FREE(new_entry); + free(new_entry); return False; } - SAFE_FREE(new_entry); + free(new_entry); } /* @@ -1298,7 +1294,6 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) { struct smb_passwd *pw_buf=NULL; BOOL done = False; - DEBUG(5,("pdb_getsampwent\n")); if (user==NULL) { @@ -1309,11 +1304,6 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) return False; } - /* do we have an entry? */ - pw_buf = getsmbfilepwent(global_vp); - if (pw_buf == NULL) - return False; - while (!done) { /* do we have an entry? */ @@ -1530,4 +1520,4 @@ BOOL pdb_delete_sam_account (char* username) #else /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */ void smbpass_dummy_function(void) { } /* stop some compilers complaining */ -#endif /* USE_SMBPASS_DB */ +#endif /* WTH_SMBPASSWD_SAM*/ diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c index cf2a7f2ec11..700a241be87 100644 --- a/source/passdb/pdb_tdb.c +++ b/source/passdb/pdb_tdb.c @@ -3,6 +3,7 @@ * Copyright (C) Andrew Tridgell 1992-1998 * Copyright (C) Simo Sorce 2000 * Copyright (C) Gerald Carter 2000 + * Copyright (C) Jeremy Allison 2001 * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free @@ -21,7 +22,7 @@ #include "includes.h" -#ifdef WITH_TDBSAM +#ifdef WITH_TDB_SAM #define PDB_VERSION "20010830" #define PASSDB_FILE_NAME "/passdb.tdb" @@ -33,9 +34,7 @@ extern int DEBUGLEVEL; extern pstring samlogon_user; extern BOOL sam_logon_in_ssb; - -struct tdb_enum_info -{ +struct tdb_enum_info { TDB_CONTEXT *passwd_tdb; TDB_DATA key; }; @@ -46,8 +45,8 @@ static struct tdb_enum_info global_tdb_ent; /********************************************************************** Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len *********************************************************************/ -static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, - uint32 buflen) + +static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { /* times are stored as 32bit integer @@ -79,11 +78,10 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 /* uid, gid,*/ user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6; uint16 acct_ctrl, logon_divs; uint8 *hours; - static uint8 *lm_pw_ptr, - *nt_pw_ptr; + static uint8 *lm_pw_ptr, *nt_pw_ptr; uint32 len = 0; uint32 lmpwlen, ntpwlen, hourslen; - + BOOL ret = True; /* unpack the buffer into variables */ len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING, @@ -117,8 +115,10 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, &unknown_5, &unknown_6); - if (len == -1) - return False; + if (len == -1) { + ret = False; + goto done; + } pdb_set_logon_time(sampass, logon_time); pdb_set_logoff_time(sampass, logoff_time); @@ -153,9 +153,21 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, pdb_set_logons_divs(sampass, logon_divs); pdb_set_hours(sampass, hours); - /* TODO: free TDB alloced memory !!!!! */ - - return True; +done: + + SAFE_FREE(username); + SAFE_FREE(domain); + SAFE_FREE(nt_username); + SAFE_FREE(fullname); + SAFE_FREE(homedir); + SAFE_FREE(dir_drive); + SAFE_FREE(logon_script); + SAFE_FREE(profile_path); + SAFE_FREE(acct_desc); + SAFE_FREE(workstations); + SAFE_FREE(munged_dial); + + return ret; } /********************************************************************** @@ -203,56 +215,80 @@ static uint32 init_buffer_from_sam (uint8 **buf, SAM_ACCOUNT *sampass) *buf = NULL; buflen = 0; - logon_time = pdb_get_logon_time(sampass); - logoff_time = pdb_get_logoff_time(sampass); - kickoff_time = pdb_get_kickoff_time(sampass); - pass_can_change_time = pdb_get_pass_can_change_time(sampass); - pass_must_change_time = pdb_get_pass_must_change_time(sampass); - pass_last_set_time = pdb_get_pass_last_set_time(sampass); + logon_time = (uint32)pdb_get_logon_time(sampass); + logoff_time = (uint32)pdb_get_logoff_time(sampass); + kickoff_time = (uint32)pdb_get_kickoff_time(sampass); + pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass); + pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass); + pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass); username = pdb_get_username(sampass); - if (username) username_len = strlen(username) +1; - else username_len = 0; + if (username) + username_len = strlen(username) +1; + else + username_len = 0; domain = pdb_get_domain(sampass); - if (domain) domain_len = strlen(domain) +1; - else domain_len = 0; + if (domain) + domain_len = strlen(domain) +1; + else + domain_len = 0; nt_username = pdb_get_nt_username(sampass); - if (nt_username) nt_username_len = strlen(nt_username) +1; - else nt_username_len = 0; + if (nt_username) + nt_username_len = strlen(nt_username) +1; + else + nt_username_len = 0; dir_drive = pdb_get_dirdrive(sampass); - if (dir_drive) dir_drive_len = strlen(dir_drive) +1; - else dir_drive_len = 0; + if (dir_drive) + dir_drive_len = strlen(dir_drive) +1; + else + dir_drive_len = 0; unknown_str = NULL; unknown_str_len = 0; munged_dial = pdb_get_munged_dial(sampass); - if (munged_dial) munged_dial_len = strlen(munged_dial) +1; - else munged_dial_len = 0; + if (munged_dial) + munged_dial_len = strlen(munged_dial) +1; + else + munged_dial_len = 0; fullname = pdb_get_fullname(sampass); - if (fullname) fullname_len = strlen(fullname) +1; - else fullname_len = 0; + if (fullname) + fullname_len = strlen(fullname) +1; + else + fullname_len = 0; homedir = pdb_get_homedir(sampass); - if (homedir) homedir_len = strlen(homedir) +1; - else homedir_len = 0; + if (homedir) + homedir_len = strlen(homedir) +1; + else + homedir_len = 0; logon_script = pdb_get_logon_script(sampass); - if (logon_script) logon_script_len = strlen(logon_script) +1; - else logon_script_len = 0; + if (logon_script) + logon_script_len = strlen(logon_script) +1; + else + logon_script_len = 0; profile_path = pdb_get_profile_path(sampass); - if (profile_path) profile_path_len = strlen(profile_path) +1; - else profile_path_len = 0; + if (profile_path) + profile_path_len = strlen(profile_path) +1; + else + profile_path_len = 0; acct_desc = pdb_get_acct_desc(sampass); - if (acct_desc) acct_desc_len = strlen(acct_desc) +1; - else acct_desc_len = 0; + if (acct_desc) + acct_desc_len = strlen(acct_desc) +1; + else + acct_desc_len = 0; workstations = pdb_get_workstations(sampass); - if (workstations) workstations_len = strlen(workstations) +1; - else workstations_len = 0; + if (workstations) + workstations_len = strlen(workstations) +1; + else + workstations_len = 0; lm_pw = pdb_get_lanman_passwd(sampass); - if (!lm_pw) lm_pw_len = 0; + if (!lm_pw) + lm_pw_len = 0; nt_pw = pdb_get_nt_passwd(sampass); - if (!nt_pw) nt_pw_len = 0; + if (!nt_pw) + nt_pw_len = 0; /* one time to get the size needed */ len = tdb_pack(NULL, 0, TDB_FORMAT_STRING, @@ -288,8 +324,7 @@ static uint32 init_buffer_from_sam (uint8 **buf, SAM_ACCOUNT *sampass) /* malloc the space needed */ - if ( (*buf=(uint8*)malloc(len)) == NULL) - { + if ( (*buf=(uint8*)malloc(len)) == NULL) { DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); return (-1); } @@ -328,8 +363,7 @@ static uint32 init_buffer_from_sam (uint8 **buf, SAM_ACCOUNT *sampass) /* check to make sure we got it correct */ - if (buflen != len) - { + if (buflen != len) { /* error */ SAFE_FREE (*buf); return (-1); @@ -341,19 +375,18 @@ static uint32 init_buffer_from_sam (uint8 **buf, SAM_ACCOUNT *sampass) /*************************************************************** Open the TDB passwd database for SAM account enumeration. ****************************************************************/ + BOOL pdb_setsampwent(BOOL update) { pstring tdbfile; - pstrcpy (tdbfile, lp_private_dir()); + get_private_directory(tdbfile); pstrcat (tdbfile, PASSDB_FILE_NAME); /* Open tdb passwd */ - if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update ? O_RDWR : O_RDONLY, 0600))) - { + if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update ? O_RDWR : O_RDONLY, 0600))) { DEBUG(0, ("Unable to open TDB passwd, trying create new!\n")); - if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) - { + if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) { DEBUG(0, ("Unable to create TDB passwd (passdb.tdb) !!!")); return False; } @@ -367,10 +400,10 @@ BOOL pdb_setsampwent(BOOL update) /*************************************************************** End enumeration of the TDB passwd list. ****************************************************************/ + void pdb_endsampwent(void) { - if (global_tdb_ent.passwd_tdb) - { + if (global_tdb_ent.passwd_tdb) { tdb_close(global_tdb_ent.passwd_tdb); global_tdb_ent.passwd_tdb = NULL; } @@ -378,10 +411,10 @@ void pdb_endsampwent(void) DEBUG(7, ("endtdbpwent: closed password file.\n")); } - /***************************************************************** Get one SAM_ACCOUNT from the TDB (next in line) *****************************************************************/ + BOOL pdb_getsampwent(SAM_ACCOUNT *user) { TDB_DATA data; @@ -402,22 +435,19 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) global_tdb_ent.key = tdb_nextkey (global_tdb_ent.passwd_tdb, global_tdb_ent.key); /* do we have an valid interation pointer? */ - if(global_tdb_ent.passwd_tdb == NULL) - { + if(global_tdb_ent.passwd_tdb == NULL) { DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n")); return False; } data = tdb_fetch (global_tdb_ent.passwd_tdb, global_tdb_ent.key); - if (!data.dptr) - { + if (!data.dptr) { DEBUG(5,("pdb_getsampwent: database entry not found.\n")); return False; } /* unpack the buffer */ - if (!init_sam_from_buffer (user, data.dptr, data.dsize)) - { + if (!init_sam_from_buffer (user, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); return False; @@ -427,8 +457,7 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) /* validate the account and fill in UNIX uid and gid. sys_getpwnam() is used instaed of Get_Pwnam() as we do not need to try case permutations */ - if ((pw=sys_getpwnam(pdb_get_username(user))) == NULL) - { + if ((pw=sys_getpwnam(pdb_get_username(user))) == NULL) { DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n", pdb_get_username(user))); return False; @@ -455,6 +484,7 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user) /****************************************************************** Lookup a name in the SAM TDB ******************************************************************/ + BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname) { TDB_CONTEXT *pwd_tdb; @@ -473,8 +503,7 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname) } fstrcpy (name, sname); - strlower (name); - pstrcpy (tdbfile, lp_private_dir()); + get_private_directory(tdbfile); pstrcat (tdbfile, PASSDB_FILE_NAME); /* set search key */ @@ -483,16 +512,14 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname) key.dsize = strlen (keystr) + 1; /* open the accounts TDB */ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) - { + if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) { DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd!\n")); return False; } /* get the record */ data = tdb_fetch (pwd_tdb, key); - if (!data.dptr) - { + if (!data.dptr) { DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n")); DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); tdb_close (pwd_tdb); @@ -500,8 +527,7 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname) } /* unpack the buffer */ - if (!init_sam_from_buffer (user, data.dptr, data.dsize)) - { + if (!init_sam_from_buffer (user, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); return False; @@ -511,8 +537,7 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname) /* validate the account and fill in UNIX uid and gid. sys_getpwnam() is used instaed of Get_Pwnam() as we do not need to try case permutations */ - if ((pw=sys_getpwnam(pdb_get_username(user))) == NULL) - { + if ((pw=sys_getpwnam(pdb_get_username(user))) == NULL) { DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n", pdb_get_username(user))); return False; @@ -539,6 +564,7 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, char *sname) /*************************************************************************** Search by uid **************************************************************************/ + BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid) { struct passwd *pw; @@ -550,8 +576,7 @@ BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid) } pw = sys_getpwuid(uid); - if (pw == NULL) - { + if (pw == NULL) { DEBUG(0,("pdb_getsampwuid: getpwuid(%d) return NULL. User does not exist!\n", uid)); return False; } @@ -564,6 +589,7 @@ BOOL pdb_getsampwuid (SAM_ACCOUNT* user, uid_t uid) /*************************************************************************** Search by rid **************************************************************************/ + BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) { TDB_CONTEXT *pwd_tdb; @@ -577,7 +603,7 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) return False; } - pstrcpy (tdbfile, lp_private_dir()); + get_private_directory(tdbfile); pstrcat (tdbfile, PASSDB_FILE_NAME); /* set search key */ @@ -586,16 +612,14 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) key.dsize = strlen (keystr) + 1; /* open the accounts TDB */ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) - { + if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) { DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n")); return False; } /* get the record */ data = tdb_fetch (pwd_tdb, key); - if (!data.dptr) - { + if (!data.dptr) { DEBUG(5,("pdb_getsampwrid (TDB): error fetching database.\n")); DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); tdb_close (pwd_tdb); @@ -610,10 +634,10 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid) return pdb_getsampwnam (user, name); } - /*************************************************************************** Delete a SAM_ACCOUNT ****************************************************************************/ + BOOL pdb_delete_sam_account(char *sname) { SAM_ACCOUNT *sam_pass = NULL; @@ -627,12 +651,11 @@ BOOL pdb_delete_sam_account(char *sname) fstrcpy (name, sname); strlower (name); - pstrcpy (tdbfile, lp_private_dir()); + get_private_directory(tdbfile); pstrcat (tdbfile, PASSDB_FILE_NAME); /* open the TDB */ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) - { + if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) { DEBUG(0, ("Unable to open TDB passwd!")); return False; } @@ -644,8 +667,7 @@ BOOL pdb_delete_sam_account(char *sname) /* get the record */ data = tdb_fetch (pwd_tdb, key); - if (!data.dptr) - { + if (!data.dptr) { DEBUG(5,("pdb_delete_sam_account (TDB): error fetching database.\n")); DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); tdb_close (pwd_tdb); @@ -653,14 +675,12 @@ BOOL pdb_delete_sam_account(char *sname) } /* unpack the buffer */ - if (!pdb_init_sam (&sam_pass)) - { + if (!pdb_init_sam (&sam_pass)) { tdb_close (pwd_tdb); return False; } - if (!init_sam_from_buffer (sam_pass, data.dptr, data.dsize)) - { + if (!init_sam_from_buffer (sam_pass, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); tdb_close (pwd_tdb); SAFE_FREE(data.dptr); @@ -673,8 +693,7 @@ BOOL pdb_delete_sam_account(char *sname) pdb_free_sam (sam_pass); /* it's outaa here! 8^) */ - if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) - { + if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) { DEBUG(5, ("Error deleting entry from tdb passwd database!\n")); DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); tdb_close(pwd_tdb); @@ -689,8 +708,7 @@ BOOL pdb_delete_sam_account(char *sname) key.dsize = strlen (keystr) + 1; /* it's outaa here! 8^) */ - if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) - { + if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) { DEBUG(5, ("Error deleting entry from tdb rid database!\n")); DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb))); tdb_close(pwd_tdb); @@ -705,6 +723,7 @@ BOOL pdb_delete_sam_account(char *sname) /*************************************************************************** Update the TDB SAM ****************************************************************************/ + static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) { TDB_CONTEXT *pwd_tdb; @@ -716,7 +735,7 @@ static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) BOOL ret = True; int newtdb = FALSE; - pstrcpy (tdbfile, lp_private_dir()); + get_private_directory(tdbfile); pstrcat (tdbfile, PASSDB_FILE_NAME); if ( (!newpwd->uid) || (!newpwd->gid) ) @@ -729,10 +748,8 @@ static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) if (!newpwd->group_rid) pdb_set_group_rid (newpwd, pdb_gid_to_group_rid (newpwd->gid)); - /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */ - if ((data.dsize=init_buffer_from_sam (&buf, newpwd)) == -1) - { + if ((data.dsize=init_buffer_from_sam (&buf, newpwd)) == -1) { DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n")); ret = False; goto done; @@ -748,21 +765,17 @@ static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) key.dsize = strlen (keystr) + 1; /* invalidate the existing TDB iterator if it is open */ - if (global_tdb_ent.passwd_tdb) - { + if (global_tdb_ent.passwd_tdb) { tdb_close(global_tdb_ent.passwd_tdb); global_tdb_ent.passwd_tdb = NULL; } /* open the account TDB passwd*/ - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) - { - DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd!\n")); - if (flag == TDB_INSERT) - { + if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) { + DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd!\n")); + if (flag == TDB_INSERT) { DEBUG(0, ("Unable to open TDB passwd, trying create new!\n")); - if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) - { + if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600))) { DEBUG(0, ("Unable to create TDB passwd (passdb.tdb) !!!\n")); ret = False; goto done; @@ -772,8 +785,7 @@ static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) } /* add the account */ - if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) - { + if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) { DEBUG(0, ("Unable to modify passwd TDB!")); DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb))); tdb_close (pwd_tdb); @@ -791,8 +803,7 @@ static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) key.dsize = strlen (keystr) + 1; /* add the reference */ - if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) - { + if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) { DEBUG(0, ("Unable to modify TDB passwd !")); DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb))); ret = False; @@ -800,17 +811,17 @@ static BOOL tdb_update_sam(SAM_ACCOUNT* newpwd, BOOL override, int flag) } done: + /* cleanup */ tdb_close (pwd_tdb); SAFE_FREE(buf); - return (ret); - } /*************************************************************************** Modifies an existing SAM_ACCOUNT ****************************************************************************/ + BOOL pdb_update_sam_account (SAM_ACCOUNT *newpwd, BOOL override) { return (tdb_update_sam(newpwd, override, TDB_MODIFY)); @@ -819,13 +830,13 @@ BOOL pdb_update_sam_account (SAM_ACCOUNT *newpwd, BOOL override) /*************************************************************************** Adds an existing SAM_ACCOUNT ****************************************************************************/ + BOOL pdb_add_sam_account (SAM_ACCOUNT *newpwd) { return (tdb_update_sam(newpwd, True, TDB_INSERT)); } - #else /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */ void samtdb_dummy_function(void) { } /* stop some compilers complaining */ -#endif /* WITH_TDBSAM */ +#endif /* WITH_TDB_SAM */ -- cgit