ECB mode added to the DES plugin
[strongswan.git] / src / libstrongswan / plugins / ldap / ldap_fetcher.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #ifndef LDAP_DEPRECATED
20 #define LDAP_DEPRECATED 1
21 #endif /* LDAP_DEPRECATED */
22 #include <ldap.h>
23
24 #include <errno.h>
25
26 #include <library.h>
27 #include <debug.h>
28
29 #include "ldap_fetcher.h"
30
31 #define DEFAULT_TIMEOUT 10
32
33 typedef struct private_ldap_fetcher_t private_ldap_fetcher_t;
34
35 /**
36 * Private Data of a ldap_fetcher_t object.
37 */
38 struct private_ldap_fetcher_t {
39 /**
40 * Public data
41 */
42 ldap_fetcher_t public;
43
44 /**
45 * timeout to use for fetches
46 */
47 u_int timeout;
48 };
49
50 /**
51 * Parses the result returned by an ldap query
52 */
53 static bool parse(LDAP *ldap, LDAPMessage *result, chunk_t *response)
54 {
55 LDAPMessage *entry = ldap_first_entry(ldap, result);
56 bool success = FALSE;
57
58 if (entry)
59 {
60 BerElement *ber = NULL;
61 char *attr;
62
63 attr = ldap_first_attribute(ldap, entry, &ber);
64 if (attr)
65 {
66 struct berval **values = ldap_get_values_len(ldap, entry, attr);
67
68 if (values)
69 {
70 if (values[0])
71 {
72 *response = chunk_alloc(values[0]->bv_len);
73 memcpy(response->ptr, values[0]->bv_val, response->len);
74 success = TRUE;
75 }
76 else
77 {
78 DBG1("LDAP response contains no values");
79 }
80 ldap_value_free_len(values);
81 }
82 else
83 {
84 DBG1("getting LDAP values failed: %s",
85 ldap_err2string(ldap_result2error(ldap, entry, 0)));
86 }
87 ldap_memfree(attr);
88 }
89 else
90 {
91 DBG1("finding LDAP attributes failed: %s",
92 ldap_err2string(ldap_result2error(ldap, entry, 0)));
93 }
94 ber_free(ber, 0);
95 }
96 else
97 {
98 DBG1("finding first LDAP entry failed: %s",
99 ldap_err2string(ldap_result2error(ldap, entry, 0)));
100 }
101 return success;
102 }
103
104
105 static status_t fetch(private_ldap_fetcher_t *this, char *url,
106 chunk_t *result, va_list args)
107 {
108 LDAP *ldap;
109 LDAPURLDesc *lurl;
110 LDAPMessage *msg;
111 int res;
112 int ldap_version = LDAP_VERSION3;
113 struct timeval timeout;
114 status_t status = FAILED;
115
116 if (!strneq(url, "ldap", 4))
117 {
118 return NOT_SUPPORTED;
119 }
120 if (ldap_url_parse(url, &lurl) != LDAP_SUCCESS)
121 {
122 return NOT_SUPPORTED;
123 }
124 ldap = ldap_init(lurl->lud_host, lurl->lud_port);
125 if (ldap == NULL)
126 {
127 DBG1("LDAP initialization failed: %s", strerror(errno));
128 ldap_free_urldesc(lurl);
129 return FAILED;
130 }
131
132 timeout.tv_sec = this->timeout;
133 timeout.tv_usec = 0;
134
135 ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
136 ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout);
137
138 DBG2("sending LDAP request to '%s'...", url);
139
140 res = ldap_simple_bind_s(ldap, NULL, NULL);
141 if (res == LDAP_SUCCESS)
142 {
143 res = ldap_search_st(ldap, lurl->lud_dn, lurl->lud_scope,
144 lurl->lud_filter, lurl->lud_attrs,
145 0, &timeout, &msg);
146
147 if (res == LDAP_SUCCESS)
148 {
149 if (parse(ldap, msg, result))
150 {
151 status = SUCCESS;
152 }
153 ldap_msgfree(msg);
154 }
155 else
156 {
157 DBG1("LDAP search failed: %s", ldap_err2string(res));
158 }
159 }
160 else
161 {
162 DBG1("LDAP bind to '%s' failed: %s", url, ldap_err2string(res));
163 }
164 ldap_unbind_s(ldap);
165 ldap_free_urldesc(lurl);
166 return status;
167 }
168
169
170 /**
171 * Implementation of fetcher_t.set_option.
172 */
173 static bool set_option(private_ldap_fetcher_t *this, fetcher_option_t option, ...)
174 {
175 va_list args;
176
177 va_start(args, option);
178 switch (option)
179 {
180 case FETCH_TIMEOUT:
181 {
182 this->timeout = va_arg(args, u_int);
183 return TRUE;
184 }
185 default:
186 return FALSE;
187 }
188 }
189
190 /**
191 * Implements ldap_fetcher_t.destroy
192 */
193 static void destroy(private_ldap_fetcher_t *this)
194 {
195 free(this);
196 }
197
198 /*
199 * Described in header.
200 */
201 ldap_fetcher_t *ldap_fetcher_create()
202 {
203 private_ldap_fetcher_t *this = malloc_thing(private_ldap_fetcher_t);
204
205 this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch;
206 this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option;
207 this->public.interface.destroy = (void (*)(fetcher_t*))destroy;
208
209 this->timeout = DEFAULT_TIMEOUT;
210
211 return &this->public;
212 }
213