NetServices Stack source
Dependents: HelloWorld ServoInterfaceBoardExample1 4180_Lab4
chpms.c
00001 /*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/ 00002 /*** The original PPPD code is written in a way to require either the UNIX DES 00003 encryption functions encrypt(3) and setkey(3) or the DES library libdes. 00004 Since both is not included in lwIP, MSCHAP currently does not work! */ 00005 /***************************************************************************** 00006 * chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file. 00007 * 00008 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00009 * Copyright (c) 1997 by Global Election Systems Inc. All rights reserved. 00010 * 00011 * The authors hereby grant permission to use, copy, modify, distribute, 00012 * and license this software and its documentation for any purpose, provided 00013 * that existing copyright notices are retained in all copies and that this 00014 * notice and the following disclaimer are included verbatim in any 00015 * distributions. No written agreement, license, or royalty fee is required 00016 * for any of the authorized uses. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00019 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00020 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00021 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00023 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00024 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00025 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00026 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00027 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00028 * 00029 ****************************************************************************** 00030 * REVISION HISTORY 00031 * 00032 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00033 * Ported to lwIP. 00034 * 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00035 * Original based on BSD chap_ms.c. 00036 *****************************************************************************/ 00037 /* 00038 * chap_ms.c - Microsoft MS-CHAP compatible implementation. 00039 * 00040 * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited. 00041 * http://www.strataware.com/ 00042 * 00043 * All rights reserved. 00044 * 00045 * Redistribution and use in source and binary forms are permitted 00046 * provided that the above copyright notice and this paragraph are 00047 * duplicated in all such forms and that any documentation, 00048 * advertising materials, and other materials related to such 00049 * distribution and use acknowledge that the software was developed 00050 * by Eric Rosenquist. The name of the author may not be used to 00051 * endorse or promote products derived from this software without 00052 * specific prior written permission. 00053 * 00054 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00055 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00056 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00057 */ 00058 00059 /* 00060 * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997 00061 * 00062 * Implemented LANManager type password response to MS-CHAP challenges. 00063 * Now pppd provides both NT style and LANMan style blocks, and the 00064 * prefered is set by option "ms-lanman". Default is to use NT. 00065 * The hash text (StdText) was taken from Win95 RASAPI32.DLL. 00066 * 00067 * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80 00068 */ 00069 00070 #define USE_CRYPT 00071 00072 #include "lwip/opt.h" 00073 00074 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00075 00076 #if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 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 #include <string.h> 00089 00090 00091 /*************************/ 00092 /*** LOCAL DEFINITIONS ***/ 00093 /*************************/ 00094 00095 00096 /************************/ 00097 /*** LOCAL DATA TYPES ***/ 00098 /************************/ 00099 typedef struct { 00100 u_char LANManResp[24]; 00101 u_char NTResp[24]; 00102 u_char UseNT; /* If 1, ignore the LANMan response field */ 00103 } MS_ChapResponse; 00104 /* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse), 00105 in case this struct gets padded. */ 00106 00107 00108 00109 /***********************************/ 00110 /*** LOCAL FUNCTION DECLARATIONS ***/ 00111 /***********************************/ 00112 00113 /* XXX Don't know what to do with these. */ 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, /* IN 8 octets */ 00127 u_char *pwHash, /* IN 16 octets */ 00128 u_char *response /* OUT 24 octets */ 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, /* IN 8 octets */ 00144 u_char *pwHash, /* IN 16 octets */ 00145 u_char *response /* OUT 24 octets */) 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, /* IN 8 octets */ 00169 u_char *key, /* IN 7 octets */ 00170 u_char *cipher /* OUT 8 octets */) 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 /* USE_CRYPT */ 00197 00198 static void 00199 DesEncrypt( u_char *clear, /* IN 8 octets */ 00200 u_char *key, /* IN 7 octets */ 00201 u_char *cipher /* OUT 8 octets */) 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 /* USE_CRYPT */ 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 /* in == 8-byte string (expanded version of the 56-bit key) 00242 * out == 64-byte string where each byte is either 1 or 0 00243 * Note that the low-order "bit" is always ignored by by setkey() 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 /* The inverse of Expand 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, /* IN 56 bit DES key missing parity bits */ 00281 u_char *des_key /* OUT 64 bit DES key with parity bits added */) 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 /* Initialize the Unicode version of the secret (== password). */ 00319 /* This implicitly supports 8-bit ISO8859/1 characters. */ 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); /* Unicode is 2 bytes/char, *8 for bit count */ 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 /* @todo: arg type - u_long* or u_int* ? */ 00332 MDreverse((unsigned int*)&md4Context); /* sfb 961105 */ 00333 } 00334 00335 MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ 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!@#$%"; /* key from rasapi32.dll */ 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]; /* max is actually 14 */ 00352 u_char PasswordHash[16]; 00353 00354 /* LANMan password is case insensitive */ 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 /* Calculate both always */ 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 /* prefered method is set by option */ 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 /* MSCHAP_SUPPORT */ 00395 00396 #endif /* PPP_SUPPORT */
Generated on Tue Jul 12 2022 11:52:56 by 1.7.2