The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
mschap.c
Go to the documentation of this file.
1/*
2 * mschap.c
3 *
4 * Version: $Id: abe8c94beb4714bf64b7031a5a72c959c2ab3e5a $
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
31RCSID("$Id: abe8c94beb4714bf64b7031a5a72c959c2ab3e5a $")
32
33#include <freeradius-devel/server/base.h>
34#include <freeradius-devel/server/module_rlm.h>
35#include <freeradius-devel/util/debug.h>
36#include <freeradius-devel/util/md5.h>
37#include <freeradius-devel/util/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 */
52int mschap_nt_password_hash(uint8_t out[static NT_DIGEST_LENGTH], 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 */
73 uint8_t const peer_challenge[static MSCHAP_PEER_CHALLENGE_LENGTH],
74 uint8_t const auth_challenge[static MSCHAP_PEER_AUTHENTICATOR_CHALLENGE_LENGTH],
75 char const *user_name, size_t user_name_len)
76{
77 fr_sha1_ctx Context;
79
80 FR_PROTO_TRACE("RFC2759 ChallengeHash");
81 FR_PROTO_HEX_DUMP(peer_challenge, MSCHAP_PEER_CHALLENGE_LENGTH, "PeerChallenge");
82 FR_PROTO_HEX_DUMP(auth_challenge, MSCHAP_PEER_AUTHENTICATOR_CHALLENGE_LENGTH, "AuthenticatorChallenge");
83 FR_PROTO_HEX_DUMP((uint8_t const *)user_name, user_name_len, "UserName");
84
85 fr_sha1_init(&Context);
86 fr_sha1_update(&Context, peer_challenge, MSCHAP_PEER_CHALLENGE_LENGTH);
88 fr_sha1_update(&Context, (uint8_t const *) user_name, user_name_len);
89 fr_sha1_final(hash, &Context);
90
91 memcpy(challenge, hash, MSCHAP_CHALLENGE_LENGTH); //-V512
92
93 FR_PROTO_HEX_DUMP(challenge, MSCHAP_CHALLENGE_LENGTH, "Challenge");
94}
95
96/*
97 * auth_response() generates MS-CHAP v2 SUCCESS response
98 * according to RFC 2759 GenerateAuthenticatorResponse()
99 * returns 42-octet response string
100 */
101void mschap_auth_response(char const *username, size_t username_len,
102 uint8_t const *nt_hash_hash,
103 uint8_t const *ntresponse,
104 uint8_t const *peer_challenge, uint8_t const *auth_challenge,
105 char *response)
106{
107 fr_sha1_ctx Context;
108 static const uint8_t magic1[39] =
109 {0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
110 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
111 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
112 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
113
114 static const uint8_t magic2[41] =
115 {0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
116 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
117 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
118 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
119 0x6E};
120
121 static char const hex[] = "0123456789ABCDEF";
122
123 size_t i;
124 uint8_t challenge[8];
125 uint8_t digest[20];
126
127 fr_sha1_init(&Context);
128 fr_sha1_update(&Context, nt_hash_hash, 16);
129 fr_sha1_update(&Context, ntresponse, 24);
130 fr_sha1_update(&Context, magic1, 39);
131 fr_sha1_final(digest, &Context);
132 mschap_challenge_hash(challenge, peer_challenge, auth_challenge, username, username_len);
133 fr_sha1_init(&Context);
134 fr_sha1_update(&Context, digest, 20);
135 fr_sha1_update(&Context, challenge, 8);
136 fr_sha1_update(&Context, magic2, 41);
137 fr_sha1_final(digest, &Context);
138
139 /*
140 * Encode the value of 'Digest' as "S=" followed by
141 * 40 ASCII hexadecimal digits and return it in
142 * AuthenticatorResponse.
143 * For example,
144 * "S=0123456789ABCDEF0123456789ABCDEF01234567"
145 */
146 response[0] = 'S';
147 response[1] = '=';
148
149 /*
150 * The hexadecimal digits [A-F] MUST be uppercase.
151 */
152 for (i = 0; i < sizeof(digest); i++) {
153 response[2 + (i * 2)] = hex[(digest[i] >> 4) & 0x0f];
154 response[3 + (i * 2)] = hex[digest[i] & 0x0f];
155 }
156}
157
158/*
159 * add_reply() adds either MS-CHAP2-Success or MS-CHAP-Error
160 * attribute to reply packet
161 */
162void mschap_add_reply(request_t *request, uint8_t ident,
163 fr_dict_attr_t const *da, char const *value, size_t len)
164{
165 fr_pair_t *vp;
166
167 MEM(pair_update_reply(&vp, da) >= 0);
168 if (vp->vp_type == FR_TYPE_STRING) {
169 char *p;
170
171 MEM(fr_pair_value_bstr_alloc(vp, &p, len + 1, vp->vp_tainted) == 0); /* Account for the ident byte */
172 p[0] = ident;
173 memcpy(p + 1, value, len);
174 } else {
175 uint8_t *p;
176
177 MEM(fr_pair_value_mem_alloc(vp, &p, len + 1, vp->vp_tainted) == 0); /* Account for the ident byte */
178 p[0] = ident;
179 memcpy(p + 1, value, len);
180 }
181}
182
#define RCSID(id)
Definition build.h:483
#define MEM(x)
Definition debug.h:36
Test enumeration values.
Definition dict_test.h:92
void fr_md4_calc(uint8_t out[static MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
Calculate the MD4 hash of the contents of a buffer.
Definition md4.c:482
@ FR_TYPE_STRING
String of printable characters.
long int ssize_t
unsigned char uint8_t
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:315
int mschap_nt_password_hash(uint8_t out[static NT_DIGEST_LENGTH], char const *password)
Converts Unicode password to 16-byte NT hash with MD4.
Definition mschap.c:52
void mschap_add_reply(request_t *request, uint8_t ident, fr_dict_attr_t const *da, char const *value, size_t len)
Definition mschap.c:162
void mschap_auth_response(char const *username, size_t username_len, 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:101
void mschap_challenge_hash(uint8_t challenge[static MSCHAP_CHALLENGE_LENGTH], uint8_t const peer_challenge[static MSCHAP_PEER_CHALLENGE_LENGTH], uint8_t const auth_challenge[static MSCHAP_PEER_AUTHENTICATOR_CHALLENGE_LENGTH], char const *user_name, size_t user_name_len)
Definition mschap.c:72
#define MSCHAP_CHALLENGE_LENGTH
Definition mschap.h:9
#define MSCHAP_PEER_CHALLENGE_LENGTH
Definition mschap.h:10
#define MSCHAP_PEER_AUTHENTICATOR_CHALLENGE_LENGTH
Definition mschap.h:11
#define NT_DIGEST_LENGTH
Definition mschap.h:7
int fr_pair_value_bstr_alloc(fr_pair_t *vp, char **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "string" type value pair.
Definition pair.c:2730
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
Definition pair.c:2930
static const uint8_t magic1[27]
static const uint8_t magic2[84]
static unsigned int hash(char const *username, unsigned int tablesize)
Definition rlm_passwd.c:132
username
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition pair.h:129
void fr_sha1_init(fr_sha1_ctx *context)
Definition sha1.c:93
void fr_sha1_final(uint8_t digest[static SHA1_DIGEST_LENGTH], fr_sha1_ctx *context)
Definition sha1.c:141
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *in, size_t len)
Definition sha1.c:105
#define SHA1_DIGEST_LENGTH
Definition sha1.h:29
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
Definition proto.h:41
#define FR_PROTO_TRACE(_fmt,...)
Definition proto.h:40
static size_t char ** out
Definition value.h:997