Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
2464
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/kerberos.c
vendored
Normal file
2464
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/kerberos.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/kerberos.h
vendored
Normal file
39
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/kerberos.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Client
|
||||
* Kerberos Auth Protocol
|
||||
*
|
||||
* Copyright 2015 ANSSI, Author Thomas Calderon
|
||||
* Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.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 WINPR_SSPI_KERBEROS_PRIVATE_H
|
||||
#define WINPR_SSPI_KERBEROS_PRIVATE_H
|
||||
|
||||
#include <winpr/sspi.h>
|
||||
#include <winpr/windows.h>
|
||||
|
||||
#include "../sspi.h"
|
||||
#include "../../log.h"
|
||||
|
||||
typedef struct s_KRB_CONTEXT KRB_CONTEXT;
|
||||
|
||||
extern const SecPkgInfoA KERBEROS_SecPkgInfoA;
|
||||
extern const SecPkgInfoW KERBEROS_SecPkgInfoW;
|
||||
extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA;
|
||||
extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW;
|
||||
|
||||
BOOL KERBEROS_init(void);
|
||||
|
||||
#endif /* WINPR_SSPI_KERBEROS_PRIVATE_H */
|
||||
108
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/krb5glue.h
vendored
Normal file
108
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/krb5glue.h
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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 WINPR_SSPI_KERBEROS_GLUE_PRIVATE_H
|
||||
#define WINPR_SSPI_KERBEROS_GLUE_PRIVATE_H
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/sspi.h>
|
||||
|
||||
#include <krb5.h>
|
||||
|
||||
#if defined(WITH_KRB5_MIT)
|
||||
typedef krb5_key krb5glue_key;
|
||||
typedef krb5_authenticator* krb5glue_authenticator;
|
||||
|
||||
#define krb5glue_free_authenticator(ctx, auth) krb5_free_authenticator((ctx), (auth))
|
||||
|
||||
#define krb5glue_crypto_length(ctx, key, type, size) \
|
||||
krb5_c_crypto_length(ctx, krb5_k_key_enctype(ctx, key), type, size)
|
||||
#define krb5glue_crypto_length_iov(ctx, key, iov, size) \
|
||||
krb5_c_crypto_length_iov(ctx, krb5_k_key_enctype(ctx, key), iov, size)
|
||||
#define krb5glue_encrypt_iov(ctx, key, usage, iov, size) \
|
||||
krb5_k_encrypt_iov(ctx, key, usage, nullptr, iov, size)
|
||||
#define krb5glue_decrypt_iov(ctx, key, usage, iov, size) \
|
||||
krb5_k_decrypt_iov(ctx, key, usage, nullptr, iov, size)
|
||||
#define krb5glue_make_checksum_iov(ctx, key, usage, iov, size) \
|
||||
krb5_k_make_checksum_iov(ctx, 0, key, usage, iov, size)
|
||||
#define krb5glue_verify_checksum_iov(ctx, key, usage, iov, size, is_valid) \
|
||||
krb5_k_verify_checksum_iov(ctx, 0, key, usage, iov, size, is_valid)
|
||||
#define krb5glue_auth_con_set_cksumtype(ctx, auth_ctx, cksumtype) \
|
||||
krb5_auth_con_set_req_cksumtype(ctx, auth_ctx, cksumtype)
|
||||
#define krb5glue_set_principal_realm(ctx, principal, realm) \
|
||||
krb5_set_principal_realm(ctx, principal, realm)
|
||||
#define krb5glue_free_keytab_entry_contents(ctx, entry) krb5_free_keytab_entry_contents(ctx, entry)
|
||||
#define krb5glue_auth_con_setuseruserkey(ctx, auth_ctx, keytab) \
|
||||
krb5_auth_con_setuseruserkey(ctx, auth_ctx, keytab)
|
||||
#define krb5glue_free_data_contents(ctx, data) krb5_free_data_contents(ctx, data)
|
||||
krb5_prompt_type krb5glue_get_prompt_type(krb5_context ctx, krb5_prompt prompts[], int index);
|
||||
|
||||
#define krb5glue_creds_getkey(creds) creds.keyblock
|
||||
|
||||
#elif defined(WITH_KRB5_HEIMDAL)
|
||||
typedef krb5_crypto krb5glue_key;
|
||||
typedef krb5_authenticator krb5glue_authenticator;
|
||||
|
||||
#define krb5glue_free_authenticator(ctx, auth) krb5_free_authenticator((ctx), &(auth))
|
||||
|
||||
krb5_error_code krb5glue_crypto_length(krb5_context ctx, krb5glue_key key, int type,
|
||||
unsigned int* size);
|
||||
#define krb5glue_crypto_length_iov(ctx, key, iov, size) krb5_crypto_length_iov(ctx, key, iov, size)
|
||||
#define krb5glue_encrypt_iov(ctx, key, usage, iov, size) \
|
||||
krb5_encrypt_iov_ivec(ctx, key, usage, iov, size, nullptr)
|
||||
#define krb5glue_decrypt_iov(ctx, key, usage, iov, size) \
|
||||
krb5_decrypt_iov_ivec(ctx, key, usage, iov, size, nullptr)
|
||||
#define krb5glue_make_checksum_iov(ctx, key, usage, iov, size) \
|
||||
krb5_create_checksum_iov(ctx, key, usage, iov, size, nullptr)
|
||||
krb5_error_code krb5glue_verify_checksum_iov(krb5_context ctx, krb5glue_key key,
|
||||
krb5_keyusage usage, krb5_crypto_iov* iov,
|
||||
unsigned int iov_size, krb5_boolean* is_valid);
|
||||
#define krb5glue_auth_con_set_cksumtype(ctx, auth_ctx, cksumtype) \
|
||||
krb5_auth_con_setcksumtype(ctx, auth_ctx, cksumtype)
|
||||
#define krb5glue_set_principal_realm(ctx, principal, realm) \
|
||||
krb5_principal_set_realm(ctx, principal, realm)
|
||||
#define krb5glue_free_keytab_entry_contents(ctx, entry) krb5_kt_free_entry(ctx, entry)
|
||||
#define krb5glue_auth_con_setuseruserkey(ctx, auth_ctx, keytab) \
|
||||
krb5_auth_con_setuserkey(ctx, auth_ctx, keytab)
|
||||
#define krb5glue_free_data_contents(ctx, data) krb5_data_free(data)
|
||||
#define krb5glue_get_prompt_type(ctx, prompts, index) prompts[index].type
|
||||
|
||||
#define krb5glue_creds_getkey(creds) creds.session
|
||||
#else
|
||||
#error "Missing implementation for KRB5 provider"
|
||||
#endif
|
||||
|
||||
struct krb5glue_keyset
|
||||
{
|
||||
krb5glue_key session_key;
|
||||
krb5glue_key initiator_key;
|
||||
krb5glue_key acceptor_key;
|
||||
};
|
||||
|
||||
void krb5glue_keys_free(krb5_context ctx, struct krb5glue_keyset* keyset);
|
||||
krb5_error_code krb5glue_update_keyset(krb5_context ctx, krb5_auth_context auth_ctx, BOOL acceptor,
|
||||
struct krb5glue_keyset* keyset);
|
||||
krb5_error_code krb5glue_log_error(krb5_context ctx, krb5_data* msg, const char* tag);
|
||||
BOOL krb5glue_authenticator_validate_chksum(krb5glue_authenticator authenticator, int cksumtype,
|
||||
uint32_t* flags);
|
||||
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);
|
||||
|
||||
#endif /* WINPR_SSPI_KERBEROS_GLUE_PRIVATE_H */
|
||||
216
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c
vendored
Normal file
216
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/krb5glue_heimdal.c
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* 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 only 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 = nullptr;
|
||||
krb5_error_code rv = 0;
|
||||
|
||||
WINPR_ASSERT(ctx);
|
||||
WINPR_ASSERT(auth_ctx);
|
||||
WINPR_ASSERT(keyset);
|
||||
|
||||
krb5glue_keys_free(ctx, keyset);
|
||||
|
||||
rv = krb5_auth_con_getkey(ctx, auth_ctx, &keyblock);
|
||||
if (!rv)
|
||||
{
|
||||
krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->session_key);
|
||||
krb5_free_keyblock(ctx, keyblock);
|
||||
keyblock = nullptr;
|
||||
}
|
||||
|
||||
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 = nullptr;
|
||||
}
|
||||
|
||||
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,
|
||||
krb5_keyusage 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, nullptr);
|
||||
*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 = WINPR_C_ARRAY_INIT;
|
||||
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 = nullptr;
|
||||
krb5_init_creds_context creds_ctx = nullptr;
|
||||
krb5_creds creds = WINPR_C_ARRAY_INIT;
|
||||
|
||||
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, nullptr, nullptr, 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 = nullptr;
|
||||
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;
|
||||
}
|
||||
|
||||
258
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c
vendored
Normal file
258
third_party/FreeRDP/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* 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_MIT
|
||||
#error "This file must only be included with MIT kerberos"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/endian.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <errno.h>
|
||||
#include "krb5glue.h"
|
||||
#include <profile.h>
|
||||
|
||||
static char* create_temporary_file(void)
|
||||
{
|
||||
BYTE buffer[32];
|
||||
char* hex = nullptr;
|
||||
char* path = nullptr;
|
||||
|
||||
if (winpr_RAND(buffer, sizeof(buffer)) < 0)
|
||||
return nullptr;
|
||||
hex = winpr_BinToHexString(buffer, sizeof(buffer), FALSE);
|
||||
path = GetKnownSubPath(KNOWN_PATH_TEMP, hex);
|
||||
free(hex);
|
||||
return path;
|
||||
}
|
||||
|
||||
void krb5glue_keys_free(krb5_context ctx, struct krb5glue_keyset* keyset)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
WINPR_ASSERT(keyset);
|
||||
|
||||
krb5_k_free_key(ctx, keyset->session_key);
|
||||
krb5_k_free_key(ctx, keyset->initiator_key);
|
||||
krb5_k_free_key(ctx, keyset->acceptor_key);
|
||||
}
|
||||
|
||||
krb5_error_code krb5glue_update_keyset(krb5_context ctx, krb5_auth_context auth_ctx, BOOL acceptor,
|
||||
struct krb5glue_keyset* keyset)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
WINPR_ASSERT(auth_ctx);
|
||||
WINPR_ASSERT(keyset);
|
||||
|
||||
krb5glue_keys_free(ctx, keyset);
|
||||
krb5_auth_con_getkey_k(ctx, auth_ctx, &keyset->session_key);
|
||||
if (acceptor)
|
||||
{
|
||||
krb5_auth_con_getsendsubkey_k(ctx, auth_ctx, &keyset->acceptor_key);
|
||||
krb5_auth_con_getrecvsubkey_k(ctx, auth_ctx, &keyset->initiator_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
krb5_auth_con_getsendsubkey_k(ctx, auth_ctx, &keyset->initiator_key);
|
||||
krb5_auth_con_getrecvsubkey_k(ctx, auth_ctx, &keyset->acceptor_key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
krb5_prompt_type krb5glue_get_prompt_type(krb5_context ctx, krb5_prompt prompts[], int index)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
WINPR_ASSERT(prompts);
|
||||
WINPR_UNUSED(prompts);
|
||||
|
||||
krb5_prompt_type* types = krb5_get_prompt_types(ctx);
|
||||
return types ? types[index] : 0;
|
||||
}
|
||||
|
||||
krb5_error_code krb5glue_log_error(krb5_context ctx, krb5_data* msg, const char* tag)
|
||||
{
|
||||
krb5_error* error = nullptr;
|
||||
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: %s", error->text.data);
|
||||
krb5_free_error(ctx, error);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
BOOL krb5glue_authenticator_validate_chksum(krb5glue_authenticator authenticator, int cksumtype,
|
||||
uint32_t* flags)
|
||||
{
|
||||
WINPR_ASSERT(flags);
|
||||
|
||||
if (!authenticator || !authenticator->checksum ||
|
||||
authenticator->checksum->checksum_type != cksumtype || authenticator->checksum->length < 24)
|
||||
return FALSE;
|
||||
*flags = winpr_Data_Get_UINT32((authenticator->checksum->contents + 20));
|
||||
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 = nullptr;
|
||||
krb5_init_creds_context creds_ctx = nullptr;
|
||||
char* tmp_profile_path = create_temporary_file();
|
||||
profile_t profile = nullptr;
|
||||
BOOL is_temp_ctx = FALSE;
|
||||
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
rv = krb5_get_init_creds_opt_alloc(ctx, &gic_opt);
|
||||
if (rv)
|
||||
goto cleanup;
|
||||
|
||||
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)
|
||||
{
|
||||
rv = krb5_get_init_creds_opt_set_pac_request(ctx, gic_opt, TRUE);
|
||||
if (rv)
|
||||
goto cleanup;
|
||||
}
|
||||
if (krb_settings->armorCache)
|
||||
{
|
||||
rv = krb5_get_init_creds_opt_set_fast_ccache_name(ctx, gic_opt,
|
||||
krb_settings->armorCache);
|
||||
if (rv)
|
||||
goto cleanup;
|
||||
}
|
||||
if (krb_settings->pkinitX509Identity)
|
||||
{
|
||||
rv = krb5_get_init_creds_opt_set_pa(ctx, gic_opt, "X509_user_identity",
|
||||
krb_settings->pkinitX509Identity);
|
||||
if (rv)
|
||||
goto cleanup;
|
||||
}
|
||||
if (krb_settings->pkinitX509Anchors)
|
||||
{
|
||||
rv = krb5_get_init_creds_opt_set_pa(ctx, gic_opt, "X509_anchors",
|
||||
krb_settings->pkinitX509Anchors);
|
||||
if (rv)
|
||||
goto cleanup;
|
||||
}
|
||||
if (krb_settings->kdcUrl && (strnlen(krb_settings->kdcUrl, 2) > 0))
|
||||
{
|
||||
const char* names[4] = WINPR_C_ARRAY_INIT;
|
||||
char* realm = nullptr;
|
||||
char* kdc_url = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
if ((rv = krb5_get_profile(ctx, &profile)))
|
||||
goto cleanup;
|
||||
|
||||
rv = ENOMEM;
|
||||
if (winpr_asprintf(&kdc_url, &size, "https://%s/KdcProxy", krb_settings->kdcUrl) <= 0)
|
||||
{
|
||||
free(kdc_url);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
realm = calloc(princ->realm.length + 1, 1);
|
||||
if (!realm)
|
||||
{
|
||||
free(kdc_url);
|
||||
goto cleanup;
|
||||
}
|
||||
CopyMemory(realm, princ->realm.data, princ->realm.length);
|
||||
|
||||
names[0] = "realms";
|
||||
names[1] = realm;
|
||||
names[2] = "kdc";
|
||||
|
||||
profile_clear_relation(profile, names);
|
||||
profile_add_relation(profile, names, kdc_url);
|
||||
|
||||
/* Since we know who the KDC is, tell krb5 that its certificate is valid for pkinit */
|
||||
names[2] = "pkinit_kdc_hostname";
|
||||
profile_add_relation(profile, names, krb_settings->kdcUrl);
|
||||
|
||||
free(kdc_url);
|
||||
free(realm);
|
||||
|
||||
long lrv = profile_flush_to_file(profile, tmp_profile_path);
|
||||
if (lrv)
|
||||
goto cleanup;
|
||||
|
||||
profile_abandon(profile);
|
||||
profile = nullptr;
|
||||
lrv = profile_init_path(tmp_profile_path, &profile);
|
||||
if (lrv)
|
||||
goto cleanup;
|
||||
|
||||
rv = krb5_init_context_profile(profile, 0, &ctx);
|
||||
if (rv)
|
||||
goto cleanup;
|
||||
is_temp_ctx = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rv = krb5_get_init_creds_opt_set_in_ccache(ctx, gic_opt, ccache)))
|
||||
goto cleanup;
|
||||
|
||||
if ((rv = krb5_get_init_creds_opt_set_out_ccache(ctx, gic_opt, ccache)))
|
||||
goto cleanup;
|
||||
|
||||
if ((rv =
|
||||
krb5_init_creds_init(ctx, princ, prompter, password, start_time, gic_opt, &creds_ctx)))
|
||||
goto cleanup;
|
||||
|
||||
if ((rv = krb5_init_creds_get(ctx, creds_ctx)))
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
krb5_init_creds_free(ctx, creds_ctx);
|
||||
krb5_get_init_creds_opt_free(ctx, gic_opt);
|
||||
if (is_temp_ctx)
|
||||
krb5_free_context(ctx);
|
||||
profile_abandon(profile);
|
||||
winpr_DeleteFile(tmp_profile_path);
|
||||
free(tmp_profile_path);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user