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

📄 digest.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	hex_encode(buf.data, buf.length, &r.u.initReply.opaque);	free(buf.data);	if (r.u.initReply.opaque == NULL) {	    krb5_clear_error_string(context);	    ret = ENOMEM;	    goto out;	}	kdc_log(context, config, 0, "Digest %s init request successful from %s",		ireq.u.init.type, from);	break;    }    case choice_DigestReqInner_digestRequest: {	sp = krb5_storage_emem();	if (sp == NULL) {	    ret = ENOMEM;	    krb5_set_error_string(context, "out of memory");	    goto out;	}	ret = krb5_store_stringz(sp, ireq.u.digestRequest.type);	if (ret) {	    krb5_clear_error_string(context);	    goto out;	}	krb5_store_stringz(sp, ireq.u.digestRequest.serverNonce);	if (ireq.u.digestRequest.hostname) {	    ret = krb5_store_stringz(sp, *ireq.u.digestRequest.hostname);	    if (ret) {		krb5_clear_error_string(context);		goto out;	    }	}	buf.length = strlen(ireq.u.digestRequest.opaque);	buf.data = malloc(buf.length);	if (buf.data == NULL) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	ret = hex_decode(ireq.u.digestRequest.opaque, buf.data, buf.length);	if (ret <= 0) {	    krb5_set_error_string(context, "Failed to decode opaque");	    ret = ENOMEM;	    goto out;	}	buf.length = ret;	ret = decode_Checksum(buf.data, buf.length, &res, NULL);	free(buf.data);	if (ret) {	    krb5_set_error_string(context, "Failed to decode digest Checksum");	    goto out;	}		ret = krb5_storage_to_data(sp, &buf);	if (ret) {	    krb5_clear_error_string(context);	    goto out;	}	serverNonce.length = strlen(ireq.u.digestRequest.serverNonce);	serverNonce.data = malloc(serverNonce.length);	if (serverNonce.data == NULL) {	    krb5_set_error_string(context, "out of memory");	    ret = ENOMEM;	    goto out;	}	    	/*	 * CHAP does the checksum of the raw nonce, but do it for all	 * types, since we need to check the timestamp.	 */	{	    ssize_t ssize;	    	    ssize = hex_decode(ireq.u.digestRequest.serverNonce, 			       serverNonce.data, serverNonce.length);	    if (ssize <= 0) {		krb5_set_error_string(context, "Failed to decode serverNonce");		ret = ENOMEM;		goto out;	    }	    serverNonce.length = ssize;	}	ret = get_digest_key(context, config, server, &crypto);	if (ret)	    goto out;	ret = krb5_verify_checksum(context, crypto, 				   KRB5_KU_DIGEST_OPAQUE,				   buf.data, buf.length, &res);	krb5_crypto_destroy(context, crypto);	crypto = NULL;	if (ret)	    goto out;	/* verify time */	{	    unsigned char *p = serverNonce.data;	    uint32_t t;	    	    if (serverNonce.length < 4) {		krb5_set_error_string(context, "server nonce too short");		ret = EINVAL;		goto out;	    }	    t = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);	    if (abs((kdc_time & 0xffffffff) - t) > context->max_skew) {		krb5_set_error_string(context, "time screw in server nonce ");		ret = EINVAL;		goto out;	    }	}	if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) {	    MD5_CTX ctx;	    unsigned char md[MD5_DIGEST_LENGTH];	    char *mdx;	    char id;	    if ((config->digests_allowed & CHAP_MD5) == 0) {		kdc_log(context, config, 0, "Digest CHAP MD5 not allowed");		goto out;	    }	    if (ireq.u.digestRequest.identifier == NULL) {		krb5_set_error_string(context, "Identifier missing "				      "from CHAP request");		ret = EINVAL;		goto out;	    }	    	    if (hex_decode(*ireq.u.digestRequest.identifier, &id, 1) != 1) {		krb5_set_error_string(context, "failed to decode identifier");		ret = EINVAL;		goto out;	    }	    	    ret = get_password_entry(context, config, 				     ireq.u.digestRequest.username,				     &password);	    if (ret)		goto out;	    MD5_Init(&ctx);	    MD5_Update(&ctx, &id, 1);	    MD5_Update(&ctx, password, strlen(password));	    MD5_Update(&ctx, serverNonce.data, serverNonce.length);	    MD5_Final(md, &ctx);	    hex_encode(md, sizeof(md), &mdx);	    if (mdx == NULL) {		krb5_clear_error_string(context);		ret = ENOMEM;		goto out;	    }	    r.element = choice_DigestRepInner_response;	    ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);	    free(mdx);	    if (ret == 0) {		r.u.response.success = TRUE;	    } else {		kdc_log(context, config, 0, 			"CHAP reply mismatch for %s",			ireq.u.digestRequest.username);		r.u.response.success = FALSE;	    }	} else if (strcasecmp(ireq.u.digestRequest.type, "SASL-DIGEST-MD5") == 0) {	    MD5_CTX ctx;	    unsigned char md[MD5_DIGEST_LENGTH];	    char *mdx;	    char *A1, *A2;	    if ((config->digests_allowed & DIGEST_MD5) == 0) {		kdc_log(context, config, 0, "Digest SASL MD5 not allowed");		goto out;	    }	    if (ireq.u.digestRequest.nonceCount == NULL) 		goto out;	    if (ireq.u.digestRequest.clientNonce == NULL) 		goto out;	    if (ireq.u.digestRequest.qop == NULL) 		goto out;	    if (ireq.u.digestRequest.realm == NULL) 		goto out;	    	    ret = get_password_entry(context, config, 				     ireq.u.digestRequest.username,				     &password);	    if (ret)		goto failed;	    MD5_Init(&ctx);	    MD5_Update(&ctx, ireq.u.digestRequest.username,		       strlen(ireq.u.digestRequest.username));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, *ireq.u.digestRequest.realm,		       strlen(*ireq.u.digestRequest.realm));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, password, strlen(password));	    MD5_Final(md, &ctx);	    	    MD5_Init(&ctx);	    MD5_Update(&ctx, md, sizeof(md));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, ireq.u.digestRequest.serverNonce,		       strlen(ireq.u.digestRequest.serverNonce));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, *ireq.u.digestRequest.nonceCount,		       strlen(*ireq.u.digestRequest.nonceCount));	    if (ireq.u.digestRequest.authid) {		MD5_Update(&ctx, ":", 1);		MD5_Update(&ctx, *ireq.u.digestRequest.authid,			   strlen(*ireq.u.digestRequest.authid));	    }	    MD5_Final(md, &ctx);	    hex_encode(md, sizeof(md), &A1);	    if (A1 == NULL) {		krb5_set_error_string(context, "out of memory");		ret = ENOMEM;		goto failed;	    }	    	    MD5_Init(&ctx);	    MD5_Update(&ctx, "AUTHENTICATE:", sizeof("AUTHENTICATE:") - 1);	    MD5_Update(&ctx, *ireq.u.digestRequest.uri,		       strlen(*ireq.u.digestRequest.uri));		    /* conf|int */	    if (strcmp(ireq.u.digestRequest.digest, "clear") != 0) {		static char conf_zeros[] = ":00000000000000000000000000000000";		MD5_Update(&ctx, conf_zeros, sizeof(conf_zeros) - 1);	    }	    	    MD5_Final(md, &ctx);	    hex_encode(md, sizeof(md), &A2);	    if (A2 == NULL) {		krb5_set_error_string(context, "out of memory");		ret = ENOMEM;		free(A1);		goto failed;	    }	    MD5_Init(&ctx);	    MD5_Update(&ctx, A1, strlen(A2));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, ireq.u.digestRequest.serverNonce,		       strlen(ireq.u.digestRequest.serverNonce));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, *ireq.u.digestRequest.nonceCount,		       strlen(*ireq.u.digestRequest.nonceCount));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, *ireq.u.digestRequest.clientNonce,		       strlen(*ireq.u.digestRequest.clientNonce));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, *ireq.u.digestRequest.qop,		       strlen(*ireq.u.digestRequest.qop));	    MD5_Update(&ctx, ":", 1);	    MD5_Update(&ctx, A2, strlen(A2));	    MD5_Final(md, &ctx);	    free(A1);	    free(A2);	    hex_encode(md, sizeof(md), &mdx);	    if (mdx == NULL) {		krb5_clear_error_string(context);		ret = ENOMEM;		goto out;	    }	    r.element = choice_DigestRepInner_response;	    ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);	    free(mdx);	    if (ret == 0) {		r.u.response.success = TRUE;	    } else {		kdc_log(context, config, 0, 			"DIGEST-MD5 reply mismatch for %s",			ireq.u.digestRequest.username);		r.u.response.success = FALSE;	    }	} else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) {	    unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];	    krb5_principal clientprincipal = NULL;	    char *mdx;	    const char *username;	    struct ntlm_buf answer;	    Key *key = NULL;	    SHA_CTX ctx;	    if ((config->digests_allowed & MS_CHAP_V2) == 0) {		kdc_log(context, config, 0, "MS-CHAP-V2 not allowed");		goto failed;	    }	    if (ireq.u.digestRequest.clientNonce == NULL)  {		krb5_set_error_string(context, 				      "MS-CHAP-V2 clientNonce missing");		ret = EINVAL;		goto failed;	    }	    	    if (serverNonce.length != 16) {		krb5_set_error_string(context, 				      "MS-CHAP-V2 serverNonce wrong length");		ret = EINVAL;		goto failed;	    }	    /* strip of the domain component */	    username = strchr(ireq.u.digestRequest.username, '\\');	    if (username == NULL)		username = ireq.u.digestRequest.username;	    else		username++;	    /* ChallangeHash */	    SHA1_Init(&ctx);	    {		ssize_t ssize;		krb5_data clientNonce;				clientNonce.length = strlen(*ireq.u.digestRequest.clientNonce);		clientNonce.data = malloc(clientNonce.length);		if (clientNonce.data == NULL) {		    ret = ENOMEM;		    krb5_set_error_string(context, "out of memory");		    goto out;		}		ssize = hex_decode(*ireq.u.digestRequest.clientNonce, 				   clientNonce.data, clientNonce.length);		if (ssize != 16) {		    krb5_set_error_string(context, 					  "Failed to decode clientNonce");		    ret = ENOMEM;		    goto out;		}		SHA1_Update(&ctx, clientNonce.data, ssize);		free(clientNonce.data);	    }	    SHA1_Update(&ctx, serverNonce.data, serverNonce.length);	    SHA1_Update(&ctx, username, strlen(username));	    SHA1_Final(challange, &ctx);	    /* NtPasswordHash */	    ret = krb5_parse_name(context, 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, 				      "MS-CHAP-V2 user %s not in database",				      username);		goto failed;	    }	    ret = hdb_enctype2key(context, &user->entry, 				  ETYPE_ARCFOUR_HMAC_MD5, &key);	    if (ret) {		krb5_set_error_string(context, 				      "MS-CHAP-V2 missing arcfour key %s",				      username);		goto failed;	    }	    /* ChallengeResponse */	    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;	    }	    	    hex_encode(answer.data, answer.length, &mdx);	    if (mdx == NULL) {		free(answer.data);		krb5_clear_error_string(context);		ret = ENOMEM;		goto out;	    }	    r.element = choice_DigestRepInner_response;	    ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);	    if (ret == 0) {		r.u.response.success = TRUE;	    } else {		kdc_log(context, config, 0, 			"MS-CHAP-V2 hash mismatch for %s",			ireq.u.digestRequest.username);		r.u.response.success = FALSE;	    }	    free(mdx);	    if (r.u.response.success) {		unsigned char hashhash[MD4_DIGEST_LENGTH];		/* hashhash */		{		    MD4_CTX hctx;		    MD4_Init(&hctx);		    MD4_Update(&hctx, key->key.keyvalue.data, 			       key->key.keyvalue.length);		    MD4_Final(hashhash, &hctx);		}		/* GenerateAuthenticatorResponse */		SHA1_Init(&ctx);		SHA1_Update(&ctx, hashhash, sizeof(hashhash));		SHA1_Update(&ctx, answer.data, answer.length);		SHA1_Update(&ctx, ms_chap_v2_magic1,sizeof(ms_chap_v2_magic1));		SHA1_Final(md, &ctx);		SHA1_Init(&ctx);		SHA1_Update(&ctx, md, sizeof(md));		SHA1_Update(&ctx, challange, 8);		SHA1_Update(&ctx, ms_chap_v2_magic2, sizeof(ms_chap_v2_magic2));		SHA1_Final(md, &ctx);		r.u.response.rsp = calloc(1, sizeof(*r.u.response.rsp));		if (r.u.response.rsp == NULL) {		    free(answer.data);		    krb5_clear_error_string(context);		    ret = ENOMEM;		    goto out;		}		hex_encode(md, sizeof(md), r.u.response.rsp);		if (r.u.response.rsp == NULL) {		    free(answer.data);		    krb5_clear_error_string(context);		    ret = ENOMEM;		    goto out;		}		/* get_master, rfc 3079 3.4 */		SHA1_Init(&ctx);		SHA1_Update(&ctx, hashhash, 16); /* md4(hash) */		SHA1_Update(&ctx, answer.data, answer.length);		SHA1_Update(&ctx, ms_rfc3079_magic1, sizeof(ms_rfc3079_magic1));		SHA1_Final(md, &ctx);		free(answer.data);		r.u.response.session_key = 		    calloc(1, sizeof(*r.u.response.session_key));		if (r.u.response.session_key == NULL) {		    krb5_clear_error_string(context);		    ret = ENOMEM;		    goto out;		}		ret = krb5_data_copy(r.u.response.session_key, md, 16);		if (ret) {		    krb5_clear_error_string(context);		    goto out;		}	    }	} else {	    r.element = choice_DigestRepInner_error;	    asprintf(&r.u.error.reason, "Unsupported digest type %s", 		     ireq.u.digestRequest.type);	    if (r.u.error.reason == NULL) {		krb5_set_error_string(context, "out of memory");		ret = ENOMEM;		goto out;

⌨️ 快捷键说明

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