Annotation of embedaddon/mpd/src/eap.c, revision 1.1.1.2
1.1 misho 1: /*
2: * See ``COPYRIGHT.mpd''
3: *
1.1.1.2 ! misho 4: * $Id: eap.c,v 1.1.1.1 2013/07/22 08:44:29 misho Exp $
1.1 misho 5: *
6: */
7:
8: #include "ppp.h"
9: #include "radius.h"
10: #include "auth.h"
11: #include "ngfunc.h"
12:
13: /*
14: * INTERNAL FUNCTIONS
15: */
16:
17: static void EapSendRequest(Link l, u_char type);
18: static void EapSendNak(Link l, u_char id, u_char type);
19: static void EapSendIdentRequest(Link l);
20: static void EapIdentTimeout(void *ptr);
21: static char EapTypeSupported(u_char type);
22: static void EapRadiusProxy(Link l, AuthData auth, const u_char *pkt, u_short len);
23: static void EapRadiusProxyFinish(Link l, AuthData auth);
24: static void EapRadiusSendMsg(void *ptr);
25: static void EapRadiusSendMsgTimeout(void *ptr);
26: static int EapSetCommand(Context ctx, int ac, char *av[], void *arg);
27:
28: /* Set menu options */
29: enum {
30: SET_ACCEPT,
31: SET_DENY,
32: SET_ENABLE,
33: SET_DISABLE,
34: SET_YES,
35: SET_NO
36: };
37:
38: /*
39: * GLOBAL VARIABLES
40: */
41:
42: const struct cmdtab EapSetCmds[] = {
43: { "accept [opt ...]", "Accept option",
44: EapSetCommand, NULL, 2, (void *) SET_ACCEPT },
45: { "deny [opt ...]", "Deny option",
46: EapSetCommand, NULL, 2, (void *) SET_DENY },
47: { "enable [opt ...]", "Enable option",
48: EapSetCommand, NULL, 2, (void *) SET_ENABLE },
49: { "disable [opt ...]", "Disable option",
50: EapSetCommand, NULL, 2, (void *) SET_DISABLE },
51: { "yes [opt ...]", "Enable and accept option",
52: EapSetCommand, NULL, 2, (void *) SET_YES },
53: { "no [opt ...]", "Disable and deny option",
54: EapSetCommand, NULL, 2, (void *) SET_NO },
55: { NULL },
56: };
57:
58: /*
59: * INTERNAL VARIABLES
60: */
61:
62: static struct confinfo gConfList[] = {
63: { 0, EAP_CONF_RADIUS, "radius-proxy" },
64: { 1, EAP_CONF_MD5, "md5" },
65: { 0, 0, NULL },
66: };
67:
68:
69:
70: /*
71: * EapInit()
72: */
73:
74: void
75: EapInit(Link l)
76: {
77: EapInfo eap = &l->lcp.auth.eap;
78:
79: Disable(&eap->conf.options, EAP_CONF_MD5);
80: Accept(&eap->conf.options, EAP_CONF_MD5);
81: }
82:
83: /*
84: * EapStart()
85: */
86:
87: void
88: EapStart(Link l, int which)
89: {
90: Auth a = &l->lcp.auth;
91: EapInfo eap = &l->lcp.auth.eap;
92: int i;
93:
94: for (i = 0; i < EAP_NUM_TYPES; i++)
95: eap->peer_types[i] = eap->want_types[i] = 0;
96:
97: /* fill a list of requestable auth types */
98: if (Enabled(&eap->conf.options, EAP_CONF_MD5))
99: eap->want_types[0] = EAP_TYPE_MD5CHAL;
100:
101: /* fill a list of acceptable auth types */
102: if (Acceptable(&eap->conf.options, EAP_CONF_MD5))
103: eap->peer_types[0] = EAP_TYPE_MD5CHAL;
104:
105: if (l->originate == LINK_ORIGINATE_LOCAL)
106: a->params.msoft.chap_alg = a->self_to_peer_alg;
107: else
108: a->params.msoft.chap_alg = a->peer_to_self_alg;
109:
110: switch (which) {
111: case AUTH_PEER_TO_SELF:
112:
113: /* Initialize retry counter and timer */
114: eap->next_id = 1;
115: eap->retry = AUTH_RETRIES;
116:
117: TimerInit(&eap->reqTimer, "EapRadiusSendMsgTimer",
118: l->conf.retry_timeout * SECONDS, EapRadiusSendMsgTimeout, (void *) l);
119:
120: TimerInit(&eap->identTimer, "EapTimer",
121: l->conf.retry_timeout * SECONDS, EapIdentTimeout, (void *) l);
122: TimerStart(&eap->identTimer);
123:
124: /* Send first request
125: * Send the request even, if the Radius-Eap-Proxy feature is active,
126: * this saves on roundtrip.
127: */
128: EapSendIdentRequest(l);
129: break;
130:
131: case AUTH_SELF_TO_PEER: /* Just wait for authenitcaor's request */
132: break;
133:
134: default:
135: assert(0);
136: }
137: }
138:
139: /*
140: * EapStop()
141: */
142:
143: void
144: EapStop(EapInfo eap)
145: {
146: TimerStop(&eap->identTimer);
147: TimerStop(&eap->reqTimer);
148: }
149:
150: /*
151: * EapSendRequest()
152: *
153: * Send an EAP request to peer.
154: */
155:
156: static void
157: EapSendRequest(Link l, u_char type)
158: {
159: Auth const a = &l->lcp.auth;
160: EapInfo const eap = &a->eap;
161: ChapInfo const chap = &a->chap;
162: ChapParams const cp = &a->params.chap;
163: int i = 0;
164: u_char req_type = 0;
165:
166: if (type == 0) {
167: for (i = 0; i < EAP_NUM_TYPES; i++) {
168: if (eap->want_types[i] != 0) {
169: req_type = eap->want_types[i];
170: break;
171: }
172: }
173: } else {
174: req_type = type;
175: }
176:
177: if (req_type == 0) {
178: Log(LG_AUTH, ("[%s] EAP: ran out of EAP Types", l->name));
179: AuthFinish(l, AUTH_PEER_TO_SELF, FALSE);
180: return;
181: }
182:
183: /* don't request this type again */
184: eap->want_types[i] = 0;
185:
186: switch (req_type) {
187: case EAP_TYPE_MD5CHAL:
188:
189: /* Invalidate any old challenge data */
190: cp->chal_len = 0;
191: /* Initialize retry counter and timer */
192: chap->next_id = 1;
193: chap->retry = AUTH_RETRIES;
194: chap->proto = PROTO_EAP;
195: a->peer_to_self_alg = CHAP_ALG_MD5;
196:
197: TimerInit(&chap->chalTimer, "ChalTimer",
198: l->conf.retry_timeout * SECONDS, ChapChalTimeout, l);
199: TimerStart(&chap->chalTimer);
200:
201: /* Send first challenge */
202: ChapSendChallenge(l);
203: break;
204:
205: default:
206: Log(LG_AUTH, ("[%s] EAP: Type %d is currently un-implemented",
207: l->name, eap->want_types[i]));
208: AuthFinish(l, AUTH_PEER_TO_SELF, FALSE);
209: }
210:
211: return;
212: }
213:
214: /*
215: * EapSendNak()
216: *
217: * Send an EAP Nak to peer.
218: */
219:
220: static void
221: EapSendNak(Link l, u_char id, u_char type)
222: {
223: Auth const a = &l->lcp.auth;
224: EapInfo const eap = &a->eap;
225: int i = 0;
226: u_char nak_type = 0;
227:
228: for (i = 0; i < EAP_NUM_TYPES; i++) {
229: if (eap->peer_types[i] != 0) {
230: nak_type = eap->peer_types[i];
231: break;
232: }
233: }
234:
235: if (nak_type == 0) {
236: Log(LG_AUTH, ("[%s] EAP: ran out of EAP Types", l->name));
237: AuthFinish(l, AUTH_SELF_TO_PEER, FALSE);
238: return;
239: }
240:
241: /* don't nak this proto again */
242: eap->peer_types[i] = 0;
243:
244: AuthOutput(l, PROTO_EAP, EAP_RESPONSE, id, &nak_type, 1, 0, EAP_TYPE_NAK);
245: return;
246: }
247:
248: /*
249: * EapSendIdentRequest()
250: *
251: * Send an Ident Request to the peer.
252: */
253:
254: static void
255: EapSendIdentRequest(Link l)
256: {
257: EapInfo const eap = &l->lcp.auth.eap;
258:
259: /* Send the initial Identity request */
260: AuthOutput(l, PROTO_EAP, EAP_REQUEST, eap->next_id++, NULL, 0, 0, EAP_TYPE_IDENT);
261: }
262:
263: /*
264: * EapInput()
265: *
266: * Accept an incoming EAP packet
267: */
268:
269: void
270: EapInput(Link l, AuthData auth, const u_char *pkt, u_short len)
271: {
272: Auth const a = &l->lcp.auth;
273: EapInfo const eap = &a->eap;
274: int data_len = len - 1, i, acc_type;
275: u_char *data = NULL, type = 0;
276:
277: if (pkt != NULL) {
278: data = data_len > 0 ? (u_char *) &pkt[1] : NULL;
279: type = pkt[0];
280: }
281:
282: if (Enabled(&eap->conf.options, EAP_CONF_RADIUS)) {
283: EapRadiusProxy(l, auth, pkt, len);
284: return;
285: }
286:
287: switch (auth->code) {
288: case EAP_REQUEST:
289: switch (type) {
290: case EAP_TYPE_IDENT:
291: AuthOutput(l, PROTO_EAP, EAP_RESPONSE, auth->id, (u_char *) auth->conf.authname,
292: strlen(auth->conf.authname), 0, EAP_TYPE_IDENT);
293: break;
294:
295: case EAP_TYPE_NAK:
296: case EAP_TYPE_NOTIF:
297: Log(LG_AUTH, ("[%s] EAP: Type %s is invalid in Request messages",
298: l->name, EapType(type)));
299: AuthFinish(l, AUTH_SELF_TO_PEER, FALSE);
300: break;
301:
302: /* deal with Auth Types */
303: default:
304: acc_type = 0;
305: if (EapTypeSupported(type)) {
306: for (i = 0; i < EAP_NUM_TYPES; i++) {
307: if (eap->peer_types[i] == type) {
308: acc_type = eap->peer_types[i];
309: break;
310: }
311: }
312:
313: if (acc_type == 0) {
314: Log(LG_AUTH, ("[%s] EAP: Type %s not acceptable", l->name,
315: EapType(type)));
316: EapSendNak(l, auth->id, type);
317: break;
318: }
319:
320: switch (type) {
321: case EAP_TYPE_MD5CHAL:
322: a->self_to_peer_alg = CHAP_ALG_MD5;
323: auth->code = CHAP_CHALLENGE;
324: ChapInput(l, auth, &pkt[1], len - 1);
325: return;
326:
327: default:
328: assert(0);
329: }
330: } else {
331: Log(LG_AUTH, ("[%s] EAP: Type %s not supported", l->name, EapType(type)));
332: EapSendNak(l, auth->id, type);
333: }
334: }
335: break;
336:
337: case EAP_RESPONSE:
338: switch (type) {
339: case EAP_TYPE_IDENT:
340: TimerStop(&eap->identTimer);
341: Log(LG_AUTH, ("[%s] EAP: Identity:%*.*s",
342: l->name, data_len, data_len, data));
343: EapSendRequest(l, 0);
344: break;
345:
346: case EAP_TYPE_NOTIF:
347: Log(LG_AUTH, ("[%s] EAP: Notify:%*.*s ", l->name,
348: data_len, data_len, data));
349: break;
350:
351: case EAP_TYPE_NAK:
352: Log(LG_AUTH, ("[%s] EAP: Nak desired Type %s ", l->name,
353: EapType(data[0])));
354: if (EapTypeSupported(data[0]))
355: EapSendRequest(l, data[0]);
356: else
357: EapSendRequest(l, 0);
358: break;
359:
360: case EAP_TYPE_MD5CHAL:
361: auth->code = CHAP_RESPONSE;
362: ChapInput(l, auth, &pkt[1], len - 1);
363: return;
364:
365: default:
366: Log(LG_AUTH, ("[%s] EAP: unknown type %d", l->name, type));
367: AuthFinish(l, AUTH_PEER_TO_SELF, FALSE);
368: }
369: break;
370:
371: case EAP_SUCCESS:
372: AuthFinish(l, AUTH_SELF_TO_PEER, TRUE);
373: break;
374:
375: case EAP_FAILURE:
376: AuthFinish(l, AUTH_SELF_TO_PEER, FALSE);
377: break;
378:
379: default:
380: Log(LG_AUTH, ("[%s] EAP: unknown code %d", l->name, auth->code));
381: AuthFinish(l, AUTH_PEER_TO_SELF, FALSE);
382: }
383: AuthDataDestroy(auth);
384: }
385:
386: /*
387: * EapRadiusProxy()
388: *
389: * Proxy EAP Requests from/to the RADIUS server
390: */
391:
392: static void
393: EapRadiusProxy(Link l, AuthData auth, const u_char *pkt, u_short len)
394: {
395: int data_len = len - 1;
396: u_char *data = NULL, type = 0;
397: Auth const a = &l->lcp.auth;
398: EapInfo const eap = &a->eap;
399: struct fsmheader lh;
400:
401: Log(LG_AUTH, ("[%s] EAP: Proxying packet to RADIUS", l->name));
402:
403: if (pkt != NULL) {
404: data = data_len > 0 ? (u_char *) &pkt[1] : NULL;
405: type = pkt[0];
406: }
407:
408: if (auth->code == EAP_RESPONSE && type == EAP_TYPE_IDENT) {
409: TimerStop(&eap->identTimer);
410: if (data_len >= AUTH_MAX_AUTHNAME) {
411: Log(LG_AUTH, ("[%s] EAP: Identity to big (%d), truncating",
412: l->name, data_len));
413: data_len = AUTH_MAX_AUTHNAME - 1;
414: }
415: memset(eap->identity, 0, sizeof(eap->identity));
416: strncpy(eap->identity, (char *) data, data_len);
417: Log(LG_AUTH, ("[%s] EAP: Identity: %s", l->name, eap->identity));
418: }
419:
420: TimerStop(&eap->reqTimer);
421:
422: /* prepare packet */
423: lh.code = auth->code;
424: lh.id = auth->id;
425: lh.length = htons(len + sizeof(lh));
426:
427: auth->params.eapmsg = Malloc(MB_AUTH, len + sizeof(lh));
428: memcpy(auth->params.eapmsg, &lh, sizeof(lh));
429: memcpy(&auth->params.eapmsg[sizeof(lh)], pkt, len);
430:
431: auth->params.eapmsg_len = len + sizeof(lh);
432: strlcpy(auth->params.authname, eap->identity, sizeof(auth->params.authname));
433:
434: auth->eap_radius = TRUE;
435:
436: auth->finish = EapRadiusProxyFinish;
437: AuthAsyncStart(l, auth);
438:
439: }
440:
441: /*
442: * RadiusEapProxyFinish()
443: *
444: * Return point from the asynch RADIUS EAP Proxy Handler.
445: *
446: */
447:
448: static void
449: EapRadiusProxyFinish(Link l, AuthData auth)
450: {
451: Auth const a = &l->lcp.auth;
452: EapInfo eap = &a->eap;
453:
454: Log(LG_AUTH, ("[%s] EAP: RADIUS return status: %s",
455: l->name, AuthStatusText(auth->status)));
456:
457: /* this shouldn't happen normally, however be liberal */
458: if (a->params.eapmsg == NULL) {
459: struct fsmheader lh;
460:
461: Log(LG_AUTH, ("[%s] EAP: Warning, rec'd empty EAP-Message",
462: l->name));
463: /* prepare packet */
464: lh.code = auth->status == AUTH_STATUS_SUCCESS ? EAP_SUCCESS : EAP_FAILURE;
465: lh.id = auth->id;
466: lh.length = htons(sizeof(lh));
467:
468: a->params.eapmsg = Mdup(MB_AUTH, &lh, sizeof(lh));
469: a->params.eapmsg_len = sizeof(lh);
470: }
471:
472: if (a->params.eapmsg != NULL) {
473: eap->retry = AUTH_RETRIES;
474:
475: EapRadiusSendMsg(l);
476: if (auth->status == AUTH_STATUS_UNDEF)
477: TimerStart(&eap->reqTimer);
478: }
479:
480: if (auth->status == AUTH_STATUS_FAIL) {
481: AuthFinish(l, AUTH_PEER_TO_SELF, FALSE);
482: } else if (auth->status == AUTH_STATUS_SUCCESS) {
483: AuthFinish(l, AUTH_PEER_TO_SELF, TRUE);
484: }
485:
486: AuthDataDestroy(auth);
487: }
488:
489: /*
490: * EapRadiusSendMsg()
491: *
492: * Send an EAP Message to the peer
493: */
494:
495: static void
496: EapRadiusSendMsg(void *ptr)
497: {
498: Mbuf bp;
499: Link l = (Link)ptr;
500: Auth const a = &l->lcp.auth;
501: FsmHeader const f = (FsmHeader)a->params.eapmsg;
502: char buf[32];
503:
504: if (a->params.eapmsg_len > 4) {
505: Log(LG_AUTH, ("[%s] EAP: send %s #%d len: %d, type: %s",
506: l->name, EapCode(f->code, buf, sizeof(buf)), f->id, htons(f->length),
507: EapType(a->params.eapmsg[4])));
508: } else {
509: Log(LG_AUTH, ("[%s] EAP: send %s #%d len: %d",
510: l->name, EapCode(f->code, buf, sizeof(buf)), f->id, htons(f->length)));
511: }
512:
513: bp = mbcopyback(NULL, 0, a->params.eapmsg, a->params.eapmsg_len);
514: NgFuncWritePppFrameLink(l, PROTO_EAP, bp);
515: }
516:
517: /*
518: * EapRadiusSendMsgTimeout()
519: *
520: * Timer expired for reply to our request
521: */
522:
523: static void
524: EapRadiusSendMsgTimeout(void *ptr)
525: {
526: Link l = (Link)ptr;
527: EapInfo const eap = &l->lcp.auth.eap;
528:
529: if (--eap->retry > 0) {
530: TimerStart(&eap->reqTimer);
531: EapRadiusSendMsg(l);
532: }
533: }
534:
535: /*
536: * EapIdentTimeout()
537: *
538: * Timer expired for reply to our request
539: */
540:
541: static void
542: EapIdentTimeout(void *ptr)
543: {
544: Link l = (Link)ptr;
545: EapInfo const eap = &l->lcp.auth.eap;
546:
547: if (--eap->retry > 0) {
548: TimerStart(&eap->identTimer);
549: EapSendIdentRequest(l);
550: }
551: }
552:
553: /*
554: * EapStat()
555: */
556:
557: int
558: EapStat(Context ctx, int ac, char *av[], void *arg)
559: {
560: EapInfo const eap = &ctx->lnk->lcp.auth.eap;
561:
562: Printf("\tIdentity : %s\r\n", eap->identity);
563: Printf("EAP options\r\n");
564: OptStat(ctx, &eap->conf.options, gConfList);
565:
566: return (0);
567: }
568:
569: /*
570: * EapCode()
571: */
572:
573: const char *
574: EapCode(u_char code, char *buf, size_t len)
575: {
576: switch (code) {
577: case EAP_REQUEST:
578: strlcpy(buf, "REQUEST", len);
579: break;
580: case EAP_RESPONSE:
581: strlcpy(buf, "RESPONSE", len);
582: break;
583: case EAP_SUCCESS:
584: strlcpy(buf, "SUCCESS", len);
585: break;
586: case EAP_FAILURE:
587: strlcpy(buf, "FAILURE", len);
588: break;
589: default:
590: snprintf(buf, len, "code%d", code);
591: }
592: return(buf);
593: }
594:
595: /*
596: * EapType()
597: */
598:
599: const char *
600: EapType(u_char type)
601: {
602: switch (type) {
603: case EAP_TYPE_IDENT:
604: return("Identity");
605: case EAP_TYPE_NOTIF:
606: return("Notification");
607: case EAP_TYPE_NAK:
608: return("Nak");
609: case EAP_TYPE_MD5CHAL:
610: return("MD5 Challenge");
611: case EAP_TYPE_OTP:
612: return("One Time Password");
613: case EAP_TYPE_GTC:
614: return("Generic Token Card");
615: case EAP_TYPE_EAP_TLS:
616: return("TLS");
617: case EAP_TYPE_MSCHAP_V2:
618: return("MS-CHAPv2");
619: case EAP_TYPE_EAP_TTLS:
620: return("TTLS");
621: default:
622: return("UNKNOWN");
623: }
624: }
625:
626: /*
627: * EapTypeSupported()
628: */
629:
630: static char
631: EapTypeSupported(u_char type)
632: {
633: switch (type) {
634: case EAP_TYPE_IDENT:
635: case EAP_TYPE_NOTIF:
636: case EAP_TYPE_NAK:
637: case EAP_TYPE_MD5CHAL:
638: return 1;
639:
640: default:
641: return 0;
642: }
643: }
644:
645: /*
646: * EapSetCommand()
647: */
648:
649: static int
650: EapSetCommand(Context ctx, int ac, char *av[], void *arg)
651: {
652: EapInfo const eap = &ctx->lnk->lcp.auth.eap;
653:
654: if (ac == 0)
655: return(-1);
656:
657: switch ((intptr_t)arg) {
658:
659: case SET_ACCEPT:
660: AcceptCommand(ac, av, &eap->conf.options, gConfList);
661: break;
662:
663: case SET_DENY:
664: DenyCommand(ac, av, &eap->conf.options, gConfList);
665: break;
666:
667: case SET_ENABLE:
668: EnableCommand(ac, av, &eap->conf.options, gConfList);
669: break;
670:
671: case SET_DISABLE:
672: DisableCommand(ac, av, &eap->conf.options, gConfList);
673: break;
674:
675: case SET_YES:
676: YesCommand(ac, av, &eap->conf.options, gConfList);
677: break;
678:
679: case SET_NO:
680: NoCommand(ac, av, &eap->conf.options, gConfList);
681: break;
682:
683: default:
684: assert(0);
685: }
686:
687: return(0);
688: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>