diff options
Diffstat (limited to 'src/libstrongswan/utils/fetcher.c')
-rw-r--r-- | src/libstrongswan/utils/fetcher.c | 206 |
1 files changed, 190 insertions, 16 deletions
diff --git a/src/libstrongswan/utils/fetcher.c b/src/libstrongswan/utils/fetcher.c index cf83adbdc..d728f0d00 100644 --- a/src/libstrongswan/utils/fetcher.c +++ b/src/libstrongswan/utils/fetcher.c @@ -24,6 +24,10 @@ #include <curl/curl.h> #endif /* LIBCURL */ +#ifdef LIBLDAP +#include <ldap.h> +#endif /* LIBLDAP */ + #include <library.h> #include <debug.h> @@ -52,13 +56,20 @@ struct private_fetcher_t { CURL* curl; #endif /* LIBCURL */ +#ifdef LIBLDAP + /** + * we use libldap from http://www.openssl.org/ as a fetcher + */ + LDAP *ldap; + LDAPURLDesc *lurl; +#endif /* LIBLDAP */ }; /** * writes data into a dynamically resizeable chunk_t * needed for libcurl responses */ -size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data) +static size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb; chunk_t *mem = (chunk_t*)data; @@ -72,9 +83,9 @@ size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data) } /** - * Implements fetcher_t.get + * Implements fetcher_t.get for http[s] and file URIs */ -static chunk_t get(private_fetcher_t *this) +static chunk_t curl_get(private_fetcher_t *this) { chunk_t response = chunk_empty; @@ -93,17 +104,17 @@ static chunk_t get(private_fetcher_t *this) curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT); curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE); - DBG1("sending http get request to '%s'...", this->uri); + DBG1("sending curl request to '%s'...", this->uri); res = curl_easy_perform(this->curl); if (res == CURLE_OK) { - DBG1("received valid http response"); + DBG1("received valid curl response"); response = chunk_clone(curl_response); } else { - DBG1("http get request to '%s' using libcurl failed: %s", + DBG1("curl request to '%s' failed: %s", this->uri, curl_error_buffer); } curl_free(curl_response.ptr); @@ -115,9 +126,9 @@ static chunk_t get(private_fetcher_t *this) } /** - * Implements fetcher_t.post + * Implements fetcher_t.post. */ -static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t request) +static chunk_t http_post(private_fetcher_t *this, const char *request_type, chunk_t request) { chunk_t response = chunk_empty; @@ -168,14 +179,146 @@ static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t r return response; } +#ifdef LIBLDAP +/** + * parses the result returned by an ldap query + */ +static chunk_t ldap_parse(LDAP *ldap, LDAPMessage *result) +{ + chunk_t response = chunk_empty; + + LDAPMessage *entry = ldap_first_entry(ldap, result); + if (entry != NULL) + { + BerElement *ber = NULL; + char *attr; + + attr = ldap_first_attribute(ldap, entry, &ber); + + if (attr != NULL) + { + struct berval **values = ldap_get_values_len(ldap, entry, attr); + + if (values != NULL) + { + if (values[0] != NULL) + { + response.len = values[0]->bv_len; + response.ptr = malloc(response.len); + memcpy(response.ptr, values[0]->bv_val, response.len); + if (values[1] != NULL) + { + DBG1("ldap: more than one value was fetched from LDAP URL"); + } + } + else + { + DBG1("ldap: no values in attribute"); + } + ldap_value_free_len(values); + } + else + { + DBG1("ldap: %s", ldap_err2string(ldap_result2error(ldap, entry, 0))); + } + ldap_memfree(attr); + } + else + { + DBG1("ldap: %s", ldap_err2string(ldap_result2error(ldap, entry, 0))); + } + ber_free(ber, 0); + } + else + { + DBG1("ldap: %s", ldap_err2string(ldap_result2error(ldap, result, 0))); + } + return response; +} +#endif /* LIBLDAP */ + +/** + * fetches a binary blob from an ldap url + */ +static chunk_t ldap_get(private_fetcher_t *this) +{ + chunk_t response = chunk_empty; + +#ifdef LIBLDAP + if (this->ldap) + { + int rc; + int ldap_version = LDAP_VERSION3; + + struct timeval timeout; + + timeout.tv_sec = FETCHER_TIMEOUT; + timeout.tv_usec = 0; + + ldap_set_option(this->ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); + ldap_set_option(this->ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); + + DBG1("sending ldap request to '%s'...", this->uri); + + rc = ldap_simple_bind_s(this->ldap, NULL, NULL); + if (rc == LDAP_SUCCESS) + { + LDAPMessage *result; + + timeout.tv_sec = FETCHER_TIMEOUT; + timeout.tv_usec = 0; + + rc = ldap_search_st(this->ldap, this->lurl->lud_dn, + this->lurl->lud_scope, + this->lurl->lud_filter, + this->lurl->lud_attrs, + 0, &timeout, &result); + + if (rc == LDAP_SUCCESS) + { + response = ldap_parse(this->ldap, result); + if (response.ptr) + { + DBG1("received valid ldap response"); + } + ldap_msgfree(result); + } + else + { + DBG1("ldap: %s", ldap_err2string(rc)); + } + } + else + { + DBG1("ldap: %s", ldap_err2string(rc)); + } + ldap_unbind_s(this->ldap); + } +#else /* !LIBLDAP */ + DBG1("warning: libldap fetching not compiled in"); +#endif /* !LIBLDAP */ + return response; +} + /** * Implements fetcher_t.destroy */ static void destroy(private_fetcher_t *this) { #ifdef LIBCURL - curl_easy_cleanup(this->curl); + if (this->curl) + { + curl_easy_cleanup(this->curl); + } #endif /* LIBCURL */ + +#ifdef LIBLDAP + if (this->lurl) + { + ldap_free_urldesc(this->lurl); + } +#endif /* LIBLDAP */ + free(this); } @@ -188,17 +331,48 @@ fetcher_t *fetcher_create(const char *uri) /* initialize */ this->uri = uri; + #ifdef LIBCURL - this->curl = curl_easy_init(); - if (this->curl == NULL) + this->curl = NULL; +#endif /* LIBCURL */ + +#ifdef LIBLDAP + this->lurl = NULL; + this->ldap = NULL; +#endif /* LIBLDAP */ + + if (strlen(uri) >= 4 && strncasecmp(uri, "ldap", 4) == 0) { - DBG1("curl_easy_init_failed()"); +#ifdef LIBLDAP + int rc = ldap_url_parse(uri, &this->lurl); + + if (rc == LDAP_SUCCESS) + { + this->ldap = ldap_init(this->lurl->lud_host, + this->lurl->lud_port); + } + else + { + DBG1("ldap: %s", ldap_err2string(rc)); + this->ldap = NULL; + } +#endif /* LIBLDAP */ + this->public.get = (chunk_t (*) (fetcher_t*))ldap_get; } + else + { +#ifdef LIBCURL + this->curl = curl_easy_init(); + if (this->curl == NULL) + { + DBG1("curl_easy_init_failed()"); + } #endif /* LIBCURL */ + this->public.get = (chunk_t (*) (fetcher_t*))curl_get; + } /* public functions */ - this->public.get = (chunk_t (*) (fetcher_t*))get; - this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))post; + this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))http_post; this->public.destroy = (void (*) (fetcher_t*))destroy; return &this->public; @@ -209,7 +383,7 @@ fetcher_t *fetcher_create(const char *uri) */ void fetcher_initialize(void) { - #ifdef LIBCURL +#ifdef LIBCURL CURLcode res; /* initialize libcurl */ @@ -227,7 +401,7 @@ void fetcher_initialize(void) */ void fetcher_finalize(void) { - #ifdef LIBCURL +#ifdef LIBCURL /* finalize libcurl */ DBG1("finalizing libcurl"); curl_global_cleanup(); |