int ldap_initialize(LDAP **ldp, char *url) { int rc = 0; LDAP *ld = NULL; LDAPURLDesc *ludp = NULL; /* * For now, we don't use any DN that may be provided. And on Solaris * (based on Mozilla's LDAP client code), we need the _nodn form to parse * "ldap://host" without a trailing slash. * * Also, this version won't handle an input string which contains multiple * URLs, unlike the OpenLDAP ldap_initialize. See * https://bugzilla.mozilla.org/show_bug.cgi?id=353336#c1 . */ #ifdef HAVE_LDAP_URL_PARSE_NODN rc = ldap_url_parse_nodn(url, &ludp); #else rc = ldap_url_parse(url, &ludp); #endif if (rc == 0) { ld = ldap_init(ludp->lud_host, ludp->lud_port); if (ld != NULL) *ldp = ld; else rc = KRB5_KDB_ACCESS_ERROR; ldap_free_urldesc(ludp); } return rc; }
void OPENLDAP::BookInfoParse (struct BookInfo &info) { LDAPURLDesc *url_tmp; std::string uri; size_t pos; ldap_url_parse (info.uri.c_str(), &url_tmp); if (url_tmp->lud_exts) { for (int i=0; url_tmp->lud_exts[i]; i++) { if (!g_ascii_strcasecmp(url_tmp->lud_exts[i], "StartTLS")) { info.starttls = true; } else if (!g_ascii_strncasecmp(url_tmp->lud_exts[i], "SASL", 4)) { info.sasl = true; if (url_tmp->lud_exts[i][4] == '=') info.saslMech = std::string(url_tmp->lud_exts[i]+5); } } } info.urld = boost::shared_ptr<LDAPURLDesc> (url_tmp, ldap_url_desc_deleter ()); pos = info.uri.find ('/', strlen(info.urld->lud_scheme) + 3); if (pos != std::string::npos) info.uri_host = info.uri.substr (0,pos); else info.uri_host = info.uri; }
/// sets LDAP server's URI /// @param[in] cnf reference to common configuration struct /// @param[in] arg value of the command line argument int ldaputils_config_set_uri(LdapUtilsConfig * cnf, const char * arg) { if ((cnf->ludp)) { if (cnf->host == cnf->ludp->lud_host) cnf->host = NULL; ldap_free_urldesc(cnf->ludp); }; cnf->ludp = NULL; if (!(cnf->uri = arg)) return(0); if ((ldap_url_parse(arg, &cnf->ludp))) { // TRANSLATORS: The following strings provide an error message if the // URI provided on the command line is an invalid LDAP URI. fprintf(stderr, _("%s: invalid LDAP URI\n"), PROGRAM_NAME); fprintf(stderr, _("Try `%s --help' for more information.\n"), PROGRAM_NAME); return(1); }; cnf->host = cnf->ludp->lud_host; cnf->port = cnf->ludp->lud_port; return(0); }
/* **| method: void create ( string uri ); ** **| Create a new OpenLDAP client connection object. ** **| name: create - create the object ** **| arg: string uri **| An URI pointing to the LDAP host to connect to as described in **| RFC 2255. The LDAP URI has the general format: **| **| # ldap://hostport/dn[?attrs[?scope[?filter[?exts]]]] **| **| where **| hostport is a host name with an optional ":portnumber" **| dn is the search base **| attrs is a comma separated list of attributes to request **| scope is one of these three strings: **| base one sub (default=base) **| filter is filter **| exts are recognized set of LDAP and/or API extensions. **| **| Documentation to this function has been written based on the **| OpenLDAP v2 ldap_url_parse(3) manual page. ** **| see_also: ldap_url_parse(3), RFC 2255 */ static void f_create(INT32 args) { if (args != 1) Pike_error("OpenLDAP.Client->create():: wrong number of arguments\n"); if (ARG(1).type != T_STRING || ARG(1).u.string->size_shift > 0) Pike_error("OpenLDAP.Client->create():: expecting an 8-bit string as the first argument (%u)\n", ARG(1).u.string->size_shift); if ((THIS->lerrno = ldap_url_parse(ARG(1).u.string->str, &THIS->server_url))) Pike_error("OpenLDAP.Client->create():: badly formed server URL\n"); if (!THIS) Pike_error("Serious problem - no THIS...\n"); THIS->conn = ldap_init(THIS->server_url->lud_host, THIS->server_url->lud_port); if (!THIS->conn) Pike_error("OpenLDAP.Client->create():: error initializing OpenLDAP: '%s'\n", strerror(errno)); pop_n_elems(args); }
static CURLcode ldap_setup_connection(struct connectdata *conn) { ldapconninfo *li; LDAPURLDesc *lud; struct SessionHandle *data=conn->data; int rc, proto; CURLcode status; rc = ldap_url_parse(data->change.url, &lud); if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { if(rc == LDAP_URL_ERR_MEM) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } failf(conn->data, "LDAP local: %s", msg); return status; } proto = ldap_pvt_url_scheme2proto(lud->lud_scheme); ldap_free_urldesc(lud); li = calloc(1, sizeof(ldapconninfo)); if(!li) return CURLE_OUT_OF_MEMORY; li->proto = proto; conn->proto.generic = li; connkeep(conn, "OpenLDAP default"); /* TODO: * - provide option to choose SASL Binds instead of Simple */ return CURLE_OK; }
/* a bit dirty but leak free */ char * ldap_parse_servers(const char * servers) { char * s = NULL; char * tmp = NULL, *urls[32]; unsigned int num = 0 , i = 0 , asize = 0; LDAPURLDesc *urld[32]; if (!servers) return NULL; /* local copy of the arg */ s = strdup(servers); if (!s) return NULL; /* first separate into URL tokens */ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0) return NULL; i = 0; while (urls[i]) { if (! ldap_is_ldap_url(urls[i]) || (ldap_url_parse(urls[i], &urld[i]) != 0)) { return NULL; } i++; } /* now free(s) */ free (s); /* how much memory do we need */ num = i; for (i = 0 ; i < num ; i++) asize += strlen(urld[i]->lud_host)+11; /* alloc */ s = (char *) calloc( asize+1 , sizeof(char)); if (!s) { for (i = 0 ; i < num ; i++) ldap_free_urldesc(urld[i]); return NULL; } /* then build the final host string */ for (i = 0 ; i < num ; i++) { /* built host part */ tmp = ldap_build_host(urld[i]->lud_host, urld[i]->lud_port); strncat(s, tmp, strlen(tmp)); ldap_free_urldesc(urld[i]); free(tmp); } return s; }
static int do_uri_explode( const char *uri ) { LDAPURLDesc *lud; int rc; rc = ldap_url_parse( uri, &lud ); if ( rc != LDAP_URL_SUCCESS ) { fprintf( stderr, "unable to parse URI \"%s\"\n", uri ); return 1; } if ( lud->lud_scheme != NULL && lud->lud_scheme[0] != '\0' ) { printf( "scheme: %s\n", lud->lud_scheme ); } if ( lud->lud_host != NULL && lud->lud_host[0] != '\0' ) { printf( "host: %s\n", lud->lud_host ); } if ( lud->lud_port != 0 ) { printf( "port: %d\n", lud->lud_port ); } if ( lud->lud_dn != NULL && lud->lud_dn[0] != '\0' ) { printf( "dn: %s\n", lud->lud_dn ); } if ( lud->lud_attrs != NULL ) { int i; for ( i = 0; lud->lud_attrs[i] != NULL; i++ ) { printf( "selector: %s\n", lud->lud_attrs[i] ); } } if ( lud->lud_scope != LDAP_SCOPE_DEFAULT ) { printf( "scope: %s\n", ldap_pvt_scope2str( lud->lud_scope ) ); } if ( lud->lud_filter != NULL && lud->lud_filter[0] != '\0' ) { printf( "filter: %s\n", lud->lud_filter ); } if ( lud->lud_exts != NULL ) { int i; for ( i = 0; lud->lud_exts[i] != NULL; i++ ) { printf( "extension: %s\n", lud->lud_exts[i] ); } } return 0; }
static int get_read_entries( char *filename, char *entries[], char *filters[] ) { FILE *fp; int entry = 0; if ( (fp = fopen( filename, "r" )) != NULL ) { char line[BUFSIZ]; while (( entry < MAXREQS ) && ( fgets( line, BUFSIZ, fp ))) { char *nl; if (( nl = strchr( line, '\r' )) || ( nl = strchr( line, '\n' ))) *nl = '\0'; if ( filters != NULL && line[0] == '+' ) { LDAPURLDesc *lud; if ( ldap_url_parse( &line[1], &lud ) != LDAP_URL_SUCCESS ) { entry = -entry - 1; break; } if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) { ldap_free_urldesc( lud ); entry = -entry - 1; break; } entries[entry] = ArgDup( lud->lud_dn ); if ( lud->lud_filter ) { filters[entry] = ArgDup( lud->lud_filter ); } else { filters[entry] = ArgDup( "(objectClass=*)" ); } ldap_free_urldesc( lud ); } else { if ( filters != NULL ) filters[entry] = NULL; entries[entry] = ArgDup( line ); } entry++; } fclose( fp ); } return( entry ); }
int ldap_url_search_async( char* _ldap_url, int* _ld_result_count, int* _msgidp, struct ld_session **ldsp) { LDAPURLDesc *ludp; int rc; if (ldap_url_parse(_ldap_url, &ludp) != 0) { LM_ERR("invalid LDAP URL [%s]\n", ZSW(_ldap_url)); if (ludp != NULL) { ldap_free_urldesc(ludp); } return -2; } if (ludp->lud_host == NULL) { LM_ERR( "no ldap session name found in ldap URL [%s]\n", ZSW(_ldap_url)); return -2; } LM_DBG( "LDAP URL parsed into session_name" " [%s], base [%s], scope [%d], filter [%s]\n", ZSW(ludp->lud_host), ZSW(ludp->lud_dn), ludp->lud_scope, ZSW(ludp->lud_filter)); rc = ldap_params_search_async(_ld_result_count, _msgidp, ludp->lud_host, ludp->lud_dn, ludp->lud_scope, ludp->lud_attrs, ludp->lud_filter); if (rc == 0 && *_msgidp >= 0) { if (get_connected_ldap_session(ludp->lud_host, ldsp)) { LM_ERR("[%s]: couldn't get ldap session\n", ludp->lud_host); return -1; } } ldap_free_urldesc(ludp); return rc; }
static CURLcode ldap_do(struct connectdata *conn, bool *done) { ldapconninfo *li = conn->proto.generic; ldapreqinfo *lr; CURLcode status = CURLE_OK; int rc = 0; LDAPURLDesc *ludp = NULL; int msgid; struct SessionHandle *data=conn->data; connkeep(conn, "OpenLDAP do"); infof(data, "LDAP local: %s\n", data->change.url); rc = ldap_url_parse(data->change.url, &ludp); if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; status = CURLE_URL_MALFORMAT; if(rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) { if(rc == LDAP_URL_ERR_MEM) status = CURLE_OUT_OF_MEMORY; msg = url_errs[rc]; } failf(conn->data, "LDAP local: %s", msg); return status; } rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, NULL, NULL, NULL, 0, &msgid); ldap_free_urldesc(ludp); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc)); return CURLE_LDAP_SEARCH_FAILED; } lr = calloc(1, sizeof(ldapreqinfo)); if(!lr) return CURLE_OUT_OF_MEMORY; lr->msgid = msgid; data->req.protop = lr; Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL); *done = TRUE; return CURLE_OK; }
nsresult nsLDAPURL::SetPathInternal(const nsCString &aPath) { LDAPURLDesc *desc; // This is from the LDAP C-SDK, which currently doesn't // support everything from RFC 2255... :( // int err = ldap_url_parse(aPath.get(), &desc); switch (err) { case LDAP_SUCCESS: { // The base URL can pick up the host & port details and deal with them // better than we can mDN = desc->lud_dn; mScope = desc->lud_scope; mFilter = desc->lud_filter; mOptions = desc->lud_options; nsresult rv = SetAttributeArray(desc->lud_attrs); if (NS_FAILED(rv)) return rv; ldap_free_urldesc(desc); return NS_OK; } case LDAP_URL_ERR_NOTLDAP: case LDAP_URL_ERR_NODN: case LDAP_URL_ERR_BADSCOPE: return NS_ERROR_MALFORMED_URI; case LDAP_URL_ERR_MEM: NS_ERROR("nsLDAPURL::SetSpec: out of memory "); return NS_ERROR_OUT_OF_MEMORY; case LDAP_URL_ERR_PARAM: return NS_ERROR_INVALID_POINTER; } // This shouldn't happen... return NS_ERROR_UNEXPECTED; }
int add_ldap_test(testitem_t *t) { #ifdef BBGEN_LDAP ldap_data_t *req; LDAPURLDesc *ludp; char *urltotest; /* * t->testspec containts the full testspec * We need to remove any URL-encoding. */ urltotest = urlunescape(t->testspec); if (ldap_url_parse(urltotest, &ludp) != 0) { errprintf("Invalid LDAP URL %s\n", t->testspec); return 1; } /* Allocate the private data and initialize it */ t->privdata = (void *) malloc(sizeof(ldap_data_t)); req = (ldap_data_t *) t->privdata; req->ldapdesc = (void *) ludp; req->usetls = (strncmp(urltotest, "ldaps:", 6) == 0); #ifdef BBGEN_LDAP_USESTARTTLS if (req->usetls && (ludp->lud_port == LDAPS_PORT)) { dbgprintf("Forcing port %d for ldaps with STARTTLS\n", LDAP_PORT ); ludp->lud_port = LDAP_PORT; } #endif req->ldapstatus = 0; req->output = NULL; req->ldapcolor = -1; req->faileddeps = NULL; req->duration.tv_sec = req->duration.tv_nsec = 0; req->certinfo = NULL; req->certexpires = 0; #endif return 0; }
// }}} // {{{AuthLDAP bool AuthLDAP::setup() { LDAPURLDesc* urlDescription; LDAP* ldap; std::string url("dc=trapni,dc=de"); int rv = ldap_url_parse(url.c_str(), &urlDescription); if (rv != LDAP_SUCCESS) { return false; } int ldapVersion = LDAP_VERSION3; ldap_set_option(nullptr, LDAP_OPT_PROTOCOL_VERSION, &ldapVersion); timeval timeout = { 10, 0 }; ldap_set_option(nullptr, LDAP_OPT_NETWORK_TIMEOUT, &timeout); int reqcert = LDAP_OPT_X_TLS_ALLOW; ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &reqcert); rv = ldap_initialize(&ldap, url.c_str()); }
/** * seahorse_ldap_is_valid_uri * @uri: The uri to check * * Returns: Whether the passed uri is valid for an ldap key source */ gboolean seahorse_ldap_is_valid_uri (const gchar *uri) { LDAPURLDesc *url; int r; g_return_val_if_fail (uri && *uri, FALSE); r = ldap_url_parse (uri, &url); if (r == LDAP_URL_SUCCESS) { /* Some checks to make sure it's a simple URI */ if (!(url->lud_host && url->lud_host[0]) || (url->lud_dn && url->lud_dn[0]) || (url->lud_attrs || url->lud_attrs)) r = LDAP_URL_ERR_PARAM; ldap_free_urldesc (url); } return r == LDAP_URL_SUCCESS; }
int ldap_url_search( char* _ldap_url, int* _ld_result_count) { LDAPURLDesc *ludp; int rc; if (ldap_url_parse(_ldap_url, &ludp) != 0) { LM_ERR("invalid LDAP URL [%s]\n", ZSW(_ldap_url)); if (ludp != NULL) { ldap_free_urldesc(ludp); } return -2; } if (ludp->lud_host == NULL) { LM_ERR( "no ldap session name found in ldap URL [%s]\n", ZSW(_ldap_url)); return -2; } LM_DBG( "LDAP URL parsed into session_name" " [%s], base [%s], scope [%d], filter [%s]\n", ZSW(ludp->lud_host), ZSW(ludp->lud_dn), ludp->lud_scope, ZSW(ludp->lud_filter)); rc = ldap_params_search(_ld_result_count, ludp->lud_host, ludp->lud_dn, ludp->lud_scope, ludp->lud_attrs, ludp->lud_filter); ldap_free_urldesc(ludp); return rc; }
/** Instantiate the module * * Creates a new instance of the module reading parameters from a configuration section. * * @param conf to parse. * @param instance Where to write pointer to configuration data. * @return 0 on success < 0 on failure. */ static int mod_instantiate(CONF_SECTION *conf, void *instance) { static bool version_done; CONF_SECTION *options; ldap_instance_t *inst = instance; inst->cs = conf; options = cf_section_sub_find(conf, "options"); if (!options || !cf_pair_find(options, "chase_referrals")) { inst->chase_referrals_unset = true; /* use OpenLDAP defaults */ } inst->xlat_name = cf_section_name2(conf); if (!inst->xlat_name) { inst->xlat_name = cf_section_name1(conf); } /* * Only needs to be done once, prevents races in environment * initialisation within libldap. * * See: https://github.com/arr2036/ldapperf/issues/2 */ #ifdef HAVE_LDAP_INITIALIZE ldap_initialize(&inst->handle, ""); #else inst->handle = ldap_init("", 0); #endif /* * Get version info from the LDAP API. */ if (!version_done) { static LDAPAPIInfo info; /* static to quiet valgrind about this being uninitialised */ int ldap_errno; version_done = true; ldap_errno = ldap_get_option(NULL, LDAP_OPT_API_INFO, &info); if (ldap_errno == LDAP_OPT_SUCCESS) { if (strcmp(info.ldapai_vendor_name, LDAP_VENDOR_NAME) != 0) { WARN("rlm_ldap: libldap vendor changed since the server was built"); WARN("rlm_ldap: linked: %s, built: %s", info.ldapai_vendor_name, LDAP_VENDOR_NAME); } if (info.ldapai_vendor_version != LDAP_VENDOR_VERSION) { WARN("rlm_ldap: libldap version changed since the server was built"); WARN("rlm_ldap: linked: %i, built: %i", info.ldapai_vendor_version, LDAP_VENDOR_VERSION); } INFO("rlm_ldap: libldap vendor: %s, version: %i", info.ldapai_vendor_name, info.ldapai_vendor_version); ldap_memfree(info.ldapai_vendor_name); ldap_memfree(info.ldapai_extensions); } else { DEBUG("rlm_ldap: Falling back to build time libldap version info. Query for LDAP_OPT_API_INFO " "returned: %i", ldap_errno); INFO("rlm_ldap: libldap vendor: %s, version: %i.%i.%i", LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION_MAJOR, LDAP_VENDOR_VERSION_MINOR, LDAP_VENDOR_VERSION_PATCH); } } /* * If the configuration parameters can't be parsed, then fail. */ if ((parse_sub_section(inst, conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) || (parse_sub_section(inst, conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0)) { cf_log_err_cs(conf, "Failed parsing configuration"); goto error; } /* * Sanity checks for cacheable groups code. */ if (inst->cacheable_group_name && inst->groupobj_membership_filter) { if (!inst->groupobj_name_attr) { cf_log_err_cs(conf, "Directive 'group.name_attribute' must be set if cacheable " "group names are enabled"); goto error; } } /* * Split original server value out into URI, server and port * so whatever initialization function we use later will have * the server information in the format it needs. */ if (ldap_is_ldap_url(inst->server)) { LDAPURLDesc *ldap_url; int port; if (ldap_url_parse(inst->server, &ldap_url)){ cf_log_err_cs(conf, "Parsing LDAP URL \"%s\" failed", inst->server); return -1; } /* * Figure out the port from the URL */ if (ldap_url->lud_port == 0) { if (strcmp(ldap_url->lud_scheme, "ldaps://") == 0) { if (inst->start_tls == true) { start_tls_error: cf_log_err_cs(conf, "ldaps:// scheme is not compatible with 'start_tls'"); return -1; } port = 636; } else { port = 384; } } else { port = ldap_url->lud_port; } inst->uri = inst->server; inst->server = talloc_strdup(inst, ldap_url->lud_host); if ((inst->port != 384) && (port != inst->port)) { WARN("Non-default 'port' directive %i set to %i by LDAP URI", inst->port, port); } inst->port = port; /* * @todo We could set a few other top level * directives using the URL, like base_dn * and scope. */ ldap_free_urldesc(ldap_url); /* * We need to construct an LDAP URI */ } else { switch (inst->port) { default: case 384: inst->uri = talloc_asprintf(inst, "ldap://%s:%i/", inst->server, inst->port); break; case 636: if (inst->start_tls == true) goto start_tls_error; inst->uri = talloc_asprintf(inst, "ldaps://%s:%i/", inst->server, inst->port); break; } } #ifdef LDAP_OPT_X_TLS_NEVER /* * Workaround for servers which support LDAPS but not START TLS */ if (inst->port == LDAPS_PORT || inst->tls_mode) { inst->tls_mode = LDAP_OPT_X_TLS_HARD; } else { inst->tls_mode = 0; } #endif /* * Convert dereference strings to enumerated constants */ if (inst->dereference_str) { inst->dereference = fr_str2int(ldap_dereference, inst->dereference_str, -1); if (inst->dereference < 0) { cf_log_err_cs(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', " "'finding' or 'always'", inst->dereference_str); goto error; } } #if LDAP_SET_REBIND_PROC_ARGS != 3 /* * The 2-argument rebind doesn't take an instance variable. Our rebind function needs the instance * variable for the username, password, etc. */ if (inst->rebind == true) { cf_log_err_cs(conf, "Cannot use 'rebind' directive as this version of libldap " "does not support the API that we need"); goto error; } #endif /* * Convert scope strings to enumerated constants */ inst->userobj_scope = fr_str2int(ldap_scope, inst->userobj_scope_str, -1); if (inst->userobj_scope < 0) { cf_log_err_cs(conf, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else " or 'base'" #endif , inst->userobj_scope_str); goto error; } inst->groupobj_scope = fr_str2int(ldap_scope, inst->groupobj_scope_str, -1); if (inst->groupobj_scope < 0) { cf_log_err_cs(conf, "Invalid 'group.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else " or 'base'" #endif , inst->groupobj_scope_str); goto error; } inst->clientobj_scope = fr_str2int(ldap_scope, inst->clientobj_scope_str, -1); if (inst->clientobj_scope < 0) { cf_log_err_cs(conf, "Invalid 'client.scope' value \"%s\", expected 'sub', 'one'" #ifdef LDAP_SCOPE_CHILDREN ", 'base' or 'children'" #else " or 'base'" #endif , inst->clientobj_scope_str); goto error; } if (inst->tls_require_cert_str) { #ifdef LDAP_OPT_X_TLS_NEVER /* * Convert cert strictness to enumerated constants */ inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1); if (inst->tls_require_cert < 0) { cf_log_err_cs(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', " "'demand', 'allow', 'try' or 'hard'", inst->tls_require_cert_str); goto error; } #else cf_log_err_cs(conf, "Modifying 'tls.require_cert' is not supported by current " "version of libldap. Please upgrade or substitute current libldap and " "rebuild this module"); goto error; #endif } /* * Build the attribute map */ if (map_afrom_cs(&inst->user_map, cf_section_sub_find(inst->cs, "update"), PAIR_LIST_REPLY, PAIR_LIST_REQUEST, rlm_ldap_map_verify, inst, LDAP_MAX_ATTRMAP) < 0) { return -1; } /* * Group comparison checks. */ if (cf_section_name2(conf)) { static ATTR_FLAGS flags; char buffer[256]; snprintf(buffer, sizeof(buffer), "%s-Ldap-Group", inst->xlat_name); if (dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags) < 0) { LDAP_ERR("Error creating group attribute: %s", fr_strerror()); return -1; } inst->group_da = dict_attrbyname(buffer); if (!inst->group_da) { LDAP_ERR("Failed creating attribute %s", buffer); goto error; } paircompare_register(inst->group_da, dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst); /* * Were the default instance */ } else { inst->group_da = dict_attrbyvalue(PW_LDAP_GROUP, 0); paircompare_register(dict_attrbyvalue(PW_LDAP_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst); } xlat_register(inst->xlat_name, ldap_xlat, rlm_ldap_escape_func, inst); /* * Setup the cache attribute */ if (inst->cache_attribute) { static ATTR_FLAGS flags; if (dict_addattr(inst->cache_attribute, -1, 0, PW_TYPE_STRING, flags) < 0) { LDAP_ERR("Error creating cache attribute: %s", fr_strerror()); goto error; } inst->cache_da = dict_attrbyname(inst->cache_attribute); } else { inst->cache_da = inst->group_da; /* Default to the group_da */ } /* * Initialize the socket pool. */ inst->pool = fr_connection_pool_module_init(inst->cs, inst, mod_conn_create, NULL, NULL); if (!inst->pool) goto error; /* * Bulk load dynamic clients. */ if (inst->do_clients) { CONF_SECTION *cs; cs = cf_section_sub_find(inst->cs, "client"); if (!cs) { cf_log_err_cs(conf, "Told to load clients but no client section found"); goto error; } cs = cf_section_sub_find(cs, "attribute"); if (!cs) { cf_log_err_cs(conf, "Told to load clients but no attribute section found"); goto error; } if (rlm_ldap_client_load(inst, cs) < 0) { cf_log_err_cs(conf, "Error loading clients"); return -1; } } return 0; error: return -1; }
/** Expand an LDAP URL into a query, and return a string result from that query. * */ static ssize_t ldap_xlat(void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace) { ldap_rcode_t status; size_t len = 0; ldap_instance_t *inst = instance; LDAPURLDesc *ldap_url; LDAPMessage *result = NULL; LDAPMessage *entry = NULL; struct berval **values; ldap_handle_t *conn; int ldap_errno; char const *url; char const **attrs; url = fmt; if (!ldap_is_ldap_url(url)) { REDEBUG("String passed does not look like an LDAP URL"); return -1; } if (ldap_url_parse(url, &ldap_url)){ REDEBUG("Parsing LDAP URL failed"); return -1; } /* * Nothing, empty string, "*" string, or got 2 things, die. */ if (!ldap_url->lud_attrs || !ldap_url->lud_attrs[0] || !*ldap_url->lud_attrs[0] || (strcmp(ldap_url->lud_attrs[0], "*") == 0) || ldap_url->lud_attrs[1]) { REDEBUG("Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve"); goto free_urldesc; } if (ldap_url->lud_host && ((strcmp(inst->server, ldap_url->lud_host) != 0) || ((uint32_t) ldap_url->lud_port != inst->port))) { REDEBUG("LDAP expansions must specify the same host and port as the their module instance"); goto free_urldesc; } conn = mod_conn_get(inst, request); if (!conn) goto free_urldesc; memcpy(&attrs, &ldap_url->lud_attrs, sizeof(attrs)); status = rlm_ldap_search(inst, request, &conn, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, attrs, &result); switch (status) { case LDAP_PROC_SUCCESS: break; default: goto free_socket; } rad_assert(conn); rad_assert(result); entry = ldap_first_entry(conn->handle, result); if (!entry) { ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno); REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno)); len = -1; goto free_result; } values = ldap_get_values_len(conn->handle, entry, ldap_url->lud_attrs[0]); if (!values) { RDEBUG("No \"%s\" attributes found in specified object", ldap_url->lud_attrs[0]); goto free_result; } if (values[0]->bv_len >= freespace) goto free_values; memcpy(out, values[0]->bv_val, values[0]->bv_len + 1); /* +1 as strlcpy expects buffer size */ len = values[0]->bv_len; free_values: ldap_value_free_len(values); free_result: ldap_msgfree(result); free_socket: mod_conn_release(inst, conn); free_urldesc: ldap_free_urldesc(ldap_url); return len; }
static int _mu_conn_setup (LDAP **pld) { int rc; LDAPURLDesc *ludlist, **ludp; char **urls = NULL; int nurls = 0; char *ldapuri = NULL; LDAP *ld = NULL; int protocol = LDAP_VERSION3; /* FIXME: must be configurable */ if (ldap_param.debug) { if (ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &ldap_param.debug) != LBER_OPT_SUCCESS ) mu_error (_("cannot set LBER_OPT_DEBUG_LEVEL %d"), ldap_param.debug); if (ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &ldap_param.debug) != LDAP_OPT_SUCCESS ) mu_error (_("could not set LDAP_OPT_DEBUG_LEVEL %d"), ldap_param.debug); } if (ldap_param.url) { rc = ldap_url_parse (ldap_param.url, &ludlist); if (rc != LDAP_URL_SUCCESS) { mu_error (_("cannot parse LDAP URL(s)=%s (%d)"), ldap_param.url, rc); return 1; } for (ludp = &ludlist; *ludp; ) { LDAPURLDesc *lud = *ludp; char **tmp; if (lud->lud_dn && lud->lud_dn[0] && (lud->lud_host == NULL || lud->lud_host[0] == '\0')) { /* if no host but a DN is provided, try DNS SRV to gather the host list */ char *domain = NULL, *hostlist = NULL; size_t i; struct mu_wordsplit ws; if (ldap_dn2domain (lud->lud_dn, &domain) || !domain) { mu_error (_("DNS SRV: cannot convert DN=\"%s\" into a domain"), lud->lud_dn ); goto dnssrv_free; } rc = ldap_domain2hostlist (domain, &hostlist); if (rc) { mu_error (_("DNS SRV: cannot convert domain=%s into a hostlist"), domain); goto dnssrv_free; } if (mu_wordsplit (hostlist, &ws, MU_WRDSF_DEFFLAGS)) { mu_error (_("DNS SRV: could not parse hostlist=\"%s\": %s"), hostlist, mu_wordsplit_strerror (&ws)); goto dnssrv_free; } tmp = realloc (urls, sizeof(char *) * (nurls + ws.ws_wordc + 1)); if (!tmp) { mu_error ("DNS SRV %s", mu_strerror (errno)); goto dnssrv_free; } urls = tmp; urls[nurls] = NULL; for (i = 0; i < ws.ws_wordc; i++) { urls[nurls + i + 1] = NULL; rc = mu_asprintf (&urls[nurls + i], "%s://%s", lud->lud_scheme, ws.ws_wordv[i]); if (rc) { mu_error ("DNS SRV %s", mu_strerror (rc)); goto dnssrv_free; } } nurls += i; dnssrv_free: mu_wordsplit_free (&ws); ber_memfree (hostlist); ber_memfree (domain); } else { tmp = realloc (urls, sizeof(char *) * (nurls + 2)); if (!tmp) { mu_error ("DNS SRV %s", mu_strerror (errno)); break; } urls = tmp; urls[nurls + 1] = NULL; urls[nurls] = ldap_url_desc2str (lud); if (!urls[nurls]) { mu_error ("DNS SRV %s", mu_strerror (errno)); break; } nurls++; } *ludp = lud->lud_next; lud->lud_next = NULL; ldap_free_urldesc (lud); } if (ludlist) { ldap_free_urldesc (ludlist); return 1; } else if (!urls) return 1; rc = mu_argcv_string (nurls, urls, &ldapuri); if (rc) { mu_error ("%s", mu_strerror (rc)); return 1; } ber_memvfree ((void **)urls); } mu_diag_output (MU_DIAG_INFO, "constructed LDAP URI: %s", ldapuri ? ldapuri : "<DEFAULT>"); rc = ldap_initialize (&ld, ldapuri); if (rc != LDAP_SUCCESS) { mu_error (_("cannot create LDAP session handle for URI=%s (%d): %s"), ldapuri, rc, ldap_err2string (rc)); free (ldapuri); return 1; } free (ldapuri); ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &protocol); if (ldap_param.tls) { rc = ldap_start_tls_s (ld, NULL, NULL); if (rc != LDAP_SUCCESS) { char *msg = NULL; ldap_get_option (ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); mu_error (_("ldap_start_tls failed: %s"), ldap_err2string (rc)); mu_error (_("TLS diagnostics: %s"), msg); ldap_memfree (msg); ldap_unbind_ext (ld, NULL, NULL); return 1; } } /* FIXME: Timeouts, SASL, etc. */ *pld = ld; return 0; }
int main( int argc, char **argv ) { int i; char *uri = NULL; char *host = "localhost"; char *dn = NULL; char *base = NULL; char *filter = "(objectClass=person)"; struct berval pass = { 0, NULL }; char *pwattr = NULL; int port = -1; int loops = LOOPS; int outerloops = 1; int force = 0; int chaserefs = 0; int noinit = 1; int delay = 0; /* extra action to do after bind... */ struct berval type[] = { BER_BVC( "tester=" ), BER_BVC( "add=" ), BER_BVC( "bind=" ), BER_BVC( "modify=" ), BER_BVC( "modrdn=" ), BER_BVC( "read=" ), BER_BVC( "search=" ), BER_BVNULL }; LDAPURLDesc *extra_ludp = NULL; tester_init( "slapd-bind", TESTER_BIND ); /* by default, tolerate invalid credentials */ tester_ignore_str2errlist( "INVALID_CREDENTIALS" ); while ( ( i = getopt( argc, argv, "a:B:b:D:Ff:H:h:Ii:L:l:p:t:w:" ) ) != EOF ) { switch ( i ) { case 'a': pwattr = optarg; break; case 'b': /* base DN of a tree of user DNs */ base = optarg; break; case 'B': { int c; for ( c = 0; type[c].bv_val; c++ ) { if ( strncasecmp( optarg, type[c].bv_val, type[c].bv_len ) == 0 ) { break; } } if ( type[c].bv_val == NULL ) { usage( argv[0], 'B' ); } switch ( c ) { case TESTER_TESTER: case TESTER_BIND: /* invalid */ usage( argv[0], 'B' ); case TESTER_SEARCH: { if ( ldap_url_parse( &optarg[type[c].bv_len], &extra_ludp ) != LDAP_URL_SUCCESS ) { usage( argv[0], 'B' ); } } break; case TESTER_ADDEL: case TESTER_MODIFY: case TESTER_MODRDN: case TESTER_READ: /* nothing to do */ break; default: assert( 0 ); } } break; case 'C': chaserefs++; break; case 'H': /* the server uri */ uri = optarg; break; case 'h': /* the servers host */ host = optarg; break; case 'i': tester_ignore_str2errlist( optarg ); break; case 'p': /* the servers port */ if ( lutil_atoi( &port, optarg ) != 0 ) { usage( argv[0], 'p' ); } break; case 'D': dn = optarg; break; case 'w': ber_str2bv( optarg, 0, 1, &pass ); memset( optarg, '*', pass.bv_len ); break; case 'l': /* the number of loops */ if ( lutil_atoi( &loops, optarg ) != 0 ) { usage( argv[0], 'l' ); } break; case 'L': /* the number of outerloops */ if ( lutil_atoi( &outerloops, optarg ) != 0 ) { usage( argv[0], 'L' ); } break; case 'f': filter = optarg; break; case 'F': force++; break; case 'I': /* reuse connection */ noinit = 0; break; case 't': /* sleep between binds */ if ( lutil_atoi( &delay, optarg ) != 0 ) { usage( argv[0], 't' ); } break; default: usage( argv[0], i ); break; } } if ( port == -1 && uri == NULL ) { usage( argv[0], '\0' ); } uri = tester_uri( uri, host, port ); for ( i = 0; i < outerloops; i++ ) { int rc; if ( base != NULL ) { rc = do_base( uri, dn, &pass, base, filter, pwattr, loops, force, chaserefs, noinit, delay, -1, NULL ); } else { rc = do_bind( uri, dn, &pass, loops, force, chaserefs, noinit, NULL, -1, NULL ); } if ( rc == LDAP_SERVER_DOWN ) break; } exit( EXIT_SUCCESS ); }
OPENLDAP::Book::Book (Ekiga::ServiceCore &_core, boost::shared_ptr<xmlDoc> _doc, xmlNodePtr _node): saslform(NULL), core(_core), doc(_doc), node(_node), name_node(NULL), uri_node(NULL), authcID_node(NULL), password_node(NULL), ldap_context(NULL), patience(0) { xmlChar *xml_str; bool upgrade_config = false; /* for previous config */ std::string hostname="", port="", base="", scope="", call_attribute=""; xmlNodePtr hostname_node = NULL, port_node = NULL, base_node = NULL, scope_node = NULL, call_attribute_node = NULL; bookinfo.name = ""; bookinfo.uri = ""; bookinfo.authcID = ""; bookinfo.password = ""; bookinfo.saslMech = ""; bookinfo.sasl = false; bookinfo.starttls = false; for (xmlNodePtr child = node->children ; child != NULL; child = child->next) { if (child->type == XML_ELEMENT_NODE && child->name != NULL) { if (xmlStrEqual (BAD_CAST ("name"), child->name)) { xml_str = xmlNodeGetContent (child); bookinfo.name = (const char *)xml_str; xmlFree (xml_str); name_node = child; continue; } if (xmlStrEqual (BAD_CAST ("uri"), child->name)) { xml_str = xmlNodeGetContent (child); bookinfo.uri = (const char *)xml_str; xmlFree (xml_str); uri_node = child; continue; } if (xmlStrEqual (BAD_CAST ("hostname"), child->name)) { xml_str = xmlNodeGetContent (child); hostname = (const char *)xml_str; hostname_node = child; xmlFree (xml_str); upgrade_config = true; continue; } if (xmlStrEqual (BAD_CAST ("port"), child->name)) { xml_str = xmlNodeGetContent (child); port = (const char *)xml_str; port_node = child; xmlFree (xml_str); upgrade_config = true; continue; } if (xmlStrEqual (BAD_CAST ("base"), child->name)) { xml_str = xmlNodeGetContent (child); base = (const char *)xml_str; base_node = child; xmlFree (xml_str); upgrade_config = true; continue; } if (xmlStrEqual (BAD_CAST ("scope"), child->name)) { xml_str = xmlNodeGetContent (child); scope = (const char *)xml_str; scope_node = child; xmlFree (xml_str); upgrade_config = true; continue; } if (xmlStrEqual (BAD_CAST ("call_attribute"), child->name)) { xml_str = xmlNodeGetContent (child); call_attribute = (const char *)xml_str; call_attribute_node = child; xmlFree (xml_str); upgrade_config = true; continue; } if (xmlStrEqual (BAD_CAST ("authcID"), child->name)) { xml_str = xmlNodeGetContent (child); bookinfo.authcID = (const char *)xml_str; authcID_node = child; xmlFree (xml_str); continue; } if (xmlStrEqual (BAD_CAST ("password"), child->name)) { xml_str = xmlNodeGetContent (child); bookinfo.password = (const char *)xml_str; password_node = child; xmlFree (xml_str); continue; } } } if (upgrade_config) { if (!uri_node) { LDAPURLDesc *url_tmp = NULL; char *url_str; std::string new_uri; if (hostname.empty()) hostname="localhost"; new_uri = std::string("ldap://") + hostname; if (!port.empty()) new_uri += std::string(":") + port; new_uri += "/?cn," + call_attribute + "?" + scope; ldap_url_parse (new_uri.c_str(), &url_tmp); url_tmp->lud_dn = (char *)base.c_str(); url_str = ldap_url_desc2str (url_tmp); bookinfo.uri = std::string(url_str); ldap_memfree (url_str); robust_xmlNodeSetContent (node, &uri_node, "uri", bookinfo.uri); url_tmp->lud_dn = NULL; ldap_free_urldesc (url_tmp); } if (hostname_node) { xmlUnlinkNode (hostname_node); xmlFreeNode (hostname_node); } if (port_node) { xmlUnlinkNode (port_node); xmlFreeNode (port_node); } if (base_node) { xmlUnlinkNode (base_node); xmlFreeNode (base_node); } if (scope_node) { xmlUnlinkNode (scope_node); xmlFreeNode (scope_node); } if (call_attribute_node) { xmlUnlinkNode (call_attribute_node); xmlFreeNode (call_attribute_node); } trigger_saving (); } OPENLDAP::BookInfoParse (bookinfo); if (bookinfo.uri_host == EKIGA_NET_URI) I_am_an_ekiga_net_book = true; else I_am_an_ekiga_net_book = false; /* Actor stuff */ add_action (Ekiga::ActionPtr (new Ekiga::Action ("edit-book", _("_Edit"), boost::bind (&OPENLDAP::Book::edit, this)))); add_action (Ekiga::ActionPtr (new Ekiga::Action ("remove-book", _("_Remove"), boost::bind (&OPENLDAP::Book::remove, this)))); add_action (Ekiga::ActionPtr (new Ekiga::Action ("refresh-book", _("_Refresh"), boost::bind (&OPENLDAP::Book::refresh, this)))); }
/* * call-seq: * OpenLDAP.split_url( str ) -> array * * Split an LDAP URL into an array of its parts: * - uri_scheme * - host * - port * - base * - attrs * - scope * - filter * - exts * - crit_exts */ static VALUE ropenldap_s_split_url( VALUE UNUSED(module), VALUE urlstring ) { const char *url = StringValueCStr( urlstring ); LDAPURLDesc *urldesc; VALUE rval = Qnil, obj = Qnil; if ( !ldap_is_ldap_url(url) ) rb_raise( rb_eArgError, "Not an LDAP URL." ); /* Parse the URL */ if ( ldap_url_parse(url, &urldesc) != 0 ) rb_raise( rb_eRuntimeError, "Error parsing %s as an LDAP URL!", url ); rval = rb_ary_new2( 9 ); /* Scheme */ if ( urldesc->lud_scheme ) { ropenldap_log( "debug", " parsed scheme: %s", urldesc->lud_scheme ); obj = rb_str_new2( urldesc->lud_scheme ); OBJ_INFECT( obj, urlstring ); rb_ary_store( rval, 0L, obj ); } /* LDAP host to contact */ if ( urldesc->lud_host ) { ropenldap_log( "debug", " parsed host: %s", urldesc->lud_host ); obj = rb_str_new2( urldesc->lud_host ); OBJ_INFECT( obj, urlstring ); rb_ary_store( rval, 1L, obj ); } /* Port */ rb_ary_store( rval, 2L, INT2FIX(urldesc->lud_port) ); /* Base DN */ if ( urldesc->lud_dn ) { ropenldap_log( "debug", " parsed DN: %s", urldesc->lud_dn ); obj = rb_str_new2( urldesc->lud_dn ); OBJ_INFECT( obj, urlstring ); rb_ary_store( rval, 3L, obj ); } /* Attributes */ rb_ary_store( rval, 4L, ropenldap_rb_string_array(urldesc->lud_attrs) ); /* Numeric scope (LDAP_SCOPE_*) */ rb_ary_store( rval, 5L, INT2FIX(urldesc->lud_scope) ); /* Filter */ if ( urldesc->lud_filter ) { ropenldap_log( "debug", " parsed filter: %s", urldesc->lud_filter ); obj = rb_str_new2( urldesc->lud_filter ); OBJ_INFECT( obj, urlstring ); rb_ary_store( rval, 6L, obj ); } /* lists of LDAP extensions */ rb_ary_store( rval, 7L, ropenldap_rb_string_array(urldesc->lud_exts) ); /* Critical extension/s flag */ rb_ary_store( rval, 8L, urldesc->lud_crit_exts ? Qtrue : Qfalse ); ldap_free_urldesc( urldesc ); return rval; }
extern "C" void * openSource(Source * source) { URI u; ldap_handle * h; int version; int rc; int i; char * s; int msgid; std::string locfilter; struct berval passwd; struct timeval tv; if (!source->uri.length()) throw std::runtime_error("LDAP loader requires an LDAP URI"); // Create the handle. h = new ldap_handle(); h->source = source; // Extract the binddn:password from the URI and rebuild // an authentication-less URI. try { if (!u.parse(source->uri)) throw std::runtime_error("Cannot parse URI"); if (u.user().empty() && u.password().empty()) h->binddn = u.unescape(u.userinfo()); else { h->binddn = u.user(); h->password = u.password(); } u.userinfo(""); // Parse the LDAP URI. if ((rc = ldap_url_parse(std::string(u).c_str(), &h->uri)) != LDAP_SUCCESS) throw ldap_error(rc); if (!h->uri->lud_attrs[0]) throw std::runtime_error( "LDAP url should select at least one attribute"); // Connect to LDAP server. rc = ldap_initialize(&h->ldap, ((std::string(h->uri->lud_scheme? h->uri->lud_scheme: "ldap")) + "://" + (h->uri->lud_host? h->uri->lud_host: "") + (h->uri->lud_port? ":" + std::to_string(h->uri->lud_port): "")).c_str()); if (rc != LDAP_SUCCESS) throw ldap_error(rc); // Set a very low timeout: connection should be quick. tv.tv_sec = 5; tv.tv_usec = 0; ldap_set_option(h->ldap, LDAP_OPT_NETWORK_TIMEOUT, &tv); // Bind if needed. if (ldap_get_option(h->ldap, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_SUCCESS) version = LDAP_VERSION2; // Bind is mandatory. rc = LDAP_SUCCESS; if (!h->binddn.length()) { if (version >= LDAP_VERSION2) { // Anonymous bind is mandatory for // version 2. rc = ldap_sasl_bind_s(h->ldap, "", LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL); } } else { passwd.bv_val = (char *) h->password.c_str(); passwd.bv_len = h->password.length(); rc = ldap_sasl_bind_s(h->ldap, h->binddn.c_str(), LDAP_SASL_SIMPLE, &passwd, NULL, NULL, NULL); } if (rc != LDAP_SUCCESS) throw ldap_error(rc); // Update the given filter to not select entries not // providing mail address attributes. locfilter = h->uri->lud_filter; if (locfilter.length()) { if (locfilter[0] != '(') locfilter = std::string("(") + locfilter + ")"; locfilter = std::string("(&") + locfilter; } if (h->uri->lud_attrs[1]) locfilter += "(|"; for (i = 0; (s = h->uri->lud_attrs[i]); i++) locfilter = locfilter + "(" + s + "=*)"; if (h->uri->lud_attrs[1]) locfilter += ')'; if (h->uri->lud_filter) locfilter += ')'; rc = ldap_search_ext(h->ldap, h->uri->lud_dn, h->uri->lud_scope, locfilter.c_str(), h->uri->lud_attrs, 0, NULL, NULL, NULL, 0x7FFFFFFF, &msgid); if (rc != LDAP_SUCCESS) throw ldap_error(rc); } catch (...) { delete h; throw; } return h; }
static void * map_ldap_parse( const char *fname, int lineno, int argc, char **argv ) { struct ldap_map_data *data; char *p, *uri; assert( fname != NULL ); assert( argv != NULL ); data = calloc( sizeof( struct ldap_map_data ), 1 ); if ( data == NULL ) { return NULL; } if ( argc < 1 ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] ldap map needs URI\n%s", fname, lineno, "" ); free( data ); return NULL; } uri = argv[ 0 ]; if ( strncasecmp( uri, "uri=", STRLENOF( "uri=" ) ) == 0 ) { uri += STRLENOF( "uri=" ); } data->lm_url = strdup( uri ); if ( data->lm_url == NULL ) { map_ldap_free( data ); return NULL; } if ( ldap_url_parse( uri, &data->lm_lud ) != REWRITE_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] illegal URI '%s'\n", fname, lineno, argv[ 0 ] ); map_ldap_free( data ); return NULL; } /* trim everything after [host][:port] */ p = strchr( data->lm_url, '/' ); assert( p[ 1 ] == '/' ); if ( ( p = strchr( p + 2, '/' ) ) != NULL ) { p[ 0 ] = '\0'; } if ( data->lm_lud->lud_attrs == NULL ) { data->lm_attrs[ 0 ] = LDAP_NO_ATTRS; data->lm_wantdn = 1; } else { if ( data->lm_lud->lud_attrs[ 1 ] != NULL ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] only one attribute allowed in URI\n", fname, lineno, 0 ); map_ldap_free( data ); return NULL; } if ( strcasecmp( data->lm_lud->lud_attrs[ 0 ], "dn" ) == 0 || strcasecmp( data->lm_lud->lud_attrs[ 0 ], "entryDN" ) == 0 ) { ldap_memfree( data->lm_lud->lud_attrs[ 0 ] ); ldap_memfree( data->lm_lud->lud_attrs ); data->lm_lud->lud_attrs = NULL; data->lm_attrs[ 0 ] = LDAP_NO_ATTRS; data->lm_wantdn = 1; } else { data->lm_attrs[ 0 ] = data->lm_lud->lud_attrs[ 0 ]; } } data->lm_attrs[ 1 ] = NULL; /* safe defaults */ data->lm_version = LDAP_VERSION3; for ( argc--, argv++; argc > 0; argc--, argv++ ) { if ( strncasecmp( argv[ 0 ], "binddn=", STRLENOF( "binddn=" ) ) == 0 ) { char *p = argv[ 0 ] + STRLENOF( "binddn=" ); int l; if ( p[ 0 ] == '\"' || p [ 0 ] == '\'' ) { l = strlen( p ) - 2; p++; if ( p[ l ] != p[ 0 ] ) { map_ldap_free( data ); return NULL; } } else { l = strlen( p ); } data->lm_binddn = strdup( p ); if ( data->lm_binddn == NULL ) { map_ldap_free( data ); return NULL; } if ( data->lm_binddn[ l ] == '\"' || data->lm_binddn[ l ] == '\'' ) { data->lm_binddn[ l ] = '\0'; } /* deprecated */ } else if ( strncasecmp( argv[ 0 ], "bindpw=", STRLENOF( "bindpw=" ) ) == 0 ) { ber_str2bv( argv[ 0 ] + STRLENOF( "bindpw=" ), 0, 1, &data->lm_cred ); if ( data->lm_cred.bv_val == NULL ) { map_ldap_free( data ); return NULL; } } else if ( strncasecmp( argv[ 0 ], "credentials=", STRLENOF( "credentials=" ) ) == 0 ) { ber_str2bv( argv[ 0 ] + STRLENOF( "credentials=" ), 0, 1, &data->lm_cred ); if ( data->lm_cred.bv_val == NULL ) { map_ldap_free( data ); return NULL; } } else if ( strncasecmp( argv[ 0 ], "bindwhen=", STRLENOF( "bindwhen=" ) ) == 0 ) { char *p = argv[ 0 ] + STRLENOF( "bindwhen=" ); if ( strcasecmp( p, "now" ) == 0 ) { int rc; data->lm_when = MAP_LDAP_NOW; /* * Init LDAP handler ... */ rc = ldap_initialize( &data->lm_ld, data->lm_url ); if ( rc != LDAP_SUCCESS ) { map_ldap_free( data ); return NULL; } ldap_set_option( data->lm_ld, LDAP_OPT_PROTOCOL_VERSION, (void *)&data->lm_version ); #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_init( &data->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } else if ( strcasecmp( p, "later" ) == 0 ) { data->lm_when = MAP_LDAP_LATER; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_init( &data->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ } else if ( strcasecmp( p, "everytime" ) == 0 ) { data->lm_when = MAP_LDAP_EVERYTIME; } else { /* ignore ... */ } } else if ( strncasecmp( argv[ 0 ], "version=", STRLENOF( "version=" ) ) == 0 ) { if ( lutil_atoi( &data->lm_version, argv[ 0 ] + STRLENOF( "version=" ) ) ) { map_ldap_free( data ); return NULL; } switch ( data->lm_version ) { case LDAP_VERSION2: case LDAP_VERSION3: break; default: Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown version %s\n", fname, lineno, p ); map_ldap_free( data ); return NULL; } } else { Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown option %s (ignored)\n", fname, lineno, argv[0] ); } } if ( data->lm_when == MAP_LDAP_UNKNOWN ) { data->lm_when = MAP_LDAP_EVERYTIME; } return ( void * )data; }
/* * Map parsing * NOTE: these are old-fashion maps; new maps will be parsed on separate * config lines, and referred by name. */ struct rewrite_map * rewrite_xmap_parse( struct rewrite_info *info, const char *s, const char **currpos ) { struct rewrite_map *map; assert( info != NULL ); assert( s != NULL ); assert( currpos != NULL ); Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s", s, "", "" ); *currpos = NULL; map = calloc( sizeof( struct rewrite_map ), 1 ); if ( map == NULL ) { Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:" " calloc failed\n%s%s%s", "", "", "" ); return NULL; } /* * Experimental passwd map: * replaces the uid with the matching gecos from /etc/passwd file */ if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) { map->lm_type = REWRITE_MAP_XPWDMAP; map->lm_name = strdup( "xpasswd" ); if ( map->lm_name == NULL ) { free( map ); return NULL; } assert( s[7] == '}' ); *currpos = s + 8; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( !xpasswd_mutex_init ) { if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) { free( map ); return NULL; } } ++xpasswd_mutex_init; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* Don't really care if fails */ return map; /* * Experimental file map: * looks up key in a `key value' ascii file */ } else if ( strncasecmp( s, "xfile", 5 ) == 0 ) { char *filename; const char *p; int l; int c = 5; map->lm_type = REWRITE_MAP_XFILEMAP; if ( s[ c ] != '(' ) { free( map ); return NULL; } /* Must start with '/' for security concerns */ c++; if ( s[ c ] != '/' ) { free( map ); return NULL; } for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ ); if ( p[ 0 ] != ')' ) { free( map ); return NULL; } l = p - s - c; filename = calloc( sizeof( char ), l + 1 ); if ( filename == NULL ) { free( map ); return NULL; } AC_MEMCPY( filename, s + c, l ); filename[ l ] = '\0'; map->lm_args = ( void * )fopen( filename, "r" ); free( filename ); if ( map->lm_args == NULL ) { free( map ); return NULL; } *currpos = p + 1; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { fclose( ( FILE * )map->lm_args ); free( map ); return NULL; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return map; /* * Experimental ldap map: * looks up key on the fly (not implemented!) */ } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) { char *p; char *url; int l, rc; int c = 5; LDAPURLDesc *lud; if ( s[ c ] != '(' ) { free( map ); return NULL; } c++; p = strchr( s, '}' ); if ( p == NULL ) { free( map ); return NULL; } p--; *currpos = p + 2; /* * Add two bytes for urlencoding of '%s' */ l = p - s - c; url = calloc( sizeof( char ), l + 3 ); if ( url == NULL ) { free( map ); return NULL; } AC_MEMCPY( url, s + c, l ); url[ l ] = '\0'; /* * Urlencodes the '%s' for ldap_url_parse */ p = strchr( url, '%' ); if ( p != NULL ) { AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 ); p[ 1 ] = '2'; p[ 2 ] = '5'; } rc = ldap_url_parse( url, &lud ); free( url ); if ( rc != LDAP_SUCCESS ) { free( map ); return NULL; } assert( lud != NULL ); map->lm_args = ( void * )lud; map->lm_type = REWRITE_MAP_XLDAPMAP; #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { ldap_free_urldesc( lud ); free( map ); return NULL; } #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return map; /* Unhandled map */ } free( map ); return NULL; }
static CURLcode Curl_ldap(struct connectdata *conn, bool *done) { CURLcode result = CURLE_OK; int rc = 0; LDAP *server = NULL; LDAPURLDesc *ludp = NULL; LDAPMessage *ldapmsg = NULL; LDAPMessage *entryIterator; int num = 0; struct SessionHandle *data=conn->data; int ldap_proto = LDAP_VERSION3; int ldap_ssl = 0; char *val_b64 = NULL; size_t val_b64_sz = 0; curl_off_t dlsize = 0; #ifdef LDAP_OPT_NETWORK_TIMEOUT struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */ #endif *done = TRUE; /* unconditionally */ infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n", LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION); infof(data, "LDAP local: %s\n", data->change.url); #ifdef HAVE_LDAP_URL_PARSE rc = ldap_url_parse(data->change.url, &ludp); #else rc = _ldap_url_parse(conn, &ludp); #endif if(rc != 0) { failf(data, "LDAP local: %s", ldap_err2string(rc)); result = CURLE_LDAP_INVALID_URL; goto quit; } /* Get the URL scheme ( either ldap or ldaps ) */ if(conn->given->flags & PROTOPT_SSL) ldap_ssl = 1; infof(data, "LDAP local: trying to establish %s connection\n", ldap_ssl ? "encrypted" : "cleartext"); #ifdef LDAP_OPT_NETWORK_TIMEOUT ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); #endif ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); if(ldap_ssl) { #ifdef HAVE_LDAP_SSL #ifdef CURL_LDAP_WIN /* Win32 LDAP SDK doesn't support insecure mode without CA! */ server = ldap_sslinit(conn->host.name, (int)conn->port, 1); ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); #else int ldap_option; char* ldap_ca = data->set.str[STRING_SSL_CAFILE]; #if defined(CURL_HAS_NOVELL_LDAPSDK) rc = ldapssl_client_init(NULL, NULL); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } if(data->set.ssl.verifypeer) { /* Novell SDK supports DER or BASE64 files. */ int cert_type = LDAPSSL_CERT_FILETYPE_B64; if((data->set.str[STRING_CERT_TYPE]) && (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER"))) cert_type = LDAPSSL_CERT_FILETYPE_DER; if(!ldap_ca) { failf(data, "LDAP local: ERROR %s CA cert not set!", (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM")); result = CURLE_SSL_CERTPROBLEM; goto quit; } infof(data, "LDAP local: using %s CA cert '%s'\n", (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), ldap_ca); rc = ldapssl_add_trusted_cert(ldap_ca, cert_type); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting %s CA cert: %s", (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"), ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } ldap_option = LDAPSSL_VERIFY_SERVER; } else ldap_option = LDAPSSL_VERIFY_NONE; rc = ldapssl_set_verify_mode(ldap_option); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting cert verify mode: %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } server = ldapssl_init(conn->host.name, (int)conn->port, 1); if(server == NULL) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.name, conn->port); result = CURLE_COULDNT_CONNECT; goto quit; } #elif defined(LDAP_OPT_X_TLS) if(data->set.ssl.verifypeer) { /* OpenLDAP SDK supports BASE64 files. */ if((data->set.str[STRING_CERT_TYPE]) && (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) { failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!"); result = CURLE_SSL_CERTPROBLEM; goto quit; } if(!ldap_ca) { failf(data, "LDAP local: ERROR PEM CA cert not set!"); result = CURLE_SSL_CERTPROBLEM; goto quit; } infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca); rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting PEM CA cert: %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } ldap_option = LDAP_OPT_X_TLS_DEMAND; } else ldap_option = LDAP_OPT_X_TLS_NEVER; rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting cert verify mode: %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } server = ldap_init(conn->host.name, (int)conn->port); if(server == NULL) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.name, conn->port); result = CURLE_COULDNT_CONNECT; goto quit; } ldap_option = LDAP_OPT_X_TLS_HARD; rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } /* rc = ldap_start_tls_s(server, NULL, NULL); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } */ #else /* we should probably never come up to here since configure should check in first place if we can support LDAP SSL/TLS */ failf(data, "LDAP local: SSL/TLS not supported with this version " "of the OpenLDAP toolkit\n"); result = CURLE_SSL_CERTPROBLEM; goto quit; #endif #endif #endif /* CURL_LDAP_USE_SSL */ } else { server = ldap_init(conn->host.name, (int)conn->port); if(server == NULL) { failf(data, "LDAP local: Cannot connect to %s:%ld", conn->host.name, conn->port); result = CURLE_COULDNT_CONNECT; goto quit; } } #ifdef CURL_LDAP_WIN ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); #endif rc = ldap_simple_bind_s(server, conn->bits.user_passwd ? conn->user : NULL, conn->bits.user_passwd ? conn->passwd : NULL); if(!ldap_ssl && rc != 0) { ldap_proto = LDAP_VERSION2; ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); rc = ldap_simple_bind_s(server, conn->bits.user_passwd ? conn->user : NULL, conn->bits.user_passwd ? conn->passwd : NULL); } if(rc != 0) { failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc)); result = CURLE_LDAP_CANNOT_BIND; goto quit; } rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: %s", ldap_err2string(rc)); result = CURLE_LDAP_SEARCH_FAILED; goto quit; } for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg); entryIterator; entryIterator = ldap_next_entry(server, entryIterator), num++) { BerElement *ber = NULL; char *attribute; /*! suspicious that this isn't 'const' */ char *dn = ldap_get_dn(server, entryIterator); int i; result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); if(result) goto quit; result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0); if(result) goto quit; result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) goto quit; dlsize += strlen(dn)+5; for(attribute = ldap_first_attribute(server, entryIterator, &ber); attribute; attribute = ldap_next_attribute(server, entryIterator, ber)) { BerValue **vals = ldap_get_values_len(server, entryIterator, attribute); if(vals != NULL) { for(i = 0; (vals[i] != NULL); i++) { result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); if(result) goto quit; result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)attribute, 0); if(result) goto quit; result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); if(result) goto quit; dlsize += strlen(attribute)+3; if((strlen(attribute) > 7) && (strcmp(";binary", (char *)attribute + (strlen((char *)attribute) - 7)) == 0)) { /* Binary attribute, encode to base64. */ CURLcode error = Curl_base64_encode(data, vals[i]->bv_val, vals[i]->bv_len, &val_b64, &val_b64_sz); if(error) { ldap_value_free_len(vals); ldap_memfree(attribute); ldap_memfree(dn); if(ber) ber_free(ber, 0); result = error; goto quit; } if(val_b64_sz > 0) { result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz); free(val_b64); if(result) goto quit; dlsize += val_b64_sz; } } else { result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val, vals[i]->bv_len); if(result) goto quit; dlsize += vals[i]->bv_len; } result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); if(result) goto quit; dlsize++; } /* Free memory used to store values */ ldap_value_free_len(vals); } result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); if(result) goto quit; dlsize++; Curl_pgrsSetDownloadCounter(data, dlsize); ldap_memfree(attribute); } ldap_memfree(dn); if(ber) ber_free(ber, 0); } quit: if(ldapmsg) { ldap_msgfree(ldapmsg); LDAP_TRACE (("Received %d entries\n", num)); } if(rc == LDAP_SIZELIMIT_EXCEEDED) infof(data, "There are more than %d entries\n", num); if(ludp) ldap_free_urldesc(ludp); if(server) ldap_unbind_s(server); #if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK) if(ldap_ssl) ldapssl_client_deinit(); #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ /* no data to transfer */ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); connclose(conn, "LDAP connection always disable re-use"); return result; }
int main(int argc, char *argv[]) { const char *url, *scope = NULL; LDAPURLDesc *lud; enum { IS_LDAP = 0, IS_LDAPS, IS_LDAPI } type = IS_LDAP; int rc; if ( argc != 2 ) { fprintf( stderr, "usage: urltest <url>\n" ); exit( EXIT_FAILURE ); } url = argv[ 1 ]; if ( ldap_is_ldaps_url( url ) ) { fprintf( stdout, "LDAPS url\n" ); type = IS_LDAPS; } else if ( ldap_is_ldapi_url( url ) ) { fprintf( stdout, "LDAPI url\n" ); type = IS_LDAPI; } else if ( ldap_is_ldap_url( url ) ) { fprintf( stdout, "generic LDAP url\n" ); } else { fprintf( stderr, "Need a valid LDAP url\n" ); exit( EXIT_FAILURE ); } rc = ldap_url_parse( url, &lud ); if ( rc != LDAP_URL_SUCCESS ) { fprintf( stderr, "ldap_url_parse(%s) failed (%d)\n", url, rc ); exit( EXIT_FAILURE ); } fprintf( stdout, "PROTO: %s\n", lud->lud_scheme ); switch ( type ) { case IS_LDAPI: fprintf( stdout, "PATH: %s\n", lud->lud_host ); break; default: fprintf( stdout, "HOST: %s\n", lud->lud_host ); if ( lud->lud_port != 0 ) { fprintf( stdout, "PORT: %d\n", lud->lud_port ); } } if ( lud->lud_dn && lud->lud_dn[ 0 ] ) { fprintf( stdout, "DN: %s\n", lud->lud_dn ); } if ( lud->lud_attrs ) { int i; fprintf( stdout, "ATTRS:\n" ); for ( i = 0; lud->lud_attrs[ i ]; i++ ) { fprintf( stdout, "\t%s\n", lud->lud_attrs[ i ] ); } } scope = ldap_pvt_scope2str( lud->lud_scope ); if ( scope ) { fprintf( stdout, "SCOPE: %s\n", scope ); } if ( lud->lud_filter ) { fprintf( stdout, "FILTER: %s\n", lud->lud_filter ); } if ( lud->lud_exts ) { int i; fprintf( stdout, "EXTS:\n" ); for ( i = 0; lud->lud_exts[ i ]; i++ ) { fprintf( stdout, "\t%s\n", lud->lud_exts[ i ] ); } } fprintf( stdout, "URL: %s\n", ldap_url_desc2str( lud )); return EXIT_SUCCESS; }
/** Expand an LDAP URL into a query, and return a string result from that query. * */ static ssize_t ldap_xlat(void *instance, REQUEST *request, char const *fmt, char *out, size_t freespace) { ldap_rcode_t status; size_t len = 0; ldap_instance_t *inst = instance; LDAPURLDesc *ldap_url; LDAPMessage *result = NULL; LDAPMessage *entry = NULL; char **vals; ldap_handle_t *conn; int ldap_errno; char const *url; char const **attrs; url = fmt; if (!ldap_is_ldap_url(url)) { REDEBUG("String passed does not look like an LDAP URL"); return -1; } if (ldap_url_parse(url, &ldap_url)){ REDEBUG("Parsing LDAP URL failed"); return -1; } /* * Nothing, empty string, "*" string, or got 2 things, die. */ if (!ldap_url->lud_attrs || !ldap_url->lud_attrs[0] || !*ldap_url->lud_attrs[0] || (strcmp(ldap_url->lud_attrs[0], "*") == 0) || ldap_url->lud_attrs[1]) { REDEBUG("Bad attributes list in LDAP URL. URL must specify exactly one attribute to retrieve"); goto free_urldesc; } if (ldap_url->lud_host && ((strncmp(inst->server, ldap_url->lud_host, strlen(inst->server)) != 0) || (ldap_url->lud_port != inst->port))) { RDEBUG("Requested server/port is \"%s:%i\"", ldap_url->lud_host, inst->port); goto free_urldesc; } conn = rlm_ldap_get_socket(inst, request); if (!conn) goto free_urldesc; memcpy(&attrs, &ldap_url->lud_attrs, sizeof(attrs)); status = rlm_ldap_search(inst, request, &conn, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, attrs, &result); switch (status) { case LDAP_PROC_SUCCESS: break; case LDAP_PROC_NO_RESULT: RDEBUG("Search returned not found"); default: goto free_socket; } rad_assert(conn); rad_assert(result); entry = ldap_first_entry(conn->handle, result); if (!entry) { ldap_get_option(conn->handle, LDAP_OPT_RESULT_CODE, &ldap_errno); REDEBUG("Failed retrieving entry: %s", ldap_err2string(ldap_errno)); len = -1; goto free_result; } vals = ldap_get_values(conn->handle, entry, ldap_url->lud_attrs[0]); if (!vals) { RDEBUG("No \"%s\" attributes found in specified object", ldap_url->lud_attrs[0]); goto free_result; } len = strlen(vals[0]); if (len >= freespace){ goto free_vals; } strlcpy(out, vals[0], freespace); free_vals: ldap_value_free(vals); free_result: ldap_msgfree(result); free_socket: rlm_ldap_release_socket(inst, conn); free_urldesc: ldap_free_urldesc(ldap_url); return len; }
static int dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli ) { Attribute *a, *id = NULL; slap_callback cb = { 0 }; Operation o = *op; struct berval *url; Entry *e; int opattrs, userattrs; dynlist_sc_t dlc = { 0 }; dynlist_map_t *dlm; a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad ); if ( a == NULL ) { /* FIXME: error? */ return SLAP_CB_CONTINUE; } opattrs = SLAP_OPATTRS( rs->sr_attr_flags ); userattrs = SLAP_USERATTRS( rs->sr_attr_flags ); /* Don't generate member list if it wasn't requested */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { AttributeDescription *ad = dlm->dlm_mapped_ad ? dlm->dlm_mapped_ad : dlm->dlm_member_ad; if ( userattrs || ad_inlist( ad, rs->sr_attrs ) ) break; } if ( dli->dli_dlm && !dlm ) return SLAP_CB_CONTINUE; if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) { Attribute *authz = NULL; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( rs->sr_entry->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } e = rs->sr_entry; /* ensure e is modifiable, but do not replace * sr_entry yet since we have pointers into it */ if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) { e = entry_dup( rs->sr_entry ); } dlc.dlc_e = e; dlc.dlc_dli = dli; cb.sc_private = &dlc; cb.sc_response = dynlist_sc_update; o.o_callback = &cb; o.ors_deref = LDAP_DEREF_NEVER; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; for ( url = a->a_nvals; !BER_BVISNULL( url ); url++ ) { LDAPURLDesc *lud = NULL; int i, j; struct berval dn; int rc; BER_BVZERO( &o.o_req_dn ); BER_BVZERO( &o.o_req_ndn ); o.ors_filter = NULL; o.ors_attrs = NULL; BER_BVZERO( &o.ors_filterstr ); if ( ldap_url_parse( url->bv_val, &lud ) != LDAP_URL_SUCCESS ) { /* FIXME: error? */ continue; } if ( lud->lud_host != NULL ) { /* FIXME: host not allowed; reject as illegal? */ Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): " "illegal URI \"%s\"\n", e->e_name.bv_val, url->bv_val, 0 ); goto cleanup; } if ( lud->lud_dn == NULL ) { /* note that an empty base is not honored in terms * of defaultSearchBase, because select_backend() * is not aware of the defaultSearchBase option; * this can be useful in case of a database serving * the empty suffix */ BER_BVSTR( &dn, "" ); } else { ber_str2bv( lud->lud_dn, 0, 0, &dn ); } rc = dnPrettyNormal( NULL, &dn, &o.o_req_dn, &o.o_req_ndn, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { /* FIXME: error? */ goto cleanup; } o.ors_scope = lud->lud_scope; for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_mapped_ad != NULL ) { break; } } if ( dli->dli_dlm && !dlm ) { /* if ( lud->lud_attrs != NULL ), * the URL should be ignored */ o.ors_attrs = slap_anlist_no_attrs; } else if ( lud->lud_attrs == NULL ) { o.ors_attrs = rs->sr_attrs; } else { for ( i = 0; lud->lud_attrs[i]; i++) /* just count */ ; o.ors_attrs = op->o_tmpcalloc( i + 1, sizeof( AttributeName ), op->o_tmpmemctx ); for ( i = 0, j = 0; lud->lud_attrs[i]; i++) { const char *text = NULL; ber_str2bv( lud->lud_attrs[i], 0, 0, &o.ors_attrs[j].an_name ); o.ors_attrs[j].an_desc = NULL; (void)slap_bv2ad( &o.ors_attrs[j].an_name, &o.ors_attrs[j].an_desc, &text ); /* FIXME: ignore errors... */ if ( rs->sr_attrs == NULL ) { if ( o.ors_attrs[j].an_desc != NULL && is_at_operational( o.ors_attrs[j].an_desc->ad_type ) ) { continue; } } else { if ( o.ors_attrs[j].an_desc != NULL && is_at_operational( o.ors_attrs[j].an_desc->ad_type ) ) { if ( !opattrs ) { continue; } if ( !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) { /* lookup if mapped -- linear search, * not very efficient unless list * is very short */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) { break; } } if ( dlm == NULL ) { continue; } } } else { if ( !userattrs && o.ors_attrs[j].an_desc != NULL && !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) { /* lookup if mapped -- linear search, * not very efficient unless list * is very short */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) { break; } } if ( dlm == NULL ) { continue; } } } } j++; } if ( j == 0 ) { goto cleanup; } BER_BVZERO( &o.ors_attrs[j].an_name ); } if ( lud->lud_filter == NULL ) { ber_dupbv_x( &o.ors_filterstr, &dli->dli_default_filter, op->o_tmpmemctx ); } else { struct berval flt; ber_str2bv( lud->lud_filter, 0, 0, &flt ); if ( dynlist_make_filter( op, rs->sr_entry, url->bv_val, &flt, &o.ors_filterstr ) ) { /* error */ goto cleanup; } } o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val ); if ( o.ors_filter == NULL ) { goto cleanup; } o.o_bd = select_backend( &o.o_req_ndn, 1 ); if ( o.o_bd && o.o_bd->be_search ) { SlapReply r = { REP_SEARCH }; r.sr_attr_flags = slap_attr_flags( o.ors_attrs ); (void)o.o_bd->be_search( &o, &r ); } cleanup:; if ( id ) { slap_op_groups_free( &o ); } if ( o.ors_filter ) { filter_free_x( &o, o.ors_filter, 1 ); } if ( o.ors_attrs && o.ors_attrs != rs->sr_attrs && o.ors_attrs != slap_anlist_no_attrs ) { op->o_tmpfree( o.ors_attrs, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &o.o_req_dn ) ) { op->o_tmpfree( o.o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &o.o_req_ndn ) ) { op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx ); } assert( BER_BVISNULL( &o.ors_filterstr ) || o.ors_filterstr.bv_val != lud->lud_filter ); op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx ); ldap_free_urldesc( lud ); } if ( e != rs->sr_entry ) { rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e ); rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; } return SLAP_CB_CONTINUE; }
static int dl_cfgen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)c->bi; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; int rc = 0, i; if ( c->op == SLAP_CONFIG_EMIT ) { switch( c->type ) { case DL_ATTRSET: for ( i = 0; dli; i++, dli = dli->dli_next ) { struct berval bv; char *ptr = c->cr_msg; dynlist_map_t *dlm; assert( dli->dli_oc != NULL ); assert( dli->dli_ad != NULL ); /* FIXME: check buffer overflow! */ ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ), SLAP_X_ORDERED_FMT "%s", i, dli->dli_oc->soc_cname.bv_val ); if ( !BER_BVISNULL( &dli->dli_uri ) ) { *ptr++ = ' '; *ptr++ = '"'; ptr = lutil_strncopy( ptr, dli->dli_uri.bv_val, dli->dli_uri.bv_len ); *ptr++ = '"'; } *ptr++ = ' '; ptr = lutil_strncopy( ptr, dli->dli_ad->ad_cname.bv_val, dli->dli_ad->ad_cname.bv_len ); for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { ptr[ 0 ] = ' '; ptr++; if ( dlm->dlm_mapped_ad ) { ptr = lutil_strcopy( ptr, dlm->dlm_mapped_ad->ad_cname.bv_val ); ptr[ 0 ] = ':'; ptr++; } ptr = lutil_strcopy( ptr, dlm->dlm_member_ad->ad_cname.bv_val ); } bv.bv_val = c->cr_msg; bv.bv_len = ptr - bv.bv_val; value_add_one( &c->rvalue_vals, &bv ); } break; case DL_ATTRPAIR_COMPAT: case DL_ATTRPAIR: rc = 1; break; default: rc = 1; break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { switch( c->type ) { case DL_ATTRSET: if ( c->valx < 0 ) { dynlist_info_t *dli_next; for ( dli_next = dli; dli_next; dli = dli_next ) { dynlist_map_t *dlm = dli->dli_dlm; dynlist_map_t *dlm_next; dli_next = dli->dli_next; if ( !BER_BVISNULL( &dli->dli_uri ) ) { ch_free( dli->dli_uri.bv_val ); } if ( dli->dli_lud != NULL ) { ldap_free_urldesc( dli->dli_lud ); } if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) { ber_memfree( dli->dli_uri_nbase.bv_val ); } if ( dli->dli_uri_filter != NULL ) { filter_free( dli->dli_uri_filter ); } ch_free( dli->dli_default_filter.bv_val ); while ( dlm != NULL ) { dlm_next = dlm->dlm_next; ch_free( dlm ); dlm = dlm_next; } ch_free( dli ); } on->on_bi.bi_private = NULL; } else { dynlist_info_t **dlip; dynlist_map_t *dlm; dynlist_map_t *dlm_next; for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private; i < c->valx; i++ ) { if ( *dlip == NULL ) { return 1; } dlip = &(*dlip)->dli_next; } dli = *dlip; *dlip = dli->dli_next; if ( !BER_BVISNULL( &dli->dli_uri ) ) { ch_free( dli->dli_uri.bv_val ); } if ( dli->dli_lud != NULL ) { ldap_free_urldesc( dli->dli_lud ); } if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) { ber_memfree( dli->dli_uri_nbase.bv_val ); } if ( dli->dli_uri_filter != NULL ) { filter_free( dli->dli_uri_filter ); } ch_free( dli->dli_default_filter.bv_val ); dlm = dli->dli_dlm; while ( dlm != NULL ) { dlm_next = dlm->dlm_next; ch_free( dlm ); dlm = dlm_next; } ch_free( dli ); dli = (dynlist_info_t *)on->on_bi.bi_private; } break; case DL_ATTRPAIR_COMPAT: case DL_ATTRPAIR: rc = 1; break; default: rc = 1; break; } return rc; } switch( c->type ) { case DL_ATTRSET: { dynlist_info_t **dlip, *dli_next = NULL; ObjectClass *oc = NULL; AttributeDescription *ad = NULL; int attridx = 2; LDAPURLDesc *lud = NULL; struct berval nbase = BER_BVNULL; Filter *filter = NULL; struct berval uri = BER_BVNULL; dynlist_map_t *dlm = NULL, *dlml = NULL; const char *text; oc = oc_find( c->argv[ 1 ] ); if ( oc == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find ObjectClass \"%s\"", c->argv[ 1 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } if ( strncasecmp( c->argv[ attridx ], "ldap://", STRLENOF("ldap://") ) == 0 ) { if ( ldap_url_parse( c->argv[ attridx ], &lud ) != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to parse URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_host != NULL ) { if ( lud->lud_host[0] == '\0' ) { ch_free( lud->lud_host ); lud->lud_host = NULL; } else { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "host not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } } if ( lud->lud_attrs != NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "attrs not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_exts != NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "extensions not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' ) { struct berval dn; ber_str2bv( lud->lud_dn, 0, 0, &dn ); rc = dnNormalize( 0, NULL, NULL, &dn, &nbase, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "DN normalization failed in URI \"%s\"", c->argv[ attridx ] ); goto done_uri; } } if ( lud->lud_filter != NULL && lud->lud_filter[ 0 ] != '\0' ) { filter = str2filter( lud->lud_filter ); if ( filter == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "filter parsing failed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } } ber_str2bv( c->argv[ attridx ], 0, 1, &uri ); done_uri:; if ( rc ) { if ( lud ) { ldap_free_urldesc( lud ); } if ( !BER_BVISNULL( &nbase ) ) { ber_memfree( nbase.bv_val ); } if ( filter != NULL ) { filter_free( filter ); } while ( dlm != NULL ) { dlml = dlm; dlm = dlm->dlm_next; ch_free( dlml ); } Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return rc; } attridx++; } rc = slap_str2ad( c->argv[ attridx ], &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find AttributeDescription \"%s\"", c->argv[ attridx ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "AttributeDescription \"%s\" " "must be a subtype of \"labeledURI\"", c->argv[ attridx ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } attridx++; for ( i = attridx; i < c->argc; i++ ) { char *arg; char *cp; AttributeDescription *member_ad = NULL; AttributeDescription *mapped_ad = NULL; dynlist_map_t *dlmp; /* * If no mapped attribute is given, dn is used * for backward compatibility. */ arg = c->argv[i]; if ( ( cp = strchr( arg, ':' ) ) != NULL ) { struct berval bv; ber_str2bv( arg, cp - arg, 0, &bv ); rc = slap_bv2ad( &bv, &mapped_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find mapped AttributeDescription #%d \"%s\"\n", i - 3, c->argv[ i ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } arg = cp + 1; } rc = slap_str2ad( arg, &member_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find AttributeDescription #%d \"%s\"\n", i - 3, c->argv[ i ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) ); if ( dlm == NULL ) { dlm = dlmp; } dlmp->dlm_member_ad = member_ad; dlmp->dlm_mapped_ad = mapped_ad; dlmp->dlm_next = NULL; if ( dlml != NULL ) dlml->dlm_next = dlmp; dlml = dlmp; } if ( c->valx > 0 ) { int i; for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private; i < c->valx; i++ ) { if ( *dlip == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "invalid index {%d}\n", c->valx ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } dlip = &(*dlip)->dli_next; } dli_next = *dlip; } else { for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private; *dlip; dlip = &(*dlip)->dli_next ) /* goto last */; } *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) ); (*dlip)->dli_oc = oc; (*dlip)->dli_ad = ad; (*dlip)->dli_dlm = dlm; (*dlip)->dli_next = dli_next; (*dlip)->dli_lud = lud; (*dlip)->dli_uri_nbase = nbase; (*dlip)->dli_uri_filter = filter; (*dlip)->dli_uri = uri; rc = dynlist_build_def_filter( *dlip ); } break; case DL_ATTRPAIR_COMPAT: snprintf( c->cr_msg, sizeof( c->cr_msg ), "warning: \"attrpair\" only supported for limited " "backward compatibility with overlay \"dyngroup\"" ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); /* fallthru */ case DL_ATTRPAIR: { dynlist_info_t **dlip; ObjectClass *oc = NULL; AttributeDescription *ad = NULL, *member_ad = NULL; const char *text; oc = oc_find( "groupOfURLs" ); if ( oc == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find default ObjectClass \"groupOfURLs\"" ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find AttributeDescription \"%s\"", c->argv[ 1 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } rc = slap_str2ad( c->argv[ 2 ], &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find AttributeDescription \"%s\"\n", c->argv[ 2 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "AttributeDescription \"%s\" " "must be a subtype of \"labeledURI\"", c->argv[ 2 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private; *dlip; dlip = &(*dlip)->dli_next ) { /* * The same URL attribute / member attribute pair * cannot be repeated, but we enforce this only * when the member attribute is unique. Performing * the check for multiple values would require * sorting and comparing the lists, which is left * as a future improvement */ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_dlm->dlm_next == NULL && member_ad == (*dlip)->dli_dlm->dlm_member_ad ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "URL attributeDescription \"%s\" already mapped.\n", ad->ad_cname.bv_val ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); #if 0 /* make it a warning... */ return 1; #endif } } *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) ); (*dlip)->dli_oc = oc; (*dlip)->dli_ad = ad; (*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) ); (*dlip)->dli_dlm->dlm_member_ad = member_ad; (*dlip)->dli_dlm->dlm_mapped_ad = NULL; rc = dynlist_build_def_filter( *dlip ); } break; default: rc = 1; break; } return rc; }
CURLcode Curl_ldap(struct connectdata *conn) { CURLcode status = CURLE_OK; int rc; void *(*ldap_init)(char *, int); int (*ldap_simple_bind_s)(void *, char *, char *); int (*ldap_unbind_s)(void *); int (*ldap_url_parse)(char *, LDAPURLDesc **); void (*ldap_free_urldesc)(void *); int (*ldap_search_s)(void *, char *, int, char *, char **, int, void **); int (*ldap_search_st)(void *, char *, int, char *, char **, int, void *, void **); void *(*ldap_first_entry)(void *, void *); void *(*ldap_next_entry)(void *, void *); char *(*ldap_err2string)(int); char *(*ldap_get_dn)(void *, void *); char *(*ldap_first_attribute)(void *, void *, void **); char *(*ldap_next_attribute)(void *, void *, void *); char **(*ldap_get_values)(void *, void *, char *); void (*ldap_value_free)(char **); void (*ldap_memfree)(void *); void (*ber_free)(void *, int); void *server; LDAPURLDesc *ludp; void *result; void *entryIterator; void *ber; void *attribute; struct SessionHandle *data=conn->data; infof(data, "LDAP: %s\n", data->change.url); DynaOpen(); if (libldap == NULL) { failf(data, "The needed LDAP library/libraries couldn't be opened"); return CURLE_LIBRARY_NOT_FOUND; } /* The types are needed because ANSI C distinguishes between * pointer-to-object (data) and pointer-to-function. */ DYNA_GET_FUNCTION(void *(*)(char *, int), ldap_init); DYNA_GET_FUNCTION(int (*)(void *, char *, char *), ldap_simple_bind_s); DYNA_GET_FUNCTION(int (*)(void *), ldap_unbind_s); DYNA_GET_FUNCTION(int (*)(char *, LDAPURLDesc **), ldap_url_parse); DYNA_GET_FUNCTION(void (*)(void *), ldap_free_urldesc); DYNA_GET_FUNCTION(int (*)(void *, char *, int, char *, char **, int, void **), ldap_search_s); DYNA_GET_FUNCTION(int (*)(void *, char *, int, char *, char **, int, void *, void **), ldap_search_st); DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_first_entry); DYNA_GET_FUNCTION(void *(*)(void *, void *), ldap_next_entry); DYNA_GET_FUNCTION(char *(*)(int), ldap_err2string); DYNA_GET_FUNCTION(char *(*)(void *, void *), ldap_get_dn); DYNA_GET_FUNCTION(char *(*)(void *, void *, void **), ldap_first_attribute); DYNA_GET_FUNCTION(char *(*)(void *, void *, void *), ldap_next_attribute); DYNA_GET_FUNCTION(char **(*)(void *, void *, char *), ldap_get_values); DYNA_GET_FUNCTION(void (*)(char **), ldap_value_free); DYNA_GET_FUNCTION(void (*)(void *), ldap_memfree); DYNA_GET_FUNCTION(void (*)(void *, int), ber_free); server = ldap_init(conn->hostname, conn->port); if (server == NULL) { failf(data, "LDAP: Cannot connect to %s:%d", conn->hostname, conn->port); status = CURLE_COULDNT_CONNECT; } else { rc = ldap_simple_bind_s(server, conn->bits.user_passwd?conn->user:NULL, conn->bits.user_passwd?conn->passwd:NULL); if (rc != 0) { failf(data, "LDAP: %s", ldap_err2string(rc)); status = CURLE_LDAP_CANNOT_BIND; } else { rc = ldap_url_parse(data->change.url, &ludp); if (rc != 0) { failf(data, "LDAP: %s", ldap_err2string(rc)); status = CURLE_LDAP_INVALID_URL; } else { rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &result); if (rc != 0) { failf(data, "LDAP: %s", ldap_err2string(rc)); status = CURLE_LDAP_SEARCH_FAILED; } else { for (entryIterator = ldap_first_entry(server, result); entryIterator; entryIterator = ldap_next_entry(server, entryIterator)) { char *dn = ldap_get_dn(server, entryIterator); char **vals; int i; Curl_client_write(data, CLIENTWRITE_BODY, (char *)"DN: ", 4); Curl_client_write(data, CLIENTWRITE_BODY, dn, 0); Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); for(attribute = ldap_first_attribute(server, entryIterator, &ber); attribute; attribute = ldap_next_attribute(server, entryIterator, ber) ) { vals = ldap_get_values(server, entryIterator, attribute); if (vals != NULL) { for(i = 0; (vals[i] != NULL); i++) { Curl_client_write(data, CLIENTWRITE_BODY, (char*)"\t", 1); Curl_client_write(data, CLIENTWRITE_BODY, attribute, 0); Curl_client_write(data, CLIENTWRITE_BODY, (char *)": ", 2); Curl_client_write(data, CLIENTWRITE_BODY, vals[i], 0); Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 0); } } /* Free memory used to store values */ ldap_value_free(vals); } Curl_client_write(data, CLIENTWRITE_BODY, (char *)"\n", 1); ldap_memfree(attribute); ldap_memfree(dn); if (ber) ber_free(ber, 0); } } ldap_free_urldesc(ludp); } ldap_unbind_s(server); } } DynaClose(); /* no data to transfer */ Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL); return status; }