Annotation of embedaddon/mpd/src/ccp_mppc.c, revision 1.1.1.2

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);
1.1.1.2 ! misho      69:   static int   MppcSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1       misho      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 },
1.1.1.2 ! misho     133:     { NULL, NULL, NULL, NULL, 0, NULL },
1.1       misho     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: 
1.1.1.2 ! misho     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: 
1.1       misho     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);
1.1.1.2 ! misho     217:        goto fail;
1.1       misho     218:     }
                    219: 
                    220:     /* Done */
                    221:     return(0);
1.1.1.2 ! misho     222: 
        !           223: fail:
        !           224:     NgFuncShutdownNode(gCcpCsock, b->name, path);
        !           225:     return(-1);
1.1       misho     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];
1.1.1.2 ! misho     499: 
        !           500:     (void)id;
        !           501:     (void)bp;
        !           502: 
1.1       misho     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
1.1.1.2 ! misho     817: MppcStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     818: {
                    819:   MppcInfo     const mppc = &ctx->bund->ccp.mppc;
                    820: 
1.1.1.2 ! misho     821:   (void)ac;
        !           822:   (void)av;
        !           823:   (void)arg;
        !           824: 
1.1       misho     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
1.1.1.2 ! misho     836: MppcSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1       misho     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>