All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mschap.c
Go to the documentation of this file.
1 /*
2  * mschap.c
3  *
4  * Version: $Id: 48737b18c9e3e55881eeb21708daeaddb800498a $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2001,2006,2010 The FreeRADIUS server project
21  */
22 
23 
24 /*
25  * This implements MS-CHAP, as described in RFC 2548
26  *
27  * http://www.freeradius.org/rfc/rfc2548.txt
28  *
29  */
30 
31 RCSID("$Id: 48737b18c9e3e55881eeb21708daeaddb800498a $")
32 
33 #include <freeradius-devel/radiusd.h>
34 #include <freeradius-devel/modules.h>
35 #include <freeradius-devel/rad_assert.h>
36 #include <freeradius-devel/md5.h>
37 #include <freeradius-devel/sha1.h>
38 
39 #include <ctype.h>
40 
41 #include "smbdes.h"
42 #include "mschap.h"
43 
44 /** Converts Unicode password to 16-byte NT hash with MD4
45  *
46  * @param[out] out Pointer to 16 byte output buffer.
47  * @param[in] password to encode.
48  * @return
49  * - 0 on success.
50  * - -1 on failure.
51  */
52 int mschap_ntpwdhash(uint8_t *out, char const *password)
53 {
54  ssize_t len;
55  uint8_t ucs2_password[512];
56 
57  len = fr_utf8_to_ucs2(ucs2_password, sizeof(ucs2_password), password, strlen(password));
58  if (len < 0) {
59  *out = '\0';
60  return -1;
61  }
62  fr_md4_calc(out, (uint8_t *) ucs2_password, len);
63 
64  return 0;
65 }
66 
67 /*
68  * challenge_hash() is used by mschap2() and auth_response()
69  * implements RFC2759 ChallengeHash()
70  * generates 64 bit challenge
71  */
72 void mschap_challenge_hash(uint8_t const *peer_challenge,
73  uint8_t const *auth_challenge,
74  char const *user_name, uint8_t *challenge )
75 {
76  fr_sha1_ctx Context;
77  uint8_t hash[20];
78 
79  fr_sha1_init(&Context);
80  fr_sha1_update(&Context, peer_challenge, 16);
81  fr_sha1_update(&Context, auth_challenge, 16);
82  fr_sha1_update(&Context, (uint8_t const *) user_name,
83  strlen(user_name));
84  fr_sha1_final(hash, &Context);
85  memcpy(challenge, hash, 8);
86 }
87 
88 /*
89  * auth_response() generates MS-CHAP v2 SUCCESS response
90  * according to RFC 2759 GenerateAuthenticatorResponse()
91  * returns 42-octet response string
92  */
93 void mschap_auth_response(char const *username,
94  uint8_t const *nt_hash_hash,
95  uint8_t const *ntresponse,
96  uint8_t const *peer_challenge, uint8_t const *auth_challenge,
97  char *response)
98 {
99  fr_sha1_ctx Context;
100  static const uint8_t magic1[39] =
101  {0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
102  0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
103  0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
104  0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
105 
106  static const uint8_t magic2[41] =
107  {0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
108  0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
109  0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
110  0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
111  0x6E};
112 
113  static char const hex[] = "0123456789ABCDEF";
114 
115  size_t i;
116  uint8_t challenge[8];
117  uint8_t digest[20];
118 
119  fr_sha1_init(&Context);
120  fr_sha1_update(&Context, nt_hash_hash, 16);
121  fr_sha1_update(&Context, ntresponse, 24);
122  fr_sha1_update(&Context, magic1, 39);
123  fr_sha1_final(digest, &Context);
124  mschap_challenge_hash(peer_challenge, auth_challenge, username, challenge);
125  fr_sha1_init(&Context);
126  fr_sha1_update(&Context, digest, 20);
127  fr_sha1_update(&Context, challenge, 8);
128  fr_sha1_update(&Context, magic2, 41);
129  fr_sha1_final(digest, &Context);
130 
131  /*
132  * Encode the value of 'Digest' as "S=" followed by
133  * 40 ASCII hexadecimal digits and return it in
134  * AuthenticatorResponse.
135  * For example,
136  * "S=0123456789ABCDEF0123456789ABCDEF01234567"
137  */
138  response[0] = 'S';
139  response[1] = '=';
140 
141  /*
142  * The hexadecimal digits [A-F] MUST be uppercase.
143  */
144  for (i = 0; i < sizeof(digest); i++) {
145  response[2 + (i * 2)] = hex[(digest[i] >> 4) & 0x0f];
146  response[3 + (i * 2)] = hex[digest[i] & 0x0f];
147  }
148 }
149 
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *data, size_t len)
Definition: sha1.c:106
void fr_md4_calc(uint8_t out[MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD4 hash of the contents of a buffer.
Definition: md4.c:24
void mschap_challenge_hash(uint8_t const *peer_challenge, uint8_t const *auth_challenge, char const *user_name, uint8_t *challenge)
Definition: mschap.c:72
void fr_sha1_init(fr_sha1_ctx *context)
Definition: sha1.c:94
static unsigned int hash(char const *username, unsigned int tablesize)
Definition: rlm_passwd.c:124
void mschap_auth_response(char const *username, uint8_t const *nt_hash_hash, uint8_t const *ntresponse, uint8_t const *peer_challenge, uint8_t const *auth_challenge, char *response)
Definition: mschap.c:93
int mschap_ntpwdhash(uint8_t *out, char const *password)
Converts Unicode password to 16-byte NT hash with MD4.
Definition: mschap.c:52
void fr_sha1_final(uint8_t digest[20], fr_sha1_ctx *context)
Definition: sha1.c:132
ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
Convert UTF8 string to UCS2 encoding.
Definition: misc.c:580
static const uint8_t magic2[84]
Definition: rlm_mschap.c:1258
static char const hex[]
Definition: smbencrypt.c:34
#define RCSID(id)
Definition: build.h:135
static const uint8_t magic1[27]
Definition: rlm_mschap.c:1253