From 4a090ba06a54f5da179ac02bb307cc03d08831bf Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 16 Jul 2003 05:34:56 +0000 Subject: trying to get HEAD building again. If you want the code prior to this merge, checkout HEAD_PRE_3_0_0_BETA_3_MERGE (This used to be commit adb98e7b7cd0f025b52c570e4034eebf4047b1ad) --- source3/passdb/pdb_ldap.c | 2479 ++++++++++----------------------------------- 1 file changed, 536 insertions(+), 1943 deletions(-) (limited to 'source3/passdb/pdb_ldap.c') diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index fb63e81d28..a4ee4dbd4b 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4,7 +4,7 @@ Copyright (C) Jean François Micouleau 1998 Copyright (C) Gerald Carter 2001-2003 Copyright (C) Shahms King 2001 - Copyright (C) Andrew Bartlett 2002 + Copyright (C) Andrew Bartlett 2002-2003 Copyright (C) Stefan (metze) Metzmacher 2002 This program is free software; you can redistribute it and/or modify @@ -51,218 +51,61 @@ #include #include -#ifndef LDAP_OPT_SUCCESS -#define LDAP_OPT_SUCCESS 0 +/* + * Work around versions of the LDAP client libs that don't have the OIDs + * defined, or have them defined under the old name. + * This functionality is really a factor of the server, not the client + * + */ + +#if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD) +#define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD +#elif !defined(LDAP_EXOP_MODIFY_PASSWD) +#define "1.3.6.1.4.1.4203.1.11.1" #endif +#if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID +#elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U) +#endif + +#if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW +#elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) +#endif + + #ifndef SAM_ACCOUNT #define SAM_ACCOUNT struct sam_passwd #endif +#include "smbldap.h" + struct ldapsam_privates { + struct smbldap_state *smbldap_state; + /* Former statics */ - LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; int index; - time_t last_ping; - /* retrive-once info */ - const char *uri; const char *domain_name; DOM_SID domain_sid; /* configuration items */ int schema_ver; - - BOOL permit_non_unix_accounts; - - uint32 low_allocated_user_rid; - uint32 high_allocated_user_rid; - - uint32 low_allocated_group_rid; - uint32 high_allocated_group_rid; - - char *bind_dn; - char *bind_secret; - - unsigned int num_failures; -}; - -#define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */ - -static struct ldapsam_privates *static_ldap_state; - -/* specify schema versions between 2.2. and 3.0 */ - -#define SCHEMAVER_SAMBAACCOUNT 1 -#define SCHEMAVER_SAMBASAMACCOUNT 2 - -/* objectclass names */ - -#define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount" -#define LDAP_OBJ_SAMBAACCOUNT "sambaAccount" -#define LDAP_OBJ_GROUPMAP "sambaGroupMapping" -#define LDAP_OBJ_DOMINFO "sambaDomain" - -#define LDAP_OBJ_ACCOUNT "account" -#define LDAP_OBJ_POSIXACCOUNT "posixAccount" -#define LDAP_OBJ_POSIXGROUP "posixGroup" - -/* some generic attributes that get reused a lot */ - -#define LDAP_ATTRIBUTE_SID "sambaSID" - -/* attribute map table indexes */ - -#define LDAP_ATTR_LIST_END 0 -#define LDAP_ATTR_UID 1 -#define LDAP_ATTR_UIDNUMBER 2 -#define LDAP_ATTR_GIDNUMBER 3 -#define LDAP_ATTR_UNIX_HOME 4 -#define LDAP_ATTR_PWD_LAST_SET 5 -#define LDAP_ATTR_PWD_CAN_CHANGE 6 -#define LDAP_ATTR_PWD_MUST_CHANGE 7 -#define LDAP_ATTR_LOGON_TIME 8 -#define LDAP_ATTR_LOGOFF_TIME 9 -#define LDAP_ATTR_KICKOFF_TIME 10 -#define LDAP_ATTR_CN 11 -#define LDAP_ATTR_DISPLAY_NAME 12 -#define LDAP_ATTR_HOME_PATH 13 -#define LDAP_ATTR_LOGON_SCRIPT 14 -#define LDAP_ATTR_PROFILE_PATH 15 -#define LDAP_ATTR_DESC 16 -#define LDAP_ATTR_USER_WKS 17 -#define LDAP_ATTR_USER_SID 18 -#define LDAP_ATTR_USER_RID 18 -#define LDAP_ATTR_PRIMARY_GROUP_SID 19 -#define LDAP_ATTR_PRIMARY_GROUP_RID 20 -#define LDAP_ATTR_LMPW 21 -#define LDAP_ATTR_NTPW 22 -#define LDAP_ATTR_DOMAIN 23 -#define LDAP_ATTR_OBJCLASS 24 -#define LDAP_ATTR_ACB_INFO 25 -#define LDAP_ATTR_NEXT_USERRID 26 -#define LDAP_ATTR_NEXT_GROUPRID 27 -#define LDAP_ATTR_DOM_SID 28 -#define LDAP_ATTR_HOME_DRIVE 29 -#define LDAP_ATTR_GROUP_SID 30 -#define LDAP_ATTR_GROUP_TYPE 31 - - -typedef struct _attrib_map_entry { - int attrib; - const char *name; -} ATTRIB_MAP_ENTRY; - - -/* attributes used by Samba 2.2 */ - -static ATTRIB_MAP_ENTRY attrib_map_v22[] = { - { LDAP_ATTR_UID, "uid" }, - { LDAP_ATTR_UIDNUMBER, "uidNumber" }, - { LDAP_ATTR_GIDNUMBER, "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, "homeDrives" }, - { 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_LIST_END, NULL } -}; - -/* attributes used by Samba 3.0's sambaSamAccount */ - -static ATTRIB_MAP_ENTRY attrib_map_v30[] = { - { LDAP_ATTR_UID, "uid" }, - { LDAP_ATTR_UIDNUMBER, "uidNumber" }, - { LDAP_ATTR_GIDNUMBER, "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, "sambaSID" }, - { 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_LIST_END, NULL } -}; - -/* attributes used for alalocating RIDs */ - -static ATTRIB_MAP_ENTRY dominfo_attr_list[] = { - { LDAP_ATTR_DOMAIN, "sambaDomainName" }, - { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, - { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, - { LDAP_ATTR_DOM_SID, "sambaSID" }, - { LDAP_ATTR_LIST_END, NULL }, -}; - -/* Samba 3.0 group mapping attributes */ - -static ATTRIB_MAP_ENTRY groupmap_attr_list[] = { - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_GROUP_SID, "sambaSID" }, - { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -static ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { - { LDAP_ATTR_GROUP_SID, "sambaSID" }, - { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_LIST_END, NULL } }; /********************************************************************** - perform a simple table lookup and return the attribute name + Free a LDAPMessage (one is stored on the SAM_ACCOUNT) **********************************************************************/ -static const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ) +static void private_data_free_fn(void **result) { - int i = 0; - - while ( table[i].attrib != LDAP_ATTR_LIST_END ) { - if ( table[i].attrib == key ) - return table[i].name; - i++; - } - - return NULL; + ldap_memfree(*result); + *result = NULL; } /********************************************************************** @@ -286,52 +129,6 @@ static const char* get_userattr_key2string( int schema_ver, int key ) return NULL; } -/********************************************************************** - Return the list of attribute names from a mapping table - **********************************************************************/ - -static char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) -{ - char **names; - int i = 0; - - while ( table[i].attrib != LDAP_ATTR_LIST_END ) - i++; - i++; - - names = (char**)malloc( sizeof(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] = strdup( table[i].name ); - i++; - } - names[i] = NULL; - - return names; -} - -/********************************************************************* - Cleanup - ********************************************************************/ - -static void free_attr_list( char **list ) -{ - int i = 0; - - if ( !list ) - return; - - while ( list[i] ) - SAFE_FREE( list[i] ); - - SAFE_FREE( list ); -} - /********************************************************************** return the list of attribute names given a user schema version **********************************************************************/ @@ -352,1478 +149,187 @@ static char** get_userattr_list( int schema_ver ) return NULL; } - /******************************************************************* - find the ldap password -******************************************************************/ -static BOOL fetch_ldapsam_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; - - SAFE_FREE(data); - - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } - - SAFE_FREE(old_style_key); + generate the LDAP search filter for the objectclass based on the + version of the schema we are using + ******************************************************************/ - *pw = smb_xstrdup(old_style_pw); - } - - return True; -} - -/******************************************************************* - open a connection to the ldap server. -******************************************************************/ -static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct) +static const char* get_objclass_filter( int schema_ver ) { - int rc = LDAP_SUCCESS; - int version; - BOOL ldap_v3 = False; - -#ifdef HAVE_LDAP_INITIALIZE - DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri)); - - if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); - return rc; - } + static fstring objclass_filter; -#else - - /* Parse the string manually */ - - { - int port = 0; - fstring protocol; - fstring host; - const char *p = ldap_state->uri; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { - p += 4; - } - - sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); - } - } - - if ((*ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); - return LDAP_OPERATIONS_ERROR; - } - - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } - - DEBUG(3,("LDAPS option set...!\n")); -#else - DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - } -#endif - - if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) + switch( schema_ver ) { - if (version != LDAP_VERSION3) - { - version = LDAP_VERSION3; - if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { - ldap_v3 = True; - } - } else { - ldap_v3 = True; - } - } - - if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { -#ifdef LDAP_OPT_X_TLS - if (ldap_v3) { - 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 rc; - } - DEBUG (3, ("StartTLS issued: using a TLS connection\n")); - } else { - - DEBUG(0, ("Need LDAPv3 for Start TLS\n")); - return LDAP_OPERATIONS_ERROR; - } -#else - DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif + case SCHEMAVER_SAMBAACCOUNT: + snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); + break; + case SCHEMAVER_SAMBASAMACCOUNT: + snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); + break; + default: + DEBUG(0,("pdb_ldapsam: get_objclass_filter(): Invalid schema version specified!\n")); + break; } - - DEBUG(2, ("ldapsam_open_connection: connection opened\n")); - return rc; + + return objclass_filter; } - /******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) + run the search by name. ******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -#else -static int rebindproc_with_state (LDAP * ld, char **whop, char **credp, - int *methodp, int freeit, void *arg) +static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, + const char *user, + LDAPMessage ** result, char **attr) { - struct ldapsam_privates *ldap_state = arg; - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ - - if (freeit) { - SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); - SAFE_FREE(*credp); - } else { - DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); + pstring filter; + char *escape_user = escape_ldap_string_alloc(user); - *whop = strdup(ldap_state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; - } - *credp = strdup(ldap_state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; - } - *methodp = LDAP_AUTH_SIMPLE; + if (!escape_user) { + return LDAP_NO_MEMORY; } - return 0; -} -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ -/******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) - and actually does the connection. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -static int rebindproc_connect_with_state (LDAP *ldap_struct, - LDAP_CONST char *url, - ber_tag_t request, - ber_int_t msgid, void *arg) -{ - struct ldapsam_privates *ldap_state = arg; - int rc; - DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ + /* + * in the filter expression, replace %u with the real name + * so in ldap filter, %u MUST exist :-) + */ + snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(), + get_objclass_filter(ldap_state->schema_ver)); - rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); + /* + * have to use this here because $ is filtered out + * in pstring_sub + */ - return rc; -} -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ -/******************************************************************* - Add a rebind function for authenticated referrals -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -#else -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc (LDAP *ldap_struct, char **whop, char **credp, - int *method, int freeit ) -{ - return rebindproc_with_state(ldap_struct, whop, credp, - method, freeit, static_ldap_state); - -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + all_string_sub(filter, "%u", escape_user, sizeof(pstring)); + SAFE_FREE(escape_user); -/******************************************************************* - a rebind function for authenticated referrals - this also does the connection, but no void*. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, - ber_int_t msgid) -{ - return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, - static_ldap_state); + return smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); } -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ /******************************************************************* - connect to the ldap server under system privilege. + run the search by rid. ******************************************************************/ -static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct) -{ - int rc; - char *ldap_dn; - char *ldap_secret; - - /* The rebind proc needs this *HACK*. We are not multithreaded, so - this will work, but it's not nice. */ - static_ldap_state = ldap_state; - - /* get the password */ - if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) - { - DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } - - ldap_state->bind_dn = ldap_dn; - ldap_state->bind_secret = ldap_secret; - - /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite - (OpenLDAP) doesnt' seem to support it */ - - DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", - ldap_state->uri, ldap_dn)); - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); -# endif -#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(ldap_struct, &rebindproc); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state); -# endif -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - - rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(ldap_state->num_failures ? 2 : 0, - ("failed to bind to server with dn= %s Error: %s\n\t%s\n", - ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc), - ld_error)); - SAFE_FREE(ld_error); - ldap_state->num_failures++; - return rc; - } - - ldap_state->num_failures = 0; - - DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n")); - return rc; -} - -/********************************************************************** -Connect to LDAP server -*********************************************************************/ -static int ldapsam_open(struct ldapsam_privates *ldap_state) +static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, + uint32 rid, LDAPMessage ** result, + char **attr) { + pstring filter; int rc; - SMB_ASSERT(ldap_state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif - if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) { - struct sockaddr_un addr; - socklen_t len = sizeof(addr); - int sd; - if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 && - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - ldap_state->last_ping = (time_t)0; - } else { - ldap_state->last_ping = time(NULL); - } - } - - if (ldap_state->ldap_struct != NULL) { - DEBUG(5,("ldapsam_open: already connected to the LDAP server\n")); - return LDAP_SUCCESS; - } - - if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) { - return rc; - } - - if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - return rc; - } - - - ldap_state->last_ping = time(NULL); - DEBUG(4,("The LDAP server is succesful connected\n")); - - return LDAP_SUCCESS; -} - -/********************************************************************** -Disconnect from LDAP server -*********************************************************************/ -static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state) -{ - if (!ldap_state) - return NT_STATUS_INVALID_PARAMETER; - - if (ldap_state->ldap_struct != NULL) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - } + snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid, + get_objclass_filter(ldap_state->schema_ver)); - DEBUG(5,("The connection to the LDAP server was closed\n")); - /* maybe free the results here --metze */ + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); - return NT_STATUS_OK; + return rc; } -static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts) +/******************************************************************* + run the search by SID. +******************************************************************/ +static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, + const DOM_SID *sid, LDAPMessage ** result, + char **attr) { + pstring filter; int rc; + fstring sid_string; - SMB_ASSERT(ldap_state && attempts); - - if (*attempts != 0) { - unsigned int sleep_time; - uint8 rand_byte; - - /* Sleep for a random timeout */ - rand_byte = (char)(sys_random()); - - sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; - /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds - on average. - */ - DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", - sleep_time)); - msleep(sleep_time); - } - (*attempts)++; - - if ((rc = ldapsam_open(ldap_state))) { - DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts)); - return rc; - } - - return LDAP_SUCCESS; -} - - -/********************************************************************* - ********************************************************************/ - -static int ldapsam_search(struct ldapsam_privates *ldap_state, - const char *base, int scope, const char *filter, - char *attrs[], int attrsonly, - LDAPMessage **res) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_filter; - - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; + snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)", + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + sid_to_string(sid_string, sid), + get_objclass_filter(ldap_state->schema_ver)); - rc = ldap_search_s(ldap_state->ldap_struct, base, scope, - utf8_filter, attrs, attrsonly, res); - } + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_filter); return rc; } -static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[]) +/******************************************************************* + Delete complete object or objectclass and attrs from + object found in search_result depending on lp_ldap_delete_dn +******************************************************************/ +static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, + LDAPMessage *result, + const char *objectclass, + char **attrs) { - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_dn; + int rc; + LDAPMessage *entry; + LDAPMod **mods = NULL; + char *name, *dn; + BerElement *ptr = NULL; - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_dn); - return rc; -} - -static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[]) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_dn; - - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_dn); - return rc; -} - -static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_dn; - - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_dn); - return rc; -} - -#ifdef LDAP_EXOP_X_MODIFY_PASSWD -static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - return rc; -} -#endif - -/******************************************************************* - run the search by name. -******************************************************************/ -static int ldapsam_search_suffix (struct ldapsam_privates *ldap_state, const char *filter, - char **search_attr, LDAPMessage ** result) -{ - int scope = LDAP_SCOPE_SUBTREE; - int rc; - - DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter)); - - rc = ldapsam_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n", - ld_error?ld_error:"(unknown)", ldap_err2string (rc))); - DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(), - filter)); - SAFE_FREE(ld_error); - } - - return rc; -} - -/******************************************************************* - generate the LDAP search filter for the objectclass based on the - version of the schema we are using - ******************************************************************/ - -static const char* get_objclass_filter( int schema_ver ) -{ - static fstring objclass_filter; - - switch( schema_ver ) - { - case SCHEMAVER_SAMBAACCOUNT: - snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); - break; - case SCHEMAVER_SAMBASAMACCOUNT: - snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); - break; - default: - DEBUG(0,("ldapsam_search_suffix_by_name(): Invalid schema version specified!\n")); - break; - } - - return objclass_filter; -} - -/******************************************************************* - run the search by name. -******************************************************************/ -static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user, - LDAPMessage ** result, char **attr) -{ - pstring filter; - char *escape_user = escape_ldap_string_alloc(user); - - if (!escape_user) { - return LDAP_NO_MEMORY; - } - - /* - * in the filter expression, replace %u with the real name - * so in ldap filter, %u MUST exist :-) - */ - snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(), - get_objclass_filter(ldap_state->schema_ver)); - - /* - * have to use this here because $ is filtered out - * in pstring_sub - */ - - - all_string_sub(filter, "%u", escape_user, sizeof(pstring)); - SAFE_FREE(escape_user); - - return ldapsam_search_suffix(ldap_state, filter, attr, result); -} - -/******************************************************************* - run the search by rid. -******************************************************************/ -static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, - uint32 rid, LDAPMessage ** result, - char **attr) -{ - pstring filter; - int rc; - - /* check if the user rid exists, if not, try searching on the uid */ - - snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid, - get_objclass_filter(ldap_state->schema_ver)); - - rc = ldapsam_search_suffix(ldap_state, filter, attr, result); - - return rc; -} - -/******************************************************************* - run the search by SID. -******************************************************************/ -static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, - const DOM_SID *sid, LDAPMessage ** result, - char **attr) -{ - pstring filter; - int rc; - fstring sid_string; - - /* check if the user rid exsists, if not, try searching on the uid */ - - snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)", - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), - sid_to_string(sid_string, sid), - get_objclass_filter(ldap_state->schema_ver)); - - rc = ldapsam_search_suffix(ldap_state, filter, attr, result); - - return rc; -} - -/******************************************************************* -search an attribute and return the first value found. -******************************************************************/ -static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - const char *attribute, pstring value) -{ - char **values; - - if ( !attribute ) - return False; - - value[0] = '\0'; - - if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { - DEBUG (10, ("get_single_attribute: [%s] = []\n", attribute)); - - return False; - } - - if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) - { - DEBUG(1, ("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, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); -#endif - return True; -} - -/************************************************************************ -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, 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 so re-add similar code --jerry */ - if (value == NULL || *value == '\0') - return; -#endif - - 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) - { - char *utf8_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; - } - - 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. -*********************************************************************/ -static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing, - LDAPMod ***mods, - const char *attribute, const char *newval) -{ - char **values = NULL; - - if (existing != NULL) { - values = ldap_get_values(ldap_struct, existing, attribute); - } - - /* all of our string attributes are case insensitive */ - - if ((values != NULL) && (values[0] != NULL) && - StrCaseCmp(values[0], 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... */ - - ldap_value_free(values); - return; - } - - /* 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)) { - make_a_mod(mods, LDAP_MOD_ADD, attribute, newval); - } - - if (values == NULL) { - /* There has been no value before, so don't delete it. - Here's a possible race: We might end up with - duplicate attributes */ - return; - } - - /* 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. */ - - make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]); - ldap_value_free(values); -} - -/******************************************************************* - Delete complete object or objectclass and attrs from - object found in search_result depending on lp_ldap_delete_dn -******************************************************************/ -static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, - LDAPMessage *result, - const char *objectclass, - char **attrs) -{ - int rc; - LDAPMessage *entry; - LDAPMod **mods = NULL; - char *name, *dn; - BerElement *ptr = NULL; - - rc = ldap_count_entries(ldap_state->ldap_struct, result); + rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (rc != 1) { DEBUG(0, ("Entry must exist exactly once!\n")); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->ldap_struct, entry); - - if (lp_ldap_delete_dn()) { - NTSTATUS ret = NT_STATUS_OK; - rc = ldapsam_delete(ldap_state, dn); - - if (rc != LDAP_SUCCESS) { - DEBUG(0, ("Could not delete object %s\n", dn)); - ret = NT_STATUS_UNSUCCESSFUL; - } - ldap_memfree(dn); - return ret; - } - - /* Ok, delete only the SAM attributes */ - - for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr); - name != NULL; - name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) - { - char **attrib; - - /* We are only allowed to delete the attributes that - really exist. */ - - for (attrib = attrs; *attrib != NULL; attrib++) - { - if (StrCaseCmp(*attrib, name) == 0) { - DEBUG(10, ("deleting attribute %s\n", name)); - make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL); - } - } - - ldap_memfree(name); - } - - if (ptr != NULL) { - ber_free(ptr, 0); - } - - make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass); - - rc = ldapsam_modify(ldap_state, dn, mods); - ldap_mods_free(mods, 1); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - - DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n", - dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); - SAFE_FREE(ld_error); - ldap_memfree(dn); - return NT_STATUS_UNSUCCESSFUL; - } - - ldap_memfree(dn); - return NT_STATUS_OK; -} - -/********************************************************************** -Search for the domain info entry -*********************************************************************/ -static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state, - LDAPMessage ** result) -{ - pstring filter; - int rc; - char **attr_list; - - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", - LDAP_OBJ_DOMINFO, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name); - - DEBUG(2, ("Searching for:[%s]\n", filter)); - - - attr_list = get_attr_list( dominfo_attr_list ); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list , result); - free_attr_list( attr_list ); - - if (rc != LDAP_SUCCESS) { - DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); - DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - } - - return rc; -} - -/********************************************************************** - If this entry is is the 'allocated' range, extract the RID and return - it, so we can find the 'next' rid to allocate. - - Do this, no matter what type of object holds the RID - be it a user, - group or somthing else. -*********************************************************************/ -static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type) -{ - pstring sid_string; - DOM_SID dom_sid; - uint32 rid; - - if (!get_single_attribute(ldap_state->ldap_struct, entry, - LDAP_ATTRIBUTE_SID, sid_string)) - { - return 0; - } - - if (!string_to_sid(&dom_sid, sid_string)) { - return 0; - } - - if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) { - /* not our domain, so we don't care */ - return 0; - } - - switch (rid_type) { - case USER_RID_TYPE: - if (rid >= ldap_state->low_allocated_user_rid && - rid <= ldap_state->high_allocated_user_rid) { - return rid; - } - break; - case GROUP_RID_TYPE: - if (rid >= ldap_state->low_allocated_group_rid && - rid <= ldap_state->high_allocated_group_rid) { - return rid; - } - break; - } - return 0; -} - - -/********************************************************************** -Connect to LDAP server and find the next available 'allocated' RID. - -The search is done 'per type' as we allocate seperate pools for the -EVEN and ODD (user and group) RIDs. - -This is only done once, so that we can fill out the sambaDomain. -*********************************************************************/ -static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type) -{ - int rc; - LDAPMessage *result; - LDAPMessage *entry; - uint32 top_rid = 0; - uint32 next_rid; - uint32 count; - uint32 rid; - char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - fstring filter; - - snprintf( filter, sizeof(filter)-1, "(%s=*)", LDAP_ATTRIBUTE_SID ); - - DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter)); - - rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result); - - if (rc != LDAP_SUCCESS) { - DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc))); - DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - - result = NULL; - return 0; - } - - count = ldap_count_entries(ldap_state->ldap_struct, result); - DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count)); - - if (count == 0) { - DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc))); - DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - } else { - entry = ldap_first_entry(ldap_state->ldap_struct,result); - - top_rid = entry_to_rid(ldap_state, entry, rid_type); - - while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) { - - rid = entry_to_rid(ldap_state, entry, rid_type); - if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) { - top_rid = rid; - } - } - } - - switch (rid_type) { - case USER_RID_TYPE: - if (top_rid < ldap_state->low_allocated_user_rid) { - return ldap_state->low_allocated_user_rid; - } - break; - case GROUP_RID_TYPE: - if (top_rid < ldap_state->low_allocated_group_rid) - return ldap_state->low_allocated_group_rid; - break; - } - - next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER; - - switch (rid_type) { - case USER_RID_TYPE: - if (next_rid > ldap_state->high_allocated_user_rid) { - return 0; - } - break; - case GROUP_RID_TYPE: - if (next_rid > ldap_state->high_allocated_group_rid) { - return 0; - } - break; - } - return next_rid; -} - -/********************************************************************** - Add the sambaDomain to LDAP, so we don't have to search for this stuff - again. This is a once-add operation for now. - - TODO: Add other attributes, and allow modification. -*********************************************************************/ -static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) -{ - pstring tmp; - pstring filter; - LDAPMod **mods = NULL; - int rc; - int ldap_op; - LDAPMessage *result = NULL; - char *dn = NULL; - int num_result; - char **attr_list; - - uint32 next_allocated_user_rid; - uint32 next_allocated_group_rid; - - next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE); - if (!next_allocated_user_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE); - if (!next_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name, LDAP_OBJ_DOMINFO); - - attr_list = get_attr_list( dominfo_attr_list ); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result); - free_attr_list( attr_list ); - - if (rc != LDAP_SUCCESS) { - return NT_STATUS_UNSUCCESSFUL; - } - - num_result = ldap_count_entries(ldap_state->ldap_struct, result); - - if (num_result > 1) { - DEBUG (0, ("More than domain with that name exists: bailing out!\n")); - ldap_msgfree(result); - return NT_STATUS_UNSUCCESSFUL; - } - - /* Check if we need to add an entry */ - DEBUG(3,("Adding new domain\n")); - ldap_op = LDAP_MOD_ADD; - asprintf (&dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name, lp_ldap_suffix()); - - /* Free original search */ - ldap_msgfree(result); - - if (!dn) - return NT_STATUS_NO_MEMORY; - - /* make the changes - the entry *must* not already have samba attributes */ - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name); - - sid_to_string(tmp, &ldap_state->domain_sid); - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), tmp); - - snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid); - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), tmp); - - snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid); - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), tmp); - - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); - - switch(ldap_op) - { - case LDAP_MOD_ADD: - rc = ldapsam_add(ldap_state, dn, mods); - break; - case LDAP_MOD_REPLACE: - rc = ldapsam_modify(ldap_state, dn, mods); - break; - default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); - return NT_STATUS_INVALID_PARAMETER; - } - - if (rc!=LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(1, - ("failed to %s domain dn= %s with: %s\n\t%s\n", - ldap_op == LDAP_MOD_ADD ? "add" : "modify", - dn, ldap_err2string(rc), - ld_error?ld_error:"unknown")); - SAFE_FREE(ld_error); - - ldap_mods_free(mods,1); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name)); - ldap_mods_free(mods, 1); - return NT_STATUS_OK; -} - -/********************************************************************** - Even if the sambaAccount attribute in LDAP tells us that this RID is - safe to use, always check before use. -*********************************************************************/ -static BOOL sid_in_use(struct ldapsam_privates *ldap_state, - const DOM_SID *sid, int *error) -{ - fstring filter; - fstring sid_string; - LDAPMessage *result = NULL; - int count; - int rc; - char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - - slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid)); - - rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n", - sid_string, ld_error)); - SAFE_FREE(ld_error); - - *error = rc; - return True; - } - - if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 0) { - DEBUG(3, ("Sid %s already in use - trying next RID\n", - sid_string)); - ldap_msgfree(result); - return True; - } - - ldap_msgfree(result); - - /* good, sid is not in use */ - return False; -} - -/********************************************************************** - Set the new nextRid attribute, and return one we can use. - - This also checks that this RID is actually free - in case the admin - manually stole it :-). -*********************************************************************/ -static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - int rc; - LDAPMessage *result = NULL; - LDAPMessage *entry = NULL; - char *dn; - LDAPMod **mods = NULL; - int count; - fstring old_rid_string; - fstring next_rid_string; - uint32 next_rid; - int attempts = 0; - - if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) { - DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n", - LDAP_OBJ_SAMBASAMACCOUNT)); - return NT_STATUS_UNSUCCESSFUL; - } - - while (attempts < 10) - { - char *ld_error; - if (ldapsam_search_domain_info(ldap_state, &result)) { - return ret; - } - - if (ldap_count_entries(ldap_state->ldap_struct, result) < 1) { - DEBUG(3, ("Got no domain info entries for domain %s\n", - ldap_state->domain_name)); - ldap_msgfree(result); - if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) { - continue; - } else { - DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret))); - return ret; - } - } - - if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 1) { - DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n", - count, ldap_state->domain_name)); - ldap_msgfree(result); - return ret; - } - - entry = ldap_first_entry(ldap_state->ldap_struct, result); - if (!entry) { - ldap_msgfree(result); - return ret; - } - - if ((dn = ldap_get_dn(ldap_state->ldap_struct, entry)) == NULL) { - DEBUG(0, ("Could not get domain info DN\n")); - ldap_msgfree(result); - return ret; - } - - /* yes, we keep 2 seperate counters, to avoid stomping on the two - different sets of algorithmic RIDs */ - - switch (rid_type) { - case USER_RID_TYPE: - if (!get_single_attribute(ldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - old_rid_string)) - { - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - break; - case GROUP_RID_TYPE: - if (!get_single_attribute(ldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - old_rid_string)) - { - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - break; - } - - /* This is the core of the whole routine. If we had - scheme-style closures, there would be a *lot* less code - duplication... */ - *rid = (uint32)atol(old_rid_string); - next_rid = *rid+RID_MULTIPLIER; - - slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); - - switch (rid_type) { - case USER_RID_TYPE: - if (next_rid > ldap_state->high_allocated_user_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - /* Try to make the modification atomically by enforcing the - old value in the delete mod. */ - make_ldap_mod(ldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - next_rid_string); - break; - - case GROUP_RID_TYPE: - if (next_rid > ldap_state->high_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - /* Try to make the modification atomically by enforcing the - old value in the delete mod. */ - make_ldap_mod(ldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - next_rid_string); - break; - } - - if ((rc = ldap_modify_s(ldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) { - DOM_SID dom_sid; - DOM_SID sid; - pstring domain_sid_string; - int error = 0; - - if (!get_single_attribute(ldap_state->ldap_struct, result, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), - domain_sid_string)) - { - ldap_mods_free(mods, 1); - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); - if (!string_to_sid(&dom_sid, domain_sid_string)) { - ldap_mods_free(mods, 1); - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } + if (lp_ldap_delete_dn()) { + NTSTATUS ret = NT_STATUS_OK; + rc = smbldap_delete(ldap_state->smbldap_state, dn); - ldap_mods_free(mods, 1); - mods = NULL; - ldap_memfree(dn); - ldap_msgfree(result); + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("Could not delete object %s\n", dn)); + ret = NT_STATUS_UNSUCCESSFUL; + } + ldap_memfree(dn); + return ret; + } + + /* Ok, delete only the SAM attributes */ + + for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr); + name != NULL; + name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) + { + char **attrib; - sid_copy(&sid, &dom_sid); - sid_append_rid(&sid, *rid); + /* We are only allowed to delete the attributes that + really exist. */ - /* check RID is not in use */ - if (sid_in_use(ldap_state, &sid, &error)) { - if (error) { - return ret; - } - continue; + for (attrib = attrs; *attrib != NULL; attrib++) + { + if (StrCaseCmp(*attrib, name) == 0) { + DEBUG(10, ("deleting attribute %s\n", name)); + smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL); } - - return NT_STATUS_OK; } - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(2, ("Failed to modify rid: %s\n", ld_error)); - SAFE_FREE(ld_error); + ldap_memfree(name); + } + + if (ptr != NULL) { + ber_free(ptr, 0); + } + + smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass); - ldap_mods_free(mods, 1); - mods = NULL; + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + ldap_mods_free(mods, True); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + + DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n", + dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); ldap_memfree(dn); - dn = NULL; - - ldap_msgfree(result); - result = NULL; - - { - /* Sleep for a random timeout */ - unsigned sleeptime = (sys_random()*sys_getpid()*attempts); - attempts += 1; - - sleeptime %= 100; - msleep(sleeptime); - } + return NT_STATUS_UNSUCCESSFUL; } - DEBUG(0, ("Failed to set new RID\n")); - return ret; + ldap_memfree(dn); + return NT_STATUS_OK; } + /* New Interface is being implemented here */ @@ -1840,7 +346,7 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, char **ldap_values; char **values; - if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) { + if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) { DEBUG (1, ("get_unix_attributes: no objectClass! \n")); return False; } @@ -1858,13 +364,13 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, } ldap_value_free(ldap_values); - if ( !get_single_attribute(ldap_state->ldap_struct, entry, + if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) ) { return False; } - if ( !get_single_attribute(ldap_state->ldap_struct, entry, + if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) ) { return False; @@ -1937,12 +443,12 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, return False; } - if (ldap_state->ldap_struct == NULL) { - DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n")); + if (ldap_state->smbldap_state->ldap_struct == NULL) { + DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n")); return False; } - if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) { + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) { DEBUG(1, ("No uid attribute found for this user!\n")); return False; } @@ -1962,13 +468,13 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) { - if (get_single_attribute(ldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) { pdb_set_user_sid_from_string(sampass, temp, PDB_SET); } - if (get_single_attribute(ldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) { pdb_set_group_sid_from_string(sampass, temp, PDB_SET); @@ -1982,14 +488,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } else { - if (get_single_attribute(ldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) { user_rid = (uint32)atol(temp); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) { pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); @@ -2027,7 +533,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, { GROUP_MAP map; /* call the mapping code here */ - if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) { + if(pdb_getgrgid(&map, gid)) { pdb_set_group_sid(sampass, &map.sid, PDB_SET); } else { @@ -2036,7 +542,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) { /* leave as default */ @@ -2045,7 +551,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) { /* leave as default */ @@ -2054,7 +560,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logon_time(sampass, logon_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) { /* leave as default */ @@ -2063,7 +569,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logoff_time(sampass, logoff_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) { /* leave as default */ @@ -2072,7 +578,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) { /* leave as default */ @@ -2081,7 +587,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) { /* leave as default */ @@ -2096,10 +602,10 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, * that fits your needs; using cn then displayName rather than 'userFullName' */ - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) { - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) { /* leave as default */ @@ -2110,7 +616,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_fullname(sampass, fullname, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) { pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2122,7 +628,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_dir_drive(sampass, dir_drive, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) { pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2134,7 +640,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_homedir(sampass, homedir, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) { pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2146,7 +652,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logon_script(sampass, logon_script, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) { pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2158,7 +664,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_profile_path(sampass, profile_path, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc)) { /* leave as default */ @@ -2166,7 +672,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_acct_desc(sampass, acct_desc, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) { /* leave as default */; @@ -2180,7 +686,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, hours_len = 21; memset(hours, 0xff, hours_len); - if (!get_single_attribute (ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) { /* leave as default */ @@ -2192,7 +698,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smblmpwd); } - if (!get_single_attribute (ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) { /* leave as default */ @@ -2204,7 +710,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smbntpwd); } - if (!get_single_attribute (ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) { acct_ctrl |= ACB_NORMAL; @@ -2256,39 +762,11 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, * do this on a per-mod basis */ if (need_update(sampass, PDB_USERNAME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, "uid", pdb_get_username(sampass)); DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass))); - if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) { - if (ldap_state->permit_non_unix_accounts) { - if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) { - DEBUG(0, ("NO user RID specified on account %s, and " - "finding next available NUA RID failed, " - "cannot store!\n", - pdb_get_username(sampass))); - ldap_mods_free(*mods, 1); - return False; - } - } else { - DEBUG(0, ("NO user RID specified on account %s, " - "cannot store!\n", pdb_get_username(sampass))); - ldap_mods_free(*mods, 1); - return False; - } - - /* now that we have figured out the RID, always store it, as - the schema requires it (either as a SID or a RID) */ - - if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) { - DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n", - pdb_get_username(sampass))); - ldap_mods_free(*mods, 1); - return False; - } - } - /* only update the RID if we actually need to */ if (need_update(sampass, PDB_USERSID)) { @@ -2299,20 +777,20 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) { + if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) { DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, user_sid), - sid_to_string(dom_sid_string, get_global_sam_sid()))); + sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; } slprintf(temp, sizeof(temp) - 1, "%i", rid); - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp); break; case SCHEMAVER_SAMBASAMACCOUNT: - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), sid_to_string(sid_string, user_sid)); break; @@ -2335,21 +813,21 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - if (!sid_peek_check_rid(get_global_sam_sid(), group_sid, &rid)) { + if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) { DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, group_sid), - sid_to_string(dom_sid_string, get_global_sam_sid()))); + sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; } slprintf(temp, sizeof(temp) - 1, "%i", rid); - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp); break; case SCHEMAVER_SAMBASAMACCOUNT: - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid)); break; @@ -2370,63 +848,63 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, */ if (need_update(sampass, PDB_FULLNAME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), pdb_get_fullname(sampass)); if (need_update(sampass, PDB_ACCTDESC)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), pdb_get_acct_desc(sampass)); if (need_update(sampass, PDB_WORKSTATIONS)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), pdb_get_workstations(sampass)); if (need_update(sampass, PDB_SMBHOME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), pdb_get_homedir(sampass)); if (need_update(sampass, PDB_DRIVE)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), pdb_get_dir_drive(sampass)); if (need_update(sampass, PDB_LOGONSCRIPT)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), pdb_get_logon_script(sampass)); if (need_update(sampass, PDB_PROFILE)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), pdb_get_profile_path(sampass)); slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass)); if (need_update(sampass, PDB_LOGONTIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp); slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass)); if (need_update(sampass, PDB_LOGOFFTIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass)); if (need_update(sampass, PDB_KICKOFFTIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass)); if (need_update(sampass, PDB_CANCHANGETIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass)); if (need_update(sampass, PDB_MUSTCHANGETIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp); if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) @@ -2437,7 +915,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, pdb_get_acct_ctrl(sampass)); if (need_update(sampass, PDB_LMPASSWD)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp); @@ -2445,13 +923,13 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, pdb_get_acct_ctrl(sampass)); if (need_update(sampass, PDB_NTPASSWD)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass)); if (need_update(sampass, PDB_PASSLASTSET)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp); } @@ -2459,7 +937,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, /* FIXME: Hours stuff goes in LDAP */ if (need_update(sampass, PDB_ACCTCTRL)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN)); @@ -2483,7 +961,8 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) all_string_sub(filter, "%u", "*", sizeof(pstring)); attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &ldap_state->result); + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, + attr_list, &ldap_state->result); free_attr_list( attr_list ); if (rc != LDAP_SUCCESS) { @@ -2495,10 +974,10 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) } DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n", - ldap_count_entries(ldap_state->ldap_struct, + ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result))); - ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, + ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); ldap_state->index = 0; @@ -2526,10 +1005,6 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; BOOL bret = False; - /* The rebind proc needs this *HACK*. We are not multithreaded, so - this will work, but it's not nice. */ - static_ldap_state = ldap_state; - while (!bret) { if (!ldap_state->entry) return ret; @@ -2537,7 +1012,7 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT ldap_state->index++; bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry); - ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct, + ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->entry); } @@ -2564,28 +1039,32 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT if ( rc != LDAP_SUCCESS ) return NT_STATUS_NO_SUCH_USER; - count = ldap_count_entries(ldap_state->ldap_struct, result); + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { DEBUG(4, ("Unable to locate user [%s] count=%d\n", sname, count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } else if (count > 1) { DEBUG(1, ("Duplicate entries for this user [%s] Failing. count=%d\n", sname, count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); if (entry) { if (!init_sam_from_ldap(ldap_state, user, entry)) { DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - ldap_msgfree(result); + pdb_set_backend_private_data(user, result, + private_data_free_fn, + my_methods, PDB_CHANGED); ret = NT_STATUS_OK; } else { ldap_msgfree(result); @@ -2593,55 +1072,65 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT return ret; } -/********************************************************************** -Get SAM_ACCOUNT entry from LDAP by SID -*********************************************************************/ -static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) +static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, + const DOM_SID *sid, LDAPMessage **result) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; - LDAPMessage *result; - LDAPMessage *entry; - fstring sid_string; - int count; - int rc; + int rc = -1; char ** attr_list; - + uint32 rid; + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_sid(ldap_state, sid, &result, attr_list); + rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); free_attr_list( attr_list ); if ( rc != LDAP_SUCCESS ) - return NT_STATUS_NO_SUCH_USER; + return rc; break; case SCHEMAVER_SAMBAACCOUNT: - { - uint32 rid; - if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) { - return NT_STATUS_NO_SUCH_USER; + if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) { + return rc; } attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_rid(ldap_state, rid, &result, attr_list ); + rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list ); free_attr_list( attr_list ); if ( rc != LDAP_SUCCESS ) - return NT_STATUS_NO_SUCH_USER; - } - break; + return rc; + break; } - - count = ldap_count_entries(ldap_state->ldap_struct, result); + return rc; +} + +/********************************************************************** +Get SAM_ACCOUNT entry from LDAP by SID +*********************************************************************/ +static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) +{ + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + LDAPMessage *result; + LDAPMessage *entry; + int count; + int rc; + fstring sid_string; + + rc = ldapsam_get_ldap_user_by_sid(ldap_state, + sid, &result); + if (rc != LDAP_SUCCESS) + return NT_STATUS_NO_SUCH_USER; + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { DEBUG(4, ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid), count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } else if (count > 1) @@ -2649,23 +1138,27 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT DEBUG(1, ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid), count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - if (entry) + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + if (!entry) { - if (!init_sam_from_ldap(ldap_state, user, entry)) { - DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n")); - ldap_msgfree(result); - return NT_STATUS_NO_SUCH_USER; - } ldap_msgfree(result); - ret = NT_STATUS_OK; - } else { + return NT_STATUS_NO_SUCH_USER; + } + + if (!init_sam_from_ldap(ldap_state, user, entry)) { + DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n")); ldap_msgfree(result); + return NT_STATUS_NO_SUCH_USER; } - return ret; + + pdb_set_backend_private_data(user, result, + private_data_free_fn, + my_methods, PDB_CHANGED); + return NT_STATUS_OK; } /******************************************************************** @@ -2693,20 +1186,25 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, switch(ldap_op) { case LDAP_MOD_ADD: - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_ACCOUNT); - rc = ldapsam_add(ldap_state, dn, mods); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + "objectclass", + LDAP_OBJ_ACCOUNT); + rc = smbldap_add(ldap_state->smbldap_state, + dn, mods); break; case LDAP_MOD_REPLACE: - rc = ldapsam_modify(ldap_state, dn ,mods); + rc = smbldap_modify(ldap_state->smbldap_state, + dn ,mods); break; default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); + DEBUG(0,("Wrong LDAP operation type: %d!\n", + ldap_op)); return NT_STATUS_INVALID_PARAMETER; } if (rc!=LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(1, ("failed to %s user dn= %s with: %s\n\t%s\n", @@ -2718,7 +1216,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } } -#ifdef LDAP_EXOP_X_MODIFY_PASSWD if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) && (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) && need_update(newpwd, PDB_PLAINTEXT_PW) && @@ -2745,8 +1242,8 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } ber_printf (ber, "{"); - ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn); - ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password); + ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn); + ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password); ber_printf (ber, "N}"); if ((rc = ber_flatten (ber, &bv))<0) { @@ -2761,8 +1258,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, SAFE_FREE(utf8_password); ber_free(ber, 1); - if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD, - bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) { + if ((rc = smbldap_extended_operation(ldap_state->smbldap_state, + LDAP_EXOP_MODIFY_PASSWD, + bv, NULL, NULL, &retoid, + &retdata)) != LDAP_SUCCESS) { DEBUG(0,("LDAP Password could not be changed for user %s: %s\n", pdb_get_username(newpwd),ldap_err2string(rc))); } else { @@ -2775,9 +1274,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } ber_bvfree(bv); } -#else - DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n")); -#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ return NT_STATUS_OK; } @@ -2857,43 +1353,46 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A LDAPMod **mods; char **attr_list; - attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list ); - free_attr_list( attr_list ); - if (rc != LDAP_SUCCESS) - return NT_STATUS_UNSUCCESSFUL; + result = pdb_get_backend_private_data(newpwd, my_methods); + if (!result) { + attr_list = get_userattr_list(ldap_state->schema_ver); + rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list ); + free_attr_list( attr_list ); + if (rc != LDAP_SUCCESS) { + return NT_STATUS_UNSUCCESSFUL; + } + pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED); + } - if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { DEBUG(0, ("No user to modify!\n")); - ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->ldap_struct, entry); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + + DEBUG(4, ("user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn)); if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, element_is_changed)) { DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); - ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - ldap_msgfree(result); - if (mods == NULL) { DEBUG(4,("mods is empty: nothing to update for user: %s\n", pdb_get_username(newpwd))); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); return NT_STATUS_OK; } ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed); - ldap_mods_free(mods,1); + ldap_mods_free(mods,True); if (!NT_STATUS_IS_OK(ret)) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n", pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc))); @@ -2935,7 +1434,9 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO char **attr_list; char *escape_user; const char *username = pdb_get_username(newpwd); + const DOM_SID *sid = pdb_get_user_sid(newpwd); pstring filter; + fstring sid_string; if (!username || !*username) { DEBUG(0, ("Cannot add user without a username!\n")); @@ -2943,8 +1444,8 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } /* free this list after the second search or in case we exit on failure */ - attr_list = get_userattr_list(ldap_state->schema_ver); + rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list); if (rc != LDAP_SUCCESS) { @@ -2952,7 +1453,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO return NT_STATUS_UNSUCCESSFUL; } - if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { DEBUG(0,("User '%s' already in the base, with samba attributes\n", username)); ldap_msgfree(result); @@ -2960,25 +1461,42 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO return NT_STATUS_UNSUCCESSFUL; } ldap_msgfree(result); + result = NULL; + + if (element_is_set_or_changed(newpwd, PDB_USERSID)) { + rc = ldapsam_get_ldap_user_by_sid(ldap_state, + sid, &result); + if (rc == LDAP_SUCCESS) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { + DEBUG(0,("SID '%s' already in the base, with samba attributes\n", + sid_to_string(sid_string, sid))); + free_attr_list( attr_list ); + return NT_STATUS_UNSUCCESSFUL; + } + ldap_msgfree(result); + } + } - /* does the entry already exist but without a samba rttibutes? - we don't really care what attributes are returned here */ + /* does the entry already exist but without a samba attributes? + we need to return the samba attributes here */ escape_user = escape_ldap_string_alloc( username ); pstrcpy( filter, lp_ldap_filter() ); all_string_sub( filter, "%u", escape_user, sizeof(filter) ); SAFE_FREE( escape_user ); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result); - free_attr_list( attr_list ); - - if ( rc != LDAP_SUCCESS ) + rc = smbldap_search_suffix(ldap_state->smbldap_state, + filter, attr_list, &result); + if ( rc != LDAP_SUCCESS ) { + free_attr_list( attr_list ); return NT_STATUS_UNSUCCESSFUL; + } - num_result = ldap_count_entries(ldap_state->ldap_struct, result); + num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (num_result > 1) { DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + free_attr_list( attr_list ); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -2989,19 +1507,62 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO DEBUG(3,("User exists without samba attributes: adding them\n")); ldap_op = LDAP_MOD_REPLACE; - entry = ldap_first_entry (ldap_state->ldap_struct, result); - tmp = ldap_get_dn (ldap_state->ldap_struct, entry); + entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); slprintf (dn, sizeof (dn) - 1, "%s", tmp); ldap_memfree (tmp); - } else { + + } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) { + + /* There might be a SID for this account already - say an idmap entry */ + + snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + sid_to_string(sid_string, sid), + LDAP_OBJ_IDMAP_ENTRY, + LDAP_OBJ_SID_ENTRY); + + rc = smbldap_search_suffix(ldap_state->smbldap_state, + filter, attr_list, &result); + + if ( rc != LDAP_SUCCESS ) { + free_attr_list( attr_list ); + return NT_STATUS_UNSUCCESSFUL; + } + + num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + + if (num_result > 1) { + DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + free_attr_list( attr_list ); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Check if we need to update an existing entry */ + if (num_result == 1) { + char *tmp; + + DEBUG(3,("User exists without samba attributes: adding them\n")); + ldap_op = LDAP_MOD_REPLACE; + entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + slprintf (dn, sizeof (dn) - 1, "%s", tmp); + ldap_memfree (tmp); + } + } + + free_attr_list( attr_list ); + + if (num_result == 0) { /* Check if we need to add an entry */ DEBUG(3,("Adding new user\n")); ldap_op = LDAP_MOD_ADD; if (username[strlen(username)-1] == '$') { - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); - } else { - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ()); - } + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); + } else { + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ()); + } } if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, @@ -3020,10 +1581,10 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT); break; case SCHEMAVER_SAMBASAMACCOUNT: - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT); break; default: DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n")); @@ -3031,43 +1592,19 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed); - if (NT_STATUS_IS_ERR(ret)) { + if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n", pdb_get_username(newpwd),dn)); - ldap_mods_free(mods,1); + ldap_mods_free(mods, True); return ret; } DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd))); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); return NT_STATUS_OK; } -/********************************************************************** - Housekeeping - *********************************************************************/ - -static void free_private_data(void **vp) -{ - struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; - - ldapsam_close(*ldap_state); - - if ((*ldap_state)->bind_secret) { - memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret)); - } - - ldapsam_close(*ldap_state); - - SAFE_FREE((*ldap_state)->bind_dn); - SAFE_FREE((*ldap_state)->bind_secret); - - *ldap_state = NULL; - - /* No need to free any further, as it is talloc()ed */ -} - /********************************************************************** *********************************************************************/ @@ -3083,19 +1620,20 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state, attr_list = get_attr_list(groupmap_attr_list); - rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, + rc = smbldap_search(ldap_state->smbldap_state, + lp_ldap_group_suffix (), scope, filter, attr_list, 0, result); free_attr_list( attr_list ); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0, ("ldapsam_search_one_group: " "Problem during the LDAP search: LDAP error: %s (%s)", ld_error?ld_error:"(unknown)", ldap_err2string(rc))); DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n", - lp_ldap_suffix(), filter)); + lp_ldap_group_suffix(), filter)); SAFE_FREE(ld_error); } @@ -3111,13 +1649,13 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, pstring temp; if (ldap_state == NULL || map == NULL || entry == NULL || - ldap_state->ldap_struct == NULL) + ldap_state->smbldap_state->ldap_struct == NULL) { DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n")); return False; } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -3128,7 +1666,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, map->gid = (gid_t)atol(temp); - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -3137,7 +1675,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, } string_to_sid(&map->sid, temp); - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -3152,11 +1690,11 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, return False; } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) { temp[0] = '\0'; - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) { DEBUG(0, ("Attributes cn not found either " @@ -3166,16 +1704,13 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, } fstrcpy(map->nt_name, temp); - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) { temp[0] = '\0'; } fstrcpy(map->comment, temp); - map->systemaccount = 0; - init_privilege(&map->priv_set); - return True; } @@ -3197,15 +1732,15 @@ static BOOL init_ldap_from_group(LDAP *ldap_struct, *mods = NULL; sid_to_string(tmp, &map->sid); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp); snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment); return True; @@ -3229,20 +1764,22 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods, return NT_STATUS_NO_SUCH_GROUP; } - count = ldap_count_entries(ldap_state->ldap_struct, result); + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { - DEBUG(4, ("Did not find group for filter %s\n", filter)); + DEBUG(4, ("Did not find group\n")); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; } if (count > 1) { DEBUG(1, ("Duplicate entries for filter %s: count=%d\n", filter, count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); if (!entry) { ldap_msgfree(result); @@ -3264,7 +1801,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods, *********************************************************************/ static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv) + DOM_SID sid) { pstring filter; @@ -3280,7 +1817,7 @@ static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, *********************************************************************/ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv) + gid_t gid) { pstring filter; @@ -3296,16 +1833,21 @@ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, *********************************************************************/ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv) + const char *name) { pstring filter; + char *escape_name = escape_ldap_string_alloc(name); - /* TODO: Escaping of name? */ + if (!escape_name) { + return NT_STATUS_NO_MEMORY; + } snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))", LDAP_OBJ_GROUPMAP, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), name, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), name); + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name, + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name); + + SAFE_FREE(escape_name); return ldapsam_getgroup(methods, filter, map); } @@ -3337,6 +1879,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, (struct ldapsam_privates *)methods->private_data; LDAPMessage *result = NULL; LDAPMod **mods = NULL; + int count; char *tmp; pstring dn; @@ -3347,7 +1890,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, int rc; if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy, - map->gid, False))) { + map->gid))) { DEBUG(0, ("Group %i already exists in LDAP\n", map->gid)); return NT_STATUS_UNSUCCESSFUL; } @@ -3357,22 +1900,27 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) { + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + + if ( count == 0 ) + return NT_STATUS_UNSUCCESSFUL; + + if (count > 1) { DEBUG(2, ("Group %i must exist exactly once in LDAP\n", map->gid)); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - tmp = ldap_get_dn(ldap_state->ldap_struct, entry); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); pstrcpy(dn, tmp); ldap_memfree(tmp); - if (!init_ldap_from_group(ldap_state->ldap_struct, + if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct, result, &mods, map)) { DEBUG(0, ("init_ldap_from_group failed!\n")); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -3384,15 +1932,14 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - make_a_mod(&mods, LDAP_MOD_ADD, "objectClass", - "sambaGroupMapping"); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP ); - rc = ldapsam_modify(ldap_state, dn, mods); - ldap_mods_free(mods, 1); + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); @@ -3424,16 +1971,16 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { DEBUG(0, ("No group to modify!\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->ldap_struct, entry); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); - if (!init_ldap_from_group(ldap_state->ldap_struct, + if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct, result, &mods, map)) { DEBUG(0, ("init_ldap_from_group failed\n")); ldap_msgfree(result); @@ -3447,13 +1994,13 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - rc = ldapsam_modify(ldap_state, dn, mods); + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); @@ -3509,24 +2056,24 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update) snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP); attr_list = get_attr_list( groupmap_attr_list ); - rc = ldapsam_search(ldap_state, lp_ldap_suffix(), + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(), LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &ldap_state->result); free_attr_list( attr_list ); 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)); + DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter)); ldap_msgfree(ldap_state->result); ldap_state->result = NULL; return NT_STATUS_UNSUCCESSFUL; } DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n", - ldap_count_entries(ldap_state->ldap_struct, + ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result))); - ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, ldap_state->result); + ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); ldap_state->index = 0; return NT_STATUS_OK; @@ -3550,10 +2097,6 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; BOOL bret = False; - /* The rebind proc needs this *HACK*. We are not multithreaded, so - this will work, but it's not nice. */ - static_ldap_state = ldap_state; - while (!bret) { if (!ldap_state->entry) return ret; @@ -3561,7 +2104,7 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, ldap_state->index++; bret = init_group_from_ldap(ldap_state, map, ldap_state->entry); - ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct, + ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->entry); } @@ -3574,7 +2117,7 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) + BOOL unix_only) { GROUP_MAP map; GROUP_MAP *mapt; @@ -3622,6 +2165,22 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, } /********************************************************************** + Housekeeping + *********************************************************************/ + +static void free_private_data(void **vp) +{ + struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; + + smbldap_free_struct(&(*ldap_state)->smbldap_state); + + *ldap_state = NULL; + + /* No need to free any further, as it is talloc()ed */ +} + +/********************************************************************** + Intitalise the parts of the pdb_context that are common to all pdb_ldap modes *********************************************************************/ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, @@ -3655,26 +2214,21 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** /* TODO: Setup private data and free */ - ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates)); - + ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state)); if (!ldap_state) { DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); return NT_STATUS_NO_MEMORY; } - if (location) { - ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location); - } else { - ldap_state->uri = "ldap://localhost"; - } + if (!NT_STATUS_IS_OK(nt_status = + smbldap_init(pdb_context->mem_ctx, location, + &ldap_state->smbldap_state))); ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name()); if (!ldap_state->domain_name) { return NT_STATUS_NO_MEMORY; } - sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); - (*pdb_method)->private_data = ldap_state; (*pdb_method)->free_private_data = free_private_data; @@ -3683,6 +2237,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** } /********************************************************************** + Initialise the 'compat' mode for pdb_ldap *********************************************************************/ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) @@ -3690,21 +2245,8 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS ** NTSTATUS nt_status; struct ldapsam_privates *ldap_state; - if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { - return nt_status; - } - - (*pdb_method)->name = "ldapsam_compat"; - - ldap_state = (*pdb_method)->private_data; - ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT; - - if (location) { - ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location); - } else { -#ifndef WITH_LDAP_SAMCONFIG - ldap_state->uri = "ldap://localhost"; -#else +#ifdef WITH_LDAP_SAMCONFIG + if (!location) { int ldap_port = lp_ldap_port(); /* remap default port if not using SSL (ie clear or TLS) */ @@ -3712,25 +2254,42 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS ** ldap_port = 389; } - ldap_state->uri = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port); - if (!ldap_state->uri) { + location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port); + if (!location) { return NT_STATUS_NO_MEMORY; } + } #endif + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { + return nt_status; } + (*pdb_method)->name = "ldapsam_compat"; + + ldap_state = (*pdb_method)->private_data; + ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT; + + sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); + return NT_STATUS_OK; } /********************************************************************** + Initialise the normal mode for pdb_ldap *********************************************************************/ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; struct ldapsam_privates *ldap_state; - uint32 low_idmap_uid, high_idmap_uid; - uint32 low_idmap_gid, high_idmap_gid; + uint32 alg_rid_base; + pstring alg_rid_base_string; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + DOM_SID ldap_domain_sid; + DOM_SID secrets_domain_sid; + pstring domain_sid_string; if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { return nt_status; @@ -3739,23 +2298,57 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met (*pdb_method)->name = "ldapsam"; ldap_state = (*pdb_method)->private_data; - ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; - ldap_state->permit_non_unix_accounts = False; + ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; + + /* Try to setup the Domain Name, Domain SID, algorithmic rid base */ + + nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result, + ldap_state->domain_name, True); + + if ( !NT_STATUS_IS_OK(nt_status) ) { + DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n")); + DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, " + "and will risk BDCs having inconsistant SIDs\n")); + sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); + return NT_STATUS_OK; + } - /* check for non-unix account ranges */ + /* Given that the above might fail, everything below this must be optional */ + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + if (!entry) { + DEBUG(0, ("Could not get domain info entry\n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } - if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid) - && lp_idmap_gid(&low_idmap_gid, &high_idmap_gid)) + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + domain_sid_string)) { - DEBUG(2, ("Enabling non-unix account ranges\n")); - - ldap_state->permit_non_unix_accounts = True; + BOOL found_sid; + string_to_sid(&ldap_domain_sid, domain_sid_string); + found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid); + if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) { + /* reset secrets.tdb sid */ + secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid); + } + sid_copy(&ldap_state->domain_sid, &ldap_domain_sid); + } - ldap_state->low_allocated_user_rid = fallback_pdb_uid_to_user_rid(low_idmap_uid); - ldap_state->high_allocated_user_rid = fallback_pdb_uid_to_user_rid(high_idmap_uid); - ldap_state->low_allocated_group_rid = pdb_gid_to_group_rid(low_idmap_gid); - ldap_state->high_allocated_group_rid = pdb_gid_to_group_rid(high_idmap_gid); + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE), + alg_rid_base_string)) + { + alg_rid_base = (uint32)atol(alg_rid_base_string); + if (alg_rid_base != algorithmic_rid_base()) { + DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n" + "database was initialised. Aborting. \n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } } + ldap_msgfree(result); return NT_STATUS_OK; } -- cgit