Root/package/ppp/patches/201-mppe_mppc_1.1.patch

1--- a/include/linux/ppp-comp.h
2+++ b/include/linux/ppp-comp.h
3@@ -36,7 +36,7 @@
4  */
5 
6 /*
7- * ==FILEVERSION 20020319==
8+ * ==FILEVERSION 20020715==
9  *
10  * NOTE TO MAINTAINERS:
11  * If you modify this file at all, please set the above date.
12@@ -86,7 +86,7 @@ struct compressor {
13 
14     /* Compress a packet */
15     int (*compress) (void *state, unsigned char *rptr,
16- unsigned char *obuf, int isize, int osize);
17+ unsigned char *obuf, int isize, int osize);
18 
19     /* Return compression statistics */
20     void (*comp_stat) (void *state, struct compstat *stats);
21@@ -107,7 +107,7 @@ struct compressor {
22 
23     /* Decompress a packet. */
24     int (*decompress) (void *state, unsigned char *ibuf, int isize,
25- unsigned char *obuf, int osize);
26+ unsigned char *obuf, int osize);
27 
28     /* Update state for an incompressible packet received */
29     void (*incomp) (void *state, unsigned char *ibuf, int icnt);
30@@ -288,6 +288,33 @@ struct compressor {
31         opts |= MPPE_OPT_UNKNOWN; \
32     } while (/* CONSTCOND */ 0)
33 
34+/* MPPE/MPPC definitions by J.D.*/
35+#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
36+#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
37+#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
38+#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
39+#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
40+
41+/*
42+ * Definitions for Stac LZS.
43+ */
44+
45+#define CI_LZS 17 /* config option for Stac LZS */
46+#define CILEN_LZS 5 /* length of config option */
47+
48+#define LZS_OVHD 4 /* max. LZS overhead */
49+#define LZS_HIST_LEN 2048 /* LZS history size */
50+#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
51+
52+#define LZS_MODE_NONE 0
53+#define LZS_MODE_LCB 1
54+#define LZS_MODE_CRC 2
55+#define LZS_MODE_SEQ 3
56+#define LZS_MODE_EXT 4
57+
58+#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
59+#define LZS_EXT_BIT_COMP 0x20 /* bit C */
60+
61 /*
62  * Definitions for other, as yet unsupported, compression methods.
63  */
64--- a/include/net/ppp-comp.h
65+++ b/include/net/ppp-comp.h
66@@ -255,6 +255,33 @@ struct compressor {
67         opts |= MPPE_OPT_UNKNOWN; \
68     } while (/* CONSTCOND */ 0)
69 
70+/* MPPE/MPPC definitions by J.D.*/
71+#define MPPE_STATELESS MPPE_H_BIT /* configuration bit H */
72+#define MPPE_40BIT MPPE_L_BIT /* configuration bit L */
73+#define MPPE_56BIT MPPE_M_BIT /* configuration bit M */
74+#define MPPE_128BIT MPPE_S_BIT /* configuration bit S */
75+#define MPPE_MPPC MPPE_C_BIT /* configuration bit C */
76+
77+/*
78+ * Definitions for Stac LZS.
79+ */
80+
81+#define CI_LZS 17 /* config option for Stac LZS */
82+#define CILEN_LZS 5 /* length of config option */
83+
84+#define LZS_OVHD 4 /* max. LZS overhead */
85+#define LZS_HIST_LEN 2048 /* LZS history size */
86+#define LZS_MAX_CCOUNT 0x0FFF /* max. coherency counter value */
87+
88+#define LZS_MODE_NONE 0
89+#define LZS_MODE_LCB 1
90+#define LZS_MODE_CRC 2
91+#define LZS_MODE_SEQ 3
92+#define LZS_MODE_EXT 4
93+
94+#define LZS_EXT_BIT_FLUSHED 0x80 /* bit A */
95+#define LZS_EXT_BIT_COMP 0x20 /* bit C */
96+
97 /*
98  * Definitions for other, as yet unsupported, compression methods.
99  */
100--- a/pppd/ccp.c
101+++ b/pppd/ccp.c
102@@ -62,12 +62,10 @@ static int setdeflate __P((char **));
103 static char bsd_value[8];
104 static char deflate_value[8];
105 
106-/*
107- * Option variables.
108- */
109 #ifdef MPPE
110-bool refuse_mppe_stateful = 1; /* Allow stateful mode? */
111-#endif
112+static int setmppe(char **);
113+static int setnomppe(void);
114+#endif /* MPPE */
115 
116 static option_t ccp_option_list[] = {
117     { "noccp", o_bool, &ccp_protent.enabled_flag,
118@@ -108,54 +106,36 @@ static option_t ccp_option_list[] = {
119       "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
120       &ccp_allowoptions[0].predictor_1 },
121 
122+ { "lzs", o_bool, &ccp_wantoptions[0].lzs,
123+ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_PRIO },
124+ { "+lzs", o_bool, &ccp_wantoptions[0].lzs,
125+ "request Stac LZS", 1, &ccp_allowoptions[0].lzs, OPT_ALIAS | OPT_PRIO },
126+ { "nolzs", o_bool, &ccp_wantoptions[0].lzs,
127+ "don't allow Stac LZS", OPT_PRIOSUB | OPT_A2CLR,
128+ &ccp_allowoptions[0].lzs },
129+ { "-lzs", o_bool, &ccp_wantoptions[0].lzs,
130+ "don't allow Stac LZS", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
131+ &ccp_allowoptions[0].lzs },
132+
133 #ifdef MPPE
134- /* MPPE options are symmetrical ... we only set wantoptions here */
135- { "require-mppe", o_bool, &ccp_wantoptions[0].mppe,
136- "require MPPE encryption",
137- OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
138- { "+mppe", o_bool, &ccp_wantoptions[0].mppe,
139- "require MPPE encryption",
140- OPT_ALIAS | OPT_PRIO | MPPE_OPT_40 | MPPE_OPT_128 },
141- { "nomppe", o_bool, &ccp_wantoptions[0].mppe,
142- "don't allow MPPE encryption", OPT_PRIO },
143- { "-mppe", o_bool, &ccp_wantoptions[0].mppe,
144- "don't allow MPPE encryption", OPT_ALIAS | OPT_PRIO },
145-
146- /* We use ccp_allowoptions[0].mppe as a junk var ... it is reset later */
147- { "require-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
148- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
149- &ccp_wantoptions[0].mppe },
150- { "+mppe-40", o_bool, &ccp_allowoptions[0].mppe,
151- "require MPPE 40-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_40,
152- &ccp_wantoptions[0].mppe },
153- { "nomppe-40", o_bool, &ccp_allowoptions[0].mppe,
154- "don't allow MPPE 40-bit encryption",
155- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40, &ccp_wantoptions[0].mppe },
156- { "-mppe-40", o_bool, &ccp_allowoptions[0].mppe,
157- "don't allow MPPE 40-bit encryption",
158- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_40,
159- &ccp_wantoptions[0].mppe },
160-
161- { "require-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
162- "require MPPE 128-bit encryption", OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
163- &ccp_wantoptions[0].mppe },
164- { "+mppe-128", o_bool, &ccp_allowoptions[0].mppe,
165- "require MPPE 128-bit encryption",
166- OPT_ALIAS | OPT_PRIO | OPT_A2OR | MPPE_OPT_128,
167- &ccp_wantoptions[0].mppe },
168- { "nomppe-128", o_bool, &ccp_allowoptions[0].mppe,
169- "don't allow MPPE 128-bit encryption",
170- OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128, &ccp_wantoptions[0].mppe },
171- { "-mppe-128", o_bool, &ccp_allowoptions[0].mppe,
172- "don't allow MPPE 128-bit encryption",
173- OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLRB | MPPE_OPT_128,
174- &ccp_wantoptions[0].mppe },
175-
176- /* strange one; we always request stateless, but will we allow stateful? */
177- { "mppe-stateful", o_bool, &refuse_mppe_stateful,
178- "allow MPPE stateful mode", OPT_PRIO },
179- { "nomppe-stateful", o_bool, &refuse_mppe_stateful,
180- "disallow MPPE stateful mode", OPT_PRIO | 1 },
181+ { "mppc", o_bool, &ccp_wantoptions[0].mppc,
182+ "request MPPC compression", 1, &ccp_allowoptions[0].mppc },
183+ { "+mppc", o_bool, &ccp_wantoptions[0].mppc,
184+ "request MPPC compression", 1, &ccp_allowoptions[0].mppc, OPT_ALIAS },
185+ { "nomppc", o_bool, &ccp_wantoptions[0].mppc,
186+ "don't allow MPPC compression", OPT_PRIOSUB | OPT_A2CLR,
187+ &ccp_allowoptions[0].mppc },
188+ { "-mppc", o_bool, &ccp_wantoptions[0].mppc,
189+ "don't allow MPPC compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR,
190+ &ccp_allowoptions[0].mppc },
191+ { "mppe", o_special, (void *)setmppe,
192+ "request MPPE encryption" },
193+ { "+mppe", o_special, (void *)setmppe,
194+ "request MPPE encryption" },
195+ { "nomppe", o_special_noarg, (void *)setnomppe,
196+ "don't allow MPPE encryption" },
197+ { "-mppe", o_special_noarg, (void *)setnomppe,
198+ "don't allow MPPE encryption" },
199 #endif /* MPPE */
200 
201     { NULL }
202@@ -241,7 +221,7 @@ static fsm_callbacks ccp_callbacks = {
203  */
204 #define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
205                  || (opt).predictor_1 || (opt).predictor_2 \
206- || (opt).mppe)
207+ || (opt).lzs || (opt).mppc || (opt).mppe)
208 
209 /*
210  * Local state (mainly for handling reset-reqs and reset-acks).
211@@ -344,6 +324,100 @@ setdeflate(argv)
212     return 1;
213 }
214 
215+#ifdef MPPE
216+/*
217+ * Functions called from config options
218+ */
219+/*
220+ MPPE suboptions:
221+ required - require MPPE; disconnect if peer doesn't support it
222+ stateless - use stateless mode
223+ no40 - disable 40 bit keys
224+ no56 - disable 56 bit keys
225+ no128 - disable 128 bit keys
226+*/
227+int setmppe(char **argv)
228+{
229+ int i;
230+ char *str, cmdbuf[16];
231+
232+ ccp_allowoptions[0].mppe = 1;
233+ ccp_allowoptions[0].mppe_40 = 1;
234+ ccp_allowoptions[0].mppe_56 = 1;
235+ ccp_allowoptions[0].mppe_128 = 1;
236+ ccp_allowoptions[0].mppe_stateless = 0;
237+ ccp_wantoptions[0].mppe = 0;
238+
239+ str = *argv;
240+
241+ while (1) {
242+ i = 0;
243+ memset(cmdbuf, '\0', 16);
244+ while ((i < 16) && (*str != ',') && (*str != '\0'))
245+ cmdbuf[i++] = *str++;
246+ cmdbuf[i] = '\0';
247+ if (!strncasecmp(cmdbuf, "no40", strlen("no40"))) {
248+ ccp_allowoptions[0].mppe_40 = 0;
249+ goto next_param;
250+ } else if (!strncasecmp(cmdbuf, "no56", strlen("no56"))) {
251+ ccp_allowoptions[0].mppe_56 = 0;
252+ goto next_param;
253+ } else if (!strncasecmp(cmdbuf, "no128", strlen("no128"))) {
254+ ccp_allowoptions[0].mppe_128 = 0;
255+ goto next_param;
256+ } else if (!strncasecmp(cmdbuf, "stateless", strlen("stateless"))) {
257+ ccp_allowoptions[0].mppe_stateless = 1;
258+ goto next_param;
259+ } else if (!strncasecmp(cmdbuf, "required", strlen("required"))) {
260+ ccp_wantoptions[0].mppe = 1;
261+ goto next_param;
262+ } else {
263+ option_error("invalid parameter '%s' for mppe option", cmdbuf);
264+ return 0;
265+ }
266+
267+ next_param:
268+ if (*str == ',') {
269+ str++;
270+ continue;
271+ }
272+ if (*str == '\0') {
273+ if (!(ccp_allowoptions[0].mppe_40 || ccp_allowoptions[0].mppe_56 ||
274+ ccp_allowoptions[0].mppe_128)) {
275+ if (ccp_wantoptions[0].mppe == 1) {
276+ option_error("You require MPPE but you have switched off "
277+ "all encryption key lengths.");
278+ return 0;
279+ }
280+ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
281+ ccp_wantoptions[0].mppe_stateless =
282+ ccp_allowoptions[0].mppe_stateless = 0;
283+ } else {
284+ ccp_allowoptions[0].mppe = 1;
285+ ccp_wantoptions[0].mppe_stateless =
286+ ccp_allowoptions[0].mppe_stateless;
287+ if (ccp_wantoptions[0].mppe == 1) {
288+ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40;
289+ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56;
290+ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128;
291+ }
292+ }
293+ return 1;
294+ }
295+ }
296+}
297+
298+int setnomppe(void)
299+{
300+ ccp_wantoptions[0].mppe = ccp_allowoptions[0].mppe = 0;
301+ ccp_wantoptions[0].mppe_40 = ccp_allowoptions[0].mppe_40 = 0;
302+ ccp_wantoptions[0].mppe_56 = ccp_allowoptions[0].mppe_56 = 0;
303+ ccp_wantoptions[0].mppe_128 = ccp_allowoptions[0].mppe_128 = 0;
304+ ccp_wantoptions[0].mppe_stateless = ccp_allowoptions[0].mppe_stateless = 0;
305+ return 1;
306+}
307+#endif /* MPPE */
308+
309 /*
310  * ccp_init - initialize CCP.
311  */
312@@ -378,6 +452,30 @@ ccp_init(unit)
313     ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
314 
315     ccp_allowoptions[0].predictor_1 = 1;
316+
317+ ccp_wantoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
318+ ccp_wantoptions[0].lzs_mode = LZS_MODE_SEQ;
319+ ccp_wantoptions[0].lzs_hists = 1;
320+ ccp_allowoptions[0].lzs = 0; /* Stac LZS - will be enabled in the future */
321+ ccp_allowoptions[0].lzs_mode = LZS_MODE_SEQ;
322+ ccp_allowoptions[0].lzs_hists = 1;
323+
324+#ifdef MPPE
325+ /* by default allow and request MPPC... */
326+ ccp_wantoptions[0].mppc = ccp_allowoptions[0].mppc = 1;
327+
328+ /* ... and allow but don't request MPPE */
329+ ccp_allowoptions[0].mppe = 1;
330+ ccp_allowoptions[0].mppe_40 = 1;
331+ ccp_allowoptions[0].mppe_56 = 1;
332+ ccp_allowoptions[0].mppe_128 = 1;
333+ ccp_allowoptions[0].mppe_stateless = 1;
334+ ccp_wantoptions[0].mppe = 0;
335+ ccp_wantoptions[0].mppe_40 = 0;
336+ ccp_wantoptions[0].mppe_56 = 0;
337+ ccp_wantoptions[0].mppe_128 = 0;
338+ ccp_wantoptions[0].mppe_stateless = 0;
339+#endif /* MPPE */
340 }
341 
342 /*
343@@ -455,11 +553,11 @@ ccp_input(unit, p, len)
344     if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED) {
345     notice("Compression disabled by peer.");
346 #ifdef MPPE
347- if (ccp_gotoptions[unit].mppe) {
348+ if (ccp_wantoptions[unit].mppe) {
349         error("MPPE disabled, closing LCP");
350         lcp_close(unit, "MPPE disabled by peer");
351     }
352-#endif
353+#endif /* MPPE */
354     }
355 
356     /*
357@@ -487,6 +585,15 @@ ccp_extcode(f, code, id, p, len)
358         break;
359     /* send a reset-ack, which the transmitter will see and
360        reset its compression state. */
361+
362+ /* In case of MPPE/MPPC or LZS we shouldn't send CCP_RESETACK,
363+ but we do it in order to reset compressor; CCP_RESETACK is
364+ then silently discarded. See functions ppp_send_frame and
365+ ppp_ccp_peek in ppp_generic.c (Linux only !!!). All the
366+ confusion is caused by the fact that CCP code is splited
367+ into two parts - one part is handled by pppd, the other one
368+ is handled by kernel. */
369+
370     fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
371     break;
372 
373@@ -515,12 +622,11 @@ ccp_protrej(unit)
374     fsm_lowerdown(&ccp_fsm[unit]);
375 
376 #ifdef MPPE
377- if (ccp_gotoptions[unit].mppe) {
378+ if (ccp_wantoptions[unit].mppe) {
379     error("MPPE required but peer negotiation failed");
380     lcp_close(unit, "MPPE required but peer negotiation failed");
381     }
382-#endif
383-
384+#endif /* MPPE */
385 }
386 
387 /*
388@@ -537,7 +643,7 @@ ccp_resetci(f)
389     all_rejected[f->unit] = 0;
390 
391 #ifdef MPPE
392- if (go->mppe) {
393+ if (go->mppe || go->mppc) {
394     ccp_options *ao = &ccp_allowoptions[f->unit];
395     int auth_mschap_bits = auth_done[f->unit];
396     int numbits;
397@@ -551,80 +657,109 @@ ccp_resetci(f)
398      * NB: If MPPE is required, all other compression opts are invalid.
399      * So, we return right away if we can't do it.
400      */
401+ if (ccp_wantoptions[f->unit].mppe) {
402+ /* Leave only the mschap auth bits set */
403+ auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
404+ CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
405+ /* Count the mschap auths */
406+ auth_mschap_bits >>= CHAP_MS_SHIFT;
407+ numbits = 0;
408+ do {
409+ numbits += auth_mschap_bits & 1;
410+ auth_mschap_bits >>= 1;
411+ } while (auth_mschap_bits);
412+ if (numbits > 1) {
413+ error("MPPE required, but auth done in both directions.");
414+ lcp_close(f->unit, "MPPE required but not available");
415+ return;
416+ }
417+ if (!numbits) {
418+ error("MPPE required, but MS-CHAP[v2] auth not performed.");
419+ lcp_close(f->unit, "MPPE required but not available");
420+ return;
421+ }
422 
423- /* Leave only the mschap auth bits set */
424- auth_mschap_bits &= (CHAP_MS_WITHPEER | CHAP_MS_PEER |
425- CHAP_MS2_WITHPEER | CHAP_MS2_PEER);
426- /* Count the mschap auths */
427- auth_mschap_bits >>= CHAP_MS_SHIFT;
428- numbits = 0;
429- do {
430- numbits += auth_mschap_bits & 1;
431- auth_mschap_bits >>= 1;
432- } while (auth_mschap_bits);
433- if (numbits > 1) {
434- error("MPPE required, but auth done in both directions.");
435- lcp_close(f->unit, "MPPE required but not available");
436- return;
437- }
438- if (!numbits) {
439- error("MPPE required, but MS-CHAP[v2] auth not performed.");
440- lcp_close(f->unit, "MPPE required but not available");
441- return;
442- }
443-
444- /* A plugin (eg radius) may not have obtained key material. */
445- if (!mppe_keys_set) {
446- error("MPPE required, but keys are not available. "
447- "Possible plugin problem?");
448- lcp_close(f->unit, "MPPE required but not available");
449- return;
450- }
451-
452- /* LM auth not supported for MPPE */
453- if (auth_done[f->unit] & (CHAP_MS_WITHPEER | CHAP_MS_PEER)) {
454- /* This might be noise */
455- if (go->mppe & MPPE_OPT_40) {
456- notice("Disabling 40-bit MPPE; MS-CHAP LM not supported");
457- go->mppe &= ~MPPE_OPT_40;
458- ccp_wantoptions[f->unit].mppe &= ~MPPE_OPT_40;
459+ /* A plugin (eg radius) may not have obtained key material. */
460+ if (!mppe_keys_set) {
461+ error("MPPE required, but keys are not available. "
462+ "Possible plugin problem?");
463+ lcp_close(f->unit, "MPPE required but not available");
464+ return;
465         }
466     }
467 
468- /* Last check: can we actually negotiate something? */
469- if (!(go->mppe & (MPPE_OPT_40 | MPPE_OPT_128))) {
470- /* Could be misconfig, could be 40-bit disabled above. */
471- error("MPPE required, but both 40-bit and 128-bit disabled.");
472- lcp_close(f->unit, "MPPE required but not available");
473- return;
474+ /*
475+ * Check whether the kernel knows about the various
476+ * compression methods we might request. Key material
477+ * unimportant here.
478+ */
479+ if (go->mppc) {
480+ opt_buf[0] = CI_MPPE;
481+ opt_buf[1] = CILEN_MPPE;
482+ opt_buf[2] = 0;
483+ opt_buf[3] = 0;
484+ opt_buf[4] = 0;
485+ opt_buf[5] = MPPE_MPPC;
486+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 0) <= 0)
487+ go->mppc = 0;
488+ }
489+ if (go->mppe_40) {
490+ opt_buf[0] = CI_MPPE;
491+ opt_buf[1] = CILEN_MPPE;
492+ opt_buf[2] = MPPE_STATELESS;
493+ opt_buf[3] = 0;
494+ opt_buf[4] = 0;
495+ opt_buf[5] = MPPE_40BIT;
496+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
497+ go->mppe_40 = 0;
498+ }
499+ if (go->mppe_56) {
500+ opt_buf[0] = CI_MPPE;
501+ opt_buf[1] = CILEN_MPPE;
502+ opt_buf[2] = MPPE_STATELESS;
503+ opt_buf[3] = 0;
504+ opt_buf[4] = 0;
505+ opt_buf[5] = MPPE_56BIT;
506+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
507+ go->mppe_56 = 0;
508+ }
509+ if (go->mppe_128) {
510+ opt_buf[0] = CI_MPPE;
511+ opt_buf[1] = CILEN_MPPE;
512+ opt_buf[2] = MPPE_STATELESS;
513+ opt_buf[3] = 0;
514+ opt_buf[4] = 0;
515+ opt_buf[5] = MPPE_128BIT;
516+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0)
517+ go->mppe_128 = 0;
518+ }
519+ if (!go->mppe_40 && !go->mppe_56 && !go->mppe_128) {
520+ if (ccp_wantoptions[f->unit].mppe) {
521+ error("MPPE required, but kernel has no support.");
522+ lcp_close(f->unit, "MPPE required but not available");
523+ }
524+ go->mppe = go->mppe_stateless = 0;
525+ } else {
526+ /* MPPE is not compatible with other compression types */
527+ if (ccp_wantoptions[f->unit].mppe) {
528+ ao->bsd_compress = go->bsd_compress = 0;
529+ ao->predictor_1 = go->predictor_1 = 0;
530+ ao->predictor_2 = go->predictor_2 = 0;
531+ ao->deflate = go->deflate = 0;
532+ ao->lzs = go->lzs = 0;
533+ }
534     }
535-
536- /* sync options */
537- ao->mppe = go->mppe;
538- /* MPPE is not compatible with other compression types */
539- ao->bsd_compress = go->bsd_compress = 0;
540- ao->predictor_1 = go->predictor_1 = 0;
541- ao->predictor_2 = go->predictor_2 = 0;
542- ao->deflate = go->deflate = 0;
543     }
544 #endif /* MPPE */
545-
546- /*
547- * Check whether the kernel knows about the various
548- * compression methods we might request.
549- */
550-#ifdef MPPE
551- if (go->mppe) {
552- opt_buf[0] = CI_MPPE;
553- opt_buf[1] = CILEN_MPPE;
554- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
555- /* Key material unimportant here. */
556- if (ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0) <= 0) {
557- error("MPPE required, but kernel has no support.");
558- lcp_close(f->unit, "MPPE required but not available");
559- }
560+ if (go->lzs) {
561+ opt_buf[0] = CI_LZS;
562+ opt_buf[1] = CILEN_LZS;
563+ opt_buf[2] = go->lzs_hists >> 8;
564+ opt_buf[3] = go->lzs_hists & 0xff;
565+ opt_buf[4] = LZS_MODE_SEQ;
566+ if (ccp_test(f->unit, opt_buf, CILEN_LZS, 0) <= 0)
567+ go->lzs = 0;
568     }
569-#endif
570     if (go->bsd_compress) {
571     opt_buf[0] = CI_BSD_COMPRESS;
572     opt_buf[1] = CILEN_BSD_COMPRESS;
573@@ -679,7 +814,8 @@ ccp_cilen(f)
574     + (go->deflate? CILEN_DEFLATE: 0)
575     + (go->predictor_1? CILEN_PREDICTOR_1: 0)
576     + (go->predictor_2? CILEN_PREDICTOR_2: 0)
577- + (go->mppe? CILEN_MPPE: 0);
578+ + (go->lzs? CILEN_LZS: 0)
579+ + ((go->mppe || go->mppc)? CILEN_MPPE: 0);
580 }
581 
582 /*
583@@ -693,6 +829,8 @@ ccp_addci(f, p, lenp)
584 {
585     int res;
586     ccp_options *go = &ccp_gotoptions[f->unit];
587+ ccp_options *ao = &ccp_allowoptions[f->unit];
588+ ccp_options *wo = &ccp_wantoptions[f->unit];
589     u_char *p0 = p;
590 
591     /*
592@@ -701,22 +839,43 @@ ccp_addci(f, p, lenp)
593      * in case it gets Acked.
594      */
595 #ifdef MPPE
596- if (go->mppe) {
597+ if (go->mppe || go->mppc || (!wo->mppe && ao->mppe)) {
598     u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
599 
600- p[0] = opt_buf[0] = CI_MPPE;
601- p[1] = opt_buf[1] = CILEN_MPPE;
602- MPPE_OPTS_TO_CI(go->mppe, &p[2]);
603- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
604+ p[0] = CI_MPPE;
605+ p[1] = CILEN_MPPE;
606+ p[2] = (go->mppe_stateless ? MPPE_STATELESS : 0);
607+ p[3] = 0;
608+ p[4] = 0;
609+ p[5] = (go->mppe_40 ? MPPE_40BIT : 0) | (go->mppe_56 ? MPPE_56BIT : 0) |
610+ (go->mppe_128 ? MPPE_128BIT : 0) | (go->mppc ? MPPE_MPPC : 0);
611+
612+ BCOPY(p, opt_buf, CILEN_MPPE);
613     BCOPY(mppe_recv_key, &opt_buf[CILEN_MPPE], MPPE_MAX_KEY_LEN);
614     res = ccp_test(f->unit, opt_buf, CILEN_MPPE + MPPE_MAX_KEY_LEN, 0);
615- if (res > 0)
616+ if (res > 0) {
617         p += CILEN_MPPE;
618- else
619+ } else {
620         /* This shouldn't happen, we've already tested it! */
621- lcp_close(f->unit, "MPPE required but not available in kernel");
622+ go->mppe = go->mppe_40 = go->mppe_56 = go->mppe_128 =
623+ go->mppe_stateless = go->mppc = 0;
624+ if (ccp_wantoptions[f->unit].mppe)
625+ lcp_close(f->unit, "MPPE required but not available in kernel");
626+ }
627+ }
628+#endif /* MPPE */
629+ if (go->lzs) {
630+ p[0] = CI_LZS;
631+ p[1] = CILEN_LZS;
632+ p[2] = go->lzs_hists >> 8;
633+ p[3] = go->lzs_hists & 0xff;
634+ p[4] = LZS_MODE_SEQ;
635+ res = ccp_test(f->unit, p, CILEN_LZS, 0);
636+ if (res > 0) {
637+ p += CILEN_LZS;
638+ } else
639+ go->lzs = 0;
640     }
641-#endif
642     if (go->deflate) {
643     p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
644     p[1] = CILEN_DEFLATE;
645@@ -802,7 +961,7 @@ ccp_addci(f, p, lenp)
646 
647 /*
648  * ccp_ackci - process a received configure-ack, and return
649- * 1 iff the packet was OK.
650+ * 1 if the packet was OK.
651  */
652 static int
653 ccp_ackci(f, p, len)
654@@ -811,24 +970,44 @@ ccp_ackci(f, p, len)
655     int len;
656 {
657     ccp_options *go = &ccp_gotoptions[f->unit];
658+ ccp_options *ao = &ccp_allowoptions[f->unit];
659+ ccp_options *wo = &ccp_wantoptions[f->unit];
660     u_char *p0 = p;
661 
662 #ifdef MPPE
663- if (go->mppe) {
664- u_char opt_buf[CILEN_MPPE];
665-
666- opt_buf[0] = CI_MPPE;
667- opt_buf[1] = CILEN_MPPE;
668- MPPE_OPTS_TO_CI(go->mppe, &opt_buf[2]);
669- if (len < CILEN_MPPE || memcmp(opt_buf, p, CILEN_MPPE))
670+ if (go->mppe || go->mppc || (!wo->mppe && ao->mppe)) {
671+ if (len < CILEN_MPPE
672+ || p[1] != CILEN_MPPE || p[0] != CI_MPPE
673+ || p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0)
674+ || p[3] != 0
675+ || p[4] != 0
676+ || (p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) |
677+ (go->mppc ? MPPE_MPPC : 0))
678+ && p[5] != ((go->mppe_56 ? MPPE_56BIT : 0) |
679+ (go->mppc ? MPPE_MPPC : 0))
680+ && p[5] != ((go->mppe_128 ? MPPE_128BIT : 0) |
681+ (go->mppc ? MPPE_MPPC : 0))))
682         return 0;
683+ if (go->mppe_40 || go->mppe_56 || go->mppe_128)
684+ go->mppe = 1;
685     p += CILEN_MPPE;
686     len -= CILEN_MPPE;
687+ /* Cope with first/fast ack */
688+ if (p == p0 && len == 0)
689+ return 1;
690+ }
691+#endif /* MPPE */
692+ if (go->lzs) {
693+ if (len < CILEN_LZS || p[0] != CI_LZS || p[1] != CILEN_LZS
694+ || p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
695+ || p[4] != LZS_MODE_SEQ)
696+ return 0;
697+ p += CILEN_LZS;
698+ len -= CILEN_LZS;
699     /* XXX Cope with first/fast ack */
700- if (len == 0)
701+ if (p == p0 && len == 0)
702         return 1;
703     }
704-#endif
705     if (go->deflate) {
706     if (len < CILEN_DEFLATE
707         || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
708@@ -891,7 +1070,7 @@ ccp_ackci(f, p, len)
709 
710 /*
711  * ccp_nakci - process received configure-nak.
712- * Returns 1 iff the nak was OK.
713+ * Returns 1 if the nak was OK.
714  */
715 static int
716 ccp_nakci(f, p, len, treat_as_reject)
717@@ -901,6 +1080,8 @@ ccp_nakci(f, p, len, treat_as_reject)
718     int treat_as_reject;
719 {
720     ccp_options *go = &ccp_gotoptions[f->unit];
721+ ccp_options *ao = &ccp_allowoptions[f->unit];
722+ ccp_options *wo = &ccp_wantoptions[f->unit];
723     ccp_options no; /* options we've seen already */
724     ccp_options try; /* options to ask for next time */
725 
726@@ -908,28 +1089,100 @@ ccp_nakci(f, p, len, treat_as_reject)
727     try = *go;
728 
729 #ifdef MPPE
730- if (go->mppe && len >= CILEN_MPPE
731- && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
732- no.mppe = 1;
733- /*
734- * Peer wants us to use a different strength or other setting.
735- * Fail if we aren't willing to use his suggestion.
736- */
737- MPPE_CI_TO_OPTS(&p[2], try.mppe);
738- if ((try.mppe & MPPE_OPT_STATEFUL) && refuse_mppe_stateful) {
739- error("Refusing MPPE stateful mode offered by peer");
740- try.mppe = 0;
741- } else if (((go->mppe | MPPE_OPT_STATEFUL) & try.mppe) != try.mppe) {
742- /* Peer must have set options we didn't request (suggest) */
743- try.mppe = 0;
744- }
745+ if ((go->mppe || go->mppc || (!wo->mppe && ao->mppe)) &&
746+ len >= CILEN_MPPE && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
747 
748- if (!try.mppe) {
749- error("MPPE required but peer negotiation failed");
750- lcp_close(f->unit, "MPPE required but peer negotiation failed");
751+ if (go->mppc) {
752+ no.mppc = 1;
753+ if (!(p[5] & MPPE_MPPC))
754+ try.mppc = 0;
755+ }
756+
757+ if (go->mppe)
758+ no.mppe = 1;
759+ if (go->mppe_40)
760+ no.mppe_40 = 1;
761+ if (go->mppe_56)
762+ no.mppe_56 = 1;
763+ if (go->mppe_128)
764+ no.mppe_128 = 1;
765+ if (go->mppe_stateless)
766+ no.mppe_stateless = 1;
767+
768+ if (ao->mppe_40) {
769+ if ((p[5] & MPPE_40BIT))
770+ try.mppe_40 = 1;
771+ else
772+ try.mppe_40 = (p[5] == 0) ? 1 : 0;
773+ }
774+ if (ao->mppe_56) {
775+ if ((p[5] & MPPE_56BIT))
776+ try.mppe_56 = 1;
777+ else
778+ try.mppe_56 = (p[5] == 0) ? 1 : 0;
779+ }
780+ if (ao->mppe_128) {
781+ if ((p[5] & MPPE_128BIT))
782+ try.mppe_128 = 1;
783+ else
784+ try.mppe_128 = (p[5] == 0) ? 1 : 0;
785+ }
786+
787+ if (ao->mppe_stateless) {
788+ if ((p[2] & MPPE_STATELESS) || wo->mppe_stateless)
789+ try.mppe_stateless = 1;
790+ else
791+ try.mppe_stateless = 0;
792+ }
793+
794+ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128) {
795+ try.mppe = try.mppe_stateless = 0;
796+ if (wo->mppe) {
797+ /* we require encryption, but peer doesn't support it
798+ so we close connection */
799+ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
800+ wo->mppe_56 = wo->mppe_128 = 0;
801+ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
802+ "key length");
803+ }
804+ }
805+ if (wo->mppe && (wo->mppe_40 != try.mppe_40) &&
806+ (wo->mppe_56 != try.mppe_56) && (wo->mppe_128 != try.mppe_128)) {
807+ /* cannot negotiate key length */
808+ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
809+ wo->mppe_56 = wo->mppe_128 = 0;
810+ lcp_close(f->unit, "Cannot negotiate MPPE key length");
811     }
812+ if (try.mppe_40 && try.mppe_56 && try.mppe_128)
813+ try.mppe_40 = try.mppe_56 = 0;
814+ else
815+ if (try.mppe_56 && try.mppe_128)
816+ try.mppe_56 = 0;
817+ else
818+ if (try.mppe_40 && try.mppe_128)
819+ try.mppe_40 = 0;
820+ else
821+ if (try.mppe_40 && try.mppe_56)
822+ try.mppe_40 = 0;
823+
824+ p += CILEN_MPPE;
825+ len -= CILEN_MPPE;
826     }
827 #endif /* MPPE */
828+
829+ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
830+ no.lzs = 1;
831+ if (((p[2]<<8)|p[3]) > 1 || (p[4] != LZS_MODE_SEQ &&
832+ p[4] != LZS_MODE_EXT))
833+ try.lzs = 0;
834+ else {
835+ try.lzs_mode = p[4];
836+ try.lzs_hists = (p[2] << 8) | p[3];
837+ }
838+ p += CILEN_LZS;
839+ len -= CILEN_LZS;
840+ }
841+
842     if (go->deflate && len >= CILEN_DEFLATE
843     && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
844     && p[1] == CILEN_DEFLATE) {
845@@ -1002,14 +1255,50 @@ ccp_rejci(f, p, len)
846     return -1;
847 
848 #ifdef MPPE
849- if (go->mppe && len >= CILEN_MPPE
850+ if ((go->mppe || go->mppc) && len >= CILEN_MPPE
851     && p[0] == CI_MPPE && p[1] == CILEN_MPPE) {
852- error("MPPE required but peer refused");
853- lcp_close(f->unit, "MPPE required but peer refused");
854+ ccp_options *wo = &ccp_wantoptions[f->unit];
855+ if (p[2] != (go->mppe_stateless ? MPPE_STATELESS : 0) ||
856+ p[3] != 0 ||
857+ p[4] != 0 ||
858+ p[5] != ((go->mppe_40 ? MPPE_40BIT : 0) |
859+ (go->mppe_56 ? MPPE_56BIT : 0) |
860+ (go->mppe_128 ? MPPE_128BIT : 0) |
861+ (go->mppc ? MPPE_MPPC : 0)))
862+ return 0;
863+ if (go->mppc)
864+ try.mppc = 0;
865+ if (go->mppe) {
866+ try.mppe = 0;
867+ if (go->mppe_40)
868+ try.mppe_40 = 0;
869+ if (go->mppe_56)
870+ try.mppe_56 = 0;
871+ if (go->mppe_128)
872+ try.mppe_128 = 0;
873+ if (go->mppe_stateless)
874+ try.mppe_stateless = 0;
875+ if (!try.mppe_56 && !try.mppe_40 && !try.mppe_128)
876+ try.mppe = try.mppe_stateless = 0;
877+ if (wo->mppe) { /* we want MPPE but cannot negotiate key length */
878+ wo->mppc = wo->mppe = wo->mppe_stateless = wo->mppe_40 =
879+ wo->mppe_56 = wo->mppe_128 = 0;
880+ lcp_close(f->unit, "MPPE required but cannot negotiate MPPE "
881+ "key length");
882+ }
883+ }
884     p += CILEN_MPPE;
885     len -= CILEN_MPPE;
886     }
887-#endif
888+#endif /* MPPE */
889+ if (go->lzs && len >= CILEN_LZS && p[0] == CI_LZS && p[1] == CILEN_LZS) {
890+ if (p[2] != go->lzs_hists>>8 || p[3] != (go->lzs_hists&0xff)
891+ || p[4] != go->lzs_mode)
892+ return 0;
893+ try.lzs = 0;
894+ p += CILEN_LZS;
895+ len -= CILEN_LZS;
896+ }
897     if (go->deflate_correct && len >= CILEN_DEFLATE
898     && p[0] == CI_DEFLATE && p[1] == CILEN_DEFLATE) {
899     if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
900@@ -1073,14 +1362,15 @@ ccp_reqci(f, p, lenp, dont_nak)
901     int dont_nak;
902 {
903     int ret, newret, res;
904- u_char *p0, *retp;
905+ u_char *p0, *retp, p2, p5;
906     int len, clen, type, nb;
907     ccp_options *ho = &ccp_hisoptions[f->unit];
908     ccp_options *ao = &ccp_allowoptions[f->unit];
909+ ccp_options *wo = &ccp_wantoptions[f->unit];
910 #ifdef MPPE
911- bool rej_for_ci_mppe = 1; /* Are we rejecting based on a bad/missing */
912- /* CI_MPPE, or due to other options? */
913-#endif
914+ u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
915+/* int mtu; */
916+#endif /* MPPE */
917 
918     ret = CONFACK;
919     retp = p0 = p;
920@@ -1103,106 +1393,302 @@ ccp_reqci(f, p, lenp, dont_nak)
921         switch (type) {
922 #ifdef MPPE
923         case CI_MPPE:
924- if (!ao->mppe || clen != CILEN_MPPE) {
925+ if ((!ao->mppc && !ao->mppe) || clen != CILEN_MPPE) {
926             newret = CONFREJ;
927             break;
928         }
929- MPPE_CI_TO_OPTS(&p[2], ho->mppe);
930-
931- /* Nak if anything unsupported or unknown are set. */
932- if (ho->mppe & MPPE_OPT_UNSUPPORTED) {
933+ p2 = p[2];
934+ p5 = p[5];
935+ /* not sure what they want, tell 'em what we got */
936+ if (((p[2] & ~MPPE_STATELESS) != 0 || p[3] != 0 || p[4] != 0 ||
937+ (p[5] & ~(MPPE_40BIT | MPPE_56BIT | MPPE_128BIT |
938+ MPPE_MPPC)) != 0 || p[5] == 0) ||
939+ (p[2] == 0 && p[3] == 0 && p[4] == 0 && p[5] == 0)) {
940             newret = CONFNAK;
941- ho->mppe &= ~MPPE_OPT_UNSUPPORTED;
942- }
943- if (ho->mppe & MPPE_OPT_UNKNOWN) {
944- newret = CONFNAK;
945- ho->mppe &= ~MPPE_OPT_UNKNOWN;
946- }
947-
948- /* Check state opt */
949- if (ho->mppe & MPPE_OPT_STATEFUL) {
950- /*
951- * We can Nak and request stateless, but it's a
952- * lot easier to just assume the peer will request
953- * it if he can do it; stateful mode is bad over
954- * the Internet -- which is where we expect MPPE.
955- */
956- if (refuse_mppe_stateful) {
957- error("Refusing MPPE stateful mode offered by peer");
958- newret = CONFREJ;
959- break;
960+ p[2] = (wo->mppe_stateless ? MPPE_STATELESS : 0);
961+ p[3] = 0;
962+ p[4] = 0;
963+ p[5] = (wo->mppe_40 ? MPPE_40BIT : 0) |
964+ (wo->mppe_56 ? MPPE_56BIT : 0) |
965+ (wo->mppe_128 ? MPPE_128BIT : 0) |
966+ (wo->mppc ? MPPE_MPPC : 0);
967+ break;
968+ }
969+
970+ if ((p[5] & MPPE_MPPC)) {
971+ if (ao->mppc) {
972+ ho->mppc = 1;
973+ BCOPY(p, opt_buf, CILEN_MPPE);
974+ opt_buf[2] = opt_buf[3] = opt_buf[4] = 0;
975+ opt_buf[5] = MPPE_MPPC;
976+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE, 1) <= 0) {
977+ ho->mppc = 0;
978+ p[5] &= ~MPPE_MPPC;
979+ newret = CONFNAK;
980+ }
981+ } else {
982+ newret = CONFREJ;
983+ if (wo->mppe || ao->mppe) {
984+ p[5] &= ~MPPE_MPPC;
985+ newret = CONFNAK;
986+ }
987             }
988         }
989-
990- /* Find out which of {S,L} are set. */
991- if ((ho->mppe & MPPE_OPT_128)
992- && (ho->mppe & MPPE_OPT_40)) {
993- /* Both are set, negotiate the strongest. */
994- newret = CONFNAK;
995- if (ao->mppe & MPPE_OPT_128)
996- ho->mppe &= ~MPPE_OPT_40;
997- else if (ao->mppe & MPPE_OPT_40)
998- ho->mppe &= ~MPPE_OPT_128;
999- else {
1000- newret = CONFREJ;
1001- break;
1002- }
1003- } else if (ho->mppe & MPPE_OPT_128) {
1004- if (!(ao->mppe & MPPE_OPT_128)) {
1005- newret = CONFREJ;
1006- break;
1007- }
1008- } else if (ho->mppe & MPPE_OPT_40) {
1009- if (!(ao->mppe & MPPE_OPT_40)) {
1010- newret = CONFREJ;
1011- break;
1012- }
1013+ if (ao->mppe)
1014+ ho->mppe = 1;
1015+
1016+ if ((p[2] & MPPE_STATELESS)) {
1017+ if (ao->mppe_stateless) {
1018+ if (wo->mppe_stateless)
1019+ ho->mppe_stateless = 1;
1020+ else {
1021+ newret = CONFNAK;
1022+ if (!dont_nak)
1023+ p[2] &= ~MPPE_STATELESS;
1024+ }
1025+ } else {
1026+ newret = CONFNAK;
1027+ if (!dont_nak)
1028+ p[2] &= ~MPPE_STATELESS;
1029+ }
1030+ } else {
1031+ if (wo->mppe_stateless && !dont_nak) {
1032+ wo->mppe_stateless = 0;
1033+ newret = CONFNAK;
1034+ p[2] |= MPPE_STATELESS;
1035+ }
1036+ }
1037+
1038+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT|MPPE_128BIT)) {
1039+ newret = CONFNAK;
1040+ if (ao->mppe_128) {
1041+ ho->mppe_128 = 1;
1042+ p[5] &= ~(MPPE_40BIT|MPPE_56BIT);
1043+ BCOPY(p, opt_buf, CILEN_MPPE);
1044+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1045+ MPPE_MAX_KEY_LEN);
1046+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1047+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1048+ ho->mppe_128 = 0;
1049+ p[5] |= (MPPE_40BIT|MPPE_56BIT);
1050+ p[5] &= ~MPPE_128BIT;
1051+ goto check_mppe_56_40;
1052+ }
1053+ goto check_mppe;
1054+ }
1055+ p[5] &= ~MPPE_128BIT;
1056+ goto check_mppe_56_40;
1057+ }
1058+ if ((p[5] & ~MPPE_MPPC) == (MPPE_56BIT|MPPE_128BIT)) {
1059+ newret = CONFNAK;
1060+ if (ao->mppe_128) {
1061+ ho->mppe_128 = 1;
1062+ p[5] &= ~MPPE_56BIT;
1063+ BCOPY(p, opt_buf, CILEN_MPPE);
1064+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1065+ MPPE_MAX_KEY_LEN);
1066+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1067+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1068+ ho->mppe_128 = 0;
1069+ p[5] |= MPPE_56BIT;
1070+ p[5] &= ~MPPE_128BIT;
1071+ goto check_mppe_56;
1072+ }
1073+ goto check_mppe;
1074+ }
1075+ p[5] &= ~MPPE_128BIT;
1076+ goto check_mppe_56;
1077+ }
1078+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_128BIT)) {
1079+ newret = CONFNAK;
1080+ if (ao->mppe_128) {
1081+ ho->mppe_128 = 1;
1082+ p[5] &= ~MPPE_40BIT;
1083+ BCOPY(p, opt_buf, CILEN_MPPE);
1084+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1085+ MPPE_MAX_KEY_LEN);
1086+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1087+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1088+ ho->mppe_128 = 0;
1089+ p[5] |= MPPE_40BIT;
1090+ p[5] &= ~MPPE_128BIT;
1091+ goto check_mppe_40;
1092+ }
1093+ goto check_mppe;
1094+ }
1095+ p[5] &= ~MPPE_128BIT;
1096+ goto check_mppe_40;
1097+ }
1098+ if ((p[5] & ~MPPE_MPPC) == MPPE_128BIT) {
1099+ if (ao->mppe_128) {
1100+ ho->mppe_128 = 1;
1101+ BCOPY(p, opt_buf, CILEN_MPPE);
1102+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1103+ MPPE_MAX_KEY_LEN);
1104+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1105+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1106+ ho->mppe_128 = 0;
1107+ p[5] &= ~MPPE_128BIT;
1108+ newret = CONFNAK;
1109+ }
1110+ goto check_mppe;
1111+ }
1112+ p[5] &= ~MPPE_128BIT;
1113+ newret = CONFNAK;
1114+ goto check_mppe;
1115+ }
1116+ check_mppe_56_40:
1117+ if ((p[5] & ~MPPE_MPPC) == (MPPE_40BIT|MPPE_56BIT)) {
1118+ newret = CONFNAK;
1119+ if (ao->mppe_56) {
1120+ ho->mppe_56 = 1;
1121+ p[5] &= ~MPPE_40BIT;
1122+ BCOPY(p, opt_buf, CILEN_MPPE);
1123+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1124+ MPPE_MAX_KEY_LEN);
1125+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1126+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1127+ ho->mppe_56 = 0;
1128+ p[5] |= MPPE_40BIT;
1129+ p[5] &= ~MPPE_56BIT;
1130+ newret = CONFNAK;
1131+ goto check_mppe_40;
1132+ }
1133+ goto check_mppe;
1134+ }
1135+ p[5] &= ~MPPE_56BIT;
1136+ goto check_mppe_40;
1137+ }
1138+ check_mppe_56:
1139+ if ((p[5] & ~MPPE_MPPC) == MPPE_56BIT) {
1140+ if (ao->mppe_56) {
1141+ ho->mppe_56 = 1;
1142+ BCOPY(p, opt_buf, CILEN_MPPE);
1143+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1144+ MPPE_MAX_KEY_LEN);
1145+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1146+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1147+ ho->mppe_56 = 0;
1148+ p[5] &= ~MPPE_56BIT;
1149+ newret = CONFNAK;
1150+ }
1151+ goto check_mppe;
1152+ }
1153+ p[5] &= ~MPPE_56BIT;
1154+ newret = CONFNAK;
1155+ goto check_mppe;
1156+ }
1157+ check_mppe_40:
1158+ if ((p[5] & ~MPPE_MPPC) == MPPE_40BIT) {
1159+ if (ao->mppe_40) {
1160+ ho->mppe_40 = 1;
1161+ BCOPY(p, opt_buf, CILEN_MPPE);
1162+ BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1163+ MPPE_MAX_KEY_LEN);
1164+ if (ccp_test(f->unit, opt_buf, CILEN_MPPE +
1165+ MPPE_MAX_KEY_LEN, 1) <= 0) {
1166+ ho->mppe_40 = 0;
1167+ p[5] &= ~MPPE_40BIT;
1168+ newret = CONFNAK;
1169+ }
1170+ goto check_mppe;
1171+ }
1172+ p[5] &= ~MPPE_40BIT;
1173+ }
1174+
1175+ check_mppe:
1176+ if (!ho->mppe_40 && !ho->mppe_56 && !ho->mppe_128) {
1177+ if (wo->mppe_40 || wo->mppe_56 || wo->mppe_128) {
1178+ newret = CONFNAK;
1179+ p[2] |= (wo->mppe_stateless ? MPPE_STATELESS : 0);
1180+ p[5] |= (wo->mppe_40 ? MPPE_40BIT : 0) |
1181+ (wo->mppe_56 ? MPPE_56BIT : 0) |
1182+ (wo->mppe_128 ? MPPE_128BIT : 0) |
1183+ (wo->mppc ? MPPE_MPPC : 0);
1184+ } else {
1185+ ho->mppe = ho->mppe_stateless = 0;
1186+ }
1187         } else {
1188- /* Neither are set. */
1189- /* We cannot accept this. */
1190- newret = CONFNAK;
1191- /* Give the peer our idea of what can be used,
1192- so it can choose and confirm */
1193- ho->mppe = ao->mppe;
1194- }
1195-
1196- /* rebuild the opts */
1197- MPPE_OPTS_TO_CI(ho->mppe, &p[2]);
1198- if (newret == CONFACK) {
1199- u_char opt_buf[CILEN_MPPE + MPPE_MAX_KEY_LEN];
1200- int mtu;
1201-
1202- BCOPY(p, opt_buf, CILEN_MPPE);
1203- BCOPY(mppe_send_key, &opt_buf[CILEN_MPPE],
1204- MPPE_MAX_KEY_LEN);
1205- if (ccp_test(f->unit, opt_buf,
1206- CILEN_MPPE + MPPE_MAX_KEY_LEN, 1) <= 0) {
1207- /* This shouldn't happen, we've already tested it! */
1208- error("MPPE required, but kernel has no support.");
1209- lcp_close(f->unit, "MPPE required but not available");
1210- newret = CONFREJ;
1211- break;
1212- }
1213- /*
1214- * We need to decrease the interface MTU by MPPE_PAD
1215- * because MPPE frames **grow**. The kernel [must]
1216- * allocate MPPE_PAD extra bytes in xmit buffers.
1217- */
1218- mtu = netif_get_mtu(f->unit);
1219- if (mtu)
1220- netif_set_mtu(f->unit, mtu - MPPE_PAD);
1221- else
1222- newret = CONFREJ;
1223- }
1224-
1225- /*
1226- * We have accepted MPPE or are willing to negotiate
1227- * MPPE parameters. A CONFREJ is due to subsequent
1228- * (non-MPPE) processing.
1229- */
1230- rej_for_ci_mppe = 0;
1231- break;
1232-#endif /* MPPE */
1233+ /* MPPE is not compatible with other compression types */
1234+ if (wo->mppe) {
1235+ ao->bsd_compress = 0;
1236+ ao->predictor_1 = 0;
1237+ ao->predictor_2 = 0;
1238+ ao->deflate = 0;
1239+ ao->lzs = 0;
1240+ }
1241+ }
1242+ if ((!ho->mppc || !ao->mppc) && !ho->mppe) {
1243+ p[2] = p2;
1244+ p[5] = p5;
1245+ newret = CONFREJ;
1246+ break;
1247+ }
1248+
1249+ /*
1250+ * I have commented the code below because according to RFC1547
1251+ * MTU is only information for higher level protocols about
1252+ * "the maximum allowable length for a packet (q.v.) transmitted
1253+ * over a point-to-point link without incurring network layer
1254+ * fragmentation." Of course a PPP implementation should be able
1255+ * to handle overhead added by MPPE - in our case apropriate code
1256+ * is located in drivers/net/ppp_generic.c in the kernel sources.
1257+ *
1258+ * According to RFC1661:
1259+ * - when negotiated MRU is less than 1500 octets, a PPP
1260+ * implementation must still be able to receive at least 1500
1261+ * octets,
1262+ * - when PFC is negotiated, a PPP implementation is still
1263+ * required to receive frames with uncompressed protocol field.
1264+ *
1265+ * So why not to handle MPPE overhead without changing MTU value?
1266+ * I am sure that RFC3078, unfortunately silently, assumes that.
1267+ */
1268+
1269+ /*
1270+ * We need to decrease the interface MTU by MPPE_PAD
1271+ * because MPPE frames **grow**. The kernel [must]
1272+ * allocate MPPE_PAD extra bytes in xmit buffers.
1273+ */
1274+ /*
1275+ mtu = netif_get_mtu(f->unit);
1276+ if (mtu) {
1277+ netif_set_mtu(f->unit, mtu - MPPE_PAD);
1278+ } else {
1279+ newret = CONFREJ;
1280+ if (ccp_wantoptions[f->unit].mppe) {
1281+ error("Cannot adjust MTU needed by MPPE.");
1282+ lcp_close(f->unit, "Cannot adjust MTU needed by MPPE.");
1283+ }
1284+ }
1285+ */
1286+ break;
1287+ #endif /* MPPE */
1288+
1289+ case CI_LZS:
1290+ if (!ao->lzs || clen != CILEN_LZS) {
1291+ newret = CONFREJ;
1292+ break;
1293+ }
1294+
1295+ ho->lzs = 1;
1296+ ho->lzs_hists = (p[2] << 8) | p[3];
1297+ ho->lzs_mode = p[4];
1298+ if ((ho->lzs_hists != ao->lzs_hists) ||
1299+ (ho->lzs_mode != ao->lzs_mode)) {
1300+ newret = CONFNAK;
1301+ if (!dont_nak) {
1302+ p[2] = ao->lzs_hists >> 8;
1303+ p[3] = ao->lzs_hists & 0xff;
1304+ p[4] = ao->lzs_mode;
1305+ } else
1306+ break;
1307+ }
1308+
1309+ if (p == p0 && ccp_test(f->unit, p, CILEN_LZS, 1) <= 0) {
1310+ newret = CONFREJ;
1311+ }
1312+ break;
1313         case CI_DEFLATE:
1314         case CI_DEFLATE_DRAFT:
1315         if (!ao->deflate || clen != CILEN_DEFLATE
1316@@ -1344,12 +1830,6 @@ ccp_reqci(f, p, lenp, dont_nak)
1317     else
1318         *lenp = retp - p0;
1319     }
1320-#ifdef MPPE
1321- if (ret == CONFREJ && ao->mppe && rej_for_ci_mppe) {
1322- error("MPPE required but peer negotiation failed");
1323- lcp_close(f->unit, "MPPE required but peer negotiation failed");
1324- }
1325-#endif
1326     return ret;
1327 }
1328 
1329@@ -1371,24 +1851,35 @@ method_name(opt, opt2)
1330     char *p = result;
1331     char *q = result + sizeof(result); /* 1 past result */
1332 
1333- slprintf(p, q - p, "MPPE ");
1334- p += 5;
1335- if (opt->mppe & MPPE_OPT_128) {
1336- slprintf(p, q - p, "128-bit ");
1337- p += 8;
1338- }
1339- if (opt->mppe & MPPE_OPT_40) {
1340- slprintf(p, q - p, "40-bit ");
1341- p += 7;
1342- }
1343- if (opt->mppe & MPPE_OPT_STATEFUL)
1344- slprintf(p, q - p, "stateful");
1345- else
1346- slprintf(p, q - p, "stateless");
1347-
1348+ if (opt->mppe) {
1349+ if (opt->mppc) {
1350+ slprintf(p, q - p, "MPPC/MPPE ");
1351+ p += 10;
1352+ } else {
1353+ slprintf(p, q - p, "MPPE ");
1354+ p += 5;
1355+ }
1356+ if (opt->mppe_128) {
1357+ slprintf(p, q - p, "128-bit ");
1358+ p += 8;
1359+ } else if (opt->mppe_56) {
1360+ slprintf(p, q - p, "56-bit ");
1361+ p += 7;
1362+ } else if (opt->mppe_40) {
1363+ slprintf(p, q - p, "40-bit ");
1364+ p += 7;
1365+ }
1366+ if (opt->mppe_stateless)
1367+ slprintf(p, q - p, "stateless");
1368+ else
1369+ slprintf(p, q - p, "stateful");
1370+ } else if (opt->mppc)
1371+ slprintf(p, q - p, "MPPC");
1372     break;
1373     }
1374-#endif
1375+#endif /* MPPE */
1376+ case CI_LZS:
1377+ return "Stac LZS";
1378     case CI_DEFLATE:
1379     case CI_DEFLATE_DRAFT:
1380     if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
1381@@ -1444,12 +1935,12 @@ ccp_up(f)
1382     } else if (ANY_COMPRESS(*ho))
1383     notice("%s transmit compression enabled", method_name(ho, NULL));
1384 #ifdef MPPE
1385- if (go->mppe) {
1386+ if (go->mppe || go->mppc) {
1387     BZERO(mppe_recv_key, MPPE_MAX_KEY_LEN);
1388     BZERO(mppe_send_key, MPPE_MAX_KEY_LEN);
1389     continue_networks(f->unit); /* Bring up IP et al */
1390     }
1391-#endif
1392+#endif /* MPPE */
1393 }
1394 
1395 /*
1396@@ -1472,7 +1963,7 @@ ccp_down(f)
1397         lcp_close(f->unit, "MPPE disabled");
1398     }
1399     }
1400-#endif
1401+#endif /* MPPE */
1402 }
1403 
1404 /*
1405@@ -1532,24 +2023,28 @@ ccp_printpkt(p, plen, printer, arg)
1406 #ifdef MPPE
1407         case CI_MPPE:
1408         if (optlen >= CILEN_MPPE) {
1409- u_char mppe_opts;
1410-
1411- MPPE_CI_TO_OPTS(&p[2], mppe_opts);
1412- printer(arg, "mppe %s %s %s %s %s %s%s",
1413- (p[2] & MPPE_H_BIT)? "+H": "-H",
1414- (p[5] & MPPE_M_BIT)? "+M": "-M",
1415- (p[5] & MPPE_S_BIT)? "+S": "-S",
1416- (p[5] & MPPE_L_BIT)? "+L": "-L",
1417+ printer(arg, "mppe %s %s %s %s %s %s",
1418+ (p[2] & MPPE_STATELESS)? "+H": "-H",
1419+ (p[5] & MPPE_56BIT)? "+M": "-M",
1420+ (p[5] & MPPE_128BIT)? "+S": "-S",
1421+ (p[5] & MPPE_40BIT)? "+L": "-L",
1422                 (p[5] & MPPE_D_BIT)? "+D": "-D",
1423- (p[5] & MPPE_C_BIT)? "+C": "-C",
1424- (mppe_opts & MPPE_OPT_UNKNOWN)? " +U": "");
1425- if (mppe_opts & MPPE_OPT_UNKNOWN)
1426+ (p[5] & MPPE_MPPC)? "+C": "-C");
1427+ if ((p[5] & ~(MPPE_56BIT | MPPE_128BIT | MPPE_40BIT |
1428+ MPPE_D_BIT | MPPE_MPPC)) ||
1429+ (p[2] & ~MPPE_STATELESS))
1430             printer(arg, " (%.2x %.2x %.2x %.2x)",
1431                 p[2], p[3], p[4], p[5]);
1432             p += CILEN_MPPE;
1433         }
1434         break;
1435-#endif
1436+#endif /* MPPE */
1437+ case CI_LZS:
1438+ if (optlen >= CILEN_LZS) {
1439+ printer(arg, "lzs %.2x %.2x %.2x", p[2], p[3], p[4]);
1440+ p += CILEN_LZS;
1441+ }
1442+ break;
1443         case CI_DEFLATE:
1444         case CI_DEFLATE_DRAFT:
1445         if (optlen >= CILEN_DEFLATE) {
1446@@ -1635,6 +2130,7 @@ ccp_datainput(unit, pkt, len)
1447         error("Lost compression sync: disabling compression");
1448         ccp_close(unit, "Lost compression sync");
1449 #ifdef MPPE
1450+ /* My module dosn't need this. J.D., 2003-07-06 */
1451         /*
1452          * If we were doing MPPE, we must also take the link down.
1453          */
1454@@ -1642,9 +2138,18 @@ ccp_datainput(unit, pkt, len)
1455         error("Too many MPPE errors, closing LCP");
1456         lcp_close(unit, "Too many MPPE errors");
1457         }
1458-#endif
1459+#endif /* MPPE */
1460     } else {
1461         /*
1462+ * When LZS or MPPE/MPPC is negotiated we just send CCP_RESETREQ
1463+ * and don't wait for CCP_RESETACK
1464+ */
1465+ if ((ccp_gotoptions[f->unit].method == CI_LZS) ||
1466+ (ccp_gotoptions[f->unit].method == CI_MPPE)) {
1467+ fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1468+ return;
1469+ }
1470+ /*
1471          * Send a reset-request to reset the peer's compressor.
1472          * We don't do that if we are still waiting for an
1473          * acknowledgement to a previous reset-request.
1474@@ -1675,4 +2180,3 @@ ccp_rack_timeout(arg)
1475     } else
1476     ccp_localstate[f->unit] &= ~RACK_PENDING;
1477 }
1478-
1479--- a/pppd/ccp.h
1480+++ b/pppd/ccp.h
1481@@ -37,9 +37,17 @@ typedef struct ccp_options {
1482     bool predictor_2; /* do Predictor-2? */
1483     bool deflate_correct; /* use correct code for deflate? */
1484     bool deflate_draft; /* use draft RFC code for deflate? */
1485+ bool lzs; /* do Stac LZS? */
1486+ bool mppc; /* do MPPC? */
1487     bool mppe; /* do MPPE? */
1488+ bool mppe_40; /* allow 40 bit encryption? */
1489+ bool mppe_56; /* allow 56 bit encryption? */
1490+ bool mppe_128; /* allow 128 bit encryption? */
1491+ bool mppe_stateless; /* allow stateless encryption */
1492     u_short bsd_bits; /* # bits/code for BSD Compress */
1493     u_short deflate_size; /* lg(window size) for Deflate */
1494+ u_short lzs_mode; /* LZS check mode */
1495+ u_short lzs_hists; /* number of LZS histories */
1496     short method; /* code for chosen compression method */
1497 } ccp_options;
1498 
1499--- a/pppd/chap_ms.c
1500+++ b/pppd/chap_ms.c
1501@@ -897,13 +897,17 @@ set_mppe_enc_types(int policy, int types
1502     /*
1503      * Disable undesirable encryption types. Note that we don't ENABLE
1504      * any encryption types, to avoid overriding manual configuration.
1505+ *
1506+ * It seems that 56 bit keys are unsupported in MS-RADIUS (see RFC 2548)
1507      */
1508     switch(types) {
1509     case MPPE_ENC_TYPES_RC4_40:
1510- ccp_wantoptions[0].mppe &= ~MPPE_OPT_128; /* disable 128-bit */
1511+ ccp_wantoptions[0].mppe_128 = 0; /* disable 128-bit */
1512+ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
1513         break;
1514     case MPPE_ENC_TYPES_RC4_128:
1515- ccp_wantoptions[0].mppe &= ~MPPE_OPT_40; /* disable 40-bit */
1516+ ccp_wantoptions[0].mppe_56 = 0; /* disable 56-bit */
1517+ ccp_wantoptions[0].mppe_40 = 0; /* disable 40-bit */
1518         break;
1519     default:
1520         break;
1521

Archive Download this file



interactive