OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [pppd/] [chap_ms.c] - Blame information for rev 214

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * chap_ms.c - Microsoft MS-CHAP compatible implementation.
3
 *
4
 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
5
 * http://www.strataware.com/
6
 *
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms are permitted
10
 * provided that the above copyright notice and this paragraph are
11
 * duplicated in all such forms and that any documentation,
12
 * advertising materials, and other materials related to such
13
 * distribution and use acknowledge that the software was developed
14
 * by Eric Rosenquist.  The name of the author may not be used to
15
 * endorse or promote products derived from this software without
16
 * specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21
 */
22
 
23
/*
24
 * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
25
 *
26
 *   Implemented LANManager type password response to MS-CHAP challenges.
27
 *   Now pppd provides both NT style and LANMan style blocks, and the
28
 *   prefered is set by option "ms-lanman". Default is to use NT.
29
 *   The hash text (StdText) was taken from Win95 RASAPI32.DLL.
30
 *
31
 *   You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
32
 */
33
 
34
#ifndef lint
35
/* static char rcsid[] = "$Id: chap_ms.c,v 1.2 2001-09-27 12:01:57 chris Exp $"; */
36
#endif
37
 
38
#ifdef CHAPMS
39
 
40
#include <stdio.h>
41
#include <string.h>
42
#include <ctype.h>
43
#include <sys/types.h>
44
#include <sys/time.h>
45
#include <syslog.h>
46
#include <unistd.h>
47
#ifdef HAVE_CRYPT_H
48
#include <crypt.h>
49
#endif
50
 
51
#include "pppd.h"
52
#include "chap.h"
53
#include "chap_ms.h"
54
#include "md4.h"
55
 
56
#ifndef USE_CRYPT
57
#include <des.h>
58
#endif
59
 
60
typedef struct {
61
    u_char LANManResp[24];
62
    u_char NTResp[24];
63
    u_char UseNT;               /* If 1, ignore the LANMan response field */
64
} MS_ChapResponse;
65
/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
66
   in case this struct gets padded. */
67
 
68
 
69
static void     ChallengeResponse __P((u_char *, u_char *, u_char *));
70
static void     DesEncrypt __P((u_char *, u_char *, u_char *));
71
static void     MakeKey __P((u_char *, u_char *));
72
static u_char   Get7Bits __P((u_char *, int));
73
static void     ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *));
74
#ifdef MSLANMAN
75
static void     ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *));
76
#endif
77
 
78
#ifdef USE_CRYPT
79
static void     Expand __P((u_char *, u_char *));
80
static void     Collapse __P((u_char *, u_char *));
81
#endif
82
 
83
static void
84
ChallengeResponse(challenge, pwHash, response)
85
    u_char *challenge;  /* IN   8 octets */
86
    u_char *pwHash;     /* IN  16 octets */
87
    u_char *response;   /* OUT 24 octets */
88
{
89
    char    ZPasswordHash[21];
90
 
91
    BZERO(ZPasswordHash, sizeof(ZPasswordHash));
92
    BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
93
 
94
#if 0
95
    log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
96
#endif
97
 
98
    DesEncrypt(challenge, ZPasswordHash +  0, response + 0);
99
    DesEncrypt(challenge, ZPasswordHash +  7, response + 8);
100
    DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
101
 
102
#if 0
103
    log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
104
#endif
105
}
106
 
107
 
108
#ifdef USE_CRYPT
109
static void
110
DesEncrypt(clear, key, cipher)
111
    u_char *clear;      /* IN  8 octets */
112
    u_char *key;        /* IN  7 octets */
113
    u_char *cipher;     /* OUT 8 octets */
114
{
115
    u_char des_key[8];
116
    u_char crypt_key[66];
117
    u_char des_input[66];
118
 
119
    MakeKey(key, des_key);
120
 
121
    Expand(des_key, crypt_key);
122
    setkey(crypt_key);
123
 
124
#if 0
125
    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X",
126
               clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
127
#endif
128
 
129
    Expand(clear, des_input);
130
    encrypt(des_input, 0);
131
    Collapse(des_input, cipher);
132
 
133
#if 0
134
    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X",
135
               cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
136
#endif
137
}
138
 
139
#else /* USE_CRYPT */
140
 
141
static void
142
DesEncrypt(clear, key, cipher)
143
    u_char *clear;      /* IN  8 octets */
144
    u_char *key;        /* IN  7 octets */
145
    u_char *cipher;     /* OUT 8 octets */
146
{
147
    des_cblock          des_key;
148
    des_key_schedule    key_schedule;
149
 
150
    MakeKey(key, des_key);
151
 
152
    des_set_key(&des_key, key_schedule);
153
 
154
#if 0
155
    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X",
156
               clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
157
#endif
158
 
159
    des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
160
 
161
#if 0
162
    CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X",
163
               cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
164
#endif
165
}
166
 
167
#endif /* USE_CRYPT */
168
 
169
 
170
static u_char Get7Bits(input, startBit)
171
    u_char *input;
172
    int startBit;
