ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source4 / auth / session.c
blob8f5d58b343720c2024f93b14212eab0ee65b86a2
1 /*
2 Unix SMB/CIFS implementation.
3 Authentication utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001-2010
6 Copyright (C) Jeremy Allison 2000-2001
7 Copyright (C) Rafal Szczesniak 2002
8 Copyright (C) Stefan Metzmacher 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "auth/auth.h"
26 #include "auth/auth_sam.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/credentials/credentials_krb5.h"
29 #include "libcli/security/security.h"
30 #include "libcli/security/claims-conversions.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "librpc/gen_ndr/claims.h"
33 #include "librpc/gen_ndr/ndr_claims.h"
34 #include "dsdb/samdb/samdb.h"
35 #include "auth/session_proto.h"
36 #include "system/kerberos.h"
37 #include <gssapi/gssapi.h>
38 #include "libcli/wbclient/wbclient.h"
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_AUTH
43 _PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx,
44 struct loadparm_context *lp_ctx)
46 NTSTATUS nt_status;
47 struct auth_session_info *session_info = NULL;
48 nt_status = auth_anonymous_session_info(mem_ctx, lp_ctx, &session_info);
49 if (!NT_STATUS_IS_OK(nt_status)) {
50 return NULL;
52 return session_info;
55 _PUBLIC_ NTSTATUS auth_generate_security_token(TALLOC_CTX *mem_ctx,
56 struct loadparm_context *lp_ctx, /* Optional, if you don't want privileges */
57 struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */
58 const struct auth_user_info_dc *user_info_dc,
59 const struct auth_user_info_dc *device_info_dc,
60 const struct auth_claims auth_claims,
61 uint32_t session_info_flags,
62 struct security_token **_security_token)
64 struct security_token *security_token = NULL;
65 NTSTATUS nt_status;
66 uint32_t i;
67 uint32_t num_sids = 0;
68 uint32_t num_device_sids = 0;
69 const char *filter = NULL;
70 struct auth_SidAttr *sids = NULL;
71 struct auth_SidAttr *device_sids = NULL;
73 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
74 if (tmp_ctx == NULL) {
75 return NT_STATUS_NO_MEMORY;
78 sids = talloc_array(tmp_ctx, struct auth_SidAttr, user_info_dc->num_sids);
79 if (sids == NULL) {
80 TALLOC_FREE(tmp_ctx);
81 return NT_STATUS_NO_MEMORY;
84 num_sids = user_info_dc->num_sids;
86 for (i=0; i < user_info_dc->num_sids; i++) {
87 sids[i] = user_info_dc->sids[i];
91 * Finally add the "standard" sids.
92 * The only difference between guest and "anonymous"
93 * is the addition of Authenticated_Users.
96 if (session_info_flags & AUTH_SESSION_INFO_DEFAULT_GROUPS) {
97 sids = talloc_realloc(tmp_ctx, sids, struct auth_SidAttr, num_sids + 2);
98 if (sids == NULL) {
99 TALLOC_FREE(tmp_ctx);
100 return NT_STATUS_NO_MEMORY;
103 sid_copy(&sids[num_sids].sid, &global_sid_World);
104 sids[num_sids].attrs = SE_GROUP_DEFAULT_FLAGS;
105 num_sids++;
107 sid_copy(&sids[num_sids].sid, &global_sid_Network);
108 sids[num_sids].attrs = SE_GROUP_DEFAULT_FLAGS;
109 num_sids++;
112 if (session_info_flags & AUTH_SESSION_INFO_AUTHENTICATED) {
113 sids = talloc_realloc(tmp_ctx, sids, struct auth_SidAttr, num_sids + 1);
114 if (sids == NULL) {
115 TALLOC_FREE(tmp_ctx);
116 return NT_STATUS_NO_MEMORY;
119 sid_copy(&sids[num_sids].sid, &global_sid_Authenticated_Users);
120 sids[num_sids].attrs = SE_GROUP_DEFAULT_FLAGS;
121 num_sids++;
124 if (session_info_flags & AUTH_SESSION_INFO_NTLM) {
125 sids = talloc_realloc(tmp_ctx, sids, struct auth_SidAttr, num_sids + 1);
126 if (sids == NULL) {
127 TALLOC_FREE(tmp_ctx);
128 return NT_STATUS_NO_MEMORY;
131 if (!dom_sid_parse(SID_NT_NTLM_AUTHENTICATION, &sids[num_sids].sid)) {
132 TALLOC_FREE(tmp_ctx);
133 return NT_STATUS_INTERNAL_ERROR;
135 sids[num_sids].attrs = SE_GROUP_DEFAULT_FLAGS;
136 num_sids++;
140 if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(&global_sid_Anonymous, &sids[PRIMARY_USER_SID_INDEX].sid)) {
141 /* Don't expand nested groups of system, anonymous etc*/
142 } else if (num_sids > PRIMARY_USER_SID_INDEX && dom_sid_equal(&global_sid_System, &sids[PRIMARY_USER_SID_INDEX].sid)) {
143 /* Don't expand nested groups of system, anonymous etc*/
144 } else if (sam_ctx != NULL) {
145 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:"LDB_OID_COMPARATOR_AND":=%u))",
146 GROUP_TYPE_BUILTIN_LOCAL_GROUP);
148 /* Search for each group in the token */
149 for (i = 0; i < num_sids; i++) {
150 struct dom_sid_buf buf;
151 const char *sid_dn;
152 DATA_BLOB sid_blob;
154 sid_dn = talloc_asprintf(
155 tmp_ctx,
156 "<SID=%s>",
157 dom_sid_str_buf(&sids[i].sid, &buf));
158 if (sid_dn == NULL) {
159 TALLOC_FREE(tmp_ctx);
160 return NT_STATUS_NO_MEMORY;
162 sid_blob = data_blob_string_const(sid_dn);
164 /* This function takes in memberOf values and expands
165 * them, as long as they meet the filter - so only
166 * builtin groups
168 * We already have the SID in the token, so set
169 * 'only childs' flag to true */
170 nt_status = dsdb_expand_nested_groups(sam_ctx, &sid_blob, true, filter,
171 tmp_ctx, &sids, &num_sids);
172 if (!NT_STATUS_IS_OK(nt_status)) {
173 talloc_free(tmp_ctx);
174 return nt_status;
179 if (device_info_dc != NULL) {
181 * Make a copy of the device SIDs in case we need to add extra SIDs on
182 * the end. One can never have too much copying.
184 num_device_sids = device_info_dc->num_sids;
185 device_sids = talloc_array(tmp_ctx,
186 struct auth_SidAttr,
187 num_device_sids);
188 if (device_sids == NULL) {
189 TALLOC_FREE(tmp_ctx);
190 return NT_STATUS_NO_MEMORY;
193 for (i = 0; i < num_device_sids; i++) {
194 device_sids[i] = device_info_dc->sids[i];
197 if (session_info_flags & AUTH_SESSION_INFO_DEVICE_DEFAULT_GROUPS) {
198 device_sids = talloc_realloc(tmp_ctx,
199 device_sids,
200 struct auth_SidAttr,
201 num_device_sids + 2);
202 if (device_sids == NULL) {
203 TALLOC_FREE(tmp_ctx);
204 return NT_STATUS_NO_MEMORY;
207 device_sids[num_device_sids++] = (struct auth_SidAttr) {
208 .sid = global_sid_World,
209 .attrs = SE_GROUP_DEFAULT_FLAGS,
211 device_sids[num_device_sids++] = (struct auth_SidAttr) {
212 .sid = global_sid_Network,
213 .attrs = SE_GROUP_DEFAULT_FLAGS,
217 if (session_info_flags & AUTH_SESSION_INFO_DEVICE_AUTHENTICATED) {
218 device_sids = talloc_realloc(tmp_ctx,
219 device_sids,
220 struct auth_SidAttr,
221 num_device_sids + 1);
222 if (device_sids == NULL) {
223 TALLOC_FREE(tmp_ctx);
224 return NT_STATUS_NO_MEMORY;
227 device_sids[num_device_sids++] = (struct auth_SidAttr) {
228 .sid = global_sid_Authenticated_Users,
229 .attrs = SE_GROUP_DEFAULT_FLAGS,
234 nt_status = security_token_create(mem_ctx,
235 lp_ctx,
236 num_sids,
237 sids,
238 num_device_sids,
239 device_sids,
240 auth_claims,
241 session_info_flags,
242 &security_token);
243 if (!NT_STATUS_IS_OK(nt_status)) {
244 TALLOC_FREE(tmp_ctx);
245 return nt_status;
248 talloc_steal(mem_ctx, security_token);
249 *_security_token = security_token;
250 talloc_free(tmp_ctx);
251 return NT_STATUS_OK;
254 _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
255 struct loadparm_context *lp_ctx, /* Optional, if you don't want privileges */
256 struct ldb_context *sam_ctx, /* Optional, if you don't want local groups */
257 const struct auth_user_info_dc *user_info_dc,
258 uint32_t session_info_flags,
259 struct auth_session_info **_session_info)
261 struct auth_session_info *session_info;
262 NTSTATUS nt_status;
264 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
265 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
267 session_info = talloc_zero(tmp_ctx, struct auth_session_info);
268 if (session_info == NULL) {
269 TALLOC_FREE(tmp_ctx);
270 return NT_STATUS_NO_MEMORY;
273 session_info->info = talloc_reference(session_info, user_info_dc->info);
274 if (session_info->info == NULL) {
275 TALLOC_FREE(tmp_ctx);
276 return NT_STATUS_NO_MEMORY;
279 session_info->torture = talloc_zero(session_info, struct auth_user_info_torture);
280 if (session_info->torture == NULL) {
281 TALLOC_FREE(tmp_ctx);
282 return NT_STATUS_NO_MEMORY;
284 session_info->torture->num_dc_sids = user_info_dc->num_sids;
285 session_info->torture->dc_sids = talloc_reference(session_info, user_info_dc->sids);
286 if (session_info->torture->dc_sids == NULL) {
287 TALLOC_FREE(tmp_ctx);
288 return NT_STATUS_NO_MEMORY;
291 /* unless set otherwise, the session key is the user session
292 * key from the auth subsystem */
293 session_info->session_key = data_blob_talloc(session_info, user_info_dc->user_session_key.data, user_info_dc->user_session_key.length);
294 if (!session_info->session_key.data && user_info_dc->user_session_key.length) {
295 TALLOC_FREE(tmp_ctx);
296 return NT_STATUS_NO_MEMORY;
299 nt_status = auth_generate_security_token(session_info,
300 lp_ctx,
301 sam_ctx,
302 user_info_dc,
303 NULL /*device_info_dc */,
304 (struct auth_claims) {},
305 session_info_flags,
306 &session_info->security_token);
307 if (!NT_STATUS_IS_OK(nt_status)) {
308 TALLOC_FREE(tmp_ctx);
309 return nt_status;
312 session_info->unique_session_token = GUID_random();
314 session_info->credentials = NULL;
316 session_info->ticket_type = user_info_dc->ticket_type;
318 talloc_steal(mem_ctx, session_info);
319 *_session_info = session_info;
320 talloc_free(tmp_ctx);
321 return NT_STATUS_OK;
325 /* Fill out the auth_session_info with a cli_credentials based on the
326 * auth_session_info we were forwarded over named pipe forwarding.
328 * NOTE: The structure members of session_info_transport are stolen
329 * with talloc_move() into auth_session_info for long term use
331 struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
332 struct auth_session_info_transport *session_info_transport,
333 struct loadparm_context *lp_ctx,
334 const char **reason)
336 struct auth_session_info *session_info;
337 session_info = talloc_steal(mem_ctx, session_info_transport->session_info);
339 * This is to allow us to check the type of this pointer using
340 * talloc_get_type()
342 talloc_set_name(session_info, "struct auth_session_info");
343 #ifdef HAVE_GSS_IMPORT_CRED
344 if (session_info_transport->exported_gssapi_credentials.length) {
345 struct cli_credentials *creds;
346 OM_uint32 minor_status;
347 gss_buffer_desc cred_token;
348 gss_cred_id_t cred_handle;
349 const char *error_string;
350 int ret;
351 bool ok;
353 DEBUG(10, ("Delegated credentials supplied by client\n"));
355 cred_token.value = session_info_transport->exported_gssapi_credentials.data;
356 cred_token.length = session_info_transport->exported_gssapi_credentials.length;
358 ret = gss_import_cred(&minor_status,
359 &cred_token,
360 &cred_handle);
361 if (ret != GSS_S_COMPLETE) {
362 *reason = "Internal error in gss_import_cred()";
363 return NULL;
366 creds = cli_credentials_init(session_info);
367 if (!creds) {
368 gss_release_cred(&minor_status, &cred_handle);
369 *reason = "Out of memory in cli_credentials_init()";
370 return NULL;
372 session_info->credentials = creds;
374 ok = cli_credentials_set_conf(creds, lp_ctx);
375 if (!ok) {
376 gss_release_cred(&minor_status, &cred_handle);
377 *reason = "Failed to load smb.conf";
378 return NULL;
381 /* Just so we don't segfault trying to get at a username */
382 cli_credentials_set_anonymous(creds);
384 ret = cli_credentials_set_client_gss_creds(creds,
385 lp_ctx,
386 cred_handle,
387 CRED_SPECIFIED,
388 &error_string);
389 if (ret) {
390 gss_release_cred(&minor_status, &cred_handle);
391 *reason = talloc_asprintf(mem_ctx,
392 "Failed to set pipe forwarded "
393 "creds: %s\n", error_string);
394 return NULL;
397 /* This credential handle isn't useful for password
398 * authentication, so ensure nobody tries to do that */
399 cli_credentials_set_kerberos_state(creds,
400 CRED_USE_KERBEROS_REQUIRED,
401 CRED_SPECIFIED);
404 #endif
405 return session_info;
409 /* Create a auth_session_info_transport from an auth_session_info.
411 * NOTE: Members of the auth_session_info_transport structure are
412 * talloc_referenced() into this structure, and should not be changed.
414 NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
415 struct auth_session_info *session_info,
416 struct tevent_context *event_ctx,
417 struct loadparm_context *lp_ctx,
418 struct auth_session_info_transport **transport_out)
421 struct auth_session_info_transport *session_info_transport
422 = talloc_zero(mem_ctx, struct auth_session_info_transport);
423 if (!session_info_transport) {
424 return NT_STATUS_NO_MEMORY;
426 session_info_transport->session_info = talloc_reference(session_info_transport, session_info);
427 if (!session_info_transport->session_info) {
428 return NT_STATUS_NO_MEMORY;
430 #ifdef HAVE_GSS_EXPORT_CRED
431 if (session_info->credentials) {
432 struct gssapi_creds_container *gcc;
433 OM_uint32 gret;
434 OM_uint32 minor_status;
435 gss_buffer_desc cred_token;
436 const char *error_string;
437 int ret;
439 ret = cli_credentials_get_client_gss_creds(session_info->credentials,
440 event_ctx,
441 lp_ctx,
442 &gcc, &error_string);
443 if (ret != 0) {
444 *transport_out = session_info_transport;
445 return NT_STATUS_OK;
448 gret = gss_export_cred(&minor_status,
449 gcc->creds,
450 &cred_token);
451 if (gret != GSS_S_COMPLETE) {
452 return NT_STATUS_INTERNAL_ERROR;
455 if (cred_token.length) {
456 session_info_transport->exported_gssapi_credentials
457 = data_blob_talloc(session_info_transport,
458 cred_token.value,
459 cred_token.length);
460 gss_release_buffer(&minor_status, &cred_token);
461 NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
464 #endif
465 *transport_out = session_info_transport;
466 return NT_STATUS_OK;
470 /* Produce a session_info for an arbitrary DN or principal in the local
471 * DB, assuming the local DB holds all the groups
473 * Supply either a principal or a DN
475 NTSTATUS authsam_get_session_info_principal(TALLOC_CTX *mem_ctx,
476 struct loadparm_context *lp_ctx,
477 struct ldb_context *sam_ctx,
478 const char *principal,
479 struct ldb_dn *user_dn,
480 uint32_t session_info_flags,
481 struct auth_session_info **session_info)
483 NTSTATUS nt_status;
484 struct auth_user_info_dc *user_info_dc;
485 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
486 if (!tmp_ctx) {
487 return NT_STATUS_NO_MEMORY;
489 nt_status = authsam_get_user_info_dc_principal(tmp_ctx, lp_ctx, sam_ctx,
490 principal, user_dn,
491 &user_info_dc);
492 if (!NT_STATUS_IS_OK(nt_status)) {
493 talloc_free(tmp_ctx);
494 return nt_status;
497 nt_status = auth_generate_session_info(tmp_ctx, lp_ctx, sam_ctx,
498 user_info_dc,
499 session_info_flags,
500 session_info);
502 if (NT_STATUS_IS_OK(nt_status)) {
503 talloc_steal(mem_ctx, *session_info);
505 talloc_free(tmp_ctx);
506 return nt_status;
510 * prints a struct auth_session_info security token to debug output.
512 void auth_session_info_debug(int dbg_lev,
513 const struct auth_session_info *session_info)
515 if (!session_info) {
516 DEBUG(dbg_lev, ("Session Info: (NULL)\n"));
517 return;
520 security_token_debug(DBGC_AUTH, dbg_lev,
521 session_info->security_token);
524 NTSTATUS encode_claims_set(TALLOC_CTX *mem_ctx,
525 struct CLAIMS_SET *claims_set,
526 DATA_BLOB *claims_blob)
528 TALLOC_CTX *tmp_ctx = NULL;
529 enum ndr_err_code ndr_err;
530 struct CLAIMS_SET_NDR *claims_set_info = NULL;
531 struct CLAIMS_SET_METADATA *metadata = NULL;
532 struct CLAIMS_SET_METADATA_NDR *metadata_ndr = NULL;
534 if (claims_blob == NULL) {
535 return NT_STATUS_INVALID_PARAMETER_3;
538 tmp_ctx = talloc_new(mem_ctx);
539 if (tmp_ctx == NULL) {
540 return NT_STATUS_NO_MEMORY;
543 metadata_ndr = talloc(tmp_ctx, struct CLAIMS_SET_METADATA_NDR);
544 if (metadata_ndr == NULL) {
545 talloc_free(tmp_ctx);
546 return NT_STATUS_NO_MEMORY;
549 metadata = talloc(metadata_ndr, struct CLAIMS_SET_METADATA);
550 if (metadata == NULL) {
551 talloc_free(tmp_ctx);
552 return NT_STATUS_NO_MEMORY;
555 claims_set_info = talloc(metadata, struct CLAIMS_SET_NDR);
556 if (claims_set_info == NULL) {
557 talloc_free(tmp_ctx);
558 return NT_STATUS_NO_MEMORY;
561 *metadata_ndr = (struct CLAIMS_SET_METADATA_NDR) {
562 .claims.metadata = metadata,
565 *metadata = (struct CLAIMS_SET_METADATA) {
566 .claims_set = claims_set_info,
567 .compression_format = CLAIMS_COMPRESSION_FORMAT_XPRESS_HUFF,
570 *claims_set_info = (struct CLAIMS_SET_NDR) {
571 .claims.claims = claims_set,
574 ndr_err = ndr_push_struct_blob(claims_blob, mem_ctx, metadata_ndr,
575 (ndr_push_flags_fn_t)ndr_push_CLAIMS_SET_METADATA_NDR);
576 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
577 NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err);
578 DBG_ERR("CLAIMS_SET_METADATA_NDR push failed: %s\n",
579 nt_errstr(nt_status));
581 talloc_free(tmp_ctx);
582 return nt_status;
585 talloc_free(tmp_ctx);
586 return NT_STATUS_OK;
590 * Construct a ‘claims_data’ structure from a claims blob, such as is found in a
591 * PAC.
593 NTSTATUS claims_data_from_encoded_claims_set(TALLOC_CTX *claims_data_ctx,
594 const DATA_BLOB *encoded_claims_set,
595 struct claims_data **out)
597 struct claims_data *claims_data = NULL;
598 DATA_BLOB data = {};
600 if (out == NULL) {
601 return NT_STATUS_INVALID_PARAMETER;
604 *out = NULL;
606 claims_data = talloc(claims_data_ctx, struct claims_data);
607 if (claims_data == NULL) {
608 return NT_STATUS_NO_MEMORY;
611 if (encoded_claims_set != NULL) {
613 * We make a copy of the data, for it might not be
614 * talloc‐allocated — we might have obtained it directly with
615 * krb5_pac_get_buffer().
617 data = data_blob_dup_talloc(claims_data, *encoded_claims_set);
618 if (data.length != encoded_claims_set->length) {
619 talloc_free(claims_data);
620 return NT_STATUS_NO_MEMORY;
624 *claims_data = (struct claims_data) {
625 .encoded_claims_set = data,
626 .flags = CLAIMS_DATA_ENCODED_CLAIMS_PRESENT,
629 *out = claims_data;
631 return NT_STATUS_OK;
635 * Construct a ‘claims_data’ structure from a talloc‐allocated claims set, such
636 * as we might build from searching the database. If this function returns
637 * successfully, it assumes ownership of the claims set.
639 NTSTATUS claims_data_from_claims_set(TALLOC_CTX *claims_data_ctx,
640 struct CLAIMS_SET *claims_set,
641 struct claims_data **out)
643 struct claims_data *claims_data = NULL;
645 if (out == NULL) {
646 return NT_STATUS_INVALID_PARAMETER;
649 *out = NULL;
651 claims_data = talloc(claims_data_ctx, struct claims_data);
652 if (claims_data == NULL) {
653 return NT_STATUS_NO_MEMORY;
655 *claims_data = (struct claims_data) {
656 .claims_set = talloc_steal(claims_data, claims_set),
657 .flags = CLAIMS_DATA_CLAIMS_PRESENT,
660 *out = claims_data;
662 return NT_STATUS_OK;
666 * From a ‘claims_data’ structure, return an encoded claims blob that can be put
667 * into a PAC.
669 NTSTATUS claims_data_encoded_claims_set(TALLOC_CTX *mem_ctx,
670 struct claims_data *claims_data,
671 DATA_BLOB *encoded_claims_set_out)
673 uint8_t *data = NULL;
674 size_t len;
676 if (encoded_claims_set_out == NULL) {
677 return NT_STATUS_INVALID_PARAMETER;
680 *encoded_claims_set_out = data_blob_null;
682 if (claims_data == NULL) {
683 return NT_STATUS_OK;
686 if (!(claims_data->flags & CLAIMS_DATA_ENCODED_CLAIMS_PRESENT)) {
687 NTSTATUS status;
689 /* See whether we have a claims set that we can encode. */
690 if (!(claims_data->flags & CLAIMS_DATA_CLAIMS_PRESENT)) {
691 return NT_STATUS_OK;
694 status = encode_claims_set(claims_data,
695 claims_data->claims_set,
696 &claims_data->encoded_claims_set);
697 if (!NT_STATUS_IS_OK(status)) {
698 return status;
701 claims_data->flags |= CLAIMS_DATA_ENCODED_CLAIMS_PRESENT;
704 if (claims_data->encoded_claims_set.data != NULL) {
705 data = talloc_reference(mem_ctx, claims_data->encoded_claims_set.data);
706 if (data == NULL) {
707 return NT_STATUS_NO_MEMORY;
710 len = claims_data->encoded_claims_set.length;
712 *encoded_claims_set_out = data_blob_const(data, len);
713 return NT_STATUS_OK;
717 * From a ‘claims_data’ structure, return an array of security claims that can
718 * be put in a security token for access checks.
720 NTSTATUS claims_data_security_claims(TALLOC_CTX *mem_ctx,
721 struct claims_data *claims_data,
722 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 **security_claims_out,
723 uint32_t *n_security_claims_out)
725 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *security_claims = NULL;
726 uint32_t n_security_claims;
727 NTSTATUS status;
729 if (security_claims_out == NULL) {
730 return NT_STATUS_INVALID_PARAMETER;
733 if (n_security_claims_out == NULL) {
734 return NT_STATUS_INVALID_PARAMETER;
737 *security_claims_out = NULL;
738 *n_security_claims_out = 0;
740 if (claims_data == NULL) {
741 return NT_STATUS_OK;
744 if (!(claims_data->flags & CLAIMS_DATA_SECURITY_CLAIMS_PRESENT)) {
745 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *decoded_claims = NULL;
746 uint32_t n_decoded_claims = 0;
748 /* See whether we have a claims set that we can convert. */
749 if (!(claims_data->flags & CLAIMS_DATA_CLAIMS_PRESENT)) {
752 * See whether we have an encoded claims set that we can
753 * decode.
755 if (!(claims_data->flags & CLAIMS_DATA_ENCODED_CLAIMS_PRESENT)) {
756 /* We don’t have anything. */
757 return NT_STATUS_OK;
760 /* Decode an existing claims set. */
762 if (claims_data->encoded_claims_set.length) {
763 TALLOC_CTX *tmp_ctx = NULL;
764 struct CLAIMS_SET_METADATA_NDR claims;
765 const struct CLAIMS_SET_METADATA *metadata = NULL;
766 enum ndr_err_code ndr_err;
768 tmp_ctx = talloc_new(claims_data);
769 if (tmp_ctx == NULL) {
770 return NT_STATUS_NO_MEMORY;
773 ndr_err = ndr_pull_struct_blob(&claims_data->encoded_claims_set,
774 tmp_ctx,
775 &claims,
776 (ndr_pull_flags_fn_t)ndr_pull_CLAIMS_SET_METADATA_NDR);
777 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
778 status = ndr_map_error2ntstatus(ndr_err);
779 DBG_ERR("Failed to parse encoded claims set: %s\n",
780 nt_errstr(status));
781 talloc_free(tmp_ctx);
782 return status;
785 metadata = claims.claims.metadata;
786 if (metadata != NULL) {
787 struct CLAIMS_SET_NDR *claims_set_ndr = metadata->claims_set;
788 if (claims_set_ndr != NULL) {
789 struct CLAIMS_SET **claims_set = &claims_set_ndr->claims.claims;
791 claims_data->claims_set = talloc_move(claims_data, claims_set);
795 talloc_free(tmp_ctx);
798 claims_data->flags |= CLAIMS_DATA_CLAIMS_PRESENT;
802 * Convert the decoded claims set to the security attribute
803 * claims format.
805 status = token_claims_to_claims_v1(claims_data,
806 claims_data->claims_set,
807 &decoded_claims,
808 &n_decoded_claims);
809 if (!NT_STATUS_IS_OK(status)) {
810 return status;
813 claims_data->security_claims = decoded_claims;
814 claims_data->n_security_claims = n_decoded_claims;
816 claims_data->flags |= CLAIMS_DATA_SECURITY_CLAIMS_PRESENT;
819 if (claims_data->security_claims != NULL) {
820 security_claims = talloc_reference(mem_ctx, claims_data->security_claims);
821 if (security_claims == NULL) {
822 return NT_STATUS_NO_MEMORY;
825 n_security_claims = claims_data->n_security_claims;
827 *security_claims_out = security_claims;
828 *n_security_claims_out = n_security_claims;
830 return NT_STATUS_OK;