📄 ntlm_auth.c
字号:
/***************************************************************************//* This code is part of WWW grabber called pavuk *//* Copyright (c) 1997 - 2001 Stefan Ondrejicka *//* Distributed under GPL 2 or later *//***************************************************************************/#include "config.h"/****************************************************************//* based on the document "NTLM Athentication Scheme for HTTP" *//* http://www.innovation.ch/java/ntlm.html *//* by Ronald Tschaler <ronald@innovation.ch> *//****************************************************************//* and http://www.opengroup.org/comsource/techref2/NCH1222X.HTM *//****************************************************************/#ifdef ENABLE_NTLM#include <string.h>#include "base64.h"#include "tools.h"#include "mime.h"#include "doc.h"#include "http.h"#include "tools.h"#include "abstract.h"#include "authinfo.h"#include "errcode.h"#include "ntlm_auth.h"#ifdef HAVE_MCRYPT#include <mcrypt.h>#elif defined(HAVE_GCRYPT)#include <gcrypt.h>#else#ifdef OPENSSL#include <openssl/des.h>#else#include <des.h>#endif#endif#ifdef HAVE_OPENSSL_MD4#include <openssl/md4.h>#define _MD4Init MD4_Init#define _MD4Update MD4_Update#define _MD4Final MD4_Final#else#include "md4c.h"#define _MD4Init MD4Init#define _MD4Update MD4Update#define _MD4Final MD4Final#endif#ifdef WORDS_BIGENDIANstatic unsigned short ntlm_do_litle_endian_short(short v){ short sh; ((char *) &sh)[0] = v && 0xFF; ((char *) &sh)[1] = v >> 8; return sh;}static unsigned short ntlm_get_litle_endian_short(short v){ short sh; sh = ((char *) &v)[0] + (((char *) &v)[1] << 8); return sh;}#else#define ntlm_do_litle_endian_short(v) ((unsigned short)(v))#define ntlm_get_litle_endian_short(v) ((unsigned short)(v))#endif#define _LB(nr) ((nr) & 0xff)#define _HB(nr) (((nr) & 0xff00) >> 8)char *ntlm_get_t1msg_str(char *domain, char *host){ int msgtk_size; int dlen, hlen;#ifndef NTLM_UNPACKED_STRUCT ntlm_type_1_msg_t msg;#else unsigned char msg[NTLM_MSG1_SIZE];#endif dlen = strlen(domain); hlen = strlen(host); memset(&msg, '\0', sizeof(msg));#ifndef NTLM_UNPACKED_STRUCT strcpy(msg.protocol, "NTLMSSP"); msg.type = 0x01; msg.flags = ntlm_do_litle_endian_short(0xb203); msg.dom_len2 = msg.dom_len = ntlm_do_litle_endian_short(dlen); msg.host_len2 = msg.host_len = ntlm_do_litle_endian_short(hlen); msg.host_off = ntlm_do_litle_endian_short(32); msg.dom_off = ntlm_do_litle_endian_short(32 + hlen);#else strcpy(msg, "NTLMSSP"); msg[8] = 0x01; msg[12] = 0x03; msg[13] = 0xb2; msg[16] = msg[18] = _LB(dlen); msg[17] = msg[19] = _HB(dlen); msg[20] = _LB(32 + hlen); msg[21] = _HB(32 + hlen); msg[24] = msg[26] = _LB(hlen); msg[25] = msg[27] = _HB(hlen); msg[28] = 32; msg[29] = 0x0;#endif strcpy(((char *) &msg) + 32, host); upperstr(((char *) &msg) + 32); strcpy(((char *) &msg) + 32 + hlen, domain); upperstr(((char *) &msg) + 32 + hlen); msgtk_size = 32 + hlen + dlen; return base64_encode_data((char *) &msg, msgtk_size);}char *ntlm_get_nonce(char *t2msg, unsigned short *t2flags){ char *rv; int st;#ifndef NTLM_UNPACKED_STRUCT ntlm_type_2_msg_t *msg;#else char *msg;#endif msg = NULL; st = base64_decode_data(t2msg, (char **) &msg);#ifndef NTLM_UNPACKED_STRUCT if(st < 0 || st < sizeof(ntlm_type_2_msg_t) || strcmp(msg->protocol, "NTLMSSP") || msg->type != 0x02) { rv = NULL; } else { rv = _malloc(9); memcpy(rv, msg->nonce, 8); rv[8] = '\0'; *t2flags = ntlm_do_litle_endian_short(msg->flags); }#else if(st < 0 || st < NTLM_MSG2_SIZE || strcmp(msg, "NTLMSSP") || msg[8] != 0x02) { rv = NULL; } else { rv = _malloc(9); memcpy(rv, msg + 24, 8); rv[8] = '\0'; *t2flags = ntlm_do_litle_endian_short(*((unsigned short *) (((char *) msg) + 20))); }#endif _free(msg); return rv;}static void ntlm_copy_str_to_wcstr(char *wcstr, char *str){ while(*str) { wcstr[0] = *str; wcstr[1] = '\0'; wcstr += 2; str++; }}static void ntlm_copy_str_to_uwcstr(char *wcstr, char *str){ while(*str) { wcstr[0] = tl_ascii_toupper(*str); wcstr[1] = '\0'; wcstr += 2; str++; }}/* turns a 56 bit key into the 64 bit */static void ntlm_setup_des_key(unsigned char *key_56, unsigned char *key_64){ key_64[0] = key_56[0]; key_64[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); key_64[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); key_64[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); key_64[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); key_64[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); key_64[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); key_64[7] = (key_56[6] << 1) & 0xFF;}#ifdef HAVE_MCRYPTstatic void ntlm_des_enc(unsigned char *key, unsigned char *plaintext, unsigned char *result){ MCRYPT ctx; unsigned char res[8]; unsigned char key64[8]; ntlm_setup_des_key(key, key64); memcpy(res, plaintext, 8); ctx = mcrypt_module_open(MCRYPT_DES, NULL, MCRYPT_ECB, NULL); mcrypt_generic_init(ctx, key64, 8, NULL); mcrypt_generic(ctx, res, 8); memcpy(result, res, 8); mcrypt_generic_end(ctx); mcrypt_module_close(ctx);}#elif defined(HAVE_GCRYPT)static void ntlm_des_enc(unsigned char *key, unsigned char *plaintext, unsigned char *result){ gcry_cipher_hd_t ctx; unsigned char key64[8]; ntlm_setup_des_key(key, key64); gcry_cipher_open(&ctx, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); gcry_cipher_setkey(ctx, key64, 8); gcry_cipher_encrypt(ctx, result, 8, plaintext, 8); gcry_cipher_close(ctx);}#elsestatic void ntlm_des_enc(unsigned char *key, unsigned char *plaintext, unsigned char *result){ des_key_schedule ks;#ifdef OPENSSL const_des_cblock _plaintext;#else const des_cblock _plaintext;#endif des_cblock _result; des_cblock key64; unsigned char skey[8]; memcpy(&_plaintext, plaintext, sizeof(_plaintext)); ntlm_setup_des_key(key, skey); memcpy(key64, skey, 8);#ifdef OPENSSL des_set_odd_parity(&key64); des_set_key(&key64, ks); des_ecb_encrypt(&_plaintext, &_result, ks, DES_ENCRYPT);#else des_set_odd_parity(key64); des_set_key(key64, ks); des_ecb_encrypt(_plaintext, _result, ks, DES_ENCRYPT);#endif memcpy(result, &_result, sizeof(_result));}#endif/* * takes a 21 byte array and treats it as 3 56-bit DES keys. The * 8 byte plaintext is encrypted with each key and the resulting 24 * bytes are stored in the results array. */static void ntlm_calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results){ ntlm_des_enc(keys, plaintext, results); ntlm_des_enc(keys + 7, plaintext, results + 8); ntlm_des_enc(keys + 14, plaintext, results + 16);}static void ntlm_gen_lm_resp(char *pass, char *nonce, char *buf){ unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }; unsigned char lm_hpw[21]; unsigned char lm_pw[14]; memset(lm_pw, '\0', sizeof(lm_pw)); strncpy(lm_pw, pass, 14); lm_pw[13] = '\0'; upperstr(lm_pw); ntlm_des_enc(lm_pw, magic, lm_hpw); ntlm_des_enc(lm_pw + 7, magic, lm_hpw + 8); memset(lm_hpw + 16, '\0', 5); ntlm_calc_resp(lm_hpw, nonce, buf);}static void ntlm_gen_nt_resp(char *pass, char *nonce, char *buf){ MD4_CTX md4ctx; char *nt_pw; unsigned char nt_hpw[21]; int len = strlen(pass); nt_pw = _malloc(2 * len); ntlm_copy_str_to_wcstr(nt_pw, pass); _MD4Init(&md4ctx); _MD4Update(&md4ctx, nt_pw, 2 * len); _MD4Final(nt_hpw, &md4ctx); memset(nt_hpw + 16, '\0', 5); ntlm_calc_resp(nt_hpw, nonce, buf); _free(nt_pw);}static char *ntlm_get_t3msg_wcstr(char *domain, char *host, char *user, char *pass, char *nonce){ int dlen, hlen, ulen, lm_len, nt_len; int dofs, hofs, uofs, lm_ofs, nt_ofs; int msgtk_size;#ifndef NTLM_UNPACKED_STRUCT ntlm_type_3_msg_t msg;#else char msg[NTLM_MSG3_SIZE];#endif dlen = strlen(domain); hlen = strlen(host); ulen = strlen(user); lm_len = 0x18; nt_len = 0x18; dofs = 64; uofs = dofs + 2 * dlen; hofs = uofs + 2 * ulen; lm_ofs = hofs + 2 * hlen; nt_ofs = lm_ofs + lm_len; msgtk_size = 64 + 2 * dlen + 2 * ulen + 2 * hlen + lm_len + nt_len; memset(&msg, '\0', sizeof(msg));#ifndef NTLM_UNPACKED_STRUCT strcpy(msg.protocol, "NTLMSSP"); msg.type = 0x03; msg.flags = 0x8201; msg.dom_len = msg.dom_len2 = ntlm_do_litle_endian_short(2 * dlen); msg.dom_off = ntlm_do_litle_endian_short(dofs); msg.user_len = msg.user_len2 = ntlm_do_litle_endian_short(2 * ulen); msg.user_off = ntlm_do_litle_endian_short(uofs); msg.host_len = msg.host_len2 = ntlm_do_litle_endian_short(2 * hlen); msg.host_off = ntlm_do_litle_endian_short(hofs); msg.lm_resp_len = msg.lm_resp_len2 = ntlm_do_litle_endian_short(lm_len); msg.lm_resp_off = ntlm_do_litle_endian_short(lm_ofs); msg.nt_resp_len = msg.nt_resp_len2 = ntlm_do_litle_endian_short(nt_len); msg.nt_resp_off = ntlm_do_litle_endian_short(nt_ofs); msg.msg_len = ntlm_do_litle_endian_short(msgtk_size);#else strcpy(msg, "NTLMSSP"); msg[8] = 0x3; msg[12] = msg[14] = _LB(lm_len); msg[13] = msg[15] = _HB(lm_len); msg[16] = _LB(lm_ofs); msg[17] = _HB(lm_ofs); msg[20] = msg[22] = _LB(nt_len); msg[21] = msg[23] = _HB(nt_len); msg[24] = _LB(nt_ofs); msg[25] = _HB(nt_ofs); msg[28] = msg[30] = _LB(2 * dlen); msg[29] = msg[31] = _HB(2 * dlen); msg[32] = _LB(dofs); msg[33] = _HB(dofs); msg[36] = msg[38] = _LB(2 * ulen); msg[37] = msg[39] = _HB(2 * ulen); msg[40] = _LB(uofs); msg[41] = _HB(uofs); msg[44] = msg[46] = _LB(2 * hlen); msg[45] = msg[47] = _HB(2 * hlen); msg[48] = _LB(hofs); msg[49] = _HB(hofs); msg[56] = _LB(msgtk_size); msg[57] = _HB(msgtk_size); msg[60] = 0x1; msg[61] = 0x82;#endif ntlm_copy_str_to_uwcstr(((char *) &msg) + dofs, domain); ntlm_copy_str_to_wcstr(((char *) &msg) + uofs, user); ntlm_copy_str_to_uwcstr(((char *) &msg) + hofs, host); ntlm_gen_lm_resp(pass, nonce, ((char *) &msg) + lm_ofs); ntlm_gen_nt_resp(pass, nonce, ((char *) &msg) + nt_ofs); return base64_encode_data((char *) &msg, msgtk_size);}static char *ntlm_get_t3msg_asciistr(char *domain, char *host, char *user, char *pass, char *nonce){ int dlen, hlen, ulen, lm_len, nt_len; int dofs, hofs, uofs, lm_ofs, nt_ofs; int msgtk_size;#ifndef NTLM_UNPACKED_STRUCT ntlm_type_3_msg_t msg;#else char msg[NTLM_MSG3_SIZE];#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -