コード例 #1
0
ファイル: kdc-heimdal.c プロジェクト: DavidMulder/samba
static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg,
				 struct kdc_check_generic_kerberos *r)
{
	struct PAC_Validate pac_validate;
	DATA_BLOB srv_sig;
	struct PAC_SIGNATURE_DATA kdc_sig;
	struct kdc_server *kdc = talloc_get_type(msg->private_data, struct kdc_server);
	krb5_kdc_configuration *kdc_config =
		(krb5_kdc_configuration *)kdc->private_data;
	enum ndr_err_code ndr_err;
	int ret;
	hdb_entry_ex ent;
	krb5_principal principal;


	/* There is no reply to this request */
	r->out.generic_reply = data_blob(NULL, 0);

	ndr_err = ndr_pull_struct_blob(&r->in.generic_request, msg, &pac_validate,
				       (ndr_pull_flags_fn_t)ndr_pull_PAC_Validate);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pac_validate.MessageType != NETLOGON_GENERIC_KRB5_PAC_VALIDATE) {
		/* We don't implement any other message types - such as certificate validation - yet */
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength)
	    || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength
	    || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	srv_sig = data_blob_const(pac_validate.ChecksumAndSignature.data,
				  pac_validate.ChecksumLength);

	ret = krb5_make_principal(kdc->smb_krb5_context->krb5_context, &principal,
				  lpcfg_realm(kdc->task->lp_ctx),
				  "krbtgt", lpcfg_realm(kdc->task->lp_ctx),
				  NULL);

	if (ret != 0) {
		return NT_STATUS_NO_MEMORY;
	}

	ret = kdc_config->db[0]->hdb_fetch_kvno(kdc->smb_krb5_context->krb5_context,
						 kdc_config->db[0],
						 principal,
						 HDB_F_GET_KRBTGT | HDB_F_DECRYPT,
						 0,
						 &ent);

	if (ret != 0) {
		hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
		krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);

		return NT_STATUS_LOGON_FAILURE;
	}

	kdc_sig.type = pac_validate.SignatureType;
	kdc_sig.signature = data_blob_const(&pac_validate.ChecksumAndSignature.data[pac_validate.ChecksumLength],
					    pac_validate.SignatureLength);

	ret = kdc_check_pac(kdc->smb_krb5_context->krb5_context, srv_sig, &kdc_sig, &ent);

	hdb_free_entry(kdc->smb_krb5_context->krb5_context, &ent);
	krb5_free_principal(kdc->smb_krb5_context->krb5_context, principal);

	if (ret != 0) {
		return NT_STATUS_LOGON_FAILURE;
	}

	return NT_STATUS_OK;
}
コード例 #2
0
ファイル: wdc-samba4.c プロジェクト: AIdrifter/samba
static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
					   const krb5_principal client_principal,
					   const krb5_principal delegated_proxy_principal,
					   struct hdb_entry_ex *client,
					   struct hdb_entry_ex *server,
					   struct hdb_entry_ex *krbtgt,
					   krb5_pac *pac)
{
	struct samba_kdc_entry *p = talloc_get_type(server->ctx, struct samba_kdc_entry);
	TALLOC_CTX *mem_ctx = talloc_named(p, 0, "samba_kdc_reget_pac context");
	DATA_BLOB *pac_blob;
	DATA_BLOB *deleg_blob = NULL;
	krb5_error_code ret;
	NTSTATUS nt_status;
	struct PAC_SIGNATURE_DATA *pac_srv_sig;
	struct PAC_SIGNATURE_DATA *pac_kdc_sig;
	bool is_in_db, is_untrusted;

	if (!mem_ctx) {
		return ENOMEM;
	}

	/* The user account may be set not to want the PAC */
	if (!samba_princ_needs_pac(server)) {
		talloc_free(mem_ctx);
		return EINVAL;
	}

	/* If the krbtgt was generated by an RODC, and we are not that
	 * RODC, then we need to regenerate the PAC - we can't trust
	 * it */
	ret = samba_krbtgt_is_in_db(krbtgt, &is_in_db, &is_untrusted);
	if (ret != 0) {
		talloc_free(mem_ctx);
		return ret;
	}

	if (is_untrusted) {
		if (client == NULL) {
			return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
		}
		nt_status = samba_kdc_get_pac_blob(mem_ctx, client, &pac_blob);
		if (!NT_STATUS_IS_OK(nt_status)) {
			talloc_free(mem_ctx);
			return EINVAL;
		}
	} else {
		pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
		if (!pac_blob) {
			talloc_free(mem_ctx);
			return ENOMEM;
		}

		pac_srv_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA);
		if (!pac_srv_sig) {
			talloc_free(mem_ctx);
			return ENOMEM;
		}

		pac_kdc_sig = talloc_zero(mem_ctx, struct PAC_SIGNATURE_DATA);
		if (!pac_kdc_sig) {
			talloc_free(mem_ctx);
			return ENOMEM;
		}

		nt_status = samba_kdc_update_pac_blob(mem_ctx, context,
						      *pac, pac_blob,
						      pac_srv_sig, pac_kdc_sig);
		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(0, ("Building PAC failed: %s\n",
				  nt_errstr(nt_status)));
			talloc_free(mem_ctx);
			return EINVAL;
		}
		
		if (is_in_db) {
			/* Now check the KDC signature, fetching the correct key based on the enc type */
			ret = kdc_check_pac(context, pac_srv_sig->signature, pac_kdc_sig, krbtgt);
			if (ret != 0) {
				DEBUG(1, ("PAC KDC signature failed to verify\n"));
				talloc_free(mem_ctx);
				return ret;
			}
		}
	}

	if (delegated_proxy_principal) {
		deleg_blob = talloc_zero(mem_ctx, DATA_BLOB);
		if (!deleg_blob) {
			talloc_free(mem_ctx);
			return ENOMEM;
		}

		nt_status = samba_kdc_update_delegation_info_blob(mem_ctx,
					context, *pac,
					server->entry.principal,
					delegated_proxy_principal,
					deleg_blob);
		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(0, ("Building PAC failed: %s\n",
				  nt_errstr(nt_status)));
			talloc_free(mem_ctx);
			return EINVAL;
		}
	}

	/* We now completely regenerate this pac */
	krb5_pac_free(context, *pac);

	ret = samba_make_krb5_pac(context, pac_blob, deleg_blob, pac);

	talloc_free(mem_ctx);
	return ret;
}