Branch data Line data Source code
1 : : /* zxidmni.c - Handwritten functions for NameID Management logic for SP
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: zxidmni.c,v 1.10 2010-01-08 02:10:09 sampo Exp $
10 : : *
11 : : * 12.10.2007, split from zxidslo.c --Sampo
12 : : * 7.10.2008, added documentation --Sampo
13 : : * 12.2.2010, added locking to lazy loading --Sampo
14 : : */
15 : :
16 : : #include "errmac.h"
17 : : #include "zxid.h"
18 : : #include "zxidpriv.h"
19 : : #include "zxidconf.h"
20 : : #include "saml2.h"
21 : : #include "c/zx-const.h"
22 : : #include "c/zx-ns.h"
23 : : #include "c/zx-data.h"
24 : :
25 : : /* ============== MNI / NID Mgmt / Defederation ============== */
26 : :
27 : : /*() Change SPNameID (newnym supplied), or Terminate federation (newnym not supplied),
28 : : * using SAML2 SOAP binding. This is the (SP) client side that contacts the IdP. */
29 : :
30 : : /* Called by: a7n_test, zxid_mgmt, zxid_simple_ses_active_cf */
31 : : int zxid_sp_mni_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_str* new_nym)
32 : 1 : {
33 : : X509* sign_cert;
34 : : EVP_PKEY* sign_pkey;
35 : :
36 : 1 : zxid_get_ses_sso_a7n(cf, ses);
37 [ - + ]: 1 : if (ses->a7n) {
38 : : struct zxsig_ref refs;
39 : : struct zx_root_s* r;
40 : : struct zx_e_Body_s* body;
41 : : zxid_entity* idp_meta;
42 : :
43 [ # # ]: 0 : if (cf->log_level>0)
44 [ # # # # : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "W", "MNISOAP", ses->sid, "newnym(%.*s) loc", new_nym?new_nym->len:0, new_nym?new_nym->s:"");
# # # # #
# ]
45 : :
46 : 0 : idp_meta = zxid_get_ses_idp(cf, ses);
47 [ # # ]: 0 : if (!idp_meta)
48 : 0 : return 0;
49 : :
50 : 0 : body = zx_NEW_e_Body(cf->ctx,0);
51 : 0 : body->ManageNameIDRequest = zxid_mk_mni(cf, zxid_get_user_nameid(cf, ses->nameid), new_nym, idp_meta);
52 [ # # ]: 0 : if (cf->sso_soap_sign) {
53 : 0 : ZERO(&refs, sizeof(refs));
54 : 0 : refs.id = &body->ManageNameIDRequest->ID->g;
55 : 0 : refs.canon = zx_easy_enc_elem_sig(cf, &body->ManageNameIDRequest->gg);
56 [ # # ]: 0 : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert mni")) {
57 : 0 : body->ManageNameIDRequest->Signature
58 : : = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
59 : 0 : zx_add_kid_after_sa_Issuer(&body->ManageNameIDRequest->gg, &body->ManageNameIDRequest->Signature->gg);
60 : : }
61 : 0 : zx_str_free(cf->ctx, refs.canon);
62 : : }
63 : 0 : r = zxid_idp_soap(cf, cgi, ses, idp_meta, ZXID_MNI_SVC, body);
64 [ # # ]: 0 : if (!zxid_saml_ok(cf, cgi, r->Envelope->Body->ManageNameIDResponse->Status, "MniResp"))
65 : 0 : return 0;
66 : : /* *** Take actual steps to terminate the federation or change the name IDs */
67 : 0 : return 1;
68 : : }
69 [ - + ]: 1 : if (ses->a7n11) {
70 : 0 : ERR("Not implemented, SAML 1.1 assetion %d", 0);
71 : : }
72 [ - + ]: 1 : if (ses->a7n12) {
73 : 0 : ERR("Not implemented, ID-FF 1.2 type SAML 1.1 assetion %d", 0);
74 : : }
75 : 1 : ERR("Session sid(%s) lacks SSO assertion.", ses->sid);
76 : 1 : return 0;
77 : : }
78 : :
79 : : /*() Change SPNameID (newnym supplied), or Terminate federation (newnym not supplied),
80 : : * using SAML2 HTTP redirect binding. This is the (SP) client side that contacts the IdP.
81 : : * Return the HTTP 302 redirect LOCATION header + CRLF2. Returns the URL as string to which
82 : : * the environment should cause the user (browser) to be redirected. */
83 : :
84 : : /* Called by: zxid_mgmt, zxid_simple_ses_active_cf */
85 : : struct zx_str* zxid_sp_mni_redir(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_str* new_nym)
86 : 0 : {
87 : 0 : zxid_get_ses_sso_a7n(cf, ses);
88 [ # # ]: 0 : if (ses->a7n) {
89 : : struct zx_sp_ManageNameIDRequest_s* r;
90 : : struct zx_str* rs;
91 : : struct zx_str* loc;
92 : : zxid_entity* idp_meta;
93 : :
94 [ # # ]: 0 : if (cf->log_level>0)
95 [ # # # # : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(ses->nameid), "N", "W", "MNIREDIR", ses->sid, "newnym(%.*s)", new_nym?new_nym->len:0, new_nym?new_nym->s:"");
# # # # #
# ]
96 : :
97 : 0 : idp_meta = zxid_get_ses_idp(cf, ses);
98 [ # # ]: 0 : if (!idp_meta)
99 : 0 : return zx_dup_str(cf->ctx, "* ERR");
100 : :
101 : 0 : loc = zxid_idp_loc(cf, cgi, ses, idp_meta, ZXID_MNI_SVC, SAML2_REDIR);
102 [ # # ]: 0 : if (!loc)
103 : 0 : return zx_dup_str(cf->ctx, "* ERR");
104 : 0 : r = zxid_mk_mni(cf, zxid_get_user_nameid(cf, ses->nameid), new_nym, 0);
105 : 0 : r->Destination = zx_ref_len_attr(cf->ctx, &r->gg, zx_Destination_ATTR, loc->len, loc->s);
106 : 0 : rs = zx_easy_enc_elem_opt(cf, &r->gg);
107 [ # # # # ]: 0 : D("NIReq(%.*s)", rs->len, rs->s);
108 : 0 : return zxid_saml2_redir(cf, loc, rs, 0);
109 : : }
110 [ # # ]: 0 : if (ses->a7n11) {
111 : 0 : ERR("Not implemented, SAML 1.1 assetion %d", 0);
112 : : }
113 [ # # ]: 0 : if (ses->a7n12) {
114 : 0 : ERR("Not implemented, ID-FF 1.2 type SAML 1.1 assetion %d", 0);
115 : : }
116 : 0 : ERR("Session sid(%s) lacks SSO assertion.", ses->sid);
117 : 0 : return zx_dup_str(cf->ctx, "* ERR");
118 : : }
119 : :
120 : : /*() Process <ManageNameIDRequest>, presumably received from IdP. This is very rarely
121 : : * used. */
122 : :
123 : : /* Called by: zxid_idp_soap_dispatch, zxid_mni_do_ss, zxid_sp_soap_dispatch */
124 : : struct zx_sp_ManageNameIDResponse_s* zxid_mni_do(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_sp_ManageNameIDRequest_s* mni)
125 : 1 : {
126 : : zxid_nid* nid;
127 : : struct zx_str* newnym;
128 : :
129 [ - + ]: 1 : if (!zxid_chk_sig(cf, cgi, ses, &mni->gg, mni->Signature, mni->Issuer, 0, "ManageNameIDRequest"))
130 : 0 : return 0;
131 : :
132 : 1 : nid = zxid_decrypt_nameid(cf, mni->NameID, mni->EncryptedID);
133 [ + - + - : 1 : if (!ZX_GET_CONTENT(nid)) {
- + ]
134 : 0 : ERR("MNI failed: request does not have NameID. %p", nid);
135 : 0 : return 0;
136 : : }
137 : :
138 [ - + # # : 1 : newnym = zxid_decrypt_newnym(cf, ZX_GET_CONTENT(mni->NewID), mni->NewEncryptedID);
# # ]
139 [ - + ]: 1 : if (!newnym) {
140 [ # # # # ]: 0 : D("MNI Terminate %d",0);
141 : : } else {
142 [ - + # # ]: 1 : D("MNI Change newnym(%.*s)", newnym->len, newnym->s);
143 : 1 : zxid_user_change_nameid(cf, nid, newnym);
144 : : }
145 : 1 : return zxid_mk_mni_resp(cf, zxid_OK(cf,0), &mni->ID->g);
146 : : }
147 : :
148 : : /*() Wrapper for zxid_mni_do(), which see. */
149 : :
150 : : /* Called by: a7n_test, zxid_idp_dispatch, zxid_sp_dispatch */
151 : : struct zx_str* zxid_mni_do_ss(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zx_sp_ManageNameIDRequest_s* mni, struct zx_str* loc)
152 : 1 : {
153 : : struct zx_sp_ManageNameIDResponse_s* res;
154 : 1 : res = zxid_mk_mni_resp(cf, zxid_OK(cf,0), &mni->ID->g);
155 : 1 : res = zxid_mni_do(cf, cgi, ses, mni);
156 : 1 : res->Destination = zx_ref_len_attr(cf->ctx, &res->gg, zx_Destination_ATTR, loc->len, loc->s);
157 : 1 : return zx_easy_enc_elem_opt(cf, &res->gg);
158 : : }
159 : :
160 : : /* EOF -- zxidmni.c */
|