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