Branch data Line data Source code
1 : : /* zxididpx.c - Handwritten functions for IdP dispatch
2 : : * Copyright (c) 2008-2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 : : * This is confidential unpublished proprietary source code of the author.
4 : : * NO WARRANTY, not even implied warranties. Contains trade secrets.
5 : : * Distribution prohibited unless authorized in writing.
6 : : * Licensed under Apache License 2.0, see file COPYING.
7 : : * $Id: zxididpx.c,v 1.10 2010-01-08 02:10:09 sampo Exp $
8 : : *
9 : : * 14.11.2008, created --Sampo
10 : : * 12.2.2010, added locking to lazy loading --Sampo
11 : : *
12 : : * TODO: *** Review of all of IdP SLO and MNI code
13 : : */
14 : :
15 : : #include "errmac.h"
16 : : #include "zxid.h"
17 : : #include "zxidpriv.h"
18 : : #include "zxidconf.h"
19 : : #include "saml2.h"
20 : : #include "c/zx-const.h"
21 : : #include "c/zx-ns.h"
22 : : #include "c/zx-data.h"
23 : :
24 : : /* ============== Dispatch incoming requests and responses ============== */
25 : :
26 : : /*() Dispatch redirect and post binding requests.
27 : : *
28 : : * return:: a string (such as Location: header) and let the caller output it. */
29 : :
30 : : /* Called by: zxid_simple_ses_active_cf */
31 : : struct zx_str* zxid_idp_dispatch(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, int chk_dup)
32 : 5 : {
33 : : struct zx_sp_LogoutRequest_s* req;
34 : : zxid_entity* sp_meta;
35 : : struct zx_str* loc;
36 : : struct zx_str* ss;
37 : : struct zx_str* ss2;
38 : : struct zx_root_s* r;
39 : 5 : ses->sigres = ZXSIG_NO_SIG;
40 : :
41 : 5 : r = zxid_decode_redir_or_post(cf, cgi, ses, chk_dup);
42 [ - + ]: 5 : if (!r)
43 : 0 : return zx_dup_str(cf->ctx, "* ERR");
44 : :
45 [ + - ]: 5 : if (r->AuthnRequest)
46 : 5 : return zxid_idp_sso(cf, cgi, ses, r->AuthnRequest);
47 : :
48 [ # # ]: 0 : if (req = r->LogoutRequest) {
49 [ # # # # ]: 0 : D("IdP SLO %d", 0);
50 [ # # ]: 0 : if (cf->idp_ena) { /* *** Kludgy check */
51 [ # # ]: 0 : if (!zxid_idp_slo_do(cf, cgi, ses, req))
52 : 0 : return zx_dup_str(cf->ctx, "* ERR");
53 : : } else {
54 [ # # ]: 0 : if (!zxid_sp_slo_do(cf, cgi, ses, req))
55 : 0 : return zx_dup_str(cf->ctx, "* ERR");
56 : : }
57 : : /* *** Need to do much more to log out all other SPs of the session. */
58 : 0 : return zxid_slo_resp_redir(cf, cgi, req);
59 : : }
60 : :
61 [ # # ]: 0 : if (r->LogoutResponse) {
62 [ # # ]: 0 : if (!zxid_saml_ok(cf, cgi, r->LogoutResponse->Status, "SLO resp"))
63 : 0 : return zx_dup_str(cf->ctx, "* ERR");
64 : 0 : cgi->msg = "Logout Response OK. Logged out.";
65 : 0 : zxid_del_ses(cf, ses);
66 : 0 : return zx_dup_str(cf->ctx, "K"); /* Prevent mgmt screen from displaying, show login screen. */
67 : : }
68 : :
69 [ # # ]: 0 : if (r->ManageNameIDRequest) {
70 [ # # # # : 0 : sp_meta = zxid_get_ent_ss(cf, ZX_GET_CONTENT(r->ManageNameIDRequest->Issuer));
# # ]
71 : 0 : loc = zxid_sp_loc_raw(cf, cgi, sp_meta, ZXID_MNI_SVC, SAML2_REDIR, 0);
72 [ # # ]: 0 : if (!loc)
73 : 0 : return 0; /* *** consider sending error page */
74 : 0 : ss = zxid_mni_do_ss(cf, cgi, ses, r->ManageNameIDRequest, loc);
75 : 0 : ss2 = zxid_saml2_resp_redir(cf, loc, ss, cgi->rs);
76 : 0 : zx_str_free(cf->ctx, loc);
77 : 0 : zx_str_free(cf->ctx, ss);
78 : 0 : return ss2;
79 : : }
80 : :
81 [ # # ]: 0 : if (r->ManageNameIDResponse) {
82 [ # # ]: 0 : if (!zxid_saml_ok(cf, cgi, r->ManageNameIDResponse->Status, "MNI resp")) {
83 : 0 : ERR("MNI Response indicates failure. %d", 0);
84 : 0 : return zx_dup_str(cf->ctx, "* ERR");
85 : : }
86 : 0 : cgi->msg = "Manage NameID Response OK.";
87 : 0 : return zx_dup_str(cf->ctx, "M"); /* Defederation doesn't have to mean SLO, show mgmt screen. */
88 : : }
89 : :
90 [ # # ]: 0 : if (cf->log_level > 0)
91 [ # # # # : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "IDPDISP", 0, "sid(%s) unknown req or resp (loc)", ses->sid);
# # ]
92 : 0 : ERR("Unknown request or response %p", r);
93 : 0 : return zx_dup_str(cf->ctx, "* ERR");
94 : : }
95 : :
96 : : #if 0
97 : : /*() SOAP dispatch can also handle requests and responses received via artifact
98 : : * resolution. However only some combinations make sense.
99 : : * Return 0 for failure, otherwise some success code such as ZXID_SSO_OK
100 : : * *** NOT CALLED FROM ANYWHERE. See zxid_sp_soap_dispatch() for real action */
101 : :
102 : : /* Called by: */
103 : : int zxid_idp_soap_dispatch(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_root_s* r)
104 : : {
105 : : X509* sign_cert;
106 : : RSA* sign_pkey;
107 : : struct zxsig_ref refs;
108 : : struct zx_e_Body_s* body;
109 : : struct zx_sp_LogoutRequest_s* req;
110 : : ses->sigres = ZXSIG_NO_SIG;
111 : :
112 : : if (!r) goto bad;
113 : : if (!r->Envelope) goto bad;
114 : :
115 : : if (cf->log_level > 1)
116 : : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "W", "IDPDISP", 0, "sid(%s) soap", ses->sid);
117 : :
118 : : if (r->Envelope->Body->ArtifactResolve) {
119 : : D("ArtifactResolve not implemented yet %d",0);
120 : : //if (!zxid_saml_ok(cf, cgi, r->Envelope->Body->ArtifactResponse->Status, "ArtResp"))
121 : : // return 0;
122 : : //return zxid_sp_dig_sso_a7n(cf, cgi, ses, r->Envelope->Body->ArtifactResponse->Response);
123 : : }
124 : :
125 : : if (req = r->Envelope->Body->LogoutRequest) {
126 : : if (!zxid_idp_slo_do(cf, cgi, ses, req))
127 : : return 0;
128 : :
129 : : body = zx_NEW_e_Body(cf->ctx,0);
130 : : body->LogoutResponse = zxid_mk_logout_resp(cf, zxid_OK(cf), req->ID);
131 : : if (cf->sso_soap_resp_sign) {
132 : : ZERO(&refs, sizeof(refs));
133 : : refs.id = body->LogoutResponse->ID;
134 : : refs.canon = zx_EASY_ENC_SO_sp_LogoutResponse(cf->ctx, body->LogoutResponse);
135 : : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert idp slo")) {
136 : : body->LogoutResponse->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
137 : : zx_add_kid_after_sa_Issuer(&body->LogoutResponse->gg, &body->LogoutResponse->Signature->gg);
138 : : }
139 : : zx_str_free(cf->ctx, refs.canon);
140 : : }
141 : : return zxid_soap_cgi_resp_body(cf, ses, body);
142 : : }
143 : :
144 : : if (r->Envelope->Body->ManageNameIDRequest) {
145 : : struct zx_sp_ManageNameIDResponse_s* res = zxid_mni_do(cf, cgi, ses, r->Envelope->Body->ManageNameIDRequest);
146 : : body = zx_NEW_e_Body(cf->ctx,0);
147 : : body->ManageNameIDResponse = res;
148 : : if (cf->sso_soap_resp_sign) {
149 : : ZERO(&refs, sizeof(refs));
150 : : refs.id = res->ID;
151 : : refs.canon = zx_EASY_ENC_SO_sp_ManageNameIDResponse(cf->ctx, res);
152 : : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert idp mni")) {
153 : : res->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
154 : : zx_add_kid_after_sa_Issuer(&res->gg, &res->Signature->gg);
155 : : }
156 : : zx_str_free(cf->ctx, refs.canon);
157 : : }
158 : : return zxid_soap_cgi_resp_body(cf, body, ZX_GET_CONTENT(r->Envelope->Body->ManageNameIDRequest->Issuer));
159 : : }
160 : :
161 : : bad:
162 : : ERR("Unknown soap request %p", r);
163 : : if (cf->log_level > 0)
164 : : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "IDPDISP", 0, "sid(%s) unknown soap req", ses->sid);
165 : : return 0;
166 : : }
167 : :
168 : : /*() Return 0 for failure, otherwise some success code such as ZXID_SSO_OK */
169 : :
170 : : /* Called by: */
171 : : int zxid_idp_soap_parse(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, int len, char* buf)
172 : : {
173 : : struct zx_root_s* r;
174 : : r = zx_dec_zx_root(cf->ctx, len, buf, "idp soap parse");
175 : : if (!r || !r->Envelope || !r->Envelope->Body) {
176 : : ERR("Failed to parse SOAP request buf(%.*s)", len, buf);
177 : : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "C", "BADXML", 0, "sid(%s) bad soap req", ses->sid);
178 : : return 0;
179 : : }
180 : : return zxid_sp_soap_dispatch(cf, cgi, ses, r);
181 : : }
182 : : #endif
183 : :
184 : : /* EOF -- zxididpx.c */
|