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