summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c
diff options
context:
space:
mode:
Diffstat (limited to 'winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c')
-rw-r--r--winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c b/winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c
new file mode 100644
index 0000000..8e01b55
--- /dev/null
+++ b/winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c
@@ -0,0 +1,215 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Kerberos Auth Protocol
+ *
+ * Copyright 2022 Isaac Klein <fifthdegree@protonmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WITH_KRB5_HEIMDAL
+#error "This file must ony be included with HEIMDAL kerberos"
+#endif
+
+#include <winpr/endian.h>
+#include <winpr/wlog.h>
+#include <winpr/assert.h>
+#include "krb5glue.h"
+
+void krb5glue_keys_free(krb5_context ctx, struct krb5glue_keyset* keyset)
+{
+ if (!ctx || !keyset)
+ return;
+ if (keyset->session_key)
+ krb5_crypto_destroy(ctx, keyset->session_key);
+ if (keyset->initiator_key)
+ krb5_crypto_destroy(ctx, keyset->initiator_key);
+ if (keyset->acceptor_key)
+ krb5_crypto_destroy(ctx, keyset->acceptor_key);
+}
+
+krb5_error_code krb5glue_update_keyset(krb5_context ctx, krb5_auth_context auth_ctx, BOOL acceptor,
+ struct krb5glue_keyset* keyset)
+{
+ krb5_keyblock* keyblock = NULL;
+ krb5_error_code rv = 0;
+
+ WINPR_ASSERT(ctx);
+ WINPR_ASSERT(auth_ctx);
+ WINPR_ASSERT(keyset);
+
+ krb5glue_keys_free(ctx, keyset);
+
+ if (!(rv = krb5_auth_con_getkey(ctx, auth_ctx, &keyblock)))
+ {
+ krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->session_key);
+ krb5_free_keyblock(ctx, keyblock);
+ keyblock = NULL;
+ }
+
+ if (acceptor)
+ rv = krb5_auth_con_getremotesubkey(ctx, auth_ctx, &keyblock);
+ else
+ rv = krb5_auth_con_getlocalsubkey(ctx, auth_ctx, &keyblock);
+
+ if (!rv && keyblock)
+ {
+ krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->initiator_key);
+ krb5_free_keyblock(ctx, keyblock);
+ keyblock = NULL;
+ }
+
+ if (acceptor)
+ rv = krb5_auth_con_getlocalsubkey(ctx, auth_ctx, &keyblock);
+ else
+ rv = krb5_auth_con_getremotesubkey(ctx, auth_ctx, &keyblock);
+
+ if (!rv && keyblock)
+ {
+ krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->acceptor_key);
+ krb5_free_keyblock(ctx, keyblock);
+ }
+
+ return rv;
+}
+
+krb5_error_code krb5glue_verify_checksum_iov(krb5_context ctx, krb5glue_key key, unsigned usage,
+ krb5_crypto_iov* iov, unsigned int iov_size,
+ krb5_boolean* is_valid)
+{
+ krb5_error_code rv = 0;
+
+ WINPR_ASSERT(ctx);
+ WINPR_ASSERT(key);
+ WINPR_ASSERT(is_valid);
+
+ rv = krb5_verify_checksum_iov(ctx, key, usage, iov, iov_size, NULL);
+ *is_valid = (rv == 0);
+ return rv;
+}
+
+krb5_error_code krb5glue_crypto_length(krb5_context ctx, krb5glue_key key, int type,
+ unsigned int* size)
+{
+ krb5_error_code rv = 0;
+ size_t s = 0;
+
+ WINPR_ASSERT(ctx);
+ WINPR_ASSERT(key);
+ WINPR_ASSERT(size);
+
+ rv = krb5_crypto_length(ctx, key, type, &s);
+ *size = (UINT)s;
+ return rv;
+}
+
+krb5_error_code krb5glue_log_error(krb5_context ctx, krb5_data* msg, const char* tag)
+{
+ krb5_error error = { 0 };
+ krb5_error_code rv = 0;
+
+ WINPR_ASSERT(ctx);
+ WINPR_ASSERT(msg);
+ WINPR_ASSERT(tag);
+
+ if (!(rv = krb5_rd_error(ctx, msg, &error)))
+ {
+ WLog_ERR(tag, "KRB_ERROR: %" PRIx32, error.error_code);
+ krb5_free_error_contents(ctx, &error);
+ }
+ return rv;
+}
+
+BOOL krb5glue_authenticator_validate_chksum(krb5glue_authenticator authenticator, int cksumtype,
+ uint32_t* flags)
+{
+ WINPR_ASSERT(flags);
+
+ if (!authenticator || !authenticator->cksum || authenticator->cksum->cksumtype != cksumtype ||
+ authenticator->cksum->checksum.length < 24)
+ return FALSE;
+
+ const BYTE* data = authenticator->cksum->checksum.data;
+ Data_Read_UINT32((data + 20), (*flags));
+ return TRUE;
+}
+
+krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ, krb5_ccache ccache,
+ krb5_prompter_fct prompter, char* password,
+ SEC_WINPR_KERBEROS_SETTINGS* krb_settings)
+{
+ krb5_error_code rv = 0;
+ krb5_deltat start_time = 0;
+ krb5_get_init_creds_opt* gic_opt = NULL;
+ krb5_init_creds_context creds_ctx = NULL;
+ krb5_creds creds = { 0 };
+
+ WINPR_ASSERT(ctx);
+
+ do
+ {
+ if ((rv = krb5_get_init_creds_opt_alloc(ctx, &gic_opt)) != 0)
+ break;
+
+ krb5_get_init_creds_opt_set_forwardable(gic_opt, 0);
+ krb5_get_init_creds_opt_set_proxiable(gic_opt, 0);
+
+ if (krb_settings)
+ {
+ if (krb_settings->startTime)
+ start_time = krb_settings->startTime;
+ if (krb_settings->lifeTime)
+ krb5_get_init_creds_opt_set_tkt_life(gic_opt, krb_settings->lifeTime);
+ if (krb_settings->renewLifeTime)
+ krb5_get_init_creds_opt_set_renew_life(gic_opt, krb_settings->renewLifeTime);
+ if (krb_settings->withPac)
+ krb5_get_init_creds_opt_set_pac_request(ctx, gic_opt, TRUE);
+ if (krb_settings->pkinitX509Anchors || krb_settings->pkinitX509Identity)
+ {
+ if ((rv = krb5_get_init_creds_opt_set_pkinit(
+ ctx, gic_opt, princ, krb_settings->pkinitX509Identity,
+ krb_settings->pkinitX509Anchors, NULL, NULL, 0, prompter, password,
+ password)) != 0)
+ break;
+ }
+ }
+
+ if ((rv = krb5_init_creds_init(ctx, princ, prompter, password, start_time, gic_opt,
+ &creds_ctx)) != 0)
+ break;
+ if ((rv = krb5_init_creds_set_password(ctx, creds_ctx, password)) != 0)
+ break;
+ if (krb_settings && krb_settings->armorCache)
+ {
+ krb5_ccache armor_cc = NULL;
+ if ((rv = krb5_cc_resolve(ctx, krb_settings->armorCache, &armor_cc)) != 0)
+ break;
+ if ((rv = krb5_init_creds_set_fast_ccache(ctx, creds_ctx, armor_cc)) != 0)
+ break;
+ krb5_cc_close(ctx, armor_cc);
+ }
+ if ((rv = krb5_init_creds_get(ctx, creds_ctx)) != 0)
+ break;
+ if ((rv = krb5_init_creds_get_creds(ctx, creds_ctx, &creds)) != 0)
+ break;
+ if ((rv = krb5_cc_store_cred(ctx, ccache, &creds)) != 0)
+ break;
+ } while (0);
+
+ krb5_free_cred_contents(ctx, &creds);
+ krb5_init_creds_free(ctx, creds_ctx);
+ krb5_get_init_creds_opt_free(ctx, gic_opt);
+
+ return rv;
+}
+