/src/samba/auth/kerberos/kerberos_pac.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | kerberos authorization data (PAC) utility library |
4 | | Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 |
5 | | Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005 |
6 | | Copyright (C) Andrew Tridgell 2001 |
7 | | Copyright (C) Luke Howard 2002-2003 |
8 | | Copyright (C) Stefan Metzmacher 2004-2005 |
9 | | Copyright (C) Guenther Deschner 2005,2007,2008 |
10 | | |
11 | | This program is free software; you can redistribute it and/or modify |
12 | | it under the terms of the GNU General Public License as published by |
13 | | the Free Software Foundation; either version 3 of the License, or |
14 | | (at your option) any later version. |
15 | | |
16 | | This program is distributed in the hope that it will be useful, |
17 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | | GNU General Public License for more details. |
20 | | |
21 | | You should have received a copy of the GNU General Public License |
22 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
23 | | */ |
24 | | |
25 | | #include "includes.h" |
26 | | |
27 | | #undef DBGC_CLASS |
28 | 0 | #define DBGC_CLASS DBGC_AUTH |
29 | | |
30 | | #ifdef HAVE_KRB5 |
31 | | |
32 | | #include "librpc/gen_ndr/ndr_krb5pac.h" |
33 | | #include "librpc/gen_ndr/auth.h" |
34 | | #include "auth/common_auth.h" |
35 | | #include "auth/kerberos/pac_utils.h" |
36 | | #include "lib/krb5_wrap/krb5_samba.h" |
37 | | |
38 | | krb5_error_code check_pac_checksum(DATA_BLOB pac_data, |
39 | | struct PAC_SIGNATURE_DATA *sig, |
40 | | krb5_context context, |
41 | | const krb5_keyblock *keyblock) |
42 | 0 | { |
43 | 0 | krb5_error_code ret; |
44 | 0 | krb5_checksum cksum; |
45 | 0 | krb5_keyusage usage = 0; |
46 | 0 | krb5_boolean checksum_valid = false; |
47 | 0 | krb5_data input; |
48 | 0 | size_t idx = 0; |
49 | 0 | struct { |
50 | 0 | krb5_cksumtype cksum_type; |
51 | 0 | krb5_enctype enc_type; |
52 | 0 | } supported_types[] = { |
53 | 0 | {CKSUMTYPE_HMAC_SHA1_96_AES_256, ENCTYPE_AES256_CTS_HMAC_SHA1_96}, |
54 | 0 | {CKSUMTYPE_HMAC_SHA1_96_AES_128, ENCTYPE_AES128_CTS_HMAC_SHA1_96}, |
55 | | /* RFC8009 types. Not supported by AD yet but used by FreeIPA and MIT Kerberos */ |
56 | 0 | {CKSUMTYPE_HMAC_SHA256_128_AES128, ENCTYPE_AES128_CTS_HMAC_SHA256_128}, |
57 | 0 | {CKSUMTYPE_HMAC_SHA384_192_AES256, ENCTYPE_AES256_CTS_HMAC_SHA384_192}, |
58 | 0 | }; |
59 | 0 | size_t num_supported_types = ARRAY_SIZE(supported_types); |
60 | |
|
61 | 0 | for (idx = 0; idx < num_supported_types; idx++) { |
62 | 0 | if (sig->type == supported_types[idx].cksum_type) { |
63 | 0 | if (KRB5_KEY_TYPE(keyblock) != supported_types[idx].enc_type) { |
64 | 0 | return EINVAL; |
65 | 0 | } |
66 | | /* ok */ |
67 | 0 | break; |
68 | 0 | } |
69 | 0 | } |
70 | | |
71 | | /* do not do key type check for HMAC-MD5 */ |
72 | 0 | if ((sig->type != CKSUMTYPE_HMAC_MD5) && |
73 | 0 | (idx == num_supported_types)) { |
74 | 0 | DEBUG(2,("check_pac_checksum: Checksum Type %d is not supported\n", |
75 | 0 | (int)sig->type)); |
76 | 0 | return EINVAL; |
77 | 0 | } |
78 | | |
79 | 0 | #ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM /* Heimdal */ |
80 | 0 | cksum.cksumtype = (krb5_cksumtype)sig->type; |
81 | 0 | cksum.checksum.length = sig->signature.length; |
82 | 0 | cksum.checksum.data = sig->signature.data; |
83 | | #else /* MIT */ |
84 | | cksum.checksum_type = (krb5_cksumtype)sig->type; |
85 | | cksum.length = sig->signature.length; |
86 | | cksum.contents = sig->signature.data; |
87 | | #endif |
88 | |
|
89 | 0 | #ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */ |
90 | 0 | usage = KRB5_KU_OTHER_CKSUM; |
91 | | #elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */ |
92 | | usage = KRB5_KEYUSAGE_APP_DATA_CKSUM; |
93 | | #else |
94 | | #error UNKNOWN_KRB5_KEYUSAGE |
95 | | #endif |
96 | |
|
97 | 0 | input.data = (char *)pac_data.data; |
98 | 0 | input.length = pac_data.length; |
99 | |
|
100 | 0 | ret = krb5_c_verify_checksum(context, |
101 | 0 | keyblock, |
102 | 0 | usage, |
103 | 0 | &input, |
104 | 0 | &cksum, |
105 | 0 | &checksum_valid); |
106 | 0 | if (!checksum_valid) { |
107 | 0 | ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; |
108 | 0 | } |
109 | 0 | if (ret){ |
110 | 0 | DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n", |
111 | 0 | error_message(ret), ret)); |
112 | 0 | return ret; |
113 | 0 | } |
114 | | |
115 | 0 | return ret; |
116 | 0 | } |
117 | | |
118 | | /** |
119 | | * @brief Decode a blob containing a NDR encoded PAC structure |
120 | | * |
121 | | * @param mem_ctx - The memory context |
122 | | * @param pac_data_blob - The data blob containing the NDR encoded data |
123 | | * @param context - The Kerberos Context |
124 | | * @param service_keyblock - The Service Key used to verify the checksum |
125 | | * @param client_principal - The client principal |
126 | | * @param tgs_authtime - The ticket timestamp |
127 | | * @param pac_data_out - [out] The decoded PAC |
128 | | * |
129 | | * @return - A NTSTATUS error code |
130 | | */ |
131 | | NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx, |
132 | | DATA_BLOB pac_data_blob, |
133 | | krb5_context context, |
134 | | const krb5_keyblock *krbtgt_keyblock, |
135 | | const krb5_keyblock *service_keyblock, |
136 | | krb5_const_principal client_principal, |
137 | | time_t tgs_authtime, |
138 | | struct PAC_DATA **pac_data_out) |
139 | 0 | { |
140 | 0 | NTSTATUS status = NT_STATUS_NO_MEMORY; |
141 | 0 | enum ndr_err_code ndr_err; |
142 | 0 | krb5_error_code ret; |
143 | 0 | DATA_BLOB modified_pac_blob; |
144 | |
|
145 | 0 | NTTIME tgs_authtime_nttime; |
146 | 0 | uint32_t i; |
147 | |
|
148 | 0 | struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; |
149 | 0 | struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL; |
150 | 0 | struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL; |
151 | 0 | struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL; |
152 | 0 | struct PAC_LOGON_NAME *logon_name = NULL; |
153 | 0 | struct PAC_LOGON_INFO *logon_info = NULL; |
154 | 0 | struct PAC_DATA *pac_data = NULL; |
155 | 0 | struct PAC_DATA_RAW *pac_data_raw = NULL; |
156 | |
|
157 | 0 | DATA_BLOB *srv_sig_blob = NULL; |
158 | 0 | DATA_BLOB *kdc_sig_blob = NULL; |
159 | |
|
160 | 0 | bool bool_ret; |
161 | |
|
162 | 0 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); |
163 | 0 | if (!tmp_ctx) { |
164 | 0 | return NT_STATUS_NO_MEMORY; |
165 | 0 | } |
166 | | |
167 | 0 | if (pac_data_out) { |
168 | 0 | *pac_data_out = NULL; |
169 | 0 | } |
170 | |
|
171 | 0 | pac_data = talloc(tmp_ctx, struct PAC_DATA); |
172 | 0 | pac_data_raw = talloc(tmp_ctx, struct PAC_DATA_RAW); |
173 | 0 | kdc_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA); |
174 | 0 | srv_sig_wipe = talloc(tmp_ctx, struct PAC_SIGNATURE_DATA); |
175 | 0 | if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) { |
176 | 0 | status = NT_STATUS_NO_MEMORY; |
177 | 0 | goto out; |
178 | 0 | } |
179 | | |
180 | 0 | ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data, |
181 | 0 | (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); |
182 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
183 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
184 | 0 | DEBUG(0,("can't parse the PAC: %s\n", |
185 | 0 | nt_errstr(status))); |
186 | 0 | goto out; |
187 | 0 | } |
188 | | |
189 | 0 | if (pac_data->num_buffers < 4) { |
190 | | /* we need logon_info, service_key and kdc_key */ |
191 | 0 | DEBUG(0,("less than 4 PAC buffers\n")); |
192 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
193 | 0 | goto out; |
194 | 0 | } |
195 | | |
196 | 0 | ndr_err = ndr_pull_struct_blob( |
197 | 0 | &pac_data_blob, pac_data_raw, pac_data_raw, |
198 | 0 | (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); |
199 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
200 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
201 | 0 | DEBUG(0,("can't parse the PAC: %s\n", |
202 | 0 | nt_errstr(status))); |
203 | 0 | goto out; |
204 | 0 | } |
205 | | |
206 | 0 | if (pac_data_raw->num_buffers < 4) { |
207 | | /* we need logon_info, service_key and kdc_key */ |
208 | 0 | DEBUG(0,("less than 4 PAC buffers\n")); |
209 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
210 | 0 | goto out; |
211 | 0 | } |
212 | | |
213 | 0 | if (pac_data->num_buffers != pac_data_raw->num_buffers) { |
214 | | /* we need logon_info, service_key and kdc_key */ |
215 | 0 | DEBUG(0, ("misparse! PAC_DATA has %d buffers while " |
216 | 0 | "PAC_DATA_RAW has %d\n", pac_data->num_buffers, |
217 | 0 | pac_data_raw->num_buffers)); |
218 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
219 | 0 | goto out; |
220 | 0 | } |
221 | | |
222 | 0 | for (i=0; i < pac_data->num_buffers; i++) { |
223 | 0 | struct PAC_BUFFER *data_buf = &pac_data->buffers[i]; |
224 | 0 | struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i]; |
225 | |
|
226 | 0 | if (data_buf->type != raw_buf->type) { |
227 | 0 | DEBUG(0, ("misparse! PAC_DATA buffer %d has type " |
228 | 0 | "%d while PAC_DATA_RAW has %d\n", i, |
229 | 0 | data_buf->type, raw_buf->type)); |
230 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
231 | 0 | goto out; |
232 | 0 | } |
233 | 0 | switch (data_buf->type) { |
234 | 0 | case PAC_TYPE_LOGON_INFO: |
235 | 0 | if (!data_buf->info) { |
236 | 0 | break; |
237 | 0 | } |
238 | 0 | logon_info = data_buf->info->logon_info.info; |
239 | 0 | break; |
240 | 0 | case PAC_TYPE_SRV_CHECKSUM: |
241 | 0 | if (!data_buf->info) { |
242 | 0 | break; |
243 | 0 | } |
244 | 0 | srv_sig_ptr = &data_buf->info->srv_cksum; |
245 | 0 | srv_sig_blob = &raw_buf->info->remaining; |
246 | 0 | break; |
247 | 0 | case PAC_TYPE_KDC_CHECKSUM: |
248 | 0 | if (!data_buf->info) { |
249 | 0 | break; |
250 | 0 | } |
251 | 0 | kdc_sig_ptr = &data_buf->info->kdc_cksum; |
252 | 0 | kdc_sig_blob = &raw_buf->info->remaining; |
253 | 0 | break; |
254 | 0 | case PAC_TYPE_LOGON_NAME: |
255 | 0 | logon_name = &data_buf->info->logon_name; |
256 | 0 | break; |
257 | 0 | default: |
258 | 0 | break; |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | 0 | if (!logon_info) { |
263 | 0 | DEBUG(0,("PAC no logon_info\n")); |
264 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
265 | 0 | goto out; |
266 | 0 | } |
267 | | |
268 | 0 | if (!logon_name) { |
269 | 0 | DEBUG(0,("PAC no logon_name\n")); |
270 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
271 | 0 | goto out; |
272 | 0 | } |
273 | | |
274 | 0 | if (!srv_sig_ptr || !srv_sig_blob) { |
275 | 0 | DEBUG(0,("PAC no srv_key\n")); |
276 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
277 | 0 | goto out; |
278 | 0 | } |
279 | | |
280 | 0 | if (!kdc_sig_ptr || !kdc_sig_blob) { |
281 | 0 | DEBUG(0,("PAC no kdc_key\n")); |
282 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
283 | 0 | goto out; |
284 | 0 | } |
285 | | |
286 | | /* Find and zero out the signatures, |
287 | | * as required by the signing algorithm */ |
288 | | |
289 | | /* We find the data blobs above, |
290 | | * now we parse them to get at the exact portion we should zero */ |
291 | 0 | ndr_err = ndr_pull_struct_blob( |
292 | 0 | kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe, |
293 | 0 | (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); |
294 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
295 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
296 | 0 | DEBUG(0,("can't parse the KDC signature: %s\n", |
297 | 0 | nt_errstr(status))); |
298 | 0 | goto out; |
299 | 0 | } |
300 | | |
301 | 0 | ndr_err = ndr_pull_struct_blob( |
302 | 0 | srv_sig_blob, srv_sig_wipe, srv_sig_wipe, |
303 | 0 | (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); |
304 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
305 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
306 | 0 | DEBUG(0,("can't parse the SRV signature: %s\n", |
307 | 0 | nt_errstr(status))); |
308 | 0 | goto out; |
309 | 0 | } |
310 | | |
311 | | /* Now zero the decoded structure */ |
312 | 0 | memset(kdc_sig_wipe->signature.data, |
313 | 0 | '\0', kdc_sig_wipe->signature.length); |
314 | 0 | memset(srv_sig_wipe->signature.data, |
315 | 0 | '\0', srv_sig_wipe->signature.length); |
316 | | |
317 | | /* and re-encode, back into the same place it came from */ |
318 | 0 | ndr_err = ndr_push_struct_blob( |
319 | 0 | kdc_sig_blob, pac_data_raw, kdc_sig_wipe, |
320 | 0 | (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); |
321 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
322 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
323 | 0 | DEBUG(0,("can't repack the KDC signature: %s\n", |
324 | 0 | nt_errstr(status))); |
325 | 0 | goto out; |
326 | 0 | } |
327 | 0 | ndr_err = ndr_push_struct_blob( |
328 | 0 | srv_sig_blob, pac_data_raw, srv_sig_wipe, |
329 | 0 | (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); |
330 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
331 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
332 | 0 | DEBUG(0,("can't repack the SRV signature: %s\n", |
333 | 0 | nt_errstr(status))); |
334 | 0 | goto out; |
335 | 0 | } |
336 | | |
337 | | /* push out the whole structure, but now with zero'ed signatures */ |
338 | 0 | ndr_err = ndr_push_struct_blob( |
339 | 0 | &modified_pac_blob, pac_data_raw, pac_data_raw, |
340 | 0 | (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); |
341 | 0 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { |
342 | 0 | status = ndr_map_error2ntstatus(ndr_err); |
343 | 0 | DEBUG(0,("can't repack the RAW PAC: %s\n", |
344 | 0 | nt_errstr(status))); |
345 | 0 | goto out; |
346 | 0 | } |
347 | | |
348 | 0 | if (service_keyblock) { |
349 | | /* verify by service_key */ |
350 | 0 | ret = check_pac_checksum(modified_pac_blob, srv_sig_ptr, |
351 | 0 | context, |
352 | 0 | service_keyblock); |
353 | 0 | if (ret) { |
354 | 0 | DEBUG(5, ("PAC Decode: Failed to verify the service " |
355 | 0 | "signature: %s\n", error_message(ret))); |
356 | 0 | status = NT_STATUS_ACCESS_DENIED; |
357 | 0 | goto out; |
358 | 0 | } |
359 | | |
360 | 0 | if (krbtgt_keyblock) { |
361 | | /* verify the service key checksum by krbtgt_key */ |
362 | 0 | ret = check_pac_checksum(srv_sig_ptr->signature, kdc_sig_ptr, |
363 | 0 | context, krbtgt_keyblock); |
364 | 0 | if (ret) { |
365 | 0 | DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n", |
366 | 0 | smb_get_krb5_error_message(context, ret, tmp_ctx))); |
367 | 0 | status = NT_STATUS_ACCESS_DENIED; |
368 | 0 | goto out; |
369 | 0 | } |
370 | 0 | } |
371 | 0 | } |
372 | | |
373 | 0 | if (tgs_authtime) { |
374 | | /* Convert to NT time, so as not to lose accuracy in comparison */ |
375 | 0 | unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); |
376 | |
|
377 | 0 | if (tgs_authtime_nttime != logon_name->logon_time) { |
378 | 0 | DEBUG(2, ("PAC Decode: " |
379 | 0 | "Logon time mismatch between ticket and PAC!\n")); |
380 | 0 | DEBUG(2, ("PAC Decode: PAC: %s\n", |
381 | 0 | nt_time_string(tmp_ctx, logon_name->logon_time))); |
382 | 0 | DEBUG(2, ("PAC Decode: Ticket: %s\n", |
383 | 0 | nt_time_string(tmp_ctx, tgs_authtime_nttime))); |
384 | 0 | status = NT_STATUS_ACCESS_DENIED; |
385 | 0 | goto out; |
386 | 0 | } |
387 | 0 | } |
388 | | |
389 | 0 | if (client_principal) { |
390 | 0 | char *client_principal_string; |
391 | 0 | ret = krb5_unparse_name_flags(context, client_principal, |
392 | 0 | KRB5_PRINCIPAL_UNPARSE_NO_REALM|KRB5_PRINCIPAL_UNPARSE_DISPLAY, |
393 | 0 | &client_principal_string); |
394 | 0 | if (ret) { |
395 | 0 | DEBUG(2, ("Could not unparse name from ticket to match with name from PAC: [%s]:%s\n", |
396 | 0 | logon_name->account_name, error_message(ret))); |
397 | 0 | status = NT_STATUS_INVALID_PARAMETER; |
398 | 0 | goto out; |
399 | 0 | } |
400 | | |
401 | 0 | bool_ret = strcmp(client_principal_string, logon_name->account_name) == 0; |
402 | |
|
403 | 0 | if (!bool_ret) { |
404 | 0 | DEBUG(2, ("Name in PAC [%s] does not match principal name " |
405 | 0 | "in ticket [%s]\n", |
406 | 0 | logon_name->account_name, |
407 | 0 | client_principal_string)); |
408 | 0 | } |
409 | 0 | SAFE_FREE(client_principal_string); |
410 | |
|
411 | 0 | } |
412 | | |
413 | 0 | DEBUG(3,("Found account name from PAC: %s [%s]\n", |
414 | 0 | logon_info->info3.base.account_name.string, |
415 | 0 | logon_info->info3.base.full_name.string)); |
416 | |
|
417 | 0 | if (DEBUGLEVEL >= 10) { |
418 | 0 | const char *s = NDR_PRINT_STRUCT_STRING( |
419 | 0 | tmp_ctx, PAC_DATA, pac_data); |
420 | |
|
421 | 0 | DEBUG(10,("Successfully validated Kerberos PAC\n%s%c", |
422 | 0 | s != NULL ? s : "", |
423 | 0 | s != NULL ? '\n' : '\0')); |
424 | 0 | } |
425 | |
|
426 | 0 | if (pac_data_out) { |
427 | 0 | *pac_data_out = talloc_move(mem_ctx, &pac_data); |
428 | 0 | } |
429 | |
|
430 | 0 | status = NT_STATUS_OK; |
431 | |
|
432 | 0 | out: |
433 | |
|
434 | 0 | TALLOC_FREE(tmp_ctx); |
435 | 0 | return status; |
436 | 0 | } |
437 | | |
438 | | NTSTATUS kerberos_pac_logon_info(TALLOC_CTX *mem_ctx, |
439 | | DATA_BLOB blob, |
440 | | krb5_context context, |
441 | | const krb5_keyblock *krbtgt_keyblock, |
442 | | const krb5_keyblock *service_keyblock, |
443 | | krb5_const_principal client_principal, |
444 | | time_t tgs_authtime, |
445 | | struct PAC_LOGON_INFO **logon_info) |
446 | 0 | { |
447 | 0 | NTSTATUS nt_status; |
448 | 0 | struct PAC_DATA *pac_data; |
449 | 0 | uint32_t i; |
450 | 0 | nt_status = kerberos_decode_pac(mem_ctx, |
451 | 0 | blob, |
452 | 0 | context, |
453 | 0 | krbtgt_keyblock, |
454 | 0 | service_keyblock, |
455 | 0 | client_principal, |
456 | 0 | tgs_authtime, |
457 | 0 | &pac_data); |
458 | 0 | if (!NT_STATUS_IS_OK(nt_status)) { |
459 | 0 | return nt_status; |
460 | 0 | } |
461 | | |
462 | 0 | *logon_info = NULL; |
463 | 0 | for (i=0; i < pac_data->num_buffers; i++) { |
464 | 0 | if (pac_data->buffers[i].type != PAC_TYPE_LOGON_INFO) { |
465 | 0 | continue; |
466 | 0 | } |
467 | 0 | *logon_info = pac_data->buffers[i].info->logon_info.info; |
468 | 0 | } |
469 | 0 | if (!*logon_info) { |
470 | 0 | return NT_STATUS_INVALID_PARAMETER; |
471 | 0 | } |
472 | 0 | return NT_STATUS_OK; |
473 | 0 | } |
474 | | |
475 | | static NTSTATUS auth4_context_fetch_PAC_DATA_CTR( |
476 | | struct auth4_context *auth_ctx, |
477 | | TALLOC_CTX *mem_ctx, |
478 | | struct smb_krb5_context *smb_krb5_context, |
479 | | DATA_BLOB *pac_blob, |
480 | | const char *princ_name, |
481 | | const struct tsocket_address *remote_address, |
482 | | uint32_t session_info_flags, |
483 | | struct auth_session_info **session_info) |
484 | 0 | { |
485 | 0 | struct PAC_DATA_CTR *pac_data_ctr = NULL; |
486 | 0 | NTSTATUS status; |
487 | |
|
488 | 0 | if (pac_blob == NULL) { |
489 | 0 | return NT_STATUS_NO_IMPERSONATION_TOKEN; |
490 | 0 | } |
491 | | |
492 | 0 | pac_data_ctr = talloc_zero(mem_ctx, struct PAC_DATA_CTR); |
493 | 0 | if (pac_data_ctr == NULL) { |
494 | 0 | status = NT_STATUS_NO_MEMORY; |
495 | 0 | goto fail; |
496 | 0 | } |
497 | | |
498 | 0 | status = kerberos_decode_pac(pac_data_ctr, |
499 | 0 | *pac_blob, |
500 | 0 | NULL, |
501 | 0 | NULL, |
502 | 0 | NULL, |
503 | 0 | NULL, |
504 | 0 | 0, |
505 | 0 | &pac_data_ctr->pac_data); |
506 | 0 | if (!NT_STATUS_IS_OK(status)) { |
507 | 0 | goto fail; |
508 | 0 | } |
509 | | |
510 | 0 | pac_data_ctr->pac_blob = data_blob_talloc(pac_data_ctr, |
511 | 0 | pac_blob->data, |
512 | 0 | pac_blob->length); |
513 | 0 | if (pac_data_ctr->pac_blob.length != pac_blob->length) { |
514 | 0 | status = NT_STATUS_NO_MEMORY; |
515 | 0 | goto fail; |
516 | 0 | } |
517 | | |
518 | 0 | *session_info = talloc_zero(mem_ctx, struct auth_session_info); |
519 | 0 | if (*session_info == NULL) { |
520 | 0 | status = NT_STATUS_NO_MEMORY; |
521 | 0 | goto fail; |
522 | 0 | } |
523 | | |
524 | 0 | TALLOC_FREE(auth_ctx->private_data); |
525 | 0 | auth_ctx->private_data = talloc_move(auth_ctx, &pac_data_ctr); |
526 | |
|
527 | 0 | return NT_STATUS_OK; |
528 | | |
529 | 0 | fail: |
530 | 0 | TALLOC_FREE(pac_data_ctr); |
531 | |
|
532 | 0 | return status; |
533 | 0 | } |
534 | | |
535 | | struct auth4_context *auth4_context_for_PAC_DATA_CTR(TALLOC_CTX *mem_ctx) |
536 | 0 | { |
537 | 0 | struct auth4_context *auth_ctx = NULL; |
538 | |
|
539 | 0 | auth_ctx = talloc_zero(mem_ctx, struct auth4_context); |
540 | 0 | if (auth_ctx == NULL) { |
541 | 0 | return NULL; |
542 | 0 | } |
543 | 0 | auth_ctx->generate_session_info_pac = auth4_context_fetch_PAC_DATA_CTR; |
544 | |
|
545 | 0 | return auth_ctx; |
546 | 0 | } |
547 | | |
548 | | struct PAC_DATA_CTR *auth4_context_get_PAC_DATA_CTR(struct auth4_context *auth_ctx, |
549 | | TALLOC_CTX *mem_ctx) |
550 | 0 | { |
551 | 0 | struct PAC_DATA_CTR *p = NULL; |
552 | 0 | SMB_ASSERT(auth_ctx->generate_session_info_pac == auth4_context_fetch_PAC_DATA_CTR); |
553 | 0 | p = talloc_get_type_abort(auth_ctx->private_data, struct PAC_DATA_CTR); |
554 | 0 | auth_ctx->private_data = NULL; |
555 | 0 | return talloc_move(mem_ctx, &p); |
556 | 0 | } |
557 | | |
558 | | #endif |