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 + -
显示快捷键?