ReactOS  0.4.15-dev-1207-g698a8e6
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 /************************/
99 typedef 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. */
114 extern void setkey(const char *);
115 extern void encrypt(char *, int);
116 
117 static void DesEncrypt (u_char *, u_char *, u_char *);
118 static void MakeKey (u_char *, u_char *);
119 
120 #ifdef USE_CRYPT
121 static void Expand (u_char *, u_char *);
122 static void Collapse (u_char *, u_char *);
123 #endif
124 
125 static void ChallengeResponse(
126  u_char *challenge, /* IN 8 octets */
127  u_char *pwHash, /* IN 16 octets */
128  u_char *response /* OUT 24 octets */
129 );
130 static void ChapMS_NT(
131  char *rchallenge,
132  int rchallenge_len,
133  char *secret,
134  int secret_len,
135  MS_ChapResponse *response
136 );
137 static u_char Get7Bits(
138  u_char *input,
139  int startBit
140 );
141 
142 static void
143 ChallengeResponse( 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
167 static void
168 DesEncrypt( 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 
198 static void
199 DesEncrypt( 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 
226 static u_char
227 Get7Bits( 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  */
245 static void
246 Expand(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  */
262 static void
263 Collapse(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 
279 static void
280 MakeKey( 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 
304 static void
305 ChapMS_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
341 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
342 
343 static void
344 ChapMS_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 
365 void
366 ChapMS( 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 */
Definition: vj.h:105
#define MS_CHAP_RESPONSE_LEN
Definition: chap.h:81
#define MAX_NT_PASSWORD
Definition: chpms.h:60
void ChapMS(chap_state *, char *, int, char *, int)
static DATA_BLOB cipher
Definition: protectdata.c:38
#define LOG_DEBUG
Definition: syslog.h:52
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
#define CHAPDEBUG(a, b)
Definition: pppdebug.h:68
smooth NULL
Definition: ftsmooth.c:416
#define PP_HTONS(x)
Definition: def.h:88
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
void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const des_key *des)
Definition: des.c:1453
int toupper(int c)
Definition: utclib.c:881
const GLubyte * c
Definition: glext.h:8905
static FILE * out
Definition: regtests2xml.c:44
static UCHAR * secret
Definition: bcrypt.c:29
GLenum GLenum GLenum input
Definition: glext.h:9031
GLuint in
Definition: glext.h:9616
struct tag_des_key des_key
const WCHAR * word
Definition: lex.c:36
#define c
Definition: ke_i.h:80
UCHAR u_char
Definition: types.h:80
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define LOG_INFO
Definition: syslog.h:51
static unsigned(__cdecl *hash_bstr)(bstr_t s)
Definition: path.c:41