📄 ccp.c
字号:
do { numbits += auth_mschap_bits & 1; auth_mschap_bits >>= 1; } while (auth_mschap_bits); if (numbits > 1) { error("MPPE required, but auth done in both directions."); lcp_close(f->unit, "MPPE required but not available"); return; } if (!numbits) { error("MPPE required, but MS-CHAP[v2] auth not performed."); lcp_close(f->unit, "MPPE required but not available"); return; } /* A plugin (eg radius) may not have obtained key material. */ if (!mppe_keys_set) { error("MPPE required, but keys are not available. " "Possible plugin problem?"); lcp_close(f->unit, "MPPE required but not available"); return; } /* LM auth not supported for MPPE */ if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) { /* This might be noise */ if (go->mppe & MPPE_OPT_40) { notice("Disabling 40-bit MPPE; MS-CHAP LM not supported"); go->mppe &= ~MPPE_OPT_40; ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40; } } /* Last check: can we actually negotiate something? */ if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) { /* Could be misconfig, could be 40-bit disabled above. */ error("MPPE required, but both 40-bit and 128-bit disabled."); lcp_close(f->unit, "MPPE required but not available"); return; } /* sync options */ ao->mppe = go->mppe; /* MPPE is not compatible with other compression types */ ao->bsd_compress = go->bsd_compress = 0; ao->predictor_1 = go->predictor_1 = 0; ao->predictor_2 = go->predictor_2 = 0; ao->deflate = go->deflate = 0; }#endif /* MPPE */ /* * Check whether the kernel knows about the various * compression methods we might request. */#ifdef MPPE if (go->mppe) { opt_buf[0] = CI_MPPE; opt_buf[1] = CILEN_MPPE; MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); /* Key material unimportant here. */ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) { error("MPPE required, but kernel has no support."); lcp_close(f->unit, "MPPE required but not available"); } }#endif if (go->bsd_compress) { opt_buf[0] = CI_BSD_COMPRESS; opt_buf[1] = CILEN_BSD_COMPRESS; opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS); if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0) go->bsd_compress = 0; } if (go->deflate) { if (go->deflate_correct) { opt_buf[0] = CI_DEFLATE; opt_buf[1] = CILEN_DEFLATE; opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); opt_buf[3] = DEFLATE_CHK_SEQUENCE; if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) go->deflate_correct = 0; } if (go->deflate_draft) { opt_buf[0] = CI_DEFLATE_DRAFT; opt_buf[1] = CILEN_DEFLATE; opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_WORKS); opt_buf[3] = DEFLATE_CHK_SEQUENCE; if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0) go->deflate_draft = 0; } if (!go->deflate_correct && !go->deflate_draft) go->deflate = 0; } if (go->predictor_1) { opt_buf[0] = CI_PREDICTOR_1; opt_buf[1] = CILEN_PREDICTOR_1; if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0) go->predictor_1 = 0; } if (go->predictor_2) { opt_buf[0] = CI_PREDICTOR_2; opt_buf[1] = CILEN_PREDICTOR_2; if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0) go->predictor_2 = 0; }}/* * ccp_cilen - Return total length of our configuration info. */static intccp_cilen(f) fsm *f;{ ccp_options *go = &ccp_gotoptions[f->unit]; return (go->bsd_compress? CILEN_BSD_COMPRESS: 0) + (go->deflate? CILEN_DEFLATE: 0) + (go->predictor_1? CILEN_PREDICTOR_1: 0) + (go->predictor_2? CILEN_PREDICTOR_2: 0) + (go->mppe? CILEN_MPPE: 0);}/* * ccp_addci - put our requests in a packet. */static voidccp_addci(f, p, lenp) fsm *f; u_char *p; int *lenp;{ int res; ccp_options *go = &ccp_gotoptions[f->unit]; u_char *p0 = p; /* * Add the compression types that we can receive, in decreasing * preference order. Get the kernel to allocate the first one * in case it gets Acked. */#ifdef MPPE if (go->mppe) { u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN]; p[0] = opt_buf[0] = CI_MPPE; p[1] = opt_buf[1] = CILEN_MPPE; MPPE_OPTS_TO_CI(go->mppe, &p[2]); MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN); res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0); if (res > 0) p += CILEN_MPPE; else /* This shouldn't happen, we've already tested it! */ lcp_close(f->unit, "MPPE required but not available in kernel"); }#endif if (go->deflate) { p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT; p[1] = CILEN_DEFLATE; p[2] = DEFLATE_MAKE_OPT(go->deflate_size); p[3] = DEFLATE_CHK_SEQUENCE; if (p != p0) { p += CILEN_DEFLATE; } else { for (;;) { if (go->deflate_size < DEFLATE_MIN_WORKS) { go->deflate = 0; break; } res = ccp_test(f->unit, p, CILEN_DEFLATE, 0); if (res > 0) { p += CILEN_DEFLATE; break; } else if (res < 0) { go->deflate = 0; break; } --go->deflate_size; p[2] = DEFLATE_MAKE_OPT(go->deflate_size); } } if (p != p0 && go->deflate_correct && go->deflate_draft) { p[0] = CI_DEFLATE_DRAFT; p[1] = CILEN_DEFLATE; p[2] = p[2 - CILEN_DEFLATE]; p[3] = DEFLATE_CHK_SEQUENCE; p += CILEN_DEFLATE; } } if (go->bsd_compress) { p[0] = CI_BSD_COMPRESS; p[1] = CILEN_BSD_COMPRESS; p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); if (p != p0) { p += CILEN_BSD_COMPRESS; /* not the first option */ } else { for (;;) { if (go->bsd_bits < BSD_MIN_BITS) { go->bsd_compress = 0; break; } res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0); if (res > 0) { p += CILEN_BSD_COMPRESS; break; } else if (res < 0) { go->bsd_compress = 0; break; } --go->bsd_bits; p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits); } } } /* XXX Should Predictor 2 be preferable to Predictor 1? */ if (go->predictor_1) { p[0] = CI_PREDICTOR_1; p[1] = CILEN_PREDICTOR_1; if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) { go->predictor_1 = 0; } else { p += CILEN_PREDICTOR_1; } } if (go->predictor_2) { p[0] = CI_PREDICTOR_2; p[1] = CILEN_PREDICTOR_2; if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) { go->predictor_2 = 0; } else { p += CILEN_PREDICTOR_2; } } go->method = (p > p0)? p0[0]: -1; *lenp = p - p0;}/* * ccp_ackci - process a received configure-ack, and return * 1 iff the packet was OK. */static intccp_ackci(f, p, len) fsm *f; u_char *p; int len;{ ccp_options *go = &ccp_gotoptions[f->unit]; u_char *p0 = p;#ifdef MPPE if (go->mppe) { u_char opt_buf[CILEN_MPPE]; opt_buf[0] = CI_MPPE; opt_buf[1] = CILEN_MPPE; MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]); if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE)) return 0; p += CILEN_MPPE; len -= CILEN_MPPE; /* XXX Cope with first/fast ack */ if (len == 0) return 1; }#endif if (go->deflate) { if (len < CILEN_DEFLATE || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) || p[1] != CILEN_DEFLATE || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) || p[3] != DEFLATE_CHK_SEQUENCE) return 0; p += CILEN_DEFLATE; len -= CILEN_DEFLATE; /* XXX Cope with first/fast ack */ if (len == 0) return 1; if (go->deflate_correct && go->deflate_draft) { if (len < CILEN_DEFLATE || p[0] != CI_DEFLATE_DRAFT || p[1] != CILEN_DEFLATE || p[2] != DEFLATE_MAKE_OPT(go->deflate_size) || p[3] != DEFLATE_CHK_SEQUENCE) return 0; p += CILEN_DEFLATE; len -= CILEN_DEFLATE; } } if (go->bsd_compress) { if (len < CILEN_BSD_COMPRESS || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits)) return 0; p += CILEN_BSD_COMPRESS; len -= CILEN_BSD_COMPRESS; /* XXX Cope with first/fast ack */ if (p == p0 && len == 0) return 1; } if (go->predictor_1) { if (len < CILEN_PREDICTOR_1 || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1) return 0; p += CILEN_PREDICTOR_1; len -= CILEN_PREDICTOR_1; /* XXX Cope with first/fast ack */ if (p == p0 && len == 0) return 1; } if (go->predictor_2) { if (len < CILEN_PREDICTOR_2 || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2) return 0; p += CILEN_PREDICTOR_2; len -= CILEN_PREDICTOR_2; /* XXX Cope with first/fast ack */ if (p == p0 && len == 0) return 1; } if (len != 0) return 0; return 1;}/* * ccp_nakci - process received configure-nak. * Returns 1 iff the nak was OK. */static intccp_nakci(f, p, len, treat_as_reject) fsm *f; u_char *p; int len; int treat_as_reject;{ ccp_options *go = &ccp_gotoptions[f->unit]; ccp_options no; /* options we've seen already */ ccp_options try; /* options to ask for next time */ memset(&no, 0, sizeof(no)); try = *go;#ifdef MPPE if (go->mppe && len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { no.mppe = 1; /* * Peer wants us to use a different strength or other setting. * Fail if we aren't willing to use his suggestion. */ MPPE_CI_TO_OPTS(&p[2], try.mppe); if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) { error("Refusing MPPE stateful mode offered by peer"); try.mppe = 0; } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) { /* Peer must have set options we didn't request (suggest) */ try.mppe = 0; } if (!try.mppe) { error("MPPE required but peer negotiation failed"); lcp_close(f->unit, "MPPE required but peer negotiation failed"); } }#endif /* MPPE */ if (go->deflate && len >= CILEN_DEFLATE && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT) && p[1] == CILEN_DEFLATE) { no.deflate = 1; /* * Peer wants us to use a different code size or something. * Stop asking for Deflate if we don't understand his suggestion. */ if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_WORKS || p[3] != DEFLATE_CHK_SEQUENCE) try.deflate = 0; else if (DEFLATE_SIZE(p[2]) < go->deflate_size) try.deflate_size = DEFLATE_SIZE(p[2]); p += CILEN_DEFLATE; len -= CILEN_DEFLATE; if (go->deflate_correct && go->deflate_draft && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { p += CILEN_DEFLATE; len -= CILEN_DEFLATE; } } if (go->bsd_compress && len >= CILEN_BSD_COMPRESS && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) { no.bsd_compress = 1; /* * Peer wants us to use a different number of bits * or a different version. */ if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION) try.bsd_compress = 0; else if (BSD_NBITS(p[2]) < go->bsd_bits) try.bsd_bits = BSD_NBITS(p[2]); p += CILEN_BSD_COMPRESS; len -= CILEN_BSD_COMPRESS; } /* * Predictor-1 and 2 have no options, so they can't be Naked. * * There may be remaining options but we ignore them. */ if (f->state != OPENED) *go = try; return 1;}/* * ccp_rejci - reject some of our suggested compression methods. */static intccp_rejci(f, p, len) fsm *f; u_char *p; int len;{ ccp_options *go = &ccp_gotoptions[f->unit]; ccp_options try; /* options to request next time */ try = *go; /* * Cope with empty configure-rejects by ceasing to send * configure-requests. */ if (len == 0 && all_rejected[f->unit]) return -1;#ifdef MPPE if (go->mppe && len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) { error("MPPE required but peer refused"); lcp_close(f->unit, "MPPE required but peer refused"); p += CILEN_MPPE; len -= CILEN_MPPE; }#endif if (go->deflate_correct && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) { if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) || p[3] != DEFLATE_CHK_SEQUENCE) return 0; /* Rej is bad */ try.deflate_correct = 0; p += CILEN_DEFLATE; len -= CILEN_DEFLATE; } if (go->deflate_draft && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT && p[1] == CILEN_DEFLATE) { if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size) || p[3] != DEFLATE_CHK_SEQUENCE) return 0; /* Rej is bad */ try.deflate_draft = 0; p += CILEN_DEFLATE; len -= CILEN_DEFLATE; } if (!try.deflate_correct && !try.deflate_draft) try.deflate = 0; 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)) return 0; try.bsd_compress = 0; p += CILEN_BSD_COMPRESS; len -= CILEN_BSD_COMPRESS; } if (go->predictor_1 && len >= CILEN_PREDICTOR_1 && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) { try.predictor_1 = 0; p += CILEN_PREDICTOR_1; len -= CILEN_PREDICTOR_1; } if (go->predictor_2 && len >= CILEN_PREDICTOR_2 && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) { try.predictor_2 = 0; p += CILEN_PREDICTOR_2; len -= CILEN_PREDICTOR_2; } if (len != 0) return 0; if (f->state != OPENED) *go = try; return 1;}/* * ccp_reqci - processed a received configure-request. * Returns CONFACK, CONFNAK or CONFREJ and the packet modified * appropriately. */static intccp_reqci(f, p, lenp, dont_nak) fsm *f; u_char *p; int *lenp; int dont_nak;{ int ret, newret, res; u_char *p0, *retp; int len, clen, type, nb; ccp_options *ho = &ccp_hisoptions[f->unit]; ccp_options *ao = &ccp_allowoptions[f->unit];#ifdef MPPE bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */ /* CI_MPPE, or due to other options? */#endif ret = CONFACK; retp = p0 = p; len = *lenp; memset(ho, 0, sizeof(ccp_options)); ho->method = (len > 0)? p[0]: -1; while (len > 0) { newret = CONFACK; if (len < 2 || p[1] < 2 || p[1] > len) { /* length is bad */ clen = len; newret = CONFREJ; } else { type = p[0]; clen = p[1]; switch (type) {#ifdef MPPE case CI_MPPE: if (!ao->mppe || clen != CILEN_MPPE) { newret = CONFREJ; break; } MPPE_CI_TO_OPTS(&p[2], ho->mppe); /* Nak if anything unsupported or unknown are set. */ if (ho->mppe & MPPE_OPT_UNSUPPORTED) { newret = CONFNAK; ho->mppe &= ~MPPE_OPT_UNSUPPORTED; } if (ho->mppe & MPPE_OPT_UNKNOWN) { newret = CONFNAK; ho->mppe &= ~MPPE_OPT_UNKNOWN; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -