ReactOS 0.4.15-dev-7924-g5949c20
chpms.c
Go to the documentation of this file.
1/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
2/*** The original PPPD code is written in a way to require either the UNIX DES
3 encryption functions encrypt(3) and setkey(3) or the DES library libdes.
4 Since both is not included in lwIP, MSCHAP currently does not work! */
5/*****************************************************************************
6* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
7*
8* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
9* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
10*
11* The authors hereby grant permission to use, copy, modify, distribute,
12* and license this software and its documentation for any purpose, provided
13* that existing copyright notices are retained in all copies and that this
14* notice and the following disclaimer are included verbatim in any
15* distributions. No written agreement, license, or royalty fee is required
16* for any of the authorized uses.
17*
18* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
19* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*
29******************************************************************************
30* REVISION HISTORY
31*
32* 03-01-01 Marc Boucher <marc@mbsi.ca>
33* Ported to lwIP.
34* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
35* Original based on BSD chap_ms.c.
36*****************************************************************************/
37/*
38 * chap_ms.c - Microsoft MS-CHAP compatible implementation.
39 *
40 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
41 * http://www.strataware.com/
42 *
43 * All rights reserved.
44 *
45 * Redistribution and use in source and binary forms are permitted
46 * provided that the above copyright notice and this paragraph are
47 * duplicated in all such forms and that any documentation,
48 * advertising materials, and other materials related to such
49 * distribution and use acknowledge that the software was developed
50 * by Eric Rosenquist. The name of the author may not be used to
51 * endorse or promote products derived from this software without
52 * specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
57 */
58
59/*
60 * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
61 *
62 * Implemented LANManager type password response to MS-CHAP challenges.
63 * Now pppd provides both NT style and LANMan style blocks, and the
64 * prefered is set by option "ms-lanman". Default is to use NT.
65 * The hash text (StdText) was taken from Win95 RASAPI32.DLL.
66 *
67 * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
68 */
69
70#define USE_CRYPT
71
72#include "lwip/opt.h"
73
74#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
75
76#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
77
78#include "ppp_impl.h"
79#include "pppdebug.h"
80
81#include "md4.h"
82#ifndef USE_CRYPT
83#include "des.h"
84#endif
85#include "chap.h"
86#include "chpms.h"
87
88#include <string.h>
89
90
91/*************************/
92/*** LOCAL DEFINITIONS ***/
93/*************************/
94
95
96/************************/
97/*** LOCAL DATA TYPES ***/
98/************************/
99typedef struct {
100 u_char LANManResp[24];
101 u_char NTResp[24];
102 u_char UseNT; /* If 1, ignore the LANMan response field */
103} MS_ChapResponse;
104/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
105 in case this struct gets padded. */
106
107
108
109/***********************************/
110/*** LOCAL FUNCTION DECLARATIONS ***/
111/***********************************/
112
113/* XXX Don't know what to do with these. */
114extern void setkey(const char *);
115extern void encrypt(char *, int);
116
117static void DesEncrypt (u_char *, u_char *, u_char *);
118static void MakeKey (u_char *, u_char *);
119
120#ifdef USE_CRYPT
121static void Expand (u_char *, u_char *);
122static void Collapse (u_char *, u_char *);
123#endif
124
125static void ChallengeResponse(
126 u_char *challenge, /* IN 8 octets */
127 u_char *pwHash, /* IN 16 octets */
128 u_char *response /* OUT 24 octets */
129);
130static void ChapMS_NT(
131 char *rchallenge,
132 int rchallenge_len,
133 char *secret,
134 int secret_len,
135 MS_ChapResponse *response
136);
137static u_char Get7Bits(
138 u_char *input,
139 int startBit
140);
141
142static void
143ChallengeResponse( u_char *challenge, /* IN 8 octets */
144 u_char *pwHash, /* IN 16 octets */
145 u_char *response /* OUT 24 octets */)
146{
147 u_char ZPasswordHash[21];
148
149 BZERO(ZPasswordHash, sizeof(ZPasswordHash));
150 BCOPY(pwHash, ZPasswordHash, 16);
151
152#if 0
153 log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
154#endif
155
156 DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
157 DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
158 DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
159
160#if 0
161 log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
162#endif
163}
164
165
166#ifdef USE_CRYPT
167static void
168DesEncrypt( u_char *clear, /* IN 8 octets */
169 u_char *key, /* IN 7 octets */
170 u_char *cipher /* OUT 8 octets */)
171{
172 u_char des_key[8];
173 u_char crypt_key[66];
174 u_char des_input[66];
175
176 MakeKey(key, des_key);
177
178 Expand(des_key, crypt_key);
179 setkey((char*)crypt_key);
180
181#if 0
182 CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
183 clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
184#endif
185
186 Expand(clear, des_input);
187 encrypt((char*)des_input, 0);
188 Collapse(des_input, cipher);
189
190#if 0
191 CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
192 cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
193#endif
194}
195
196#else /* USE_CRYPT */
197
198static void
199DesEncrypt( u_char *clear, /* IN 8 octets */
200 u_char *key, /* IN 7 octets */
201 u_char *cipher /* OUT 8 octets */)
202{
203 des_cblock des_key;
204 des_key_schedule key_schedule;
205
206 MakeKey(key, des_key);
207
208 des_set_key(&des_key, key_schedule);
209
210#if 0
211 CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
212 clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
213#endif
214
215 des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
216
217#if 0
218 CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
219 cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
220#endif
221}
222
223#endif /* USE_CRYPT */
224
225
226static u_char
227Get7Bits( u_char *input, int startBit)
228{
229 register unsigned int word;
230
231 word = (unsigned)input[startBit / 8] << 8;
232 word |= (unsigned)input[startBit / 8 + 1];
233
234 word >>= 15 - (startBit % 8 + 7);
235
236 return word & 0xFE;
237}
238
239#ifdef USE_CRYPT
240
241/* in == 8-byte string (expanded version of the 56-bit key)
242 * out == 64-byte string where each byte is either 1 or 0
243 * Note that the low-order "bit" is always ignored by by setkey()
244 */
245static void
246Expand(u_char *in, u_char *out)
247{
248 int j, c;
249 int i;
250
251 for(i = 0; i < 64; in++){
252 c = *in;
253 for(j = 7; j >= 0; j--) {
254 *out++ = (c >> j) & 01;
255 }
256 i += 8;
257 }
258}
259
260/* The inverse of Expand
261 */
262static void
263Collapse(u_char *in, u_char *out)
264{
265 int j;
266 int i;
267 unsigned int c;
268
269 for (i = 0; i < 64; i += 8, out++) {
270 c = 0;
271 for (j = 7; j >= 0; j--, in++) {
272 c |= *in << j;
273 }
274 *out = c & 0xff;
275 }
276}
277#endif
278
279static void
280MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */
281 u_char *des_key /* OUT 64 bit DES key with parity bits added */)
282{
283 des_key[0] = Get7Bits(key, 0);
284 des_key[1] = Get7Bits(key, 7);
285 des_key[2] = Get7Bits(key, 14);
286 des_key[3] = Get7Bits(key, 21);
287 des_key[4] = Get7Bits(key, 28);
288 des_key[5] = Get7Bits(key, 35);
289 des_key[6] = Get7Bits(key, 42);
290 des_key[7] = Get7Bits(key, 49);
291
292#ifndef USE_CRYPT
293 des_set_odd_parity((des_cblock *)des_key);
294#endif
295
296#if 0
297 CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
298 key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
299 CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
300 des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
301#endif
302}
303
304static void
305ChapMS_NT( char *rchallenge,
306 int rchallenge_len,
307 char *secret,
308 int secret_len,
309 MS_ChapResponse *response)
310{
311 int i;
312 MDstruct md4Context;
313 u_char unicodePassword[MAX_NT_PASSWORD * 2];
314 static int low_byte_first = -1;
315
316 LWIP_UNUSED_ARG(rchallenge_len);
317
318 /* Initialize the Unicode version of the secret (== password). */
319 /* This implicitly supports 8-bit ISO8859/1 characters. */
320 BZERO(unicodePassword, sizeof(unicodePassword));
321 for (i = 0; i < secret_len; i++) {
322 unicodePassword[i * 2] = (u_char)secret[i];
323 }
324 MDbegin(&md4Context);
325 MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
326
327 if (low_byte_first == -1) {
328 low_byte_first = (PP_HTONS((unsigned short int)1) != 1);
329 }
330 if (low_byte_first == 0) {
331 /* @todo: arg type - u_long* or u_int* ? */
332 MDreverse((unsigned int*)&md4Context); /* sfb 961105 */
333 }
334
335 MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
336
337 ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp);
338}
339
340#ifdef MSLANMAN
341static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
342
343static void
344ChapMS_LANMan( char *rchallenge,
345 int rchallenge_len,
346 char *secret,
347 int secret_len,
348 MS_ChapResponse *response)
349{
350 int i;
351 u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
352 u_char PasswordHash[16];
353
354 /* LANMan password is case insensitive */
355 BZERO(UcasePassword, sizeof(UcasePassword));
356 for (i = 0; i < secret_len; i++) {
357 UcasePassword[i] = (u_char)toupper(secret[i]);
358 }
359 DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
360 DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
361 ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
362}
363#endif
364
365void
366ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
367{
368 MS_ChapResponse response;
369#ifdef MSLANMAN
370 extern int ms_lanman;
371#endif
372
373#if 0
374 CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret));
375#endif
376 BZERO(&response, sizeof(response));
377
378 /* Calculate both always */
379 ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
380
381#ifdef MSLANMAN
382 ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
383
384 /* prefered method is set by option */
385 response.UseNT = !ms_lanman;
386#else
387 response.UseNT = 1;
388#endif
389
390 BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
391 cstate->resp_length = MS_CHAP_RESPONSE_LEN;
392}
393
394#endif /* MSCHAP_SUPPORT */
395
396#endif /* PPP_SUPPORT */
int toupper(int c)
Definition: utclib.c:881
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define MS_CHAP_RESPONSE_LEN
Definition: chap.h:81
void ChapMS(chap_state *, char *, int, char *, int)
#define MAX_NT_PASSWORD
Definition: chpms.h:60
#define PP_HTONS(x)
Definition: def.h:88
#define NULL
Definition: types.h:112
UCHAR u_char
Definition: types.h:80
void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const des_key *des)
Definition: des.c:1453
struct tag_des_key des_key
const GLubyte * c
Definition: glext.h:8905
GLuint in
Definition: glext.h:9616
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
const WCHAR * word
Definition: lex.c:36
#define c
Definition: ke_i.h:80
static DATA_BLOB cipher
Definition: protectdata.c:38
static DATA_BLOB CRYPTPROTECT_PROMPTSTRUCT DATA_BLOB *static LPWSTR DATA_BLOB CRYPTPROTECT_PROMPTSTRUCT DATA_BLOB *static char secret[]
Definition: protectdata.c:33
static unsigned(__cdecl *hash_bstr)(bstr_t s)
#define CHAPDEBUG(a, b)
Definition: pppdebug.h:68
static FILE * out
Definition: regtests2xml.c:44
Definition: vj.h:105
Definition: copy.c:22
#define LOG_DEBUG
Definition: syslog.h:52
#define LOG_INFO
Definition: syslog.h:51