⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 digest.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	    }	    r.u.error.code = EINVAL;	}	kdc_log(context, config, 0, "Digest %s request successful %s",		ireq.u.digestRequest.type, ireq.u.digestRequest.username);	break;    }    case choice_DigestReqInner_ntlmInit:	if ((config->digests_allowed & (NTLM_V1|NTLM_V1_SESSION|NTLM_V2)) == 0) {	    kdc_log(context, config, 0, "NTLM not allowed");	    goto failed;	}	r.element = choice_DigestRepInner_ntlmInitReply;	r.u.ntlmInitReply.flags = NTLM_NEG_UNICODE;	if ((ireq.u.ntlmInit.flags & NTLM_NEG_UNICODE) == 0) {	    kdc_log(context, config, 0, "NTLM client have no unicode");	    goto failed;	}	if (ireq.u.ntlmInit.flags & NTLM_NEG_NTLM)	    r.u.ntlmInitReply.flags |= NTLM_NEG_NTLM;	else {	    kdc_log(context, config, 0, "NTLM client doesn't support NTLM");	    goto failed;	}	r.u.ntlmInitReply.flags |= 	    NTLM_NEG_TARGET |	    NTLM_TARGET_DOMAIN |	    NTLM_ENC_128;#define ALL					\	NTLM_NEG_SIGN|				\	    NTLM_NEG_SEAL|			\	    NTLM_NEG_ALWAYS_SIGN|		\	    NTLM_NEG_NTLM2_SESSION|		\	    NTLM_NEG_KEYEX	r.u.ntlmInitReply.flags |= (ireq.u.ntlmInit.flags & (ALL));#undef ALL	r.u.ntlmInitReply.targetname = 	    get_ntlm_targetname(context, client);	if (r.u.ntlmInitReply.targetname == NULL) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	r.u.ntlmInitReply.challange.data = malloc(8);	if (r.u.ntlmInitReply.challange.data == NULL) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	r.u.ntlmInitReply.challange.length = 8;	if (RAND_bytes(r.u.ntlmInitReply.challange.data,		       r.u.ntlmInitReply.challange.length) != 1) 	{	    krb5_set_error_string(context, "out of random error");	    ret = ENOMEM;	    goto out;	}	/* XXX fix targetinfo */	ALLOC(r.u.ntlmInitReply.targetinfo);	if (r.u.ntlmInitReply.targetinfo == NULL) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	ret = fill_targetinfo(context,			      r.u.ntlmInitReply.targetname,			      client,			      r.u.ntlmInitReply.targetinfo);	if (ret) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	/* 	 * Save data encryted in opaque for the second part of the	 * ntlm authentication	 */	sp = krb5_storage_emem();	if (sp == NULL) {	    ret = ENOMEM;	    krb5_set_error_string(context, "out of memory");	    goto out;	}		ret = krb5_storage_write(sp, r.u.ntlmInitReply.challange.data, 8);	if (ret != 8) {	    ret = ENOMEM;	    krb5_set_error_string(context, "storage write challange");	    goto out;	}	ret = krb5_store_uint32(sp, r.u.ntlmInitReply.flags);	if (ret) {	    krb5_clear_error_string(context);	    goto out;	}	ret = krb5_storage_to_data(sp, &buf);	if (ret) {	    krb5_clear_error_string(context);	    goto out;	}	ret = get_digest_key(context, config, server, &crypto);	if (ret)	    goto out;	ret = krb5_encrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE,			   buf.data, buf.length, &r.u.ntlmInitReply.opaque);	krb5_data_free(&buf);	krb5_crypto_destroy(context, crypto);	crypto = NULL;	if (ret)	    goto out;	kdc_log(context, config, 0, "NTLM init from %s", from);	break;    case choice_DigestReqInner_ntlmRequest: {	krb5_principal clientprincipal;	unsigned char sessionkey[16];	unsigned char challange[8];	uint32_t flags;	Key *key = NULL;	int version;	    	r.element = choice_DigestRepInner_ntlmResponse;	r.u.ntlmResponse.success = 0;	r.u.ntlmResponse.flags = 0;	r.u.ntlmResponse.sessionkey = NULL;	r.u.ntlmResponse.tickets = NULL;	/* get username */	ret = krb5_parse_name(context,			      ireq.u.ntlmRequest.username,			      &clientprincipal);	if (ret)	    goto failed;	ret = _kdc_db_fetch(context, config, clientprincipal,			    HDB_F_GET_CLIENT, NULL, &user);	krb5_free_principal(context, clientprincipal);	if (ret) {	    krb5_set_error_string(context, "NTLM user %s not in database",				  ireq.u.ntlmRequest.username);	    goto failed;	}	ret = get_digest_key(context, config, server, &crypto);	if (ret)	    goto failed;	ret = krb5_decrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE,			   ireq.u.ntlmRequest.opaque.data,			   ireq.u.ntlmRequest.opaque.length, &buf);	krb5_crypto_destroy(context, crypto);	crypto = NULL;	if (ret) {	    kdc_log(context, config, 0, 		    "Failed to decrypt nonce from %s", from);	    goto failed;	}	sp = krb5_storage_from_data(&buf);	if (sp == NULL) {	    ret = ENOMEM;	    krb5_set_error_string(context, "out of memory");	    goto out;	}		ret = krb5_storage_read(sp, challange, sizeof(challange));	if (ret != sizeof(challange)) {	    krb5_set_error_string(context, "NTLM storage read challange");	    ret = ENOMEM;	    goto out;	}	ret = krb5_ret_uint32(sp, &flags);	if (ret) {	    krb5_set_error_string(context, "NTLM storage read flags");	    goto out;	}	krb5_data_free(&buf);	if ((flags & NTLM_NEG_NTLM) == 0) {	    ret = EINVAL;	    krb5_set_error_string(context, "NTLM not negotiated");	    goto out;	}	ret = hdb_enctype2key(context, &user->entry, 			      ETYPE_ARCFOUR_HMAC_MD5, &key);	if (ret) {	    krb5_set_error_string(context, "NTLM missing arcfour key");	    goto out;	}	/* check if this is NTLMv2 */	if (ireq.u.ntlmRequest.ntlm.length != 24) {	    struct ntlm_buf infotarget, answer;	    char *targetname;	    if ((config->digests_allowed & NTLM_V2) == 0) {		kdc_log(context, config, 0, "NTLM v2 not allowed");		goto out;	    }	    version = 2;	    targetname = get_ntlm_targetname(context, client);	    if (targetname == NULL) {		krb5_set_error_string(context, "out of memory");		ret = ENOMEM;		goto out;	    }	    answer.length = ireq.u.ntlmRequest.ntlm.length;	    answer.data = ireq.u.ntlmRequest.ntlm.data;	    ret = heim_ntlm_verify_ntlm2(key->key.keyvalue.data,					 key->key.keyvalue.length,					 ireq.u.ntlmRequest.username,					 targetname,					 0,					 challange,					 &answer,					 &infotarget,					 sessionkey);	    free(targetname);	    if (ret) {		krb5_set_error_string(context, "NTLM v2 verify failed");		goto failed;	    }	    /* XXX verify infotarget matches client (checksum ?) */	    free(infotarget.data);	    /* */	} else {	    struct ntlm_buf answer;	    version = 1;	    if (flags & NTLM_NEG_NTLM2_SESSION) {		unsigned char sessionhash[MD5_DIGEST_LENGTH];		MD5_CTX md5ctx;				if ((config->digests_allowed & NTLM_V1_SESSION) == 0) {		    kdc_log(context, config, 0, "NTLM v1-session not allowed");		    ret = EINVAL;		    goto failed;		}		if (ireq.u.ntlmRequest.lm.length != 24) {		    krb5_set_error_string(context, "LM hash have wrong length "					  "for NTLM session key");		    ret = EINVAL;		    goto failed;		}				MD5_Init(&md5ctx);		MD5_Update(&md5ctx, challange, sizeof(challange));		MD5_Update(&md5ctx, ireq.u.ntlmRequest.lm.data, 8);		MD5_Final(sessionhash, &md5ctx);		memcpy(challange, sessionhash, sizeof(challange));	    } else {		if ((config->digests_allowed & NTLM_V1) == 0) {		    kdc_log(context, config, 0, "NTLM v1 not allowed");		    goto failed;		}	    }	    	    ret = heim_ntlm_calculate_ntlm1(key->key.keyvalue.data,					    key->key.keyvalue.length,					    challange, &answer);	    if (ret) {		krb5_set_error_string(context, "NTLM missing arcfour key");		goto failed;	    }	    	    if (ireq.u.ntlmRequest.ntlm.length != answer.length ||		memcmp(ireq.u.ntlmRequest.ntlm.data, answer.data, answer.length) != 0)	    {		free(answer.data);		ret = EINVAL;		krb5_set_error_string(context, "NTLM hash mismatch");		goto failed;	    }	    free(answer.data);	    {		MD4_CTX ctx;		MD4_Init(&ctx);		MD4_Update(&ctx, 			   key->key.keyvalue.data, key->key.keyvalue.length);		MD4_Final(sessionkey, &ctx);	    }	}	if (ireq.u.ntlmRequest.sessionkey) {	    unsigned char masterkey[MD4_DIGEST_LENGTH];	    RC4_KEY rc4;	    size_t len;	    	    if ((flags & NTLM_NEG_KEYEX) == 0) {		krb5_set_error_string(context,				      "NTLM client failed to neg key "				      "exchange but still sent key");		ret = EINVAL;		goto failed;	    }	    	    len = ireq.u.ntlmRequest.sessionkey->length;	    if (len != sizeof(masterkey)){		krb5_set_error_string(context,				      "NTLM master key wrong length: %lu",				      (unsigned long)len);		goto failed;	    }	    	    RC4_set_key(&rc4, sizeof(sessionkey), sessionkey);	    	    RC4(&rc4, sizeof(masterkey),		ireq.u.ntlmRequest.sessionkey->data, 		masterkey);	    memset(&rc4, 0, sizeof(rc4));	    	    r.u.ntlmResponse.sessionkey = 		malloc(sizeof(*r.u.ntlmResponse.sessionkey));	    if (r.u.ntlmResponse.sessionkey == NULL) {		krb5_set_error_string(context, "out of memory");		goto out;	    }	    	    ret = krb5_data_copy(r.u.ntlmResponse.sessionkey,				 masterkey, sizeof(masterkey));	    if (ret) {		krb5_set_error_string(context, "out of memory");		goto out;	    }	}	r.u.ntlmResponse.success = 1;	kdc_log(context, config, 0, "NTLM version %d successful for %s",		version, ireq.u.ntlmRequest.username);	break;    }    case choice_DigestReqInner_supportedMechs:	kdc_log(context, config, 0, "digest supportedMechs from %s", from);	r.element = choice_DigestRepInner_supportedMechs;	memset(&r.u.supportedMechs, 0, sizeof(r.u.supportedMechs));	if (config->digests_allowed & NTLM_V1)	    r.u.supportedMechs.ntlm_v1 = 1;	if (config->digests_allowed & NTLM_V1_SESSION)	    r.u.supportedMechs.ntlm_v1_session = 1;	if (config->digests_allowed & NTLM_V2)	    r.u.supportedMechs.ntlm_v2 = 1;	if (config->digests_allowed & DIGEST_MD5)	    r.u.supportedMechs.digest_md5 = 1;	if (config->digests_allowed & CHAP_MD5)	    r.u.supportedMechs.chap_md5 = 1;	if (config->digests_allowed & MS_CHAP_V2)	    r.u.supportedMechs.ms_chap_v2 = 1;	break;    default: {	char *s;	krb5_set_error_string(context, "unknown operation to digest");	ret = EINVAL;    failed:	s = krb5_get_error_message(context, ret);	if (s == NULL) {	    krb5_clear_error_string(context);	    goto out;	}		kdc_log(context, config, 0, "Digest failed with: %s", s);	r.element = choice_DigestRepInner_error;	r.u.error.reason = strdup("unknown error");	krb5_free_error_string(context, s);	if (r.u.error.reason == NULL) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	r.u.error.code = EINVAL;	break;    }    }    ASN1_MALLOC_ENCODE(DigestRepInner, buf.data, buf.length, &r, &size, ret);    if (ret) {	krb5_set_error_string(context, "Failed to encode inner digest reply");	goto out;    }    if (size != buf.length)	krb5_abortx(context, "ASN1 internal error");    krb5_auth_con_addflags(context, ac, KRB5_AUTH_CONTEXT_USE_SUBKEY, NULL);    ret = krb5_mk_rep (context, ac, &rep.apRep);    if (ret)	goto out;    {	krb5_keyblock *key;	ret = krb5_auth_con_getlocalsubkey(context, ac, &key);	if (ret)	    goto out;	ret = krb5_crypto_init(context, key, 0, &crypto);	krb5_free_keyblock (context, key);	if (ret)	    goto out;    }    ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT, 				     buf.data, buf.length, 0,				     &rep.innerRep);        ASN1_MALLOC_ENCODE(DigestREP, reply->data, reply->length, &rep, &size, ret);    if (ret) {	krb5_set_error_string(context, "Failed to encode digest reply");	goto out;    }    if (size != reply->length)	krb5_abortx(context, "ASN1 internal error");    out:    if (ac)	krb5_auth_con_free(context, ac);    if (ret)	krb5_warn(context, ret, "Digest request from %s failed", from);    if (ticket)	krb5_free_ticket(context, ticket);    if (id)	krb5_kt_close(context, id);    if (crypto)	krb5_crypto_destroy(context, crypto);    if (sp)	krb5_storage_free(sp);    if (user)	_kdc_free_ent (context, user);    if (server)	_kdc_free_ent (context, server);    if (client)	_kdc_free_ent (context, client);    if (password) {	memset(password, 0, strlen(password));	free (password);    }    if (client_name)	free (client_name);    krb5_data_free(&buf);    krb5_data_free(&serverNonce);    free_DigestREP(&rep);    free_DigestRepInner(&r);    free_DigestReqInner(&ireq);    return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -