21#error "This file must only be included with MIT kerberos"
26#include <winpr/path.h>
27#include <winpr/wlog.h>
28#include <winpr/endian.h>
29#include <winpr/crypto.h>
30#include <winpr/print.h>
31#include <winpr/assert.h>
36static char* create_temporary_file(
void)
42 if (winpr_RAND(buffer,
sizeof(buffer)) < 0)
44 hex = winpr_BinToHexString(buffer,
sizeof(buffer), FALSE);
45 path = GetKnownSubPath(KNOWN_PATH_TEMP, hex);
50void krb5glue_keys_free(krb5_context ctx,
struct krb5glue_keyset* keyset)
55 krb5_k_free_key(ctx, keyset->session_key);
56 krb5_k_free_key(ctx, keyset->initiator_key);
57 krb5_k_free_key(ctx, keyset->acceptor_key);
60krb5_error_code krb5glue_update_keyset(krb5_context ctx, krb5_auth_context auth_ctx, BOOL acceptor,
64 WINPR_ASSERT(auth_ctx);
67 krb5glue_keys_free(ctx, keyset);
68 krb5_auth_con_getkey_k(ctx, auth_ctx, &keyset->session_key);
71 krb5_auth_con_getsendsubkey_k(ctx, auth_ctx, &keyset->acceptor_key);
72 krb5_auth_con_getrecvsubkey_k(ctx, auth_ctx, &keyset->initiator_key);
76 krb5_auth_con_getsendsubkey_k(ctx, auth_ctx, &keyset->initiator_key);
77 krb5_auth_con_getrecvsubkey_k(ctx, auth_ctx, &keyset->acceptor_key);
82krb5_prompt_type krb5glue_get_prompt_type(krb5_context ctx, krb5_prompt prompts[],
int index)
85 WINPR_ASSERT(prompts);
86 WINPR_UNUSED(prompts);
88 krb5_prompt_type* types = krb5_get_prompt_types(ctx);
89 return types ? types[index] : 0;
92krb5_error_code krb5glue_log_error(krb5_context ctx, krb5_data* msg,
const char* tag)
94 krb5_error* error =
nullptr;
95 krb5_error_code rv = 0;
101 if (!(rv = krb5_rd_error(ctx, msg, &error)))
103 WLog_ERR(tag,
"KRB_ERROR: %s", error->text.data);
104 krb5_free_error(ctx, error);
110BOOL krb5glue_authenticator_validate_chksum(krb5glue_authenticator authenticator,
int cksumtype,
115 if (!authenticator || !authenticator->checksum ||
116 authenticator->checksum->checksum_type != cksumtype || authenticator->checksum->length < 24)
118 *flags = winpr_Data_Get_UINT32((authenticator->checksum->contents + 20));
122krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ, krb5_ccache ccache,
123 krb5_prompter_fct prompter,
char* password,
126 krb5_error_code rv = 0;
127 krb5_deltat start_time = 0;
128 krb5_get_init_creds_opt* gic_opt =
nullptr;
129 krb5_init_creds_context creds_ctx =
nullptr;
130 char* tmp_profile_path = create_temporary_file();
131 profile_t profile =
nullptr;
132 BOOL is_temp_ctx = FALSE;
136 rv = krb5_get_init_creds_opt_alloc(ctx, &gic_opt);
140 krb5_get_init_creds_opt_set_forwardable(gic_opt, 0);
141 krb5_get_init_creds_opt_set_proxiable(gic_opt, 0);
145 if (krb_settings->startTime)
146 start_time = krb_settings->startTime;
147 if (krb_settings->lifeTime)
148 krb5_get_init_creds_opt_set_tkt_life(gic_opt, krb_settings->lifeTime);
149 if (krb_settings->renewLifeTime)
150 krb5_get_init_creds_opt_set_renew_life(gic_opt, krb_settings->renewLifeTime);
151 if (krb_settings->withPac)
153 rv = krb5_get_init_creds_opt_set_pac_request(ctx, gic_opt, TRUE);
157 if (krb_settings->armorCache)
159 rv = krb5_get_init_creds_opt_set_fast_ccache_name(ctx, gic_opt,
160 krb_settings->armorCache);
164 if (krb_settings->pkinitX509Identity)
166 rv = krb5_get_init_creds_opt_set_pa(ctx, gic_opt,
"X509_user_identity",
167 krb_settings->pkinitX509Identity);
171 if (krb_settings->pkinitX509Anchors)
173 rv = krb5_get_init_creds_opt_set_pa(ctx, gic_opt,
"X509_anchors",
174 krb_settings->pkinitX509Anchors);
178 if (krb_settings->kdcUrl && (strnlen(krb_settings->kdcUrl, 2) > 0))
180 const char* names[4] = WINPR_C_ARRAY_INIT;
181 char* realm =
nullptr;
182 char* kdc_url =
nullptr;
185 if ((rv = krb5_get_profile(ctx, &profile)))
189 if (winpr_asprintf(&kdc_url, &size,
"https://%s/KdcProxy", krb_settings->kdcUrl) <= 0)
195 realm = calloc(princ->realm.length + 1, 1);
201 CopyMemory(realm, princ->realm.data, princ->realm.length);
207 profile_clear_relation(profile, names);
208 profile_add_relation(profile, names, kdc_url);
211 names[2] =
"pkinit_kdc_hostname";
212 profile_add_relation(profile, names, krb_settings->kdcUrl);
217 long lrv = profile_flush_to_file(profile, tmp_profile_path);
221 profile_abandon(profile);
223 lrv = profile_init_path(tmp_profile_path, &profile);
227 rv = krb5_init_context_profile(profile, 0, &ctx);
234 if ((rv = krb5_get_init_creds_opt_set_in_ccache(ctx, gic_opt, ccache)))
237 if ((rv = krb5_get_init_creds_opt_set_out_ccache(ctx, gic_opt, ccache)))
241 krb5_init_creds_init(ctx, princ, prompter, password, start_time, gic_opt, &creds_ctx)))
244 if ((rv = krb5_init_creds_get(ctx, creds_ctx)))
248 krb5_init_creds_free(ctx, creds_ctx);
249 krb5_get_init_creds_opt_free(ctx, gic_opt);
251 krb5_free_context(ctx);
252 profile_abandon(profile);
253 winpr_DeleteFile(tmp_profile_path);
254 free(tmp_profile_path);