]>
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 | |
65 | #ifdef HAVE_SHADOW_H | |
66 | #include <shadow.h> | |
67 | #endif | |
52b7d2ce A |
68 | |
69 | #include "var.h" | |
70 | #include "misc.h" | |
71 | #include "vmbuf.h" | |
72 | #include "plog.h" | |
73 | #include "sockmisc.h" | |
74 | #include "schedule.h" | |
75 | #include "debug.h" | |
65c25746 | 76 | #include "fsm.h" |
52b7d2ce A |
77 | |
78 | #include "crypto_openssl.h" | |
79 | #include "isakmp_var.h" | |
80 | #include "isakmp.h" | |
52b7d2ce A |
81 | #include "handler.h" |
82 | #include "throttle.h" | |
83 | #include "remoteconf.h" | |
84 | #include "isakmp_inf.h" | |
85 | #include "isakmp_xauth.h" | |
86 | #include "isakmp_unity.h" | |
87 | #include "isakmp_cfg.h" | |
88 | #include "strnames.h" | |
89 | #include "ipsec_doi.h" | |
90 | #include "remoteconf.h" | |
91 | #include "localconf.h" | |
d1e348cf A |
92 | #include "vpn_control.h" |
93 | #include "vpn_control_var.h" | |
94 | #include "ipsecSessionTracer.h" | |
95 | #include "ipsecMessageTracer.h" | |
52b7d2ce | 96 | |
52b7d2ce A |
97 | |
98 | void | |
99 | xauth_sendreq(iph1) | |
65c25746 | 100 | phase1_handle_t *iph1; |
52b7d2ce A |
101 | { |
102 | vchar_t *buffer; | |
103 | struct isakmp_pl_attr *attr; | |
104 | struct isakmp_data *typeattr; | |
105 | struct isakmp_data *usrattr; | |
106 | struct isakmp_data *pwdattr; | |
107 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
108 | size_t tlen; | |
109 | ||
110 | /* Status checks */ | |
65c25746 A |
111 | if (!FSM_STATE_IS_ESTABLISHED(iph1->status)) { |
112 | plog(ASL_LEVEL_ERR, | |
52b7d2ce A |
113 | "Xauth request while phase 1 is not completed\n"); |
114 | return; | |
115 | } | |
116 | ||
117 | if (xst->status != XAUTHST_NOTYET) { | |
65c25746 | 118 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
119 | "Xauth request whith Xauth state %d\n", xst->status); |
120 | return; | |
121 | } | |
122 | ||
7ebaebe2 | 123 | plog(ASL_LEVEL_NOTICE, "Sending Xauth request\n"); |
52b7d2ce A |
124 | |
125 | tlen = sizeof(*attr) + | |
126 | + sizeof(*typeattr) + | |
127 | + sizeof(*usrattr) + | |
128 | + sizeof(*pwdattr); | |
129 | ||
130 | if ((buffer = vmalloc(tlen)) == NULL) { | |
65c25746 | 131 | plog(ASL_LEVEL_ERR, "Cannot allocate buffer\n"); |
52b7d2ce A |
132 | return; |
133 | } | |
134 | ||
135 | attr = (struct isakmp_pl_attr *)buffer->v; | |
136 | memset(attr, 0, tlen); | |
137 | ||
138 | attr->h.len = htons(tlen); | |
139 | attr->type = ISAKMP_CFG_REQUEST; | |
140 | attr->id = htons(eay_random()); | |
141 | ||
142 | typeattr = (struct isakmp_data *)(attr + 1); | |
143 | typeattr->type = htons(XAUTH_TYPE | ISAKMP_GEN_TV); | |
144 | typeattr->lorv = htons(XAUTH_TYPE_GENERIC); | |
145 | ||
146 | usrattr = (struct isakmp_data *)(typeattr + 1); | |
147 | usrattr->type = htons(XAUTH_USER_NAME | ISAKMP_GEN_TLV); | |
148 | usrattr->lorv = htons(0); | |
149 | ||
150 | pwdattr = (struct isakmp_data *)(usrattr + 1); | |
151 | pwdattr->type = htons(XAUTH_USER_PASSWORD | ISAKMP_GEN_TLV); | |
152 | pwdattr->lorv = htons(0); | |
153 | ||
154 | isakmp_cfg_send(iph1, buffer, | |
d1e348cf | 155 | ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL); |
52b7d2ce A |
156 | |
157 | vfree(buffer); | |
158 | ||
159 | xst->status = XAUTHST_REQSENT; | |
160 | ||
161 | return; | |
162 | } | |
163 | ||
d1e348cf | 164 | int |
52b7d2ce | 165 | xauth_attr_reply(iph1, attr, id) |
65c25746 | 166 | phase1_handle_t *iph1; |
52b7d2ce A |
167 | struct isakmp_data *attr; |
168 | int id; | |
169 | { | |
170 | char **outlet = NULL; | |
171 | size_t alen = 0; | |
172 | int type; | |
173 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
174 | ||
175 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { | |
65c25746 | 176 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
177 | "Xauth reply but peer did not declare " |
178 | "itself as Xauth capable\n"); | |
d1e348cf | 179 | return -1; |
52b7d2ce A |
180 | } |
181 | ||
182 | if (xst->status != XAUTHST_REQSENT) { | |
65c25746 | 183 | plog(ASL_LEVEL_ERR, |
52b7d2ce | 184 | "Xauth reply while Xauth state is %d\n", xst->status); |
d1e348cf | 185 | return -1; |
52b7d2ce A |
186 | } |
187 | ||
188 | type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; | |
189 | switch (type) { | |
190 | case XAUTH_TYPE: | |
191 | switch (ntohs(attr->lorv)) { | |
192 | case XAUTH_TYPE_GENERIC: | |
193 | xst->authtype = XAUTH_TYPE_GENERIC; | |
194 | break; | |
195 | default: | |
65c25746 | 196 | plog(ASL_LEVEL_WARNING, |
52b7d2ce A |
197 | "Unexpected authentication type %d\n", |
198 | ntohs(type)); | |
d1e348cf | 199 | return -1; |
52b7d2ce A |
200 | } |
201 | break; | |
202 | ||
203 | case XAUTH_USER_NAME: | |
204 | outlet = &xst->authdata.generic.usr; | |
205 | break; | |
206 | ||
207 | case XAUTH_USER_PASSWORD: | |
208 | outlet = &xst->authdata.generic.pwd; | |
209 | break; | |
210 | ||
211 | default: | |
65c25746 | 212 | plog(ASL_LEVEL_WARNING, |
52b7d2ce A |
213 | "ignored Xauth attribute %d\n", type); |
214 | break; | |
215 | } | |
216 | ||
217 | if (outlet != NULL) { | |
218 | alen = ntohs(attr->lorv); | |
219 | ||
d1e348cf | 220 | if ((*outlet = racoon_realloc(*outlet, alen + 1)) == NULL) { |
65c25746 | 221 | plog(ASL_LEVEL_ERR, |
52b7d2ce | 222 | "Cannot allocate memory for Xauth Data\n"); |
d1e348cf | 223 | return -1; |
52b7d2ce A |
224 | } |
225 | ||
226 | memcpy(*outlet, attr + 1, alen); | |
227 | (*outlet)[alen] = '\0'; | |
228 | outlet = NULL; | |
229 | } | |
230 | ||
231 | ||
232 | if ((xst->authdata.generic.usr != NULL) && | |
233 | (xst->authdata.generic.pwd != NULL)) { | |
234 | int port; | |
235 | int res; | |
236 | char *usr = xst->authdata.generic.usr; | |
237 | char *pwd = xst->authdata.generic.pwd; | |
238 | time_t throttle_delay = 0; | |
239 | ||
240 | #if 0 /* Real debug, don't do that at home */ | |
65c25746 | 241 | plog(ASL_LEVEL_DEBUG, |
52b7d2ce A |
242 | "Got username \"%s\", password \"%s\"\n", usr, pwd); |
243 | #endif | |
d1e348cf | 244 | strlcpy(iph1->mode_cfg->login, usr, sizeof(iph1->mode_cfg->login)); |
52b7d2ce A |
245 | |
246 | res = -1; | |
247 | if ((port = isakmp_cfg_getport(iph1)) == -1) { | |
65c25746 | 248 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
249 | "Port pool depleted\n"); |
250 | goto skip_auth; | |
251 | } | |
252 | ||
253 | switch (isakmp_cfg_config.authsource) { | |
254 | case ISAKMP_CFG_AUTH_SYSTEM: | |
e8d9021d | 255 | res = xauth_login_system(usr, pwd); |
52b7d2ce | 256 | break; |
65c25746 | 257 | |
52b7d2ce | 258 | default: |
65c25746 | 259 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
260 | "Unexpected authentication source\n"); |
261 | res = -1; | |
262 | break; | |
263 | } | |
264 | ||
d1e348cf A |
265 | /* |
266 | * Optional group authentication | |
267 | */ | |
268 | if (!res && (isakmp_cfg_config.groupcount)) | |
269 | res = group_check(iph1, | |
270 | isakmp_cfg_config.grouplist, | |
271 | isakmp_cfg_config.groupcount); | |
272 | ||
52b7d2ce A |
273 | /* |
274 | * On failure, throttle the connexion for the remote host | |
275 | * in order to make password attacks more difficult. | |
276 | */ | |
277 | throttle_delay = throttle_host(iph1->remote, res) - time(NULL); | |
278 | if (throttle_delay > 0) { | |
279 | char *str; | |
280 | ||
85f41bec | 281 | str = saddrwop2str((struct sockaddr *)iph1->remote); |
52b7d2ce | 282 | |
65c25746 | 283 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
284 | "Throttling in action for %s: delay %lds\n", |
285 | str, (unsigned long)throttle_delay); | |
286 | res = -1; | |
287 | } else { | |
288 | throttle_delay = 0; | |
289 | } | |
290 | ||
291 | skip_auth: | |
292 | if (throttle_delay != 0) { | |
293 | struct xauth_reply_arg *xra; | |
294 | ||
295 | if ((xra = racoon_malloc(sizeof(*xra))) == NULL) { | |
65c25746 | 296 | plog(ASL_LEVEL_ERR, |
52b7d2ce | 297 | "malloc failed, bypass throttling\n"); |
d1e348cf | 298 | return xauth_reply(iph1, port, id, res); |
52b7d2ce A |
299 | } |
300 | ||
301 | /* | |
302 | * We need to store the ph1, but it might have | |
303 | * disapeared when xauth_reply is called, so | |
304 | * store the index instead. | |
305 | */ | |
306 | xra->index = iph1->index; | |
307 | xra->port = port; | |
308 | xra->id = id; | |
309 | xra->res = res; | |
310 | sched_new(throttle_delay, xauth_reply_stub, xra); | |
311 | } else { | |
d1e348cf | 312 | return xauth_reply(iph1, port, id, res); |
52b7d2ce A |
313 | } |
314 | } | |
315 | ||
d1e348cf | 316 | return 0; |
52b7d2ce A |
317 | } |
318 | ||
319 | void | |
320 | xauth_reply_stub(args) | |
321 | void *args; | |
322 | { | |
323 | struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args; | |
65c25746 | 324 | phase1_handle_t *iph1; |
52b7d2ce | 325 | |
65c25746 | 326 | if ((iph1 = ike_session_getph1byindex(NULL, &xra->index)) != NULL) |
d1e348cf | 327 | (void)xauth_reply(iph1, xra->port, xra->id, xra->res); |
52b7d2ce | 328 | else |
65c25746 | 329 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
330 | "Delayed Xauth reply: phase 1 no longer exists.\n"); |
331 | ||
332 | racoon_free(xra); | |
333 | return; | |
334 | } | |
335 | ||
d1e348cf | 336 | int |
52b7d2ce | 337 | xauth_reply(iph1, port, id, res) |
65c25746 | 338 | phase1_handle_t *iph1; |
52b7d2ce A |
339 | int port; |
340 | int id; | |
341 | { | |
342 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
343 | char *usr = xst->authdata.generic.usr; | |
344 | ||
e8d9021d | 345 | if (iph1->is_dying) { |
7ebaebe2 | 346 | plog(ASL_LEVEL_NOTICE, |
e8d9021d A |
347 | "dropped login for user \"%s\"\n", usr); |
348 | return -1; | |
349 | } | |
350 | ||
52b7d2ce A |
351 | if (res != 0) { |
352 | if (port != -1) | |
353 | isakmp_cfg_putport(iph1, port); | |
354 | ||
7ebaebe2 | 355 | plog(ASL_LEVEL_NOTICE, |
52b7d2ce A |
356 | "login failed for user \"%s\"\n", usr); |
357 | ||
358 | xauth_sendstatus(iph1, XAUTH_STATUS_FAIL, id); | |
359 | xst->status = XAUTHST_NOTYET; | |
360 | ||
361 | /* Delete Phase 1 SA */ | |
65c25746 | 362 | if (FSM_STATE_IS_ESTABLISHED(iph1->status)) |
52b7d2ce | 363 | isakmp_info_send_d1(iph1); |
47612122 | 364 | isakmp_ph1expire(iph1); |
52b7d2ce | 365 | |
d1e348cf | 366 | return -1; |
52b7d2ce A |
367 | } |
368 | ||
369 | xst->status = XAUTHST_OK; | |
7ebaebe2 | 370 | plog(ASL_LEVEL_NOTICE, |
52b7d2ce A |
371 | "login succeeded for user \"%s\"\n", usr); |
372 | ||
373 | xauth_sendstatus(iph1, XAUTH_STATUS_OK, id); | |
374 | ||
d1e348cf | 375 | return 0; |
52b7d2ce A |
376 | } |
377 | ||
378 | void | |
379 | xauth_sendstatus(iph1, status, id) | |
65c25746 | 380 | phase1_handle_t *iph1; |
52b7d2ce A |
381 | int status; |
382 | int id; | |
383 | { | |
384 | vchar_t *buffer; | |
385 | struct isakmp_pl_attr *attr; | |
386 | struct isakmp_data *stattr; | |
387 | size_t tlen; | |
388 | ||
389 | tlen = sizeof(*attr) + | |
390 | + sizeof(*stattr); | |
391 | ||
392 | if ((buffer = vmalloc(tlen)) == NULL) { | |
65c25746 | 393 | plog(ASL_LEVEL_ERR, "Cannot allocate buffer\n"); |
52b7d2ce A |
394 | return; |
395 | } | |
396 | ||
397 | attr = (struct isakmp_pl_attr *)buffer->v; | |
398 | memset(attr, 0, tlen); | |
399 | ||
400 | attr->h.len = htons(tlen); | |
401 | attr->type = ISAKMP_CFG_SET; | |
402 | attr->id = htons(id); | |
403 | ||
404 | stattr = (struct isakmp_data *)(attr + 1); | |
405 | stattr->type = htons(XAUTH_STATUS | ISAKMP_GEN_TV); | |
406 | stattr->lorv = htons(status); | |
407 | ||
408 | isakmp_cfg_send(iph1, buffer, | |
d1e348cf | 409 | ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL); |
52b7d2ce A |
410 | |
411 | vfree(buffer); | |
412 | ||
413 | return; | |
414 | } | |
415 | ||
d1e348cf | 416 | |
52b7d2ce A |
417 | int |
418 | xauth_login_system(usr, pwd) | |
419 | char *usr; | |
420 | char *pwd; | |
421 | { | |
422 | struct passwd *pw; | |
423 | char *cryptpwd; | |
424 | char *syscryptpwd; | |
425 | #ifdef HAVE_SHADOW_H | |
426 | struct spwd *spw; | |
427 | ||
428 | if ((spw = getspnam(usr)) == NULL) | |
429 | return -1; | |
430 | ||
431 | syscryptpwd = spw->sp_pwdp; | |
432 | #endif | |
433 | ||
434 | if ((pw = getpwnam(usr)) == NULL) | |
435 | return -1; | |
436 | ||
437 | #ifndef HAVE_SHADOW_H | |
438 | syscryptpwd = pw->pw_passwd; | |
439 | #endif | |
440 | ||
441 | /* No root login. Ever. */ | |
442 | if (pw->pw_uid == 0) | |
443 | return -1; | |
444 | ||
445 | if ((cryptpwd = crypt(pwd, syscryptpwd)) == NULL) | |
446 | return -1; | |
447 | ||
448 | if (strcmp(cryptpwd, syscryptpwd) == 0) | |
449 | return 0; | |
450 | ||
451 | return -1; | |
452 | } | |
453 | ||
d1e348cf A |
454 | int |
455 | xauth_group_system(usr, grp) | |
456 | char * usr; | |
457 | char * grp; | |
458 | { | |
459 | struct group * gr; | |
460 | char * member; | |
461 | int index = 0; | |
462 | ||
463 | gr = getgrnam(grp); | |
464 | if (gr == NULL) { | |
65c25746 | 465 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
466 | "the system group name \'%s\' is unknown\n", |
467 | grp); | |
468 | return -1; | |
469 | } | |
470 | ||
471 | while ((member = gr->gr_mem[index++])!=NULL) { | |
472 | if (!strcmp(member,usr)) { | |
7ebaebe2 | 473 | plog(ASL_LEVEL_NOTICE, |
d1e348cf A |
474 | "membership validated\n"); |
475 | return 0; | |
476 | } | |
477 | } | |
478 | ||
479 | return -1; | |
480 | } | |
481 | ||
52b7d2ce A |
482 | int |
483 | xauth_check(iph1) | |
65c25746 | 484 | phase1_handle_t *iph1; |
52b7d2ce A |
485 | { |
486 | struct xauth_state *xst = &iph1->mode_cfg->xauth; | |
487 | ||
d1e348cf A |
488 | /* |
489 | * Only the server side (edge device) really check for Xauth | |
490 | * status. It does it if the chose authmethod is using Xauth. | |
491 | * On the client side (roadwarrior), we don't check anything. | |
492 | */ | |
493 | switch (AUTHMETHOD(iph1)) { | |
494 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: | |
495 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: | |
496 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: | |
52b7d2ce | 497 | /* The following are not yet implemented */ |
d1e348cf A |
498 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: |
499 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: | |
52b7d2ce | 500 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { |
65c25746 | 501 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
502 | "Hybrid auth negotiated but peer did not " |
503 | "announced as Xauth capable\n"); | |
504 | return -1; | |
505 | } | |
506 | ||
507 | if (xst->status != XAUTHST_OK) { | |
65c25746 | 508 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
509 | "Hybrid auth negotiated but peer did not " |
510 | "succeed Xauth exchange\n"); | |
511 | return -1; | |
512 | } | |
513 | ||
514 | return 0; | |
515 | break; | |
516 | default: | |
517 | return 0; | |
518 | break; | |
519 | } | |
520 | ||
521 | return 0; | |
522 | } | |
523 | ||
d1e348cf A |
524 | int |
525 | group_check(iph1, grp_list, grp_count) | |
65c25746 | 526 | phase1_handle_t *iph1; |
d1e348cf A |
527 | char **grp_list; |
528 | int grp_count; | |
529 | { | |
530 | int res = -1; | |
531 | int grp_index = 0; | |
532 | char * usr = NULL; | |
533 | ||
534 | /* check for presence of modecfg data */ | |
535 | ||
536 | if(iph1->mode_cfg == NULL) { | |
65c25746 | 537 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
538 | "xauth group specified but modecfg not found\n"); |
539 | return res; | |
540 | } | |
541 | ||
542 | /* loop through our group list */ | |
543 | ||
544 | for(; grp_index < grp_count; grp_index++) { | |
545 | ||
546 | /* check for presence of xauth data */ | |
547 | ||
548 | usr = iph1->mode_cfg->xauth.authdata.generic.usr; | |
549 | ||
550 | if(usr == NULL) { | |
65c25746 | 551 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
552 | "xauth group specified but xauth not found\n"); |
553 | return res; | |
554 | } | |
555 | ||
556 | /* call appropriate group validation funtion */ | |
557 | ||
558 | switch (isakmp_cfg_config.groupsource) { | |
559 | ||
560 | case ISAKMP_CFG_GROUP_SYSTEM: | |
561 | res = xauth_group_system( | |
562 | usr, | |
563 | grp_list[grp_index]); | |
564 | break; | |
565 | ||
d1e348cf A |
566 | default: |
567 | /* we should never get here */ | |
65c25746 | 568 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
569 | "Unknown group auth source\n"); |
570 | break; | |
571 | } | |
572 | ||
573 | if( !res ) { | |
7ebaebe2 | 574 | plog(ASL_LEVEL_NOTICE, |
d1e348cf A |
575 | "user \"%s\" is a member of group \"%s\"\n", |
576 | usr, | |
577 | grp_list[grp_index]); | |
578 | break; | |
579 | } else { | |
7ebaebe2 | 580 | plog(ASL_LEVEL_NOTICE, |
d1e348cf A |
581 | "user \"%s\" is not a member of group \"%s\"\n", |
582 | usr, | |
583 | grp_list[grp_index]); | |
584 | } | |
585 | } | |
586 | ||
587 | return res; | |
588 | } | |
589 | ||
52b7d2ce A |
590 | vchar_t * |
591 | isakmp_xauth_req(iph1, attr) | |
65c25746 | 592 | phase1_handle_t *iph1; |
52b7d2ce A |
593 | struct isakmp_data *attr; |
594 | { | |
595 | int type; | |
596 | size_t dlen = 0; | |
597 | int ashort = 0; | |
598 | int value = 0; | |
599 | vchar_t *buffer = NULL; | |
d1e348cf A |
600 | char* mraw = NULL; |
601 | vchar_t *mdata = NULL; | |
52b7d2ce A |
602 | char *data; |
603 | vchar_t *usr = NULL; | |
604 | vchar_t *pwd = NULL; | |
605 | size_t skip = 0; | |
606 | int freepwd = 0; | |
607 | ||
608 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { | |
65c25746 | 609 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
610 | "Xauth mode config request but peer " |
611 | "did not declare itself as Xauth capable\n"); | |
612 | return NULL; | |
613 | } | |
614 | ||
615 | type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; | |
616 | ||
617 | /* Sanity checks */ | |
618 | switch(type) { | |
619 | case XAUTH_TYPE: | |
620 | if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { | |
65c25746 | 621 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
622 | "Unexpected long XAUTH_TYPE attribute\n"); |
623 | return NULL; | |
624 | } | |
625 | if (ntohs(attr->lorv) != XAUTH_TYPE_GENERIC) { | |
65c25746 | 626 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
627 | "Unsupported Xauth authentication %d\n", |
628 | ntohs(attr->lorv)); | |
629 | return NULL; | |
630 | } | |
631 | ashort = 1; | |
632 | dlen = 0; | |
633 | value = XAUTH_TYPE_GENERIC; | |
634 | break; | |
635 | ||
636 | case XAUTH_USER_NAME: | |
d1e348cf | 637 | if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) { |
65c25746 | 638 | plog(ASL_LEVEL_ERR, "Xauth performed " |
52b7d2ce A |
639 | "with no login supplied\n"); |
640 | return NULL; | |
641 | } | |
642 | ||
d1e348cf A |
643 | dlen = iph1->rmconf->xauth->login->l - 1; |
644 | iph1->rmconf->xauth->state |= XAUTH_SENT_USERNAME; | |
52b7d2ce A |
645 | break; |
646 | ||
647 | case XAUTH_USER_PASSWORD: | |
d1e348cf A |
648 | case XAUTH_PASSCODE: |
649 | if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) | |
52b7d2ce A |
650 | return NULL; |
651 | ||
652 | skip = sizeof(struct ipsecdoi_id_b); | |
d1e348cf A |
653 | usr = vmalloc(iph1->rmconf->xauth->login->l - 1 + skip); |
654 | if (usr == NULL) { | |
65c25746 | 655 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
656 | "Cannot allocate memory\n"); |
657 | return NULL; | |
658 | } | |
52b7d2ce A |
659 | memset(usr->v, 0, skip); |
660 | memcpy(usr->v + skip, | |
d1e348cf A |
661 | iph1->rmconf->xauth->login->v, |
662 | iph1->rmconf->xauth->login->l - 1); | |
52b7d2ce | 663 | |
d1e348cf | 664 | if (iph1->rmconf->xauth->pass) { |
52b7d2ce | 665 | /* A key given through racoonctl */ |
d1e348cf | 666 | pwd = iph1->rmconf->xauth->pass; |
52b7d2ce A |
667 | } else { |
668 | if ((pwd = getpskbyname(usr)) == NULL) { | |
65c25746 | 669 | plog(ASL_LEVEL_ERR, |
52b7d2ce | 670 | "No password was found for login %s\n", |
d1e348cf | 671 | iph1->rmconf->xauth->login->v); |
52b7d2ce A |
672 | vfree(usr); |
673 | return NULL; | |
674 | } | |
675 | /* We have to free it before returning */ | |
676 | freepwd = 1; | |
677 | } | |
678 | vfree(usr); | |
679 | ||
d1e348cf A |
680 | iph1->rmconf->xauth->state |= XAUTH_SENT_PASSWORD; |
681 | dlen = pwd->l - 1; | |
52b7d2ce A |
682 | |
683 | break; | |
d1e348cf A |
684 | |
685 | case XAUTH_MESSAGE: | |
686 | if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { | |
687 | dlen = ntohs(attr->lorv); | |
688 | if (dlen > 0) { | |
689 | mraw = (char*)(attr + 1); | |
690 | if ((mdata = vmalloc(dlen)) == NULL) { | |
65c25746 | 691 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
692 | "Cannot allocate memory\n"); |
693 | return NULL; | |
694 | } | |
695 | memcpy(mdata->v, mraw, mdata->l); | |
65c25746 | 696 | plog(ASL_LEVEL_NOTICE, "XAUTH Message: '%s'.\n", |
d1e348cf A |
697 | binsanitize(mdata->v, mdata->l)); |
698 | vfree(mdata); | |
699 | } | |
700 | } | |
701 | return NULL; | |
52b7d2ce | 702 | default: |
65c25746 | 703 | plog(ASL_LEVEL_WARNING, |
d1e348cf | 704 | "Ignored attribute %s\n", s_isakmp_cfg_type(type)); |
52b7d2ce A |
705 | return NULL; |
706 | break; | |
707 | } | |
708 | ||
709 | if ((buffer = vmalloc(sizeof(*attr) + dlen)) == NULL) { | |
65c25746 | 710 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
711 | "Cannot allocate memory\n"); |
712 | goto out; | |
713 | } | |
714 | ||
715 | attr = (struct isakmp_data *)buffer->v; | |
716 | if (ashort) { | |
717 | attr->type = htons(type | ISAKMP_GEN_TV); | |
718 | attr->lorv = htons(value); | |
719 | goto out; | |
720 | } | |
721 | ||
722 | attr->type = htons(type | ISAKMP_GEN_TLV); | |
723 | attr->lorv = htons(dlen); | |
724 | data = (char *)(attr + 1); | |
725 | ||
726 | switch(type) { | |
727 | case XAUTH_USER_NAME: | |
d1e348cf A |
728 | /* |
729 | * iph1->rmconf->xauth->login->v is valid, | |
730 | * we just checked it in the previous switch case | |
731 | */ | |
732 | memcpy(data, iph1->rmconf->xauth->login->v, dlen); | |
52b7d2ce A |
733 | break; |
734 | case XAUTH_USER_PASSWORD: | |
d1e348cf | 735 | case XAUTH_PASSCODE: |
52b7d2ce A |
736 | memcpy(data, pwd->v, dlen); |
737 | break; | |
738 | default: | |
739 | break; | |
740 | } | |
741 | ||
742 | out: | |
743 | if (freepwd) | |
744 | vfree(pwd); | |
745 | ||
746 | return buffer; | |
747 | } | |
748 | ||
749 | vchar_t * | |
750 | isakmp_xauth_set(iph1, attr) | |
65c25746 | 751 | phase1_handle_t *iph1; |
52b7d2ce A |
752 | struct isakmp_data *attr; |
753 | { | |
754 | int type; | |
755 | vchar_t *buffer = NULL; | |
d1e348cf A |
756 | struct xauth_state *xst; |
757 | size_t dlen = 0; | |
758 | char* mraw = NULL; | |
759 | vchar_t *mdata = NULL; | |
52b7d2ce A |
760 | |
761 | if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { | |
d1e348cf A |
762 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
763 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
764 | CONSTSTR("XAUTH is not supported by peer"), | |
765 | CONSTSTR("XAUTH dropped (not supported by peer)")); | |
65c25746 | 766 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
767 | "Xauth mode config set but peer " |
768 | "did not declare itself as Xauth capable\n"); | |
769 | return NULL; | |
770 | } | |
771 | ||
772 | type = ntohs(attr->type) & ~ISAKMP_GEN_MASK; | |
773 | ||
774 | switch(type) { | |
775 | case XAUTH_STATUS: | |
d1e348cf A |
776 | /* |
777 | * We should only receive ISAKMP mode_cfg SET XAUTH_STATUS | |
778 | * when running as a client (initiator). | |
779 | */ | |
780 | xst = &iph1->mode_cfg->xauth; | |
781 | switch(AUTHMETHOD(iph1)) { | |
782 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: | |
783 | if (!iph1->is_rekey) { | |
784 | IPSECSESSIONTRACEREVENT(iph1->parent_session, | |
785 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
786 | CONSTSTR("Unexpected XAUTH Status"), | |
65c25746 A |
787 | CONSTSTR("Xauth dropped (unexpected Xauth status)... not a Phase 1 rekey")); |
788 | plog(ASL_LEVEL_ERR, | |
789 | "Unexpected XAUTH_STATUS_OK... not a Phase 1 rekey\n"); | |
d1e348cf A |
790 | return NULL; |
791 | } | |
792 | case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: | |
793 | case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I: | |
794 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: | |
795 | /* Not implemented ... */ | |
d1e348cf A |
796 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: |
797 | case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: | |
798 | break; | |
799 | default: | |
800 | IPSECSESSIONTRACEREVENT(iph1->parent_session, | |
801 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
802 | CONSTSTR("Unexpected XAUTH Status"), | |
803 | CONSTSTR("Xauth dropped (unexpected Xauth status)")); | |
65c25746 | 804 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
805 | "Unexpected XAUTH_STATUS_OK\n"); |
806 | return NULL; | |
807 | break; | |
808 | } | |
809 | ||
52b7d2ce A |
810 | /* If we got a failure, delete iph1 */ |
811 | if (ntohs(attr->lorv) != XAUTH_STATUS_OK) { | |
d1e348cf A |
812 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
813 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_FAIL, | |
814 | CONSTSTR("XAUTH Status is not OK"), | |
815 | CONSTSTR("Xauth Failed (status not ok)")); | |
65c25746 | 816 | plog(ASL_LEVEL_ERR, |
52b7d2ce | 817 | "Xauth authentication failed\n"); |
d06a7ccb | 818 | |
d1e348cf | 819 | vpncontrol_notify_ike_failed(VPNCTL_NTYPE_AUTHENTICATION_FAILED, FROM_LOCAL, |
d06a7ccb | 820 | iph1_get_remote_v4_address(iph1), 0, NULL); |
52b7d2ce A |
821 | |
822 | iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1; | |
e8d9021d A |
823 | |
824 | IPSECLOGASLMSG("IPSec Extended Authentication Failed.\n"); | |
52b7d2ce | 825 | } else { |
d1e348cf A |
826 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
827 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_SUCC, | |
828 | CONSTSTR("XAUTH Status is OK"), | |
829 | CONSTSTR(NULL)); | |
d1e348cf A |
830 | if (iph1->is_rekey) { |
831 | xst->status = XAUTHST_OK; | |
832 | } | |
e8d9021d A |
833 | |
834 | IPSECLOGASLMSG("IPSec Extended Authentication Passed.\n"); | |
52b7d2ce A |
835 | } |
836 | ||
837 | ||
838 | /* We acknowledge it */ | |
839 | break; | |
d1e348cf A |
840 | case XAUTH_MESSAGE: |
841 | if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) { | |
842 | dlen = ntohs(attr->lorv); | |
843 | if (dlen > 0) { | |
844 | mraw = (char*)(attr + 1); | |
845 | if ((mdata = vmalloc(dlen)) == NULL) { | |
65c25746 | 846 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
847 | "Cannot allocate memory\n"); |
848 | return NULL; | |
849 | } | |
850 | memcpy(mdata->v, mraw, mdata->l); | |
65c25746 | 851 | plog(ASL_LEVEL_NOTICE, "XAUTH Message: '%s'.\n", |
d1e348cf A |
852 | binsanitize(mdata->v, mdata->l)); |
853 | vfree(mdata); | |
854 | } | |
855 | } | |
856 | ||
52b7d2ce | 857 | default: |
d1e348cf A |
858 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
859 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
860 | CONSTSTR("ignored attribute"), | |
861 | CONSTSTR("Xauth dropped (ignored attribute)")); | |
65c25746 | 862 | plog(ASL_LEVEL_WARNING, |
d1e348cf | 863 | "Ignored attribute %s\n", s_isakmp_cfg_type(type)); |
52b7d2ce A |
864 | return NULL; |
865 | break; | |
866 | } | |
867 | ||
868 | if ((buffer = vmalloc(sizeof(*attr))) == NULL) { | |
d1e348cf A |
869 | IPSECSESSIONTRACEREVENT(iph1->parent_session, |
870 | IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP, | |
871 | CONSTSTR("Failed to allocate attribute"), | |
872 | CONSTSTR("Xauth dropped (failed to allocate attribute)")); | |
65c25746 | 873 | plog(ASL_LEVEL_ERR, |
52b7d2ce A |
874 | "Cannot allocate memory\n"); |
875 | return NULL; | |
876 | } | |
877 | ||
878 | attr = (struct isakmp_data *)buffer->v; | |
879 | attr->type = htons(type | ISAKMP_GEN_TV); | |
880 | attr->lorv = htons(0); | |
881 | ||
882 | return buffer; | |
883 | } | |
884 | ||
885 | ||
886 | void | |
887 | xauth_rmstate(xst) | |
888 | struct xauth_state *xst; | |
889 | { | |
890 | switch (xst->authtype) { | |
891 | case XAUTH_TYPE_GENERIC: | |
892 | if (xst->authdata.generic.usr) | |
893 | racoon_free(xst->authdata.generic.usr); | |
894 | ||
895 | if (xst->authdata.generic.pwd) | |
896 | racoon_free(xst->authdata.generic.pwd); | |
897 | ||
898 | break; | |
899 | ||
900 | case XAUTH_TYPE_CHAP: | |
901 | case XAUTH_TYPE_OTP: | |
902 | case XAUTH_TYPE_SKEY: | |
65c25746 | 903 | plog(ASL_LEVEL_WARNING, |
52b7d2ce A |
904 | "Unsupported authtype %d\n", xst->authtype); |
905 | break; | |
906 | ||
907 | default: | |
65c25746 | 908 | plog(ASL_LEVEL_WARNING, |
52b7d2ce A |
909 | "Unexpected authtype %d\n", xst->authtype); |
910 | break; | |
911 | } | |
912 | ||
913 | return; | |
914 | } | |
915 | ||
d1e348cf A |
916 | int |
917 | xauth_rmconf_used(xauth_rmconf) | |
918 | struct xauth_rmconf **xauth_rmconf; | |
919 | { | |
920 | if (*xauth_rmconf == NULL) { | |
921 | *xauth_rmconf = racoon_malloc(sizeof(**xauth_rmconf)); | |
922 | if (*xauth_rmconf == NULL) { | |
65c25746 | 923 | plog(ASL_LEVEL_ERR, |
d1e348cf A |
924 | "xauth_rmconf_used: malloc failed\n"); |
925 | return -1; | |
926 | } | |
927 | ||
928 | (*xauth_rmconf)->login = NULL; | |
929 | (*xauth_rmconf)->pass = NULL; | |
930 | (*xauth_rmconf)->state = 0; | |
931 | } else { | |
932 | if ((*xauth_rmconf)->login) { | |
933 | vfree((*xauth_rmconf)->login); | |
934 | (*xauth_rmconf)->login = NULL; | |
935 | } | |
936 | if ((*xauth_rmconf)->pass != NULL) { | |
937 | vfree((*xauth_rmconf)->pass); | |
938 | (*xauth_rmconf)->pass = NULL; | |
939 | } | |
940 | (*xauth_rmconf)->state = 0; | |
941 | } | |
942 | ||
943 | return 0; | |
944 | } | |
945 | ||
946 | void | |
947 | xauth_rmconf_delete(xauth_rmconf) | |
948 | struct xauth_rmconf **xauth_rmconf; | |
949 | { | |
950 | if (*xauth_rmconf != NULL) { | |
951 | if ((*xauth_rmconf)->login != NULL) | |
952 | vfree((*xauth_rmconf)->login); | |
953 | if ((*xauth_rmconf)->pass != NULL) | |
954 | vfree((*xauth_rmconf)->pass); | |
955 | ||
956 | racoon_free(*xauth_rmconf); | |
957 | *xauth_rmconf = NULL; | |
958 | } | |
959 | ||
960 | return; | |
961 | } |