$NetBSD$ --- pppd/ccp.c.orig Fri Aug 13 02:46:11 1999 +++ pppd/ccp.c Sat Sep 25 14:31:25 1999 @@ -33,6 +33,9 @@ #include "pppd.h" #include "fsm.h" #include "ccp.h" +#ifdef MPPE +#include "mppe.h" +#endif #include static const char rcsid[] = RCSID; @@ -75,6 +78,32 @@ { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, "don't allow Predictor-1", OPT_A2COPY, &ccp_allowoptions[0].predictor_1 }, +#ifdef MPPE + { "mppe-40", o_special_noarg, setmppe_40, + "Allow 40 bit MPPE encryption" }, + { "+mppe-40", o_special_noarg, setmppe_40, + "Allow 40 bit MPPE encryption" }, + { "nomppe-40", o_special_noarg, setnomppe_40, + "Disallow 40 bit MPPE encryption" }, + { "-mppe-40", o_special_noarg, setnomppe_40, + "Disallow 40 bit MPPE encryption" }, + { "mppe-128", o_special_noarg, setmppe_128, + "Allow 128 bit MPPE encryption" }, + { "+mppe-128", o_special_noarg, setmppe_128, + "Allow 128 bit MPPE encryption" }, + { "nomppe-128", o_special_noarg, setnomppe_128, + "Disallow 128 bit MPPE encryption" }, + { "-mppe-128", o_special_noarg, setnomppe_128, + "Disallow 128 bit MPPE encryption" }, + { "mppe-stateless", o_special_noarg, setmppe_stateless, + "Allow stateless MPPE encryption" }, + { "+mppe-stateless", o_special_noarg, setmppe_stateless, + "Allow stateless MPPE encryption" }, + { "nomppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, + { "-mppe-stateless", o_special_noarg, setnomppe_stateless, + "Disallow stateless MPPE encryption" }, +#endif { NULL } }; @@ -157,8 +186,14 @@ /* * Do we want / did we get any compression? */ +#ifdef MPPE +#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ + || (opt).predictor_1 || (opt).predictor_2 \ + || (opt).mppe ) +#else #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \ || (opt).predictor_1 || (opt).predictor_2) +#endif /* * Local state (mainly for handling reset-reqs and reset-acks). @@ -282,6 +317,16 @@ ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS; ccp_allowoptions[0].predictor_1 = 1; +#ifdef MPPE + ccp_wantoptions[0].mppe = 0; + ccp_wantoptions[0].mppe_stateless = 0; + ccp_wantoptions[0].mppe_40 = 0; + ccp_wantoptions[0].mppe_128 = 0; + ccp_allowoptions[0].mppe_stateless = 1; + ccp_allowoptions[0].mppe = 1; + ccp_allowoptions[0].mppe_40 = 1; + ccp_allowoptions[0].mppe_128 = 1; +#endif /* MPPE*/ } /* @@ -420,7 +465,7 @@ fsm *f; { ccp_options *go = &ccp_gotoptions[f->unit]; - u_char opt_buf[16]; + u_char opt_buf[256]; *go = ccp_wantoptions[f->unit]; all_rejected[f->unit] = 0; @@ -436,6 +481,18 @@ if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) go->bsd_compress = 0; } +#ifdef MPPE + if (go->mppe) { + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + opt_buf[2] = 0; + /* keysize is 8 here */ + BCOPY(mppe_master_send_key_40, opt_buf+3, 8); + BCOPY(mppe_master_recv_key_40, opt_buf+11, 8); + if (ccp_test(f->unit, opt_buf, (2*8)+3, 0) <= 0) + go->mppe = 0; + } +#endif /*MPPE*/ if (go->deflate) { if (go->deflate_correct) { opt_buf[0] = CI_DEFLATE; @@ -481,6 +538,9 @@ return (go->bsd_compress? CILEN_BSD_COMPRESS: 0) + (go->deflate? CILEN_DEFLATE: 0) +#ifdef MPPE + + (go->mppe? CILEN_MPPE: 0) +#endif + (go->predictor_1? CILEN_PREDICTOR_1: 0) + (go->predictor_2? CILEN_PREDICTOR_2: 0); } @@ -529,6 +589,41 @@ p += CILEN_DEFLATE; } } +#ifdef MPPE + if (go->mppe) { + u_char opt_buf[64]; + u_int keysize = 0; + + if(!mppe_allowed) + go->mppe_stateless = go->mppe_40 = go->mppe_128 = 0; + p[0]=CI_MPPE; + p[1]=CILEN_MPPE; + p[2]=(go->mppe_stateless ? MPPE_STATELESS : 0); + p[3]=0; + p[4]=0; + p[5]=(go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0); + if(p[5] & MPPE_40BIT) { + keysize = 8; + BCOPY(mppe_master_send_key_40, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize); + } else if(p[5] & MPPE_128BIT) { + keysize = 16; + BCOPY(mppe_master_send_key_128, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize); + } + if(p[5] != 0) { + opt_buf[0]=CI_MPPE; + opt_buf[1]=CILEN_MPPE; + opt_buf[2] = (go->mppe_stateless) ? 1 : 0; + res = ccp_test(f->unit, opt_buf, (2*keysize)+3, 0); + } else { + res = -1; + } + if (res > 0) { + p += CILEN_MPPE; + } + } +#endif /* MPPE*/ if (go->bsd_compress) { p[0] = CI_BSD_COMPRESS; p[1] = CILEN_BSD_COMPRESS; @@ -612,6 +707,22 @@ len -= CILEN_DEFLATE; } } +#ifdef MPPE + if (go->mppe) { + if ( len < CILEN_MPPE + || p[1] != CILEN_MPPE || p[0] != CI_MPPE + || p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) + || p[3] != 0 + || p[4] != 0 + || p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_128 ? MPPE_128BIT : 0))) + return 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + /* Cope with first/fast ack */ + if (len == 0) + return 1; + } +#endif /* MPPE */ if (go->bsd_compress) { if (len < CILEN_BSD_COMPRESS || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS @@ -690,6 +801,23 @@ } } +#ifdef MPPE + if (len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + no.mppe = 1; + if((p[5] & MPPE_128BIT) == 0) + try.mppe_128 = 0; + if((p[5] & MPPE_40BIT) == 0) + try.mppe_40 = 0; + if((p[2] & MPPE_STATELESS) == 0) + try.mppe_stateless = 0; + if(!try.mppe_128 && !try.mppe_40) { + no.mppe = 0; + try.mppe = 0; + } + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /* MPPE */ if (go->bsd_compress && len >= CILEN_BSD_COMPRESS && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { no.bsd_compress = 1; @@ -762,6 +890,14 @@ if (!try.deflate_correct && !try.deflate_draft) try.deflate = 0; } +#ifdef MPPE + if (go->mppe && len >= CILEN_MPPE + && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { + try.mppe = 0; + p += CILEN_MPPE; + len -= CILEN_MPPE; + } +#endif /*MPPE*/ if (go->bsd_compress && len >= CILEN_BSD_COMPRESS && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) @@ -875,6 +1011,78 @@ } break; +#ifdef MPPE + case CI_MPPE: + if (!ao->mppe || clen != CILEN_MPPE) { + newret = CONFREJ; + break; + } + if(!mppe_allowed) + { + newret = CONFREJ; + break; + } + ho->mppe = 1; + if((p[5]&(MPPE_40BIT|MPPE_128BIT)) == (MPPE_40BIT|MPPE_128BIT)) + { + /* if both are available, select the stronger */ + p[5] &= ~MPPE_40BIT; + newret = CONFNAK; + } + if((p[2] & ~MPPE_STATELESS) != 0 + || p[3] != 0 + || p[4] != 0 + || (p[5] & ~(MPPE_40BIT | MPPE_128BIT)) != 0) + { + ccp_options *wo = &ccp_wantoptions[f->unit]; + /* not sure what they want, tell 'em what we got */ + p[2] &= MPPE_STATELESS; + p[3] &= 0; + p[4] &= 0; + p[5] &= MPPE_40BIT | MPPE_128BIT; + if(wo->mppe_40) + p[5] |= MPPE_40BIT; + if(wo->mppe_128) + p[5] |= MPPE_128BIT; + newret = CONFNAK; + } + + if((newret == CONFACK) || (newret == CONFNAK)) + { + /* + * The kernel ppp driver needs the session key + * which is not sent via CCP :( + */ + unsigned int keysize; + unsigned char opt_buf[64]; + opt_buf[0] = CI_MPPE; + opt_buf[1] = CILEN_MPPE; + opt_buf[2] = ((p[2] & MPPE_STATELESS) ? 1 : 0); + /* push in our send/receive keys */ + if(p[5] & MPPE_40BIT) { + ho->mppe_40 = 1; + keysize = 8; + BCOPY(mppe_master_send_key_40, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_40, opt_buf+11, keysize); + } else if(p[5] & MPPE_128BIT) { + ho->mppe_128 = 1; + keysize = 16; + BCOPY(mppe_master_send_key_128, opt_buf+3, keysize); + BCOPY(mppe_master_recv_key_128, opt_buf+19, keysize); + } else { + ho->mppe = 0; + newret = CONFREJ; + break; + } + /* call ioctl and pass this nasty stuff to the kernel */ + if (ccp_test(f->unit, opt_buf, (2*keysize)+3, 1) <= 0){ + ho->mppe = 0; + newret = CONFREJ; + break; + } + } + break; +#endif /* MPPE */ case CI_BSD_COMPRESS: if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) { newret = CONFREJ; @@ -996,6 +1204,28 @@ (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""), opt->deflate_size); break; +#ifdef MPPE + case CI_MPPE: + if (opt->mppe_40) { + if (opt->mppe_stateless) { + return "MPPE 40 bit, stateless"; + } else { + return "MPPE 40 bit, non-stateless"; + } + } else if (opt->mppe_128) { + if (opt->mppe_stateless) { + return "MPPE 128 bit, stateless"; + } else { + return "MPPE 128 bit, non-stateless"; + } + } else { + if (opt->mppe_stateless) { + return "MPPE unknown strength, stateless"; + } else { + return "MPPE unknown strength, stateless"; + } + } +#endif case CI_BSD_COMPRESS: if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits) slprintf(result, sizeof(result), "BSD-Compress (%d/%d)", @@ -1134,6 +1364,14 @@ p += CILEN_PREDICTOR_1; } break; +#ifdef MPPE + case CI_MPPE: + if (optlen >= CILEN_MPPE) { + printer(arg, "mppe %x %x %x %x",p[2],p[3],p[4],p[5]); + p += CILEN_MPPE; + } + break; +#endif case CI_PREDICTOR_2: if (optlen >= CILEN_PREDICTOR_2) { printer(arg, "predictor 2"); @@ -1193,6 +1431,11 @@ error("Lost compression sync: disabling compression"); ccp_close(unit, "Lost compression sync"); } else { +#ifdef MPPE + /* MPPE/MPPC does not requires CCP_RESETREQ */ + if (ccp_gotoptions[f->unit].method == CI_MPPE) + return; +#endif /* * Send a reset-request to reset the peer's compressor. * We don't do that if we are still waiting for an