1 /* zxidspx.c - Handwritten functions for SP dispatch
2 * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
4 * Author: Sampo Kellomaki (sampo@iki.fi)
5 * This is confidential unpublished proprietary source code of the author.
6 * NO WARRANTY, not even implied warranties. Contains trade secrets.
7 * Distribution prohibited unless authorized in writing.
8 * Licensed under Apache License 2.0, see file COPYING.
9 * $Id: zxidspx.c,v 1.14 2010-01-08 02:10:09 sampo Exp $
10 *
11 * 12.8.2006, created --Sampo
12 * 12.10.2007, tweaked for signing SLO and MNI --Sampo
13 * 14.4.2008, added SimpleSign --Sampo
14 * 7.10.2008, added documentation --Sampo
15 * 22.8.2009, added XACML dummy PDP support --Sampo
16 * 15.11.2009, added discovery service Query --Sampo
17 * 12.2.2010, added locking to lazy loading --Sampo
18 *
19 * See also zxid/sg/wsf-soap11.sg and zxid/c/zx-e-data.h, which is generated.
20 */
21
22 #include "platform.h" /* needed on Win32 for pthread_mutex_lock() et al. */
23
24 #include "errmac.h"
25 #include "zxid.h"
26 #include "zxidutil.h"
27 #include "zxidpriv.h"
28 #include "zxidconf.h"
29 #include "saml2.h"
30 #include "c/zx-const.h"
31 #include "c/zx-ns.h"
32 #include "c/zx-data.h"
33
34 /*() Extract an assertion, decrypting EncryptedAssertion if needed. */
35
36 /* Called by: sig_validate x2, zxid_imreq, zxid_sp_dig_oauth_sso_a7n, zxid_sp_dig_sso_a7n, zxid_wsp_validate_env x2 */
zxid_dec_a7n(zxid_conf * cf,zxid_a7n * a7n,struct zx_sa_EncryptedAssertion_s * enca7n)37 zxid_a7n* zxid_dec_a7n(zxid_conf* cf, zxid_a7n* a7n, struct zx_sa_EncryptedAssertion_s* enca7n)
38 {
39 struct zx_str* ss;
40 struct zx_root_s* r;
41
42 if (!a7n && enca7n) {
43 ss = zxenc_privkey_dec(cf, enca7n->EncryptedData, enca7n->EncryptedKey);
44 if (!ss || !ss->s || !ss->len) {
45 return 0;
46 }
47 r = zx_dec_zx_root(cf->ctx, ss->len, ss->s, "dec a7n");
48 if (!r) {
49 ERR("Failed to parse EncryptedAssertion buf(%.*s)", ss->len, ss->s);
50 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "BADXML", 0, "bad EncryptedAssertion");
51 return 0;
52 }
53 a7n = r->Assertion;
54 }
55 return a7n;
56 }
57
58 /*() Extract an assertion from Request, decrypting EncryptedAssertion if needed, and perform SSO */
59
60 /* Called by: zxid_idp_soap_dispatch, zxid_sp_dispatch, zxid_sp_soap_dispatch x3 */
zxid_sp_dig_sso_a7n(zxid_conf * cf,zxid_cgi * cgi,zxid_ses * ses,struct zx_sp_Response_s * resp)61 static int zxid_sp_dig_sso_a7n(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_sp_Response_s* resp)
62 {
63 zxid_a7n* a7n;
64 struct zx_ns_s* pop_seen = 0;
65
66 if (!zxid_chk_sig(cf, cgi, ses, &resp->gg, resp->Signature, resp->Issuer, 0, "Response"))
67 return 0;
68
69 a7n = zxid_dec_a7n(cf, resp->Assertion, resp->EncryptedAssertion);
70 if (a7n) {
71 zx_see_elem_ns(cf->ctx, &pop_seen, &resp->gg);
72 return zxid_sp_sso_finalize(cf, cgi, ses, a7n, pop_seen);
73 }
74 if (cf->anon_ok && cgi->rs && zx_match(cf->anon_ok, cgi->rs))
75 return zxid_sp_anon_finalize(cf, cgi, ses);
76 ERR("No Assertion found in SAML Response and anon_ok does not match %p", cf->anon_ok);
77 zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "ERR", 0, "sid(%s) No assertion", ses->sid?ses->sid:"");
78 return 0;
79 }
80
81 /*() Dispatch redirct or post binding requests (and sometimes responses).
82 *
83 * return:: a string (such as Location: header) and let the caller output it.
84 * Sometimes a dummy string is just output to indicate status, e.g.
85 * "O" for SSO OK, "K" for normal OK no further action needed,
86 * "M" show management screen, "I" forward to IdP dispatch, or
87 * "* ERR" for error situations. These special strings
88 * are allocated from static storage and MUST NOT be freed. Other
89 * strings such as "Location: ..." should be freed by caller. */
90
91 /* Called by: main x3, zxid_mgmt, zxid_simple_no_ses_cf, zxid_simple_ses_active_cf */
zxid_sp_dispatch(zxid_conf * cf,zxid_cgi * cgi,zxid_ses * ses)92 struct zx_str* zxid_sp_dispatch(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses)
93 {
94 struct zx_sp_LogoutRequest_s* req;
95 zxid_entity* idp_meta;
96 struct zx_str* loc;
97 struct zx_str* ss;
98 struct zx_str* ss2;
99 struct zx_root_s* r;
100 int ret;
101
102 ses->sigres = ZXSIG_NO_SIG;
103 r = zxid_decode_redir_or_post(cf, cgi, ses, 1);
104 if (!r)
105 return zx_dup_str(cf->ctx, "* ERR");
106
107 if (r->Response) {
108 if (!zxid_saml_ok(cf, cgi, r->Response->Status, "SAMLresp"))
109 return zx_dup_str(cf->ctx, "* ERR");
110 ret = zxid_sp_dig_sso_a7n(cf, cgi, ses, r->Response);
111 D("ret=%d ses=%p", ret, ses);
112 switch (ret) {
113 case ZXID_OK: return zx_dup_str(cf->ctx, "K");
114 case ZXID_SSO_OK: return zx_dup_str(cf->ctx, "O");
115 case ZXID_IDP_REQ: /* (PXY) Middle IdP of IdP Proxy flow */
116 return zx_dup_str(cf->ctx, zxid_simple_ses_active_cf(cf, cgi, ses, 0, 0x1fff));
117 case ZXID_FAIL:
118 D("*** FAIL, should send back to IdP select %d", 0);
119 return zx_dup_str(cf->ctx, "* ERR");
120 }
121 return zx_dup_str(cf->ctx, "M"); /* Management screen, please. */
122 }
123
124 if (req = r->LogoutRequest) {
125 if (cf->idp_ena) { /* *** Kludgy check */
126 D("IdP SLO %d", 0);
127 if (!zxid_idp_slo_do(cf, cgi, ses, req))
128 return zx_dup_str(cf->ctx, "* ERR");
129 } else {
130 if (!zxid_sp_slo_do(cf, cgi, ses, req))
131 return zx_dup_str(cf->ctx, "* ERR");
132 }
133 return zxid_slo_resp_redir(cf, cgi, req);
134 }
135
136 if (r->LogoutResponse) {
137 if (!zxid_saml_ok(cf, cgi, r->LogoutResponse->Status, "SLO resp"))
138 return zx_dup_str(cf->ctx, "* ERR");
139 cgi->msg = "Logout Response OK. Logged out.";
140 zxid_del_ses(cf, ses);
141 return zx_dup_str(cf->ctx, "K"); /* Prevent mgmt screen from displaying, show login screen. */
142 }
143
144 if (r->ManageNameIDRequest) {
145 idp_meta = zxid_get_ent_ss(cf, ZX_GET_CONTENT(r->ManageNameIDRequest->Issuer));
146 loc = zxid_idp_loc_raw(cf, cgi, idp_meta, ZXID_MNI_SVC, SAML2_REDIR, 0);
147 if (!loc)
148 return zx_dup_str(cf->ctx, "* ERR"); /* *** consider sending error page */
149 ss = zxid_mni_do_ss(cf, cgi, ses, r->ManageNameIDRequest, loc);
150 ss2 = zxid_saml2_resp_redir(cf, loc, ss, cgi->rs);
151 zx_str_free(cf->ctx, loc);
152 zx_str_free(cf->ctx, ss);
153 return ss2;
154 }
155
156 if (r->ManageNameIDResponse) {
157 if (!zxid_saml_ok(cf, cgi, r->ManageNameIDResponse->Status, "MNI resp")) {
158 ERR("MNI Response indicates failure. %d", 0);
159 return zx_dup_str(cf->ctx, "* ERR");
160 }
161 cgi->msg = "Manage NameID Response OK.";
162 return zx_dup_str(cf->ctx, "M"); /* Defederation doesn't have to mean SLO, show mgmt screen. */
163 }
164
165 if (r->AuthnRequest) {
166 D("AuthnRequest %d", 0);
167 return zx_dup_str(cf->ctx, "I");
168 }
169
170 if (cf->log_level > 0)
171 zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "SPDISP", 0, "sid(%s) unknown req or resp", STRNULLCHK(ses->sid));
172 ERR("Unknown request or response %p", r);
173 return zx_dup_str(cf->ctx, "* ERR");
174 }
175
176 /*() Create Authorization Decision */
177
178 /* Called by: zxid_xacml_az_do x2 */
zxid_ins_xacml_az_stmt(zxid_conf * cf,zxid_a7n * a7n,char * deci)179 static void zxid_ins_xacml_az_stmt(zxid_conf* cf, zxid_a7n* a7n, char* deci)
180 {
181 /* Two ways of doing assertion with XACMLAuthzDecisionStatement:
182 * 1. Explicitly include such statement in assertion
183 * 2. Use sa:Statement, but brandit with xsi:type
184 * The former is more logical, but the latter is what Jericho does
185 * and in effect the XACML interop events have done (de-facto standard?). */
186
187 #if 1
188 a7n->XACMLAuthzDecisionStatement = zx_NEW_xasa_XACMLAuthzDecisionStatement(cf->ctx,0);
189 ZX_ADD_KID(a7n->XACMLAuthzDecisionStatement, Response, zxid_mk_xacml_resp(cf, deci));
190 /* *** Add xaspcd1 and xasacd1 variants */
191 zx_add_kid_before(&a7n->gg, zx_xasa_XACMLPolicyStatement_ELEM, &a7n->XACMLAuthzDecisionStatement->gg);
192 #else
193 a7n->Statement = zx_NEW_sa_Statement(cf->ctx,0);
194 a7n->Statement->type = zx_ref_str(cf->ctx, "xasa:XACMLAuthzDecisionStatementType");
195 a7n->Statement->Response = zxid_mk_xacml_resp(cf, deci);
196 zx_add_kid_before(&a7n->gg, zx_sa_AuthnStatement_ELEM, a7n->Statement);
197 #endif
198 }
199
200 /* Called by: zxid_xacml_az_cd1_do x2 */
zxid_ins_xacml_az_cd1_stmt(zxid_conf * cf,zxid_a7n * a7n,char * deci)201 static void zxid_ins_xacml_az_cd1_stmt(zxid_conf* cf, zxid_a7n* a7n, char* deci)
202 {
203 /* Two ways of doing assertion with XACMLAuthzDecisionStatement:
204 * 1. Explicitly include such statement in assertion
205 * 2. Use sa:Statement, but brandit with xsi:type
206 * The former is more logical, but the latter is what Jericho does
207 * and in effect the XACML interop events have done (de-facto standard?). */
208
209 #if 1
210 a7n->xasacd1_XACMLAuthzDecisionStatement = zx_NEW_xasacd1_XACMLAuthzDecisionStatement(cf->ctx,0);
211 ZX_ADD_KID(a7n->xasacd1_XACMLAuthzDecisionStatement, Response, zxid_mk_xacml_resp(cf, deci));
212 /* *** Add xaspcd1 and xasacd1 variants */
213 zx_add_kid_before(&a7n->gg, zx_xasacd1_XACMLPolicyStatement_ELEM, &a7n->xasacd1_XACMLAuthzDecisionStatement->gg);
214 #else
215 a7n->Statement = zx_NEW_sa_Statement(cf->ctx,0);
216 a7n->Statement->type = zx_ref_str(cf->ctx, "xasacd1:XACMLAuthzDecisionStatementType");
217 a7n->Statement->Response = zxid_mk_xacml_resp(cf, deci);
218 zx_add_kid_before(&a7n->gg, zx_sa_AuthnStatement_ELEM, a7n->Statement);
219 #endif
220 }
221
222 /*() Process <XACMLAuthzDecisionQuery>. The response will have
223 * SAML assertion containing Authorization Decision Statement. */
224
225 /* Called by: zxid_sp_soap_dispatch */
zxid_xacml_az_do(zxid_conf * cf,zxid_cgi * cgi,zxid_ses * ses,struct zx_xasp_XACMLAuthzDecisionQuery_s * azq)226 static struct zx_sp_Response_s* zxid_xacml_az_do(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_xasp_XACMLAuthzDecisionQuery_s* azq)
227 {
228 zxid_a7n* a7n;
229 struct zx_str* affil;
230 struct zx_str* subj;
231 struct zx_str* ss;
232 struct zx_xac_Attribute_s* xac_at;
233
234 if (!zxid_chk_sig(cf, cgi, ses, &azq->gg, azq->Signature, azq->Issuer, 0, "XACMLAuthzDecisionQuery"))
235 return 0;
236
237 affil = subj = 0;
238 #if 0
239 affil = ar->NameIDPolicy && ar->NameIDPolicy->SPNameQualifier
240 ? ar->NameIDPolicy->SPNameQualifier
241 : ZX_GET_CONTENT(ar->Issuer);
242 subj = zxid_mk_subj(cf, ses, affil, sp_meta);
243 #endif
244 //a7n = zxid_mk_a7n(cf, affil, subj, 0, 0);
245 a7n = zxid_mk_a7n(cf, affil, 0, 0, 0);
246
247 if (azq->Request && azq->Request->Subject) {
248 for (xac_at = azq->Request->Subject->Attribute;
249 xac_at;
250 xac_at = (struct zx_xac_Attribute_s*)ZX_NEXT(xac_at)) {
251 if (xac_at->gg.g.tok != zx_xac_Attribute_ELEM)
252 continue;
253 if (xac_at->AttributeId->g.len == sizeof("role")-1
254 && !memcmp(xac_at->AttributeId->g.s, "role", sizeof("role")-1)) {
255 ss = ZX_GET_CONTENT(xac_at->AttributeValue);
256 if (ss?ss->len:0 == sizeof("deny")-1 && !memcmp(ss->s, "deny", sizeof("deny")-1)) {
257 D("PDP: DENY due to role=deny %d",0);
258 zxid_ins_xacml_az_stmt(cf, a7n, "Deny");
259 return zxid_mk_saml_resp(cf, a7n, 0);
260 }
261 }
262 }
263 }
264 D("PDP: PERMIT by default %d",0);
265 zxid_ins_xacml_az_stmt(cf, a7n, "Permit");
266 return zxid_mk_saml_resp(cf, a7n, 0);
267 }
268
269 /* Called by: zxid_sp_soap_dispatch */
zxid_xacml_az_cd1_do(zxid_conf * cf,zxid_cgi * cgi,zxid_ses * ses,struct zx_xaspcd1_XACMLAuthzDecisionQuery_s * azq)270 static struct zx_sp_Response_s* zxid_xacml_az_cd1_do(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_xaspcd1_XACMLAuthzDecisionQuery_s* azq)
271 {
272 zxid_a7n* a7n;
273 struct zx_str* affil;
274 struct zx_str* subj;
275 struct zx_str* ss;
276 struct zx_xac_Attribute_s* xac_at;
277
278 if (!zxid_chk_sig(cf, cgi, ses, &azq->gg, azq->Signature, azq->Issuer, 0, "XACMLAuthzDecisionQuery"))
279 return 0;
280
281 affil = subj = 0;
282 #if 0
283 affil = ar->NameIDPolicy && ar->NameIDPolicy->SPNameQualifier
284 ? ar->NameIDPolicy->SPNameQualifier
285 : ZX_GET_CONTENT(ar->Issuer);
286 subj = zxid_mk_subj(cf, ses, affil, sp_meta);
287 #endif
288 //a7n = zxid_mk_a7n(cf, affil, subj, 0, 0);
289 a7n = zxid_mk_a7n(cf, affil, 0, 0, 0);
290
291 if (azq->Request && azq->Request->Subject) {
292 for (xac_at = azq->Request->Subject->Attribute;
293 xac_at;
294 xac_at = (struct zx_xac_Attribute_s*)ZX_NEXT(xac_at)) {
295 if (xac_at->gg.g.tok == zx_xac_Attribute_ELEM)
296 continue;
297 if (xac_at->AttributeId->g.len == sizeof("role")-1
298 && !memcmp(xac_at->AttributeId->g.s, "role", sizeof("role")-1)) {
299 ss = ZX_GET_CONTENT(xac_at->AttributeValue);
300 if (ss?ss->len:0 == sizeof("deny")-1 && !memcmp(ss->s, "deny", sizeof("deny")-1)) {
301 D("PDP: Deny due to role=deny %d",0);
302 zxid_ins_xacml_az_cd1_stmt(cf, a7n, "Deny");
303 return zxid_mk_saml_resp(cf, a7n, 0);
304 }
305 }
306 }
307 }
308 D("PDP: Permit by default %d",0);
309 zxid_ins_xacml_az_cd1_stmt(cf, a7n, "Permit");
310 return zxid_mk_saml_resp(cf, a7n, 0);
311 }
312
313 /*() SOAP dispatch can also handle requests and responses received via artifact
314 * resolution. However only some combinations make sense.
315 * See zxid/sg/wsf-soap11.sg for the master SOAP dispatch from parsing perspective.
316 * Despite being called zxid_sp_soap_dispatch(), this actually dispatches
317 * the IdP functions, such as ManageNameIDRequest, XACMLAuthzDecisionQuery,
318 * SASLRequest (AnSvc), Query (Discovery), and People Service requests.
319 *
320 * Return 0 for failure, otherwise some success code such as ZXID_SSO_OK */
321
322 /* Called by: zxid_idp_soap_parse, zxid_sp_deref_art, zxid_sp_soap_parse */
zxid_sp_soap_dispatch(zxid_conf * cf,zxid_cgi * cgi,zxid_ses * ses,struct zx_root_s * r)323 int zxid_sp_soap_dispatch(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_root_s* r)
324 {
325 X509* sign_cert;
326 EVP_PKEY* sign_pkey;
327 struct zxsig_ref refs;
328 struct zx_e_Header_s* hdr; /* Request headers */
329 struct zx_e_Body_s* bdy; /* Request Body */
330 struct zx_e_Body_s* body; /* Response Body */
331 ses->sigres = ZXSIG_NO_SIG;
332
333 if (!r) goto bad;
334 if (!r->Envelope) goto bad;
335 hdr = r->Envelope->Header;
336 bdy = r->Envelope->Body;
337
338 if (cf->log_level > 1)
339 zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "W", "SPDISP", 0, "sid(%s) soap", STRNULLCHK(ses->sid));
340
341 if (bdy->ArtifactResponse) {
342 if (!zxid_saml_ok(cf, cgi, bdy->ArtifactResponse->Status, "ArtResp"))
343 return 0;
344 return zxid_sp_dig_sso_a7n(cf, cgi, ses, bdy->ArtifactResponse->Response);
345 }
346
347 if (bdy->Response) { /* PAOS/ECP response */
348 if (!zxid_saml_ok(cf, cgi, bdy->Response->Status, "PAOS Resp"))
349 return 0;
350 return zxid_sp_dig_sso_a7n(cf, cgi, ses, bdy->Response);
351 }
352
353 body = zx_NEW_e_Body(cf->ctx,0);
354
355 if (bdy->LogoutRequest) {
356 ses->issuer = ZX_GET_CONTENT(bdy->LogoutRequest->Issuer);
357 if (!zxid_sp_slo_do(cf, cgi, ses, bdy->LogoutRequest))
358 return 0;
359 ZX_ADD_KID(body, LogoutResponse, zxid_mk_logout_resp(cf, zxid_OK(cf, 0), &bdy->LogoutRequest->ID->g));
360 if (cf->sso_soap_resp_sign) {
361 ZERO(&refs, sizeof(refs));
362 refs.id = &body->LogoutResponse->ID->g;
363 refs.canon = zx_easy_enc_elem_sig(cf, &body->LogoutResponse->gg);
364 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert slor")) {
365 body->LogoutResponse->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
366 zx_add_kid_after_sa_Issuer(&body->LogoutResponse->gg,&body->LogoutResponse->Signature->gg);
367 }
368 zx_str_free(cf->ctx, refs.canon);
369 }
370 return zxid_soap_cgi_resp_body(cf, ses, body);
371 }
372
373 if (bdy->ManageNameIDRequest) {
374 ses->issuer = ZX_GET_CONTENT(bdy->ManageNameIDRequest->Issuer);
375 ZX_ADD_KID(body, ManageNameIDResponse, zxid_mni_do(cf, cgi, ses, bdy->ManageNameIDRequest));
376 if (cf->sso_soap_resp_sign) {
377 ZERO(&refs, sizeof(refs));
378 refs.id = &body->ManageNameIDResponse->ID->g;
379 refs.canon = zx_easy_enc_elem_sig(cf, &body->ManageNameIDResponse->gg);
380 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert mnir")) {
381 body->ManageNameIDResponse->Signature = zxsig_sign(cf->ctx, 1, &refs,sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
382 zx_add_kid_after_sa_Issuer(&body->ManageNameIDResponse->gg, &body->ManageNameIDResponse->Signature->gg);
383 }
384 zx_str_free(cf->ctx, refs.canon);
385 }
386 return zxid_soap_cgi_resp_body(cf, ses, body);
387 }
388
389 DD("as_ena=%d %p", cf->as_ena, bdy->SASLRequest);
390 if (cf->as_ena) {
391 if (bdy->SASLRequest) {
392 if (hdr && hdr->Sender && hdr->Sender->providerID)
393 ses->issuer = &hdr->Sender->providerID->g;
394 else
395 ses->issuer = 0;
396 //ses->issuer = ZX_GET_CONTENT(bdy->SASLRequest->Issuer);
397 ZX_ADD_KID(body, SASLResponse, zxid_idp_as_do(cf, bdy->SASLRequest));
398 #if 0
399 if (cf->sso_soap_resp_sign) {
400 ZERO(&refs, sizeof(refs));
401 refs.id = res->ID;
402 refs.canon = zx_EASY_ENC_SO_as_SASLResponse(cf->ctx, res);
403 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert asr")) {
404 res->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
405 zx_add_kid(&res->gg, &res->gg);
406 }
407 zx_str_free(cf->ctx, refs.canon);
408 }
409 #endif
410 return zxid_soap_cgi_resp_body(cf, ses, body);
411 }
412 }
413
414 if (cf->pdp_ena) {
415 if (bdy->XACMLAuthzDecisionQuery) {
416 ses->issuer = ZX_GET_CONTENT(bdy->XACMLAuthzDecisionQuery->Issuer);
417 D("XACMLAuthzDecisionQuery %d",0);
418 ZX_ADD_KID(body, Response, zxid_xacml_az_do(cf, cgi, ses, bdy->XACMLAuthzDecisionQuery));
419 if (cf->sso_soap_resp_sign) {
420 ZERO(&refs, sizeof(refs));
421 refs.id = &body->Response->ID->g;
422 refs.canon = zx_easy_enc_elem_sig(cf, &body->Response->gg);
423 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert azr")) {
424 body->Response->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
425 zx_add_kid_after_sa_Issuer(&body->Response->gg, &body->Response->Signature->gg);
426 }
427 zx_str_free(cf->ctx, refs.canon);
428 }
429 return zxid_soap_cgi_resp_body(cf, ses, body);
430 }
431 if (bdy->xaspcd1_XACMLAuthzDecisionQuery) {
432 ses->issuer = ZX_GET_CONTENT(bdy->XACMLAuthzDecisionQuery->Issuer);
433 D("xaspcd1:XACMLAuthzDecisionQuery %d",0);
434 ZX_ADD_KID(body, Response, zxid_xacml_az_cd1_do(cf, cgi, ses, bdy->xaspcd1_XACMLAuthzDecisionQuery));
435 if (cf->sso_soap_resp_sign) {
436 ZERO(&refs, sizeof(refs));
437 refs.id = &body->Response->ID->g;
438 refs.canon = zx_easy_enc_elem_sig(cf, &body->Response->gg);
439 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert azr")) {
440 body->Response->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
441 zx_add_kid_after_sa_Issuer(&body->Response->gg, &body->Response->Signature->gg);
442 }
443 zx_str_free(cf->ctx, refs.canon);
444 }
445 return zxid_soap_cgi_resp_body(cf, ses, body);
446 }
447 }
448
449 if (cf->idp_ena) {
450 if (bdy->ArtifactResolve) {
451 D("*** ArtifactResolve not implemented yet %d",0);
452 //if (!zxid_saml_ok(cf, cgi, bdy->ArtifactResponse->Status, "ArtResp"))
453 // return 0;
454 //return zxid_sp_dig_sso_a7n(cf, cgi, ses, bdy->ArtifactResponse->Response);
455 }
456
457 if (bdy->NameIDMappingRequest && cf->imps_ena) {
458 ses->issuer = ZX_GET_CONTENT(bdy->NameIDMappingRequest->Issuer);
459 ZX_ADD_KID(body, NameIDMappingResponse, zxid_nidmap_do(cf, bdy->NameIDMappingRequest));
460 if (cf->sso_soap_resp_sign) {
461 ZERO(&refs, sizeof(refs));
462 refs.id = &body->NameIDMappingResponse->ID->g;
463 refs.canon = zx_easy_enc_elem_sig(cf, &body->NameIDMappingResponse->gg);
464 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert mnir")) {
465 body->NameIDMappingResponse->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
466 zx_add_kid_after_sa_Issuer(&body->NameIDMappingResponse->gg, &body->NameIDMappingResponse->Signature->gg);
467 }
468 zx_str_free(cf->ctx, refs.canon);
469 }
470 return zxid_soap_cgi_resp_body(cf, ses, body);
471 }
472
473 if (!zxid_wsp_validate_env(cf, ses, "Resource=Discovery", r->Envelope)) {
474 return zxid_soap_cgi_resp_body(cf, ses, body); /* will include the fault */
475 }
476
477 if (bdy->Query) { /* Discovery 2.0 Query */
478 ZX_ADD_KID(body, QueryResponse, zxid_di_query(cf, ses, bdy->Query));
479 idwsf_resp:
480 #if 0
481 // *** should really sign the Body, putting sig in wsse:Security header
482 if (cf->sso_soap_resp_sign) {
483 ZERO(&refs, sizeof(refs));
484 refs.id = di_resp->ID;
485 refs.canon = zx_EASY_ENC_SO_e_Body(cf->ctx, body);
486 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert dir")) {
487 res->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
488 zx_add_kid_after_sa_Issuer(&res->gg, &res->Signature->gg);
489 }
490 zx_str_free(cf->ctx, refs.canon);
491 }
492 #endif
493
494 return zxid_soap_cgi_resp_body(cf, ses, body);
495 }
496
497 if (cf->imps_ena) {
498 if (bdy->AddEntityRequest) {
499 ZX_ADD_KID(body, AddEntityResponse, zxid_ps_addent_invite(cf, ses, bdy->AddEntityRequest));
500 goto idwsf_resp;
501 }
502 if (bdy->ResolveIdentifierRequest) {
503 ZX_ADD_KID(body, ResolveIdentifierResponse, zxid_ps_resolv_id(cf, ses, bdy->ResolveIdentifierRequest));
504 goto idwsf_resp;
505 }
506 if (bdy->IdentityMappingRequest) {
507 ZX_ADD_KID(body, IdentityMappingResponse, zxid_imreq(cf,ses, bdy->IdentityMappingRequest));
508 goto idwsf_resp;
509 }
510 }
511 if (bdy->AuthnRequest && cf->as_ena) {
512 ZX_ADD_KID(body, Response, zxid_ssos_anreq(cf, ses, bdy->AuthnRequest));
513 goto idwsf_resp;
514 }
515 }
516
517 bad:
518 ERR("Unknown SOAP request %p", r);
519 if (cf->log_level > 0)
520 zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "SPDISP", 0, "sid(%s) unknown soap req", STRNULLCHK(ses->sid));
521 return 0;
522 }
523
524 /*() Return 0 for failure, otherwise some success code such as ZXID_SSO_OK */
525
526 /* Called by: chkuid, main x6, zxid_mini_httpd_sso, zxid_simple_cf_ses */
zxid_sp_soap_parse(zxid_conf * cf,zxid_cgi * cgi,zxid_ses * ses,int len,char * buf)527 int zxid_sp_soap_parse(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, int len, char* buf)
528 {
529 struct zx_root_s* r;
530 r = zx_dec_zx_root(cf->ctx, len, buf, "sp soap parse");
531 if (!r || !r->Envelope || !r->Envelope->Body) {
532 ERR("Failed to parse SOAP request buf(%.*s)", len, buf);
533 zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "BADXML", 0, "sid(%s) bad soap req", STRNULLCHK(ses->sid));
534 return 0;
535 }
536 return zxid_sp_soap_dispatch(cf, cgi, ses, r);
537 }
538
539 /* EOF -- zxidspx.c */
540