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>
36 static char* create_temporary_file(
void)
42 winpr_RAND(buffer,
sizeof(buffer));
43 hex = winpr_BinToHexString(buffer,
sizeof(buffer), FALSE);
44 path = GetKnownSubPath(KNOWN_PATH_TEMP, hex);
49 void krb5glue_keys_free(krb5_context ctx,
struct krb5glue_keyset* keyset)
54 krb5_k_free_key(ctx, keyset->session_key);
55 krb5_k_free_key(ctx, keyset->initiator_key);
56 krb5_k_free_key(ctx, keyset->acceptor_key);
59 krb5_error_code krb5glue_update_keyset(krb5_context ctx, krb5_auth_context auth_ctx, BOOL acceptor,
63 WINPR_ASSERT(auth_ctx);
66 krb5glue_keys_free(ctx, keyset);
67 krb5_auth_con_getkey_k(ctx, auth_ctx, &keyset->session_key);
70 krb5_auth_con_getsendsubkey_k(ctx, auth_ctx, &keyset->acceptor_key);
71 krb5_auth_con_getrecvsubkey_k(ctx, auth_ctx, &keyset->initiator_key);
75 krb5_auth_con_getsendsubkey_k(ctx, auth_ctx, &keyset->initiator_key);
76 krb5_auth_con_getrecvsubkey_k(ctx, auth_ctx, &keyset->acceptor_key);
81 krb5_prompt_type krb5glue_get_prompt_type(krb5_context ctx, krb5_prompt prompts[],
int index)
84 WINPR_ASSERT(prompts);
85 WINPR_UNUSED(prompts);
87 krb5_prompt_type* types = krb5_get_prompt_types(ctx);
88 return types ? types[index] : 0;
91 krb5_error_code krb5glue_log_error(krb5_context ctx, krb5_data* msg,
const char* tag)
93 krb5_error* error = NULL;
94 krb5_error_code rv = 0;
100 if (!(rv = krb5_rd_error(ctx, msg, &error)))
102 WLog_ERR(tag,
"KRB_ERROR: %s", error->text.data);
103 krb5_free_error(ctx, error);
109 BOOL krb5glue_authenticator_validate_chksum(krb5glue_authenticator authenticator,
int cksumtype,
114 if (!authenticator || !authenticator->checksum ||
115 authenticator->checksum->checksum_type != cksumtype || authenticator->checksum->length < 24)
117 Data_Read_UINT32((authenticator->checksum->contents + 20), (*flags));
121 krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ, krb5_ccache ccache,
122 krb5_prompter_fct prompter,
char* password,
125 krb5_error_code rv = 0;
126 krb5_deltat start_time = 0;
127 krb5_get_init_creds_opt* gic_opt = NULL;
128 krb5_init_creds_context creds_ctx = NULL;
129 char* tmp_profile_path = create_temporary_file();
130 profile_t profile = NULL;
131 BOOL is_temp_ctx = FALSE;
135 rv = krb5_get_init_creds_opt_alloc(ctx, &gic_opt);
139 krb5_get_init_creds_opt_set_forwardable(gic_opt, 0);
140 krb5_get_init_creds_opt_set_proxiable(gic_opt, 0);
144 if (krb_settings->startTime)
145 start_time = krb_settings->startTime;
146 if (krb_settings->lifeTime)
147 krb5_get_init_creds_opt_set_tkt_life(gic_opt, krb_settings->lifeTime);
148 if (krb_settings->renewLifeTime)
149 krb5_get_init_creds_opt_set_renew_life(gic_opt, krb_settings->renewLifeTime);
150 if (krb_settings->withPac)
152 rv = krb5_get_init_creds_opt_set_pac_request(ctx, gic_opt, TRUE);
156 if (krb_settings->armorCache)
158 rv = krb5_get_init_creds_opt_set_fast_ccache_name(ctx, gic_opt,
159 krb_settings->armorCache);
163 if (krb_settings->pkinitX509Identity)
165 rv = krb5_get_init_creds_opt_set_pa(ctx, gic_opt,
"X509_user_identity",
166 krb_settings->pkinitX509Identity);
170 if (krb_settings->pkinitX509Anchors)
172 rv = krb5_get_init_creds_opt_set_pa(ctx, gic_opt,
"X509_anchors",
173 krb_settings->pkinitX509Anchors);
177 if (krb_settings->kdcUrl && (strnlen(krb_settings->kdcUrl, 2) > 0))
179 const char* names[4] = { 0 };
181 char* kdc_url = NULL;
184 if ((rv = krb5_get_profile(ctx, &profile)))
188 if (winpr_asprintf(&kdc_url, &size,
"https://%s/KdcProxy", krb_settings->kdcUrl) <= 0)
194 realm = calloc(princ->realm.length + 1, 1);
200 CopyMemory(realm, princ->realm.data, princ->realm.length);
206 profile_clear_relation(profile, names);
207 profile_add_relation(profile, names, kdc_url);
210 names[2] =
"pkinit_kdc_hostname";
211 profile_add_relation(profile, names, krb_settings->kdcUrl);
216 long lrv = profile_flush_to_file(profile, tmp_profile_path);
220 profile_abandon(profile);
222 lrv = profile_init_path(tmp_profile_path, &profile);
226 rv = krb5_init_context_profile(profile, 0, &ctx);
233 if ((rv = krb5_get_init_creds_opt_set_in_ccache(ctx, gic_opt, ccache)))
236 if ((rv = krb5_get_init_creds_opt_set_out_ccache(ctx, gic_opt, ccache)))
240 krb5_init_creds_init(ctx, princ, prompter, password, start_time, gic_opt, &creds_ctx)))
243 if ((rv = krb5_init_creds_get(ctx, creds_ctx)))
247 krb5_init_creds_free(ctx, creds_ctx);
248 krb5_get_init_creds_opt_free(ctx, gic_opt);
250 krb5_free_context(ctx);
251 profile_abandon(profile);
252 winpr_DeleteFile(tmp_profile_path);
253 free(tmp_profile_path);