[PATCH] smb_register_idmap()
Jelmer Vernooij
jelmer at nl.linux.org
Wed May 14 08:26:25 GMT 2003
Just took a quick look at this patch:
Please don't use module_path_get_name() anymore... Also, why did you
remove the autorebuilding of the rpc stuff on modification of the
Makefile?
Jelmer
On Wed, May 14, 2003 at 10:06:46AM +0200, Stefan (metze) Metzmacher wrote about '[PATCH] smb_register_idmap()':
> Hi Simo,
> here's the smb_register_idmap() patch...
> and a fixed version of idmap_ldap.c
> - but it needs to converted to the new schema system
> - and I'm not sure if there're some ldap_free_*()'s missing in some
> places...
> Anthony can you check that please.
> metze
> -----------------------------------------------------------------------------
> Stefan "metze" Metzmacher <metze at metzemix.de>
> /*
> Unix SMB/CIFS implementation.
> idmap LDAP backend
> Copyright (C) Tim Potter 2000
> Copyright (C) Anthony Liguori 2003
> Copyright (C) Simo Sorce 2003
> This program is free software; you can redistribute it and/or modify
> it under the terms of the GNU General Public License as published by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> */
> #include "includes.h"
> #undef DBGC_CLASS
> #define DBGC_CLASS DBGC_IDMAP
> #include <lber.h>
> #include <ldap.h>
> struct ldap_idmap_state {
> LDAP *ldap_struct;
> time_t last_ping;
> const char *uri;
> char *bind_dn;
> char *bind_secret;
> unsigned int num_failures;
> struct ldap_idmap_state *prev, *next;
> };
> #define LDAP_IDMAP_DONT_PING_TIME 10 /* ping only all 10 seconds */
> #define LDAP_MAX_ALLOC_ID 128 /* number tries while allocating
> new id */
> static struct ldap_idmap_state ldap_state;
> static int ldap_idmap_connect_system(struct ldap_idmap_state *state);
> static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type);
> static NTSTATUS ldap_idmap_close(void);
> /*******************************************************************
> 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);
> *pw = smb_xstrdup(old_style_pw);
> }
> return True;
> }
> /*******************************************************************
> open a connection to the ldap server.
> ******************************************************************/
> static int ldap_idmap_open_connection(struct ldap_idmap_state *state)
> {
> int rc = LDAP_SUCCESS;
> int version;
> BOOL ldap_v3 = False;
> #ifdef HAVE_LDAP_INITIALIZE
> DEBUG(10, ("ldap_idmap_open_connection: %s\n", state->uri));
> if ((rc = ldap_initialize(&state->ldap_struct, state->uri))
> != LDAP_SUCCESS) {
> DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
> return rc;
> }
> #else
> /* Parse the string manually */
> {
> int port = 0;
> fstring protocol;
> fstring host;
> const char *p = 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 ((state->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 (state->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,("ldap_idmap_open_connection: Secure "
> "connection not supported by LDAP client "
> "libraries!\n"));
> return LDAP_OPERATIONS_ERROR;
> #endif
> }
> }
> #endif
> if (ldap_get_option(state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION,
> &version) == LDAP_OPT_SUCCESS) {
> if (version != LDAP_VERSION3) {
> version = LDAP_VERSION3;
> if (ldap_set_option(state->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(state->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,("ldap_idmap_open_connection: StartTLS not supported by "
> "LDAP client libraries!\n"));
> return LDAP_OPERATIONS_ERROR;
> #endif
> }
> DEBUG(2, ("ldap_idmap_open_connection: connection opened\n"));
> return rc;
> }
> /**********************************************************************
> Connect to LDAP server
> *********************************************************************/
> static int ldap_idmap_open(struct ldap_idmap_state *state)
> {
> int rc;
> SMB_ASSERT(state);
> #ifndef NO_LDAP_SECURITY
> if (geteuid() != 0) {
> DEBUG(0,
> ("ldap_idmap_open: cannot access LDAP when not root\n"));
> return LDAP_INSUFFICIENT_ACCESS;
> }
> #endif
> if ((state->ldap_struct != NULL) &&
> ((state->last_ping + LDAP_IDMAP_DONT_PING_TIME)<time(NULL))) {
> struct sockaddr_un addr;
> socklen_t len = sizeof(addr);
> int sd;
> if (!ldap_get_option(state->ldap_struct, LDAP_OPT_DESC, &sd)&&
> getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
> /* the other end has died. reopen. */
> ldap_unbind_ext(state->ldap_struct, NULL, NULL);
> state->ldap_struct = NULL;
> state->last_ping = (time_t)0;
> } else {
> state->last_ping = time(NULL);
> }
> }
> if (state->ldap_struct != NULL) {
> DEBUG(5,("ldap_idmap_open: already connected to the LDAP "
> "server\n"));
> return LDAP_SUCCESS;
> }
> if ((rc = ldap_idmap_open_connection(state))) {
> return rc;
> }
> if ((rc = ldap_idmap_connect_system(state))) {
> ldap_unbind_ext(state->ldap_struct, NULL, NULL);
> state->ldap_struct = NULL;
> return rc;
> }
> state->last_ping = time(NULL);
> DEBUG(4,("The LDAP server is succesful connected\n"));
> return LDAP_SUCCESS;
> }
> static int ldap_idmap_retry_open(struct ldap_idmap_state *state, int *attempts)
> {
> int rc;
> SMB_ASSERT(state && attempts);
> if (*attempts != 0) {
> unsigned int sleep_time;
> uint8 rand_byte = 128; /* a reasonable place to start */
> generate_random_buffer(&rand_byte, 1, False);
> 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 = ldap_idmap_open(state))) {
> DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",
> *attempts));
> return rc;
> }
> return LDAP_SUCCESS;
> }
> /*******************************************************************
> a rebind function for authenticated referrals
> This version takes a void* that we can shove useful stuff in :-)
> ******************************************************************/
> #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)
> {
> struct ldap_idmap_state *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",
> state->bind_dn));
> *whop = strdup(state->bind_dn);
> if (!*whop) {
> return LDAP_NO_MEMORY;
> }
> *credp = strdup(state->bind_secret);
> if (!*credp) {
> SAFE_FREE(*whop);
> return LDAP_NO_MEMORY;
> }
> *methodp = LDAP_AUTH_SIMPLE;
> }
> 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 ldap_idmap_state *state = arg;
> int rc;
> DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
> 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? */
> rc = ldap_simple_bind_s(ldap_struct, state->bind_dn,
> state->bind_secret);
> 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, &ldap_state);
> }
> # endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
> #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
> /*******************************************************************
> 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, &ldap_state);
> }
> # 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.
> ******************************************************************/
> static int ldap_idmap_connect_system(struct ldap_idmap_state *state)
> {
> int rc;
> char *ldap_dn;
> char *ldap_secret;
> /* get the password */
> if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret))
> {
> DEBUG(0, ("ldap_idmap_connect_system: Failed to retrieve "
> "password from secrets.tdb\n"));
> return LDAP_INVALID_CREDENTIALS;
> }
> state->bind_dn = ldap_dn;
> state->bind_secret = ldap_secret;
> /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite
> (OpenLDAP) doesnt' seem to support it */
> DEBUG(10,("ldap_idmap_connect_system: Binding to ldap server %s as "
> "\"%s\"\n", 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(state->ldap_struct, &rebindproc_connect);
> # endif
> # if LDAP_SET_REBIND_PROC_ARGS == 3
> ldap_set_rebind_proc(state->ldap_struct,
> &rebindproc_connect_with_state, (void *)state);
> # endif
> #else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
> # if LDAP_SET_REBIND_PROC_ARGS == 2
> ldap_set_rebind_proc(state->ldap_struct, &rebindproc);
> # endif
> # if LDAP_SET_REBIND_PROC_ARGS == 3
> ldap_set_rebind_proc(state->ldap_struct, &rebindproc_with_state,
> (void *)state);
> # endif
> #endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
> rc = ldap_simple_bind_s(state->ldap_struct, ldap_dn, ldap_secret);
> if (rc != LDAP_SUCCESS) {
> char *ld_error = NULL;
> ldap_get_option(state->ldap_struct, LDAP_OPT_ERROR_STRING,
> &ld_error);
> DEBUG(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);
> state->num_failures++;
> return rc;
> }
> state->num_failures = 0;
> DEBUG(3, ("ldap_idmap_connect_system: succesful connection to the "
> "LDAP server\n"));
> return rc;
> }
> static int ldap_idmap_search(struct ldap_idmap_state *state,
> const char *base, int scope, const char *filter,
> const char *attrs[], int attrsonly,
> LDAPMessage **res)
> {
> int rc = LDAP_SERVER_DOWN;
> int attempts = 0;
> char *utf8_filter;
> SMB_ASSERT(state);
> if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) {
> return LDAP_NO_MEMORY;
> }
> while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) {
> if ((rc = ldap_idmap_retry_open(state, &attempts)) !=
> LDAP_SUCCESS) continue;
> rc = ldap_search_s(state->ldap_struct, base, scope,
> utf8_filter, (char**)attrs, attrsonly, res);
> }
> if (rc == LDAP_SERVER_DOWN) {
> DEBUG(0,("ldap_idmap_search: LDAP server is down!\n"));
> ldap_idmap_close();
> }
> SAFE_FREE(utf8_filter);
> return rc;
> }
> /*******************************************************************
> search an attribute and return the first value found.
> ******************************************************************/
> static BOOL ldap_idmap_attribute (struct ldap_idmap_state *state,
> LDAPMessage * entry,
> const char *attribute, pstring value)
> {
> char **values;
> value[0] = '\0';
> if ((values = ldap_get_values (state->ldap_struct, entry, attribute))
> == NULL) {
> DEBUG(10,("get_single_attribute: [%s] = [<does not exist>]\n",
> attribute));
> return False;
> }
> if (convert_string(CH_UTF8, CH_UNIX,
> values[0], -1,
> value, sizeof(pstring)) == (size_t)-1)
> {
> DEBUG(1, ("ldap_idmap_attribute: string conversion of [%s] = "
> "[%s] failed!\n", attribute, values[0]));
> ldap_value_free(values);
> return False;
> }
> ldap_value_free(values);
> return True;
> }
> static const char *attrs[] = {"objectClass", "uidNumber", "gidNumber",
> "ntSid", NULL};
> static const char *pool_attr[] = {"uidNumber", "gidNumber", NULL};
> static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
> {
> NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> int rc = LDAP_SERVER_DOWN;
> int count = 0;
> LDAPMessage *result = 0;
> LDAPMessage *entry = 0;
> pstring id_str, new_id_str;
> LDAPMod mod[2];
> LDAPMod *mods[3];
> const char *type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
> char *val[4];
> char *dn;
> rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(),
> LDAP_SCOPE_SUBTREE, "(objectClass=unixIdPool)",
> pool_attr, 0, &result);
> if (rc != LDAP_SUCCESS) {
> DEBUG(0,("ldap_allocate_id: unixIdPool object not found\n"));
> goto out;
> }
> count = ldap_count_entries(ldap_state.ldap_struct, result);
> if (count != 1) {
> DEBUG(0,("ldap_allocate_id: single unixIdPool not found\n"));
> goto out;
> }
> dn = ldap_get_dn(ldap_state.ldap_struct, result);
> entry = ldap_first_entry(ldap_state.ldap_struct, result);
> if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) {
> DEBUG(0,("ldap_allocate_id: %s attribute not found\n",
> type));
> goto out;
> }
> if (id_type & ID_USERID) {
> id->uid = strtoul(id_str, NULL, 10);
> } else {
> id->gid = strtoul(id_str, NULL, 10);
> }
> mod[0].mod_op = LDAP_MOD_DELETE;
> mod[0].mod_type = strdup(type);
> val[0] = id_str; val[1] = NULL;
> mod[0].mod_values = val;
> pstr_sprintf(new_id_str, "%ud",
> ((id_type & ID_USERID) ? id->uid : id->gid) + 1);
> mod[1].mod_op = LDAP_MOD_ADD;
> mod[1].mod_type = strdup(type);
> val[3] = new_id_str; val[4] = NULL;
> mod[1].mod_values = val + 2;
> mods[0] = mod; mods[1] = mod + 1; mods[2] = NULL;
> rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods);
> ldap_memfree(dn);
> if (rc == LDAP_SUCCESS) ret = NT_STATUS_OK;
> out:
> return ret;
> }
> /* Get a sid from an id */
> static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
> {
> LDAPMessage *result = 0;
> LDAPMessage *entry = 0;
> pstring sid_str;
> pstring filter;
> char type = (id_type & ID_USERID) ? 'u' : 'g';
> int rc;
> int count;
> NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> pstr_sprintf(filter, "(&(%cidNumber=%ud)(objectClass=sambaAccount))",
> type, ((id_type & ID_USERID) ? id.uid : id.gid));
> rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(),
> LDAP_SCOPE_SUBTREE, filter, attrs, 0,
> &result);
> if (rc != LDAP_SUCCESS) {
> goto out;
> }
> count = ldap_count_entries(ldap_state.ldap_struct, result);
> if (count == 0) {
> pstr_sprintf(filter,
> "(&(objectClass=idmapEntry)(%cidNumber=%ud))",
> type, ((id_type & ID_USERID) ? id.uid : id.gid));
> rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(),
> LDAP_SCOPE_SUBTREE, filter,
> attrs, 0, &result);
> if (rc != LDAP_SUCCESS) {
> goto out;
> }
> count = ldap_count_entries(ldap_state.ldap_struct, result);
> }
> if (count != 1) {
> DEBUG(0,("ldap_get_sid_from_id: mapping not found for "
> "%cid: %ud\n", (id_type&ID_USERID)?'u':'g',
> ((id_type & ID_USERID) ? id.uid : id.gid)));
> goto out;
> }
> entry = ldap_first_entry(ldap_state.ldap_struct, result);
> if (!ldap_idmap_attribute(&ldap_state, entry, "ntSid", sid_str)) {
> goto out;
> }
> if (!string_to_sid(sid, sid_str)) {
> goto out;
> }
> ret = NT_STATUS_OK;
> out:
> return ret;
> }
> /* Get an id from a sid */
> static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type,
> const DOM_SID *sid)
> {
> LDAPMessage *result = 0;
> LDAPMessage *entry = 0;
> pstring sid_str;
> pstring filter;
> pstring id_str;
> const char *type = (*id_type & ID_USERID) ? "uidNumber" : "gidNumber";
> const char *class =
> (*id_type & ID_USERID) ? "sambaAccount" : "sambaGroupMapping";
> int rc;
> int count;
> NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
> sid_to_string(sid_str, sid);
> pstr_sprintf(filter, "(&(objectClass=%s)(ntSid=%s)", class, sid_str);
> rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(),
> LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result);
> if (rc != LDAP_SUCCESS) {
> goto out;
> }
> count = ldap_count_entries(ldap_state.ldap_struct, result);
> if (count == 0) {
> pstr_sprintf(filter,
> "(&(objectClass=idmapEntry)(ntSid=%s))", sid_str);
> rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(),
> LDAP_SCOPE_SUBTREE, filter,
> attrs, 0, &result);
> if (rc != LDAP_SUCCESS) {
> goto out;
> }
> count = ldap_count_entries(ldap_state.ldap_struct, result);
> }
> /* our search filters may 2 objects in the case that a user and group
> rid are the same */
> if (count != 1 && count != 2) {
> DEBUG(0,
> ("ldap_get_id_from_sid: incorrect number of objects\n"));
> goto out;
> }
> entry = ldap_first_entry(ldap_state.ldap_struct, result);
> if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) {
> entry = ldap_next_entry(ldap_state.ldap_struct, entry);
> if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) {
> int i;
> for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
> ret = ldap_allocate_id(id, *id_type);
> if (NT_STATUS_IS_OK(ret)) {
> break;
> }
> }
> if (NT_STATUS_IS_OK(ret)) {
> ret = ldap_set_mapping(sid, *id, *id_type);
> } else {
> DEBUG(0,("ldap_allocate_id: cannot acquire id"
> " lock\n"));
> }
> } else {
> if ((*id_type & ID_USERID)) {
> id->uid = strtoul(id_str, NULL, 10);
> } else {
> id->gid = strtoul(id_str, NULL, 10);
> }
> ret = NT_STATUS_OK;
> }
> } else {
> if ((*id_type & ID_USERID)) {
> id->uid = strtoul(id_str, NULL, 10);
> } else {
> id->gid = strtoul(id_str, NULL, 10);
> }
> ret = NT_STATUS_OK;
> }
> out:
> return ret;
> }
> /* This function cannot be called to modify a mapping, only set a new one */
> static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
> {
> pstring dn, sid_str, id_str;
> const char *type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
> LDAPMod *mods[3];
> LDAPMod mod[2];
> char *val[4];
> int rc;
> int attempts = 0;
> pstr_sprintf(id_str, "%ud", ((id_type & ID_USERID) ? id.uid : id.gid));
> sid_to_string(sid_str, sid);
> pstr_sprintf(dn, "%s=%ud,%s", type, ((id_type & ID_USERID) ? id.uid : id.gid), lp_ldap_suffix());
> mod[0].mod_op = LDAP_MOD_REPLACE;
> mod[0].mod_type = strdup(type);
> val[0] = id_str; val[1] = NULL;
> mod[0].mod_values = val;
> mod[1].mod_op = LDAP_MOD_REPLACE;
> mod[1].mod_type = strdup("ntSid");
> val[2] = sid_str; val[3] = NULL;
> mod[1].mod_values = val + 2;
> mods[0] = mod; mods[1] = mod + 1; mods[2] = NULL;
> do {
> if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) !=
> LDAP_SUCCESS) continue;
> rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods);
> } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8));
> if (rc != LDAP_SUCCESS) {
> return NT_STATUS_UNSUCCESSFUL;
> }
> return NT_STATUS_OK;
> }
> /*****************************************************************************
> Initialise idmap database.
> *****************************************************************************/
> static NTSTATUS ldap_idmap_init(void)
> {
> /* We wait for the first search request before we try to connect to
> the LDAP server. We may want to connect upon initialization though
> -- aliguori */
> return NT_STATUS_OK;
> }
> /* End the LDAP session */
> static NTSTATUS ldap_idmap_close(void)
> {
> if (ldap_state.ldap_struct != NULL) {
> ldap_unbind_ext(ldap_state.ldap_struct, NULL, NULL);
> ldap_state.ldap_struct = NULL;
> }
> DEBUG(5,("The connection to the LDAP server was closed\n"));
> /* maybe free the results here --metze */
> return NT_STATUS_OK;
> }
> /* This function doesn't make as much sense in an LDAP world since the calling
> node doesn't really control the ID ranges */
> static void ldap_idmap_status(void)
> {
> DEBUG(0, ("LDAP IDMAP Status not available\n"));
> }
> static struct idmap_methods ldap_methods = {
> ldap_idmap_init,
> ldap_get_sid_from_id,
> ldap_get_id_from_sid,
> ldap_set_mapping,
> ldap_idmap_close,
> ldap_idmap_status
> };
> NTSTATUS idmap_ldap_init(void)
> {
> DEBUG(0,("idmap_reg_ldap: no LDAP support\n"));
> return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &ldap_methods);
> }
--
Jelmer Vernooij <jelmer at samba.org>
~/.plan:
More information about the samba-technical
mailing list