File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ccp_mppc.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (3 years, 4 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

    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, const char *const av[], const 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, NULL, NULL, NULL, 0, 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:     if ((id = NgGetNodeID(-1, path)) == 0) {
  201: 	Perror("[%s] Cannot get %s node id", b->name, NG_MPPC_NODE_TYPE);
  202: 	goto fail;
  203:     }
  204: 
  205:     if (dir == COMP_DIR_XMIT) {
  206: 	b->ccp.comp_node_id = id;
  207:     } else {
  208: 	b->ccp.decomp_node_id = id;
  209:     }
  210: 
  211:     /* Configure MPPC node */
  212:     snprintf(path, sizeof(path), "[%x]:", id);
  213:     if (NgSendMsg(gCcpCsock, path,
  214:     	    NGM_MPPC_COOKIE, cmd, &conf, sizeof(conf)) < 0) {
  215: 	Perror("[%s] can't config %s node at %s",
  216:     	    b->name, NG_MPPC_NODE_TYPE, path);
  217: 	goto fail;
  218:     }
  219: 
  220:     /* Done */
  221:     return(0);
  222: 
  223: fail:
  224:     NgFuncShutdownNode(gCcpCsock, b->name, path);
  225:     return(-1);
  226: }
  227: 
  228: static int
  229: MppcConfigure(Bund b)
  230: {
  231:     MppcInfo	const mppc = &b->ccp.mppc;
  232: 
  233:     mppc->peer_reject = 0;
  234:     mppc->recv_bits = 0;
  235:     mppc->xmit_bits = 0;
  236: 
  237:     if (Enabled(&mppc->options, MPPC_CONF_COMPRESS)
  238:       && MPPCPresent)
  239: 	return (0);
  240: 
  241:     if (MppcEnabledMppeType(b, 40) || MppcAcceptableMppeType(b, 40)) 
  242: 	return (0);
  243:     if (MppcEnabledMppeType(b, 56) || MppcAcceptableMppeType(b, 56)) 
  244: 	return (0);
  245:     if (MppcEnabledMppeType(b, 128) || MppcAcceptableMppeType(b, 128)) 
  246: 	return (0);
  247:     
  248:     return (-1);
  249: }
  250: 
  251: /*
  252:  * MppcDescribe()
  253:  */
  254: 
  255: static char *
  256: MppcDescribe(Bund b, int dir, char *buf, size_t len)
  257: {
  258:   MppcInfo	const mppc = &b->ccp.mppc;
  259: 
  260:   switch (dir) {
  261:     case COMP_DIR_XMIT:
  262:       return(MppcDescribeBits(mppc->xmit_bits, buf, len));
  263:     case COMP_DIR_RECV:
  264:       return(MppcDescribeBits(mppc->recv_bits, buf, len));
  265:     default:
  266:       assert(0);
  267:       return(NULL);
  268:   }
  269: }
  270: 
  271: /*
  272:  * MppcSubtractBloat()
  273:  */
  274: 
  275: static int
  276: MppcSubtractBloat(Bund b, int size)
  277: {
  278: 
  279:   /* Account for MPPC header */
  280:   size -= 2;
  281: 
  282:   /* Account for possible expansion with MPPC compression */
  283:   if ((b->ccp.mppc.xmit_bits & MPPC_BIT) != 0) {
  284:     int	l, h, size0 = size;
  285: 
  286:     while (1) {
  287:       l = MPPC_MAX_BLOWUP(size0);
  288:       h = MPPC_MAX_BLOWUP(size0 + 1);
  289:       if (l > size) {
  290: 	size0 -= 20;
  291:       } else if (h > size) {
  292: 	size = size0;
  293: 	break;
  294:       } else {
  295: 	size0++;
  296:       }
  297:     }
  298:   }
  299: 
  300:   /* Done */
  301:   return(size);
  302: }
  303: 
  304: /*
  305:  * MppcNegotiated()
  306:  */
  307: 
  308: static int
  309: MppcNegotiated(Bund b, int dir)
  310: {
  311:   MppcInfo	const mppc = &b->ccp.mppc;
  312: 
  313:   switch (dir) {
  314:     case COMP_DIR_XMIT:
  315:       return(mppc->xmit_bits != 0);
  316:     case COMP_DIR_RECV:
  317:       return(mppc->recv_bits != 0);
  318:     default:
  319:       assert(0);
  320:       return(0);
  321:   }
  322: }
  323: 
  324: /*
  325:  * MppcCleanup()
  326:  */
  327: 
  328: static void
  329: MppcCleanup(Bund b, int dir)
  330: {
  331:     char		path[NG_PATHSIZ];
  332: 
  333:     /* Remove node */
  334:     if (dir == COMP_DIR_XMIT) {
  335: 	snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
  336: 	b->ccp.comp_node_id = 0;
  337:     } else {
  338: 	snprintf(path, sizeof(path), "[%x]:", b->ccp.decomp_node_id);
  339: 	b->ccp.decomp_node_id = 0;
  340:     }
  341:     NgFuncShutdownNode(gCcpCsock, b->name, path);
  342: }
  343: 
  344: /*
  345:  * MppcBuildConfigReq()
  346:  */
  347: 
  348: static u_char *
  349: MppcBuildConfigReq(Bund b, u_char *cp, int *ok)
  350: {
  351:   MppcInfo	const mppc = &b->ccp.mppc;
  352:   u_int32_t	bits = 0;
  353: 
  354:   /* Compression */
  355:   if (Enabled(&mppc->options, MPPC_CONF_COMPRESS)
  356:       && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_COMPRESS)
  357:       && MPPCPresent)
  358:     bits |= MPPC_BIT;
  359: 
  360:   /* Encryption */
  361:   if (MppcEnabledMppeType(b, 40)
  362:       && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_40)) 
  363:     bits |= MPPE_40;
  364:   if (MppcEnabledMppeType(b, 56)
  365:       && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_56)) 
  366:     bits |= MPPE_56;
  367:   if (MppcEnabledMppeType(b, 128)
  368:       && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_128)) 
  369:     bits |= MPPE_128;
  370: 
  371:   /* Stateless mode */
  372:   if (Enabled(&mppc->options, MPPC_CONF_STATELESS)
  373:       && !MPPC_PEER_REJECTED(mppc, MPPC_CONF_STATELESS)
  374:       && bits != 0)
  375:     bits |= MPPE_STATELESS;
  376: 
  377:   /* Ship it */
  378:   mppc->xmit_bits = bits;
  379:   if (bits != 0) {
  380:     cp = FsmConfValue(cp, CCP_TY_MPPC, -4, &bits);
  381:     *ok = 1;
  382:   } else {
  383:     *ok = 0;
  384:   }
  385:   return(cp);
  386: }
  387: 
  388: /*
  389:  * MppcDecodeConfigReq()
  390:  */
  391: 
  392: static void
  393: MppcDecodeConfigReq(Fsm fp, FsmOption opt, int mode)
  394: {
  395:     Bund 	b = (Bund)fp->arg;
  396:   MppcInfo	const mppc = &b->ccp.mppc;
  397:   u_int32_t	orig_bits;
  398:   u_int32_t	bits;
  399:   char		buf[64];
  400: 
  401:   /* Get bits */
  402:   memcpy(&orig_bits, opt->data, 4);
  403:   orig_bits = ntohl(orig_bits);
  404:   bits = orig_bits;
  405: 
  406:   /* Sanity check */
  407:   if (opt->len != 6) {
  408:     Log(LG_CCP, ("[%s]     bogus length %d", b->name, opt->len));
  409:     if (mode == MODE_REQ)
  410:       FsmRej(fp, opt);
  411:     return;
  412:   }
  413: 
  414:   /* Display it */
  415:   Log(LG_CCP, ("[%s]     0x%08x:%s", b->name, bits, MppcDescribeBits(bits, buf, sizeof(buf))));
  416: 
  417:   /* Deal with it */
  418:   switch (mode) {
  419:     case MODE_REQ:
  420: 
  421:       /* Check for supported bits */
  422:       if (bits & ~MPPC_SUPPORTED) {
  423: 	Log(LG_CCP, ("[%s]     Bits 0x%08x not supported", b->name, bits & ~MPPC_SUPPORTED));
  424: 	bits &= MPPC_SUPPORTED;
  425:       }
  426: 
  427:       /* Check compression */
  428:       if (!Acceptable(&mppc->options, MPPC_CONF_COMPRESS) || !MPPCPresent)
  429: 	bits &= ~MPPC_BIT;
  430: 
  431:       /* Check encryption */
  432:       if (!MppcAcceptableMppeType(b, 40))
  433: 	bits &= ~MPPE_40;
  434:       if (!MppcAcceptableMppeType(b, 56))
  435: 	bits &= ~MPPE_56;
  436:       if (!MppcAcceptableMppeType(b, 128))
  437: 	bits &= ~MPPE_128;
  438: 
  439:       /* Choose the strongest encryption available */
  440:       if (bits & MPPE_128)
  441: 	bits &= ~(MPPE_40|MPPE_56);
  442:       else if (bits & MPPE_56)
  443: 	bits &= ~MPPE_40;
  444: 
  445:       /* It doesn't really make sense to encrypt in only one direction.
  446: 	 Also, Win95/98 PPTP can't handle uni-directional encryption. So
  447: 	 if the remote side doesn't request encryption, try to prompt it.
  448: 	 This is broken wrt. normal PPP negotiation: typical Microsoft. */
  449:       if ((bits & MPPE_BITS) == 0) {
  450: 	if (MppcAcceptableMppeType(b, 40)) bits |= MPPE_40;
  451: 	if (MppcAcceptableMppeType(b, 56)) bits |= MPPE_56;
  452: 	if (MppcAcceptableMppeType(b, 128)) bits |= MPPE_128;
  453:       }
  454: 
  455:       /* Stateless mode */
  456:       if ((bits & MPPE_STATELESS) && 
  457:     	  (!Acceptable(&mppc->options, MPPC_CONF_STATELESS)
  458: 	    || (bits & (MPPE_BITS|MPPC_BIT)) == 0))
  459: 	bits &= ~MPPE_STATELESS;
  460: 
  461:       /* See if what we want equals what was sent */
  462:       mppc->recv_bits = bits;
  463:       if (bits) {
  464:         if (bits != orig_bits) {
  465: 	    bits = htonl(bits);
  466: 	    memcpy(opt->data, &bits, 4);
  467: 	    FsmNak(fp, opt);
  468:         }
  469:         else
  470: 	    FsmAck(fp, opt);
  471:       }
  472:       else
  473:         FsmRej(fp, opt);
  474:       break;
  475: 
  476:     case MODE_NAK:
  477:       if (!(bits & MPPC_BIT))
  478: 	MPPC_PEER_REJ(mppc, MPPC_CONF_COMPRESS);
  479:       if (!(bits & MPPE_40))
  480: 	MPPC_PEER_REJ(mppc, MPPC_CONF_40);
  481:       if (!(bits & MPPE_56))
  482: 	MPPC_PEER_REJ(mppc, MPPC_CONF_56);
  483:       if (!(bits & MPPE_128))
  484: 	MPPC_PEER_REJ(mppc, MPPC_CONF_128);
  485:       if (!(bits & MPPE_STATELESS))
  486: 	MPPC_PEER_REJ(mppc, MPPC_CONF_STATELESS);
  487:       break;
  488:   }
  489: }
  490: 
  491: /*
  492:  * MppcRecvResetReq()
  493:  */
  494: 
  495: static Mbuf
  496: MppcRecvResetReq(Bund b, int id, Mbuf bp, int *noAck)
  497: {
  498:     char		path[NG_PATHSIZ];
  499: 
  500:     (void)id;
  501:     (void)bp;
  502: 
  503:     /* Forward ResetReq to the MPPC compression node */
  504:     snprintf(path, sizeof(path), "[%x]:", b->ccp.comp_node_id);
  505:     if (NgSendMsg(gCcpCsock, path,
  506:     	    NGM_MPPC_COOKIE, NGM_MPPC_RESETREQ, NULL, 0) < 0) {
  507: 	Perror("[%s] reset-req to %s node", b->name, NG_MPPC_NODE_TYPE);
  508:     }
  509: 
  510:     /* No ResetAck required for MPPC */
  511:     if (noAck)
  512: 	*noAck = 1;
  513:     return(NULL);
  514: }
  515: 
  516: /*
  517:  * MppcDescribeBits()
  518:  */
  519: 
  520: static char *
  521: MppcDescribeBits(u_int32_t bits, char *buf, size_t len)
  522: {
  523:   *buf = 0;
  524:   if (bits & MPPC_BIT)
  525:     snprintf(buf + strlen(buf), len - strlen(buf), "MPPC");
  526:   if (bits & MPPE_BITS) {
  527:     snprintf(buf + strlen(buf), len - strlen(buf), "%sMPPE(", (*buf)?", ":"");
  528:     if (bits & MPPE_40) {
  529:       snprintf(buf + strlen(buf), len - strlen(buf), "40");
  530:       if (bits & (MPPE_56|MPPE_128))
  531:         snprintf(buf + strlen(buf), len - strlen(buf), ", ");
  532:     }
  533:     if (bits & MPPE_56) {
  534:       snprintf(buf + strlen(buf), len - strlen(buf), "56");
  535:       if ((bits & MPPE_128))
  536:         snprintf(buf + strlen(buf), len - strlen(buf), ", ");
  537:     }
  538:     if (bits & MPPE_128)
  539:       snprintf(buf + strlen(buf), len - strlen(buf), "128");
  540:     snprintf(buf + strlen(buf), len - strlen(buf), " bits)");
  541:   }
  542:   if (bits & MPPE_STATELESS)
  543:     snprintf(buf + strlen(buf), len - strlen(buf), "%sstateless", (*buf)?", ":"");
  544:   return(buf);
  545: }
  546: 
  547: static short
  548: MppcEnabledMppeType(Bund b, short type)
  549: {
  550:     MppcInfo	const mppc = &b->ccp.mppc;
  551:     short	ret;
  552: 
  553:     /* Check if we have kernel support */
  554:     if (!MPPEPresent)
  555: 	return (0);
  556:     
  557:     /* Check if we are able to calculate key */
  558:     if (!MppcKeyAvailable(b, type))
  559: 	return (0);
  560: 
  561:     switch (type) {
  562:     case 40:
  563: 	if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
  564:     	    ret = (b->params.msoft.types & MPPE_TYPE_40BIT) &&
  565: 		!MPPC_PEER_REJECTED(mppc, MPPC_CONF_40);
  566: 	} else {
  567:     	    ret = Enabled(&mppc->options, MPPC_CONF_40) &&
  568: 		!MPPC_PEER_REJECTED(mppc, MPPC_CONF_40);
  569: 	}
  570: 	break;
  571: 
  572:     case 56:
  573: 	if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
  574:     	    ret = (b->params.msoft.types & MPPE_TYPE_56BIT) &&
  575: 		!MPPC_PEER_REJECTED(mppc, MPPC_CONF_56);
  576: 	} else {
  577:     	    ret = Enabled(&mppc->options, MPPC_CONF_56) &&
  578: 		!MPPC_PEER_REJECTED(mppc, MPPC_CONF_56);
  579: 	}
  580: 	break;
  581:       
  582:     case 128:
  583:     default:
  584: 	if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
  585:     	    ret = (b->params.msoft.types & MPPE_TYPE_128BIT) &&
  586: 		!MPPC_PEER_REJECTED(mppc, MPPC_CONF_128);
  587: 	} else {
  588:     	    ret = Enabled(&mppc->options, MPPC_CONF_128) &&
  589: 		!MPPC_PEER_REJECTED(mppc, MPPC_CONF_128);
  590: 	}
  591:     }
  592: 
  593:     return ret;
  594: }
  595: 
  596: static short
  597: MppcAcceptableMppeType(Bund b, short type)
  598: {
  599:     MppcInfo	const mppc = &b->ccp.mppc;
  600:     short	ret;
  601:   
  602:     /* Check if we have kernel support */
  603:     if (!MPPEPresent)
  604: 	return (0);
  605:     
  606:     /* Check if we are able to calculate key */
  607:     if (!MppcKeyAvailable(b, type))
  608: 	return (0);
  609: 
  610:     switch (type) {
  611:     case 40:
  612: 	if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
  613:     	    ret = b->params.msoft.types & MPPE_TYPE_40BIT;
  614: 	} else {
  615:     	    ret = Acceptable(&mppc->options, MPPC_CONF_40);
  616: 	}
  617: 	break;
  618: 
  619:     case 56:
  620: 	if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
  621:     	    ret = b->params.msoft.types & MPPE_TYPE_56BIT;
  622: 	} else {
  623:     	    ret = Acceptable(&mppc->options, MPPC_CONF_56);
  624: 	}
  625: 	break;
  626:       
  627:     case 128:
  628:     default:
  629: 	if (Enabled(&mppc->options, MPPC_CONF_POLICY)) {
  630:     	    ret = b->params.msoft.types & MPPE_TYPE_128BIT;
  631: 	} else {
  632:     	    ret = Acceptable(&mppc->options, MPPC_CONF_128);
  633: 	}
  634:     }
  635: 
  636:     return ret;
  637: }
  638: 
  639: #define KEYLEN(b)	(((b) & MPPE_128) ? 16 : 8)
  640: 
  641: /*
  642:  * MppeInitKey()
  643:  */
  644: 
  645: static void
  646: MppeInitKey(Bund b, MppcInfo mppc, int dir)
  647: {
  648:   u_int32_t	const bits = (dir == COMP_DIR_XMIT) ?
  649: 			mppc->xmit_bits : mppc->recv_bits;
  650:   u_char	*const key0 = (dir == COMP_DIR_XMIT) ?
  651: 			mppc->xmit_key0 : mppc->recv_key0;
  652:   u_char	hash[MPPE_KEY_LEN];
  653:   u_char	*chal;
  654: 
  655:   /* The secret comes from the originating caller's credentials */
  656:   chal = b->params.msoft.msChal;
  657: 
  658:   /* Compute basis for the session key (ie, "start key" or key0) */
  659:   if (bits & MPPE_128) {
  660:     memcpy(hash, b->params.msoft.nt_hash_hash, sizeof(hash));
  661:     KEYDEBUG((hash, sizeof(hash), "NT Password Hash Hash"));
  662:     KEYDEBUG((chal, CHAP_MSOFT_CHAL_LEN, "Challenge"));
  663:     MsoftGetStartKey(chal, hash);
  664:     KEYDEBUG((hash, sizeof(hash), "NT StartKey"));
  665:   } else {
  666:     memcpy(hash, b->params.msoft.lm_hash, 8);
  667:     KEYDEBUG((hash, sizeof(hash), "LM StartKey"));
  668:   }
  669:   memcpy(key0, hash, MPPE_KEY_LEN);
  670:   KEYDEBUG((key0, (bits & MPPE_128) ? 16 : 8, "InitialKey"));
  671:   return;
  672: }
  673: 
  674: /*
  675:  * MppeInitKeyv2()
  676:  */
  677: 
  678: static void
  679: MppeInitKeyv2(Bund b, MppcInfo mppc, int dir)
  680: {
  681:   u_char	*const key0 = (dir == COMP_DIR_XMIT) ?
  682: 			mppc->xmit_key0 : mppc->recv_key0;
  683:   u_char	hash[MPPE_KEY_LEN];
  684:   u_char	*resp;
  685: 
  686:   if (b->params.msoft.has_keys)
  687:   { 
  688:     memcpy(mppc->xmit_key0, b->params.msoft.xmit_key, MPPE_KEY_LEN);
  689:     memcpy(mppc->recv_key0, b->params.msoft.recv_key, MPPE_KEY_LEN);
  690:     return;
  691:   }
  692: 
  693:   /* The secret comes from the originating caller's credentials */
  694:   resp = b->params.msoft.ntResp;
  695: 
  696:   /* Compute basis for the session key (ie, "start key" or key0) */
  697:   memcpy(hash, b->params.msoft.nt_hash_hash, sizeof(hash));
  698:   KEYDEBUG((hash, sizeof(hash), "NT Password Hash Hash"));
  699:   KEYDEBUG((resp, CHAP_MSOFTv2_CHAL_LEN, "Response"));
  700:   MsoftGetMasterKey(resp, hash);
  701:   KEYDEBUG((hash, sizeof(hash), "GetMasterKey"));
  702:   MsoftGetAsymetricStartKey(hash,
  703:     (dir == COMP_DIR_RECV) ^
  704:       (b->originate == LINK_ORIGINATE_LOCAL));
  705:   KEYDEBUG((hash, sizeof(hash), "GetAsymmetricKey"));
  706:   memcpy(key0, hash, MPPE_KEY_LEN);
  707:   KEYDEBUG((key0, MPPE_KEY_LEN, "InitialKey"));
  708:   return;
  709: }
  710: 
  711: #ifdef DEBUG_KEYS
  712: 
  713: /*
  714:  * KeyDebug()
  715:  */
  716: 
  717: static void
  718: KeyDebug(const u_char *data, int len, const char *fmt, ...)
  719: {
  720:   char		buf[100];
  721:   int		k;
  722:   va_list	args;
  723: 
  724:   va_start(args, fmt);
  725:   vsnprintf(buf, sizeof(buf), fmt, args);
  726:   va_end(args);
  727:   snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ":");
  728:   for (k = 0; k < len; k++) {
  729:     snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
  730:       " %02x", (u_char) data[k]);
  731:   }
  732:   Log(LG_ERR, ("%s", buf));
  733: }
  734: 
  735: #endif	/* DEBUG_KEYS */
  736: 
  737: static int
  738: MppcKeyAvailable(Bund b, short type) {
  739: 
  740:     if (b->params.msoft.chap_alg == CHAP_ALG_MSOFT) {
  741: 	if (((type == 128) && (!b->params.msoft.has_nt_hash)) ||
  742: 	    ((type != 128) && (!b->params.msoft.has_lm_hash))) {
  743: 		return (0);
  744: 	}
  745:     } else {
  746: 	if (!b->params.msoft.has_keys && !b->params.msoft.has_nt_hash) {
  747: 	    return (0);
  748: 	}
  749:     }
  750:     return (1);
  751: }
  752: 
  753: /*
  754:  * MppcTestCap()
  755:  */
  756: 
  757: int
  758: MppcTestCap(void)
  759: {
  760:     struct ng_mppc_config	conf;
  761:     struct ngm_mkpeer		mp;
  762:     int				cs, ds;
  763: 
  764:     /* Create a netgraph socket node */
  765:     if (NgMkSockNode(NULL, &cs, &ds) < 0) {
  766: 	Perror("MppcTestCap: can't create socket node");
  767:     	return(-1);
  768:     }
  769: 
  770:     /* Attach a new MPPC node */
  771:     strcpy(mp.type, NG_MPPC_NODE_TYPE);
  772:     strcpy(mp.ourhook, "mppc");
  773:     strcpy(mp.peerhook, NG_MPPC_HOOK_COMP);
  774:     if (NgSendMsg(cs, ".",
  775:       NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
  776: 	Perror("MppcTestCap: can't create %s node", mp.type);
  777: 	goto done;
  778:     }
  779: 
  780:     /* Initialize configuration structure */
  781:     memset(&conf, 0, sizeof(conf));
  782:     conf.enable = 1;
  783:     conf.bits = MPPC_BIT;
  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: 	MPPCPresent = 1;
  793: 
  794:     conf.bits = MPPE_128;
  795: 
  796:     /* Configure MPPC node */
  797:     if (NgSendMsg(cs, "mppc",
  798:       NGM_MPPC_COOKIE, NGM_MPPC_CONFIG_COMP, &conf, sizeof(conf)) < 0) {
  799:         if (errno != EPROTONOSUPPORT) {
  800: 	    Perror("MppcTestCap: can't config %s node", NG_MPPC_NODE_TYPE);
  801: 	}
  802:     } else 
  803: 	MPPEPresent = 1;
  804: 
  805:     /* Done */
  806: done:
  807:     close(cs);
  808:     close(ds);
  809:     return(0);
  810: }
  811: 
  812: /*
  813:  * MppcStat()
  814:  */
  815: 
  816: int
  817: MppcStat(Context ctx, int ac, const char *const av[], const void *arg)
  818: {
  819:   MppcInfo	const mppc = &ctx->bund->ccp.mppc;
  820: 
  821:   (void)ac;
  822:   (void)av;
  823:   (void)arg;
  824: 
  825:   Printf("MPPC options:\r\n");
  826:   OptStat(ctx, &mppc->options, gConfList);
  827: 
  828:   return(0);
  829: }
  830: 
  831: /*
  832:  * MppcSetCommand()
  833:  */
  834: 
  835: static int
  836: MppcSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
  837: {
  838:   MppcInfo	const mppc = &ctx->bund->ccp.mppc;
  839: 
  840:   if (ac == 0)
  841:     return(-1);
  842:   switch ((intptr_t)arg) {
  843:     case SET_ACCEPT:
  844:       AcceptCommand(ac, av, &mppc->options, gConfList);
  845:       break;
  846: 
  847:     case SET_DENY:
  848:       DenyCommand(ac, av, &mppc->options, gConfList);
  849:       break;
  850: 
  851:     case SET_ENABLE:
  852:       EnableCommand(ac, av, &mppc->options, gConfList);
  853:       break;
  854: 
  855:     case SET_DISABLE:
  856:       DisableCommand(ac, av, &mppc->options, gConfList);
  857:       break;
  858: 
  859:     case SET_YES:
  860:       YesCommand(ac, av, &mppc->options, gConfList);
  861:       break;
  862: 
  863:     case SET_NO:
  864:       NoCommand(ac, av, &mppc->options, gConfList);
  865:       break;
  866: 
  867:     default:
  868:       assert(0);
  869:   }
  870:   return(0);
  871: }
  872: 
  873: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>