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