📄 smbldap.c
字号:
/* Unix SMB/CIFS implementation. LDAP protocol helper functions for SAMBA Copyright (C) Jean François Micouleau 1998 Copyright (C) Gerald Carter 2001-2003 Copyright (C) Shahms King 2001 Copyright (C) Andrew Bartlett 2002-2003 Copyright (C) Stefan (metze) Metzmacher 2002-2003 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"#include "smbldap.h"#ifndef LDAP_OPT_SUCCESS#define LDAP_OPT_SUCCESS 0#endif/* Try not to hit the up or down server forever */#define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */#define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */#define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect *//* attributes used by Samba 2.2 */ATTRIB_MAP_ENTRY attrib_map_v22[] = { { LDAP_ATTR_UID, "uid" }, { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, { LDAP_ATTR_LOGON_TIME, "logonTime" }, { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, { LDAP_ATTR_CN, "cn" }, { LDAP_ATTR_DISPLAY_NAME, "displayName" }, { LDAP_ATTR_HOME_PATH, "smbHome" }, { LDAP_ATTR_HOME_DRIVE, "homeDrive" }, { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, { LDAP_ATTR_PROFILE_PATH, "profilePath" }, { LDAP_ATTR_DESC, "description" }, { LDAP_ATTR_USER_WKS, "userWorkstations"}, { LDAP_ATTR_USER_RID, "rid" }, { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, { LDAP_ATTR_LMPW, "lmPassword" }, { LDAP_ATTR_NTPW, "ntPassword" }, { LDAP_ATTR_DOMAIN, "domain" }, { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_ACB_INFO, "acctFlags" }, { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" }, { LDAP_ATTR_LIST_END, NULL }};ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[] = { { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, { LDAP_ATTR_LOGON_TIME, "logonTime" }, { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, { LDAP_ATTR_DISPLAY_NAME, "displayName" }, { LDAP_ATTR_HOME_PATH, "smbHome" }, { LDAP_ATTR_HOME_DRIVE, "homeDrives" }, { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, { LDAP_ATTR_PROFILE_PATH, "profilePath" }, { LDAP_ATTR_USER_WKS, "userWorkstations"}, { LDAP_ATTR_USER_RID, "rid" }, { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, { LDAP_ATTR_LMPW, "lmPassword" }, { LDAP_ATTR_NTPW, "ntPassword" }, { LDAP_ATTR_DOMAIN, "domain" }, { LDAP_ATTR_ACB_INFO, "acctFlags" }, { LDAP_ATTR_LIST_END, NULL }};/* attributes used by Samba 3.0's sambaSamAccount */ATTRIB_MAP_ENTRY attrib_map_v30[] = { { LDAP_ATTR_UID, "uid" }, { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, { LDAP_ATTR_CN, "cn" }, { LDAP_ATTR_DISPLAY_NAME, "displayName" }, { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, { LDAP_ATTR_DESC, "description" }, { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, { LDAP_ATTR_LMPW, "sambaLMPassword" }, { LDAP_ATTR_NTPW, "sambaNTPassword" }, { LDAP_ATTR_DOMAIN, "sambaDomainName" }, { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" }, { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" }, { LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" }, { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" }, { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" }, { LDAP_ATTR_LOGON_HOURS, "sambaLogonHours" }, { LDAP_ATTR_LIST_END, NULL }};ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[] = { { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, { LDAP_ATTR_LMPW, "sambaLMPassword" }, { LDAP_ATTR_NTPW, "sambaNTPassword" }, { LDAP_ATTR_DOMAIN, "sambaDomainName" }, { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" }, { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" }, { LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" }, { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" }, { LDAP_ATTR_LOGON_HOURS, "sambaLogonHours" }, { LDAP_ATTR_LIST_END, NULL }};/* attributes used for allocating RIDs */ATTRIB_MAP_ENTRY dominfo_attr_list[] = { { LDAP_ATTR_DOMAIN, "sambaDomainName" }, { LDAP_ATTR_NEXT_RID, "sambaNextRid" }, { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, { LDAP_ATTR_DOM_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"}, { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL },};/* Samba 3.0 group mapping attributes */ATTRIB_MAP_ENTRY groupmap_attr_list[] = { { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, { LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, { LDAP_ATTR_SID_LIST, "sambaSIDList" }, { LDAP_ATTR_DESC, "description" }, { LDAP_ATTR_DISPLAY_NAME, "displayName" }, { LDAP_ATTR_CN, "cn" }, { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL } };ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { { LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, { LDAP_ATTR_DESC, "description" }, { LDAP_ATTR_DISPLAY_NAME, "displayName" }, { LDAP_ATTR_SID_LIST, "sambaSIDList" }, { LDAP_ATTR_LIST_END, NULL } };/* idmap_ldap sambaUnixIdPool */ATTRIB_MAP_ENTRY idpool_attr_list[] = { { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL } };ATTRIB_MAP_ENTRY sidmap_attr_list[] = { { LDAP_ATTR_SID, LDAP_ATTRIBUTE_SID }, { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, { LDAP_ATTR_OBJCLASS, "objectClass" }, { LDAP_ATTR_LIST_END, NULL } };/********************************************************************** perform a simple table lookup and return the attribute name **********************************************************************/ const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ){ int i = 0; while ( table[i].attrib != LDAP_ATTR_LIST_END ) { if ( table[i].attrib == key ) return table[i].name; i++; } return NULL;}/********************************************************************** Return the list of attribute names from a mapping table **********************************************************************/ const char** get_attr_list( ATTRIB_MAP_ENTRY table[] ){ const char **names; int i = 0; while ( table[i].attrib != LDAP_ATTR_LIST_END ) i++; i++; names = SMB_MALLOC_ARRAY( const char*, i ); if ( !names ) { DEBUG(0,("get_attr_list: out of memory\n")); return NULL; } i = 0; while ( table[i].attrib != LDAP_ATTR_LIST_END ) { names[i] = SMB_STRDUP( table[i].name ); i++; } names[i] = NULL; return names;}/********************************************************************* Cleanup ********************************************************************/ void free_attr_list( const char **list ){ int i = 0; if ( !list ) return; while ( list[i] ) { /* SAFE_FREE generates a warning here that can't be gotten rid * of with CONST_DISCARD */ if (list[i] != NULL) { free(CONST_DISCARD(char *, list[i])); } i+=1; } SAFE_FREE( list );}/******************************************************************* Search an attribute and return the first value found.******************************************************************/ BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, const char *attribute, char *value, int max_len){ char **values; if ( !attribute ) return False; value[0] = '\0'; if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { DEBUG (10, ("smbldap_get_single_attribute: [%s] = [<does not exist>]\n", attribute)); return False; } if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, max_len, False) == (size_t)-1) { DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", attribute, values[0])); ldap_value_free(values); return False; } ldap_value_free(values);#ifdef DEBUG_PASSWORDS DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value));#endif return True;} BOOL smbldap_get_single_pstring (LDAP * ldap_struct, LDAPMessage * entry, const char *attribute, pstring value){ return smbldap_get_single_attribute(ldap_struct, entry, attribute, value, sizeof(pstring));}/************************************************************************ Routine to manage the LDAPMod structure array manage memory used by the array, by each struct, and values ***********************************************************************/ void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value){ LDAPMod **mods; int i; int j; mods = *modlist; /* sanity checks on the mod values */ if (attribute == NULL || *attribute == '\0') { return; }#if 0 /* commented out after discussion with abartlet. Do not reenable. left here so other do not re-add similar code --jerry */ if (value == NULL || *value == '\0') return;#endif if (mods == NULL) { mods = SMB_MALLOC_P(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 && strequal(mods[i]->mod_type, attribute)) break; } if (mods[i] == NULL) { mods = SMB_REALLOC_ARRAY (mods, LDAPMod *, i + 2); if (mods == NULL) { DEBUG(0, ("make_a_mod: out of memory!\n")); return; } mods[i] = SMB_MALLOC_P(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 = SMB_STRDUP(attribute); mods[i + 1] = NULL; } if (value != NULL) { char *utf8_value = NULL; j = 0; if (mods[i]->mod_values != NULL) { for (; mods[i]->mod_values[j] != NULL; j++); } mods[i]->mod_values = SMB_REALLOC_ARRAY(mods[i]->mod_values, char *, j + 2); if (mods[i]->mod_values == NULL) { DEBUG (0, ("make_a_mod: Memory allocation failure!\n")); return; } if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) { DEBUG (0, ("make_a_mod: String conversion failure!\n")); return; } mods[i]->mod_values[j] = utf8_value; mods[i]->mod_values[j + 1] = NULL; } *modlist = mods;}/********************************************************************** Set attribute to newval in LDAP, regardless of what value the attribute had in LDAP before.*********************************************************************/ void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, LDAPMod ***mods, const char *attribute, const char *newval){ char oldval[2048]; /* current largest allowed value is mungeddial */ BOOL existed; if (attribute == NULL) { /* This can actually happen for ldapsam_compat where we for * example don't have a password history */ return; } if (existing != NULL) { existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval)); } else { existed = False; *oldval = '\0'; } /* all of our string attributes are case insensitive */ if (existed && newval && (StrCaseCmp(oldval, newval) == 0)) { /* Believe it or not, but LDAP will deny a delete and an add at the same time if the values are the same... */ DEBUG(10,("smbldap_make_mod: attribute |%s| not changed.\n", attribute)); return; } if (existed) { /* There has been no value before, so don't delete it. * Here's a possible race: We might end up with * duplicate attributes */ /* By deleting exactly the value we found in the entry this * should be race-free in the sense that the LDAP-Server will * deny the complete operation if somebody changed the * attribute behind our back. */ /* This will also allow modifying single valued attributes * in Novell NDS. In NDS you have to first remove attribute and then * you could add new value */ DEBUG(10,("smbldap_make_mod: deleting attribute |%s| values |%s|\n", attribute, oldval)); smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval); } /* Regardless of the real operation (add or modify) we add the new value here. We rely on deleting the old value, should it exist. */ if ((newval != NULL) && (strlen(newval) > 0)) { DEBUG(10,("smbldap_make_mod: adding attribute |%s| value |%s|\n", attribute, newval)); smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); }}/********************************************************************** Some varients of the LDAP rebind code do not pass in the third 'arg' pointer to a void*, so we try and work around it by assuming that the value of the 'LDAP *' pointer is the same as the one we had passed in **********************************************************************/struct smbldap_state_lookup { LDAP *ld; struct smbldap_state *smbldap_state; struct smbldap_state_lookup *prev, *next;};static struct smbldap_state_lookup *smbldap_state_lookup_list;static struct smbldap_state *smbldap_find_state(LDAP *ld) { struct smbldap_state_lookup *t; for (t = smbldap_state_lookup_list; t; t = t->next) { if (t->ld == ld) { return t->smbldap_state; } } return NULL;}static void smbldap_delete_state(struct smbldap_state *smbldap_state) { struct smbldap_state_lookup *t; for (t = smbldap_state_lookup_list; t; t = t->next) { if (t->smbldap_state == smbldap_state) { DLIST_REMOVE(smbldap_state_lookup_list, t); SAFE_FREE(t); return; } }}static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) { struct smbldap_state *tmp_ldap_state; struct smbldap_state_lookup *t; struct smbldap_state_lookup *tmp; if ((tmp_ldap_state = smbldap_find_state(ld))) { SMB_ASSERT(tmp_ldap_state == smbldap_state); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -