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>