int ldap_search_user(const char *account, LDAPMessage **entry) { char filter[MAXLEN+1]; int rc; LDAPMessage *res; struct timeval timeout; memset(filter, 0, MAXLEN+1); snprintf(filter, MAXLEN, "%s=%s", nickserv_conf.ldap_field_account, account); /* Now we do a search; */ timeout.tv_usec = 0; timeout.tv_sec = nickserv_conf.ldap_timeout; if(!admin_bind && LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); return rc; } if( (rc = ldap_search_st(ld, nickserv_conf.ldap_base, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &timeout, &res)) != LDAP_SUCCESS) { log_module(MAIN_LOG, LOG_ERROR, "search failed: %s %s: %s", nickserv_conf.ldap_base, filter, ldap_err2string(rc)); return(rc); } log_module(MAIN_LOG, LOG_DEBUG, "Search successfull! %s %s\n", nickserv_conf.ldap_base, filter); if(ldap_count_entries(ld, res) != 1) { log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries when looking for %s", ldap_count_entries(ld, res), account); return(LDAP_OTHER); /* Search was a success, but user not found.. */ } log_module(MAIN_LOG, LOG_DEBUG, "LDAP search got %d entries", ldap_count_entries(ld, res)); *entry = ldap_first_entry(ld, res); return(rc); }
static int idmap_query_attrs( struct idmap_context *context, const struct idmap_lookup *lookup, const unsigned attributes, const unsigned optional, PCHAR *values[], const int len) { char filter[FILTER_LEN]; struct idmap_config *config = &context->config; LDAPMessage *res = NULL, *entry; int i, status; /* format the ldap filter */ status = idmap_filter(config, lookup, filter, FILTER_LEN); if (status) goto out; /* send the ldap query */ status = ldap_search_st(context->ldap, config->base, LDAP_SCOPE_SUBTREE, filter, NULL, 0, NULL, &res); if (status) { eprintf("ldap search for '%s' failed with %d: %s\n", filter, status, ldap_err2stringA(status)); status = LdapMapErrorToWin32(status); goto out; } entry = ldap_first_entry(context->ldap, res); if (entry == NULL) { status = LDAP_NO_RESULTS_RETURNED; eprintf("ldap search for '%s' failed with %d: %s\n", filter, status, ldap_err2stringA(status)); status = LdapMapErrorToWin32(status); goto out; } /* fetch the attributes */ for (i = 0; i < len; i++) { if (ATTR_ISSET(attributes, i)) { values[i] = ldap_get_values(context->ldap, entry, config->attributes[i]); /* fail if required attributes are missing */ if (values[i] == NULL && !ATTR_ISSET(optional, i)) { status = LDAP_NO_SUCH_ATTRIBUTE; eprintf("ldap entry for '%s' missing required " "attribute '%s', returning %d: %s\n", filter, config->attributes[i], status, ldap_err2stringA(status)); status = LdapMapErrorToWin32(status); goto out; } } } out: if (res) ldap_msgfree(res); return status; }
/* ARGSUSED */ int _ns_ldap_search_st(char *service, int flags, char *base, int scope, char *filter, char **attrs, int attrsonly, struct timeval *timeout, LDAPMessage **res) { LDAP *ld = __s_api_getLDAPconn(flags); return (ldap_search_st(ld, base, scope, filter, attrs, attrsonly, timeout, res)); }
/* -1 if trouble 0 if user is NOT member of current server group 1 if user IS MEMBER of current server group */ int ldap_ismember(ldap_opt_t * l, const char * user) { LDAPMessage *res; char * filter; int i; if ((!l->sgroup) || !(l->g_basedn)) return 1; /* Am i still connected ? RETRY n times */ /* XXX TODO: setup some conf value for retrying */ if (!(l->flags & FLAG_CONNECTED)) for (i = 0 ; i < 2 ; i++) if (ldap_connect(l) == 0) break; /* quick check for attempts to be evil */ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) return FAILURE; /* build filter for LDAP request */ REQUEST_GROUP(filter, l->fgroup, user); if (ldap_search_st( l->ld, l->g_basedn, LDAP_SCOPE_SUBTREE, filter, NULL, 0, &l->s_timeout, &res) != LDAP_SUCCESS) { ldap_perror(l->ld, "ldap_search_st()"); free(filter); /* XXX error on search, timeout etc.. close ask for reconnect */ ldap_close(l); return FAILURE; } free(filter); /* check if any results */ if (ldap_count_entries(l->ld, res) > 0) { ldap_msgfree(res); return 1; } ldap_msgfree(res); return 0; }
static int get_ldap_seq(const char *server, int port, uint32 *seq) { int ret = -1; struct timeval to; char *attrs[] = {"highestCommittedUSN", NULL}; LDAPMessage *res = NULL; char **values = NULL; LDAP *ldp = NULL; *seq = DOM_SEQUENCE_NONE; /* * Parameterised (5) second timeout on open. This is needed as the search timeout * doesn't seem to apply to doing an open as well. JRA. */ if ((ldp = ldap_open_with_timeout(server, port, lp_ldap_timeout())) == NULL) return -1; /* Timeout if no response within 20 seconds. */ to.tv_sec = 10; to.tv_usec = 0; if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res)) goto done; if (ldap_count_entries(ldp, res) != 1) goto done; values = ldap_get_values(ldp, res, "highestCommittedUSN"); if (!values || !values[0]) goto done; *seq = atoi(values[0]); ret = 0; done: if (values) ldap_value_free(values); if (res) ldap_msgfree(res); if (ldp) ldap_unbind(ldp); return ret; }
static int nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech ) { char *attr[] = { "supportedSASLMechanisms", NULL }; char **values, **v, *mech, *m; LDAPMessage *res, *e; struct timeval timeout; int slen, rc; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } timeout.tv_sec = SEARCH_TIMEOUT_SECS; timeout.tv_usec = 0; rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE, "objectclass=*", attr, 0, &timeout, &res ); if ( rc != LDAP_SUCCESS ) { return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } e = ldap_first_entry( ld, res ); if ( e == NULL ) { ldap_msgfree( res ); if ( ld->ld_errno == LDAP_SUCCESS ) { LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL ); } return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); if ( values == NULL ) { ldap_msgfree( res ); LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL ); return( LDAP_NO_SUCH_ATTRIBUTE ); } slen = 0; for(v = values; *v != NULL; v++ ) { slen += strlen(*v) + 1; } if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) { ldap_value_free( values ); ldap_msgfree( res ); LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( LDAP_NO_MEMORY ); } m = mech; for(v = values; *v; v++) { if (v != values) { *m++ = ' '; } slen = strlen(*v); strncpy(m, *v, slen); m += slen; } *m = '\0'; ldap_value_free( values ); ldap_msgfree( res ); *pmech = mech; return( LDAP_SUCCESS ); }
int qldap_lookup(qldap *q, const char *filter, const char *attrs[]) { /* search a unique entry */ struct timeval tv; int rc; unsigned int num_entries; CHECK(q, SEARCH); tv.tv_sec = ldap_timeout; tv.tv_usec = 0; rc = ldap_search_st(q->ld, basedn.s, LDAP_SCOPE_SUBTREE, filter, (char **)attrs, 0, &tv, &q->res); switch (rc) { /* probably more detailed information should be returned, eg.: LDAP_TIMELIMIT_EXCEEDED, LDAP_SIZELIMIT_EXCEEDED, LDAP_PARTIAL_RESULTS, LDAP_INSUFFICIENT_ACCESS, LDAP_BUSY, LDAP_UNAVAILABLE, LDAP_UNWILLING_TO_PERFORM, LDAP_TIMEOUT */ case LDAP_SUCCESS: logit(128, "qldap_lookup: search for %s succeeded\n", filter); break; case LDAP_TIMEOUT: case LDAP_TIMELIMIT_EXCEEDED: case LDAP_BUSY: logit(64, "qldap_lookup: search for %s failed (%s)\n", filter, ldap_err2string(rc) ); return TIMEOUT; case LDAP_NO_SUCH_OBJECT: logit(64, "qldap_filter: search for %s failed (%s)\n", filter, ldap_err2string(rc) ); return NOSUCH; default: logit(64, "qldap_lookup: search for %s failed (%s)\n", filter, ldap_err2string(rc) ); return FAILED; } /* count the results, we must have exactly one */ num_entries = ldap_count_entries(q->ld, q->res); if (num_entries != 1) { if (num_entries > 1) { logit(64, "qldap_lookup: Too many entries found (%i)\n", num_entries); return TOOMANY; } else { logit(64, "qldap_lookup: Nothing found\n"); return NOSUCH; } } /* go to the first entry */ q->msg = ldap_first_entry(q->ld, q->res); /* * We already selected the first and only entry so * skip SEARCH state and move directly to EXTRACT state. */ q->state = EXTRACT; return OK; }
int qldap_filter(qldap *q, const char *filter, const char *attrs[], char *bdn, int scope) { /* search a unique entry */ struct timeval tv; int rc; /* search multiple entries */ CHECK(q, SEARCH); switch (scope) { case SCOPE_BASE: scope = LDAP_SCOPE_BASE; break; case SCOPE_ONELEVEL: scope = LDAP_SCOPE_ONELEVEL; break; case SCOPE_SUBTREE: scope = LDAP_SCOPE_SUBTREE; break; default: return FAILED; } tv.tv_sec = ldap_timeout; tv.tv_usec = 0; rc = ldap_search_st(q->ld, bdn, scope, filter, (char **)attrs, 0, &tv, &q->res); switch (rc) { /* probably more detailed information should be returned, eg.: LDAP_TIMELIMIT_EXCEEDED, LDAP_SIZELIMIT_EXCEEDED, LDAP_PARTIAL_RESULTS, LDAP_INSUFFICIENT_ACCESS, LDAP_BUSY, LDAP_UNAVAILABLE, LDAP_UNWILLING_TO_PERFORM, LDAP_TIMEOUT */ case LDAP_SUCCESS: logit(128, "qldap_filter: search for %s succeeded\n", filter); break; case LDAP_TIMEOUT: case LDAP_TIMELIMIT_EXCEEDED: case LDAP_BUSY: logit(64, "qldap_filter: search for %s failed (%s)\n", filter, ldap_err2string(rc) ); return TIMEOUT; case LDAP_NO_SUCH_OBJECT: logit(64, "qldap_filter: search for %s failed (%s)\n", filter, ldap_err2string(rc) ); return NOSUCH; default: logit(64, "qldap_filter: search for %s failed (%s)\n", filter, ldap_err2string(rc) ); return FAILED; } q->state = SEARCH; return OK; }
static const char *dict_ldap_lookup(DICT *dict, const char *name) { char *myname = "dict_ldap_lookup"; DICT_LDAP *dict_ldap = (DICT_LDAP *) dict; LDAPMessage *res = 0; static VSTRING *result; struct timeval tv; VSTRING *escaped_name = 0, *filter_buf = 0; int rc = 0; int sizelimit; char *sub, *end; dict_errno = 0; if (msg_verbose) msg_info("%s: In dict_ldap_lookup", myname); /* * If they specified a domain list for this map, then only search for * addresses in domains on the list. This can significantly reduce the * load on the LDAP server. */ if (dict_ldap->domain) { const char *p = strrchr(name, '@'); if (p == 0 || p == name || match_list_match(dict_ldap->domain, ++p) == 0) { if (msg_verbose) msg_info("%s: domain of %s not found in domain list", myname, name); return (0); } } /* * Initialize the result holder. */ if (result == 0) result = vstring_alloc(2); vstring_strcpy(result, ""); /* * Because the connection may be shared and invalidated via queries for * another map, update private copy of "ld" from shared connection * container. */ dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld; /* * Connect to the LDAP server, if necessary. */ if (dict_ldap->ld == NULL) { if (msg_verbose) msg_info ("%s: No existing connection for LDAP source %s, reopening", myname, dict_ldap->ldapsource); dict_ldap_connect(dict_ldap); /* * if dict_ldap_connect() set dict_errno, abort. */ if (dict_errno) return (0); } else if (msg_verbose) msg_info("%s: Using existing connection for LDAP source %s", myname, dict_ldap->ldapsource); /* * Connection caching, means that the connection handle may have the * wrong size limit. Re-adjust before each query. This is cheap, just * sets a field in the ldap connection handle. We also do this in the * connect code, because we sometimes reconnect (below) in the middle of * a query. */ sizelimit = dict_ldap->size_limit ? dict_ldap->size_limit : LDAP_NO_LIMIT; if (ldap_set_option(dict_ldap->ld, LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) msg_warn("%s: %s: Unable to set query result size limit to %ld.", myname, dict_ldap->ldapsource, dict_ldap->size_limit); /* * Prepare the query. */ tv.tv_sec = dict_ldap->timeout; tv.tv_usec = 0; escaped_name = vstring_alloc(20); filter_buf = vstring_alloc(30); /* * If any characters in the supplied address should be escaped per RFC * 2254, do so. Thanks to Keith Stevenson and Wietse. And thanks to * Samuel Tardieu for spotting that wildcard searches were being done in * the first place, which prompted the ill-conceived lookup_wildcards * parameter and then this more comprehensive mechanism. */ end = (char *) name + strlen((char *) name); sub = (char *) strpbrk((char *) name, "*()\\\0"); if (sub && sub != end) { if (msg_verbose) msg_info("%s: Found character(s) in %s that must be escaped", myname, name); for (sub = (char *) name; sub != end; sub++) { switch (*sub) { case '*': vstring_strcat(escaped_name, "\\2a"); break; case '(': vstring_strcat(escaped_name, "\\28"); break; case ')': vstring_strcat(escaped_name, "\\29"); break; case '\\': vstring_strcat(escaped_name, "\\5c"); break; case '\0': vstring_strcat(escaped_name, "\\00"); break; default: vstring_strncat(escaped_name, sub, 1); } } if (msg_verbose) msg_info("%s: After escaping, it's %s", myname, vstring_str(escaped_name)); } else vstring_strcpy(escaped_name, (char *) name); /* * Does the supplied query_filter even include a substitution? */ if ((char *) strchr(dict_ldap->query_filter, '%') == NULL) { /* * No, log the fact and continue. */ msg_warn("%s: %s: Fixed query_filter %s is probably useless", myname, dict_ldap->ldapsource, dict_ldap->query_filter); vstring_strcpy(filter_buf, dict_ldap->query_filter); } else { dict_ldap_expand_filter(dict_ldap->ldapsource, dict_ldap->query_filter, vstring_str(escaped_name), filter_buf); } /* * On to the search. */ if (msg_verbose) msg_info("%s: Searching with filter %s", myname, vstring_str(filter_buf)); rc = ldap_search_st(dict_ldap->ld, dict_ldap->search_base, dict_ldap->scope, vstring_str(filter_buf), dict_ldap->result_attributes->argv, 0, &tv, &res); if (rc == LDAP_SERVER_DOWN) { if (msg_verbose) msg_info("%s: Lost connection for LDAP source %s, reopening", myname, dict_ldap->ldapsource); ldap_unbind(dict_ldap->ld); dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0; dict_ldap_connect(dict_ldap); /* * if dict_ldap_connect() set dict_errno, abort. */ if (dict_errno) return (0); rc = ldap_search_st(dict_ldap->ld, dict_ldap->search_base, dict_ldap->scope, vstring_str(filter_buf), dict_ldap->result_attributes->argv, 0, &tv, &res); } if (rc == LDAP_SUCCESS) { /* * Search worked; extract the requested result_attribute. */ dict_ldap_get_values(dict_ldap, res, result); /* * OpenLDAP's ldap_next_attribute returns a bogus * LDAP_DECODING_ERROR; I'm ignoring that for now. */ rc = dict_ldap_get_errno(dict_ldap->ld); if (rc != LDAP_SUCCESS && rc != LDAP_DECODING_ERROR) msg_warn ("%s: Had some trouble with entries returned by search: %s", myname, ldap_err2string(rc)); if (msg_verbose) msg_info("%s: Search returned %s", myname, VSTRING_LEN(result) > 0 ? vstring_str(result) : "nothing"); } else { /* * Rats. The search didn't work. */ msg_warn("%s: Search error %d: %s ", myname, rc, ldap_err2string(rc)); /* * Tear down the connection so it gets set up from scratch on the * next lookup. */ ldap_unbind(dict_ldap->ld); dict_ldap->ld = DICT_LDAP_CONN(dict_ldap)->conn_ld = 0; /* * And tell the caller to try again later. */ dict_errno = DICT_ERR_RETRY; } /* * Cleanup. */ if (res != 0) ldap_msgfree(res); if (filter_buf != 0) vstring_free(filter_buf); if (escaped_name != 0) vstring_free(escaped_name); /* * If we had an error, return nothing, Otherwise, return the result, if * any. */ return (VSTRING_LEN(result) > 0 && !dict_errno ? vstring_str(result) : 0); }
void run_ldap_tests(service_t *ldaptest, int sslcertcheck, int querytimeout) { #ifdef HAVE_LDAP ldap_data_t *req; testitem_t *t; struct timespec starttime; struct timespec endtime; /* Pick a sensible default for the timeout setting */ if (querytimeout == 0) querytimeout = 30; for (t = ldaptest->items; (t); t = t->next) { LDAPURLDesc *ludp; LDAP *ld; int rc, finished; int msgID = -1; struct timeval ldaptimeout; struct timeval openldaptimeout; LDAPMessage *result; LDAPMessage *e; strbuffer_t *response; char buf[MAX_LINE_LEN]; req = (ldap_data_t *) t->privdata; if (req->skiptest) continue; ludp = (LDAPURLDesc *) req->ldapdesc; getntimer(&starttime); /* Initiate session with the LDAP server */ dbgprintf("Initiating LDAP session for host %s port %d\n", ludp->lud_host, ludp->lud_port); if( (ld = ldap_init(ludp->lud_host, ludp->lud_port)) == NULL ) { dbgprintf("ldap_init failed\n"); req->ldapstatus = XYMON_LDAP_INITFAIL; continue; } /* * There is apparently no standard way of defining a network * timeout for the initial connection setup. */ #if (LDAP_VENDOR == OpenLDAP) && defined(LDAP_OPT_NETWORK_TIMEOUT) /* * OpenLDAP has an undocumented ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv) */ openldaptimeout.tv_sec = querytimeout; openldaptimeout.tv_usec = 0; ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &openldaptimeout); #else /* * So using an alarm() to interrupt any pending operations * seems to be the least insane way of doing this. * * Note that we must do this right after ldap_init(), as * any operation on the session handle (ld) may trigger the * network connection to be established. */ connect_timeout = 0; signal(SIGALRM, ldap_alarmhandler); alarm(querytimeout); #endif /* * This is completely undocumented in the OpenLDAP docs. * But apparently it is documented in * http://www.ietf.org/proceedings/99jul/I-D/draft-ietf-ldapext-ldap-c-api-03.txt * * Both of these routines appear in the <ldap.h> file * from OpenLDAP 2.1.22. Their use to enable TLS has * been deciphered from the ldapsearch() utility * sourcecode. * * According to Manon Goo <*****@*****.**>, recent (Jan. 2005) * OpenLDAP implementations refuse to talk LDAPv2. */ #ifdef LDAP_OPT_PROTOCOL_VERSION { int protocol = LDAP_VERSION3; dbgprintf("Attempting to select LDAPv3\n"); if ((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) { dbgprintf("Failed to select LDAPv3, trying LDAPv2\n"); protocol = LDAP_VERSION2; if ((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) { req->output = strdup(ldap_err2string(rc)); req->ldapstatus = XYMON_LDAP_TLSFAIL; } continue; } } #endif if (req->usetls) { dbgprintf("Trying to enable TLS for session\n"); if ((rc = ldap_start_tls_s(ld, NULL, NULL)) != LDAP_SUCCESS) { dbgprintf("ldap_start_tls failed\n"); req->output = strdup(ldap_err2string(rc)); req->ldapstatus = XYMON_LDAP_TLSFAIL; continue; } } if (!connect_timeout) { msgID = ldap_simple_bind(ld, (t->host->ldapuser ? t->host->ldapuser : ""), (t->host->ldappasswd ? t->host->ldappasswd : "")); } /* Cancel any pending alarms */ alarm(0); signal(SIGALRM, SIG_DFL); /* Did we connect? */ if (connect_timeout || (msgID == -1)) { req->ldapstatus = XYMON_LDAP_BINDFAIL; req->output = "Cannot connect to server"; continue; } /* Wait for bind to complete */ rc = 0; finished = 0; ldaptimeout.tv_sec = querytimeout; ldaptimeout.tv_usec = 0L; while( ! finished ) { int rc2; rc = ldap_result(ld, msgID, LDAP_MSG_ONE, &ldaptimeout, &result); dbgprintf("ldap_result returned %d for ldap_simple_bind()\n", rc); if(rc == -1) { finished = 1; req->ldapstatus = XYMON_LDAP_BINDFAIL; if (result == NULL) { errprintf("LDAP library problem - NULL result returned\n"); req->output = strdup("LDAP BIND failed\n"); } else { rc2 = ldap_result2error(ld, result, 1); req->output = strdup(ldap_err2string(rc2)); } ldap_unbind(ld); } else if (rc == 0) { finished = 1; req->ldapstatus = XYMON_LDAP_BINDFAIL; req->output = strdup("Connection timeout"); ldap_unbind(ld); } else if( rc > 0 ) { finished = 1; if (result == NULL) { errprintf("LDAP library problem - got a NULL resultcode for status %d\n", rc); req->ldapstatus = XYMON_LDAP_BINDFAIL; req->output = strdup("LDAP library problem: ldap_result2error returned a NULL result for status %d\n"); ldap_unbind(ld); } else { rc2 = ldap_result2error(ld, result, 1); if(rc2 != LDAP_SUCCESS) { req->ldapstatus = XYMON_LDAP_BINDFAIL; req->output = strdup(ldap_err2string(rc)); ldap_unbind(ld); } } } } /* ... while() */ /* We're done connecting. If something went wrong, go to next query. */ if (req->ldapstatus != 0) continue; /* Now do the search. With a timeout */ ldaptimeout.tv_sec = querytimeout; ldaptimeout.tv_usec = 0L; rc = ldap_search_st(ld, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldaptimeout, &result); if(rc == LDAP_TIMEOUT) { req->ldapstatus = XYMON_LDAP_TIMEOUT; req->output = strdup(ldap_err2string(rc)); ldap_unbind(ld); continue; } if( rc != LDAP_SUCCESS ) { req->ldapstatus = XYMON_LDAP_SEARCHFAILED; req->output = strdup(ldap_err2string(rc)); ldap_unbind(ld); continue; } getntimer(&endtime); response = newstrbuffer(0); sprintf(buf, "Searching LDAP for %s yields %d results:\n\n", t->testspec, ldap_count_entries(ld, result)); addtobuffer(response, buf); for(e = ldap_first_entry(ld, result); (e != NULL); e = ldap_next_entry(ld, e) ) { char *dn; BerElement *ber; char *attribute; char **vals; dn = ldap_get_dn(ld, e); sprintf(buf, "DN: %s\n", dn); addtobuffer(response, buf); /* Addtributes and values */ for (attribute = ldap_first_attribute(ld, e, &ber); (attribute != NULL); attribute = ldap_next_attribute(ld, e, ber) ) { if ((vals = ldap_get_values(ld, e, attribute)) != NULL) { int i; for(i = 0; (vals[i] != NULL); i++) { sprintf(buf, "\t%s: %s\n", attribute, vals[i]); addtobuffer(response, buf); } } /* Free memory used to store values */ ldap_value_free(vals); } /* Free memory used to store attribute */ ldap_memfree(attribute); ldap_memfree(dn); if (ber != NULL) ber_free(ber, 0); addtobuffer(response, "\n"); } req->ldapstatus = XYMON_LDAP_OK; req->output = grabstrbuffer(response); tvdiff(&starttime, &endtime, &req->duration); ldap_msgfree(result); ldap_unbind(ld); ldap_free_urldesc(ludp); } #endif }
static int auth_ldap_do3(const char *attrname, const char *user, const char *pass, int (*callback)(struct authinfo *, void *), void *arg, const char *newpass, const char *authaddr) { char *newpass_crypt=0; const char *attributes[10], *ldap_attributes[10]; struct timeval timeout; LDAPMessage *result; LDAPMessage *entry; char *filter, *dn; int i, j; struct authinfo auth; char *homeDir=0; char *mailDir=0; char *userPassword=0; char *cryptPassword=0; char *cn=0; uid_t au; gid_t ag; int rc; char *quota=0; int additionalFilter = 0; int hasAdditionalFilter = 0; hasAdditionalFilter = my_ldap.filter != 0; memset(&auth, 0, sizeof(auth)); if (hasAdditionalFilter) { /* To add the additional filter, we need to add on the * additional size for "(&)" and the other filter. So * filter+3 */ additionalFilter = strlen(my_ldap.filter) + 3; } if ((filter=malloc(additionalFilter+strlen(attrname)+strlen(user)+ (my_ldap.domain ? strlen(my_ldap.domain):0)+ sizeof ("(=@)"))) == 0) { perror("malloc"); return 1; } strcpy(filter, "\0"); if (hasAdditionalFilter) { strcat(filter, "(&"); strcat(filter, my_ldap.filter); } strcat(strcat(strcat(strcat(filter, "("), attrname), "="), user); if ( my_ldap.domain && my_ldap.domain[0] && strchr(user, '@') == 0 ) strcat(strcat(filter, "@"), my_ldap.domain); strcat(filter, ")"); if (hasAdditionalFilter) { strcat(filter, ")"); } timeout.tv_sec=my_ldap.timeout; timeout.tv_usec=0; read_env("LDAP_HOMEDIR", &attributes[0], "", 0, "homeDir"); read_env("LDAP_MAILDIR", &attributes[1], "", 0, 0); read_env("LDAP_FULLNAME", &attributes[2], "", 0, "cn"); read_env("LDAP_CLEARPW", &attributes[3], "", 0, 0); read_env("LDAP_CRYPTPW", &attributes[4], "", 0, 0); read_env("LDAP_UID", &attributes[5], "", 0, 0); read_env("LDAP_GID", &attributes[6], "", 0, 0); attributes[7]=my_ldap.mail; read_env("LDAP_MAILDIRQUOTA", &attributes[8], "", 0, 0); j=0; for (i=0; i<9; i++) { if (attributes[i]) ldap_attributes[j++]=attributes[i]; } ldap_attributes[j]=0; if (ldaperror(ldap_search_st(my_ldap_fp, (char *)my_ldap.basedn,LDAP_SCOPE_SUBTREE, filter, (char **)ldap_attributes, 0, &timeout, &result) != LDAP_SUCCESS)) { free(filter); if (my_ldap_fp) return (-1); return (1); } free(filter); /* If we are more than one result, reject */ if (ldap_count_entries(my_ldap_fp,result)!=1) { ldap_msgfree(result); return -1; } #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"Nombre de résulat: %d\n",ldap_count_entries(my_ldap_fp,result)); #endif dn = ldap_get_dn(my_ldap_fp, result); #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"DN: %s\n",dn); #endif if (dn == NULL) { ldap_perror(my_ldap_fp, "ldap_get_dn"); return -1; } /* Get the pointer on this result */ entry=ldap_first_entry(my_ldap_fp,result); if (entry==NULL) { ldap_perror(my_ldap_fp,"ldap_first_entry"); free(dn); return -1; } #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"after ldap_first_entry\n"); #endif /* Copy the directory and the password into struct */ copy_value(my_ldap_fp,entry,attributes[0],&homeDir, user); if (attributes[1]) copy_value(my_ldap_fp,entry,attributes[1],&mailDir, user); copy_value(my_ldap_fp,entry,attributes[2],&cn, user); if (attributes[3]) copy_value(my_ldap_fp,entry,attributes[3],&userPassword, user); if (attributes[4]) copy_value(my_ldap_fp,entry,attributes[4],&cryptPassword, user); au=my_ldap.uid; ag=my_ldap.gid; if (attributes[5]) { char *p=0; unsigned long n; copy_value(my_ldap_fp, entry, attributes[5], &p, user); if (p) { if (sscanf(p, "%lu", &n) > 0) au= (uid_t)n; free(p); } #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"au= %d\n",au); #endif } if (attributes[6]) { char *p=0; unsigned long n; copy_value(my_ldap_fp, entry, attributes[6], &p, user); if (p) { if (sscanf(p, "%lu", &n) > 0) ag= (gid_t)n; free(p); } #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"ag= %d\n",ag); #endif } if (attributes[8]) copy_value(my_ldap_fp,entry,attributes[8],"a, user); if (homeDir != 0 && my_ldap.mailroot != 0 && *my_ldap.mailroot) { char *new_mailroot=malloc(strlen(homeDir)+ strlen(my_ldap.mailroot)+2); if (!new_mailroot) { syslog(LOG_DAEMON|LOG_CRIT, "authldap: malloc failed"); rc= -1; } else { strcat(strcat(strcpy(new_mailroot, my_ldap.mailroot), "/"), homeDir); free(homeDir); homeDir=new_mailroot; } } auth.sysusername=user; auth.sysuserid= &au; auth.sysgroupid= ag; auth.homedir=homeDir; auth.address=authaddr; auth.fullname=cn; auth.maildir=mailDir; auth.clearpasswd=userPassword; auth.passwd=cryptPassword; auth.quota=quota; if (auth.sysusername == 0) auth.sysusername=auth.address=""; if (homeDir == 0) auth.homedir=""; rc=0; if (au == 0 || ag == 0) { syslog(LOG_DAEMON|LOG_CRIT, "authlib: refuse to authenticate %s: uid=%d, gid=%d\n", user, au, ag); rc= 1; } if (pass) { if (my_ldap.authbind) { LDAP *bindp=ldapconnect(); if (!bindp) rc=1; else { #if HAVE_LDAP_TLS if(my_ldap.tls && enable_tls_on(bindp)) { #if HAVE_SYSLOG_H syslog(LOG_DAEMON|LOG_CRIT, "authlib: LDAP_TLS enabled but I'm unable to start tls, check your config\n"); #endif rc = 1; } else { #endif switch (ldap_simple_bind_s(bindp, dn, (char *)pass)) { case LDAP_SUCCESS: break; case LDAP_INVALID_CREDENTIALS: rc = -1; break; default: rc = 1; break; } #if HAVE_LDAP_TLS } #endif ldap_unbind(bindp); } if (rc == 0 && newpass) { if ((newpass_crypt=authcryptpasswd(newpass, NULL)) == 0) rc= -1; } } else { if (auth.clearpasswd) { if (strcmp(pass,auth.clearpasswd)) rc= -1; } else { const char *p=auth.passwd; if (p && strncasecmp(p, "{crypt}", 7) == 0) p += 7; /* For authcheckpassword */ if (!p || authcheckpassword(pass, p)) rc= -1; } if (rc == 0 && newpass && auth.passwd) { if ((newpass_crypt=authcryptpasswd(newpass, auth.passwd) ) == 0) rc= -1; } } } if (rc == 0 && newpass) { LDAPMod *mods[3]; int mod_index=0; LDAPMod mod_clear, mod_crypt; char *mod_clear_vals[2], *mod_crypt_vals[2]; if (attributes[3]) { mods[mod_index]= &mod_clear; mod_clear.mod_op=LDAP_MOD_REPLACE; mod_clear.mod_type=(char *)attributes[3]; mod_clear.mod_values=mod_clear_vals; mod_clear_vals[0]=(char *)newpass; mod_clear_vals[1]=NULL; ++mod_index; } if (attributes[4] && newpass_crypt) { mods[mod_index]= &mod_crypt; mod_crypt.mod_op=LDAP_MOD_REPLACE; mod_crypt.mod_type=(char *)attributes[4]; mod_crypt.mod_values=mod_crypt_vals; mod_crypt_vals[0]=newpass_crypt; mod_crypt_vals[1]=NULL; ++mod_index; } if (mod_index == 0) rc= -1; else { mods[mod_index]=0; if (ldap_modify_s(my_ldap_fp, dn, mods)) { rc= -1; } } } if (newpass_crypt) free(newpass_crypt); free (dn); #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"before callback rc=%d\n",rc); #endif if (rc == 0 && callback) rc= (*callback)(&auth, arg); #if DEBUG_LDAP syslog(LOG_DAEMON|LOG_CRIT,"after callback rc=%d\n",rc); #endif ldap_msgfree(result); if (homeDir) free(homeDir); if (mailDir) free(mailDir); if (userPassword) free(userPassword); if (cryptPassword) free(cryptPassword); if (cn) free(cn); if (quota) free(quota); return (rc); }
/* * dict_ldap_get_values: for each entry returned by a search, get the values * of all its attributes. Recurses to resolve any DN or URL values found. * * This and the rest of the handling of multiple attributes, DNs and URLs * are thanks to LaMont Jones. */ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage * res, VSTRING *result) { static int recursion = 0; static int expansion; long entries = 0; long i = 0; int rc = 0; LDAPMessage *resloop = 0; LDAPMessage *entry = 0; BerElement *ber; char **vals; char *attr; char *myname = "dict_ldap_get_values"; struct timeval tv; LDAPURLDesc *url; tv.tv_sec = dict_ldap->timeout; tv.tv_usec = 0; if (++recursion == 1) expansion = 0; if (msg_verbose) msg_info("%s[%d]: Search found %d match(es)", myname, recursion, ldap_count_entries(dict_ldap->ld, res)); for (entry = ldap_first_entry(dict_ldap->ld, res); entry != NULL; entry = ldap_next_entry(dict_ldap->ld, entry)) { ber = NULL; /* * LDAP should not, but may produce more than the requested maximum * number of entries. */ if (dict_errno == 0 && ++entries > dict_ldap->size_limit && dict_ldap->size_limit) { msg_warn("%s[%d]: %s: Query size limit (%ld) exceeded", myname, recursion, dict_ldap->ldapsource, dict_ldap->size_limit); dict_errno = DICT_ERR_RETRY; } for (attr = ldap_first_attribute(dict_ldap->ld, entry, &ber); attr != NULL; ldap_memfree(attr), attr = ldap_next_attribute(dict_ldap->ld, entry, ber)) { vals = ldap_get_values(dict_ldap->ld, entry, attr); if (vals == NULL) { if (msg_verbose) msg_info("%s[%d]: Entry doesn't have any values for %s", myname, recursion, attr); continue; } /* * If we previously encountered an error, we still continue * through the loop, to avoid memory leaks, but we don't waste * time accumulating any further results. * * XXX: There may be a more efficient way to exit the loop with no * leaks, but it will likely be more fragile and not worth the * extra code. */ if (dict_errno != 0 || vals[0] == 0) { ldap_value_free(vals); continue; } /* * The "result_attributes" list enumerates all the requested * attributes, first the ordinary result attribtutes and then the * special result attributes that hold DN or LDAP URL values. * * The number of ordinary attributes is "num_attributes". * * We compute the attribute type (ordinary or special) from its * index on the "result_attributes" list. */ for (i = 0; dict_ldap->result_attributes->argv[i]; i++) { if (strcasecmp(dict_ldap->result_attributes->argv[i], attr) == 0) break; } /* * Append each returned address to the result list, possibly * recursing (for dn or url attributes). */ if (i < dict_ldap->num_attributes) { /* Ordinary result attribute */ for (i = 0; vals[i] != NULL; i++) { if (++expansion > dict_ldap->expansion_limit && dict_ldap->expansion_limit) { msg_warn("%s[%d]: %s: Expansion limit exceeded at" " result attribute %s=%s", myname, recursion, dict_ldap->ldapsource, attr, vals[i]); dict_errno = DICT_ERR_RETRY; break; } if (VSTRING_LEN(result) > 0) vstring_strcat(result, ","); if (dict_ldap->result_filter == NULL) vstring_strcat(result, vals[i]); else dict_ldap_expand_filter(dict_ldap->ldapsource, dict_ldap->result_filter, vals[i], result); } if (dict_errno != 0) continue; if (msg_verbose) msg_info("%s[%d]: search returned %ld value(s) for" " requested result attribute %s", myname, recursion, i, attr); } else if (recursion < dict_ldap->recursion_limit && dict_ldap->result_attributes->argv[i]) { /* Special result attribute */ for (i = 0; vals[i] != NULL; i++) { if (ldap_is_ldap_url(vals[i])) { if (msg_verbose) msg_info("%s[%d]: looking up URL %s", myname, recursion, vals[i]); rc = ldap_url_parse(vals[i], &url); if (rc == 0) { rc = ldap_search_st(dict_ldap->ld, url->lud_dn, url->lud_scope, url->lud_filter, url->lud_attrs, 0, &tv, &resloop); ldap_free_urldesc(url); } } else { if (msg_verbose) msg_info("%s[%d]: looking up DN %s", myname, recursion, vals[i]); rc = ldap_search_st(dict_ldap->ld, vals[i], LDAP_SCOPE_BASE, "objectclass=*", dict_ldap->result_attributes->argv, 0, &tv, &resloop); } switch (rc) { case LDAP_SUCCESS: dict_ldap_get_values(dict_ldap, resloop, result); break; case LDAP_NO_SUCH_OBJECT: /* * Go ahead and treat this as though the DN existed * and just didn't have any result attributes. */ msg_warn("%s[%d]: DN %s not found, skipping ", myname, recursion, vals[i]); break; default: msg_warn("%s[%d]: search error %d: %s ", myname, recursion, rc, ldap_err2string(rc)); dict_errno = DICT_ERR_RETRY; break; } if (resloop != 0) ldap_msgfree(resloop); if (dict_errno != 0) break; } if (dict_errno != 0) continue; if (msg_verbose) msg_info("%s[%d]: search returned %ld value(s) for" " special result attribute %s", myname, recursion, i, attr); } else if (recursion >= dict_ldap->recursion_limit && dict_ldap->result_attributes->argv[i]) { msg_warn("%s[%d]: %s: Recursion limit exceeded" " for special attribute %s=%s", myname, recursion, dict_ldap->ldapsource, attr, vals[0]); dict_errno = DICT_ERR_RETRY; } ldap_value_free(vals); } if (ber) ber_free(ber, 0); } if (msg_verbose) msg_info("%s[%d]: Leaving %s", myname, recursion, myname); --recursion; }
/* **| method: object search ( mapping params ); **| This is the preferred way of calling this method. ** **| alt: object search ( string filter ); **| alt: object search ( string filter, array attrs ); **| alt: object search ( string filter, array attrs, int attrsonly ); **| alt: object search ( string filter, array attrs, int attrsonly, int timeout ); ** **| general: search the LDAP directory for the specified entry **| (entries). The first form is the preferred one as it **| encompasses all the current and future parameters as expected **| by the underlying API. The following fields are read from the **| mapping:@nl **| **| @list **| * base - the base DN to use in this search. Overrides the **| default base DN (as set with set_base_dn) **| * scope - the search scope for this search. Overrides the **| default scope (as set with set_scope) **| * filter - the search filter. The BNF for the filter is as **| follows: **| @pre **| <filter> ::= `(' <filtercomp> `)' **| <filtercomp> ::= <and> | <or> | <not> | <simple> **| <and> ::= `&' <filterlist> **| <or> ::= `|' <filterlist> **| <not> ::= `!' <filter> **| <filterlist> ::= <filter> | <filter> <filterlist> **| <simple> ::= <attributetype> <filtertype> <attributevalue> **| <filtertype> ::= `=' | `~=' | `<=' | `>=' **| @pre_end **| * attrs - search attributes. An array of attribute types to **| return in the result. If absent, all types will be returned. **| * attrsonly - if != then the result will contain attribute **| types only - no values shall be returned. **| * timeout - the timeout, in seconds, after which the call **| should return if the search isn't finished. **| @list_end */ static void f_ldap_search(INT32 args) { char *filter; int scope; struct pike_string *base; char **attrs; int attrsonly; struct timeval *timeout; LDAPMessage *res; int ret; struct object *obj; if (!THIS->bound) Pike_error("OpenLDAP.Client: attempting operation on an unbound connection\n"); if (!args) Pike_error("OpenLDAP.Client->search() requires at least one argument\n"); if (args == 1) { switch(ARG(1).type) { case T_MAPPING: { /* the new style case */ struct svalue *val; struct mapping *m = ARG(1).u.mapping; /* * m->base */ val = low_mapping_string_lookup(m, base_str); if (!val || val->type != T_STRING) base = THIS->basedn; else base = val->u.string; /* * m->scope */ val = low_mapping_string_lookup(m, scope_str); if (!val || val->type != T_INT) scope = THIS->scope; else scope = val->u.integer; /* * m->filter */ val = low_mapping_string_lookup(m, filter_str); if (!val || val->type != T_STRING) filter = OL_DEF_FILTER; else filter = val->u.string->str; /* * m->attrs */ val = low_mapping_string_lookup(m, attrs_str); if (!val || val->type != T_ARRAY) attrs = NULL; else attrs = make_c_array(val); /* * m->attrsonly */ val = low_mapping_string_lookup(m, attrsonly_str); if (!val || val->type != T_INT) attrsonly = 0; else attrsonly = val->u.integer != 0; /* * m->timeout */ val = low_mapping_string_lookup(m, timeout_str); if (!val || val->type != T_INT) timeout = NULL; else timeout = make_timeout(val->u.integer); /*TEMPORARY*/ break; } case T_STRING: /* the old style case */ base = THIS->basedn; scope = THIS->scope; filter = ARG(1).u.string->str; attrs = NULL; attrsonly = 0; timeout = NULL; break; default: Pike_error("OpenLDAP.Client->search() with single argument requires either a mapping or a string\n"); break; } } else switch(args) { case 4: /* timeout */ if (ARG(4).type != T_INT) Pike_error("OpenLDAP.Client->search(): argument 4 must be an integer\n"); else timeout = make_timeout(ARG(4).u.integer); /* fall through */ case 3: /* attrsonly */ if (ARG(3).type != T_INT) Pike_error("OpenLDAP.Client->search(): argument 3 must be an integer\n"); else attrsonly = ARG(3).u.integer != 0; /* fall through */ case 2: /* attrs */ if (ARG(2).type != T_ARRAY) Pike_error("OpenLDAP.Client->search(): argument 2 must be an array\n"); else attrs = make_c_array(&ARG(2)); base = THIS->basedn; scope = THIS->scope; filter = ARG(1).u.string->str; attrsonly = 0; timeout = NULL; break; default: Pike_error("OpenLDAP.Client->search(): incorrect number of arguments\n"); break; } ret = timeout ? ldap_search_st(THIS->conn, base->str, scope, filter, attrs, attrsonly, timeout, &res) : ldap_search_s(THIS->conn, base->str, scope, filter, attrs, attrsonly, &res); if (ret) Pike_error("OpenLDAP.Client->search(): %s\n", ldap_err2string(ret)); pop_n_elems(args); THIS->data = res; obj = clone_object(result_program, 0); push_object(obj); if (attrs) free(attrs); }
static int auth_ldap_do2(const char *user, const char *pass, int (*callback)(struct authinfo *, void *), void *arg, const char *newpass) { char *srch; struct timeval tv; const char *attributes[2]; LDAPMessage *result, *entry; int cnt; char *v; const char *aname; if (ldapopen()) return (1); if (my_ldap.emailmap[0] == 0 || strchr(user, '@') == NULL) return (auth_ldap_do3(my_ldap.mail, user, pass, callback, arg, newpass, user)); /* Mapping is not enabled */ srch=emailmap_get_search_string(my_ldap.emailmap, user); if (!srch) { perror("malloc"); exit(1); } tv.tv_sec=my_ldap.timeout; tv.tv_usec=0; attributes[0]=my_ldap.emailmap_handle; if (!attributes[0][0]) attributes[0]="handle"; attributes[1]=NULL; if (ldaperror(ldap_search_st(my_ldap_fp, (char *)(my_ldap.emailmap_basedn[0] ? my_ldap.emailmap_basedn :my_ldap.basedn), LDAP_SCOPE_SUBTREE, srch, (char **)attributes, 0, &tv, &result) != LDAP_SUCCESS)) { free(srch); if (my_ldap_fp) return (-1); return (1); } if ((cnt=ldap_count_entries(my_ldap_fp, result)) != 1) { free(srch); if (cnt) syslog(LOG_DAEMON|LOG_CRIT, "authldap: %d results from search: %s\n", cnt, srch); ldap_msgfree(result); return -1; } free(srch); entry=ldap_first_entry(my_ldap_fp, result); if (!entry) { ldap_msgfree(result); syslog(LOG_DAEMON|LOG_CRIT, "authldap: unexpected NULL from ldap_first_entry"); return -1; } copy_value(my_ldap_fp, entry, attributes[0], &v, user); if (!v) { ldap_msgfree(result); return (-1); } aname=my_ldap.emailmap_handle_lookup; if (aname[0] == 0) aname=my_ldap.mail; cnt=auth_ldap_do3(aname, v, pass, callback, arg, newpass, user); ldap_msgfree(result); free(v); return (cnt); }
DWORD LwLdapDirectorySearch( HANDLE hDirectory, PCSTR pszObjectDN, int scope, PCSTR pszQuery, PSTR* ppszAttributeList, LDAPMessage** ppMessage ) { DWORD dwError = LW_ERROR_SUCCESS; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = (PLW_LDAP_DIRECTORY_CONTEXT)hDirectory; struct timeval timeout = {0}; LDAPMessage* pMessage = NULL; timeout.tv_sec = 15; timeout.tv_usec = 0; dwError = ldap_search_st(pDirectory->ld, pszObjectDN, scope, pszQuery, ppszAttributeList, 0, &timeout, &pMessage); if (dwError) { if (dwError == LDAP_NO_SUCH_OBJECT) { LW_RTL_LOG_VERBOSE("Caught LDAP_NO_SUCH_OBJECT Error on ldap search"); BAIL_ON_LDAP_ERROR(dwError); } if (dwError == LDAP_REFERRAL) { LW_RTL_LOG_ERROR("Caught LDAP_REFERRAL Error on ldap search"); LW_RTL_LOG_ERROR("LDAP Search Info: DN: [%s]", LW_IS_NULL_OR_EMPTY_STR(pszObjectDN) ? "<null>" : pszObjectDN); LW_RTL_LOG_ERROR("LDAP Search Info: scope: [%d]", scope); LW_RTL_LOG_ERROR("LDAP Search Info: query: [%s]", LW_IS_NULL_OR_EMPTY_STR(pszQuery) ? "<null>" : pszQuery); if (ppszAttributeList) { size_t i; for (i = 0; ppszAttributeList[i] != NULL; i++) { LW_RTL_LOG_ERROR("LDAP Search Info: attribute: [%s]", ppszAttributeList[i]); } } else { LW_RTL_LOG_ERROR("Error: LDAP Search Info: no attributes were specified"); } } BAIL_ON_LDAP_ERROR(dwError); } *ppMessage = pMessage; cleanup: return(dwError); error: *ppMessage = NULL; if (pMessage) { ldap_msgfree(pMessage); } goto cleanup; }
char* ldap_lookup(config_t agent_config, const char *username, char *external_uid) { LDAP *ld; LDAPMessage *result = (LDAPMessage *) 0; LDAPMessage *e; BerElement *ber; char *a, *dn; char *sane_username = malloc(strlen(username)*2); char *p = sane_username; char **vals = NULL; struct timeval ldaptimeout = {.tv_sec = BIND_TIMEOUT, .tv_usec = 0}; int i, rc=0, num_entries=0; char *transcoded_query = NULL; char *ldap_uri = NULL; char *end_ptr; char *ldap_host = _ds_read_attribute(agent_config, "ExtLookupServer"); char *port = _ds_read_attribute(agent_config, "ExtLookupPort"); long lldap_port; int ldap_port = 389; char *ldap_binddn = _ds_read_attribute(agent_config, "ExtLookupLogin"); char *ldap_passwd = _ds_read_attribute(agent_config, "ExtLookupPassword"); char *ldap_base = _ds_read_attribute(agent_config, "ExtLookupDB"); char *ldap_attrs[] = {_ds_read_attribute(agent_config, "ExtLookupLDAPAttribute"),0}; char *version = _ds_read_attribute(agent_config, "ExtLookupLDAPVersion"); long lldap_version; int ldap_version = 3; char *ldap_filter = _ds_read_attribute(agent_config, "ExtLookupQuery"); int ldap_scope; if (port != NULL) { errno=0; lldap_port = strtol(port, &end_ptr, 0); if ( (errno != 0) || (lldap_port < INT_MIN) || (lldap_port > INT_MAX) || (*end_ptr != '\0')) { LOG(LOG_ERR, "External Lookup: bad LDAP port number"); return NULL; } else ldap_port = (int)lldap_port; } /* set ldap protocol version */ if (version != NULL) { errno=0; lldap_version = strtol(version, &end_ptr, 0); if ((errno != 0) || (lldap_version < 1) || (lldap_version > 3) || (*end_ptr != '\0')) { LOG(LOG_ERR, "External Lookup: bad LDAP protocol version"); return NULL; } else ldap_version = (int)lldap_version; } if (_ds_match_attribute(agent_config, "ExtLookupLDAPScope", "one")) ldap_scope = LDAP_SCOPE_ONELEVEL; else /* defaults to sub */ ldap_scope = LDAP_SCOPE_SUBTREE; /* set alarm handler */ signal(SIGALRM, sig_alrm); /* sanitize username for filter integration */ for (; *username != '\0'; username++) { switch(*username) { case 0x2a: /* '*' */ case 0x28: /* '(' */ case 0x29: /* ')' */ case 0x5c: /* '\' */ case 0x00: /* NUL */ *p++ = 0x5c; /* '\' */ *p++ = *username; break; default: *p++ = *username; break; } } *p = '\0'; LOGDEBUG("External Lookup: sanitized username is %s\n", sane_username); /* build proper LDAP filter*/ transcoded_query = strdup(transcode_query(ldap_filter, sane_username, transcoded_query)); free(sane_username); if (transcoded_query == NULL) { LOG(LOG_ERR, "External Lookup: %s", ERR_EXT_LOOKUP_MISCONFIGURED); return NULL; } if( ldap_host != NULL || ldap_port ) { /* construct URL */ LDAPURLDesc url; memset( &url, 0, sizeof(url)); url.lud_scheme = "ldap"; url.lud_host = ldap_host; url.lud_port = ldap_port; url.lud_scope = LDAP_SCOPE_SUBTREE; ldap_uri = ldap_url_desc2str( &url ); } rc = ldap_initialize( &ld, ldap_uri ); if( rc != LDAP_SUCCESS ) { LOG(LOG_ERR, "External Lookup: Could not create LDAP session handle for URI=%s (%d): %s\n", ldap_uri, rc, ldap_err2string(rc)); return NULL; } if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version ) != LDAP_OPT_SUCCESS ) { LOG(LOG_ERR, "External Lookup: Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", ldap_version ); return NULL; } /* use TLS if configured */ if ( _ds_match_attribute(agent_config, "ExtLookupCrypto", "tls" )) { if (ldap_version != 3) { LOG(LOG_ERR, "External Lookup: TLS only supported with LDAP protocol version 3"); return NULL; } if ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { LOG(LOG_ERR, "External Lookup: %s: %s (%d)", ERR_EXT_LOOKUP_INIT_FAIL, strerror(errno), errno); return NULL; } } /* schedules alarm */ alarm(BIND_TIMEOUT); /* authenticate to the directory */ if ( (rc = ldap_simple_bind_s( ld, ldap_binddn, ldap_passwd )) != LDAP_SUCCESS ) { /* cancel alarms */ alarm(0); LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_INIT_FAIL, ldap_err2string(rc) ); ldap_unbind(ld); return NULL; } /* cancel alarms */ alarm(0); /* search for all entries matching the filter */ if ( (rc = ldap_search_st( ld, ldap_base, ldap_scope, transcoded_query, ldap_attrs, 0, &ldaptimeout, &result )) != LDAP_SUCCESS ) { free(transcoded_query); switch(rc) { case LDAP_TIMEOUT: case LDAP_BUSY: case LDAP_UNAVAILABLE: case LDAP_UNWILLING_TO_PERFORM: case LDAP_SERVER_DOWN: case LDAP_TIMELIMIT_EXCEEDED: LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)) ); ldap_unbind( ld ); return NULL; break; case LDAP_FILTER_ERROR: LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)) ); ldap_unbind( ld ); return NULL; break; case LDAP_SIZELIMIT_EXCEEDED: if ( result == NULL ) { LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1)) ); ldap_unbind( ld ); return NULL; } break; default: LOG(LOG_ERR, "External Lookup: %s: code=%d, %s", ERR_EXT_LOOKUP_SEARCH_FAIL, rc, ldap_err2string(ldap_result2error(ld, result, 1)) ); ldap_unbind( ld ); return NULL; } } num_entries=ldap_count_entries(ld,result); LOGDEBUG("External Lookup: found %d LDAP entries", num_entries); switch (num_entries) { case 1: /* only one entry, let's proceed */ break; case -1: /* an error occured */ LOG(LOG_ERR, "External Lookup: %s: %s", ERR_EXT_LOOKUP_SEARCH_FAIL, ldap_err2string(ldap_result2error(ld, result, 1))); ldap_unbind( ld ); return NULL ; case 0: /* no entries found */ LOGDEBUG("External Lookup: %s: no entries found.", ERR_EXT_LOOKUP_SEARCH_FAIL); ldap_msgfree( result ); ldap_unbind( ld ); return NULL ; default: /* more than one entry returned */ LOG(LOG_ERR, "External Lookup: %s: more than one entry returned.", ERR_EXT_LOOKUP_SEARCH_FAIL); ldap_msgfree( result ); ldap_unbind( ld ); return NULL; } /* for each entry print out name + all attrs and values */ for ( e = ldap_first_entry( ld, result ); e != NULL; e = ldap_next_entry( ld, e ) ) { if ( (dn = ldap_get_dn( ld, e )) != NULL ) { ldap_memfree( dn ); } for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { if ((vals = ldap_get_values( ld, e, a)) != NULL ) { for ( i = 0; vals[i] != NULL; i++ ) { external_uid = strdup(vals[i]); } ldap_value_free( vals ); } ldap_memfree( a ); } if ( ber != NULL ) { ber_free( ber, 0 ); } } ldap_msgfree( result ); ldap_unbind( ld ); return external_uid; } #endif char* program_lookup(config_t agent_config, const char *username, char *external_uid) { pid_t wstatus, pid; int i, status; int fd[2]; char *output = malloc (1024); char **args = malloc (1024); char *token; char *saveptr; char *str; char *command_line = 0; /* build proper command line*/ command_line = strdup(transcode_query(_ds_read_attribute(agent_config, "ExtLookupServer"), username, command_line)); if (command_line == NULL) { LOG(LOG_ERR, ERR_EXT_LOOKUP_MISCONFIGURED); free(output); free(args); return NULL; } LOGDEBUG("command line is %s", command_line); /* break the command line into arguments */ for (i = 0, str = command_line; ; i++, str = NULL) { token = strtok_r(str, " ", &saveptr); if (token == NULL) break; args[i] = token; LOGDEBUG("args[%d] = %s",i,token); } args[i] = (char *) 0; if (pipe(fd) == -1) { LOG(LOG_ERR, "%s: errno=%i (%s)", ERR_EXT_LOOKUP_INIT_FAIL, errno, strerror(errno)); free(output); free(args); return NULL; } switch(pid=fork()) { case -1: /* couldn't fork - something went wrong */ LOG(LOG_ERR, "%s: errno=%i (%s)", ERR_EXT_LOOKUP_INIT_FAIL, errno, strerror(errno)); free(output); free(args); return NULL; case 0: /* execute the command and write to fd */ close(fd[0]); dup2(fd[1], fileno(stdout)); execve(args[0], args, 0); exit(EXIT_FAILURE); default: /* read from fd the first output line */ do { wstatus = waitpid( pid, &status, WUNTRACED | WCONTINUED); if (wstatus == -1) { LOGDEBUG("waitpid() exited with an error: %s: errno=%i", strerror(errno), errno); free(output); free(args); return NULL; } if (WIFEXITED(status)) { LOGDEBUG("exited, status=%d\n", WEXITSTATUS(status)); if (WEXITSTATUS(status)) { LOGDEBUG("Error running %s. Check path and permissions.\n", args[0]); } } else if (WIFSIGNALED(status)) { LOGDEBUG("killed by signal %d\n", WTERMSIG(status)); } else if (WIFSTOPPED(status)) { LOGDEBUG("stopped by signal %d\n", WSTOPSIG(status)); } else if (WIFCONTINUED(status)) { LOGDEBUG("continued\n"); } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); close(fd[1]); /* just in case there's no line break at the end of the return... */ memset(output, 0, 1024); if (read(fd[0], output, 1024) == -1) { LOG(LOG_ERR, "%s: errno=%i (%s)", ERR_EXT_LOOKUP_INIT_FAIL, errno, strerror(errno)); free(output); free(args); return NULL; } close(fd[0]); } if (strlen(output) == 0) { free(output); free(args); return NULL; } /* terminate the output string at the first \n */ token = strchr(output, '\n'); if (token != NULL) *token = '\0'; external_uid = strdup(output); free(output); free(command_line); free(args); return external_uid; }
static int do_entry2text_search( LDAP *ld, char *dn, /* if NULL, use entry */ char *base, /* if NULL, no search actions */ LDAPMessage *entry, /* if NULL, use dn */ struct ldap_disptmpl* tmpllist, /* if NULL, load default file */ char **defattrs, char ***defvals, writeptype writeproc, void *writeparm, char *eol, int rdncount, /* if 0, display full DN */ unsigned int opts, char *urlprefix ) { int err, freedn, freetmpls, html; char *buf, **fetchattrs, **vals; LDAPMessage *ldmp; struct ldap_disptmpl *tmpl; struct timeval timeout; if ( dn == NULL && entry == NULLMSG ) { ld->ld_errno = LDAP_PARAM_ERROR; return( ld->ld_errno ); } html = ( urlprefix != NULL ); timeout.tv_sec = SEARCH_TIMEOUT_SECS; timeout.tv_usec = 0; if (( buf = malloc( LDAP_DTMPL_BUFSIZ )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } freedn = freetmpls = 0; tmpl = NULL; if ( tmpllist == NULL ) { if (( err = ldap_init_templates( TEMPLATEFILE, &tmpllist )) != 0 ) { sprintf( buf, "%sUnable to read template file %s (error %d)%s%s", html ? "<!-- " : "", TEMPLATEFILE, err, html ? "-->" : "", eol ); (*writeproc)( writeparm, buf, strlen( buf )); } freetmpls = 1; } if ( dn == NULL ) { if (( dn = ldap_get_dn( ld, entry )) == NULL ) { free( buf ); if ( freetmpls ) { ldap_free_templates( tmpllist ); } return( ld->ld_errno ); } freedn = 1; } if ( tmpllist != NULL ) { ldmp = NULLMSG; if ( entry == NULL ) { char *ocattrs[2]; ocattrs[0] = OCATTRNAME; ocattrs[1] = NULL; #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", ocattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", ocattrs, 0, &timeout, &ldmp ); if ( err == LDAP_SUCCESS ) { entry = ldap_first_entry( ld, ldmp ); } } if ( entry != NULL ) { vals = ldap_get_values( ld, entry, OCATTRNAME ); tmpl = ldap_oc2template( vals, tmpllist ); if ( vals != NULL ) { ldap_value_free( vals ); } } if ( ldmp != NULL ) { ldap_msgfree( ldmp ); } } entry = NULL; if ( tmpl == NULL ) { fetchattrs = NULL; } else { fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER ); } #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", fetchattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", fetchattrs, 0, &timeout, &ldmp ); if ( freedn ) { free( dn ); } if ( fetchattrs != NULL ) { ldap_value_free( fetchattrs ); } if ( err != LDAP_SUCCESS || ( entry = ldap_first_entry( ld, ldmp )) == NULL ) { if ( freetmpls ) { ldap_free_templates( tmpllist ); } free( buf ); return( ld->ld_errno ); } err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix ); free( buf ); if ( freetmpls ) { ldap_free_templates( tmpllist ); } ldap_msgfree( ldmp ); return( err ); }
static int searchaction( LDAP *ld, char *buf, char *base, LDAPMessage *entry, char *dn, struct ldap_tmplitem *tip, int labelwidth, int rdncount, writeptype writeproc, void *writeparm, char *eol, char *urlprefix ) { int err, lderr, i, count, html; char **vals, **members; char *value, *filtpattern, *attr, *selectname; char *retattrs[2], filter[ 256 ]; LDAPMessage *ldmp; struct timeval timeout; html = ( urlprefix != NULL ); for ( i = 0; tip->ti_args != NULL && tip->ti_args[ i ] != NULL; ++i ) { ; } if ( i < 3 ) { return( LDAP_PARAM_ERROR ); } attr = tip->ti_args[ 0 ]; filtpattern = tip->ti_args[ 1 ]; retattrs[ 0 ] = tip->ti_args[ 2 ]; retattrs[ 1 ] = NULL; selectname = tip->ti_args[ 3 ]; vals = NULL; if ( attr == NULL ) { value = NULL; } else if ( strcasecmp( attr, "-dnb" ) == 0 ) { return( LDAP_PARAM_ERROR ); } else if ( strcasecmp( attr, "-dnt" ) == 0 ) { value = dn; } else if (( vals = ldap_get_values( ld, entry, attr )) != NULL ) { value = vals[ 0 ]; } else { value = NULL; } ldap_build_filter( filter, sizeof( filter ), filtpattern, NULL, NULL, NULL, value, NULL ); if ( html ) { /* * if we are generating HTML, we add an HREF link that embodies this * search action as an LDAP URL, instead of actually doing the search * now. */ sprintf( buf, "<DT><A HREF=\"%s", urlprefix ); if ( base != NULL ) { strcat_escaped( buf, base ); } strcat( buf, "??sub?" ); strcat_escaped( buf, filter ); sprintf( buf + strlen( buf ), "\"><B>%s</B></A><DD><BR>%s", tip->ti_label, eol ); if ((*writeproc)( writeparm, buf, strlen( buf )) < 0 ) { return( LDAP_LOCAL_ERROR ); } return( LDAP_SUCCESS ); } timeout.tv_sec = SEARCH_TIMEOUT_SECS; timeout.tv_usec = 0; #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) lderr = cldap_search_s( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ lderr = ldap_search_st( ld, base, LDAP_SCOPE_SUBTREE, filter, retattrs, 0, &timeout, &ldmp ); if ( lderr == LDAP_SUCCESS || NONFATAL_LDAP_ERR( lderr )) { if (( count = ldap_count_entries( ld, ldmp )) > 0 ) { if (( members = (char **)malloc( (count + 1) * sizeof(char *))) == NULL ) { err = LDAP_NO_MEMORY; } else { for ( i = 0, entry = ldap_first_entry( ld, ldmp ); entry != NULL; entry = ldap_next_entry( ld, entry ), ++i ) { members[ i ] = ldap_get_dn( ld, entry ); } members[ i ] = NULL; ldap_sort_values( ld, members, ldap_sort_strcasecmp ); err = do_vals2text( ld, NULL, members, tip->ti_label, html ? -1 : 0, LDAP_SYN_DN, writeproc, writeparm, eol, rdncount, urlprefix ); ldap_value_free( members ); } } ldap_msgfree( ldmp ); } if ( vals != NULL ) { ldap_value_free( vals ); } return(( err == LDAP_SUCCESS ) ? lderr : err ); }
/* * ldap_getattr_fromfilter_withbase_scope(): * conflags: KEEPALIVE * scope: LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE * result: return unique search result here, allocated here, caller must free * * returns: -1 on error * 0 nothing found * 1 successfull search, result int 'result' * * All connection managment to the LDAP server is done here. Just set KEEPALIVE if you know * you will be dispatching more than one search in a row, then don't set it with the last search. * You MUST dispatch the queries timely, otherwise the LDAP handle might timeout. */ static int ldap_getattr_fromfilter_withbase_scope( const char *searchbase, const char *filter, char *attributes[], int scope, ldapcon_t conflags, char **result) { int ret; int ldaperr; int retrycount = 0; int desired_version = LDAP_VERSION3; static int ldapconnected = 0; static LDAP *ld = NULL; LDAPMessage* msg = NULL; LDAPMessage* entry = NULL; char **attribute_values = NULL; struct timeval timeout; LOG(log_maxdebug, logtype_afpd,"ldap: BEGIN"); timeout.tv_sec = 3; timeout.tv_usec = 0; /* init LDAP if necessary */ retry: ret = 0; if (ld == NULL) { LOG(log_maxdebug, logtype_default, "ldap: server: \"%s\"", ldap_server); if ((ld = ldap_init(ldap_server, LDAP_PORT)) == NULL ) { LOG(log_error, logtype_default, "ldap: ldap_init error: %s", strerror(errno)); return -1; } if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != 0) { /* LDAP_OPT_SUCCESS is not in the proposed standard, so we check for 0 http://tools.ietf.org/id/draft-ietf-ldapext-ldap-c-api-05.txt */ LOG(log_error, logtype_default, "ldap: ldap_set_option failed!"); free(ld); ld = NULL; return -1; } } /* connect */ if (!ldapconnected) { if (LDAP_AUTH_NONE == ldap_auth_method) { if (ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != LDAP_SUCCESS ) { LOG(log_error, logtype_default, "ldap: ldap_bind failed, auth_method: \'%d\'", ldap_auth_method); free(ld); ld = NULL; return -1; } ldapconnected = 1; } else if (LDAP_AUTH_SIMPLE == ldap_auth_method) { if (ldap_bind_s(ld, ldap_auth_dn, ldap_auth_pw, ldap_auth_method) != LDAP_SUCCESS ) { LOG(log_error, logtype_default, "ldap: ldap_bind failed: ldap_auth_dn: \'%s\', ldap_auth_pw: \'%s\', ldap_auth_method: \'%d\'", ldap_auth_dn, ldap_auth_pw, ldap_auth_method); free(ld); ld = NULL; return -1; } ldapconnected = 1; } } LOG(log_maxdebug, logtype_afpd, "ldap: start search: base: %s, filter: %s, attr: %s", searchbase, filter, attributes[0]); /* start LDAP search */ ldaperr = ldap_search_st(ld, searchbase, scope, filter, attributes, 0, &timeout, &msg); LOG(log_maxdebug, logtype_default, "ldap: ldap_search_st returned: %s", ldap_err2string(ldaperr)); if (ldaperr != LDAP_SUCCESS) { LOG(log_error, logtype_default, "ldap: ldap_search_st failed: %s, retrycount: %i", ldap_err2string(ldaperr), retrycount); ret = -1; goto cleanup; } /* parse search result */ LOG(log_maxdebug, logtype_default, "ldap: got %d entries from ldap search", ldap_count_entries(ld, msg)); if ((ret = ldap_count_entries(ld, msg)) != 1) { ret = 0; goto cleanup; } entry = ldap_first_entry(ld, msg); if (entry == NULL) { LOG(log_error, logtype_default, "ldap: ldap_first_entry error"); ret = -1; goto cleanup; } attribute_values = ldap_get_values(ld, entry, attributes[0]); if (attribute_values == NULL) { LOG(log_error, logtype_default, "ldap: ldap_get_values error"); ret = -1; goto cleanup; } LOG(log_maxdebug, logtype_afpd,"ldap: search result: %s: %s", attributes[0], attribute_values[0]); /* allocate result */ *result = strdup(attribute_values[0]); if (*result == NULL) { LOG(log_error, logtype_default, "ldap: strdup error: %s",strerror(errno)); ret = -1; goto cleanup; } cleanup: if (attribute_values) ldap_value_free(attribute_values); /* FIXME: is there another way to free entry ? */ while (entry != NULL) entry = ldap_next_entry(ld, entry); if (msg) ldap_msgfree(msg); if (ldapconnected) { if ((ret == -1) || !(conflags & KEEPALIVE)) { LOG(log_maxdebug, logtype_default,"ldap: unbind"); if (ldap_unbind_s(ld) != 0) { LOG(log_error, logtype_default, "ldap: unbind: %s\n", ldap_err2string(ldaperr)); return -1; } ld = NULL; ldapconnected = 0; /* In case of error we try twice */ if (ret == -1) { retrycount++; if (retrycount < 2) goto retry; } } } return ret; }
static int do_entry2text_search( LDAP *ld, char *dn, /* if NULL, use entry */ char *base, /* if NULL, no search actions */ LDAPMessage *entry, /* if NULL, use dn */ struct ldap_disptmpl* tmpllist, /* if NULL, no template used */ char **defattrs, char ***defvals, writeptype writeproc, void *writeparm, char *eol, int rdncount, /* if 0, display full DN */ unsigned long opts, char *urlprefix ) { int err, freedn, html; char *buf, **fetchattrs, **vals; LDAPMessage *ldmp; struct ldap_disptmpl *tmpl; struct timeval timeout; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( dn == NULL && entry == NULLMSG ) { err = LDAP_PARAM_ERROR; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); return( err ); } html = ( urlprefix != NULL ); timeout.tv_sec = SEARCH_TIMEOUT_SECS; timeout.tv_usec = 0; if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { err = LDAP_NO_MEMORY; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); return( err ); } freedn = 0; tmpl = NULL; if ( dn == NULL ) { if (( dn = ldap_get_dn( ld, entry )) == NULL ) { NSLDAPI_FREE( buf ); return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } freedn = 1; } if ( tmpllist != NULL ) { ldmp = NULLMSG; if ( entry == NULL ) { char *ocattrs[2]; ocattrs[0] = OCATTRNAME; ocattrs[1] = NULL; #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", ocattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", ocattrs, 0, &timeout, &ldmp ); if ( err == LDAP_SUCCESS ) { entry = ldap_first_entry( ld, ldmp ); } } if ( entry != NULL ) { vals = ldap_get_values( ld, entry, OCATTRNAME ); tmpl = ldap_oc2template( vals, tmpllist ); if ( vals != NULL ) { ldap_value_free( vals ); } } if ( ldmp != NULL ) { ldap_msgfree( ldmp ); } } entry = NULL; if ( tmpl == NULL ) { fetchattrs = NULL; } else { fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER ); } #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", fetchattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", fetchattrs, 0, &timeout, &ldmp ); if ( freedn ) { NSLDAPI_FREE( dn ); } if ( fetchattrs != NULL ) { ldap_value_free( fetchattrs ); } if ( err != LDAP_SUCCESS || ( entry = ldap_first_entry( ld, ldmp )) == NULL ) { NSLDAPI_FREE( buf ); return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix ); NSLDAPI_FREE( buf ); ldap_msgfree( ldmp ); return( err ); }
int ldapLogin(char *thisUid, char *thisPwd, struct threadInfo * ti) { extern struct threadInfo *pMainThreadInfo; int (*dbConnect)(struct threadStorageInfo *); void (*dbDisconnect)(struct threadStorageInfo *); int (*dbCookie)(char *, int, struct threadStorageInfo *); int (*dbInsert)(char *, int, struct threadStorageInfo *); dbConnect = pMainThreadInfo->dbInfo.connect; dbDisconnect = pMainThreadInfo->dbInfo.disconnect; dbCookie = pMainThreadInfo->dbInfo.cookie; dbInsert = pMainThreadInfo->dbInfo.insert; if(thisUid == NULL) { return(-1); } if((ti->directoryInfo.ldapUri = configFetch("ldap_uri", &ti->directoryInfo.i)) == NULL) { ti->directoryInfo.ldapUri = LDAP_MYURI; } if((ti->directoryInfo.ldapUsername = configFetch("ldap_username", &ti->directoryInfo.i)) == NULL) { ti->directoryInfo.ldapUsername = LDAP_MYUSERNAME; } if((ti->directoryInfo.ldapPassword = configFetch("ldap_password", &ti->directoryInfo.i)) == NULL) { ti->directoryInfo.ldapPassword = LDAP_MYPASSWORD; } if((ti->directoryInfo.ldapAttr = configFetch("ldap_searchattr", &ti->directoryInfo.i)) == NULL) { ti->directoryInfo.ldapAttr = LDAP_MYATTR; } if((ti->directoryInfo.ldapBase = configFetch("ldap_searchbase", &ti->directoryInfo.i)) == NULL) { ti->directoryInfo.ldapBase = LDAP_MYBASE; } if((ti->directoryInfo.ldapFilter = configFetch("ldap_searchfilter", &ti->directoryInfo.i)) == NULL) { ti->directoryInfo.ldapFilter = LDAP_MYFILTER; } if(ldap_initialize(&ti->directoryInfo.l, ti->directoryInfo.ldapUri) != LDAP_SUCCESS) { ldapMessage(ti, ERROR_SLIGHT, "Error occurred while trying to initialize LDAP connection", NULL); return(-1); } ti->directoryInfo.v = LDAP_MYVERSION; if(ldap_set_option(ti->directoryInfo.l, LDAP_OPT_PROTOCOL_VERSION, (int *) &ti->directoryInfo.v) != LDAP_OPT_SUCCESS) { ldapMessage(ti, ERROR_SLIGHT, "Error occurred while trying to initialize LDAP connection", NULL); ldap_unbind(ti->directoryInfo.l); return(-1); } if(ti->directoryInfo.ldapUsername != NULL && ti->directoryInfo.ldapUsername[0] != 0) { if(ldap_bind_s(ti->directoryInfo.l, ti->directoryInfo.ldapUsername, ti->directoryInfo.ldapPassword, LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) { ldapMessage(ti, ERROR_SLIGHT, "Error occurred while trying to establish LDAP connection", ti->directoryInfo.ldapUsername); ldap_unbind(ti->directoryInfo.l); return(-1); } } ti->directoryInfo.timeVal.tv_sec = LDAP_MYTIMEOUT; ti->directoryInfo.timeVal.tv_usec = 0; if(ldap_search_st(ti->directoryInfo.l, ti->directoryInfo.ldapBase, LDAP_SCOPE_SUBTREE, ti->directoryInfo.ldapFilter, NULL, 0, &ti->directoryInfo.timeVal, &ti->directoryInfo.m) != LDAP_SUCCESS) { ldapMessage(ti, ERROR_SLIGHT, "Error occurred while trying to search from LDAP database", ti->directoryInfo.ldapFilter); ldap_unbind(ti->directoryInfo.l); return(-1); } if(ldap_count_entries(ti->directoryInfo.l, ti->directoryInfo.m) <= 0) { ldapMessage(ti, ERROR_SLIGHT, "Search from LDAP database returned no entries", ti->directoryInfo.ldapFilter); ldap_msgfree(ti->directoryInfo.m); ldap_unbind(ti->directoryInfo.l); return(-1); } if((ti->directoryInfo.e = ldap_first_entry(ti->directoryInfo.l, ti->directoryInfo.m)) == NULL) { ldapMessage(ti, ERROR_SLIGHT, "Search from LDAP database returned no entries", ti->directoryInfo.ldapFilter); ldap_msgfree(ti->directoryInfo.m); ldap_unbind(ti->directoryInfo.l); return(-1); } if((ti->directoryInfo.d = ldap_get_dn(ti->directoryInfo.l, ti->directoryInfo.e)) == NULL) { ldapMessage(ti, ERROR_SLIGHT, "Search from LDAP database returned no entries", ti->directoryInfo.ldapFilter); ldap_msgfree(ti->directoryInfo.m); ldap_unbind(ti->directoryInfo.l); return(-1); } snprintf(ti->directoryInfo.dnSpace, sizeof(ti->directoryInfo.dnSpace), "%s=%s,%s%c", ti->directoryInfo.ldapAttr, thisUid, ti->directoryInfo.d, 0); ldap_memfree(ti->directoryInfo.d); ldap_msgfree(ti->directoryInfo.m); if(ldap_bind_s(ti->directoryInfo.l, ti->directoryInfo.dnSpace, thisPwd, LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) { ldapMessage(ti, ERROR_SLIGHT, "Authentication against LDAP failed", ti->directoryInfo.dnSpace); ldap_unbind(ti->directoryInfo.l); return(-1); } ldap_unbind(ti->directoryInfo.l); ti->directoryInfo.l = NULL; if(dbConnect(&ti->storageInfo) == 0) { if(dbCookie(thisUid, strlen(thisUid), &ti->storageInfo) != 0) { ldapMessage(ti, ERROR_SLIGHT, "Authentication against LDAP failed", "Error occurred while trying to create session"); dbDisconnect(&ti->storageInfo); return(-1); } if(dbInsert(thisUid, strlen(thisUid), &ti->storageInfo) != 0) { ldapMessage(ti, ERROR_SLIGHT, "Authentication against LDAP failed", "Error occurred while trying to create session"); dbDisconnect(&ti->storageInfo); return(-1); } dbDisconnect(&ti->storageInfo); return(0); } else { ldapMessage(ti, ERROR_SLIGHT, "Authentication against LDAP failed", "Error occurred while trying to create session"); return(-1); } }
/* * fetches a binary blob from an ldap url */ static err_t fetch_ldap_url(char *url, chunk_t *blob) { LDAPURLDesc *lurl; err_t ugh = NULL; int rc; DBG(DBG_CONTROL, DBG_log("Trying LDAP URL '%s'", url) ) rc = ldap_url_parse(url, &lurl); if (rc == LDAP_SUCCESS) { LDAP *ldap = ldap_init(lurl->lud_host, lurl->lud_port); if (ldap != NULL) { int ldap_version = (LDAP_VER == 2)? LDAP_VERSION2 : LDAP_VERSION3; struct timeval timeout; timeout.tv_sec = FETCH_CMD_TIMEOUT; timeout.tv_usec = 0; ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); rc = ldap_simple_bind_s(ldap, NULL, NULL); if (rc == LDAP_SUCCESS) { LDAPMessage *result; timeout.tv_sec = FETCH_CMD_TIMEOUT; timeout.tv_usec = 0; rc = ldap_search_st(ldap, lurl->lud_dn , lurl->lud_scope , lurl->lud_filter , lurl->lud_attrs , 0, &timeout, &result); if (rc == LDAP_SUCCESS) { ugh = parse_ldap_result(ldap, result, blob); ldap_msgfree(result); } else { ugh = ldap_err2string(rc); } } else { ugh = ldap_err2string(rc); } ldap_unbind_s(ldap); } else { ugh = "ldap init"; } ldap_free_urldesc(lurl); } else { ugh = ldap_err2string(rc); } return ugh; }
int do_search( REQUEST *r, RESPONSE *resp ) { char *filtertype, **search_attrs, *search_filter; char *print_filter, *human_filter; int scope, count = 0, rc, i = 0, j, in_home; int option_param; struct timeval timeout; LDAPFiltInfo *fi; LDAPMessage *e, *res; static char *def_attrs[] = {"objectClass", "sn", "aliasedObjectName", "labeledURI", 0}; struct ldap_disptmpl *tmpl; char **oc; char *result_dn, *doc, *foc, *url_dn; char *base_dn, *base_ufn, *result_ufn, *alias_ufn, *sortstring, *cp, *bp; char **sn, href[10 * BUFSIZ], *temp, **val, *server = NULL; int counter = 0, base_len, isalias = 0; #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "do_search (%s, %s, (", r->r_dn, flag2string(r->r_flags), 0, 0); while (r->r_attrs && r->r_attrs[i]) { Web500gw_debug(WEB500GW_DEBUG_TRACE, "%s ", r->r_attrs[i], 0, 0, 0); i++; } Web500gw_debug(WEB500GW_DEBUG_TRACE, "), %s)\n", (r->r_filter && *r->r_filter) ? r->r_filter : "No filter", 0, 0, 0); #endif if (r->r_ld == (LDAP *)0 && (r->r_ld = web500gw_ldap_init(r, resp, NULL, NULL, 1)) == NULL) return NOTOK; base_dn = r->r_dn; if (strlen(base_dn) > 0) { base_ufn = friendly_dn(resp, base_dn); } else { base_ufn = NULL; } base_len = base_ufn ? strlen(base_ufn) : 0; if (r->r_filter == NULL) { return NOTOK; } print_filter = r->r_filter; #if defined(OWN_STR_TRANSLATION) search_filter = strdup(web500gw_isotot61(r->r_filter)); #else search_filter = r->r_filter; #endif if (*search_filter == '\0' || *(search_filter+1) != '=') { scope = LDAP_SCOPE_ONELEVEL; } else { if (*search_filter == 'S') { scope = LDAP_SCOPE_SUBTREE; } else { scope = LDAP_SCOPE_ONELEVEL; } search_filter += 2; print_filter += 2; } /* make a "human readable filter" - for now, no artistic things are done */ human_filter = print_filter; if ((cp = strchr(print_filter, '=')) != NULL) { if ((cp = strchr(cp+1, '=')) != NULL) { /* two '=' in it - must be a complex filter - isn't readable... */ human_filter = MSG_COMPLEX_FILTER; } } if (*search_filter) { /* not the default filter */ r->r_flags |= FLAG_FILTER; /* skip leading white spaces */ while (isspace(*search_filter)) ++search_filter; } if (r->r_attrs == NULL || *r->r_attrs == NULL) { /* No attributes requested - read default attrs for sorting */ search_attrs = def_attrs; } else { j = 0; while (def_attrs[j]) j++; search_attrs = (char **) calloc(r->r_attrnumb + j + 1, sizeof(char *)); i = j = 0; while (r->r_attrs && r->r_attrs[i]) { search_attrs[i] = r->r_attrs[i]; i++; } while (def_attrs[j]) search_attrs[i++] = def_attrs[j++]; search_attrs[i] = NULL; } if ((in_home = isinhome(base_dn))) /* ACCESS sizelimit if searching below HOME DN */ ldap_set_option(r->r_ld, LDAP_OPT_SIZELIMIT, &(r->r_access->a_sizelimit)); else ldap_set_option(r->r_ld, LDAP_OPT_SIZELIMIT, &sizelimit); /* A simple filter (not starting with '(') with a comma in it * -> UFN assumed */ /* if (ufnsearch && search_filter[0] != '(' && strchr(search_filter, ',') != NULL && strlen(search_filter) > 3) { if (strlen(base_dn) > 0) ldap_ufn_setprefix(r->r_ld, base_dn); timeout.tv_sec = timelimit; timeout.tv_usec = 0; ldap_ufn_timeout((void *) &timeout); option_param = LDAP_DEREF_FINDING; ldap_set_option(r->r_ld, LDAP_OPT_DEREF, (void *) &option_param); #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "ldap_ufn_search_s (%s)\n", search_filter, 0, 0, 0); #endif if ((rc = ldap_ufn_search_s(r->r_ld, search_filter, search_attrs, 0, &res)) != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED) { do_error(r, resp, rc, 0, get_ldap_result_code(r->r_ld), get_ldap_matched_str(r->r_ld)); return NOTOK; } count = ldap_count_entries(r->r_ld, res); #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "UFN ready: %d results!\n", count, 0, 0, 0); #endif // Reset DN, because this UFN search was probably not below DN base_dn = base_ufn = ""; in_home = 0; friendlyDesc = MSG_UFN; } else { */ /* let's do the search */ filtertype = (scope == LDAP_SCOPE_ONELEVEL ? "web500gw onelevel" : "web500gw subtree"); option_param = (scope == LDAP_SCOPE_ONELEVEL ? LDAP_DEREF_FINDING : LDAP_DEREF_ALWAYS); ldap_set_option(r->r_ld, LDAP_OPT_DEREF, (void *) &option_param); timeout.tv_sec = timelimit; timeout.tv_usec = 0; friendlyDesc = NULL; /* try all filters til we have success */ for (fi = ldap_getfirstfilter(r->r_access->a_filtd, filtertype, search_filter); fi != NULL; fi = ldap_getnextfilter(r->r_access->a_filtd)) { #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_FILTER, " search %s: %s -- %s\n", scope == LDAP_SCOPE_ONELEVEL ? "onelevel" : "subtree", fi->lfi_filter, fi->lfi_desc, 0); #endif if ((rc = ldap_search_st(r->r_ld, base_dn, scope, fi->lfi_filter, search_attrs, 0, &timeout, &res)) != LDAP_SUCCESS && rc != LDAP_SIZELIMIT_EXCEEDED && rc != LDAP_INSUFFICIENT_ACCESS && rc != LDAP_TIMELIMIT_EXCEEDED && rc != LDAP_TIMEOUT && rc != LDAP_PARTIAL_RESULTS) { do_error(r, resp, rc, 0, get_ldap_result_code(r->r_ld), get_ldap_matched_str(r->r_ld)); return NOTOK; } if ((count = ldap_count_entries(r->r_ld, res)) > 0) { /* found something */ friendlyDesc = friendly_label(resp, fi->lfi_desc); #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_FILTER, " searched ... and found %d results!\n", count, 0, 0, 0); #endif break; } #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_FILTER, " searched ... and found no results!\n", 0, 0, 0, 0); #endif } option_param = LDAP_DEREF_ALWAYS; ldap_set_option(r->r_ld, LDAP_OPT_DEREF, (void *) &option_param); /* }*/ if (count < 1) { /* nothing found :-( */ if (r->r_flags & FLAG_SEARCHACT) { /* in a search action we silently ignore this */ return OK; } resp->resp_status = NOT_FOUND; if (resp->resp_httpheader == 0) { if (r->r_httpversion == 1) { /* Expires now */ resp->resp_expires = 0; http_header(r, resp); } if (r->r_method == HEAD) { return OK; } } if (resp->resp_htmlheader == 0) { msg_fprintf(fp, in_home && *MSG_HTML_START_NO_SEARCH_RESULTS_HOME ? MSG_HTML_START_NO_SEARCH_RESULTS_HOME : MSG_HTML_START_NO_SEARCH_RESULTS, "ss", print_filter, base_ufn ? base_ufn : MSG_ROOT); resp->resp_htmlheader = 1; if (!(r->r_flags & FLAG_ENTRYONLY)) { if (in_home && MSG_HOMEBANNER) { msg_fprintf(fp, MSG_HOMEBANNER, "sss", r->r_query, other_lang_select, other_lang_string); } else { msg_fprintf(fp, MSG_BANNER, "sss", r->r_query, other_lang_select, other_lang_string); } } if (rc == LDAP_INSUFFICIENT_ACCESS) { fputs(MSG_NO_LIST_ACCESS, fp); } else if (rc == LDAP_TIMELIMIT_EXCEEDED || rc == LDAP_TIMEOUT) { fputs(MSG_TIMELIMIT, fp); } else { if (print_filter && *print_filter) { msg_fprintf(fp, MSG_NO_SEARCH_RESULTS, "ssss", (scope == LDAP_SCOPE_ONELEVEL ? MSG_ONELEVEL : MSG_SUBTREE), print_filter, human_filter, base_ufn ? base_ufn : MSG_ROOT); } else { fputs(MSG_NOTHING_FOUND_READORSEARCH, fp); } } if (!(r->r_flags & FLAG_ENTRYONLY)) { make_upsearch(r->r_ld, r, resp, 1); if (in_home && MSG_HOMETRAILER) { fputs(MSG_HOMETRAILER, fp); } else { fputs(MSG_TRAILER, fp); } } fputs(MSG_HTML_END, fp); fputs("\n", fp); } else { /* resp->resp_htmlheader != 0 -> within a document (searchaction) */ if (rc == LDAP_INSUFFICIENT_ACCESS) { fputs(MSG_NO_LIST_ACCESS, fp); } else if (rc == LDAP_TIMELIMIT_EXCEEDED || rc == LDAP_TIMEOUT) { fputs(MSG_TIMELIMIT, fp); } else { fputs(MSG_NOTHING_FOUND_READORSEARCH, fp); fputs(MSG_HTML_END, fp); fputs("\n", fp); } } return OK; } if (showonematch == 1 && count == 1 && r->r_attrnumb == 0 && !(r->r_flags & FLAG_SEARCHACT)) { /* header != 0 ? */ /* only one result and not searching for special attrs (searchaction) */ e = ldap_first_entry(r->r_ld, res); if (e != NULL) { char **oc, **aliasdn; oc = ldap_get_values(r->r_ld, e, objectclass_attr); aliasdn = ldap_get_values(r->r_ld, e, "aliasedObjectName"); if (aliasdn && *aliasdn) result_dn = *aliasdn; else result_dn = ldap_get_dn(r->r_ld, e); if (result_dn) { result_ufn = friendly_dn(resp, result_dn); if (gwswitch) { server = gw_switch(r->r_ld, resp, e); } r->r_flags &= ~FLAG_FILTER; /* it's not a search anymore */ url_dn = dn2url(r, result_dn, server ? r->r_flags & ~FLAG_LANGUAGE : r->r_flags, 0, NULL, server); /* Redirect */ #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "do_search: found one entry -> REDIRECT: %s\n", url_dn, 0, 0, 0); #endif resp->resp_status = REDIRECT; if (resp->resp_httpheader == 0 && r->r_httpversion == 1) { resp->resp_location = malloc(strlen(url_dn) + 11); strcpy(resp->resp_location, url_dn); http_header(r, resp); /* free(resp->resp_location); */ } if (r->r_method == HEAD) { return OK; } msg_fprintf(fp, in_home && *MSG_HTML_START_SEARCH_RESULTS_HOME ? MSG_HTML_START_SEARCH_RESULTS_HOME : MSG_HTML_START_SEARCH_RESULTS, "ss", print_filter, result_ufn); msg_fprintf(fp, MSG_REDIRECT, "ss", url_dn, result_ufn); fputs(MSG_HTML_END, fp); fputs("\n", fp); return OK; } } } /* Found something */ /* Prepare HTTP + HTML header */ if (resp->resp_httpheader == 0 && r->r_httpversion == 1) { http_header(r, resp); if (r->r_method == HEAD) return OK; } if (resp->resp_htmlheader == 0) { msg_fprintf(fp, in_home && *MSG_HTML_START_SEARCH_RESULTS_HOME ? MSG_HTML_START_SEARCH_RESULTS_HOME : MSG_HTML_START_SEARCH_RESULTS, "ss", print_filter, base_ufn ? base_ufn : MSG_ROOT); if (!(r->r_flags & FLAG_ENTRYONLY)) { if (in_home && MSG_HOMEBANNER) { msg_fprintf(fp, MSG_HOMEBANNER, "sss", r->r_query, other_lang_select, other_lang_string); } else { msg_fprintf(fp, MSG_BANNER, "sss", r->r_query, other_lang_select, other_lang_string); } } resp->resp_htmlheader = 1; } if ((!(r->r_flags & FLAG_ENTRYONLY)) && (r->r_browser->b_upsearch & UPSEARCH_ON_TOP)) { make_upsearch(r->r_ld, r, resp, 1); } if (r->r_flags & FLAG_FILTER && (!(r->r_flags & FLAG_ENTRYONLY))) { /* Not the default filter and not entryonly */ msg_fprintf(fp, MSG_SEARCH_RESULTS, "ssssisss", (scope == LDAP_SCOPE_ONELEVEL ? MSG_ONELEVEL : MSG_SUBTREE), print_filter, human_filter, base_ufn && *base_ufn ? base_ufn : MSG_ROOT, count, count == 1 ? MSG_ENTRY : MSG_ENTRIES, friendlyDesc, rc == LDAP_PARTIAL_RESULTS ? resp->resp_language->l_conf->c_errmsg[LDAP_PARTIAL_RESULTS] : ""); } if (ldap_result2error(r->r_ld, res, 0) == LDAP_SIZELIMIT_EXCEEDED) { fprintf(fp, r->r_flags & FLAG_FILTER && r->r_access->a_sizelimit == 0 ? MSG_SIZELIMIT_1 : MSG_SIZELIMIT_0, count); } /* Now prepare the result for sorting */ #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "do_search: preparing for sort\n", 0, 0, 0, 0); #endif /* for all the results ... */ for (e = ldap_first_entry(r->r_ld, res); e != NULL && counter < MAX_LISTSIZE; e = ldap_next_entry(r->r_ld, e)) { result_dn = ldap_get_dn(r->r_ld, e); result_ufn = friendly_dn(resp, result_dn); if ((val = ldap_get_values(r->r_ld, e, "aliasedObjectName"))) { /* entry is alias */ free(result_dn); result_dn = strdup(*val); alias_ufn = friendly_dn(resp, result_dn); ldap_value_free(val); isalias = 1; } else { isalias = 0; } if (isalias && r->r_flags & FLAG_DEREFALIAS) { /* if alias, look for objectClass of real entry */ oc = deref(r->r_ld, result_dn); } else { oc = ldap_get_values(r->r_ld, e, objectclass_attr); } /* find template to see the plural name of the objectclass */ tmpl = ldap_oc2template(oc, r->r_access->a_tmpllist); doc = pick_oc(oc); if (tmpl && tmpl->dt_pluralname) { foc = strdup(friendly_label(resp, tmpl->dt_pluralname)); } else { foc = strdup(friendly_label(resp, doc)); if (strcmp(foc, doc) == 0) { /* "no friendly objectclass" found -> last in the list (a hack) */ foc = (char *)malloc(strlen(doc)+9); sprintf(foc, " %s", doc); } } if (strncasecmp(result_ufn, "{ASN}", 5) == 0) { /* ASNs are not something we want to display! */ free(result_dn); ldap_value_free(oc); continue; } if (base_len > 0) { /* strip search base from result */ result_ufn = strip_ufn_dn(result_ufn, base_ufn); } #ifdef nodef cp = result_ufn + strlen(result_ufn) - 1; bp = base_ufn + base_len - 1; while (bp >= base_ufn && *cp-- && *bp-- && *cp == *bp); if ((bp+1) == base_ufn && cp != NULL) { /* Complete match on base */ /* strip trailing whitespaces and ',' */ while (*cp && isspace(*cp)) cp--; if (cp != NULL && *cp == ',') *cp = '\0'; } } #endif sortstring = strdup(result_ufn); if (strcasecmp(doc, "country") == 0) { /* a country */ sn = NULL; } else { /* not a country */ /* DNs may have components in '"', ignored when sorting */ if (*sortstring == '"') { sortstring++; cp = strchr(sortstring+1, '"'); } else { cp = sortstring; } if ((cp = strchr(cp,','))) *cp = '\0'; if (isalias) { /* aliases don't have surnames */ if (isoc (oc, "person")) { } } sn = ldap_get_values(r->r_ld, e, "sn"); /* Delete spaces ??? if (sn) { cp = *sn; while ((cp = strchr(cp,' '))) { cp ++; spaces ++; } } while (spaces > 0) { if ((cp = strrchr(sortstring,' '))) { *cp = '\0'; spaces --; } else break; } */ if ((cp = strchr(sortstring,'+'))) { cp --; *cp = '\0'; } } if (gwswitch) { server = gw_switch(r->r_ld, resp, e); } /* build the link (HREF) */ if (isalias) { if (isnonleaf(r->r_ld, oc, result_dn)) { if (r->r_flags & FLAG_NOHREFDN) msg_snprintf(href, sizeof(href), MSG_DN_ALIAS_TO_NONLEAF, "sss", result_ufn, alias_ufn, html_encode(result_dn)); else msg_snprintf(href, sizeof(href), MSG_HREF_ALIAS_TO_NONLEAF, "ssssss", dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0, NULL, server), result_ufn, alias_ufn, html_encode(result_dn), string_encode(result_ufn),string_encode(result_dn)); } else { if (r->r_flags & FLAG_NOHREFDN) msg_snprintf(href, sizeof(href), MSG_DN_ALIAS_TO_LEAF, "sss", result_ufn, alias_ufn, html_encode(result_dn)); else msg_snprintf(href, sizeof(href), MSG_HREF_ALIAS_TO_LEAF, "ssssss", dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0, NULL, server), result_ufn, alias_ufn, html_encode(result_dn), string_encode(result_ufn),string_encode(result_dn)); } } else if (isnonleaf(r->r_ld, oc, result_dn)) { if (r->r_flags & FLAG_NOHREFDN) msg_snprintf(href, sizeof(href), MSG_DN_NON_LEAF, "ss", result_ufn, html_encode(result_dn)); else msg_snprintf(href, sizeof(href), MSG_HREF_NON_LEAF, "sssss", dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0, NULL, server), result_ufn, html_encode(result_dn), string_encode(result_ufn), string_encode(result_dn)); } else { if (r->r_flags & FLAG_NOHREFDN) msg_snprintf(href, sizeof(href), MSG_DN_LEAF, "ss", result_ufn, html_encode(result_dn)); else msg_snprintf(href, sizeof(href), MSG_HREF_LEAF, "sssss", dn2url(r, result_dn, server ? 0 : FLAG_LANGUAGE, 0, NULL, server), result_ufn, html_encode(result_dn), string_encode(result_ufn), string_encode(result_dn)); } /* build the sortstring: foc[sn]sortstring */ if (sn) { temp = (char *) malloc(strlen(foc)+strlen(*sn)+strlen(sortstring)+1); } else { temp = (char *) malloc(strlen(foc)+strlen(sortstring)+1); } strcpy(temp, foc); if (sn) { strcat(temp, *sn); } strcat(temp, sortstring); if (!dnlist[counter]) { dnlist[counter] = (struct dncompare *) malloc(sizeof(struct dncompare)); } dnlist[counter]->sortstring = temp; dnlist[counter]->href = strdup(href); dnlist[counter]->friendly_oc = foc; dnlist[counter]->oc = doc; dnlist[counter]->tmpl = tmpl; dnlist[counter]->entry = e; dnlist[counter]->dn = strdup(result_dn); counter++; ldap_value_free(oc); free(result_dn); if (sn) ldap_value_free(sn); }
int do_addform( REQUEST *r, RESPONSE *resp ) { #ifndef MODIFY do_error(r, resp, LDAP_OTHER, NOT_IMPLEMENTED, MSG_NOT_SUPPORTED, NULL); return NOTOK; #else /* defined MODIFY */ int rc, in_home; char *bind_as, *pw, *args, *tmpl, *basedn, *rdn, *ufn, *cp; LDAPMessage *res; struct timeval timeout; struct ldap_disptmpl *templ; /* * query = default Base-DN, * args = dn=BindDN&userPassword=PASSWD&tmpl=template&basedn=DN */ args = r->r_method == POST ? r->r_postdata : r->r_filter; #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "do_addform (%s, %s)\n", r->r_dn, args ? args : "", 0, 0); #endif if (args == NULL) { do_error(r, resp, LDAP_OTHER, BAD_REQUEST, NULL, NULL); return NOTOK; } bind_as = pw = tmpl = basedn = NULL; cp = args; while (cp && *cp) { if (strncmp(cp, "dn=", 3) == 0) { bind_as = cp + 3; } else if (strncmp(cp, "userPassword="******"tmpl=", 5) == 0) { tmpl = cp + 5; } else if (strncmp(cp, "basedn=", 7) == 0) { basedn = cp + 7; } /* else ignore */ cp = strchr(cp, '&'); if (cp && *cp) *cp++ = '\0'; } if (!bind_as) { do_error(r, resp, LDAP_OTHER, BAD_REQUEST, MSG_NO_BIND_DN, NULL); return NOTOK; } hex_qdecode(bind_as); if (! pw) { do_error(r, resp, LDAP_OTHER, BAD_REQUEST, MSG_MISSING_PASSWORD, NULL); return NOTOK; } hex_qdecode(pw); if (basedn && *basedn) { hex_qdecode(basedn); } else { basedn = r->r_dn; } hex_qdecode(tmpl); if (tmpl && *tmpl) /* overrides the template in URL */ r->r_template = tmpl; if (! (r->r_template && *r->r_template)) { /* need a objectclass template */ do_error(r, resp, LDAP_OTHER, BAD_REQUEST, MSG_TEMPLATE_MISSING, NULL); return NOTOK; } /* No bind necessary at this stage but checking it anyway to block * non-admins */ if ((!bind_as) || strlen(bind_as) == 0) { /* No DN to bind as */ do_error (r, resp, LDAP_INAPPROPRIATE_AUTH, BAD_REQUEST, MSG_UNKNOWN_ARGUMENT, NULL); return NOTOK; } r->r_binddn = bind_as; if ((!pw) || strlen(pw) == 0) { /* we need a password for simple auth */ do_error (r, resp, LDAP_INAPPROPRIATE_AUTH, 0, MSG_NULL_PASSWORD, NULL); return NOTOK; } #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "BINDING as %s ... ", bind_as, 0, 0, 0); #endif if ((r->r_ld = web500gw_ldap_init(r, resp, bind_as, pw, 1)) == (LDAP *)0) return NOTOK; #ifdef WEB500GW_DEBUG Web500gw_debug(WEB500GW_DEBUG_TRACE, "BOUND\n", 0, 0, 0, 0); #endif /* let's see if basedn exists ... */ timeout.tv_sec = timelimit; timeout.tv_usec = 0; if ((rc = ldap_search_st(r->r_ld, basedn, LDAP_SCOPE_BASE, default_filter, NULL, 0, &timeout, &res)) != LDAP_SUCCESS) { /* better error description here ??? */ do_error(r, resp, rc, 0, get_ldap_error_str(r->r_ld), get_ldap_matched_str(r->r_ld)); return NOTOK; } /* check if nonleaf here ??? */ ufn = friendly_dn(resp, basedn); rdn = friendly_rdn(resp, basedn, 1); in_home = isinhome(basedn); /* find the requested template */ templ = ldap_name2template(r->r_template, r->r_access->a_tmpllist); if (templ == NULL) { /* template not found */ do_error(r, resp, LDAP_OTHER, BAD_REQUEST, MSG_TEMPLATE_MISSING, NULL); return NOTOK; } /* .. and see if it's allowed to add such an entry */ if (!LDAP_IS_DISPTMPL_OPTION_SET(templ, LDAP_DTMPL_OPT_ADDABLE)) { do_error(r, resp, LDAP_OTHER, BAD_REQUEST, MSG_ADD_OC_NOT_ADDABLE, NULL); return NOTOK; } if (r->r_httpversion == 1 && resp->resp_httpheader == 0) { /* Expires now - don't allow to cache */ /* resp->resp_expires = 0; */ http_header(r, resp); } if (resp->resp_htmlheader == 0) { msg_fprintf(fp, in_home && *MSG_HTML_START_MISC_HOME ? MSG_HTML_START_MISC_HOME : MSG_HTML_START_MISC, "sss", MSG_ADD, rdn, ufn); resp->resp_htmlheader = 1; } msg_fprintf(fp, MSG_EXPLAIN_ADD, "ss", rdn, ufn); fprintf(fp, "<FORM METHOD=POST ACTION=\"%s\">\n", dn2url(r, basedn, FLAG_LANGUAGE|FLAG_TMPL, ACTION_ADD, NULL, NULL)); if (r->r_browser->b_opts & B_HIDDEN) { fprintf(fp, "<INPUT TYPE=\"hidden\" NAME=\"adder_dn\" VALUE=\"%s\">\n\ <INPUT TYPE=\"hidden\" NAME=\"adder_pw\" VALUE=\"%s\">\n", html_encode(bind_as, strlen(bind_as)), html_encode(pw, strlen(pw))); } else {
ldap_key_t * ldap_getuserkey(ldap_opt_t *l, const char * user) { ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t)); LDAPMessage *res, *e; char * filter; int i; char *attrs[] = { l->pub_key_attr, NULL }; if ((!k) || (!l)) return NULL; /* Am i still connected ? RETRY n times */ /* XXX TODO: setup some conf value for retrying */ if (!(l->flags & FLAG_CONNECTED)) for (i = 0 ; i < 2 ; i++) if (ldap_connect(l) == 0) break; /* quick check for attempts to be evil */ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) return NULL; /* build filter for LDAP request */ REQUEST_USER(filter, user, l->filter); if ( ldap_search_st( l->ld, l->u_basedn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, &l->s_timeout, &res ) != LDAP_SUCCESS) { ldap_perror(l->ld, "ldap_search_st()"); free(filter); free(k); /* XXX error on search, timeout etc.. close ask for reconnect */ ldap_close(l); return NULL; } /* free */ free(filter); /* check if any results */ i = ldap_count_entries(l->ld,res); if (i <= 0) { ldap_msgfree(res); free(k); return NULL; } if (i > 1) debug("[LDAP] duplicate entries, using the FIRST entry returned"); e = ldap_first_entry(l->ld, res); k->keys = ldap_get_values_len(l->ld, e, l->pub_key_attr); k->num = ldap_count_values_len(k->keys); ldap_msgfree(res); return k; }