FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
krb5glue_heimdal.c
1
20#ifndef WITH_KRB5_HEIMDAL
21#error "This file must only be included with HEIMDAL kerberos"
22#endif
23
24#include <winpr/endian.h>
25#include <winpr/wlog.h>
26#include <winpr/assert.h>
27#include "krb5glue.h"
28
29void krb5glue_keys_free(krb5_context ctx, struct krb5glue_keyset* keyset)
30{
31 if (!ctx || !keyset)
32 return;
33 if (keyset->session_key)
34 krb5_crypto_destroy(ctx, keyset->session_key);
35 if (keyset->initiator_key)
36 krb5_crypto_destroy(ctx, keyset->initiator_key);
37 if (keyset->acceptor_key)
38 krb5_crypto_destroy(ctx, keyset->acceptor_key);
39}
40
41krb5_error_code krb5glue_update_keyset(krb5_context ctx, krb5_auth_context auth_ctx, BOOL acceptor,
42 struct krb5glue_keyset* keyset)
43{
44 krb5_keyblock* keyblock = NULL;
45 krb5_error_code rv = 0;
46
47 WINPR_ASSERT(ctx);
48 WINPR_ASSERT(auth_ctx);
49 WINPR_ASSERT(keyset);
50
51 krb5glue_keys_free(ctx, keyset);
52
53 rv = krb5_auth_con_getkey(ctx, auth_ctx, &keyblock);
54 if (!rv)
55 {
56 krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->session_key);
57 krb5_free_keyblock(ctx, keyblock);
58 keyblock = NULL;
59 }
60
61 if (acceptor)
62 rv = krb5_auth_con_getremotesubkey(ctx, auth_ctx, &keyblock);
63 else
64 rv = krb5_auth_con_getlocalsubkey(ctx, auth_ctx, &keyblock);
65
66 if (!rv && keyblock)
67 {
68 krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->initiator_key);
69 krb5_free_keyblock(ctx, keyblock);
70 keyblock = NULL;
71 }
72
73 if (acceptor)
74 rv = krb5_auth_con_getlocalsubkey(ctx, auth_ctx, &keyblock);
75 else
76 rv = krb5_auth_con_getremotesubkey(ctx, auth_ctx, &keyblock);
77
78 if (!rv && keyblock)
79 {
80 krb5_crypto_init(ctx, keyblock, ENCTYPE_NULL, &keyset->acceptor_key);
81 krb5_free_keyblock(ctx, keyblock);
82 }
83
84 return rv;
85}
86
87krb5_error_code krb5glue_verify_checksum_iov(krb5_context ctx, krb5glue_key key,
88 krb5_keyusage usage, krb5_crypto_iov* iov,
89 unsigned int iov_size, krb5_boolean* is_valid)
90{
91 krb5_error_code rv = 0;
92
93 WINPR_ASSERT(ctx);
94 WINPR_ASSERT(key);
95 WINPR_ASSERT(is_valid);
96
97 rv = krb5_verify_checksum_iov(ctx, key, usage, iov, iov_size, NULL);
98 *is_valid = (rv == 0);
99 return rv;
100}
101
102krb5_error_code krb5glue_crypto_length(krb5_context ctx, krb5glue_key key, int type,
103 unsigned int* size)
104{
105 krb5_error_code rv = 0;
106 size_t s = 0;
107
108 WINPR_ASSERT(ctx);
109 WINPR_ASSERT(key);
110 WINPR_ASSERT(size);
111
112 rv = krb5_crypto_length(ctx, key, type, &s);
113 *size = (UINT)s;
114 return rv;
115}
116
117krb5_error_code krb5glue_log_error(krb5_context ctx, krb5_data* msg, const char* tag)
118{
119 krb5_error error = { 0 };
120 krb5_error_code rv = 0;
121
122 WINPR_ASSERT(ctx);
123 WINPR_ASSERT(msg);
124 WINPR_ASSERT(tag);
125
126 if (!(rv = krb5_rd_error(ctx, msg, &error)))
127 {
128 WLog_ERR(tag, "KRB_ERROR: %" PRIx32, error.error_code);
129 krb5_free_error_contents(ctx, &error);
130 }
131 return rv;
132}
133
134BOOL krb5glue_authenticator_validate_chksum(krb5glue_authenticator authenticator, int cksumtype,
135 uint32_t* flags)
136{
137 WINPR_ASSERT(flags);
138
139 if (!authenticator || !authenticator->cksum || authenticator->cksum->cksumtype != cksumtype ||
140 authenticator->cksum->checksum.length < 24)
141 return FALSE;
142
143 const BYTE* data = authenticator->cksum->checksum.data;
144 Data_Read_UINT32((data + 20), (*flags));
145 return TRUE;
146}
147
148krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ, krb5_ccache ccache,
149 krb5_prompter_fct prompter, char* password,
150 SEC_WINPR_KERBEROS_SETTINGS* krb_settings)
151{
152 krb5_error_code rv = 0;
153 krb5_deltat start_time = 0;
154 krb5_get_init_creds_opt* gic_opt = NULL;
155 krb5_init_creds_context creds_ctx = NULL;
156 krb5_creds creds = { 0 };
157
158 WINPR_ASSERT(ctx);
159
160 do
161 {
162 if ((rv = krb5_get_init_creds_opt_alloc(ctx, &gic_opt)) != 0)
163 break;
164
165 krb5_get_init_creds_opt_set_forwardable(gic_opt, 0);
166 krb5_get_init_creds_opt_set_proxiable(gic_opt, 0);
167
168 if (krb_settings)
169 {
170 if (krb_settings->startTime)
171 start_time = krb_settings->startTime;
172 if (krb_settings->lifeTime)
173 krb5_get_init_creds_opt_set_tkt_life(gic_opt, krb_settings->lifeTime);
174 if (krb_settings->renewLifeTime)
175 krb5_get_init_creds_opt_set_renew_life(gic_opt, krb_settings->renewLifeTime);
176 if (krb_settings->withPac)
177 krb5_get_init_creds_opt_set_pac_request(ctx, gic_opt, TRUE);
178 if (krb_settings->pkinitX509Anchors || krb_settings->pkinitX509Identity)
179 {
180 if ((rv = krb5_get_init_creds_opt_set_pkinit(
181 ctx, gic_opt, princ, krb_settings->pkinitX509Identity,
182 krb_settings->pkinitX509Anchors, NULL, NULL, 0, prompter, password,
183 password)) != 0)
184 break;
185 }
186 }
187
188 if ((rv = krb5_init_creds_init(ctx, princ, prompter, password, start_time, gic_opt,
189 &creds_ctx)) != 0)
190 break;
191 if ((rv = krb5_init_creds_set_password(ctx, creds_ctx, password)) != 0)
192 break;
193 if (krb_settings && krb_settings->armorCache)
194 {
195 krb5_ccache armor_cc = NULL;
196 if ((rv = krb5_cc_resolve(ctx, krb_settings->armorCache, &armor_cc)) != 0)
197 break;
198 if ((rv = krb5_init_creds_set_fast_ccache(ctx, creds_ctx, armor_cc)) != 0)
199 break;
200 krb5_cc_close(ctx, armor_cc);
201 }
202 if ((rv = krb5_init_creds_get(ctx, creds_ctx)) != 0)
203 break;
204 if ((rv = krb5_init_creds_get_creds(ctx, creds_ctx, &creds)) != 0)
205 break;
206 if ((rv = krb5_cc_store_cred(ctx, ccache, &creds)) != 0)
207 break;
208 } while (0);
209
210 krb5_free_cred_contents(ctx, &creds);
211 krb5_init_creds_free(ctx, creds_ctx);
212 krb5_get_init_creds_opt_free(ctx, gic_opt);
213
214 return rv;
215}
216