Exemple #1
0
static int mit_samba_update_pac_data(struct mit_samba_context *ctx,
				     hdb_entry_ex *client,
				     DATA_BLOB *pac_data,
				     DATA_BLOB *logon_data)
{
	TALLOC_CTX *tmp_ctx;
	DATA_BLOB *logon_blob;
	krb5_error_code code;
	NTSTATUS nt_status;
	krb5_pac pac = NULL;
	int ret;

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

	tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac_data context");
	if (!tmp_ctx) {
		return ENOMEM;
	}

	logon_blob = talloc_zero(tmp_ctx, DATA_BLOB);
	if (!logon_blob) {
		ret = ENOMEM;
		goto done;
	}

	code = krb5_pac_parse(ctx->context,
			      pac_data->data, pac_data->length, &pac);
	if (code) {
		ret = EINVAL;
		goto done;
	}

	nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context,
					      &pac, logon_blob);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0, ("Building PAC failed: %s\n",
			  nt_errstr(nt_status)));
		ret = EINVAL;
		goto done;
	}

	logon_data->data = (uint8_t *)malloc(logon_blob->length);
	if (!logon_data->data) {
		ret = ENOMEM;
		goto done;
	}
	memcpy(logon_data->data, logon_blob->data, logon_blob->length);
	logon_data->length = logon_blob->length;

	ret = 0;

done:
	if (pac) krb5_pac_free(ctx->context, pac);
	talloc_free(tmp_ctx);
	return ret;
}
Exemple #2
0
static krb5_error_code samba_wdc_reget_pac(void *priv, krb5_context context,
					   const krb5_principal client_principal,
					   struct hdb_entry_ex *client,
					   struct hdb_entry_ex *server, 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;
	krb5_error_code ret;
	NTSTATUS nt_status;

	if (!mem_ctx) {
		return ENOMEM;
	}

	pac_blob = talloc_zero(mem_ctx, DATA_BLOB);
	if (!pac_blob) {
		talloc_free(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;
	}

	nt_status = samba_kdc_update_pac_blob(mem_ctx, context,
					      p->kdc_db_ctx->ic_ctx,
					      pac, pac_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 completly regenerate this pac */
	krb5_pac_free(context, *pac);

	ret = samba_make_krb5_pac(context, pac_blob, pac);

	talloc_free(mem_ctx);
	return ret;
}
Exemple #3
0
static int mit_samba_update_pac_data(struct mit_samba_context *ctx,
				     hdb_entry_ex *client,
				     DATA_BLOB *pac_data,
				     DATA_BLOB *logon_data)
{
	TALLOC_CTX *tmp_ctx;
	DATA_BLOB *logon_blob;
	krb5_error_code code;
	NTSTATUS nt_status;
	krb5_pac pac = NULL;
	int ret;
	struct samba_kdc_entry *skdc_entry = NULL;

	if (client) {
		skdc_entry = talloc_get_type_abort(client->ctx,
						   struct samba_kdc_entry);
	}

	/* The user account may be set not to want the PAC */
	if (client && !samba_princ_needs_pac(skdc_entry)) {
		return EINVAL;
	}

	tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac_data context");
	if (!tmp_ctx) {
		return ENOMEM;
	}

	logon_blob = talloc_zero(tmp_ctx, DATA_BLOB);
	if (!logon_blob) {
		ret = ENOMEM;
		goto done;
	}

	code = krb5_pac_parse(ctx->context,
			      pac_data->data, pac_data->length, &pac);
	if (code) {
		ret = EINVAL;
		goto done;
	}

	/* TODO: An implementation-specific decision will need to be
	 * made as to when to check the KDC pac signature, and how to
	 * untrust untrusted RODCs */
	nt_status = samba_kdc_update_pac_blob(tmp_ctx, ctx->context,
					      pac, logon_blob, NULL, NULL);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0, ("Building PAC failed: %s\n",
			  nt_errstr(nt_status)));
		ret = EINVAL;
		goto done;
	}

	logon_data->data = (uint8_t *)malloc(logon_blob->length);
	if (!logon_data->data) {
		ret = ENOMEM;
		goto done;
	}
	memcpy(logon_data->data, logon_blob->data, logon_blob->length);
	logon_data->length = logon_blob->length;

	ret = 0;

done:
	if (pac) krb5_pac_free(ctx->context, pac);
	talloc_free(tmp_ctx);
	return ret;
}
Exemple #4
0
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;
}