]>
Commit | Line | Data |
---|---|---|
d1e348cf A |
1 | /* $NetBSD: isakmp_xauth.c,v 1.11.6.1 2007/08/07 04:49:24 manu Exp $ */ |
2 | ||
3 | /* Id: isakmp_xauth.c,v 1.38 2006/08/22 18:17:17 manubsd Exp */ | |
52b7d2ce A |
4 | |
5 | /* | |
6 | * Copyright (C) 2004-2005 Emmanuel Dreyfus | |
7 | * All rights reserved. | |
8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. Neither the name of the project nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include "config.h" | |
35 | ||
36 | #include <sys/types.h> | |
37 | #include <sys/param.h> | |
38 | #include <sys/socket.h> | |
39 | #include <sys/queue.h> | |
40 | ||
41 | #include <netinet/in.h> | |
42 | ||
43 | #include <stdlib.h> | |
44 | #include <stdio.h> | |
45 | #include <string.h> | |
46 | #include <errno.h> | |
47 | #include <pwd.h> | |
d1e348cf | 48 | #include <grp.h> |
52b7d2ce A |
49 | #if TIME_WITH_SYS_TIME |
50 | # include <sys/time.h> | |
51 | # include <time.h> | |
52 | #else | |
53 | # if HAVE_SYS_TIME_H | |
54 | # include <sys/time.h> | |
55 | # else | |
56 | # include <time.h> | |
57 | # endif | |
58 | #endif | |
59 | #include <netdb.h> | |
60 | #ifdef HAVE_UNISTD_H | |
61 | #include <unistd.h> | |
62 | #endif | |
63 | #include <ctype.h> | |
d1e348cf A |
64 | #include <resolv.h> |
65 | ||
66 | #ifdef HAVE_SHADOW_H | |
67 | #include <shadow.h> | |
68 | #endif | |
52b7d2ce A |
69 | |
70 | #include "var.h" | |
71 | #include "misc.h" | |
72 | #include "vmbuf.h" | |
73 | #include "plog.h" | |
74 | #include "sockmisc.h" | |
75 | #include "schedule.h" | |
76 | #include "debug.h" | |
77 | ||
78 | #include "crypto_openssl.h" | |
79 | #include "isakmp_var.h" | |
80 | #include "isakmp.h" | |
81 | #include "admin.h" | |
82 | #include "privsep.h" | |
83 | #include "evt.h" | |
84 | #include "handler.h" | |
85 | #include "throttle.h" | |
86 | #include "remoteconf.h" | |
87 | #include "isakmp_inf.h" | |
88 | #include "isakmp_xauth.h" | |
89 | #include "isakmp_unity.h" | |
90 | #include "isakmp_cfg.h" | |
91 | #include "strnames.h" | |
92 | #include "ipsec_doi.h" | |
93 | #include "remoteconf.h" | |
94 | #include "localconf.h" | |
d1e348cf A |
95 | #include "vpn_control.h" |
96 | #include "vpn_control_var.h" | |
97 | #include "ipsecSessionTracer.h" | |
98 | #include "ipsecMessageTracer.h" | |
52b7d2ce A |
99 | |
100 | #ifdef HAVE_LIBRADIUS | |
101 | #include <radlib.h> | |
102 | ||
103 | struct rad_handle *radius_auth_state = NULL; | |
104 | struct rad_handle *radius_acct_state = NULL; | |
105 | #endif | |
106 | ||
107 | #ifdef HAVE_LIBPAM | |
52b7d2ce | 108 | #include <security/pam_appl.h> |
52b7d2ce A |
109 | |
110 | static char *PAM_usr = NULL; | |
111 | static char *PAM_pwd = NULL; | |
112 | static int PAM_conv(int, const struct pam_message **, | |
113 | struct pam_response **, void *); | |
114 | static struct pam_conv PAM_chat = { &PAM_conv, NULL }; | |
115 | #endif | |
116 | ||
d1e348cf A |
117 | #ifdef HAVE_LIBLDAP |
118 | #include "ldap.h" | |
119 | #include <arpa/inet.h> | |
120 | struct xauth_ldap_config xauth_ldap_config; | |
121 | #endif | |
52b7d2ce A |
122 | |
123 | void | |
124 | xauth_sendreq(iph1) | |
125 | struct ph1handle *iph1; | |
126 | { | |
127 | vchar_t *buffer; | |
128 | struct isakmp_pl_attr *attr; | |
129 | struct isakmp_data *typeattr; | |
130 | struct isakmp_data *usrattr; | |
131 | struct isakmp_data *pwdattr; | |
132 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
133 | size_t tlen; | |
134 | ||
135 | /* Status checks */ | |
136 | if (iph1->status != PHASE1ST_ESTABLISHED) { | |
137 | plog(LLV_ERROR, LOCATION, NULL, | |
138 | "Xauth request while phase 1 is not completed\n"); | |
139 | return; | |
140 | } | |
141 | ||
142 | if (xst->status != XAUTHST_NOTYET) { | |
143 | plog(LLV_ERROR, LOCATION, NULL, | |
144 | "Xauth request whith Xauth state %d\n", xst->status); | |
145 | return; | |
146 | } | |
147 | ||
148 | plog(LLV_INFO, LOCATION, NULL, "Sending Xauth request\n"); | |
149 | ||
150 | tlen = sizeof(*attr) + | |
151 | + sizeof(*typeattr) + | |
152 | + sizeof(*usrattr) + | |
153 | + sizeof(*pwdattr); | |
154 | ||
155 | if ((buffer = vmalloc(tlen)) == NULL) { | |
156 | plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n"); | |
157 | return; | |
158 | } | |
159 | ||
160 | attr = (struct isakmp_pl_attr *)buffer->v; | |
161 | memset(attr, 0, tlen); | |
162 | ||
163 | attr->h.len = htons(tlen); | |
164 | attr->type = ISAKMP_CFG_REQUEST; | |
165 | attr->id = htons(eay_random()); | |
166 | ||
167 | typeattr = (struct isakmp_data *)(attr + 1); | |
168 | typeattr->type = htons(XAUTH_TYPE | ISAKMP_GEN_TV); | |
169 | typeattr->lorv = htons(XAUTH_TYPE_GENERIC); | |
170 | ||
171 | usrattr = (struct isakmp_data *)(typeattr + 1); | |
172 | usrattr->type = htons(XAUTH_USER_NAME | ISAKMP_GEN_TLV); | |
173 | usrattr->lorv = htons(0); | |
174 | ||
175 | pwdattr = (struct isakmp_data *)(usrattr + 1); | |
176 | pwdattr->type = htons(XAUTH_USER_PASSWORD | ISAKMP_GEN_TLV); | |
177 | pwdattr->lorv = htons(0); | |
178 | ||
179 | isakmp_cfg_send(iph1, buffer, | |
d1e348cf | 180 | ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL); |
52b7d2ce A |
181 | |
182 | vfree(buffer); | |
183 | ||
184 | xst->status = XAUTHST_REQSENT; | |
185 | ||
186 | return; | |
187 | } | |
188 | ||
d1e348cf | 189 | int |
52b7d2ce A |
190 | xauth_attr_reply(iph1, attr, id) |
191 | struct ph1handle *iph1; | |
192 | struct isakmp_data *attr; | |
193 | int id; | |
194 | { | |
195 | char **outlet = NULL; | |
196 | size_t alen = 0; | |
197 | int type; | |
198 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
199 | ||
200 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { | |
201 | plog(LLV_ERROR, LOCATION, NULL, | |
202 | "Xauth reply but peer did not declare " | |
203 | "itself as Xauth capable\n"); | |
d1e348cf | 204 | return -1; |
52b7d2ce A |
205 | } |
206 | ||
207 | if (xst->status != XAUTHST_REQSENT) { | |
208 | plog(LLV_ERROR, LOCATION, NULL, | |
209 | "Xauth reply while Xauth state is %d\n", xst->status); | |
d1e348cf | 210 | return -1; |
52b7d2ce A |
211 | } |
212 | ||
213 | type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; | |
214 | switch (type) { | |
215 | case XAUTH_TYPE: | |
216 | switch (ntohs(attr->lorv)) { | |
217 | case XAUTH_TYPE_GENERIC: | |
218 | xst->authtype = XAUTH_TYPE_GENERIC; | |
219 | break; | |
220 | default: | |
221 | plog(LLV_WARNING, LOCATION, NULL, | |
222 | "Unexpected authentication type %d\n", | |
223 | ntohs(type)); | |
d1e348cf | 224 | return -1; |
52b7d2ce A |
225 | } |
226 | break; | |
227 | ||
228 | case XAUTH_USER_NAME: | |
229 | outlet = &xst->authdata.generic.usr; | |
230 | break; | |
231 | ||
232 | case XAUTH_USER_PASSWORD: | |
233 | outlet = &xst->authdata.generic.pwd; | |
234 | break; | |
235 | ||
236 | default: | |
237 | plog(LLV_WARNING, LOCATION, NULL, | |
238 | "ignored Xauth attribute %d\n", type); | |
239 | break; | |
240 | } | |
241 | ||
242 | if (outlet != NULL) { | |
243 | alen = ntohs(attr->lorv); | |
244 | ||
d1e348cf | 245 | if ((*outlet = racoon_realloc(*outlet, alen + 1)) == NULL) { |
52b7d2ce A |
246 | plog(LLV_ERROR, LOCATION, NULL, |
247 | "Cannot allocate memory for Xauth Data\n"); | |
d1e348cf | 248 | return -1; |
52b7d2ce A |
249 | } |
250 | ||
251 | memcpy(*outlet, attr + 1, alen); | |
252 | (*outlet)[alen] = '\0'; | |
253 | outlet = NULL; | |
254 | } | |
255 | ||
256 | ||
257 | if ((xst->authdata.generic.usr != NULL) && | |
258 | (xst->authdata.generic.pwd != NULL)) { | |
259 | int port; | |
260 | int res; | |
261 | char *usr = xst->authdata.generic.usr; | |
262 | char *pwd = xst->authdata.generic.pwd; | |
263 | time_t throttle_delay = 0; | |
264 | ||
265 | #if 0 /* Real debug, don't do that at home */ | |
266 | plog(LLV_DEBUG, LOCATION, NULL, | |
267 | "Got username \"%s\", password \"%s\"\n", usr, pwd); | |
268 | #endif | |
d1e348cf | 269 | strlcpy(iph1->mode_cfg->login, usr, sizeof(iph1->mode_cfg->login)); |
52b7d2ce A |
270 | |
271 | res = -1; | |
272 | if ((port = isakmp_cfg_getport(iph1)) == -1) { | |
273 | plog(LLV_ERROR, LOCATION, NULL, | |
274 | "Port pool depleted\n"); | |
275 | goto skip_auth; | |
276 | } | |
277 | ||
278 | switch (isakmp_cfg_config.authsource) { | |
279 | case ISAKMP_CFG_AUTH_SYSTEM: | |
280 | res = privsep_xauth_login_system(usr, pwd); | |
281 | break; | |
282 | #ifdef HAVE_LIBRADIUS | |
283 | case ISAKMP_CFG_AUTH_RADIUS: | |
284 | res = xauth_login_radius(iph1, usr, pwd); | |
285 | break; | |
286 | #endif | |
287 | #ifdef HAVE_LIBPAM | |
288 | case ISAKMP_CFG_AUTH_PAM: | |
289 | res = privsep_xauth_login_pam(iph1->mode_cfg->port, | |
290 | iph1->remote, usr, pwd); | |
291 | break; | |
d1e348cf A |
292 | #endif |
293 | #ifdef HAVE_LIBLDAP | |
294 | case ISAKMP_CFG_AUTH_LDAP: | |
295 | res = xauth_login_ldap(iph1, usr, pwd); | |
296 | break; | |
52b7d2ce A |
297 | #endif |
298 | default: | |
299 | plog(LLV_ERROR, LOCATION, NULL, | |
300 | "Unexpected authentication source\n"); | |
301 | res = -1; | |
302 | break; | |
303 | } | |
304 | ||
d1e348cf A |
305 | /* |
306 | * Optional group authentication | |
307 | */ | |
308 | if (!res && (isakmp_cfg_config.groupcount)) | |
309 | res = group_check(iph1, | |
310 | isakmp_cfg_config.grouplist, | |
311 | isakmp_cfg_config.groupcount); | |
312 | ||
52b7d2ce A |
313 | /* |
314 | * On failure, throttle the connexion for the remote host | |
315 | * in order to make password attacks more difficult. | |
316 | */ | |
317 | throttle_delay = throttle_host(iph1->remote, res) - time(NULL); | |
318 | if (throttle_delay > 0) { | |
319 | char *str; | |
320 | ||
321 | str = saddrwop2str(iph1->remote); | |
322 | ||
323 | plog(LLV_ERROR, LOCATION, NULL, | |
324 | "Throttling in action for %s: delay %lds\n", | |
325 | str, (unsigned long)throttle_delay); | |
326 | res = -1; | |
327 | } else { | |
328 | throttle_delay = 0; | |
329 | } | |
330 | ||
331 | skip_auth: | |
332 | if (throttle_delay != 0) { | |
333 | struct xauth_reply_arg *xra; | |
334 | ||
335 | if ((xra = racoon_malloc(sizeof(*xra))) == NULL) { | |
336 | plog(LLV_ERROR, LOCATION, NULL, | |
337 | "malloc failed, bypass throttling\n"); | |
d1e348cf | 338 | return xauth_reply(iph1, port, id, res); |
52b7d2ce A |
339 | } |
340 | ||
341 | /* | |
342 | * We need to store the ph1, but it might have | |
343 | * disapeared when xauth_reply is called, so | |
344 | * store the index instead. | |
345 | */ | |
346 | xra->index = iph1->index; | |
347 | xra->port = port; | |
348 | xra->id = id; | |
349 | xra->res = res; | |
350 | sched_new(throttle_delay, xauth_reply_stub, xra); | |
351 | } else { | |
d1e348cf | 352 | return xauth_reply(iph1, port, id, res); |
52b7d2ce A |
353 | } |
354 | } | |
355 | ||
d1e348cf | 356 | return 0; |
52b7d2ce A |
357 | } |
358 | ||
359 | void | |
360 | xauth_reply_stub(args) | |
361 | void *args; | |
362 | { | |
363 | struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args; | |
364 | struct ph1handle *iph1; | |
365 | ||
366 | if ((iph1 = getph1byindex(&xra->index)) != NULL) | |
d1e348cf | 367 | (void)xauth_reply(iph1, xra->port, xra->id, xra->res); |
52b7d2ce A |
368 | else |
369 | plog(LLV_ERROR, LOCATION, NULL, | |
370 | "Delayed Xauth reply: phase 1 no longer exists.\n"); | |
371 | ||
372 | racoon_free(xra); | |
373 | return; | |
374 | } | |
375 | ||
d1e348cf | 376 | int |
52b7d2ce A |
377 | xauth_reply(iph1, port, id, res) |
378 | struct ph1handle *iph1; | |
379 | int port; | |
380 | int id; | |
381 | { | |
382 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
383 | char *usr = xst->authdata.generic.usr; | |
384 | ||
385 | if (res != 0) { | |
386 | if (port != -1) | |
387 | isakmp_cfg_putport(iph1, port); | |
388 | ||
389 | plog(LLV_INFO, LOCATION, NULL, | |
390 | "login failed for user \"%s\"\n", usr); | |
391 | ||
392 | xauth_sendstatus(iph1, XAUTH_STATUS_FAIL, id); | |
393 | xst->status = XAUTHST_NOTYET; | |
394 | ||
395 | /* Delete Phase 1 SA */ | |
396 | if (iph1->status == PHASE1ST_ESTABLISHED) | |
397 | isakmp_info_send_d1(iph1); | |
47612122 | 398 | isakmp_ph1expire(iph1); |
52b7d2ce | 399 | |
d1e348cf | 400 | return -1; |
52b7d2ce A |
401 | } |
402 | ||
403 | xst->status = XAUTHST_OK; | |
404 | plog(LLV_INFO, LOCATION, NULL, | |
405 | "login succeeded for user \"%s\"\n", usr); | |
406 | ||
407 | xauth_sendstatus(iph1, XAUTH_STATUS_OK, id); | |
408 | ||
d1e348cf | 409 | return 0; |
52b7d2ce A |
410 | } |
411 | ||
412 | void | |
413 | xauth_sendstatus(iph1, status, id) | |
414 | struct ph1handle *iph1; | |
415 | int status; | |
416 | int id; | |
417 | { | |
418 | vchar_t *buffer; | |
419 | struct isakmp_pl_attr *attr; | |
420 | struct isakmp_data *stattr; | |
421 | size_t tlen; | |
422 | ||
423 | tlen = sizeof(*attr) + | |
424 | + sizeof(*stattr); | |
425 | ||
426 | if ((buffer = vmalloc(tlen)) == NULL) { | |
427 | plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n"); | |
428 | return; | |
429 | } | |
430 | ||
431 | attr = (struct isakmp_pl_attr *)buffer->v; | |
432 | memset(attr, 0, tlen); | |
433 | ||
434 | attr->h.len = htons(tlen); | |
435 | attr->type = ISAKMP_CFG_SET; | |
436 | attr->id = htons(id); | |
437 | ||
438 | stattr = (struct isakmp_data *)(attr + 1); | |
439 | stattr->type = htons(XAUTH_STATUS | ISAKMP_GEN_TV); | |
440 | stattr->lorv = htons(status); | |
441 | ||
442 | isakmp_cfg_send(iph1, buffer, | |
d1e348cf | 443 | ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL); |
52b7d2ce A |
444 | |
445 | vfree(buffer); | |
446 | ||
447 | return; | |
448 | } | |
449 | ||
450 | #ifdef HAVE_LIBRADIUS | |
451 | int | |
452 | xauth_radius_init(void) | |
453 | { | |
454 | /* For first time use, initialize Radius */ | |
455 | if ((isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_RADIUS) && | |
456 | (radius_auth_state == NULL)) { | |
457 | if ((radius_auth_state = rad_auth_open()) == NULL) { | |
458 | plog(LLV_ERROR, LOCATION, NULL, | |
459 | "Cannot init libradius\n"); | |
460 | return -1; | |
461 | } | |
462 | ||
463 | if (rad_config(radius_auth_state, NULL) != 0) { | |
464 | plog(LLV_ERROR, LOCATION, NULL, | |
465 | "Cannot open librarius config file: %s\n", | |
466 | rad_strerror(radius_auth_state)); | |
467 | rad_close(radius_auth_state); | |
468 | radius_auth_state = NULL; | |
469 | return -1; | |
470 | } | |
471 | } | |
472 | ||
473 | if ((isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS) && | |
474 | (radius_acct_state == NULL)) { | |
d1e348cf | 475 | if ((radius_acct_state = rad_acct_open()) == NULL) { |
52b7d2ce A |
476 | plog(LLV_ERROR, LOCATION, NULL, |
477 | "Cannot init libradius\n"); | |
478 | return -1; | |
479 | } | |
480 | ||
481 | if (rad_config(radius_acct_state, NULL) != 0) { | |
482 | plog(LLV_ERROR, LOCATION, NULL, | |
483 | "Cannot open librarius config file: %s\n", | |
484 | rad_strerror(radius_acct_state)); | |
485 | rad_close(radius_acct_state); | |
486 | radius_acct_state = NULL; | |
487 | return -1; | |
488 | } | |
489 | } | |
490 | ||
491 | return 0; | |
492 | } | |
493 | ||
494 | int | |
495 | xauth_login_radius(iph1, usr, pwd) | |
496 | struct ph1handle *iph1; | |
497 | char *usr; | |
498 | char *pwd; | |
499 | { | |
500 | int res; | |
501 | const void *data; | |
502 | size_t len; | |
503 | int type; | |
504 | ||
505 | if (rad_create_request(radius_auth_state, RAD_ACCESS_REQUEST) != 0) { | |
506 | plog(LLV_ERROR, LOCATION, NULL, | |
507 | "rad_create_request failed: %s\n", | |
508 | rad_strerror(radius_auth_state)); | |
509 | return -1; | |
510 | } | |
511 | ||
512 | if (rad_put_string(radius_auth_state, RAD_USER_NAME, usr) != 0) { | |
513 | plog(LLV_ERROR, LOCATION, NULL, | |
514 | "rad_put_string failed: %s\n", | |
515 | rad_strerror(radius_auth_state)); | |
516 | return -1; | |
517 | } | |
518 | ||
519 | if (rad_put_string(radius_auth_state, RAD_USER_PASSWORD, pwd) != 0) { | |
520 | plog(LLV_ERROR, LOCATION, NULL, | |
521 | "rad_put_string failed: %s\n", | |
522 | rad_strerror(radius_auth_state)); | |
523 | return -1; | |
524 | } | |
525 | ||
526 | if (isakmp_cfg_radius_common(radius_auth_state, iph1->mode_cfg->port) != 0) | |
527 | return -1; | |
528 | ||
529 | switch (res = rad_send_request(radius_auth_state)) { | |
530 | case RAD_ACCESS_ACCEPT: | |
531 | while ((type = rad_get_attr(radius_auth_state, &data, &len)) != 0) { | |
532 | switch (type) { | |
533 | case RAD_FRAMED_IP_ADDRESS: | |
534 | iph1->mode_cfg->addr4 = rad_cvt_addr(data); | |
535 | iph1->mode_cfg->flags | |
d1e348cf | 536 | |= ISAKMP_CFG_ADDR4_EXTERN; |
52b7d2ce A |
537 | break; |
538 | ||
539 | case RAD_FRAMED_IP_NETMASK: | |
540 | iph1->mode_cfg->mask4 = rad_cvt_addr(data); | |
541 | iph1->mode_cfg->flags | |
d1e348cf | 542 | |= ISAKMP_CFG_MASK4_EXTERN; |
52b7d2ce A |
543 | break; |
544 | ||
545 | default: | |
546 | plog(LLV_INFO, LOCATION, NULL, | |
547 | "Unexpected attribute: %d\n", type); | |
548 | break; | |
549 | } | |
550 | } | |
551 | ||
552 | return 0; | |
553 | break; | |
554 | ||
555 | case RAD_ACCESS_REJECT: | |
556 | return -1; | |
557 | break; | |
558 | ||
559 | case -1: | |
560 | plog(LLV_ERROR, LOCATION, NULL, | |
561 | "rad_send_request failed: %s\n", | |
562 | rad_strerror(radius_auth_state)); | |
563 | return -1; | |
564 | break; | |
565 | default: | |
566 | plog(LLV_ERROR, LOCATION, NULL, | |
567 | "rad_send_request returned %d\n", res); | |
568 | return -1; | |
569 | break; | |
570 | } | |
571 | ||
572 | return -1; | |
573 | } | |
574 | #endif | |
575 | ||
576 | #ifdef HAVE_LIBPAM | |
577 | static int | |
578 | PAM_conv(msg_count, msg, rsp, dontcare) | |
579 | int msg_count; | |
580 | const struct pam_message **msg; | |
581 | struct pam_response **rsp; | |
582 | void *dontcare; | |
583 | { | |
584 | int i; | |
585 | int replies = 0; | |
586 | struct pam_response *reply = NULL; | |
587 | ||
588 | if ((reply = racoon_malloc(sizeof(*reply) * msg_count)) == NULL) | |
589 | return PAM_CONV_ERR; | |
590 | bzero(reply, sizeof(*reply) * msg_count); | |
591 | ||
592 | for (i = 0; i < msg_count; i++) { | |
593 | switch (msg[i]->msg_style) { | |
594 | case PAM_PROMPT_ECHO_ON: | |
595 | /* Send the username, libpam frees resp */ | |
596 | reply[i].resp_retcode = PAM_SUCCESS; | |
d1e348cf A |
597 | if ((reply[i].resp = strdup(PAM_usr)) == NULL) { |
598 | plog(LLV_ERROR, LOCATION, | |
599 | NULL, "strdup failed\n"); | |
600 | exit(1); | |
601 | } | |
52b7d2ce A |
602 | break; |
603 | ||
604 | case PAM_PROMPT_ECHO_OFF: | |
605 | /* Send the password, libpam frees resp */ | |
606 | reply[i].resp_retcode = PAM_SUCCESS; | |
d1e348cf A |
607 | if ((reply[i].resp = strdup(PAM_pwd)) == NULL) { |
608 | plog(LLV_ERROR, LOCATION, | |
609 | NULL, "strdup failed\n"); | |
610 | exit(1); | |
611 | } | |
52b7d2ce A |
612 | break; |
613 | ||
614 | case PAM_TEXT_INFO: | |
615 | case PAM_ERROR_MSG: | |
616 | reply[i].resp_retcode = PAM_SUCCESS; | |
617 | reply[i].resp = NULL; | |
618 | break; | |
619 | ||
620 | default: | |
621 | if (reply != NULL) | |
622 | racoon_free(reply); | |
623 | return PAM_CONV_ERR; | |
624 | break; | |
625 | } | |
626 | } | |
627 | ||
628 | if (reply != NULL) | |
629 | *rsp = reply; | |
630 | ||
631 | return PAM_SUCCESS; | |
632 | } | |
633 | ||
634 | int | |
635 | xauth_login_pam(port, raddr, usr, pwd) | |
636 | int port; | |
637 | struct sockaddr *raddr; | |
638 | char *usr; | |
639 | char *pwd; | |
640 | { | |
641 | int error; | |
642 | int res; | |
643 | const void *data; | |
644 | size_t len; | |
645 | int type; | |
d1e348cf | 646 | char *remote = NULL; |
52b7d2ce A |
647 | pam_handle_t *pam = NULL; |
648 | ||
649 | if (isakmp_cfg_config.port_pool == NULL) { | |
650 | plog(LLV_ERROR, LOCATION, NULL, | |
651 | "isakmp_cfg_config.port_pool == NULL\n"); | |
652 | return -1; | |
653 | } | |
654 | ||
655 | if ((error = pam_start("racoon", usr, | |
656 | &PAM_chat, &isakmp_cfg_config.port_pool[port].pam)) != 0) { | |
657 | if (isakmp_cfg_config.port_pool[port].pam == NULL) { | |
658 | plog(LLV_ERROR, LOCATION, NULL, "pam_start failed\n"); | |
659 | return -1; | |
660 | } else { | |
661 | plog(LLV_ERROR, LOCATION, NULL, | |
662 | "pam_start failed: %s\n", | |
663 | pam_strerror(isakmp_cfg_config.port_pool[port].pam, | |
664 | error)); | |
665 | goto out; | |
666 | } | |
667 | } | |
668 | pam = isakmp_cfg_config.port_pool[port].pam; | |
669 | ||
670 | if ((remote = strdup(saddrwop2str(raddr))) == NULL) { | |
671 | plog(LLV_ERROR, LOCATION, NULL, | |
672 | "cannot allocate memory: %s\n", strerror(errno)); | |
673 | goto out; | |
674 | } | |
675 | ||
676 | if ((error = pam_set_item(pam, PAM_RHOST, remote)) != 0) { | |
677 | plog(LLV_ERROR, LOCATION, NULL, | |
678 | "pam_set_item failed: %s\n", | |
679 | pam_strerror(pam, error)); | |
680 | goto out; | |
681 | } | |
682 | ||
683 | PAM_usr = usr; | |
684 | PAM_pwd = pwd; | |
685 | error = pam_authenticate(pam, 0); | |
686 | PAM_usr = NULL; | |
687 | PAM_pwd = NULL; | |
688 | if (error != 0) { | |
689 | plog(LLV_ERROR, LOCATION, NULL, | |
690 | "pam_authenticate failed: %s\n", | |
691 | pam_strerror(pam, error)); | |
692 | goto out; | |
693 | } | |
694 | ||
695 | if ((error = pam_acct_mgmt(pam, 0)) != 0) { | |
696 | plog(LLV_ERROR, LOCATION, NULL, | |
697 | "pam_acct_mgmt failed: %s\n", | |
698 | pam_strerror(pam, error)); | |
699 | goto out; | |
700 | } | |
701 | ||
702 | if ((error = pam_setcred(pam, 0)) != 0) { | |
703 | plog(LLV_ERROR, LOCATION, NULL, | |
704 | "pam_setcred failed: %s\n", | |
705 | pam_strerror(pam, error)); | |
706 | goto out; | |
707 | } | |
708 | ||
d1e348cf A |
709 | if (remote != NULL) |
710 | free(remote); | |
711 | ||
52b7d2ce A |
712 | return 0; |
713 | ||
714 | out: | |
715 | pam_end(pam, error); | |
716 | isakmp_cfg_config.port_pool[port].pam = NULL; | |
d1e348cf A |
717 | if (remote != NULL) |
718 | free(remote); | |
52b7d2ce A |
719 | return -1; |
720 | } | |
721 | #endif | |
722 | ||
d1e348cf A |
723 | #ifdef HAVE_LIBLDAP |
724 | int | |
725 | xauth_ldap_init(void) | |
726 | { | |
727 | int tmplen; | |
728 | int error = -1; | |
729 | ||
730 | xauth_ldap_config.pver = 3; | |
731 | xauth_ldap_config.host = NULL; | |
732 | xauth_ldap_config.port = LDAP_PORT; | |
733 | xauth_ldap_config.base = NULL; | |
734 | xauth_ldap_config.subtree = 0; | |
735 | xauth_ldap_config.bind_dn = NULL; | |
736 | xauth_ldap_config.bind_pw = NULL; | |
737 | xauth_ldap_config.auth_type = LDAP_AUTH_SIMPLE; | |
738 | xauth_ldap_config.attr_user = NULL; | |
739 | xauth_ldap_config.attr_addr = NULL; | |
740 | xauth_ldap_config.attr_mask = NULL; | |
741 | xauth_ldap_config.attr_group = NULL; | |
742 | xauth_ldap_config.attr_member = NULL; | |
743 | ||
744 | /* set default host */ | |
745 | tmplen = strlen(LDAP_DFLT_HOST); | |
746 | xauth_ldap_config.host = vmalloc(tmplen); | |
747 | if (xauth_ldap_config.host == NULL) | |
748 | goto out; | |
749 | memcpy(xauth_ldap_config.host->v, LDAP_DFLT_HOST, tmplen); | |
750 | ||
751 | /* set default user naming attribute */ | |
752 | tmplen = strlen(LDAP_DFLT_USER); | |
753 | xauth_ldap_config.attr_user = vmalloc(tmplen); | |
754 | if (xauth_ldap_config.attr_user == NULL) | |
755 | goto out; | |
756 | memcpy(xauth_ldap_config.attr_user->v, LDAP_DFLT_USER, tmplen); | |
757 | ||
758 | /* set default address attribute */ | |
759 | tmplen = strlen(LDAP_DFLT_ADDR); | |
760 | xauth_ldap_config.attr_addr = vmalloc(tmplen); | |
761 | if (xauth_ldap_config.attr_addr == NULL) | |
762 | goto out; | |
763 | memcpy(xauth_ldap_config.attr_addr->v, LDAP_DFLT_ADDR, tmplen); | |
764 | ||
765 | /* set default netmask attribute */ | |
766 | tmplen = strlen(LDAP_DFLT_MASK); | |
767 | xauth_ldap_config.attr_mask = vmalloc(tmplen); | |
768 | if (xauth_ldap_config.attr_mask == NULL) | |
769 | goto out; | |
770 | memcpy(xauth_ldap_config.attr_mask->v, LDAP_DFLT_MASK, tmplen); | |
771 | ||
772 | /* set default group naming attribute */ | |
773 | tmplen = strlen(LDAP_DFLT_GROUP); | |
774 | xauth_ldap_config.attr_group = vmalloc(tmplen); | |
775 | if (xauth_ldap_config.attr_group == NULL) | |
776 | goto out; | |
777 | memcpy(xauth_ldap_config.attr_group->v, LDAP_DFLT_GROUP, tmplen); | |
778 | ||
779 | /* set default member attribute */ | |
780 | tmplen = strlen(LDAP_DFLT_MEMBER); | |
781 | xauth_ldap_config.attr_member = vmalloc(tmplen); | |
782 | if (xauth_ldap_config.attr_member == NULL) | |
783 | goto out; | |
784 | memcpy(xauth_ldap_config.attr_member->v, LDAP_DFLT_MEMBER, tmplen); | |
785 | ||
786 | error = 0; | |
787 | out: | |
788 | if (error != 0) | |
789 | plog(LLV_ERROR, LOCATION, NULL, "cannot allocate memory\n"); | |
790 | ||
791 | return error; | |
792 | } | |
793 | ||
794 | void | |
795 | xauth_ldap_flush(void) | |
796 | { | |
797 | if (xauth_ldap_config.host) { | |
798 | vfree(xauth_ldap_config.host); | |
799 | xauth_ldap_config.host = NULL; | |
800 | } | |
801 | if (xauth_ldap_config.base) { | |
802 | vfree(xauth_ldap_config.base); | |
803 | xauth_ldap_config.base = NULL; | |
804 | } | |
805 | if (xauth_ldap_config.bind_dn) { | |
806 | vfree(xauth_ldap_config.bind_dn); | |
807 | xauth_ldap_config.bind_dn = NULL; | |
808 | } | |
809 | if (xauth_ldap_config.bind_pw) { | |
810 | vfree(xauth_ldap_config.bind_pw); | |
811 | xauth_ldap_config.bind_pw = NULL; | |
812 | } | |
813 | if (xauth_ldap_config.attr_user) { | |
814 | vfree(xauth_ldap_config.attr_user); | |
815 | xauth_ldap_config.attr_user = NULL; | |
816 | } | |
817 | if (xauth_ldap_config.attr_addr) { | |
818 | vfree(xauth_ldap_config.attr_addr); | |
819 | xauth_ldap_config.attr_addr = NULL; | |
820 | } | |
821 | if (xauth_ldap_config.attr_mask) { | |
822 | vfree(xauth_ldap_config.attr_mask); | |
823 | xauth_ldap_config.attr_mask = NULL; | |
824 | } | |
825 | if (xauth_ldap_config.attr_group) { | |
826 | vfree(xauth_ldap_config.attr_group); | |
827 | xauth_ldap_config.attr_group = NULL; | |
828 | } | |
829 | if (xauth_ldap_config.attr_member) { | |
830 | vfree(xauth_ldap_config.attr_member); | |
831 | xauth_ldap_config.attr_member = NULL; | |
832 | } | |
833 | } | |
834 | ||
835 | int | |
836 | xauth_login_ldap(iph1, usr, pwd) | |
837 | struct ph1handle *iph1; | |
838 | char *usr; | |
839 | char *pwd; | |
840 | { | |
841 | int rtn = -1; | |
842 | int res = -1; | |
843 | LDAP *ld = NULL; | |
844 | LDAPMessage *lr = NULL; | |
845 | LDAPMessage *le = NULL; | |
846 | struct berval cred; | |
847 | struct berval **bv = NULL; | |
848 | struct timeval timeout; | |
849 | char *init = NULL; | |
850 | char *filter = NULL; | |
851 | char *atlist[3]; | |
852 | int atlist_len[sizeof(atlist)/sizeof(__typeof__(*atlist))]; | |
853 | char *basedn = NULL; | |
854 | char *userdn = NULL; | |
855 | int udn_len = 0; | |
856 | int tmplen = 0; | |
857 | int ecount = 0; | |
858 | int scope = LDAP_SCOPE_ONE; | |
859 | ||
860 | atlist[0] = NULL; | |
861 | atlist_len[0] = 0; | |
862 | atlist[1] = NULL; | |
863 | atlist_len[1] = 0; | |
864 | atlist[2] = NULL; | |
865 | atlist_len[2] = 0; | |
866 | ||
867 | /* build our initialization url */ | |
868 | tmplen = strlen("ldap://:") + 17; | |
869 | tmplen += strlen(xauth_ldap_config.host->v); | |
870 | init = racoon_malloc(tmplen); | |
871 | if (init == NULL) { | |
872 | plog(LLV_ERROR, LOCATION, NULL, | |
873 | "unable to alloc ldap init url\n"); | |
874 | goto ldap_end; | |
875 | } | |
876 | snprintf(init, tmplen, "ldap://%s:%d", | |
877 | xauth_ldap_config.host->v, | |
878 | xauth_ldap_config.port ); | |
879 | ||
880 | /* initialize the ldap handle */ | |
881 | res = ldap_initialize(&ld, init); | |
882 | if (res != LDAP_SUCCESS) { | |
883 | plog(LLV_ERROR, LOCATION, NULL, | |
884 | "ldap_initialize failed: %s\n", | |
885 | ldap_err2string(res)); | |
886 | goto ldap_end; | |
887 | } | |
888 | ||
889 | /* initialize the protocol version */ | |
890 | ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, | |
891 | &xauth_ldap_config.pver); | |
892 | ||
893 | /* | |
894 | * attempt to bind to the ldap server. | |
895 | * default to anonymous bind unless a | |
896 | * user dn and password has been | |
897 | * specified in our configuration | |
898 | */ | |
899 | if ((xauth_ldap_config.bind_dn != NULL)&& | |
900 | (xauth_ldap_config.bind_pw != NULL)) | |
901 | { | |
902 | cred.bv_val = xauth_ldap_config.bind_pw->v; | |
903 | cred.bv_len = strlen( cred.bv_val ); | |
904 | res = ldap_sasl_bind_s(ld, | |
905 | xauth_ldap_config.bind_dn->v, NULL, &cred, | |
906 | NULL, NULL, NULL); | |
907 | } | |
908 | else | |
909 | { | |
910 | res = ldap_sasl_bind_s(ld, | |
911 | NULL, NULL, NULL, | |
912 | NULL, NULL, NULL); | |
913 | } | |
914 | ||
915 | if (res!=LDAP_SUCCESS) { | |
916 | plog(LLV_ERROR, LOCATION, NULL, | |
917 | "ldap_sasl_bind_s (search) failed: %s\n", | |
918 | ldap_err2string(res)); | |
919 | goto ldap_end; | |
920 | } | |
921 | ||
922 | /* build an ldap user search filter */ | |
923 | tmplen = strlen(xauth_ldap_config.attr_user->v); | |
924 | tmplen += 1; | |
925 | tmplen += strlen(usr); | |
926 | tmplen += 1; | |
927 | filter = racoon_malloc(tmplen); | |
928 | if (filter == NULL) { | |
929 | plog(LLV_ERROR, LOCATION, NULL, | |
930 | "unable to alloc ldap search filter buffer\n"); | |
931 | goto ldap_end; | |
932 | } | |
933 | snprintf(filter, tmplen, "%s=%s", | |
934 | xauth_ldap_config.attr_user->v, usr); | |
935 | ||
936 | /* build our return attribute list */ | |
937 | atlist_len[0] = strlen(xauth_ldap_config.attr_addr->v) + 1; | |
938 | atlist[0] = racoon_malloc(atlist_len[0]); | |
939 | atlist_len[1] = strlen(xauth_ldap_config.attr_mask->v) + 1; | |
940 | atlist[1] = racoon_malloc(atlist_len[1]); | |
941 | if ((atlist[0] == NULL)||(atlist[1] == NULL)) { | |
942 | plog(LLV_ERROR, LOCATION, NULL, | |
943 | "unable to alloc ldap attrib list buffer\n"); | |
944 | goto ldap_end; | |
945 | } | |
946 | strlcpy(atlist[0],xauth_ldap_config.attr_addr->v,atlist_len[0]); | |
947 | strlcpy(atlist[1],xauth_ldap_config.attr_mask->v,atlist_len[1]); | |
948 | ||
949 | /* attempt to locate the user dn */ | |
950 | if (xauth_ldap_config.base != NULL) | |
951 | basedn = xauth_ldap_config.base->v; | |
952 | if (xauth_ldap_config.subtree) | |
953 | scope = LDAP_SCOPE_SUBTREE; | |
954 | timeout.tv_sec = 15; | |
955 | timeout.tv_usec = 0; | |
956 | res = ldap_search_ext_s(ld, basedn, scope, | |
957 | filter, atlist, 0, NULL, NULL, | |
958 | &timeout, 2, &lr); | |
959 | if (res != LDAP_SUCCESS) { | |
960 | plog(LLV_ERROR, LOCATION, NULL, | |
961 | "ldap_search_ext_s failed: %s\n", | |
962 | ldap_err2string(res)); | |
963 | goto ldap_end; | |
964 | } | |
965 | ||
966 | /* check the number of ldap entries returned */ | |
967 | ecount = ldap_count_entries(ld, lr); | |
968 | if (ecount < 1) { | |
969 | plog(LLV_WARNING, LOCATION, NULL, | |
970 | "no ldap results for filter \'%s\'\n", | |
971 | filter); | |
972 | goto ldap_end; | |
973 | } | |
974 | if (ecount > 1) { | |
975 | plog(LLV_WARNING, LOCATION, NULL, | |
976 | "multiple (%i) ldap results for filter \'%s\'\n", | |
977 | ecount, filter); | |
978 | } | |
979 | ||
980 | /* obtain the dn from the first result */ | |
981 | le = ldap_first_entry(ld, lr); | |
982 | if (le == NULL) { | |
983 | plog(LLV_ERROR, LOCATION, NULL, | |
984 | "ldap_first_entry failed: invalid entry returned\n"); | |
985 | goto ldap_end; | |
986 | } | |
987 | userdn = ldap_get_dn(ld, le); | |
988 | if (userdn == NULL) { | |
989 | plog(LLV_ERROR, LOCATION, NULL, | |
990 | "ldap_get_dn failed: invalid string returned\n"); | |
991 | goto ldap_end; | |
992 | } | |
993 | ||
994 | /* cache the user dn in the xauth state */ | |
995 | udn_len = strlen(userdn)+1; | |
996 | iph1->mode_cfg->xauth.udn = racoon_malloc(udn_len); | |
997 | strlcpy(iph1->mode_cfg->xauth.udn,userdn,udn_len); | |
998 | ||
999 | /* retrieve modecfg address */ | |
1000 | bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_addr->v); | |
1001 | if (bv != NULL) { | |
1002 | char tmpaddr[16]; | |
1003 | /* sanity check for address value */ | |
1004 | if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) { | |
1005 | plog(LLV_DEBUG, LOCATION, NULL, | |
1006 | "ldap returned invalid modecfg address\n"); | |
1007 | ldap_value_free_len(bv); | |
1008 | goto ldap_end; | |
1009 | } | |
1010 | memcpy(tmpaddr,bv[0]->bv_val,bv[0]->bv_len); | |
1011 | tmpaddr[bv[0]->bv_len]=0; | |
1012 | iph1->mode_cfg->addr4.s_addr = inet_addr(tmpaddr); | |
1013 | iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_EXTERN; | |
1014 | plog(LLV_INFO, LOCATION, NULL, | |
1015 | "ldap returned modecfg address %s\n", tmpaddr); | |
1016 | ldap_value_free_len(bv); | |
1017 | } | |
1018 | ||
1019 | /* retrieve modecfg netmask */ | |
1020 | bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_mask->v); | |
1021 | if (bv != NULL) { | |
1022 | char tmpmask[16]; | |
1023 | /* sanity check for netmask value */ | |
1024 | if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) { | |
1025 | plog(LLV_DEBUG, LOCATION, NULL, | |
1026 | "ldap returned invalid modecfg netmask\n"); | |
1027 | ldap_value_free_len(bv); | |
1028 | goto ldap_end; | |
1029 | } | |
1030 | memcpy(tmpmask,bv[0]->bv_val,bv[0]->bv_len); | |
1031 | tmpmask[bv[0]->bv_len]=0; | |
1032 | iph1->mode_cfg->mask4.s_addr = inet_addr(tmpmask); | |
1033 | iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_EXTERN; | |
1034 | plog(LLV_INFO, LOCATION, NULL, | |
1035 | "ldap returned modecfg netmask %s\n", tmpmask); | |
1036 | ldap_value_free_len(bv); | |
1037 | } | |
1038 | ||
1039 | /* | |
1040 | * finally, use the dn and the xauth | |
1041 | * password to check the users given | |
1042 | * credentials by attempting to bind | |
1043 | * to the ldap server | |
1044 | */ | |
1045 | plog(LLV_INFO, LOCATION, NULL, | |
1046 | "attempting ldap bind for dn \'%s\'\n", userdn); | |
1047 | cred.bv_val = pwd; | |
1048 | cred.bv_len = strlen( cred.bv_val ); | |
1049 | res = ldap_sasl_bind_s(ld, | |
1050 | userdn, NULL, &cred, | |
1051 | NULL, NULL, NULL); | |
1052 | if(res==LDAP_SUCCESS) | |
1053 | rtn = 0; | |
1054 | ||
1055 | ldap_end: | |
1056 | ||
1057 | /* free ldap resources */ | |
1058 | if (userdn != NULL) | |
1059 | ldap_memfree(userdn); | |
1060 | if (atlist[0] != NULL) | |
1061 | racoon_free(atlist[0]); | |
1062 | if (atlist[1] != NULL) | |
1063 | racoon_free(atlist[1]); | |
1064 | if (filter != NULL) | |
1065 | racoon_free(filter); | |
1066 | if (lr != NULL) | |
1067 | ldap_msgfree(lr); | |
1068 | if (init != NULL) | |
1069 | racoon_free(init); | |
1070 | ||
1071 | ldap_unbind_ext_s(ld, NULL, NULL); | |
1072 | ||
1073 | return rtn; | |
1074 | } | |
1075 | ||
1076 | int | |
1077 | xauth_group_ldap(udn, grp) | |
1078 | char * udn; | |
1079 | char * grp; | |
1080 | { | |
1081 | int rtn = -1; | |
1082 | int res = -1; | |
1083 | LDAP *ld = NULL; | |
1084 | LDAPMessage *lr = NULL; | |
1085 | LDAPMessage *le = NULL; | |
1086 | struct berval cred; | |
1087 | struct timeval timeout; | |
1088 | char *init = NULL; | |
1089 | char *filter = NULL; | |
1090 | char *basedn = NULL; | |
1091 | char *groupdn = NULL; | |
1092 | int tmplen = 0; | |
1093 | int ecount = 0; | |
1094 | int scope = LDAP_SCOPE_ONE; | |
1095 | ||
1096 | /* build our initialization url */ | |
1097 | tmplen = strlen("ldap://:") + 17; | |
1098 | tmplen += strlen(xauth_ldap_config.host->v); | |
1099 | init = racoon_malloc(tmplen); | |
1100 | if (init == NULL) { | |
1101 | plog(LLV_ERROR, LOCATION, NULL, | |
1102 | "unable to alloc ldap init url\n"); | |
1103 | goto ldap_group_end; | |
1104 | } | |
1105 | snprintf(init, tmplen, "ldap://%s:%d", | |
1106 | xauth_ldap_config.host->v, | |
1107 | xauth_ldap_config.port ); | |
1108 | ||
1109 | /* initialize the ldap handle */ | |
1110 | res = ldap_initialize(&ld, init); | |
1111 | if (res != LDAP_SUCCESS) { | |
1112 | plog(LLV_ERROR, LOCATION, NULL, | |
1113 | "ldap_initialize failed: %s\n", | |
1114 | ldap_err2string(res)); | |
1115 | goto ldap_group_end; | |
1116 | } | |
1117 | ||
1118 | /* initialize the protocol version */ | |
1119 | ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, | |
1120 | &xauth_ldap_config.pver); | |
1121 | ||
1122 | /* | |
1123 | * attempt to bind to the ldap server. | |
1124 | * default to anonymous bind unless a | |
1125 | * user dn and password has been | |
1126 | * specified in our configuration | |
1127 | */ | |
1128 | if ((xauth_ldap_config.bind_dn != NULL)&& | |
1129 | (xauth_ldap_config.bind_pw != NULL)) | |
1130 | { | |
1131 | cred.bv_val = xauth_ldap_config.bind_pw->v; | |
1132 | cred.bv_len = strlen( cred.bv_val ); | |
1133 | res = ldap_sasl_bind_s(ld, | |
1134 | xauth_ldap_config.bind_dn->v, NULL, &cred, | |
1135 | NULL, NULL, NULL); | |
1136 | } | |
1137 | else | |
1138 | { | |
1139 | res = ldap_sasl_bind_s(ld, | |
1140 | NULL, NULL, NULL, | |
1141 | NULL, NULL, NULL); | |
1142 | } | |
1143 | ||
1144 | if (res!=LDAP_SUCCESS) { | |
1145 | plog(LLV_ERROR, LOCATION, NULL, | |
1146 | "ldap_sasl_bind_s (search) failed: %s\n", | |
1147 | ldap_err2string(res)); | |
1148 | goto ldap_group_end; | |
1149 | } | |
1150 | ||
1151 | /* build an ldap group search filter */ | |
1152 | tmplen = strlen("(&(=)(=))") + 1; | |
1153 | tmplen += strlen(xauth_ldap_config.attr_group->v); | |
1154 | tmplen += strlen(grp); | |
1155 | tmplen += strlen(xauth_ldap_config.attr_member->v); | |
1156 | tmplen += strlen(udn); | |
1157 | filter = racoon_malloc(tmplen); | |
1158 | if (filter == NULL) { | |
1159 | plog(LLV_ERROR, LOCATION, NULL, | |
1160 | "unable to alloc ldap search filter buffer\n"); | |
1161 | goto ldap_group_end; | |
1162 | } | |
1163 | snprintf(filter, tmplen, "(&(%s=%s)(%s=%s))", | |
1164 | xauth_ldap_config.attr_group->v, grp, | |
1165 | xauth_ldap_config.attr_member->v, udn); | |
1166 | ||
1167 | /* attempt to locate the group dn */ | |
1168 | if (xauth_ldap_config.base != NULL) | |
1169 | basedn = xauth_ldap_config.base->v; | |
1170 | if (xauth_ldap_config.subtree) | |
1171 | scope = LDAP_SCOPE_SUBTREE; | |
1172 | timeout.tv_sec = 15; | |
1173 | timeout.tv_usec = 0; | |
1174 | res = ldap_search_ext_s(ld, basedn, scope, | |
1175 | filter, NULL, 0, NULL, NULL, | |
1176 | &timeout, 2, &lr); | |
1177 | if (res != LDAP_SUCCESS) { | |
1178 | plog(LLV_ERROR, LOCATION, NULL, | |
1179 | "ldap_search_ext_s failed: %s\n", | |
1180 | ldap_err2string(res)); | |
1181 | goto ldap_group_end; | |
1182 | } | |
1183 | ||
1184 | /* check the number of ldap entries returned */ | |
1185 | ecount = ldap_count_entries(ld, lr); | |
1186 | if (ecount < 1) { | |
1187 | plog(LLV_WARNING, LOCATION, NULL, | |
1188 | "no ldap results for filter \'%s\'\n", | |
1189 | filter); | |
1190 | goto ldap_group_end; | |
1191 | } | |
1192 | ||
1193 | /* success */ | |
1194 | rtn = 0; | |
1195 | ||
1196 | /* obtain the dn from the first result */ | |
1197 | le = ldap_first_entry(ld, lr); | |
1198 | if (le == NULL) { | |
1199 | plog(LLV_ERROR, LOCATION, NULL, | |
1200 | "ldap_first_entry failed: invalid entry returned\n"); | |
1201 | goto ldap_group_end; | |
1202 | } | |
1203 | groupdn = ldap_get_dn(ld, le); | |
1204 | if (groupdn == NULL) { | |
1205 | plog(LLV_ERROR, LOCATION, NULL, | |
1206 | "ldap_get_dn failed: invalid string returned\n"); | |
1207 | goto ldap_group_end; | |
1208 | } | |
1209 | ||
1210 | plog(LLV_INFO, LOCATION, NULL, | |
1211 | "ldap membership group returned \'%s\'\n", groupdn); | |
1212 | ldap_group_end: | |
1213 | ||
1214 | /* free ldap resources */ | |
1215 | if (groupdn != NULL) | |
1216 | ldap_memfree(groupdn); | |
1217 | if (filter != NULL) | |
1218 | racoon_free(filter); | |
1219 | if (lr != NULL) | |
1220 | ldap_msgfree(lr); | |
1221 | if (init != NULL) | |
1222 | racoon_free(init); | |
1223 | ||
1224 | ldap_unbind_ext_s(ld, NULL, NULL); | |
1225 | ||
1226 | return rtn; | |
1227 | } | |
1228 | ||
1229 | #endif | |
1230 | ||
52b7d2ce A |
1231 | int |
1232 | xauth_login_system(usr, pwd) | |
1233 | char *usr; | |
1234 | char *pwd; | |
1235 | { | |
1236 | struct passwd *pw; | |
1237 | char *cryptpwd; | |
1238 | char *syscryptpwd; | |
1239 | #ifdef HAVE_SHADOW_H | |
1240 | struct spwd *spw; | |
1241 | ||
1242 | if ((spw = getspnam(usr)) == NULL) | |
1243 | return -1; | |
1244 | ||
1245 | syscryptpwd = spw->sp_pwdp; | |
1246 | #endif | |
1247 | ||
1248 | if ((pw = getpwnam(usr)) == NULL) | |
1249 | return -1; | |
1250 | ||
1251 | #ifndef HAVE_SHADOW_H | |
1252 | syscryptpwd = pw->pw_passwd; | |
1253 | #endif | |
1254 | ||
1255 | /* No root login. Ever. */ | |
1256 | if (pw->pw_uid == 0) | |
1257 | return -1; | |
1258 | ||
1259 | if ((cryptpwd = crypt(pwd, syscryptpwd)) == NULL) | |
1260 | return -1; | |
1261 | ||
1262 | if (strcmp(cryptpwd, syscryptpwd) == 0) | |
1263 | return 0; | |
1264 | ||
1265 | return -1; | |
1266 | } | |
1267 | ||
d1e348cf A |
1268 | int |
1269 | xauth_group_system(usr, grp) | |
1270 | char * usr; | |
1271 | char * grp; | |
1272 | { | |
1273 | struct group * gr; | |
1274 | char * member; | |
1275 | int index = 0; | |
1276 | ||
1277 | gr = getgrnam(grp); | |
1278 | if (gr == NULL) { | |
1279 | plog(LLV_ERROR, LOCATION, NULL, | |
1280 | "the system group name \'%s\' is unknown\n", | |
1281 | grp); | |
1282 | return -1; | |
1283 | } | |
1284 | ||
1285 | while ((member = gr->gr_mem[index++])!=NULL) { | |
1286 | if (!strcmp(member,usr)) { | |
1287 | plog(LLV_INFO, LOCATION, NULL, | |
1288 | "membership validated\n"); | |
1289 | return 0; | |
1290 | } | |
1291 | } | |
1292 | ||
1293 | return -1; | |
1294 | } | |
1295 | ||
52b7d2ce A |
1296 | int |
1297 | xauth_check(iph1) | |
1298 | struct ph1handle *iph1; | |
1299 | { | |
1300 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
1301 | ||
d1e348cf A |
1302 | /* |
1303 | * Only the server side (edge device) really check for Xauth | |
1304 | * status. It does it if the chose authmethod is using Xauth. | |
1305 | * On the client side (roadwarrior), we don't check anything. | |
1306 | */ | |
1307 | switch (AUTHMETHOD(iph1)) { | |
1308 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: | |
1309 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: | |
1310 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: | |
52b7d2ce | 1311 | /* The following are not yet implemented */ |
d1e348cf A |
1312 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: |
1313 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: | |
1314 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: | |
1315 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: | |
52b7d2ce A |
1316 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { |
1317 | plog(LLV_ERROR, LOCATION, NULL, | |
1318 | "Hybrid auth negotiated but peer did not " | |
1319 | "announced as Xauth capable\n"); | |
1320 | return -1; | |
1321 | } | |
1322 | ||
1323 | if (xst->status != XAUTHST_OK) { | |
1324 | plog(LLV_ERROR, LOCATION, NULL, | |
1325 | "Hybrid auth negotiated but peer did not " | |
1326 | "succeed Xauth exchange\n"); | |
1327 | return -1; | |
1328 | } | |
1329 | ||
1330 | return 0; | |
1331 | break; | |
1332 | default: | |
1333 | return 0; | |
1334 | break; | |
1335 | } | |
1336 | ||
1337 | return 0; | |
1338 | } | |
1339 | ||
d1e348cf A |
1340 | int |
1341 | group_check(iph1, grp_list, grp_count) | |
1342 | struct ph1handle *iph1; | |
1343 | char **grp_list; | |
1344 | int grp_count; | |
1345 | { | |
1346 | int res = -1; | |
1347 | int grp_index = 0; | |
1348 | char * usr = NULL; | |
1349 | ||
1350 | /* check for presence of modecfg data */ | |
1351 | ||
1352 | if(iph1->mode_cfg == NULL) { | |
1353 | plog(LLV_ERROR, LOCATION, NULL, | |
1354 | "xauth group specified but modecfg not found\n"); | |
1355 | return res; | |
1356 | } | |
1357 | ||
1358 | /* loop through our group list */ | |
1359 | ||
1360 | for(; grp_index < grp_count; grp_index++) { | |
1361 | ||
1362 | /* check for presence of xauth data */ | |
1363 | ||
1364 | usr = iph1->mode_cfg->xauth.authdata.generic.usr; | |
1365 | ||
1366 | if(usr == NULL) { | |
1367 | plog(LLV_ERROR, LOCATION, NULL, | |
1368 | "xauth group specified but xauth not found\n"); | |
1369 | return res; | |
1370 | } | |
1371 | ||
1372 | /* call appropriate group validation funtion */ | |
1373 | ||
1374 | switch (isakmp_cfg_config.groupsource) { | |
1375 | ||
1376 | case ISAKMP_CFG_GROUP_SYSTEM: | |
1377 | res = xauth_group_system( | |
1378 | usr, | |
1379 | grp_list[grp_index]); | |
1380 | break; | |
1381 | ||
1382 | #ifdef HAVE_LIBLDAP | |
1383 | case ISAKMP_CFG_GROUP_LDAP: | |
1384 | res = xauth_group_ldap( | |
1385 | iph1->mode_cfg->xauth.udn, | |
1386 | grp_list[grp_index]); | |
1387 | break; | |
1388 | #endif | |
1389 | ||
1390 | default: | |
1391 | /* we should never get here */ | |
1392 | plog(LLV_ERROR, LOCATION, NULL, | |
1393 | "Unknown group auth source\n"); | |
1394 | break; | |
1395 | } | |
1396 | ||
1397 | if( !res ) { | |
1398 | plog(LLV_INFO, LOCATION, NULL, | |
1399 | "user \"%s\" is a member of group \"%s\"\n", | |
1400 | usr, | |
1401 | grp_list[grp_index]); | |
1402 | break; | |
1403 | } else { | |
1404 | plog(LLV_INFO, LOCATION, NULL, | |
1405 | "user \"%s\" is not a member of group \"%s\"\n", | |
1406 | usr, | |
1407 | grp_list[grp_index]); | |
1408 | } | |
1409 | } | |
1410 | ||
1411 | return res; | |
1412 | } | |
1413 | ||
52b7d2ce A |
1414 | vchar_t * |
1415 | isakmp_xauth_req(iph1, attr) | |
1416 | struct ph1handle *iph1; | |
1417 | struct isakmp_data *attr; | |
1418 | { | |
1419 | int type; | |
1420 | size_t dlen = 0; | |
1421 | int ashort = 0; | |
1422 | int value = 0; | |
1423 | vchar_t *buffer = NULL; | |
d1e348cf A |
1424 | char* mraw = NULL; |
1425 | vchar_t *mdata = NULL; | |
52b7d2ce A |
1426 | char *data; |
1427 | vchar_t *usr = NULL; | |
1428 | vchar_t *pwd = NULL; | |
1429 | size_t skip = 0; | |
1430 | int freepwd = 0; | |
1431 | ||
1432 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { | |
1433 | plog(LLV_ERROR, LOCATION, NULL, | |
1434 | "Xauth mode config request but peer " | |
1435 | "did not declare itself as Xauth capable\n"); | |
1436 | return NULL; | |
1437 | } | |
1438 | ||
1439 | type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; | |
1440 | ||
1441 | /* Sanity checks */ | |
1442 | switch(type) { | |
1443 | case XAUTH_TYPE: | |
1444 | if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { | |
1445 | plog(LLV_ERROR, LOCATION, NULL, | |
1446 | "Unexpected long XAUTH_TYPE attribute\n"); | |
1447 | return NULL; | |
1448 | } | |
1449 | if (ntohs(attr->lorv) != XAUTH_TYPE_GENERIC) { | |
1450 | plog(LLV_ERROR, LOCATION, NULL, | |
1451 | "Unsupported Xauth authentication %d\n", | |
1452 | ntohs(attr->lorv)); | |
1453 | return NULL; | |
1454 | } | |
1455 | ashort = 1; | |
1456 | dlen = 0; | |
1457 | value = XAUTH_TYPE_GENERIC; | |
1458 | break; | |
1459 | ||
1460 | case XAUTH_USER_NAME: | |
d1e348cf | 1461 | if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) { |
52b7d2ce A |
1462 | plog(LLV_ERROR, LOCATION, NULL, "Xauth performed " |
1463 | "with no login supplied\n"); | |
1464 | return NULL; | |
1465 | } | |
1466 | ||
d1e348cf A |
1467 | dlen = iph1->rmconf->xauth->login->l - 1; |
1468 | iph1->rmconf->xauth->state |= XAUTH_SENT_USERNAME; | |
52b7d2ce A |
1469 | break; |
1470 | ||
1471 | case XAUTH_USER_PASSWORD: | |
d1e348cf A |
1472 | case XAUTH_PASSCODE: |
1473 | if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) | |
52b7d2ce A |
1474 | return NULL; |
1475 | ||
1476 | skip = sizeof(struct ipsecdoi_id_b); | |
d1e348cf A |
1477 | usr = vmalloc(iph1->rmconf->xauth->login->l - 1 + skip); |
1478 | if (usr == NULL) { | |
52b7d2ce A |
1479 | plog(LLV_ERROR, LOCATION, NULL, |
1480 | "Cannot allocate memory\n"); | |
1481 | return NULL; | |
1482 | } | |
52b7d2ce A |
1483 | memset(usr->v, 0, skip); |
1484 | memcpy(usr->v + skip, | |
d1e348cf A |
1485 | iph1->rmconf->xauth->login->v, |
1486 | iph1->rmconf->xauth->login->l - 1); | |
52b7d2ce | 1487 | |
d1e348cf | 1488 | if (iph1->rmconf->xauth->pass) { |
52b7d2ce | 1489 | /* A key given through racoonctl */ |
d1e348cf | 1490 | pwd = iph1->rmconf->xauth->pass; |
52b7d2ce A |
1491 | } else { |
1492 | if ((pwd = getpskbyname(usr)) == NULL) { | |
1493 | plog(LLV_ERROR, LOCATION, NULL, | |
1494 | "No password was found for login %s\n", | |
d1e348cf | 1495 | iph1->rmconf->xauth->login->v); |
52b7d2ce A |
1496 | vfree(usr); |
1497 | return NULL; | |
1498 | } | |
1499 | /* We have to free it before returning */ | |
1500 | freepwd = 1; | |
1501 | } | |
1502 | vfree(usr); | |
1503 | ||
d1e348cf A |
1504 | iph1->rmconf->xauth->state |= XAUTH_SENT_PASSWORD; |
1505 | dlen = pwd->l - 1; | |
52b7d2ce A |
1506 | |
1507 | break; | |
d1e348cf A |
1508 | |
1509 | case XAUTH_MESSAGE: | |
1510 | if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { | |
1511 | dlen = ntohs(attr->lorv); | |
1512 | if (dlen > 0) { | |
1513 | mraw = (char*)(attr + 1); | |
1514 | if ((mdata = vmalloc(dlen)) == NULL) { | |
1515 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1516 | "Cannot allocate memory\n"); | |
1517 | return NULL; | |
1518 | } | |
1519 | memcpy(mdata->v, mraw, mdata->l); | |
1520 | plog(LLV_NOTIFY,LOCATION, iph1->remote, | |
1521 | "XAUTH Message: '%s'.\n", | |
1522 | binsanitize(mdata->v, mdata->l)); | |
1523 | vfree(mdata); | |
1524 | } | |
1525 | } | |
1526 | return NULL; | |
52b7d2ce A |
1527 | default: |
1528 | plog(LLV_WARNING, LOCATION, NULL, | |
d1e348cf | 1529 | "Ignored attribute %s\n", s_isakmp_cfg_type(type)); |
52b7d2ce A |
1530 | return NULL; |
1531 | break; | |
1532 | } | |
1533 | ||
1534 | if ((buffer = vmalloc(sizeof(*attr) + dlen)) == NULL) { | |
1535 | plog(LLV_ERROR, LOCATION, NULL, | |
1536 | "Cannot allocate memory\n"); | |
1537 | goto out; | |
1538 | } | |
1539 | ||
1540 | attr = (struct isakmp_data *)buffer->v; | |
1541 | if (ashort) { | |
1542 | attr->type = htons(type | ISAKMP_GEN_TV); | |
1543 | attr->lorv = htons(value); | |
1544 | goto out; | |
1545 | } | |
1546 | ||
1547 | attr->type = htons(type | ISAKMP_GEN_TLV); | |
1548 | attr->lorv = htons(dlen); | |
1549 | data = (char *)(attr + 1); | |
1550 | ||
1551 | switch(type) { | |
1552 | case XAUTH_USER_NAME: | |
d1e348cf A |
1553 | /* |
1554 | * iph1->rmconf->xauth->login->v is valid, | |
1555 | * we just checked it in the previous switch case | |
1556 | */ | |
1557 | memcpy(data, iph1->rmconf->xauth->login->v, dlen); | |
52b7d2ce A |
1558 | break; |
1559 | case XAUTH_USER_PASSWORD: | |
d1e348cf | 1560 | case XAUTH_PASSCODE: |
52b7d2ce A |
1561 | memcpy(data, pwd->v, dlen); |
1562 | break; | |
1563 | default: | |
1564 | break; | |
1565 | } | |
1566 | ||
1567 | out: | |
1568 | if (freepwd) | |
1569 | vfree(pwd); | |
1570 | ||
1571 | return buffer; | |
1572 | } | |
1573 | ||
1574 | vchar_t * | |
1575 | isakmp_xauth_set(iph1, attr) | |
1576 | struct ph1handle *iph1; | |
1577 | struct isakmp_data *attr; | |
1578 | { | |
1579 | int type; | |
1580 | vchar_t *buffer = NULL; | |
1581 | char *data; | |
d1e348cf A |
1582 | struct xauth_state *xst; |
1583 | size_t dlen = 0; | |
1584 | char* mraw = NULL; | |
1585 | vchar_t *mdata = NULL; | |
52b7d2ce A |
1586 | |
1587 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { | |
d1e348cf A |
1588 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
1589 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
1590 | CONSTSTR("XAUTH is not supported by peer"), | |
1591 | CONSTSTR("XAUTH dropped (not supported by peer)")); | |
52b7d2ce A |
1592 | plog(LLV_ERROR, LOCATION, NULL, |
1593 | "Xauth mode config set but peer " | |
1594 | "did not declare itself as Xauth capable\n"); | |
1595 | return NULL; | |
1596 | } | |
1597 | ||
1598 | type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; | |
1599 | ||
1600 | switch(type) { | |
1601 | case XAUTH_STATUS: | |
d1e348cf A |
1602 | /* |
1603 | * We should only receive ISAKMP mode_cfg SET XAUTH_STATUS | |
1604 | * when running as a client (initiator). | |
1605 | */ | |
1606 | xst = &iph1->mode_cfg->xauth; | |
1607 | switch(AUTHMETHOD(iph1)) { | |
1608 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: | |
1609 | if (!iph1->is_rekey) { | |
1610 | IPSECSESSIONTRACEREVENT(iph1->parent_session, | |
1611 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
1612 | CONSTSTR("Unexpected XAUTH Status"), | |
1613 | CONSTSTR("Xauth dropped (unexpected Xauth status)... not a phase1 rekey")); | |
1614 | plog(LLV_ERROR, LOCATION, NULL, | |
1615 | "Unexpected XAUTH_STATUS_OK... not a phase1 rekey\n"); | |
1616 | return NULL; | |
1617 | } | |
1618 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: | |
1619 | case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I: | |
1620 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: | |
1621 | /* Not implemented ... */ | |
1622 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: | |
1623 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: | |
1624 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: | |
1625 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: | |
1626 | break; | |
1627 | default: | |
1628 | IPSECSESSIONTRACEREVENT(iph1->parent_session, | |
1629 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
1630 | CONSTSTR("Unexpected XAUTH Status"), | |
1631 | CONSTSTR("Xauth dropped (unexpected Xauth status)")); | |
1632 | plog(LLV_ERROR, LOCATION, NULL, | |
1633 | "Unexpected XAUTH_STATUS_OK\n"); | |
1634 | return NULL; | |
1635 | break; | |
1636 | } | |
1637 | ||
52b7d2ce A |
1638 | /* If we got a failure, delete iph1 */ |
1639 | if (ntohs(attr->lorv) != XAUTH_STATUS_OK) { | |
d1e348cf A |
1640 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
1641 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_FAIL, | |
1642 | CONSTSTR("XAUTH Status is not OK"), | |
1643 | CONSTSTR("Xauth Failed (status not ok)")); | |
52b7d2ce A |
1644 | plog(LLV_ERROR, LOCATION, NULL, |
1645 | "Xauth authentication failed\n"); | |
1646 | ||
1647 | EVT_PUSH(iph1->local, iph1->remote, | |
1648 | EVTT_XAUTH_FAILED, NULL); | |
d1e348cf A |
1649 | |
1650 | vpncontrol_notify_ike_failed(VPNCTL_NTYPE_AUTHENTICATION_FAILED, FROM_LOCAL, | |
1651 | ((struct sockaddr_in*)iph1->remote)->sin_addr.s_addr, 0, NULL); | |
52b7d2ce A |
1652 | |
1653 | iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1; | |
1654 | } else { | |
d1e348cf A |
1655 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
1656 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_SUCC, | |
1657 | CONSTSTR("XAUTH Status is OK"), | |
1658 | CONSTSTR(NULL)); | |
1659 | EVT_PUSH(iph1->local, iph1->remote, | |
1660 | EVTT_XAUTH_SUCCESS, NULL); | |
1661 | if (iph1->is_rekey) { | |
1662 | xst->status = XAUTHST_OK; | |
1663 | } | |
52b7d2ce A |
1664 | } |
1665 | ||
1666 | ||
1667 | /* We acknowledge it */ | |
1668 | break; | |
d1e348cf A |
1669 | case XAUTH_MESSAGE: |
1670 | if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { | |
1671 | dlen = ntohs(attr->lorv); | |
1672 | if (dlen > 0) { | |
1673 | mraw = (char*)(attr + 1); | |
1674 | if ((mdata = vmalloc(dlen)) == NULL) { | |
1675 | plog(LLV_ERROR, LOCATION, iph1->remote, | |
1676 | "Cannot allocate memory\n"); | |
1677 | return NULL; | |
1678 | } | |
1679 | memcpy(mdata->v, mraw, mdata->l); | |
1680 | plog(LLV_NOTIFY,LOCATION, iph1->remote, | |
1681 | "XAUTH Message: '%s'.\n", | |
1682 | binsanitize(mdata->v, mdata->l)); | |
1683 | vfree(mdata); | |
1684 | } | |
1685 | } | |
1686 | ||
52b7d2ce | 1687 | default: |
d1e348cf A |
1688 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
1689 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
1690 | CONSTSTR("ignored attribute"), | |
1691 | CONSTSTR("Xauth dropped (ignored attribute)")); | |
52b7d2ce | 1692 | plog(LLV_WARNING, LOCATION, NULL, |
d1e348cf | 1693 | "Ignored attribute %s\n", s_isakmp_cfg_type(type)); |
52b7d2ce A |
1694 | return NULL; |
1695 | break; | |
1696 | } | |
1697 | ||
1698 | if ((buffer = vmalloc(sizeof(*attr))) == NULL) { | |
d1e348cf A |
1699 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
1700 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
1701 | CONSTSTR("Failed to allocate attribute"), | |
1702 | CONSTSTR("Xauth dropped (failed to allocate attribute)")); | |
52b7d2ce A |
1703 | plog(LLV_ERROR, LOCATION, NULL, |
1704 | "Cannot allocate memory\n"); | |
1705 | return NULL; | |
1706 | } | |
1707 | ||
1708 | attr = (struct isakmp_data *)buffer->v; | |
1709 | attr->type = htons(type | ISAKMP_GEN_TV); | |
1710 | attr->lorv = htons(0); | |
1711 | ||
1712 | return buffer; | |
1713 | } | |
1714 | ||
1715 | ||
1716 | void | |
1717 | xauth_rmstate(xst) | |
1718 | struct xauth_state *xst; | |
1719 | { | |
1720 | switch (xst->authtype) { | |
1721 | case XAUTH_TYPE_GENERIC: | |
1722 | if (xst->authdata.generic.usr) | |
1723 | racoon_free(xst->authdata.generic.usr); | |
1724 | ||
1725 | if (xst->authdata.generic.pwd) | |
1726 | racoon_free(xst->authdata.generic.pwd); | |
1727 | ||
1728 | break; | |
1729 | ||
1730 | case XAUTH_TYPE_CHAP: | |
1731 | case XAUTH_TYPE_OTP: | |
1732 | case XAUTH_TYPE_SKEY: | |
1733 | plog(LLV_WARNING, LOCATION, NULL, | |
1734 | "Unsupported authtype %d\n", xst->authtype); | |
1735 | break; | |
1736 | ||
1737 | default: | |
1738 | plog(LLV_WARNING, LOCATION, NULL, | |
1739 | "Unexpected authtype %d\n", xst->authtype); | |
1740 | break; | |
1741 | } | |
1742 | ||
d1e348cf A |
1743 | #ifdef HAVE_LIBLDAP |
1744 | if (xst->udn != NULL) | |
1745 | racoon_free(xst->udn); | |
1746 | #endif | |
52b7d2ce A |
1747 | return; |
1748 | } | |
1749 | ||
d1e348cf A |
1750 | int |
1751 | xauth_rmconf_used(xauth_rmconf) | |
1752 | struct xauth_rmconf **xauth_rmconf; | |
1753 | { | |
1754 | if (*xauth_rmconf == NULL) { | |
1755 | *xauth_rmconf = racoon_malloc(sizeof(**xauth_rmconf)); | |
1756 | if (*xauth_rmconf == NULL) { | |
1757 | plog(LLV_ERROR, LOCATION, NULL, | |
1758 | "xauth_rmconf_used: malloc failed\n"); | |
1759 | return -1; | |
1760 | } | |
1761 | ||
1762 | (*xauth_rmconf)->login = NULL; | |
1763 | (*xauth_rmconf)->pass = NULL; | |
1764 | (*xauth_rmconf)->state = 0; | |
1765 | } else { | |
1766 | if ((*xauth_rmconf)->login) { | |
1767 | vfree((*xauth_rmconf)->login); | |
1768 | (*xauth_rmconf)->login = NULL; | |
1769 | } | |
1770 | if ((*xauth_rmconf)->pass != NULL) { | |
1771 | vfree((*xauth_rmconf)->pass); | |
1772 | (*xauth_rmconf)->pass = NULL; | |
1773 | } | |
1774 | (*xauth_rmconf)->state = 0; | |
1775 | } | |
1776 | ||
1777 | return 0; | |
1778 | } | |
1779 | ||
1780 | void | |
1781 | xauth_rmconf_delete(xauth_rmconf) | |
1782 | struct xauth_rmconf **xauth_rmconf; | |
1783 | { | |
1784 | if (*xauth_rmconf != NULL) { | |
1785 | if ((*xauth_rmconf)->login != NULL) | |
1786 | vfree((*xauth_rmconf)->login); | |
1787 | if ((*xauth_rmconf)->pass != NULL) | |
1788 | vfree((*xauth_rmconf)->pass); | |
1789 | ||
1790 | racoon_free(*xauth_rmconf); | |
1791 | *xauth_rmconf = NULL; | |
1792 | } | |
1793 | ||
1794 | return; | |
1795 | } |