00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #define USE_CRYPT
00071
00072 #include "lwip/opt.h"
00073
00074 #if PPP_SUPPORT
00075
00076 #if MSCHAP_SUPPORT
00077
00078 #include "ppp.h"
00079 #include "pppdebug.h"
00080
00081 #include "md4.h"
00082 #ifndef USE_CRYPT
00083 #include "des.h"
00084 #endif
00085 #include "chap.h"
00086 #include "chpms.h"
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 typedef struct {
00098 u_char LANManResp[24];
00099 u_char NTResp[24];
00100 u_char UseNT;
00101 } MS_ChapResponse;
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 extern void setkey(const char *);
00113 extern void encrypt(char *, int);
00114
00115 static void DesEncrypt (u_char *, u_char *, u_char *);
00116 static void MakeKey (u_char *, u_char *);
00117
00118 #ifdef USE_CRYPT
00119 static void Expand (u_char *, u_char *);
00120 static void Collapse (u_char *, u_char *);
00121 #endif
00122
00123 static void ChallengeResponse(
00124 u_char *challenge,
00125 u_char *pwHash,
00126 u_char *response
00127 );
00128 static void ChapMS_NT(
00129 char *rchallenge,
00130 int rchallenge_len,
00131 char *secret,
00132 int secret_len,
00133 MS_ChapResponse *response
00134 );
00135 static u_char Get7Bits(
00136 u_char *input,
00137 int startBit
00138 );
00139
00140
00141
00142
00143
00144 void
00145 ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
00146 {
00147 MS_ChapResponse response;
00148 #ifdef MSLANMAN
00149 extern int ms_lanman;
00150 #endif
00151
00152 #if 0
00153 CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", secret_len, secret));
00154 #endif
00155 BZERO(&response, sizeof(response));
00156
00157
00158 ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
00159
00160 #ifdef MSLANMAN
00161 ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
00162
00163
00164 response.UseNT = !ms_lanman;
00165 #else
00166 response.UseNT = 1;
00167 #endif
00168
00169 BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
00170 cstate->resp_length = MS_CHAP_RESPONSE_LEN;
00171 }
00172
00173
00174
00175
00176
00177 static void
00178 ChallengeResponse( u_char *challenge,
00179 u_char *pwHash,
00180 u_char *response )
00181 {
00182 char ZPasswordHash[21];
00183
00184 BZERO(ZPasswordHash, sizeof(ZPasswordHash));
00185 BCOPY(pwHash, ZPasswordHash, 16);
00186
00187 #if 0
00188 log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
00189 #endif
00190
00191 DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
00192 DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
00193 DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
00194
00195 #if 0
00196 log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
00197 #endif
00198 }
00199
00200
00201 #ifdef USE_CRYPT
00202 static void
00203 DesEncrypt( u_char *clear,
00204 u_char *key,
00205 u_char *cipher )
00206 {
00207 u_char des_key[8];
00208 u_char crypt_key[66];
00209 u_char des_input[66];
00210
00211 MakeKey(key, des_key);
00212
00213 Expand(des_key, crypt_key);
00214 setkey(crypt_key);
00215
00216 #if 0
00217 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
00218 clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
00219 #endif
00220
00221 Expand(clear, des_input);
00222 encrypt(des_input, 0);
00223 Collapse(des_input, cipher);
00224
00225 #if 0
00226 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
00227 cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
00228 #endif
00229 }
00230
00231 #else
00232
00233 static void
00234 DesEncrypt( u_char *clear,
00235 u_char *key,
00236 u_char *cipher )
00237 {
00238 des_cblock des_key;
00239 des_key_schedule key_schedule;
00240
00241 MakeKey(key, des_key);
00242
00243 des_set_key(&des_key, key_schedule);
00244
00245 #if 0
00246 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
00247 clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
00248 #endif
00249
00250 des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
00251
00252 #if 0
00253 CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
00254 cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
00255 #endif
00256 }
00257
00258 #endif
00259
00260
00261 static u_char
00262 Get7Bits( u_char *input, int startBit)
00263 {
00264 register unsigned int word;
00265
00266 word = (unsigned)input[startBit / 8] << 8;
00267 word |= (unsigned)input[startBit / 8 + 1];
00268
00269 word >>= 15 - (startBit % 8 + 7);
00270
00271 return word & 0xFE;
00272 }
00273
00274 #ifdef USE_CRYPT
00275
00276
00277
00278
00279
00280 static void
00281 Expand(u_char *in, u_char *out)
00282 {
00283 int j, c;
00284 int i;
00285
00286 for(i = 0; i < 64; in++){
00287 c = *in;
00288 for(j = 7; j >= 0; j--) {
00289 *out++ = (c >> j) & 01;
00290 }
00291 i += 8;
00292 }
00293 }
00294
00295
00296
00297 static void
00298 Collapse(u_char *in, u_char *out)
00299 {
00300 int j;
00301 int i;
00302 unsigned int c;
00303
00304 for (i = 0; i < 64; i += 8, out++) {
00305 c = 0;
00306 for (j = 7; j >= 0; j--, in++) {
00307 c |= *in << j;
00308 }
00309 *out = c & 0xff;
00310 }
00311 }
00312 #endif
00313
00314 static void
00315 MakeKey( u_char *key,
00316 u_char *des_key )
00317 {
00318 des_key[0] = Get7Bits(key, 0);
00319 des_key[1] = Get7Bits(key, 7);
00320 des_key[2] = Get7Bits(key, 14);
00321 des_key[3] = Get7Bits(key, 21);
00322 des_key[4] = Get7Bits(key, 28);
00323 des_key[5] = Get7Bits(key, 35);
00324 des_key[6] = Get7Bits(key, 42);
00325 des_key[7] = Get7Bits(key, 49);
00326
00327 #ifndef USE_CRYPT
00328 des_set_odd_parity((des_cblock *)des_key);
00329 #endif
00330
00331 #if 0
00332 CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
00333 key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
00334 CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
00335 des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
00336 #endif
00337 }
00338
00339 static void
00340 ChapMS_NT( char *rchallenge,
00341 int rchallenge_len,
00342 char *secret,
00343 int secret_len,
00344 MS_ChapResponse *response)
00345 {
00346 int i;
00347 MDstruct md4Context;
00348 u_char unicodePassword[MAX_NT_PASSWORD * 2];
00349 static int low_byte_first = -1;
00350
00351
00352
00353 BZERO(unicodePassword, sizeof(unicodePassword));
00354 for (i = 0; i < secret_len; i++) {
00355 unicodePassword[i * 2] = (u_char)secret[i];
00356 }
00357 MDbegin(&md4Context);
00358 MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8);
00359
00360 if (low_byte_first == -1) {
00361 low_byte_first = (htons((unsigned short int)1) != 1);
00362 }
00363 if (low_byte_first == 0) {
00364 MDreverse((u_long *)&md4Context);
00365 }
00366
00367 MDupdate(&md4Context, NULL, 0);
00368
00369 ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp);
00370 }
00371
00372 #ifdef MSLANMAN
00373 static u_char *StdText = (u_char *)"KGS!@#$%";
00374
00375 static void
00376 ChapMS_LANMan( char *rchallenge,
00377 int rchallenge_len,
00378 char *secret,
00379 int secret_len,
00380 MS_ChapResponse *response)
00381 {
00382 int i;
00383 u_char UcasePassword[MAX_NT_PASSWORD];
00384 u_char PasswordHash[16];
00385
00386
00387 BZERO(UcasePassword, sizeof(UcasePassword));
00388 for (i = 0; i < secret_len; i++) {
00389 UcasePassword[i] = (u_char)toupper(secret[i]);
00390 }
00391 DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
00392 DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
00393 ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
00394 }
00395 #endif
00396
00397 #endif
00398
00399 #endif