Annotation of embedaddon/mpd/src/ccp_mppc.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * ccp_mppc.c
4: *
5: * Written by Archie Cobbs <archie@freebsd.org>
6: * Copyright (c) 1998-1999 Whistle Communications, Inc. All rights reserved.
7: * See ``COPYRIGHT.whistle''
8: */
9:
10: #include "defs.h"
11:
12: #ifdef CCP_MPPC
13:
14: #include "ppp.h"
15: #include "ccp.h"
16: #include "msoft.h"
17: #include "ngfunc.h"
18: #include "bund.h"
19: #include <md4.h>
20:
21: #include <netgraph/ng_message.h>
22: #include <netgraph.h>
23:
24: /*
25: * This implements both MPPC compression and MPPE encryption.
26: */
27:
28: /*
29: * DEFINITIONS
30: */
31:
32: /* #define DEBUG_KEYS */
33:
34: #define MPPC_SUPPORTED (MPPC_BIT | MPPE_BITS | MPPE_STATELESS)
35:
36: /* Set menu options */
37: enum {
38: SET_ACCEPT,
39: SET_DENY,
40: SET_ENABLE,
41: SET_DISABLE,
42: SET_YES,
43: SET_NO
44: };
45:
46: enum {
47: MPPC_CONF_COMPRESS,
48: MPPC_CONF_40,
49: MPPC_CONF_56,
50: MPPC_CONF_128,
51: MPPC_CONF_STATELESS,
52: MPPC_CONF_POLICY
53: };
54:
55: /*
56: * INTERNAL FUNCTIONS
57: */
58:
59: static int MppcInit(Bund b, int dir);
60: static int MppcConfigure(Bund b);
61: static char *MppcDescribe(Bund b, int xmit, char *buf, size_t len);
62: static int MppcSubtractBloat(Bund b, int size);
63: static void MppcCleanup(Bund b, int dir);
64: static u_char *MppcBuildConfigReq(Bund b, u_char *cp, int *ok);
65: static void MppcDecodeConfigReq(Fsm fp, FsmOption opt, int mode);
66: static Mbuf MppcRecvResetReq(Bund b, int id, Mbuf bp, int *noAck);
67: static char *MppcDescribeBits(u_int32_t bits, char *buf, size_t len);
68: static int MppcNegotiated(Bund b, int xmit);
69: static int MppcSetCommand(Context ctx, int ac, char *av[], void *arg);
70:
71: /* Encryption stuff */
72: static void MppeInitKey(Bund b, MppcInfo mppc, int dir);
73: static void MppeInitKeyv2(Bund b, MppcInfo mppc, int dir);
74: static short MppcEnabledMppeType(Bund b, short type);
75: static short MppcAcceptableMppeType(Bund b, short type);
76: static int MppcKeyAvailable(Bund b, short type);
77:
78: #ifdef DEBUG_KEYS
79: static void KeyDebug(const u_char *data, int len, const char *fmt, ...);
80: #define KEYDEBUG(x) KeyDebug x
81: #else
82: #define KEYDEBUG(x)
83: #endif
84:
85: /*
86: * GLOBAL VARIABLES
87: */
88:
89: static const struct confinfo gConfList[] = {
90: { 1, MPPC_CONF_COMPRESS, "compress" },
91: { 1, MPPC_CONF_40, "e40" },
92: { 1, MPPC_CONF_56, "e56" },
93: { 1, MPPC_CONF_128, "e128" },
94: { 1, MPPC_CONF_STATELESS, "stateless" },
95: { 0, MPPC_CONF_POLICY, "policy" },
96: { 0, 0, NULL },
97: };
98:
99: const struct comptype gCompMppcInfo = {
100: "mppc",
101: CCP_TY_MPPC,
102: 1,
103: MppcInit,
104: MppcConfigure,
105: NULL,
106: MppcDescribe,
107: MppcSubtractBloat,
108: MppcCleanup,
109: MppcBuildConfigReq,
110: MppcDecodeConfigReq,
111: NULL,
112: MppcRecvResetReq,
113: NULL,
114: MppcNegotiated,
115: NULL,
116: NULL,
117: NULL,
118: };
119:
120: const struct cmdtab MppcSetCmds[] = {
121: { "accept [opt ...]", "Accept option",
122: MppcSetCommand, NULL, 2, (void *) SET_ACCEPT },
123: { "deny [opt ...]", "Deny option",
124: MppcSetCommand, NULL, 2, (void *) SET_DENY },
125: { "enable [opt ...]", "Enable option",
126: MppcSetCommand, NULL, 2, (void *) SET_ENABLE },
127: { "disable [opt ...]", "Disable option",
128: MppcSetCommand, NULL, 2, (void *) SET_DISABLE },
129: { "yes [opt ...]", "Enable and accept option",
130: MppcSetCommand, NULL, 2, (void *) SET_YES },
131: { "no [opt ...]", "Disable and deny option",
132: MppcSetCommand, NULL, 2, (void *) SET_NO },
133: { NULL },
134: };
135:
136: int MPPCPresent = 0;
137: int MPPEPresent = 0;
138:
139: /*
140: * MppcInit()
141: */
142:
143: static int
144: MppcInit(Bund b, int dir)
145: {
146: MppcInfo const mppc = &b->ccp.mppc;
147: struct ng_mppc_config conf;
148: struct ngm_mkpeer mp;
149: char path[NG_PATHSIZ];
150: const char *mppchook, *ppphook;
151: int mschap;
152: int cmd;
153: ng_ID_t id;
154:
155: /* Which type of MS-CHAP did we do? */
156: mschap = b->params.msoft.chap_alg;
157:
158: /* Initialize configuration structure */
159: memset(&conf, 0, sizeof(conf));
160: conf.enable = 1;
161: if (dir == COMP_DIR_XMIT) {
162: cmd = NGM_MPPC_CONFIG_COMP;
163: ppphook = NG_PPP_HOOK_COMPRESS;
164: mppchook = NG_MPPC_HOOK_COMP;
165: conf.bits = mppc->xmit_bits;
166: if (conf.bits & MPPE_BITS) {
167: if (mschap == CHAP_ALG_MSOFT)
168: MppeInitKey(b, mppc, dir);
169: else
170: MppeInitKeyv2(b, mppc, dir);
171: memcpy(conf.startkey, mppc->xmit_key0, sizeof(conf.startkey));
172: }
173: } else {
174: cmd = NGM_MPPC_CONFIG_DECOMP;
175: ppphook = NG_PPP_HOOK_DECOMPRESS;
176: mppchook = NG_MPPC_HOOK_DECOMP;
177: conf.bits = mppc->recv_bits;
178: if (conf.bits & MPPE_BITS) {
179: if (mschap == CHAP_ALG_MSOFT)
180: MppeInitKey(b, mppc, dir);
181: else
182: MppeInitKeyv2(b, mppc, dir);
183: memcpy(conf.startkey, mppc->recv_key0, sizeof(conf.startkey));
184: }
185: }
186:
187: /* Attach a new MPPC node to the PPP node */
188: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
189: strcpy(mp.type, NG_MPPC_NODE_TYPE);
190: strcpy(mp.ourhook, ppphook);
191: strcpy(mp.peerhook, mppchook);
192: if (NgSendMsg(gCcpCsock, path,
193: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
194: Perror("[%s] can't create %s node", b->name, mp.type);
195: return(-1);
196: }
197:
198: strlcat(path, ppphook, sizeof(path));
199:
200: id = NgGetNodeID(-1, path);
201: if (dir == COMP_DIR_XMIT) {
202: b->ccp.comp_node_id = id;
203: } else {
204: b->ccp.decomp_node_id = id;
205: }
206:
207: /* Configure MPPC node */
208: snprintf(path, sizeof(path), "[%x]:", id);
209: if (NgSendMsg(gCcpCsock, path,
210: NGM_MPPC_COOKIE, cmd, &conf, sizeof(conf)) < 0) {
211: Perror("[%s] can't config %s node at %s",
212: b->name, NG_MPPC_NODE_TYPE, path);
213: NgFuncShutdownNode(gCcpCsock, b->name, path);
214: return(-1);
215: }
216:
217: /* Done */
218: return(0);
219: }
220:
221: static int
222: MppcConfigure(Bund b)
223: {
224: MppcInfo const mppc = &b->ccp.mppc;
225:
226: mppc->peer_reject = 0;
227: mppc->recv_bits = 0;
228: mppc->xmit_bits = 0;
229:
230: if (Enabled(&mppc->options, MPPC_CONF_COMPRESS)
231: && MPPCPresent)
232: return (0);
233:
234: if (MppcEnabledMppeType(b, 40) || MppcAcceptableMppeType(b, 40))
235: return (0);
236: if (MppcEnabledMppeType(b, 56) || MppcAcceptableMppeType(b, 56))
237: return (0);
238: if (MppcEnabledMppeType(b, 128) || MppcAcceptableMppeType(b, 128))
239: return (0);
240:
241: return (-1);
242: }
243:
244: /*
245: * MppcDescribe()
246: */
247:
248: static char *
249: MppcDescribe(Bund b, int dir, char *buf, size_t len)
250: {
251: MppcInfo const mppc = &b->ccp.mppc;
252:
253: switch (dir) {
254: case COMP_DIR_XMIT:
255: return(MppcDescribeBits(mppc->xmit_bits, buf, len));
256: case COMP_DIR_RECV:
257: return(MppcDescribeBits(mppc->recv_bits, buf, len));
258: default:
259: assert(0);
260: return(NULL);
261: }
262: }
263:
264: /*
265: * MppcSubtractBloat()
266: */
267:
268: static int
269: MppcSubtractBloat(Bund b, int size)
270: {
271:
272: /* Account for MPPC header */
273: size -= 2;
274:
275: /* Account for possible expansion with MPPC compression */
276: if ((b->ccp.mppc.xmit_bits & MPPC_BIT) != 0) {
277: int l, h, size0 = size;
278:
279: while (1) {
280: l = MPPC_MAX_BLOWUP(size0);
281: h = MPPC_MAX_BLOWUP(size0 + 1);
282: if (l > size) {
283: size0 -= 20;
284: } else if (h > size) {
285: size = size0;
286: break;
287: } else {
288: size0++;
289: }
290: }
291: }
292:
293: /* Done */
294: return(size);
295: }
296:
297: /*
298: * MppcNegotiated()
299: */
300:
301: static int
302: MppcNegotiated(Bund b, int dir)
303: {
304: MppcInfo const mppc = &b->ccp.mppc;
305:
306: switch (dir) {
307: case COMP_DIR_XMIT:
308: return(mppc->xmit_bits != 0);
309: case COMP_DIR_RECV:
310: return(mppc->recv_bits != 0);
311: default:
312: assert(0);
313: return(0);
314: }
315: }
316:
317: /*
318: * MppcCleanup()
319: */
320:
321: static void
322: MppcCleanup(Bund b, int dir)
323: {
324: char path[NG_PATHSIZ];
325:
326: /* Remove node */
327: if (dir == COMP_DIR_XMIT) {
328: snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
329: b->ccp.comp_node_id = 0;
330: } else {
331: snprintf(path, sizeof(path), "[%x]:", b->ccp.decomp_node_id);
332: b->ccp.decomp_node_id = 0;
333: }
334: NgFuncShutdownNode(gCcpCsock, b->name, path);
335: }
336:
337: /*
338: * MppcBuildConfigReq()
339: */
340:
341: static u_char *
342: MppcBuildConfigReq(Bund b, u_char *cp, int *ok)
343: {
344: MppcInfo const mppc = &b->ccp.mppc;
345: u_int32_t bits = 0;
346:
347: /* Compression */
348: if (Enabled(&mppc->options, MPPC_CONF_COMPRESS)
349: && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_COMPRESS)
350: && MPPCPresent)
351: bits |= MPPC_BIT;
352:
353: /* Encryption */
354: if (MppcEnabledMppeType(b, 40)
355: && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_40))
356: bits |= MPPE_40;
357: if (MppcEnabledMppeType(b, 56)
358: && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_56))
359: bits |= MPPE_56;
360: if (MppcEnabledMppeType(b, 128)
361: && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_128))
362: bits |= MPPE_128;
363:
364: /* Stateless mode */
365: if (Enabled(&mppc->options, MPPC_CONF_STATELESS)
366: && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_STATELESS)
367: && bits != 0)
368: bits |= MPPE_STATELESS;
369:
370: /* Ship it */
371: mppc->xmit_bits = bits;
372: if (bits != 0) {
373: cp = FsmConfValue(cp, CCP_TY_MPPC, -4, &bits);
374: *ok = 1;
375: } else {
376: *ok = 0;
377: }
378: return(cp);
379: }
380:
381: /*
382: * MppcDecodeConfigReq()
383: */
384:
385: static void
386: MppcDecodeConfigReq(Fsm fp, FsmOption opt, int mode)
387: {
388: Bund b = (Bund)fp->arg;
389: MppcInfo const mppc = &b->ccp.mppc;
390: u_int32_t orig_bits;
391: u_int32_t bits;
392: char buf[64];
393:
394: /* Get bits */
395: memcpy(&orig_bits, opt->data, 4);
396: orig_bits = ntohl(orig_bits);
397: bits = orig_bits;
398:
399: /* Sanity check */
400: if (opt->len != 6) {
401: Log(LG_CCP, ("[%s] bogus length %d", b->name, opt->len));
402: if (mode == MODE_REQ)
403: FsmRej(fp, opt);
404: return;
405: }
406:
407: /* Display it */
408: Log(LG_CCP, ("[%s] 0x%08x:%s", b->name, bits, MppcDescribeBits(bits, buf, sizeof(buf))));
409:
410: /* Deal with it */
411: switch (mode) {
412: case MODE_REQ:
413:
414: /* Check for supported bits */
415: if (bits & ~MPPC_SUPPORTED) {
416: Log(LG_CCP, ("[%s] Bits 0x%08x not supported", b->name, bits & ~MPPC_SUPPORTED));
417: bits &= MPPC_SUPPORTED;
418: }
419:
420: /* Check compression */
421: if (!Acceptable(&mppc->options, MPPC_CONF_COMPRESS) || !MPPCPresent)
422: bits &= ~MPPC_BIT;
423:
424: /* Check encryption */
425: if (!MppcAcceptableMppeType(b, 40))
426: bits &= ~MPPE_40;
427: if (!MppcAcceptableMppeType(b, 56))
428: bits &= ~MPPE_56;
429: if (!MppcAcceptableMppeType(b, 128))
430: bits &= ~MPPE_128;
431:
432: /* Choose the strongest encryption available */
433: if (bits & MPPE_128)
434: bits &= ~(MPPE_40|MPPE_56);
435: else if (bits & MPPE_56)
436: bits &= ~MPPE_40;
437:
438: /* It doesn't really make sense to encrypt in only one direction.
439: Also, Win95/98 PPTP can't handle uni-directional encryption. So
440: if the remote side doesn't request encryption, try to prompt it.
441: This is broken wrt. normal PPP negotiation: typical Microsoft. */
442: if ((bits & MPPE_BITS) == 0) {
443: if (MppcAcceptableMppeType(b, 40)) bits |= MPPE_40;
444: if (MppcAcceptableMppeType(b, 56)) bits |= MPPE_56;
445: if (MppcAcceptableMppeType(b, 128)) bits |= MPPE_128;
446: }
447:
448: /* Stateless mode */
449: if ((bits & MPPE_STATELESS) &&
450: (!Acceptable(&mppc->options, MPPC_CONF_STATELESS)
451: || (bits & (MPPE_BITS|MPPC_BIT)) == 0))
452: bits &= ~MPPE_STATELESS;
453:
454: /* See if what we want equals what was sent */
455: mppc->recv_bits = bits;
456: if (bits) {
457: if (bits != orig_bits) {
458: bits = htonl(bits);
459: memcpy(opt->data, &bits, 4);
460: FsmNak(fp, opt);
461: }
462: else
463: FsmAck(fp, opt);
464: }
465: else
466: FsmRej(fp, opt);
467: break;
468:
469: case MODE_NAK:
470: if (!(bits & MPPC_BIT))
471: MPPC_PEER_REJ(mppc, MPPC_CONF_COMPRESS);
472: if (!(bits & MPPE_40))
473: MPPC_PEER_REJ(mppc, MPPC_CONF_40);
474: if (!(bits & MPPE_56))
475: MPPC_PEER_REJ(mppc, MPPC_CONF_56);
476: if (!(bits & MPPE_128))
477: MPPC_PEER_REJ(mppc, MPPC_CONF_128);
478: if (!(bits & MPPE_STATELESS))
479: MPPC_PEER_REJ(mppc, MPPC_CONF_STATELESS);
480: break;
481: }
482: }
483:
484: /*
485: * MppcRecvResetReq()
486: */
487:
488: static Mbuf
489: MppcRecvResetReq(Bund b, int id, Mbuf bp, int *noAck)
490: {
491: char path[NG_PATHSIZ];
492: /* Forward ResetReq to the MPPC compression node */
493: snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
494: if (NgSendMsg(gCcpCsock, path,
495: NGM_MPPC_COOKIE, NGM_MPPC_RESETREQ, NULL, 0) < 0) {
496: Perror("[%s] reset-req to %s node", b->name, NG_MPPC_NODE_TYPE);
497: }
498:
499: /* No ResetAck required for MPPC */
500: if (noAck)
501: *noAck = 1;
502: return(NULL);
503: }
504:
505: /*
506: * MppcDescribeBits()
507: */
508:
509: static char *
510: MppcDescribeBits(u_int32_t bits, char *buf, size_t len)
511: {
512: *buf = 0;
513: if (bits & MPPC_BIT)
514: snprintf(buf + strlen(buf), len - strlen(buf), "MPPC");
515: if (bits & MPPE_BITS) {
516: snprintf(buf + strlen(buf), len - strlen(buf), "%sMPPE(", (*buf)?", ":"");
517: if (bits & MPPE_40) {
518: snprintf(buf + strlen(buf), len - strlen(buf), "40");
519: if (bits & (MPPE_56|MPPE_128))
520: snprintf(buf + strlen(buf), len - strlen(buf), ", ");
521: }
522: if (bits & MPPE_56) {
523: snprintf(buf + strlen(buf), len - strlen(buf), "56");
524: if ((bits & MPPE_128))
525: snprintf(buf + strlen(buf), len - strlen(buf), ", ");
526: }
527: if (bits & MPPE_128)
528: snprintf(buf + strlen(buf), len - strlen(buf), "128");
529: snprintf(buf + strlen(buf), len - strlen(buf), " bits)");
530: }
531: if (bits & MPPE_STATELESS)
532: snprintf(buf + strlen(buf), len - strlen(buf), "%sstateless", (*buf)?", ":"");
533: return(buf);
534: }
535:
536: static short
537: MppcEnabledMppeType(Bund b, short type)
538: {
539: MppcInfo const mppc = &b->ccp.mppc;
540: short ret;
541:
542: /* Check if we have kernel support */
543: if (!MPPEPresent)
544: return (0);
545:
546: /* Check if we are able to calculate key */
547: if (!MppcKeyAvailable(b, type))
548: return (0);
549:
550: switch (type) {
551: case 40:
552: if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
553: ret = (b->params.msoft.types & MPPE_TYPE_40BIT) &&
554: !MPPC_PEER_REJECTED(mppc, MPPC_CONF_40);
555: } else {
556: ret = Enabled(&mppc->options, MPPC_CONF_40) &&
557: !MPPC_PEER_REJECTED(mppc, MPPC_CONF_40);
558: }
559: break;
560:
561: case 56:
562: if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
563: ret = (b->params.msoft.types & MPPE_TYPE_56BIT) &&
564: !MPPC_PEER_REJECTED(mppc, MPPC_CONF_56);
565: } else {
566: ret = Enabled(&mppc->options, MPPC_CONF_56) &&
567: !MPPC_PEER_REJECTED(mppc, MPPC_CONF_56);
568: }
569: break;
570:
571: case 128:
572: default:
573: if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
574: ret = (b->params.msoft.types & MPPE_TYPE_128BIT) &&
575: !MPPC_PEER_REJECTED(mppc, MPPC_CONF_128);
576: } else {
577: ret = Enabled(&mppc->options, MPPC_CONF_128) &&
578: !MPPC_PEER_REJECTED(mppc, MPPC_CONF_128);
579: }
580: }
581:
582: return ret;
583: }
584:
585: static short
586: MppcAcceptableMppeType(Bund b, short type)
587: {
588: MppcInfo const mppc = &b->ccp.mppc;
589: short ret;
590:
591: /* Check if we have kernel support */
592: if (!MPPEPresent)
593: return (0);
594:
595: /* Check if we are able to calculate key */
596: if (!MppcKeyAvailable(b, type))
597: return (0);
598:
599: switch (type) {
600: case 40:
601: if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
602: ret = b->params.msoft.types & MPPE_TYPE_40BIT;
603: } else {
604: ret = Acceptable(&mppc->options, MPPC_CONF_40);
605: }
606: break;
607:
608: case 56:
609: if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
610: ret = b->params.msoft.types & MPPE_TYPE_56BIT;
611: } else {
612: ret = Acceptable(&mppc->options, MPPC_CONF_56);
613: }
614: break;
615:
616: case 128:
617: default:
618: if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
619: ret = b->params.msoft.types & MPPE_TYPE_128BIT;
620: } else {
621: ret = Acceptable(&mppc->options, MPPC_CONF_128);
622: }
623: }
624:
625: return ret;
626: }
627:
628: #define KEYLEN(b) (((b) & MPPE_128) ? 16 : 8)
629:
630: /*
631: * MppeInitKey()
632: */
633:
634: static void
635: MppeInitKey(Bund b, MppcInfo mppc, int dir)
636: {
637: u_int32_t const bits = (dir == COMP_DIR_XMIT) ?
638: mppc->xmit_bits : mppc->recv_bits;
639: u_char *const key0 = (dir == COMP_DIR_XMIT) ?
640: mppc->xmit_key0 : mppc->recv_key0;
641: u_char hash[MPPE_KEY_LEN];
642: u_char *chal;
643:
644: /* The secret comes from the originating caller's credentials */
645: chal = b->params.msoft.msChal;
646:
647: /* Compute basis for the session key (ie, "start key" or key0) */
648: if (bits & MPPE_128) {
649: memcpy(hash, b->params.msoft.nt_hash_hash, sizeof(hash));
650: KEYDEBUG((hash, sizeof(hash), "NT Password Hash Hash"));
651: KEYDEBUG((chal, CHAP_MSOFT_CHAL_LEN, "Challenge"));
652: MsoftGetStartKey(chal, hash);
653: KEYDEBUG((hash, sizeof(hash), "NT StartKey"));
654: } else {
655: memcpy(hash, b->params.msoft.lm_hash, 8);
656: KEYDEBUG((hash, sizeof(hash), "LM StartKey"));
657: }
658: memcpy(key0, hash, MPPE_KEY_LEN);
659: KEYDEBUG((key0, (bits & MPPE_128) ? 16 : 8, "InitialKey"));
660: return;
661: }
662:
663: /*
664: * MppeInitKeyv2()
665: */
666:
667: static void
668: MppeInitKeyv2(Bund b, MppcInfo mppc, int dir)
669: {
670: u_char *const key0 = (dir == COMP_DIR_XMIT) ?
671: mppc->xmit_key0 : mppc->recv_key0;
672: u_char hash[MPPE_KEY_LEN];
673: u_char *resp;
674:
675: if (b->params.msoft.has_keys)
676: {
677: memcpy(mppc->xmit_key0, b->params.msoft.xmit_key, MPPE_KEY_LEN);
678: memcpy(mppc->recv_key0, b->params.msoft.recv_key, MPPE_KEY_LEN);
679: return;
680: }
681:
682: /* The secret comes from the originating caller's credentials */
683: resp = b->params.msoft.ntResp;
684:
685: /* Compute basis for the session key (ie, "start key" or key0) */
686: memcpy(hash, b->params.msoft.nt_hash_hash, sizeof(hash));
687: KEYDEBUG((hash, sizeof(hash), "NT Password Hash Hash"));
688: KEYDEBUG((resp, CHAP_MSOFTv2_CHAL_LEN, "Response"));
689: MsoftGetMasterKey(resp, hash);
690: KEYDEBUG((hash, sizeof(hash), "GetMasterKey"));
691: MsoftGetAsymetricStartKey(hash,
692: (dir == COMP_DIR_RECV) ^
693: (b->originate == LINK_ORIGINATE_LOCAL));
694: KEYDEBUG((hash, sizeof(hash), "GetAsymmetricKey"));
695: memcpy(key0, hash, MPPE_KEY_LEN);
696: KEYDEBUG((key0, MPPE_KEY_LEN, "InitialKey"));
697: return;
698: }
699:
700: #ifdef DEBUG_KEYS
701:
702: /*
703: * KeyDebug()
704: */
705:
706: static void
707: KeyDebug(const u_char *data, int len, const char *fmt, ...)
708: {
709: char buf[100];
710: int k;
711: va_list args;
712:
713: va_start(args, fmt);
714: vsnprintf(buf, sizeof(buf), fmt, args);
715: va_end(args);
716: snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":");
717: for (k = 0; k < len; k++) {
718: snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
719: " %02x", (u_char) data[k]);
720: }
721: Log(LG_ERR, ("%s", buf));
722: }
723:
724: #endif /* DEBUG_KEYS */
725:
726: static int
727: MppcKeyAvailable(Bund b, short type) {
728:
729: if (b->params.msoft.chap_alg == CHAP_ALG_MSOFT) {
730: if (((type == 128) && (!b->params.msoft.has_nt_hash)) ||
731: ((type != 128) && (!b->params.msoft.has_lm_hash))) {
732: return (0);
733: }
734: } else {
735: if (!b->params.msoft.has_keys && !b->params.msoft.has_nt_hash) {
736: return (0);
737: }
738: }
739: return (1);
740: }
741:
742: /*
743: * MppcTestCap()
744: */
745:
746: int
747: MppcTestCap(void)
748: {
749: struct ng_mppc_config conf;
750: struct ngm_mkpeer mp;
751: int cs, ds;
752:
753: /* Create a netgraph socket node */
754: if (NgMkSockNode(NULL, &cs, &ds) < 0) {
755: Perror("MppcTestCap: can't create socket node");
756: return(-1);
757: }
758:
759: /* Attach a new MPPC node */
760: strcpy(mp.type, NG_MPPC_NODE_TYPE);
761: strcpy(mp.ourhook, "mppc");
762: strcpy(mp.peerhook, NG_MPPC_HOOK_COMP);
763: if (NgSendMsg(cs, ".",
764: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
765: Perror("MppcTestCap: can't create %s node", mp.type);
766: goto done;
767: }
768:
769: /* Initialize configuration structure */
770: memset(&conf, 0, sizeof(conf));
771: conf.enable = 1;
772: conf.bits = MPPC_BIT;
773:
774: /* Configure MPPC node */
775: if (NgSendMsg(cs, "mppc",
776: NGM_MPPC_COOKIE, NGM_MPPC_CONFIG_COMP, &conf, sizeof(conf)) < 0) {
777: if (errno != EPROTONOSUPPORT) {
778: Perror("MppcTestCap: can't config %s node", NG_MPPC_NODE_TYPE);
779: }
780: } else
781: MPPCPresent = 1;
782:
783: conf.bits = MPPE_128;
784:
785: /* Configure MPPC node */
786: if (NgSendMsg(cs, "mppc",
787: NGM_MPPC_COOKIE, NGM_MPPC_CONFIG_COMP, &conf, sizeof(conf)) < 0) {
788: if (errno != EPROTONOSUPPORT) {
789: Perror("MppcTestCap: can't config %s node", NG_MPPC_NODE_TYPE);
790: }
791: } else
792: MPPEPresent = 1;
793:
794: /* Done */
795: done:
796: close(cs);
797: close(ds);
798: return(0);
799: }
800:
801: /*
802: * MppcStat()
803: */
804:
805: int
806: MppcStat(Context ctx, int ac, char *av[], void *arg)
807: {
808: MppcInfo const mppc = &ctx->bund->ccp.mppc;
809:
810: Printf("MPPC options:\r\n");
811: OptStat(ctx, &mppc->options, gConfList);
812:
813: return(0);
814: }
815:
816: /*
817: * MppcSetCommand()
818: */
819:
820: static int
821: MppcSetCommand(Context ctx, int ac, char *av[], void *arg)
822: {
823: MppcInfo const mppc = &ctx->bund->ccp.mppc;
824:
825: if (ac == 0)
826: return(-1);
827: switch ((intptr_t)arg) {
828: case SET_ACCEPT:
829: AcceptCommand(ac, av, &mppc->options, gConfList);
830: break;
831:
832: case SET_DENY:
833: DenyCommand(ac, av, &mppc->options, gConfList);
834: break;
835:
836: case SET_ENABLE:
837: EnableCommand(ac, av, &mppc->options, gConfList);
838: break;
839:
840: case SET_DISABLE:
841: DisableCommand(ac, av, &mppc->options, gConfList);
842: break;
843:
844: case SET_YES:
845: YesCommand(ac, av, &mppc->options, gConfList);
846: break;
847:
848: case SET_NO:
849: NoCommand(ac, av, &mppc->options, gConfList);
850: break;
851:
852: default:
853: assert(0);
854: }
855: return(0);
856: }
857:
858: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>