All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
otp_mppe.c
Go to the documentation of this file.
1 /*
2  * $Id: 399689abf3b775f3d16f9fb82fa35d931cbd6497 $
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  * Copyright 2001,2002 Google, Inc.
19  * Copyright 2005,2006 TRI-D Systems, Inc.
20  */
21 
22 RCSID("$Id: 399689abf3b775f3d16f9fb82fa35d931cbd6497 $")
23 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
24 
25 /* avoid inclusion of these FR headers which conflict w/ OpenSSL */
26 #define _FR_MD4_H
27 #define _FR_SHA1_H
28 
29 #include <freeradius-devel/rad_assert.h>
30 
31 #include "extern.h"
32 #include "otp.h"
33 #include "otp_mppe.h"
34 
35 #include <openssl/des.h>
36 #include <openssl/md4.h>
37 #include <openssl/md5.h>
38 #include <openssl/sha.h>
39 
40 #include <string.h>
41 
42 /*
43  * Add MPPE attributes to a request, if required.
44  */
45 void otp_mppe(REQUEST *request, otp_pwe_t pwe, rlm_otp_t const *opt, char const *passcode)
46 {
47  VALUE_PAIR *cvp, *rvp;
48 
49  cvp = fr_pair_find_by_da(request->packet->vps, pwattr[pwe - 1], TAG_ANY);
50  rvp = fr_pair_find_by_da(request->packet->vps, pwattr[pwe], TAG_ANY);
51  if (!cvp || !rvp) {
52  return;
53  }
54 
55  switch (pwe) {
56  case PWE_NONE:
57  case PWE_PAP:
58  case PWE_CHAP:
59  return;
60 
61  case PWE_MSCHAP:
62  /* First, set some related attributes. */
63  pair_make_reply("MS-MPPE-Encryption-Policy", otp_mppe_policy[opt->mschap_mppe_policy], T_OP_EQ);
64  pair_make_reply("MS-MPPE-Encryption-Types", otp_mppe_types[opt->mschap_mppe_types], T_OP_EQ);
65 
66  /* If no MPPE, we're done. */
67  if (!opt->mschap_mppe_policy) {
68  return;
69  }
70 
71  /*
72  * Generate the MS-CHAP-MPPE-Keys attribute. This is not specified
73  * anywhere -- RFC 2548, par. 2.4.1 is the authority but it has
74  * typos and omissions that make this unimplementable. The
75  * code here is based on experimental results provided by
76  * Takahiro Wagatsuma <waga@sic.shibaura-it.ac.jp>.
77  * We only support 128-bit keys derived from the NT hash; 40-bit
78  * and 56-bit keys are derived from the LM hash, which besides
79  * being deprecated, has severe security problems.
80  */
81  {
82  size_t i, passcode_len;
83  uint8_t password_unicode[2 * OTP_MAX_PASSCODE_LEN];
84  uint8_t password_md[MD4_DIGEST_LENGTH];
85  uint8_t mppe_keys[32];
86 
87  /* 0x ASCII(mppe_keys) '\0' */
88  char mppe_keys_string[2 + (2 * sizeof(mppe_keys)) + 1];
89 
90  /* Zero the LM-Key sub-field (and padding). */
91  (void) memset(mppe_keys, 0, sizeof(mppe_keys));
92 
93  /*
94  * The NT-Key sub-field is MD4(MD4(unicode(password))).
95  * Start by hashing the unicode passcode.
96  * This is broken because unicode chars are machine-ordered,
97  * but the spec (RFC 2433) doesn't say how to prepare
98  * the password for md4 (other than by example values).
99  */
100  passcode_len = strlen(passcode);
101  for (i = 0; i < passcode_len; ++i) {
102  /* Set the high order 8 bits to 0 (little-endian) */
103  password_unicode[i * 2] = *passcode++;
104  password_unicode[i * 2 + 1] = 0;
105  }
106 
107  /* first md4 */
108  (void) MD4(password_unicode, 2 * passcode_len, password_md);
109  /* second md4 */
110  (void) MD4(password_md, MD4_DIGEST_LENGTH, &mppe_keys[8]);
111 
112  /* Whew. Now stringify it for fr_pair_make(). */
113  mppe_keys_string[0] = '0';
114  mppe_keys_string[1] = 'x';
115 
116  for (i = 0; i < 32; ++i) {
117  (void) sprintf(&mppe_keys_string[i*2+2], "%02X", mppe_keys[i]);
118  }
119 
120  pair_make_reply("MS-CHAP-MPPE-Keys", mppe_keys_string, T_OP_EQ);
121  } /* (doing mppe) */
122  break; /* PWE_MSCHAP */
123 
124  case PWE_MSCHAP2:
125  {
126  size_t i;
127  uint8_t password_md_md[MD4_DIGEST_LENGTH];
128 
129  /*
130  * MS-CHAPv2 requires mutual authentication; we must prove
131  * that we know the secret. This is a bit circuitous: set
132  * MD1 = SHA(MD4(MD4(unicode(password)))|NT_RESPONSE|MAGIC1),
133  * MD2 = MSB8(SHA(PEER_CHALLENGE|MS_CHAP_CHALLENGE|USERNAME)),
134  * and finally use SHA(MD1|MD2|MAGIC2) as the authenticator.
135  * The authenticator is returned as the string "S=<auth>",
136  * <auth> is the authenticator expressed as [uppercase] ASCII.
137  * See RFC 2759.
138  */
139  {
140  size_t passcode_len;
141  uint8_t password_unicode[2 * OTP_MAX_PASSCODE_LEN];
142  uint8_t password_md[MD4_DIGEST_LENGTH];
143 
144  SHA_CTX ctx;
145  uint8_t md1[SHA_DIGEST_LENGTH];
146  uint8_t md2[SHA_DIGEST_LENGTH];
147  uint8_t auth_md[SHA_DIGEST_LENGTH];
148  /* S=(ASCII(auth_md))\0 */
149  char auth_md_string[2 + (2 * sizeof(auth_md)) + 1];
150  /*
151  * ugh. The ASCII authenticator (auth_md_string) is sent
152  * along with a single (useless) binary byte (the ID).
153  * So we must "stringify" it again (for fr_pair_make()) since the
154  * binary byte requires the attribute to be of type "octets".
155  */
156  /* 0x(ID)(ASCII("S="ASCII(auth_md))) */
157  char auth_octet_string[2 + 2 + (2 * sizeof(auth_md_string))];
158 
159  char const *username = request->username->vp_strvalue;
160  int username_len = request->username->vp_length;
161 
162  /* "Magic server to client signing constant" */
163  uint8_t magic1[39] = {
164  0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
165  0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
166  0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
167  0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
168  };
169  /* "Pad to make it do more than one iteration" */
170  uint8_t magic2[41] = {
171  0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
172  0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
173  0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
174  0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
175  0x6E
176  };
177 
178  /*
179  * Start by hashing the unicode passcode.
180  * This is broken because unicode chars are machine-ordered,
181  * but the spec (RFC 2759) doesn't say how to prepare
182  * the password for md4 (other than by example values).
183  */
184  passcode_len = strlen(passcode);
185  for (i = 0; i < passcode_len; ++i) {
186  /* Set the high order 8 bits to 0 (little-endian) */
187  password_unicode[i * 2] = *passcode++;
188  password_unicode[i * 2 + 1] = 0;
189  }
190  /* first md4 */
191  (void) MD4(password_unicode, 2 * passcode_len, password_md);
192  /* second md4 */
193  (void) MD4(password_md, MD4_DIGEST_LENGTH, password_md_md);
194 
195  /* MD1 */
196  SHA1_Init(&ctx);
197  SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
198  SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);
199  SHA1_Update(&ctx, magic1, sizeof(magic1));
200  SHA1_Final(md1, &ctx);
201 
202  /* MD2 */
203  SHA1_Init(&ctx);
204  SHA1_Update(&ctx, rvp->vp_strvalue + 2, 16);
205  SHA1_Update(&ctx, cvp->vp_strvalue, 16);
206  SHA1_Update(&ctx, username, username_len);
207  SHA1_Final(md2, &ctx);
208 
209  /* The Authenticator */
210  SHA1_Init(&ctx);
211  SHA1_Update(&ctx, md1, SHA_DIGEST_LENGTH);
212  SHA1_Update(&ctx, md2, 8);
213  SHA1_Update(&ctx, magic2, sizeof(magic2));
214  SHA1_Final(auth_md, &ctx);
215 
216  /* String conversion. */
217  auth_md_string[0] = 'S';
218  auth_md_string[1] = '=';
219  for (i = 0; i < sizeof(auth_md); ++i) {
220  (void) sprintf(&auth_md_string[i * 2 + 2], "%02X", auth_md[i]);
221  }
222 
223  /* And then octet conversion. Ugh! */
224  auth_octet_string[0] = '0';
225  auth_octet_string[1] = 'x';
226  (void) sprintf(&auth_octet_string[2], "%02X", rvp->vp_strvalue[0]);
227  for (i = 0; i < sizeof(auth_md_string) - 1; ++i) {
228  (void) sprintf(&auth_octet_string[i * 2 +4], "%02X", auth_md_string[i]);
229  }
230 
231  pair_make_reply("MS-CHAP2-Success", auth_octet_string, T_OP_EQ);
232  } /* Generate mutual auth info. */
233 
234  /*
235  * Now, set some MPPE related attributes.
236  */
237  pair_make_reply("MS-MPPE-Encryption-Policy", otp_mppe_policy[opt->mschapv2_mppe_policy], T_OP_EQ);
238  pair_make_reply("MS-MPPE-Encryption-Types", otp_mppe_types[opt->mschapv2_mppe_types], T_OP_EQ);
239 
240  /* If no MPPE, we're done. */
241  if (!opt->mschapv2_mppe_policy) {
242  return;
243  }
244 
245  /*
246  * Generate the MPPE initial session key, per RFC 3079.
247  * (Although, RFC 2548 leaves us guessing at how to generate this.)
248  * For MS-CHAPv2 we support all key lengths (40-, 56- and 128-bit),
249  * although MPPE via RADIUS supports only 40- and 128-bit keys.
250  * This is a bit more complicated than MS-CHAP. Start by generating
251  * a "master session key"
252  * MSB16(SHA(NTPasswordHashHash|NT_RESPONSE|MAGIC1)), where
253  * NTPasswordHashHash is MD4(MD4(unicode(password))), NT_RESPONSE
254  * is from the MS-CHAP2-Response attribute, and MAGIC1 is a
255  * constant from RFC 3079. Then, we derive asymmetric send/receive
256  * keys from the master session key. The "master send key" is
257  * MSBx(SHA(MASTERKEY|SHSPAD1|MAGIC3|SHSPAD2)),
258  * and the "master receive key" is
259  * MSBx(SHA(MASTERKEY|SHSPAD1|MAGIC2|SHSPAD2)), where
260  * MASTERKEY is the "master session key" generated above, and the
261  * other values are constants from RFC 3079. MSBx is the x-most
262  * significant bytes, where x is 5, 7, or 16 as appropriate for
263  * the desired key length. We always generate 16 byte (128-bit)
264  * keys, the NAS is required to truncate as needed.
265  */
266  {
267  /* These constants and key vars are named from RFC 3079. */
268  /* "This is the MPPE Master Key" */
269  uint8_t Magic1[27] = {
270  0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
271  0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
272  0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
273  };
274  /* "On the client side, this is the send key; on the server side, it is the receive key." */
275  uint8_t Magic2[84] = {
276  0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
277  0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
278  0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
279  0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
280  0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
281  0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
282  0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
283  0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
284  0x6b, 0x65, 0x79, 0x2e
285  };
286  /* "On the client side, this is the receive key; on the server side, it is the send key." */
287  uint8_t Magic3[84] = {
288  0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
289  0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
290  0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
291  0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
292  0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
293  0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
294  0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
295  0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
296  0x6b, 0x65, 0x79, 0x2e
297  };
298  uint8_t SHSpad1[40] = {
299  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
303  };
304 
305  uint8_t SHSpad2[40] = {
306  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
307  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
308  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
309  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
310  };
311  uint8_t MasterKey[16];
312  uint8_t MasterSendKey[16];
313  uint8_t MasterReceiveKey[16];
314 
315  SHA_CTX ctx;
316  uint8_t sha_md[SHA_DIGEST_LENGTH];
317 
318  /* 0x(ASCII(mppe_key))\0 */
319  char mppe_key_string[2 + (2 * sizeof(MasterKey)) + 1];
320 
321  /* Generate the master session key. */
322  SHA1_Init(&ctx);
323  SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
324  SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);
325  SHA1_Update(&ctx, Magic1, sizeof(Magic1));
326  SHA1_Final(sha_md, &ctx);
327  (void) memcpy(MasterKey, sha_md, 16);
328 
329  /* Generate the master send key. */
330  SHA1_Init(&ctx);
331  SHA1_Update(&ctx, MasterKey, 16);
332  SHA1_Update(&ctx, SHSpad1, 40);
333  SHA1_Update(&ctx, Magic3, sizeof(Magic3));
334  SHA1_Update(&ctx, SHSpad2, 40);
335  SHA1_Final(sha_md, &ctx);
336  (void) memcpy(MasterSendKey, sha_md, 16);
337 
338  /* Generate the master receive key. */
339  SHA1_Init(&ctx);
340  SHA1_Update(&ctx, MasterKey, 16);
341  SHA1_Update(&ctx, SHSpad1, 40);
342  SHA1_Update(&ctx, Magic2, sizeof(Magic3));
343  SHA1_Update(&ctx, SHSpad2, 40);
344  SHA1_Final(sha_md, &ctx);
345  (void) memcpy(MasterReceiveKey, sha_md, 16);
346 
347  /*
348  * Now, generate the MS-MPPE-Send-Key attribute.
349  */
350  mppe_key_string[0] = '0';
351  mppe_key_string[1] = 'x';
352  for (i = 0; i < sizeof(MasterSendKey); ++i) {
353  (void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterSendKey[i]);
354  }
355 
356  pair_make_reply("MS-MPPE-Send-Key", mppe_key_string, T_OP_EQ);
357 
358  /*
359  * Generate the MS-MPPE-Recv-Key attribute.
360  */
361  mppe_key_string[0] = '0';
362  mppe_key_string[1] = 'x';
363  for (i = 0; i < sizeof(MasterReceiveKey); ++i) {
364  (void) sprintf(&mppe_key_string[i*2+2], "%02X", MasterReceiveKey[i]);
365  }
366  pair_make_reply("MS-MPPE-Recv-Key", mppe_key_string, T_OP_EQ);
367  } /* (doing mppe) */
368 
369  break; /* PWE_MSCHAP2 */
370  } /* PWE_MSCHAP2 */
371 
372  } /* switch (pwe) */
373 
374  return;
375 }
Definition: otp.h:58
const fr_dict_attr_t * pwattr[8]
Definition: otp_pwe.c:48
uint32_t mschapv2_mppe_types
Key type/length for mschapv2/mppe.
Definition: extern.h:57
uint32_t mschap_mppe_policy
Whether or not do to mppe for mschap .
Definition: extern.h:58
enum otp_pwe otp_pwe_t
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
Definition: radiusd.h:222
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
Definition: otp.h:59
Definition: otp.h:60
Definition: token.h:46
static char const * otp_mppe_policy[3]
Definition: otp_mppe.h:38
void void MD4_DIGEST_LENGTH
Definition: md4.h:68
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
VALUE_PAIR * fr_pair_find_by_da(VALUE_PAIR *head, fr_dict_attr_t const *da, int8_t tag)
Find the pair with the matching DAs.
Definition: pair.c:624
uint32_t mschapv2_mppe_policy
Whether or not do to mppe for mschapv2.
Definition: extern.h:55
#define TAG_ANY
Definition: pair.h:191
static const uint8_t magic2[84]
Definition: rlm_mschap.c:1258
#define pair_make_reply(_a, _b, _c)
Definition: radiusd.h:546
#define OTP_MAX_PASSCODE_LEN
Definition: otp.h:52
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
Definition: otp.h:57
static char const * otp_mppe_types[3]
Definition: otp_mppe.h:43
static const uint8_t SHSpad1[40]
Definition: rlm_mschap.c:1241
static const uint8_t SHSpad2[40]
Definition: rlm_mschap.c:1247
#define RCSID(id)
Definition: build.h:135
static const uint8_t magic1[27]
Definition: rlm_mschap.c:1253
void otp_mppe(REQUEST *request, otp_pwe_t pwe, rlm_otp_t const *opt, char const *passcode)
Definition: otp_mppe.c:45
uint32_t mschap_mppe_types
key type/length for mschap/mppe.
Definition: extern.h:60
#define USES_APPLE_DEPRECATED_API
Definition: build.h:122