173
{
174
    register unsigned int       word;
175
 
176
    word  = (unsigned)input[startBit / 8] << 8;
177
    word |= (unsigned)input[startBit / 8 + 1];
178
 
179
    word >>= 15 - (startBit % 8 + 7);
180
 
181
    return word & 0xFE;
182
}
183
 
184
#ifdef USE_CRYPT
185
 
186
/* in == 8-byte string (expanded version of the 56-bit key)
187
 * out == 64-byte string where each byte is either 1 or 0
188
 * Note that the low-order "bit" is always ignored by by setkey()
189
 */
190
static void Expand(in, out)
191
    u_char *in;
192
    u_char *out;
193
{
194
        int j, c;
195
        int i;
196
 
197
        for(i = 0; i < 64; in++){
198
                c = *in;
199
                for(j = 7; j >= 0; j--)
200
                        *out++ = (c >> j) & 01;
201
                i += 8;
202
        }
203
}
204
 
205
/* The inverse of Expand
206
 */
207
static void Collapse(in, out)
208
    u_char *in;
209
    u_char *out;
210
{
211
        int j;
212
        int i;
213
        unsigned int c;
214
 
215
        for (i = 0; i < 64; i += 8, out++) {
216
            c = 0;
217
            for (j = 7; j >= 0; j--, in++)
218
                c |= *in << j;
219
            *out = c & 0xff;
220
        }
221
}
222
#endif
223
 
224
static void MakeKey(key, des_key)
225
    u_char *key;        /* IN  56 bit DES key missing parity bits */
226
    u_char *des_key;    /* OUT 64 bit DES key with parity bits added */
227
{
228
    des_key[0] = Get7Bits(key,  0);
229
    des_key[1] = Get7Bits(key,  7);
230
    des_key[2] = Get7Bits(key, 14);
231
    des_key[3] = Get7Bits(key, 21);
232
    des_key[4] = Get7Bits(key, 28);
233
    des_key[5] = Get7Bits(key, 35);
234
    des_key[6] = Get7Bits(key, 42);
235
    des_key[7] = Get7Bits(key, 49);
236
 
237
#ifndef USE_CRYPT
238
    des_set_odd_parity((des_cblock *)des_key);
239
#endif
240
 
241
#if 0
242
    CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X",
243
               key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
244
    CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X",
245
               des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
246
#endif
247
}
248
 
249
static void
250
ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
251
    char *rchallenge;
252
    int rchallenge_len;
253
    char *secret;
254
    int secret_len;
255
    MS_ChapResponse    *response;
256
{
257
    int                 i;
258
    MD4_CTX             md4Context;
259
    u_char              hash[MD4_SIGNATURE_SIZE];
260
    u_char              unicodePassword[MAX_NT_PASSWORD * 2];
261
 
262
    /* Initialize the Unicode version of the secret (== password). */
263
    /* This implicitly supports 8-bit ISO8859/1 characters. */
264
    BZERO(unicodePassword, sizeof(unicodePassword));
265
    for (i = 0; i < secret_len; i++)
266
        unicodePassword[i * 2] = (u_char)secret[i];
267
 
268
    MD4Init(&md4Context);
269
    MD4Update(&md4Context, unicodePassword, secret_len * 2 * 8);        /* Unicode is 2 bytes/char, *8 for bit count */
270
 
271
    MD4Final(hash, &md4Context);        /* Tell MD4 we're done */
272
 
273
    ChallengeResponse(rchallenge, hash, response->NTResp);
274
}
275
 
276
#ifdef MSLANMAN
277
static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
278
 
279
static void
280
ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
281
    char *rchallenge;
282
    int rchallenge_len;
283
    char *secret;
284
    int secret_len;
285
    MS_ChapResponse     *response;
286
{
287
    int                 i;
288
    u_char              UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
289
    u_char              PasswordHash[MD4_SIGNATURE_SIZE];
290
 
291
    /* LANMan password is case insensitive */
292
    BZERO(UcasePassword, sizeof(UcasePassword));
293
    for (i = 0; i < secret_len; i++)
294
       UcasePassword[i] = (u_char)toupper(secret[i]);
295
    DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
296
    DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
297
    ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
298
}
299
#endif
300
 
301
void
302
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
303
    chap_state *cstate;
304
    char *rchallenge;
305
    int rchallenge_len;
306
    char *secret;
307
    int secret_len;
308
{
309
    MS_ChapResponse     response;
310
#ifdef MSLANMAN
311
    extern int ms_lanman;
312
#endif
313
 
314
#if 0
315
    CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
316
#endif
317
    BZERO(&response, sizeof(response));
318
 
319
    /* Calculate both always */
320
    ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
321
 
322
#ifdef MSLANMAN
323
    ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
324
 
325
    /* prefered method is set by option  */
326
    response.UseNT = !ms_lanman;
327
#else
328
    response.UseNT = 1;
329
#endif
330
 
331
    BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
332
    cstate->resp_length = MS_CHAP_RESPONSE_LEN;
333
}
334
 
335
#endif /* CHAPMS */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.