ntlm.c
来自「samba最新软件」· C语言 代码 · 共 1,365 行 · 第 1/3 页
C
1,365 行
struct sec_buffer domain, hostname; krb5_storage *out; uint32_t base, flags; flags = type1->flags; base = 16; if (type1->domain) { base += 8; flags |= NTLM_SUPPLIED_DOMAIN; } if (type1->hostname) { base += 8; flags |= NTLM_SUPPLIED_WORKSTAION; } if (type1->os[0]) base += 8; if (type1->domain) { domain.offset = base; domain.length = len_string(0, type1->domain); domain.allocated = domain.length; } if (type1->hostname) { hostname.offset = domain.allocated + domain.offset; hostname.length = len_string(0, type1->hostname); hostname.allocated = hostname.length; } out = krb5_storage_emem(); if (out == NULL) return ENOMEM; krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); CHECK(krb5_storage_write(out, ntlmsigature, sizeof(ntlmsigature)), sizeof(ntlmsigature)); CHECK(krb5_store_uint32(out, 1), 0); CHECK(krb5_store_uint32(out, flags), 0); if (type1->domain) CHECK(store_sec_buffer(out, &domain), 0); if (type1->hostname) CHECK(store_sec_buffer(out, &hostname), 0); if (type1->os[0]) { CHECK(krb5_store_uint32(out, type1->os[0]), 0); CHECK(krb5_store_uint32(out, type1->os[1]), 0); } if (type1->domain) CHECK(put_string(out, 0, type1->domain), 0); if (type1->hostname) CHECK(put_string(out, 0, type1->hostname), 0); { krb5_data d; ret = krb5_storage_to_data(out, &d); data->data = d.data; data->length = d.length; }out: krb5_storage_free(out); return ret;}/** * Frees the ntlm_type2 message * * @param data message to be freed * * @ingroup ntlm_core */voidheim_ntlm_free_type2(struct ntlm_type2 *data){ if (data->targetname) free(data->targetname); heim_ntlm_free_buf(&data->targetinfo); memset(data, 0, sizeof(*data));}intheim_ntlm_decode_type2(const struct ntlm_buf *buf, struct ntlm_type2 *type2){ krb5_error_code ret; unsigned char sig[8]; uint32_t type, ctx[2]; struct sec_buffer targetname, targetinfo; krb5_storage *in; int ucs2 = 0; memset(type2, 0, sizeof(*type2)); in = krb5_storage_from_readonly_mem(buf->data, buf->length); if (in == NULL) { ret = EINVAL; goto out; } krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); CHECK(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig)); CHECK(memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0); CHECK(krb5_ret_uint32(in, &type), 0); CHECK(type, 2); CHECK(ret_sec_buffer(in, &targetname), 0); CHECK(krb5_ret_uint32(in, &type2->flags), 0); if (type2->flags & NTLM_NEG_UNICODE) ucs2 = 1; CHECK(krb5_storage_read(in, type2->challange, sizeof(type2->challange)), sizeof(type2->challange)); CHECK(krb5_ret_uint32(in, &ctx[0]), 0); /* context */ CHECK(krb5_ret_uint32(in, &ctx[1]), 0); CHECK(ret_sec_buffer(in, &targetinfo), 0); /* os version */#if 0 CHECK(krb5_ret_uint32(in, &type2->os[0]), 0); CHECK(krb5_ret_uint32(in, &type2->os[1]), 0);#endif CHECK(ret_string(in, ucs2, &targetname, &type2->targetname), 0); CHECK(ret_buf(in, &targetinfo, &type2->targetinfo), 0); ret = 0;out: krb5_storage_free(in); if (ret) heim_ntlm_free_type2(type2); return ret;}/** * Encodes an ntlm_type2 message. * * @param type2 the ntlm_type2 message to encode. * @param data is the return buffer with the encoded message, should be * freed with heim_ntlm_free_buf(). * * @return In case of success 0 is return, an errors, a errno in what * went wrong. * * @ingroup ntlm_core */intheim_ntlm_encode_type2(const struct ntlm_type2 *type2, struct ntlm_buf *data){ struct sec_buffer targetname, targetinfo; krb5_error_code ret; krb5_storage *out = NULL; uint32_t base; int ucs2 = 0; if (type2->os[0]) base = 56; else base = 48; if (type2->flags & NTLM_NEG_UNICODE) ucs2 = 1; targetname.offset = base; targetname.length = len_string(ucs2, type2->targetname); targetname.allocated = targetname.length; targetinfo.offset = targetname.allocated + targetname.offset; targetinfo.length = type2->targetinfo.length; targetinfo.allocated = type2->targetinfo.length; out = krb5_storage_emem(); if (out == NULL) return ENOMEM; krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); CHECK(krb5_storage_write(out, ntlmsigature, sizeof(ntlmsigature)), sizeof(ntlmsigature)); CHECK(krb5_store_uint32(out, 2), 0); CHECK(store_sec_buffer(out, &targetname), 0); CHECK(krb5_store_uint32(out, type2->flags), 0); CHECK(krb5_storage_write(out, type2->challange, sizeof(type2->challange)), sizeof(type2->challange)); CHECK(krb5_store_uint32(out, 0), 0); /* context */ CHECK(krb5_store_uint32(out, 0), 0); CHECK(store_sec_buffer(out, &targetinfo), 0); /* os version */ if (type2->os[0]) { CHECK(krb5_store_uint32(out, type2->os[0]), 0); CHECK(krb5_store_uint32(out, type2->os[1]), 0); } CHECK(put_string(out, ucs2, type2->targetname), 0); CHECK(krb5_storage_write(out, type2->targetinfo.data, type2->targetinfo.length), type2->targetinfo.length); { krb5_data d; ret = krb5_storage_to_data(out, &d); data->data = d.data; data->length = d.length; }out: krb5_storage_free(out); return ret;}/** * Frees the ntlm_type3 message * * @param data message to be freed * * @ingroup ntlm_core */voidheim_ntlm_free_type3(struct ntlm_type3 *data){ heim_ntlm_free_buf(&data->lm); heim_ntlm_free_buf(&data->ntlm); if (data->targetname) free(data->targetname); if (data->username) free(data->username); if (data->ws) free(data->ws); heim_ntlm_free_buf(&data->sessionkey); memset(data, 0, sizeof(*data));}/* * */intheim_ntlm_decode_type3(const struct ntlm_buf *buf, int ucs2, struct ntlm_type3 *type3){ krb5_error_code ret; unsigned char sig[8]; uint32_t type; krb5_storage *in; struct sec_buffer lm, ntlm, target, username, sessionkey, ws; memset(type3, 0, sizeof(*type3)); memset(&sessionkey, 0, sizeof(sessionkey)); in = krb5_storage_from_readonly_mem(buf->data, buf->length); if (in == NULL) { ret = EINVAL; goto out; } krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); CHECK(krb5_storage_read(in, sig, sizeof(sig)), sizeof(sig)); CHECK(memcmp(ntlmsigature, sig, sizeof(ntlmsigature)), 0); CHECK(krb5_ret_uint32(in, &type), 0); CHECK(type, 3); CHECK(ret_sec_buffer(in, &lm), 0); CHECK(ret_sec_buffer(in, &ntlm), 0); CHECK(ret_sec_buffer(in, &target), 0); CHECK(ret_sec_buffer(in, &username), 0); CHECK(ret_sec_buffer(in, &ws), 0); if (lm.offset >= 60) { CHECK(ret_sec_buffer(in, &sessionkey), 0); } if (lm.offset >= 64) { CHECK(krb5_ret_uint32(in, &type3->flags), 0); } if (lm.offset >= 72) { CHECK(krb5_ret_uint32(in, &type3->os[0]), 0); CHECK(krb5_ret_uint32(in, &type3->os[1]), 0); } CHECK(ret_buf(in, &lm, &type3->lm), 0); CHECK(ret_buf(in, &ntlm, &type3->ntlm), 0); CHECK(ret_string(in, ucs2, &target, &type3->targetname), 0); CHECK(ret_string(in, ucs2, &username, &type3->username), 0); CHECK(ret_string(in, ucs2, &ws, &type3->ws), 0); if (sessionkey.offset) CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0);out: krb5_storage_free(in); if (ret) heim_ntlm_free_type3(type3); return ret;}/** * Encodes an ntlm_type3 message. * * @param type3 the ntlm_type3 message to encode. * @param data is the return buffer with the encoded message, should be * freed with heim_ntlm_free_buf(). * * @return In case of success 0 is return, an errors, a errno in what * went wrong. * * @ingroup ntlm_core */intheim_ntlm_encode_type3(const struct ntlm_type3 *type3, struct ntlm_buf *data){ struct sec_buffer lm, ntlm, target, username, sessionkey, ws; krb5_error_code ret; krb5_storage *out = NULL; uint32_t base; int ucs2 = 0; memset(&lm, 0, sizeof(lm)); memset(&ntlm, 0, sizeof(ntlm)); memset(&target, 0, sizeof(target)); memset(&username, 0, sizeof(username)); memset(&ws, 0, sizeof(ws)); memset(&sessionkey, 0, sizeof(sessionkey)); base = 52; if (type3->sessionkey.length) { base += 8; /* sessionkey sec buf */ base += 4; /* flags */ } if (type3->os[0]) { base += 8; } if (type3->flags & NTLM_NEG_UNICODE) ucs2 = 1; lm.offset = base; lm.length = type3->lm.length; lm.allocated = type3->lm.length; ntlm.offset = lm.offset + lm.allocated; ntlm.length = type3->ntlm.length; ntlm.allocated = ntlm.length; target.offset = ntlm.offset + ntlm.allocated; target.length = len_string(ucs2, type3->targetname); target.allocated = target.length; username.offset = target.offset + target.allocated; username.length = len_string(ucs2, type3->username); username.allocated = username.length; ws.offset = username.offset + username.allocated; ws.length = len_string(ucs2, type3->ws); ws.allocated = ws.length; sessionkey.offset = ws.offset + ws.allocated; sessionkey.length = type3->sessionkey.length; sessionkey.allocated = type3->sessionkey.length; out = krb5_storage_emem(); if (out == NULL) return ENOMEM; krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); CHECK(krb5_storage_write(out, ntlmsigature, sizeof(ntlmsigature)), sizeof(ntlmsigature)); CHECK(krb5_store_uint32(out, 3), 0); CHECK(store_sec_buffer(out, &lm), 0); CHECK(store_sec_buffer(out, &ntlm), 0); CHECK(store_sec_buffer(out, &target), 0); CHECK(store_sec_buffer(out, &username), 0); CHECK(store_sec_buffer(out, &ws), 0); /* optional */ if (type3->sessionkey.length) { CHECK(store_sec_buffer(out, &sessionkey), 0); CHECK(krb5_store_uint32(out, type3->flags), 0); }#if 0 CHECK(krb5_store_uint32(out, 0), 0); /* os0 */ CHECK(krb5_store_uint32(out, 0), 0); /* os1 */#endif CHECK(put_buf(out, &type3->lm), 0); CHECK(put_buf(out, &type3->ntlm), 0); CHECK(put_string(out, ucs2, type3->targetname), 0); CHECK(put_string(out, ucs2, type3->username), 0); CHECK(put_string(out, ucs2, type3->ws), 0); CHECK(put_buf(out, &type3->sessionkey), 0); { krb5_data d; ret = krb5_storage_to_data(out, &d); data->data = d.data; data->length = d.length; }out: krb5_storage_free(out); return ret;}/* * */static voidsplitandenc(unsigned char *hash, unsigned char *challange, unsigned char *answer){ DES_cblock key; DES_key_schedule sched; ((unsigned char*)key)[0] = hash[0]; ((unsigned char*)key)[1] = (hash[0] << 7) | (hash[1] >> 1); ((unsigned char*)key)[2] = (hash[1] << 6) | (hash[2] >> 2); ((unsigned char*)key)[3] = (hash[2] << 5) | (hash[3] >> 3); ((unsigned char*)key)[4] = (hash[3] << 4) | (hash[4] >> 4); ((unsigned char*)key)[5] = (hash[4] << 3) | (hash[5] >> 5); ((unsigned char*)key)[6] = (hash[5] << 2) | (hash[6] >> 6); ((unsigned char*)key)[7] = (hash[6] << 1); DES_set_odd_parity(&key); DES_set_key(&key, &sched); DES_ecb_encrypt((DES_cblock *)challange, (DES_cblock *)answer, &sched, 1); memset(&sched, 0, sizeof(sched)); memset(key, 0, sizeof(key));}/** * Calculate the NTLM key, the password is assumed to be in UTF8. * * @param password password to calcute the key for. * @param key calcuted key, should be freed with heim_ntlm_free_buf(). * * @return In case of success 0 is return, an errors, a errno in what * went wrong. * * @ingroup ntlm_core */intheim_ntlm_nt_key(const char *password, struct ntlm_buf *key){ struct ntlm_buf buf; MD4_CTX ctx; int ret; key->data = malloc(MD5_DIGEST_LENGTH); if (key->data == NULL) return ENOMEM; key->length = MD5_DIGEST_LENGTH; ret = ascii2ucs2le(password, 0, &buf); if (ret) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?