Branch data Line data Source code
1 : : /* zxidmk.c - Handwritten nitty-gritty functions for constructing various elems
2 : : * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
3 : : * Author: Sampo Kellomaki (sampo@iki.fi)
4 : : * This is confidential unpublished proprietary source code of the author.
5 : : * NO WARRANTY, not even implied warranties. Contains trade secrets.
6 : : * Distribution prohibited unless authorized in writing.
7 : : * Licensed under Apache License 2.0, see file COPYING.
8 : : * $Id: zxidmk.c,v 1.27 2009-11-24 23:53:40 sampo Exp $
9 : : *
10 : : * 12.8.2006, created --Sampo
11 : : * 8.10.2007, added signing ArtifactResolve --Sampo
12 : : * 7.10.2008, added documentation --Sampo
13 : : * 24.8.2009, added XACML stuff --Sampo
14 : : */
15 : :
16 : : #include "errmac.h"
17 : : #include "zxid.h"
18 : : #include "zxidpriv.h"
19 : : #include "zxidutil.h"
20 : : #include "zxidconf.h"
21 : : #include "saml2.h"
22 : : #include "c/zx-const.h"
23 : : #include "c/zx-ns.h"
24 : : #include "c/zx-data.h"
25 : :
26 : : /*() Interpret ZXID standard form fields to construct a XML structure for AuthnRequest */
27 : :
28 : : /* Called by: a7n_test, x509_test, zxid_lecp_check, zxid_start_sso_url */
29 : : struct zx_sp_AuthnRequest_s* zxid_mk_authn_req(zxid_conf* cf, zxid_cgi* cgi)
30 : 7 : {
31 : 7 : char index[2] = "1";
32 : 7 : struct zx_sp_AuthnRequest_s* ar = zx_NEW_sp_AuthnRequest(cf->ctx,0);
33 : 7 : ar->Issuer = zxid_my_issuer(cf, &ar->gg);
34 : 7 : ar->ID = zxid_mk_id_attr(cf, &ar->gg, zx_ID_ATTR, "N", ZXID_ID_BITS);
35 : 7 : ar->Version = zx_ref_attr(cf->ctx, &ar->gg, zx_Version_ATTR, SAML2_VERSION);
36 : 7 : ar->IssueInstant = zxid_date_time_attr(cf, &ar->gg, zx_IssueInstant_ATTR, time(0));
37 : :
38 [ + - + - ]: 7 : if (cf->nice_name && cf->nice_name[0])
39 : 7 : ar->ProviderName = zx_ref_attr(cf->ctx, &ar->gg, zx_ProviderName_ATTR, cf->nice_name);
40 : :
41 [ + + - + ]: 7 : if (BOOL_STR_TEST(cgi->force_authn))
42 : 0 : ar->ForceAuthn = zx_ref_attr(cf->ctx, &ar->gg, zx_ForceAuthn_ATTR, XML_TRUE);
43 : :
44 [ + + - + ]: 7 : if (BOOL_STR_TEST(cgi->ispassive))
45 : 0 : ar->IsPassive = zx_ref_attr(cf->ctx, &ar->gg, zx_IsPassive_ATTR, XML_TRUE);
46 : :
47 [ + + - + ]: 7 : if (cgi->consent && cgi->consent[0])
48 : 0 : ar->Consent = zx_ref_attr(cf->ctx, &ar->gg, zx_Consent_ATTR, cgi->consent);
49 : :
50 [ + + - + ]: 7 : D("nid_fmt(%s) allow_create=%c ispassive=%c", cgi->nid_fmt, cgi->allow_create, cgi->ispassive);
51 [ + + - + : 7 : if (cgi->nid_fmt && cgi->nid_fmt[0] || cgi->affil && cgi->affil[0]
- + # # -
+ # # ]
52 : : || BOOL_STR_TEST(cgi->allow_create)) {
53 : 5 : ar->NameIDPolicy = zx_NEW_sp_NameIDPolicy(cf->ctx, &ar->gg);
54 : :
55 [ + - + - ]: 5 : if (cgi->nid_fmt && cgi->nid_fmt[0])
56 : 5 : ar->NameIDPolicy->Format = zx_ref_attr(cf->ctx, &ar->NameIDPolicy->gg, zx_Format_ATTR, zxid_saml2_map_nid_fmt(cgi->nid_fmt));
57 : :
58 [ + - - + ]: 5 : if (cgi->affil && cgi->affil[0])
59 : 0 : ar->NameIDPolicy->SPNameQualifier = zx_ref_attr(cf->ctx, &ar->NameIDPolicy->gg, zx_SPNameQualifier_ATTR, cgi->affil);
60 : :
61 [ + - + - ]: 5 : if (BOOL_STR_TEST(cgi->allow_create))
62 : 5 : ar->NameIDPolicy->AllowCreate = zx_ref_attr(cf->ctx, &ar->NameIDPolicy->gg, zx_AllowCreate_ATTR, XML_TRUE); /* default false */
63 : : }
64 : :
65 [ + + - + ]: 7 : if (cgi->authn_ctx && cgi->authn_ctx[0]) {
66 : 0 : ar->RequestedAuthnContext = zx_NEW_sp_RequestedAuthnContext(cf->ctx, &ar->gg);
67 : 0 : ar->RequestedAuthnContext->AuthnContextClassRef
68 : : = zx_ref_elem(cf->ctx, &ar->RequestedAuthnContext->gg, zx_sa_AuthnContextClassRef_ELEM, zxid_saml2_map_authn_ctx(cgi->authn_ctx));
69 [ # # # # ]: 0 : if (cgi->matching_rule && cgi->matching_rule[0])
70 : 0 : ar->RequestedAuthnContext->Comparison = zx_ref_attr(cf->ctx, &ar->RequestedAuthnContext->gg, zx_Comparison_ATTR, cgi->matching_rule);
71 : : }
72 [ + + - + ]: 7 : if (cgi->pr_ix && cgi->pr_ix != '0') {
73 : 0 : index[0] = cgi->pr_ix;
74 : 0 : ar->AssertionConsumerServiceIndex = zx_dup_attr(cf->ctx, &ar->gg, zx_AssertionConsumerServiceIndex_ATTR, index);
75 : : }
76 [ - + # # : 7 : if (cgi->get_complete && cgi->get_complete[0]
- + # # -
+ # # ]
77 : : || cgi->pxy_count && cgi->pxy_count[0]
78 : : || cgi->idppxylist && cgi->idppxylist[0]) {
79 : 0 : ar->Scoping = zx_NEW_sp_Scoping(cf->ctx, &ar->gg);
80 [ # # # # ]: 0 : if (cgi->pxy_count && cgi->pxy_count[0])
81 : 0 : ar->Scoping->ProxyCount = zx_ref_attr(cf->ctx, &ar->gg, zx_ProxyCount_ATTR, cgi->pxy_count);
82 : : #if 0
83 : : if (cgi->get_complete && cgi->get_complete[0] || cgi->idppxylist) {
84 : : ar->Scoping->IDPList = zx_NEW_sp_IDPList(cf->ctx, &ar->Scoping->gg);
85 : : /* *** Add IDPEntry and GetComplete */
86 : : }
87 : : #endif
88 : : }
89 : 7 : return ar;
90 : : }
91 : :
92 : : /*() Make the body for the ArtifactResolve SOAP message, signing it if needed. */
93 : :
94 : : /* Called by: zxid_sp_deref_art */
95 : : struct zx_sp_ArtifactResolve_s* zxid_mk_art_deref(zxid_conf* cf, zxid_entity* idp_meta, const char* artifact)
96 : 1 : {
97 : : X509* sign_cert;
98 : : EVP_PKEY* sign_pkey;
99 : : struct zxsig_ref refs;
100 : 1 : struct zx_sp_ArtifactResolve_s* ar = zx_NEW_sp_ArtifactResolve(cf->ctx,0);
101 : 1 : ar->Issuer = zxid_my_issuer(cf, &ar->gg);
102 : 1 : ar->ID = zxid_mk_id_attr(cf, &ar->gg, zx_ID_ATTR, "R", ZXID_ID_BITS);
103 : 1 : ar->Version = zx_ref_attr(cf->ctx, &ar->gg, zx_Version_ATTR, SAML2_VERSION);
104 : 1 : ar->IssueInstant = zxid_date_time_attr(cf, &ar->gg, zx_IssueInstant_ATTR, time(0));
105 : 1 : ar->Artifact = zx_ref_elem(cf->ctx, &ar->gg, zx_sp_Artifact_ELEM, artifact);
106 [ + - ]: 1 : if (cf->sso_soap_sign) {
107 : 1 : ZERO(&refs, sizeof(refs));
108 : 1 : refs.id = &ar->ID->g;
109 : 1 : refs.canon = zx_easy_enc_elem_sig(cf, &ar->gg);
110 [ + - ]: 1 : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert art deref")) {
111 : 1 : ar->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
112 : 1 : zx_add_kid_after_sa_Issuer(&ar->gg, &ar->Signature->gg);
113 : : }
114 : 1 : zx_str_free(cf->ctx, refs.canon);
115 : : }
116 : 1 : return ar;
117 : : }
118 : :
119 : : /*() Create SAML protocol <Status> element, given various levels of error input. */
120 : :
121 : : /* Called by: so_enc_dec, zxid_OK, zxid_nidmap_do x2, zxid_ssos_anreq x4 */
122 : : struct zx_sp_Status_s* zxid_mk_Status(zxid_conf* cf, struct zx_elem_s* father, const char* sc1, const char* sc2, const char* msg)
123 : 111 : {
124 : 111 : struct zx_sp_Status_s* st = zx_NEW_sp_Status(cf->ctx, father);
125 [ + + ]: 111 : if (msg)
126 : 2 : st->StatusMessage = zx_ref_elem(cf->ctx, &st->gg, zx_sp_StatusMessage_ELEM, msg);
127 : 111 : st->StatusCode = zx_NEW_sp_StatusCode(cf->ctx, &st->gg);
128 : 111 : st->StatusCode->Value = zx_ref_attr(cf->ctx, &st->StatusCode->gg, zx_Value_ATTR, sc1);
129 [ + + ]: 111 : if (sc2) {
130 : 2 : st->StatusCode->StatusCode = zx_NEW_sp_StatusCode(cf->ctx, &st->StatusCode->gg);
131 : 2 : st->StatusCode->StatusCode->Value = zx_ref_attr(cf->ctx, &st->StatusCode->StatusCode->gg, zx_Value_ATTR, sc2);
132 : : }
133 : 111 : return st;
134 : : }
135 : :
136 : : /*() Create SAML <Status> element indicating success. */
137 : :
138 : : /* Called by: zxid_idp_soap_dispatch, zxid_mk_saml_resp, zxid_mni_do, zxid_mni_do_ss, zxid_nidmap_do, zxid_slo_resp_redir, zxid_sp_soap_dispatch */
139 : : struct zx_sp_Status_s* zxid_OK(zxid_conf* cf, struct zx_elem_s* father)
140 : 109 : {
141 : 109 : return zxid_mk_Status(cf, father, SAML2_SC_SUCCESS, 0, 0);
142 : : }
143 : :
144 : : /*() Create EncryptedID given normal NameID and metadata of destination. Encryption
145 : : * will be done using encryption certificate of the receiver identified by the metadata. */
146 : :
147 : : /* Called by: zxid_mk_logout, zxid_mk_mni, zxid_mk_subj */
148 : : struct zx_sa_EncryptedID_s* zxid_mk_enc_id(zxid_conf* cf, struct zx_elem_s* father, zxid_nid* nid, zxid_entity* meta)
149 : 820 : {
150 : 820 : struct zx_sa_EncryptedID_s* encid = zx_NEW_sa_EncryptedID(cf->ctx, father);
151 : 820 : struct zx_str* ss = zx_easy_enc_elem_opt(cf, &nid->gg);
152 [ + - ]: 820 : if (cf->enckey_opt & 0x20) {
153 : : /* Nested EncryptedKey approach (Shibboleth early 2010) */
154 : 820 : ZX_ADD_KID(encid, EncryptedData, zxenc_pubkey_enc(cf, ss, 0, meta->enc_cert, "41", 0));
155 : : } else {
156 : : /* RetrievalMethod approach */
157 : 0 : ZX_ADD_KID(encid, EncryptedData, zxenc_pubkey_enc(cf, ss, &encid->EncryptedKey, meta->enc_cert, "38", meta));
158 : : }
159 : 820 : zx_str_free(cf->ctx, ss);
160 : 820 : return encid;
161 : : }
162 : :
163 : : /*() Create EncryptedAssertion given normal A7N and metadata of destination. Encryption
164 : : * will be done using encryption certificate of the receiver identified by the metadata. */
165 : :
166 : : /* Called by: zxid_add_fed_tok2epr, zxid_imreq, zxid_mk_saml_resp */
167 : : struct zx_sa_EncryptedAssertion_s* zxid_mk_enc_a7n(zxid_conf* cf, struct zx_elem_s* father, zxid_a7n* a7n, zxid_entity* meta)
168 : 136 : {
169 : 136 : struct zx_sa_EncryptedAssertion_s* enc_a7n = zx_NEW_sa_EncryptedAssertion(cf->ctx, father);
170 : 136 : struct zx_str* ss = zx_easy_enc_elem_opt(cf, &a7n->gg);
171 [ + - ]: 136 : if (cf->enckey_opt & 0x20) {
172 : : /* Nested EncryptedKey approach (Shibboleth early 2010) */
173 : 136 : ZX_ADD_KID(enc_a7n, EncryptedData, zxenc_pubkey_enc(cf, ss, 0, meta->enc_cert, "40", 0));
174 : : } else {
175 : : /* RetrievalMethod approach */
176 : 0 : ZX_ADD_KID(enc_a7n, EncryptedData, zxenc_pubkey_enc(cf, ss, &enc_a7n->EncryptedKey, meta->enc_cert, "39", meta));
177 : : }
178 : 136 : zx_str_free(cf->ctx, ss);
179 : 136 : return enc_a7n;
180 : : }
181 : :
182 : : /*() Create XML data structure for <LogoutRequest> element. Low level API. */
183 : :
184 : : /* Called by: test_ibm_cert_problem_enc_dec, zxid_sp_slo_redir, zxid_sp_slo_soap */
185 : : struct zx_sp_LogoutRequest_s* zxid_mk_logout(zxid_conf* cf, zxid_nid* nid, struct zx_str* ses_ix, zxid_entity* idp_meta)
186 : 3 : {
187 : 3 : struct zx_sp_LogoutRequest_s* r = zx_NEW_sp_LogoutRequest(cf->ctx,0);
188 : 3 : r->Issuer = zxid_my_issuer(cf, &r->gg);
189 : 3 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "L", ZXID_ID_BITS);
190 : 3 : r->Version = zx_ref_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
191 : 3 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
192 : :
193 [ + + - + ]: 3 : D("nameid_enc(%d) idp_meta(%p) enc_cert(%p)", cf->nameid_enc, idp_meta, idp_meta->enc_cert);
194 [ + - + + ]: 5 : if (cf->nameid_enc && idp_meta)
195 : 2 : r->EncryptedID = zxid_mk_enc_id(cf, &r->gg, nid, idp_meta);
196 : : else
197 : 1 : r->NameID = nid;
198 [ + + ]: 3 : if (ses_ix)
199 : 2 : r->SessionIndex = zx_new_str_elem(cf->ctx, &r->gg, zx_sp_SessionIndex_ELEM, ses_ix);
200 : 3 : return r;
201 : : }
202 : :
203 : : /*() Create XML data structure for <LogoutResponse> element. Low level API. */
204 : :
205 : : /* Called by: zxid_idp_soap_dispatch, zxid_slo_resp_redir, zxid_sp_soap_dispatch */
206 : : struct zx_sp_LogoutResponse_s* zxid_mk_logout_resp(zxid_conf* cf, struct zx_sp_Status_s* st, struct zx_str* req_id)
207 : 2 : {
208 : 2 : struct zx_sp_LogoutResponse_s* r = zx_NEW_sp_LogoutResponse(cf->ctx,0);
209 : 2 : r->Issuer = zxid_my_issuer(cf, &r->gg);
210 : 2 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "r", ZXID_ID_BITS);
211 : 2 : r->Version = zx_ref_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
212 : 2 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
213 [ + - ]: 2 : if (req_id)
214 : 2 : r->InResponseTo = zx_ref_len_attr(cf->ctx, &r->gg, zx_InResponseTo_ATTR, req_id->len, req_id->s);
215 : 2 : zx_add_kid(&r->gg, &st->gg);
216 : 2 : r->Status = st;
217 : 2 : return r;
218 : : }
219 : :
220 : : /*() Change SPNameID (newnym supplied), or Terminate federation (newnym not supplied).
221 : : * Create XML data structure for <ManageNameIDRequest> element. Low level API. */
222 : :
223 : : /* Called by: a7n_test, zxid_sp_mni_redir, zxid_sp_mni_soap */
224 : : struct zx_sp_ManageNameIDRequest_s* zxid_mk_mni(zxid_conf* cf, zxid_nid* nid, struct zx_str* new_nym, zxid_entity* idp_meta)
225 : 1 : {
226 : : struct zx_str* ss;
227 : : struct zx_xenc_EncryptedKey_s* ek;
228 : : struct zx_elem_s* newid;
229 : 1 : struct zx_sp_ManageNameIDRequest_s* r = zx_NEW_sp_ManageNameIDRequest(cf->ctx,0);
230 : 1 : r->Issuer = zxid_my_issuer(cf, &r->gg);
231 : 1 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "R", ZXID_ID_BITS);
232 : 1 : r->Version = zx_ref_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
233 : 1 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
234 [ + - + - ]: 2 : if (cf->nameid_enc && idp_meta) {
235 : 1 : r->EncryptedID = zxid_mk_enc_id(cf, &r->gg, nid, idp_meta);
236 [ + - + - ]: 2 : if (new_nym && new_nym->len) {
237 : 1 : newid = zx_new_str_elem(cf->ctx, 0, zx_sp_NewID_ELEM, new_nym);
238 : 1 : ss = zx_easy_enc_elem_opt(cf, newid);
239 : 1 : r->NewEncryptedID = zx_NEW_sp_NewEncryptedID(cf->ctx, &r->gg);
240 [ + - ]: 1 : if (cf->enckey_opt & 0x20) {
241 : : /* Nested EncryptedKey approach (Shibboleth early 2010) */
242 : 1 : ZX_ADD_KID(r->NewEncryptedID, EncryptedData, zxenc_pubkey_enc(cf, ss, 0, idp_meta->enc_cert, "43",0));
243 : : } else {
244 : : /* RetrievalMethod approach */
245 : 0 : ZX_ADD_KID(r->NewEncryptedID, EncryptedData, zxenc_pubkey_enc(cf, ss, &ek, idp_meta->enc_cert, "39", idp_meta));
246 : 0 : ZX_ADD_KID(r->NewEncryptedID, EncryptedKey, ek);
247 : 0 : zx_reverse_elem_lists(&r->NewEncryptedID->gg);
248 : : }
249 : 1 : zx_str_free(cf->ctx, ss);
250 : 1 : zx_free_elem(cf->ctx, newid, 0);
251 : : } else
252 : 0 : r->Terminate = zx_new_str_elem(cf->ctx, &r->gg, zx_sp_Terminate_ELEM, 0);
253 : : } else {
254 : 0 : r->NameID = nid;
255 [ # # # # ]: 0 : if (new_nym && new_nym->len)
256 : 0 : r->NewID = zx_new_str_elem(cf->ctx, &r->gg, zx_sp_NewID_ELEM, new_nym);
257 : : else
258 : 0 : r->Terminate = zx_new_str_elem(cf->ctx, &r->gg, zx_sp_Terminate_ELEM, 0);
259 : : }
260 : 1 : return r;
261 : : }
262 : :
263 : : /*() Create XML data structure for <ManageNameIDResponse> element. Low level API.*/
264 : :
265 : : /* Called by: zxid_mni_do, zxid_mni_do_ss */
266 : : struct zx_sp_ManageNameIDResponse_s* zxid_mk_mni_resp(zxid_conf* cf, struct zx_sp_Status_s* st, struct zx_str* req_id)
267 : 2 : {
268 : 2 : struct zx_sp_ManageNameIDResponse_s* r = zx_NEW_sp_ManageNameIDResponse(cf->ctx,0);
269 : 2 : r->Issuer = zxid_my_issuer(cf, &r->gg);
270 : 2 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "r", ZXID_ID_BITS);
271 : 2 : r->Version = zx_ref_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
272 : 2 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
273 [ + - ]: 2 : if (req_id)
274 : 2 : r->InResponseTo = zx_ref_len_attr(cf->ctx, &r->gg,zx_InResponseTo_ATTR, req_id->len,req_id->s);
275 : 2 : zx_add_kid(&r->gg, &st->gg);
276 : 2 : r->Status = st;
277 : 2 : return r;
278 : : }
279 : :
280 : : /* ======== IdP SSO Related ======== */
281 : :
282 : : /*() Constructor for Assertion */
283 : :
284 : : /* Called by: zxid_map_val_ss, zxid_mk_usr_a7n_to_sp, zxid_xacml_az_cd1_do x2, zxid_xacml_az_do x2 */
285 : : zxid_a7n* zxid_mk_a7n(zxid_conf* cf, struct zx_str* audience, struct zx_sa_Subject_s* subj, struct zx_sa_AuthnStatement_s* an_stmt, struct zx_sa_AttributeStatement_s* at_stmt)
286 : 916 : {
287 : 916 : zxid_a7n* a7n = zx_NEW_sa_Assertion(cf->ctx,0);
288 : 916 : a7n->Version = zx_dup_attr(cf->ctx, &a7n->gg, zx_Version_ATTR, SAML2_VERSION);
289 : 916 : a7n->ID = zxid_mk_id_attr(cf, &a7n->gg, zx_ID_ATTR, "A", ZXID_ID_BITS);
290 : 916 : a7n->IssueInstant = zxid_date_time_attr(cf, &a7n->gg, zx_IssueInstant_ATTR, time(0));
291 : 916 : a7n->Issuer = zxid_my_issuer(cf, &a7n->gg);
292 : 916 : a7n->Subject = subj;
293 [ + + ]: 916 : if (subj)
294 : 817 : zx_add_kid(&a7n->gg, &subj->gg);
295 : 916 : a7n->Conditions = zx_NEW_sa_Conditions(cf->ctx, &a7n->gg);
296 : 916 : a7n->Conditions->NotOnOrAfter = zxid_date_time_attr(cf, &a7n->Conditions->gg, zx_NotOnOrAfter_ATTR, time(0) + cf->a7nttl);
297 : 916 : a7n->Conditions->NotBefore = zxid_date_time_attr(cf, &a7n->Conditions->gg, zx_NotBefore_ATTR, time(0));
298 [ + + ]: 916 : if (audience) {
299 : 817 : a7n->Conditions->AudienceRestriction = zx_NEW_sa_AudienceRestriction(cf->ctx, &a7n->Conditions->gg);
300 : 817 : a7n->Conditions->AudienceRestriction->Audience = zx_new_str_elem(cf->ctx, &a7n->Conditions->AudienceRestriction->gg, zx_sa_Audience_ELEM, audience);
301 : : }
302 : 916 : a7n->AuthnStatement = an_stmt;
303 [ + + ]: 916 : if (an_stmt)
304 : 137 : zx_add_kid(&a7n->gg, &an_stmt->gg);
305 : 916 : a7n->AttributeStatement = at_stmt;
306 [ + + ]: 916 : if (at_stmt)
307 : 817 : zx_add_kid(&a7n->gg, &at_stmt->gg);
308 : 916 : zx_reverse_elem_lists(&a7n->gg);
309 : 916 : return a7n;
310 : : }
311 : :
312 : : /*() Construct Subject, possibly with EncryptedID */
313 : :
314 : : /* Called by: zxid_map_val_ss, zxid_mk_usr_a7n_to_sp, zxid_xacml_az_cd1_do, zxid_xacml_az_do */
315 : : struct zx_sa_Subject_s* zxid_mk_subj(zxid_conf* cf, struct zx_elem_s* father, zxid_entity* sp_meta, zxid_nid* nid)
316 : 817 : {
317 : 817 : struct zx_sa_Subject_s* subj = zx_NEW_sa_Subject(cf->ctx, father);
318 : :
319 : : #if 0
320 : : // , struct zx_str* affil, char* fmt
321 : : nid = zx_NEW_sa_NameID(cf->ctx,0);
322 : : nid->Format = zx_dup_str(cf->ctx, fmt); /* *** implement persistent */
323 : : nid->NameQualifier = zxid_my_ent_id(cf);
324 : : nid->SPNameQualifier = affil;
325 : : if (!strcmp(fmt, SAML2_TRANSIENT_NID_FMT)) {
326 : : zx_add_content(cf->ctx, nid, zxid_mk_id(cf, "T", ZXID_ID_BITS));
327 : : } else {
328 : : /* *** see also zxid_get_user_nameid() */
329 : : }
330 : : #endif
331 : :
332 [ + - ]: 817 : if (cf->nameid_enc) {
333 [ + - ]: 817 : if (sp_meta)
334 : 817 : subj->EncryptedID = zxid_mk_enc_id(cf, &subj->gg, nid, sp_meta);
335 : : else {
336 : 0 : ERR("NameID encryption confugred, but no metadata supplied. Defaulting to unencrypted NameID %d", 0);
337 : 0 : subj->NameID = nid;
338 : : }
339 : : } else
340 : 0 : subj->NameID = nid;
341 : : /* SAML spec is more lax than the schema: saml-core-2.0-os.pdf ll.653-657 says <SubjectConfirmation> [Zero or More] */
342 : 817 : return subj;
343 : : }
344 : :
345 : : /*() Construct AuthnStatement */
346 : :
347 : : /* Called by: zxid_mk_usr_a7n_to_sp */
348 : : struct zx_sa_AuthnStatement_s* zxid_mk_an_stmt(zxid_conf* cf, zxid_ses* ses, struct zx_elem_s* father, const char* eid)
349 : 137 : {
350 : : struct zx_str sesix;
351 : : struct zx_str eid_ss;
352 : : struct zx_str* ss;
353 : 137 : struct zx_sa_AuthnStatement_s* an_stmt = zx_NEW_sa_AuthnStatement(cf->ctx, father);
354 [ + + ]: 137 : if (ses->sesix) {
355 : : #if 0
356 : : an_stmt->SessionIndex = zx_dup_str(cf->ctx, ses->sesix);
357 : : #else
358 : : /* Need noncorrelatable session index */
359 : 72 : eid_ss.len = strlen(eid);
360 : 72 : eid_ss.s = (char*)eid;
361 : 72 : sesix.len = strlen(ses->sesix);
362 : 72 : sesix.s = ses->sesix;
363 : 72 : ss = zxid_psobj_enc(cf, &eid_ss, "ZS", &sesix);
364 : 72 : an_stmt->SessionIndex = zx_ref_len_attr(cf->ctx, &an_stmt->gg, zx_SessionIndex_ATTR, ss->len, ss->s);
365 : : #endif
366 : : }
367 : 137 : an_stmt->AuthnInstant = zxid_date_time_attr(cf, &an_stmt->gg, zx_AuthnInstant_ATTR, ses->an_instant);
368 : 137 : an_stmt->AuthnContext = zx_NEW_sa_AuthnContext(cf->ctx, &an_stmt->gg);
369 [ + + ]: 137 : if (ses->an_ctx)
370 : 72 : an_stmt->AuthnContext->AuthnContextClassRef
371 : : = zx_dup_elem(cf->ctx, &an_stmt->AuthnContext->gg, zx_sa_AuthnContextClassRef_ELEM, ses->an_ctx);
372 : : else {
373 : 65 : ERR("Session(%s) lacks AuthentContextClassRef. Output AuthnStatement will not satisfy all processing rules. See configuration option ISSUE_AUTHNCTX_PW.", ses->sesix);
374 : : }
375 : 137 : return an_stmt;
376 : : }
377 : :
378 : : /*() Construct SAML SAML Attribute from string */
379 : :
380 : : /* Called by: zxid_add_mapped_attr, zxid_map_val_ss, zxid_mk_sa_attribute */
381 : : struct zx_sa_Attribute_s* zxid_mk_sa_attribute_ss(zxid_conf* cf, struct zx_elem_s* father, const char* name, const char* namfmt, struct zx_str* val)
382 : 3806 : {
383 : : struct zx_root_s* r;
384 : 3806 : struct zx_sa_Attribute_s* at = zx_NEW_sa_Attribute(cf->ctx, father);
385 [ - + ]: 3806 : if (namfmt)
386 : 0 : at->NameFormat = zx_ref_attr(cf->ctx, &at->gg, zx_NameFormat_ATTR, namfmt);
387 : 3806 : at->Name = zx_dup_attr(cf->ctx, &at->gg, zx_Name_ATTR, name);
388 : 3806 : at->AttributeValue = zx_NEW_sa_AttributeValue(cf->ctx, &at->gg);
389 [ + + ]: 3806 : if (!val)
390 : 114 : return at;
391 : :
392 [ + + ]: 3692 : if (val->s[0] == '<') {
393 : : /* Looks like the value may be XML data. We need to pass it as XML data structure for
394 : : * canonicalization to work right (e.g. value is an A7N that is rendered one
395 : : * way when canonicalized independently, but in different way when canonicalized
396 : : * as part of a bigger structure - for example sa namespace may be omitted as it
397 : : * is already supplied by the parent element). */
398 : 816 : r = zx_dec_zx_root(cf->ctx, val->len, val->s, "sa at parse");
399 [ + - + - ]: 1632 : if (r && r->gg.kids) {
400 : 816 : at->AttributeValue->gg.kids = r->gg.kids;
401 [ + - - - : 816 : switch (r->gg.kids->g.tok) {
+ ]
402 : 136 : case zx_sa_Assertion_ELEM: at->AttributeValue->Assertion = (void*)r->gg.kids; break;
403 : 0 : case zx_sa_EncryptedAssertion_ELEM: at->AttributeValue->EncryptedAssertion = (void*)r->gg.kids; break;
404 : 0 : case zx_di12_ResourceOffering_ELEM: at->AttributeValue->ResourceOffering = (void*)r->gg.kids; break;
405 : 0 : case zx_a_EndpointReference_ELEM: at->AttributeValue->EndpointReference = (void*)r->gg.kids; break;
406 : : }
407 : 816 : ZX_FREE(cf->ctx, r);
408 : : } else {
409 : : /* XML did not parse, may be its just string data, after all. */
410 : 0 : zx_add_content(cf->ctx, &at->AttributeValue->gg, val);
411 : : }
412 : : } else {
413 : 2876 : zx_add_content(cf->ctx, &at->AttributeValue->gg, val);
414 : : }
415 : 3692 : return at;
416 : : }
417 : :
418 : : /*() Construct SAML SAML Attribute */
419 : :
420 : : /* Called by: zxid_gen_boots, zxid_mk_usr_a7n_to_sp x2 */
421 : : struct zx_sa_Attribute_s* zxid_mk_sa_attribute(zxid_conf* cf, struct zx_elem_s* father, const char* name, const char* namfmt, const char* val)
422 : 251 : {
423 [ + + ]: 251 : return zxid_mk_sa_attribute_ss(cf, father, name, namfmt, val?zx_dup_str(cf->ctx, val):0);
424 : : }
425 : :
426 : : /*() Construct SAML protocol Response (such as may be used to carry assertion in SSO) */
427 : :
428 : : /* Called by: zxid_idp_sso x4, zxid_ssos_anreq, zxid_xacml_az_cd1_do x2, zxid_xacml_az_do x2 */
429 : : struct zx_sp_Response_s* zxid_mk_saml_resp(zxid_conf* cf, zxid_a7n* a7n, zxid_entity* enc_meta)
430 : 105 : {
431 : 105 : struct zx_sp_Response_s* r = zx_NEW_sp_Response(cf->ctx,0);
432 : 105 : r->Version = zx_dup_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
433 : 105 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "R", ZXID_ID_BITS);
434 : 105 : r->Issuer = zxid_my_issuer(cf, &r->gg);
435 : 105 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
436 : 105 : r->Status = zxid_OK(cf, &r->gg);
437 [ + - ]: 105 : if (a7n) {
438 [ + + ]: 105 : if (enc_meta) {
439 : : /* See saml-bindings-2.0-os.pdf, sec 3.5.5.2 Security Considerations, p.24, ll.847-851
440 : : * After publication it was understood that the SHOULD NOT could be eliminated
441 : : * if EncryptedAssertion is used. */
442 : :
443 : 6 : r->EncryptedAssertion = zxid_mk_enc_a7n(cf, &r->gg, a7n, enc_meta);
444 : : } else {
445 : 99 : r->Assertion = a7n;
446 : 99 : zx_add_kid(&r->gg, &a7n->gg);
447 : : }
448 : : }
449 : 105 : zx_reverse_elem_lists(&r->gg);
450 : 105 : return r;
451 : : }
452 : :
453 : : /*() Construct XACML Response */
454 : :
455 : : /* Called by: zxid_ins_xacml_az_cd1_stmt x2, zxid_ins_xacml_az_stmt x2 */
456 : : struct zx_xac_Response_s* zxid_mk_xacml_resp(zxid_conf* cf, char* decision)
457 : 99 : {
458 : 99 : struct zx_xac_Response_s* resp = zx_NEW_xac_Response(cf->ctx,0);
459 : 99 : resp->Result = zx_NEW_xac_Result(cf->ctx, &resp->gg);
460 : 99 : resp->Result->Decision = zx_ref_elem(cf->ctx, &resp->Result->gg, zx_xac_Decision_ELEM, decision);
461 : 99 : resp->Result->Status = zx_NEW_xac_Status(cf->ctx, &resp->Result->gg);
462 : 99 : resp->Result->Status->StatusCode = zx_NEW_xac_StatusCode(cf->ctx, &resp->Result->Status->gg);
463 : 99 : resp->Result->Status->StatusCode->Value
464 : : = zx_ref_attr(cf->ctx, &resp->Result->Status->StatusCode->gg, zx_Value_ATTR, "urn:oasis:names:tc:xacml:1.0:status:ok");
465 : 99 : zx_reverse_elem_lists(&resp->Result->gg);
466 : 99 : return resp;
467 : : }
468 : :
469 : : /* Called by: zxid_pepmap_extract x3 */
470 : : struct zx_xac_Attribute_s* zxid_mk_xacml_simple_at(zxid_conf* cf, struct zx_elem_s* father, struct zx_str* atid, struct zx_str* attype, struct zx_str* atissuer, struct zx_str* atvalue)
471 : 4148 : {
472 : : struct zx_root_s* r;
473 : 4148 : struct zx_xac_Attribute_s* at = zx_NEW_xac_Attribute(cf->ctx, father);
474 : 4148 : at->AttributeId = zx_ref_len_attr(cf->ctx, &at->gg, zx_AttributeId_ATTR, atid->len, atid->s);
475 : 4148 : at->DataType = zx_ref_len_attr(cf->ctx, &at->gg, zx_DataType_ATTR, attype->len, attype->s);
476 [ + + ]: 4148 : if (atissuer)
477 : 1625 : at->Issuer = zx_ref_len_attr(cf->ctx, &at->gg, zx_Issuer_ATTR, atissuer->len, atissuer->s);
478 [ + + ]: 4148 : if (atvalue->s[0] == '<') {
479 : : /* Looks like the value may be XML data. We need to pass it as XML data structure for
480 : : * canonicalization to work right (e.g. value is an A7N that is rendered one
481 : : * way when canonicalized independently, but in different way when canonicalized
482 : : * as part of a bigger structure - for example sa namespace may be omitted as it
483 : : * is already supplied by the parent element). */
484 : 142 : r = zx_dec_zx_root(cf->ctx, atvalue->len, atvalue->s, "xac at parse");
485 [ + - + - ]: 284 : if (r && r->gg.kids) {
486 : 142 : at->AttributeValue = zx_new_elem(cf->ctx, &at->gg, zx_xac_AttributeValue_ELEM);
487 : 142 : at->AttributeValue->kids = r->gg.kids;
488 : 142 : ZX_FREE(cf->ctx, r);
489 : : } else {
490 : : /* XML did not parse, may be its just string data, after all. */
491 : 0 : at->AttributeValue = zx_new_str_elem(cf->ctx, &at->gg, zx_xac_AttributeValue_ELEM, atvalue);
492 : : }
493 : : } else {
494 : 4006 : at->AttributeValue = zx_new_str_elem(cf->ctx, &at->gg, zx_xac_AttributeValue_ELEM, atvalue);
495 : : }
496 : 4148 : zx_reverse_elem_lists(&at->gg);
497 : 4148 : return at;
498 : : }
499 : :
500 : : /*() Construct xac_Request */
501 : :
502 : : /* Called by: zxid_az_soap, zxid_mk_az, zxid_mk_az_cd1 */
503 : : struct zx_xac_Request_s* zxid_mk_xac_az(zxid_conf* cf, struct zx_elem_s* father, struct zx_xac_Attribute_s* subj, struct zx_xac_Attribute_s* rsrc, struct zx_xac_Attribute_s* act, struct zx_xac_Attribute_s* env)
504 : 93 : {
505 : 93 : struct zx_xac_Request_s* r = zx_NEW_xac_Request(cf->ctx, father);
506 : : /* N.B. The lists are already linked and only need to be attached to kids lists. */
507 : 93 : r->Subject = zx_NEW_xac_Subject(cf->ctx, &r->gg);
508 : 93 : r->Subject->gg.kids = (struct zx_elem_s*)(r->Subject->Attribute = subj);
509 : :
510 : 93 : r->Resource = zx_NEW_xac_Resource(cf->ctx, &r->gg);
511 : 93 : r->Resource->gg.kids = (struct zx_elem_s*)(r->Resource->Attribute = rsrc);
512 : :
513 : 93 : r->Action = zx_NEW_xac_Action(cf->ctx, &r->gg);
514 : 93 : r->Action->gg.kids = (struct zx_elem_s*)(r->Action->Attribute = act);
515 : :
516 : 93 : r->Environment = zx_NEW_xac_Environment(cf->ctx, &r->gg);
517 : 93 : r->Environment->gg.kids = (struct zx_elem_s*)(r->Environment->Attribute = env);
518 : :
519 : 93 : zx_reverse_elem_lists(&r->gg);
520 : 93 : return r;
521 : : }
522 : :
523 : : /*() Construct XACMLAuthzDecisionQuery */
524 : :
525 : : /* Called by: attribute_sort_test, zxid_az_soap */
526 : : struct zx_xasp_XACMLAuthzDecisionQuery_s* zxid_mk_az(zxid_conf* cf, struct zx_xac_Attribute_s* subj, struct zx_xac_Attribute_s* rsrc, struct zx_xac_Attribute_s* act, struct zx_xac_Attribute_s* env)
527 : 91 : {
528 : 91 : struct zx_xasp_XACMLAuthzDecisionQuery_s* r = zx_NEW_xasp_XACMLAuthzDecisionQuery(cf->ctx,0);
529 : 91 : r->Issuer = zxid_my_issuer(cf, &r->gg);
530 : 91 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "R", ZXID_ID_BITS);
531 : 91 : r->Version = zx_ref_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
532 : 91 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
533 : 91 : r->Request = zxid_mk_xac_az(cf, &r->gg, subj, rsrc, act, env);
534 : 91 : zx_reverse_elem_lists(&r->gg);
535 : 91 : return r;
536 : : }
537 : :
538 : : /*() Construct XACMLAuthzDecisionQuery according to Commitee Draft 1 */
539 : :
540 : : /* Called by: zxid_az_soap */
541 : : struct zx_xaspcd1_XACMLAuthzDecisionQuery_s* zxid_mk_az_cd1(zxid_conf* cf, struct zx_xac_Attribute_s* subj, struct zx_xac_Attribute_s* rsrc, struct zx_xac_Attribute_s* act, struct zx_xac_Attribute_s* env)
542 : 2 : {
543 : 2 : struct zx_xaspcd1_XACMLAuthzDecisionQuery_s* r = zx_NEW_xaspcd1_XACMLAuthzDecisionQuery(cf->ctx,0);
544 : 2 : r->Issuer = zxid_my_issuer(cf, &r->gg);
545 : 2 : r->ID = zxid_mk_id_attr(cf, &r->gg, zx_ID_ATTR, "R", ZXID_ID_BITS);
546 : 2 : r->Version = zx_ref_attr(cf->ctx, &r->gg, zx_Version_ATTR, SAML2_VERSION);
547 : 2 : r->IssueInstant = zxid_date_time_attr(cf, &r->gg, zx_IssueInstant_ATTR, time(0));
548 : 2 : r->Request = zxid_mk_xac_az(cf, &r->gg, subj, rsrc, act, env);
549 : 2 : zx_reverse_elem_lists(&r->gg);
550 : 2 : return r;
551 : : }
552 : :
553 : : /* EOF -- zxidmk.c */
|