backport from HEAD
[freeradius.git] / src / modules / rlm_otp / otp_pwe.c
1 /*
2  * otp_pwe.c
3  * $Id$
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Copyright 2001,2002  Google, Inc.
20  * Copyright 2005 TRI-D Systems, Inc.
21  */
22
23 /*
24  * This file implements passcode (password) checking functions for each
25  * supported encoding (PAP, CHAP, etc.).  The current libradius interface
26  * is not sufficient for X9.9 use.
27  */
28
29 #ifdef FREERADIUS
30 #define _LRAD_MD4_H
31 #define _LRAD_SHA1_H
32 #include <rad_assert.h>
33 #endif
34 #include "otp.h"
35 #include "otp_pwe.h"
36
37 #include <openssl/des.h>
38 #include <openssl/md4.h>
39 #include <openssl/md5.h>
40 #include <openssl/sha.h>
41
42 #include <string.h>
43
44 static const char rcsid[] = "$Id$";
45
46
47 /* Attribute IDs for supported password encodings. */
48 static int pwattr[8];
49
50
51 /* Initialize the pwattr array for supported password encodings. */
52 void
53 otp_pwe_init(void)
54 {
55   DICT_ATTR *da;
56   int i = 0;
57
58   /*
59    * Setup known password types.  These are pairs.
60    * NB: Increase pwattr array size when adding a type.
61    *     It should be sized as (number of password types * 2)
62    */
63   (void) memset(pwattr, 0, sizeof(pwattr));
64
65   /* PAP */
66   if ((da = dict_attrbyname("User-Password")) != NULL) {
67     pwattr[i++] = da->attr;
68     pwattr[i++] = da->attr;
69   }
70
71   /* CHAP */
72   if ((da = dict_attrbyname("CHAP-Challenge")) != NULL) {
73     pwattr[i++] = da->attr;
74     if ((da = dict_attrbyname("CHAP-Password")) != NULL)
75       pwattr[i++] = da->attr;
76     else
77       pwattr[--i] = 0;
78   }
79
80 #if 0
81   /* MS-CHAP (recommended not to use) */
82   if ((da = dict_attrbyname("MS-CHAP-Challenge")) != NULL) {
83     pwattr[i++] = da->attr;
84     if ((da = dict_attrbyname("MS-CHAP-Response")) != NULL)
85       pwattr[i++] = da->attr;
86     else
87       pwattr[--i] = 0;
88   }
89 #endif /* 0 */
90
91   /* MS-CHAPv2 */
92   if ((da = dict_attrbyname("MS-CHAP-Challenge")) != NULL) {
93     pwattr[i++] = da->attr;
94     if ((da = dict_attrbyname("MS-CHAP2-Response")) != NULL)
95       pwattr[i++] = da->attr;
96     else
97       pwattr[--i] = 0;
98   }
99 }
100
101
102 /*
103  * Test for password presence in an Access-Request packet.
104  * Returns 0 for "no supported password present", or an non-zero
105  * opaque value that must be used when calling otp_pwe_cmp().
106  */
107 int
108 otp_pwe_present(const REQUEST *request, const char *log_prefix)
109 {
110   unsigned i;
111
112   for (i = 0; i < sizeof(pwattr) && pwattr[i]; i += 2) {
113     if (pairfind(request->packet->vps, pwattr[i]) &&
114         pairfind(request->packet->vps, pwattr[i + 1])) {
115       DEBUG("%s: %s: password attributes %d, %d", log_prefix, __func__,
116              pwattr[i], pwattr[i + 1]);
117       return i + 1; /* Can't return 0 (indicates failure) */
118     }
119   }
120
121   DEBUG("%s: %s: no password attributes present", log_prefix, __func__);
122   return 0;
123 }
124
125
126 /*
127  * Test for passcode (password) equality.
128  * returns 0 for match, non-zero for non-match.
129  * If data->returned_vps is non-null, then on matches, it will point to
130  * vps that should be added to an Access-Accept packet.  If access is denied,
131  * the caller is responsible for freeing any vps returned.
132  */
133 int
134 otp_pwe_cmp(struct otp_pwe_cmp_t *data, const char *password,
135             const char *log_prefix)
136 {
137   const REQUEST *request        = data->request;
138   const otp_option_t *inst      = data->inst;
139   int attr                      = data->pwattr;
140   VALUE_PAIR **vps              = data->returned_vps;
141
142   int nmatch = -1;
143   VALUE_PAIR *chal_vp, *resp_vp;
144
145   /*
146    * A module that does this might want to verify the presence of these.
147    * This code is self contained to otp, so I know these exist.
148    */
149   chal_vp = pairfind(request->packet->vps, pwattr[attr - 1]);
150   resp_vp = pairfind(request->packet->vps, pwattr[attr]);
151
152   /* Prepare for failure return. */
153   if (vps)
154     *vps = NULL;
155
156   /* If modular, this would actually call the authentication function. */
157   switch(pwattr[attr]) {
158   case PW_PASSWORD:
159     DEBUG("%s: %s: handling PW_PASSWORD", log_prefix, __func__);
160     nmatch = strcmp(password, resp_vp->strvalue);
161     break;
162
163   case PW_CHAP_PASSWORD:
164   {
165     /*
166      * See RFC 1994.
167      * A CHAP password is MD5(CHAP_ID|SECRET|CHAP_CHALLENGE).
168      * CHAP_ID is a value set by the authenticator (the NAS), and used
169      * in the response calculation.  It is available as the first byte
170      * of the CHAP-Password attribute.
171      * SECRET is the password.
172      * CHAP_CHALLENGE is the challenge given to the peer (the user).
173      * The CHAP-Challenge Attribute may be missing, in which case the
174      * challenge is taken to be the Request Authenticator.  We don't
175      * handle this case.
176      */
177     /*                 ID       password    chal */
178     unsigned char input[1 + MAX_STRING_LEN + 16];
179     unsigned char output[MD5_DIGEST_LENGTH];
180
181     DEBUG("%s: %s: handling PW_CHAP_PASSWORD", log_prefix, __func__);
182     if (1 + strlen(password) + chal_vp->length > sizeof(input)) {
183       DEBUG("%s: %s: CHAP-Challenge/password too long", log_prefix, __func__);
184       nmatch = -1;
185       break;
186     }
187     if (resp_vp->length != 17) {
188       otp_log(OTP_LOG_AUTH, "%s: %s: CHAP-Password wrong size",
189               log_prefix, __func__);
190       nmatch = -1;
191       break;
192     }
193     input[0] = *(resp_vp->strvalue);
194     (void) memcpy(&input[1], password, strlen(password));
195     (void) memcpy(&input[1+strlen(password)], chal_vp->strvalue,
196                   chal_vp->length);
197     (void) MD5(input, 1 + strlen(password) + chal_vp->length, output);
198     nmatch = memcmp(output, &(resp_vp->strvalue)[1], MD5_DIGEST_LENGTH);
199   } /* case PW_CHAP_PASSWORD */
200   break;
201
202 #if 0
203   case PW_MS_CHAP_RESPONSE:
204   {
205     /*
206      * See RFCs 2548, 2433, 3079.
207      * An MS-CHAP response is (IDENT|FLAGS|LM_RESPONSE|NT_RESPONSE).
208      *                 octets:   1     1       24           24
209      * IDENT is not used by RADIUS (it is the PPP MS-CHAP Identifier).
210      * FLAGS is 1 to indicate the NT_RESPONSE should be preferred.
211      * LM_RESPONSE is the LAN Manager compatible response.
212      * NT_RESPONSE is the NT compatible response.
213      * Either response may be zero-filled indicating its absence.
214      * Use of the LM response has been deprecated (RFC 2433, par. 6),
215      * so we don't handle it.
216      *
217      * The NT_RESPONSE is (DES(CHAL,K1)|DES(CHAL,K2)|DES(CHAL,K3)), where
218      * CHAL is the 8-octet challenge, and K1, K2, K3 are 7-octet pieces
219      * of MD4(unicode(password)), zero-filled to 21 octets.  Sigh.
220      */
221     unsigned char nt_keys[21]; /* sized for 3 DES keys */
222     unsigned char input[MAX_STRING_LEN * 2]; /* doubled for unicode */
223     unsigned char output[24];
224     int password_len, i;
225     VALUE_PAIR *vp;
226
227     DEBUG("%s: %s: handling PW_MS_CHAP_RESPONSE", log_prefix, __func__);
228     if (chal_vp->length != 8) {
229       otp_log(OTP_LOG_AUTH, "%s: %s: MS-CHAP-Challenge wrong size",
230               log_prefix, __func__);
231       nmatch = -1;
232       break;
233     }
234     if (resp_vp->length != 50) {
235       otp_log(OTP_LOG_AUTH, "%s: %s: MS-CHAP-Response wrong size",
236               log_prefix, __func__);
237       nmatch = -1;
238       break;
239     }
240     if ((resp_vp->strvalue)[1] != 1) {
241       otp_log(OTP_LOG_AUTH,
242               "%s: %s: MS-CHAP-Response bad flags (LM not supported)",
243               log_prefix, __func__);
244       nmatch = -1;
245       break;
246     }
247     /* This is probably overkill. */
248     if (strlen(password) > MAX_STRING_LEN) {
249       otp_log(OTP_LOG_AUTH, "%s: %s: MS-CHAP password too long",
250               log_prefix, __func__);
251       nmatch = -1;
252       break;
253     }
254
255     /*
256      * Start by hashing the unicode password.
257      * This is broken because unicode chars are machine-ordered,
258      * but the spec (RFC 2433) doesn't say how to prepare
259      * the password for md4 (other than by example values).
260      */
261     password_len = strlen(password);
262     for (i = 0; i < password_len; ++i) {
263       /* Set the high order 8 bits to 0 (little-endian) */
264       input[i * 2] = *password++;
265       input[i * 2 + 1] = 0;
266     }
267     (void) memset(nt_keys, 0, sizeof(nt_keys));
268     (void) MD4(input, 2 * password_len, nt_keys);
269
270     /* The challenge gets encrypted. */
271     (void) memcpy(input, chal_vp->strvalue, 8);
272
273     /* Convert the password hash to keys, and do the encryptions. */
274     for (i = 0; i < 3; ++i) {
275       des_cblock key;
276       des_key_schedule ks;
277
278       otp_key_from_hash(&key, &nt_keys[i * 7]);
279       des_set_key_unchecked(&key, ks);
280       des_ecb_encrypt((des_cblock *) input,
281                       (des_cblock *) &output[i * 8],
282                       ks, DES_ENCRYPT);
283     }
284
285     nmatch = memcmp(output, resp_vp->strvalue + 26, 24);
286     if (nmatch || !vps)
287       break;
288
289     /*
290      * Generate the MS-CHAP-MPPE-Keys attribute if needed.  This is not
291      * specified anywhere -- RFC 2548, par. 2.4.1 is the authority but
292      * it has typos and omissions that make this unimplementable.  The
293      * code here is based on experimental results provided by
294      * Takahiro Wagatsuma <waga@sic.shibaura-it.ac.jp>.
295      * We only support 128-bit keys derived from the NT hash; 40-bit
296      * and 56-bit keys are derived from the LM hash, which besides
297      * being deprecated, has severe security problems.
298      */
299
300     /* First, set some related attributes. */
301     vp = pairmake("MS-MPPE-Encryption-Policy",
302                   otp_mppe_policy[inst->mschap_mppe_policy], T_OP_EQ);
303     rad_assert(vp != NULL);
304     pairadd(vps, vp);
305     vp = pairmake("MS-MPPE-Encryption-Types",
306                   otp_mppe_types[inst->mschap_mppe_types], T_OP_EQ);
307     rad_assert(vp != NULL);
308     pairadd(vps, vp);
309
310     if (inst->mschap_mppe_policy) {
311       unsigned char mppe_keys[32];
312       /*                    0x    ASCII(mppe_keys)      '\0' */
313       char mppe_keys_string[2 + (2 * sizeof(mppe_keys)) + 1];
314
315       unsigned char md5_md[MD5_DIGEST_LENGTH];
316       unsigned char encode_buf[AUTH_VECTOR_LEN + MAX_STRING_LEN];
317       int secretlen;
318
319       /* Zero the LM-Key sub-field (and padding). */
320       (void) memset(mppe_keys, 0, sizeof(mppe_keys));
321       /* The NT-Key sub-field is MD4(MD4(unicode(password))). */
322       (void) MD4(nt_keys, 16, &mppe_keys[8]);
323
324 #if 0 /* encoding now handled in lib/radius.c:rad_pwencode() */
325       /* Now we must encode the key as User-Password is encoded. */
326       secretlen = strlen(request->secret);
327       (void) memcpy(encode_buf, request->secret, secretlen);
328       (void) memcpy(encode_buf + secretlen, request->packet->vector,
329                     AUTH_VECTOR_LEN);
330       (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN, md5_md);
331       for (i = 0; i < 16; ++i)
332         mppe_keys[i] ^= md5_md[i];
333       (void) memcpy(encode_buf + secretlen, mppe_keys, MD5_DIGEST_LENGTH);
334       (void) MD5(encode_buf, secretlen + MD5_DIGEST_LENGTH, md5_md);
335       for (i = 0; i < 16; ++i)
336         mppe_keys[i + 16] ^= md5_md[i];
337 #endif /* 0 */
338
339       /* Whew.  Now stringify it for pairmake(). */
340       mppe_keys_string[0] = '0';
341       mppe_keys_string[1] = 'x';
342       for (i = 0; i < 32; ++i)
343         (void) sprintf(&mppe_keys_string[i*2+2], "%02X", mppe_keys[i]);
344       vp = pairmake("MS-CHAP-MPPE-Keys", mppe_keys_string, T_OP_EQ);
345       rad_assert(vp != NULL);
346       pairadd(vps, vp);
347     } /* if (doing mppe) */
348
349   } /* case PW_MS_CHAP_RESPONSE */
350   break;
351 #endif /* 0 (MS_CHAP) */
352
353   case PW_MS_CHAP2_RESPONSE:
354   {
355     /*
356      * See RFCs 2548, 2759, 3079.
357      * An MS-CHAPv2 response is
358      *          (IDENT|FLAGS|PEER_CHALLENGE|RESERVED|NT_RESPONSE).
359      *   octets:   1     1         16          8        24
360      * IDENT is the PPP MS-CHAPv2 Identifier, used in MS-CHAP2-Success.
361      * FLAGS is currently unused.
362      * PEER_CHALLENGE is a random number, generated by the peer.
363      * NT_RESPONSE is (DES(CHAL,K1)|DES(CHAL,K2)|DES(CHAL,K3)), where
364      * K1, K2, K3 are 7-octet pieces of MD4(unicode(password)), zero-
365      * filled to 21 octets (just as in MS-CHAP); and CHAL is
366      * MSB8(SHA(PEER_CHALLENGE|MS_CHAP_CHALLENGE|USERNAME)).
367      */
368     unsigned char nt_keys[21]; /* aka "password_md", sized for 3 DES keys */
369     unsigned char password_md_md[MD4_DIGEST_LENGTH]; /* for mutual auth */
370     unsigned char input[MAX_STRING_LEN * 2]; /* doubled for unicode */
371     unsigned char output[24];
372     unsigned password_len, i;
373     VALUE_PAIR *vp;
374
375     DEBUG("%s: %s: handling PW_MS_CHAP2_RESPONSE", log_prefix, __func__);
376     if (chal_vp->length != 16) {
377       otp_log(OTP_LOG_AUTH, "%s: %s: MS-CHAP-Challenge (v2) wrong size",
378               log_prefix, __func__);
379       nmatch = -1;
380       break;
381     }
382     if (resp_vp->length != 50) {
383       otp_log(OTP_LOG_AUTH, "%s: %s: MS-CHAP2-Response wrong size",
384               log_prefix, __func__);
385       nmatch = -1;
386       break;
387     }
388     /* This is probably overkill. */
389     if (strlen(password) > MAX_STRING_LEN) {
390       otp_log(OTP_LOG_AUTH, "%s: %s: MS-CHAPv2 password too long",
391               log_prefix, __func__);
392       nmatch = -1;
393       break;
394     }
395
396     /*
397      * Start by hashing the unicode password.
398      * This is broken because unicode chars are machine-ordered,
399      * but the spec (RFC 2759) doesn't say how to prepare
400      * the password for md4 (other than by example values).
401      */
402     password_len = strlen(password);
403     for (i = 0; i < password_len; ++i) {
404       /* Set the high order 8 bits to 0 (little-endian) */
405       input[i * 2] = *password++;
406       input[i * 2 + 1] = 0;
407     }
408     (void) memset(nt_keys, 0, sizeof(nt_keys));
409     (void) MD4(input, 2 * password_len, nt_keys);
410
411     /* Now calculate the CHAL value from our various inputs. */
412     {
413       SHA_CTX ctx;
414       unsigned char md[SHA_DIGEST_LENGTH];
415       char *username = request->username->strvalue;
416       int username_len = request->username->length;
417
418       SHA1_Init(&ctx);
419       SHA1_Update(&ctx, resp_vp->strvalue + 2, 16);
420       SHA1_Update(&ctx, chal_vp->strvalue, 16);
421       SHA1_Update(&ctx, username, username_len);
422       SHA1_Final(md, &ctx);
423
424       (void) memcpy(input, md, 8);
425     }
426
427     /* Convert the password hash to keys, and do the encryptions. */
428     for (i = 0; i < 3; ++i) {
429       des_cblock key;
430       des_key_schedule ks;
431
432       otp_key_from_hash(&key, &nt_keys[i * 7]);
433       des_set_key_unchecked(&key, ks);
434       des_ecb_encrypt((des_cblock *) input,
435                       (des_cblock *) &output[i * 8],
436                       ks, DES_ENCRYPT);
437     }
438
439     nmatch = memcmp(output, resp_vp->strvalue + 26, 24);
440     if (nmatch || !vps)
441       break;
442
443     /*
444      * MS-CHAPv2 requires mutual authentication; we must prove
445      * that we know the secret.  This is a bit circuitous: set
446      * MD1 = SHA(MD4(MD4(unicode(password)))|NT_RESPONSE|MAGIC1),
447      * MD2 = MSB8(SHA(PEER_CHALLENGE|MS_CHAP_CHALLENGE|USERNAME)),
448      * and finally use SHA(MD1|MD2|MAGIC2) as the authenticator.
449      * The authenticator is returned as the string "S=<auth>",
450      * <auth> is the authenticator expressed as [uppercase] ASCII.
451      * See RFC 2759.
452      */
453     {
454       SHA_CTX ctx;
455       unsigned char md1[SHA_DIGEST_LENGTH];
456       unsigned char md2[SHA_DIGEST_LENGTH];
457       unsigned char auth_md[SHA_DIGEST_LENGTH];
458       /*                  S=  (  ASCII(auth_md)   )  \0 */
459       char auth_md_string[2 + (2 * sizeof(auth_md)) + 1];
460       /*
461        * ugh.  The ASCII authenticator (auth_md_string) is sent
462        * along with a single (useless) binary byte (the ID).
463        * So we must "stringify" it again (for pairmake()) since the
464        * binary byte requires the attribute to be of type "octets".
465        */
466       /*                    0x  (ID) ( ASCII("S="ASCII(auth_md))) */
467       char auth_octet_string[2 + 2 + (2 * sizeof(auth_md_string))];
468
469       char *username = request->username->strvalue;
470       int username_len = request->username->length;
471
472       /* "Magic server to client signing constant" */
473       unsigned char magic1[39] =
474         { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
475           0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
476           0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
477           0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };
478       /* "Pad to make it do more than one iteration" */
479       unsigned char magic2[41] =
480         { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
481           0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
482           0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
483           0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
484           0x6E };
485
486       /* MD1 */
487       (void) MD4(nt_keys, MD4_DIGEST_LENGTH, password_md_md);
488       SHA1_Init(&ctx);
489       SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
490       SHA1_Update(&ctx, resp_vp->strvalue + 26, 24);
491       SHA1_Update(&ctx, magic1, sizeof(magic1));
492       SHA1_Final(md1, &ctx);
493
494       /* MD2 */
495       SHA1_Init(&ctx);
496       SHA1_Update(&ctx, resp_vp->strvalue + 2, 16);
497       SHA1_Update(&ctx, chal_vp->strvalue, 16);
498       SHA1_Update(&ctx, username, username_len);
499       SHA1_Final(md2, &ctx);
500
501       /* The Authenticator */
502       SHA1_Init(&ctx);
503       SHA1_Update(&ctx, md1, SHA_DIGEST_LENGTH);
504       SHA1_Update(&ctx, md2, 8);
505       SHA1_Update(&ctx, magic2, sizeof(magic2));
506       SHA1_Final(auth_md, &ctx);
507
508       /* String conversion. */
509       auth_md_string[0] = 'S';
510       auth_md_string[1] = '=';
511       for (i = 0; i < sizeof(auth_md); ++i)
512         (void) sprintf(&auth_md_string[i * 2 + 2], "%02X", auth_md[i]);
513
514       /* And then octet conversion.  Ugh! */
515       auth_octet_string[0] = '0';
516       auth_octet_string[1] = 'x';
517       (void) sprintf(&auth_octet_string[2], "%02X", resp_vp->strvalue[0]);
518       for (i = 0; i < sizeof(auth_md_string) - 1; ++i)
519         (void) sprintf(&auth_octet_string[i * 2 +4], "%02X", auth_md_string[i]);
520
521       vp = pairmake("MS-CHAP2-Success", auth_octet_string, T_OP_EQ);
522       rad_assert(vp != NULL);
523       pairadd(vps, vp);
524     } /* Generate mutual auth info. */
525
526     /*
527      * Generate the MPPE initial session key if needed, per RFC 3079.
528      * (Although, RFC 2548 leaves us guessing at how to generate this.)
529      * For MS-CHAPv2 we support all key lengths (40-, 56- and 128-bit),
530      * although MPPE via RADIUS supports only 40- and 128-bit keys.
531      * This is a bit more complicated than MS-CHAP.  Start by generating
532      * a "master session key"
533      *    MSB16(SHA(NTPasswordHashHash|NT_RESPONSE|MAGIC1)), where
534      * NTPasswordHashHash is MD4(MD4(unicode(password))), NT_RESPONSE
535      * is from the MS-CHAP2-Response attribute, and MAGIC1 is a
536      * constant from RFC 3079.  Then, we derive asymmetric send/receive
537      * keys from the master session key.  The "master send key" is
538      *     MSBx(SHA(MASTERKEY|SHSPAD1|MAGIC3|SHSPAD2)),
539      * and the "master receive key" is
540      *     MSBx(SHA(MASTERKEY|SHSPAD1|MAGIC2|SHSPAD2)), where
541      * MASTERKEY is the "master session key" generated above, and the
542      * other values are constants from RFC 3079.  MSBx is the x-most
543      * significant bytes, where x is 5, 7, or 16 as appropriate for
544      * the desired key length.  We always generate 16 byte (128-bit)
545      * keys, the NAS is required to truncate as needed.
546      */
547
548     /* First, set some related attributes. */
549     vp = pairmake("MS-MPPE-Encryption-Policy",
550                   otp_mppe_policy[inst->mschapv2_mppe_policy], T_OP_EQ);
551     rad_assert(vp != NULL);
552     pairadd(vps, vp);
553     vp = pairmake("MS-MPPE-Encryption-Types",
554                   otp_mppe_types[inst->mschapv2_mppe_types], T_OP_EQ);
555     rad_assert(vp != NULL);
556     pairadd(vps, vp);
557
558     if (inst->mschapv2_mppe_policy) {
559       /* These constants and key vars are named from RFC 3079. */
560       /* "This is the MPPE Master Key" */
561       unsigned char Magic1[27] =
562         { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
563           0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
564           0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };
565       /* "On the client side, this is the send key; "
566          "on the server side, it is the receive key." */
567       unsigned char Magic2[84] =
568         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
569           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
570           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
571           0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
572           0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
573           0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
574           0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
575           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
576           0x6b, 0x65, 0x79, 0x2e };
577       /* "On the client side, this is the receive key; "
578          "on the server side, it is the send key." */
579       unsigned char Magic3[84] =
580         { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
581           0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
582           0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
583           0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
584           0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
585           0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
586           0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
587           0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
588           0x6b, 0x65, 0x79, 0x2e };
589       unsigned char SHSpad1[40] =
590         { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
594       unsigned char SHSpad2[40] =
595         { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
596           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
597           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
598           0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };
599       unsigned char MasterKey[16];
600       unsigned char MasterSendKey[16];
601       unsigned char MasterReceiveKey[16];
602
603       SHA_CTX ctx;
604       unsigned char sha_md[SHA_DIGEST_LENGTH];
605 #if 0 /* salting/encoding now handled in lib/radius.c:tunnel_pwencode() */
606       unsigned char md5_md[MD5_DIGEST_LENGTH];
607
608       /*   From RFC 2548:           S                 R           A */
609       unsigned char encode_buf[MAX_STRING_LEN + AUTH_VECTOR_LEN + 2];
610       int secretlen;
611
612       /* A useless value required by RFC 2548. */
613       unsigned char salt[2];
614       unsigned char mppe_key[32]; /* 1 + 16 + padding */
615       /*                           0x   (   ASCII(salt)  ) */
616       unsigned char mppe_key_string[2 + (2 * sizeof(salt)) +
617       /*                            (   ASCII(mppe_key)  )  \0 */
618                                     (2 * sizeof(mppe_key)) + 1];
619 #else /* 0 */
620       /*                           0x   (   ASCII(mppe_key)   )  \0 */
621       unsigned char mppe_key_string[2 + (2 * sizeof(MasterKey)) + 1];
622 #endif /* 0 */
623
624       /* Generate the master session key. */
625       SHA1_Init(&ctx);
626       SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
627       SHA1_Update(&ctx, resp_vp->strvalue + 26, 24);
628       SHA1_Update(&ctx, Magic1, sizeof(Magic1));
629       SHA1_Final(sha_md, &ctx);
630       (void) memcpy(MasterKey, sha_md, 16);
631
632       /* Generate the master send key. */
633       SHA1_Init(&ctx);
634       SHA1_Update(&ctx, MasterKey, 16);
635       SHA1_Update(&ctx, SHSpad1, 40);
636       SHA1_Update(&ctx, Magic3, sizeof(Magic3));
637       SHA1_Update(&ctx, SHSpad2, 40);
638       SHA1_Final(sha_md, &ctx);
639       (void) memcpy(MasterSendKey, sha_md, 16);
640
641       /* Generate the master receive key. */
642       SHA1_Init(&ctx);
643       SHA1_Update(&ctx, MasterKey, 16);
644       SHA1_Update(&ctx, SHSpad1, 40);
645       SHA1_Update(&ctx, Magic2, sizeof(Magic3));
646       SHA1_Update(&ctx, SHSpad2, 40);
647       SHA1_Final(sha_md, &ctx);
648       (void) memcpy(MasterReceiveKey, sha_md, 16);
649
650       /* Now, generate the MS-MPPE-Send-Key attribute. */
651
652 #if 0
653       /* Setup the salt value. */
654       salt[0] = 0x80;
655       salt[1] = 0x01;
656
657       /* Encode the key. */
658       (void) memset(mppe_key, 0, sizeof(mppe_key));
659       mppe_key[0] = 16; /* length */
660       (void) memcpy(&mppe_key[1], MasterSendKey, 16);
661       secretlen = strlen(request->secret);
662       (void) memcpy(encode_buf, request->secret, secretlen);
663       (void) memcpy(encode_buf + secretlen, request->packet->vector,
664                     AUTH_VECTOR_LEN);
665       (void) memcpy(encode_buf + secretlen + 16, salt, 2);
666       (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN + 2, md5_md);
667       for (i = 0; i < 16; ++i)
668         mppe_key[i] ^= md5_md[i];
669       (void) memcpy(encode_buf + secretlen, mppe_key, 16);
670       (void) MD5(encode_buf, secretlen + 16, md5_md);
671       for (i = 0; i < 16; ++i)
672         mppe_key[i + 16] ^= md5_md[i];
673
674       /* Whew.  Now stringify it for pairmake(). */
675       mppe_key_string[0] = '0';
676       mppe_key_string[1] = 'x';
677       (void) sprintf(&mppe_key_string[2], "%02X", salt[0]);
678       (void) sprintf(&mppe_key_string[4], "%02X", salt[1]);
679       for (i = 0; i < sizeof(mppe_key); ++i)
680         (void) sprintf(&mppe_key_string[i*2+6], "%02X", mppe_key[i]);
681 #else /* 0 */
682       mppe_key_string[0] = '0';
683       mppe_key_string[1] = 'x';
684       for (i = 0; i < sizeof(MasterSendKey); ++i)
685         (void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterSendKey[i]);
686 #endif /* 0 */
687       vp = pairmake("MS-MPPE-Send-Key", mppe_key_string, T_OP_EQ);
688       rad_assert(vp != NULL);
689       pairadd(vps, vp);
690
691       /* Generate the MS-MPPE-Recv-Key attribute. */
692
693 #if 0
694       /* Setup the salt value. */
695       salt[0] = 0x80;
696       salt[1] = 0x02;
697
698       /* Encode the key. */
699       (void) memset(mppe_key, 0, sizeof(mppe_key));
700       mppe_key[0] = 16; /* length */
701       (void) memcpy(&mppe_key[1], MasterReceiveKey, 16);
702       secretlen = strlen(request->secret);
703       (void) memcpy(encode_buf, request->secret, secretlen);
704       (void) memcpy(encode_buf + secretlen, request->packet->vector,
705                     AUTH_VECTOR_LEN);
706       (void) memcpy(encode_buf + secretlen + 16, salt, 2);
707       (void) MD5(encode_buf, secretlen + AUTH_VECTOR_LEN + 2, md5_md);
708       for (i = 0; i < 16; ++i)
709         mppe_key[i] ^= md5_md[i];
710       (void) memcpy(encode_buf + secretlen, mppe_key, 16);
711       (void) MD5(encode_buf, secretlen + 16, md5_md);
712       for (i = 0; i < 16; ++i)
713         mppe_key[i + 16] ^= md5_md[i];
714
715       /* Whew.  Now stringify it for pairmake(). */
716       mppe_key_string[0] = '0';
717       mppe_key_string[1] = 'x';
718       (void) sprintf(&mppe_key_string[2], "%02X", salt[0]);
719       (void) sprintf(&mppe_key_string[4], "%02X", salt[1]);
720       for (i = 0; i < sizeof(mppe_key); ++i)
721         (void) sprintf(&mppe_key_string[i*2+6], "%02X", mppe_key[i]);
722 #else /* 0 */
723       mppe_key_string[0] = '0';
724       mppe_key_string[1] = 'x';
725       for (i = 0; i < sizeof(MasterReceiveKey); ++i)
726         (void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterReceiveKey[i]);
727 #endif /* 0 */
728       vp = pairmake("MS-MPPE-Recv-Key", mppe_key_string, T_OP_EQ);
729       rad_assert(vp != NULL);
730       pairadd(vps, vp);
731
732     } /* if (doing mppe) */
733
734   } /* case PW_MS_CHAP2_RESPONSE */
735   break;
736
737   default:
738     DEBUG("%s: %s: unknown password type", log_prefix, __func__);
739     nmatch = -1;
740     break;
741
742   } /* switch(pwattr[attr]) */
743
744   return nmatch;
745 }
746
747
748 /*
749  * #$!#@ have to convert 7 octet ranges into 8 octet keys.
750  * Implementation cribbed (and slightly modified) from
751  * rlm_mschap.c by Jay Miller <jaymiller@socket.net>.
752  * We don't bother checking/setting parity.
753  */
754 static void
755 otp_key_from_hash(des_cblock *key, const unsigned char hashbytes[7])
756 {
757   int i;
758   unsigned char working;
759   unsigned char next = 0;
760
761   for (i = 0; i < 7; ++i) {
762     working = hashbytes[i];
763     (*key)[i] = (working >> i) | next;
764     next = (working << (7 - i));
765   }
766   (*key)[i] = next;
767 }