Branch data Line data Source code
1 : : /* zxidim.c - Identity Mapping Service
2 : : * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 : : * Copyright (c) 2010 Risaris Ltd, 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: zxiddi.c,v 1.2 2009-11-24 23:53:40 sampo Exp $
10 : : *
11 : : * 16.9.2010, created --Sampo
12 : : *
13 : : * See also zxcall for client
14 : : * - liberty-idwsf-authn-svc-v2.0.pdf sec 7 "Identity Mapping Service"
15 : : *
16 : : * zxcot -e http://idp.tas3.pt:8081/zxididp?o=S 'IDMap Svc' \
17 : : * http://idp.tas3.pt:8081/zxididp?o=B urn:liberty:ims:2006-08 \
18 : : * | zxcot -b /var/zxid/idpdimd
19 : : *
20 : : * [SOAPAuthn2] "Liberty ID-WSF Authentication, Single Sign-On, and Identity Mapping Services Specification", liberty-idwsf-authn-svc-2.0-errata-v1.0.pdf from http://projectliberty.org/resource_center/specifications/
21 : : */
22 : :
23 : : #include "platform.h" /* for dirent.h */
24 : : #include "errmac.h"
25 : : #include "zxid.h"
26 : : #include "zxidpriv.h"
27 : : #include "zxidutil.h"
28 : : #include "zxidconf.h"
29 : : #include "saml2.h"
30 : : #include "wsf.h"
31 : : #include "c/zx-const.h"
32 : : #include "c/zx-ns.h"
33 : : #include "c/zx-data.h"
34 : :
35 : : /*() ID-WSF Single Sign-On Service (SSOS): Issue SSO assertion in response to receiving a token.
36 : : * See also zxid_idp_sso() for similar code. */
37 : :
38 : : /* Called by: a7n_test, zxid_sp_soap_dispatch */
39 : : struct zx_sp_Response_s* zxid_ssos_anreq(zxid_conf* cf, zxid_ses* ses, struct zx_sp_AuthnRequest_s* ar)
40 : 1 : {
41 : : zxid_a7n* outa7n;
42 : : X509* sign_cert;
43 : : EVP_PKEY* sign_pkey;
44 : : struct zxsig_ref refs;
45 : : zxid_cgi cgi;
46 : : char logop[8];
47 : 1 : struct zx_sp_Response_s* resp = zx_NEW_sp_Response(cf->ctx,0);
48 : : struct zx_str* payload;
49 : : struct zx_str* ss;
50 : : zxid_entity* sp_meta;
51 : : char uid[ZXID_MAX_BUF];
52 : 1 : D_INDENT("ssos: ");
53 : :
54 [ + - + - : 1 : if (!ar || !ZX_GET_CONTENT(ar->Issuer)) {
+ - - + ]
55 : 0 : ERR("No Issuer found in AuthnRequest %p", ar);
56 : 0 : resp->Status = zxid_mk_Status(cf, &resp->gg, "Fail", 0, 0);
57 : 0 : D_DEDENT("ssos: ");
58 : 0 : return resp;
59 : : }
60 : :
61 [ - + ]: 1 : if (!zxid_idp_map_nid2uid(cf, sizeof(uid), uid, ses->tgtnameid, 0)) {
62 : 0 : resp->Status = zxid_mk_Status(cf, &resp->gg, "Fail", 0, 0);
63 : 0 : D_DEDENT("ssos: ");
64 : 0 : return resp;
65 : : }
66 : :
67 : 1 : ZERO(&cgi, sizeof(cgi));
68 : 1 : ses->an_instant = time(0); /* This will be later used by AuthnStatement constructor. */
69 : 1 : ses->an_ctx = SAML_AUTHCTX_PREVSESS; /* Is there better one to use for token based auth? */
70 : 1 : ss = zxid_mk_id(cf, "OSES", ZXID_ID_BITS); /* Onetime Master session. Each pairwise SSO should have its own to avoid correlation. The session can not be used for SLO. */
71 : 1 : ses->sesix = ss->s;
72 : 1 : ZX_FREE(cf->ctx, ss);
73 : 1 : ses->sid = cgi.sid = ses->sesix;
74 : 1 : cgi.uid = uid;
75 : 1 : ses->uid = cgi.uid;
76 : : /*zxid_put_ses(cf, ses);*/
77 : :
78 [ + - + - : 1 : sp_meta = zxid_get_ent_ss(cf, ZX_GET_CONTENT(ar->Issuer));
+ - ]
79 [ - + ]: 1 : if (!sp_meta) {
80 : 0 : ERR("The metadata for Issuer of the AuthnRequest could not be found or fetched %d", 0);
81 : 0 : resp->Status = zxid_mk_Status(cf, &resp->gg, "Fail", 0, 0);
82 : 0 : D_DEDENT("ssos: ");
83 : 0 : return resp;
84 : : }
85 [ + - - + ]: 1 : D("sp_eid(%s)", sp_meta->eid);
86 : :
87 : 1 : outa7n = zxid_sso_issue_a7n(cf, &cgi, ses, &ses->srcts, sp_meta, 0, 0, logop, ar);
88 : :
89 [ + - ]: 1 : if (cf->sso_sign & ZXID_SSO_SIGN_A7N) {
90 : 1 : ZERO(&refs, sizeof(refs));
91 : 1 : refs.id = &outa7n->ID->g;
92 : 1 : refs.canon = zx_easy_enc_elem_sig(cf, &outa7n->gg);
93 [ + - ]: 1 : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert paos")) {
94 : 1 : outa7n->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
95 : 1 : zx_add_kid_after_sa_Issuer(&outa7n->gg, &outa7n->Signature->gg);
96 : : }
97 : : }
98 [ + - ]: 1 : resp = zxid_mk_saml_resp(cf, outa7n, cf->post_a7n_enc?sp_meta:0);
99 : 1 : payload = zxid_anoint_sso_resp(cf, cf->sso_sign & ZXID_SSO_SIGN_RESP, resp, ar);
100 [ - + ]: 1 : if (!payload) {
101 : 0 : resp->Status = zxid_mk_Status(cf, &resp->gg, "Fail", 0, 0);
102 : 0 : D_DEDENT("ssos: ");
103 : 0 : return resp;
104 : : }
105 : 1 : zx_str_free(cf->ctx, payload);
106 : :
107 : 1 : zxlogwsp(cf, ses, "K", logop, uid, "SSOS");
108 : :
109 : : /* *** Generate SOAP envelope with ECP header as required by ECP PAOS */
110 : :
111 : 1 : D_DEDENT("ssos: ");
112 : 1 : return resp;
113 : : }
114 : :
115 : : /*(i) Use Liberty ID-WSF 2.0 Identity Mapping Service to convert
116 : : * the identity of the session to identity token in the namespace
117 : : * of the entity at_eid.
118 : : *
119 : : * This is the main work horse for WSCs wishing to call WSPs via EPR.
120 : : *
121 : : * cf:: ZXID configuration object, also used for memory allocation
122 : : * ses:: Session object in whose EPR cache the file will be searched
123 : : * at_eid:: EntityID of the destination namespace
124 : : * how:: How to make mapping (0 = invocaction identity, 1 = target identity)
125 : : * return:: 0 on failure, token on success
126 : : *
127 : : * This will generate <im:IdentityMappingRequest> in SOAP envelope to the
128 : : * IM service of the user, as discovered dynamically. For the discovery to work,
129 : : * the service must have been provisioned to the discovery, with command
130 : : * similar to
131 : : *
132 : : * zxcot -e http://idp.tas3.pt:8081/zxididp?o=S 'IDMap Svc' \
133 : : * http://idp.tas3.pt:8081/zxididp?o=B urn:liberty:ims:2006-08 \
134 : : * | zxcot -b /var/zxid/idpdimd
135 : : *
136 : : * The received identity token is stored in session. From there it is usually
137 : : * automatically used in appropriate context (see the how argument). Typically
138 : : * you would not use the return value for anything else than checking for an error.
139 : : */
140 : :
141 : : /* Called by: zxcall_main */
142 : : zxid_tok* zxid_map_identity_token(zxid_conf* cf, zxid_ses* ses, const char* at_eid, int how)
143 : 1 : {
144 : : struct zx_e_Envelope_s* env;
145 : : struct zx_im_MappingInput_s* inp;
146 : : struct zx_im_MappingOutput_s* out;
147 : : zxid_epr* epr;
148 : 1 : epr = zxid_get_epr(cf, ses, XMLNS_IMS, 0, 0, 0, 1);
149 [ - + ]: 1 : if (!epr) {
150 [ # # ]: 0 : ERR("No Identity Mapping Service discovered svc(%s) how=%d", STRNULLCHK(at_eid), how);
151 : 0 : return 0;
152 : : }
153 : :
154 [ + - ]: 1 : INFO("Identity Mapping Svc svc(%s) how=%d...", STRNULLCHK(at_eid), how);
155 : 1 : env = zx_NEW_e_Envelope(cf->ctx,0);
156 : 1 : env->Body = zx_NEW_e_Body(cf->ctx, &env->gg);
157 : 1 : env->Header = zx_NEW_e_Header(cf->ctx, &env->gg);
158 : 1 : env->Body->IdentityMappingRequest = zx_NEW_im_IdentityMappingRequest(cf->ctx, &env->Body->gg);
159 : 1 : env->Body->IdentityMappingRequest->MappingInput = inp = zx_NEW_im_MappingInput(cf->ctx, &env->Body->IdentityMappingRequest->gg);
160 : : //inp->Token = zx_NEW_sec_Token(cf->ctx, &inp->gg);
161 : : //inp->Token->ref = zx_dup_str(cf->ctx, "#A7N");
162 : 1 : inp->TokenPolicy = zx_NEW_sec_TokenPolicy(cf->ctx, &inp->gg);
163 : 1 : inp->TokenPolicy->type = zx_dup_attr(cf->ctx, &inp->TokenPolicy->gg, zx_type_ATTR, TOKNUSG_SEC);
164 : : #if 0 /* Default is true anyway */
165 : : inp->TokenPolicy->wantDSEPR = zx_dup_attr(cf->ctx, &inp->TokenPolicy->gg, zx_wantDSEPR_ATTR, "1");
166 : : #endif
167 : 1 : inp->TokenPolicy->NameIDPolicy = zx_NEW_sp_NameIDPolicy(cf->ctx, &inp->TokenPolicy->gg);
168 : 1 : inp->TokenPolicy->NameIDPolicy->Format = zx_ref_attr(cf->ctx, &inp->TokenPolicy->NameIDPolicy->gg, zx_Format_ATTR, zxid_saml2_map_nid_fmt("prstnt"));
169 : 1 : inp->TokenPolicy->NameIDPolicy->SPNameQualifier = zx_dup_attr(cf->ctx, &inp->TokenPolicy->NameIDPolicy->gg, zx_SPNameQualifier_ATTR, at_eid);
170 : 1 : inp->TokenPolicy->NameIDPolicy->AllowCreate = zx_ref_attr(cf->ctx, &inp->TokenPolicy->NameIDPolicy->gg, zx_AllowCreate_ATTR, XML_TRUE); /* default false */
171 : :
172 : 1 : env = zxid_wsc_call(cf, ses, epr, env, 0);
173 [ - + # # ]: 1 : if (!env || !env->Body) {
174 : 1 : ERR("Identity Mapping call failed envelope=%p", env);
175 : 1 : return 0;
176 : : }
177 [ # # ]: 0 : if (!env->Body->IdentityMappingResponse) {
178 [ # # ]: 0 : ERR("No Identity Mapping Response at_eid(%s)", STRNULLCHK(at_eid));
179 : 0 : return 0;
180 : : }
181 : :
182 : 0 : for (out = env->Body->IdentityMappingResponse->MappingOutput;
183 [ # # # # ]: 0 : out && out->gg.g.tok == zx_im_MappingOutput_ELEM;
184 : : out = (void*)ZX_NEXT(out)) {
185 [ # # # ]: 0 : switch (how) {
186 : : case 0:
187 [ # # # # ]: 0 : D("Invocation token set %p", out->Token);
188 : 0 : ses->call_invoktok = out->Token;
189 : 0 : break;
190 : : case 1:
191 [ # # # # ]: 0 : D("Target Identity token set %p", out->Token);
192 : 0 : ses->call_tgttok = out->Token;
193 : : break;
194 : : }
195 : 0 : return out->Token; /* Not really iterating */
196 : : }
197 : 0 : return 0; /* never reached */
198 : : }
199 : :
200 : : /*() ID-WSF Identity Mapping Service: Issue token in response to receiving a token */
201 : :
202 : : /* Called by: zxid_sp_soap_dispatch */
203 : : struct zx_im_IdentityMappingResponse_s* zxid_imreq(zxid_conf* cf, zxid_ses* ses, struct zx_im_IdentityMappingRequest_s* req)
204 : 0 : {
205 : 0 : struct zx_im_IdentityMappingResponse_s* resp = zx_NEW_im_IdentityMappingResponse(cf->ctx,0);
206 : : struct zx_im_MappingInput_s* mapinp;
207 : : struct zx_im_MappingOutput_s* mapout;
208 : : zxid_tok* tok;
209 : : zxid_a7n* ina7n;
210 : : zxid_a7n* outa7n;
211 : : struct zx_str* issue_to;
212 : : char allow_create;
213 : : char* nid_fmt;
214 : : zxid_nid* nameid;
215 : : char* logop;
216 : 0 : int n_mapped = 0;
217 : : zxid_entity* sp_meta;
218 : : char sp_name_buf[1024];
219 : : char uid[ZXID_MAX_BUF];
220 : 0 : D_INDENT("imreq: ");
221 : 0 : ses->uid = uid;
222 : :
223 [ # # # # ]: 0 : if (!req || !req->MappingInput) {
224 : 0 : ERR("No IdentityMappingRequest/MappingInput found (WSC error) %p", req);
225 : 0 : resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
226 : 0 : D_DEDENT("imreq: ");
227 : 0 : return resp;
228 : : }
229 : :
230 : 0 : for (mapinp = req->MappingInput;
231 [ # # # # ]: 0 : mapinp && mapinp->gg.g.tok == zx_im_MappingInput_ELEM;
232 : 0 : mapinp = (struct zx_im_MappingInput_s*)mapinp->gg.g.n) {
233 : :
234 [ # # ]: 0 : if (tok = mapinp->Token) {
235 [ # # # # ]: 0 : if (tok->Assertion || tok->EncryptedAssertion) {
236 : 0 : ina7n = zxid_dec_a7n(cf, tok->Assertion, tok->EncryptedAssertion);
237 [ # # # # ]: 0 : if (!ina7n || !ina7n->Subject) {
238 : 0 : ERR("Missing or malformed MappingInput/Token/Assertion %p", ina7n);
239 : 0 : continue;
240 : : }
241 : 0 : ses->tgtnameid = zxid_decrypt_nameid(cf, ina7n->Subject->NameID, ina7n->Subject->EncryptedID);
242 [ # # # # : 0 : } else if (tok->ref && !ZX_STRCMP(&tok->ref->g, &ses->a7n->ID->g)) {
# # # # ]
243 [ # # # # ]: 0 : D("Token->ref(%.*s) matches invocation security token.", tok->ref->g.len, tok->ref->g.s);
244 : : /* N.B. This is a common optimization as it often happens that invoker (delegatee) needs to
245 : : * IDMap his own token, while delegator's token can usually be found using discovery. */
246 : 0 : ina7n = ses->a7n;
247 : : } else {
248 : 0 : ERR("*** Missing IdentityMappingRequest/MappingInput/Token/(Encrypted)Assertion (WSC error). Using invocation identity instead. %p", tok);
249 : 0 : ina7n = ses->a7n;
250 : : }
251 : : } else {
252 : 0 : ERR("*** Missing IdentityMappingRequest/MappingInput/Token (WSC error). Using invocation identity instead. %d", 0);
253 : 0 : ina7n = ses->a7n;
254 : : }
255 : :
256 [ # # ]: 0 : if (!mapinp->TokenPolicy) {
257 : 0 : ERR("Missing TokenPolicy. %d", 0);
258 : 0 : resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
259 : 0 : D_DEDENT("imreq: ");
260 : 0 : return resp;
261 : : }
262 : :
263 [ # # ]: 0 : if (!zxid_idp_map_nid2uid(cf, sizeof(uid), uid, ses->tgtnameid, &resp->Status)) {
264 : 0 : D_DEDENT("imreq: ");
265 : 0 : return resp;
266 : : }
267 : :
268 : : /* Figure out destination */
269 : :
270 [ # # ]: 0 : if (mapinp->TokenPolicy->NameIDPolicy) {
271 : 0 : issue_to = &mapinp->TokenPolicy->NameIDPolicy->SPNameQualifier->g;
272 [ # # # # : 0 : nid_fmt = ZX_STR_EQ(&mapinp->TokenPolicy->NameIDPolicy->Format->g, SAML2_TRANSIENT_NID_FMT) ? "trnsnt" : "prstnt";
# # ]
273 [ # # # # : 0 : allow_create = XML_TRUE_TEST(&mapinp->TokenPolicy->NameIDPolicy->AllowCreate->g) ? '1':'0';
# # # # #
# ]
274 : : } else {
275 : 0 : issue_to = &mapinp->TokenPolicy->issueTo->g;
276 : 0 : nid_fmt = "prstnt";
277 : 0 : allow_create = '1';
278 : : }
279 : :
280 [ # # ]: 0 : if (!issue_to) {
281 : 0 : ERR("No NameIDPolicy->SPNameQualifier or issueTo %p", mapinp->TokenPolicy);
282 : 0 : resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
283 : 0 : D_DEDENT("imreq: ");
284 : 0 : return resp;
285 : : }
286 : 0 : zxid_nice_sha1(cf, sp_name_buf, sizeof(sp_name_buf), issue_to, issue_to, 7);
287 : :
288 : : /* Check for federation */
289 : :
290 : 0 : nameid = zxid_check_fed(cf, issue_to, uid, allow_create, 0, 0, 0, sp_name_buf);
291 [ # # ]: 0 : if (nameid) {
292 [ # # # # ]: 0 : if (nid_fmt && !strcmp(nid_fmt, "trnsnt")) {
293 [ # # # # : 0 : D("Despite old fed, using transient due to nid_fmt(%s)", STRNULLCHKD(nid_fmt));
# # ]
294 : 0 : zxid_mk_transient_nid(cf, nameid, sp_name_buf, uid);
295 : 0 : logop = "ITIM";
296 : : } else
297 : 0 : logop = "IFIM";
298 : : } else {
299 [ # # # # ]: 0 : D("No nameid (because of no federation), using transient %d", 0);
300 : 0 : nameid = zx_NEW_sa_NameID(cf->ctx,0);
301 : 0 : zxid_mk_transient_nid(cf, nameid, sp_name_buf, uid);
302 : 0 : logop = "ITIM";
303 : : }
304 : :
305 : : /* Issue the assertion and sign it. */
306 : :
307 : 0 : sp_meta = zxid_get_ent_ss(cf, issue_to);
308 [ # # ]: 0 : if (!sp_meta) {
309 : 0 : ERR("The metadata for provider could not be found or fetched. Reject. %d", 0);
310 : 0 : resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
311 : 0 : D_DEDENT("imreq: ");
312 : 0 : return resp;
313 : : }
314 : :
315 : 0 : outa7n = zxid_mk_usr_a7n_to_sp(cf, ses, nameid, sp_meta, sp_name_buf, 1);
316 : :
317 [ # # ]: 0 : if (!zxid_anoint_a7n(cf, cf->sso_sign & ZXID_SSO_SIGN_A7N, outa7n, issue_to, "IMA7N", uid)) {
318 : 0 : resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "Fail", 0, 0, 0);
319 : 0 : D_DEDENT("imreq: ");
320 : 0 : return resp;
321 : : }
322 : :
323 : : /* Formulate mapping output */
324 : :
325 : 0 : resp->MappingOutput = mapout = zx_NEW_im_MappingOutput(cf->ctx, &resp->gg);
326 [ # # # # : 0 : if (mapinp->reqID && mapinp->reqID->g.len && mapinp->reqID->g.s)
# # ]
327 : 0 : mapout->reqRef = zx_dup_len_attr(cf->ctx, &mapout->gg, zx_reqRef_ATTR, mapinp->reqID->g.len, mapinp->reqID->g.s);
328 : 0 : mapout->Token = zx_NEW_sec_Token(cf->ctx, &mapout->gg);
329 [ # # ]: 0 : if (cf->di_a7n_enc) {
330 : 0 : mapout->Token->EncryptedAssertion = zxid_mk_enc_a7n(cf, &mapout->Token->gg, outa7n, sp_meta);
331 : : } else {
332 : 0 : zx_add_kid(&mapout->Token->gg, &outa7n->gg);
333 : 0 : mapout->Token->Assertion = outa7n;
334 : : }
335 : :
336 : 0 : ++n_mapped;
337 : 0 : zxlogwsp(cf, ses, "K", logop, 0,"n=%d", n_mapped);
338 : : }
339 : :
340 [ # # # # ]: 0 : D("TOTAL Identity Mappings issued %d", n_mapped);
341 : 0 : zxlogwsp(cf, ses, "K", "IMOK", 0, "n=%d", n_mapped);
342 : 0 : resp->Status = zxid_mk_lu_Status(cf, &resp->gg, "OK", 0, 0, 0);
343 : 0 : D_DEDENT("imreq: ");
344 : 0 : return resp;
345 : : }
346 : :
347 : : /*(i) Use SAML 2.0 NameID Mapping Service to convert
348 : : * the identity of the session to identity token in the namespace
349 : : * of the entity at_eid.
350 : : *
351 : : * cf:: ZXID configuration object, also used for memory allocation
352 : : * ses:: Session object in whose EPR cache the file will be searched
353 : : * at_eid:: EntityID of the destination namespace
354 : : * how:: How to make mapping (0 = invocaction identity, 1 = target identity)
355 : : * return:: 0 on failure, token on success
356 : : *
357 : : * This will generate <im:IdentityMappingRequest> in SOAP envelope to the
358 : : * IM service of the user, as discovered dynamically. For the discovery to work,
359 : : * the service must have been provisioned to the discovery, with command
360 : : * similar to
361 : : *
362 : : * zxcot -e http://idp.tas3.pt:8081/zxididp?o=S 'IDMap Svc' \
363 : : * http://idp.tas3.pt:8081/zxididp?o=B urn:liberty:ims:2006-08 \
364 : : * | zxcot -b /var/zxid/idpdimd
365 : : *
366 : : * The received identity token is stored in session. From there it is usually
367 : : * automatically used in appropriate context (see the how argument). Typically
368 : : * you would not use the return value for anything else than checking for an error.
369 : : */
370 : :
371 : : /* Called by: zxcall_main */
372 : : zxid_tok* zxid_nidmap_identity_token(zxid_conf* cf, zxid_ses* ses, const char* at_eid, int how)
373 : 1 : {
374 : : struct zx_e_Envelope_s* env;
375 : : struct zx_sec_Token_s* tok;
376 : : struct zx_sp_NameIDMappingRequest_s* req;
377 : : zxid_epr* epr;
378 : 1 : epr = zxid_get_epr(cf, ses, XMLNS_IMS, 0, 0, 0, 1);
379 [ - + ]: 1 : if (!epr) {
380 [ # # ]: 0 : ERR("No Identity Mapping Service discovered svc(%s) how=%d", STRNULLCHK(at_eid), how);
381 : 0 : return 0;
382 : : }
383 : :
384 [ + - ]: 1 : INFO("NID Mapping svc(%s) how=%d...", STRNULLCHK(at_eid), how);
385 : 1 : env = zx_NEW_e_Envelope(cf->ctx,0);
386 : 1 : env->Body = zx_NEW_e_Body(cf->ctx, &env->gg);
387 : 1 : env->Header = zx_NEW_e_Header(cf->ctx, &env->gg);
388 : 1 : env->Body->NameIDMappingRequest = req = zx_NEW_sp_NameIDMappingRequest(cf->ctx, &env->Body->gg);
389 : :
390 : 1 : req->NameIDPolicy = zx_NEW_sp_NameIDPolicy(cf->ctx, &req->gg);
391 : 1 : req->NameIDPolicy->Format = zx_ref_attr(cf->ctx, &req->NameIDPolicy->gg, zx_Format_ATTR, zxid_saml2_map_nid_fmt("prstnt"));
392 : 1 : req->NameIDPolicy->SPNameQualifier = zx_dup_attr(cf->ctx, &req->NameIDPolicy->gg, zx_SPNameQualifier_ATTR, at_eid);
393 : 1 : req->NameIDPolicy->AllowCreate = zx_ref_attr(cf->ctx, &req->NameIDPolicy->gg, zx_AllowCreate_ATTR, XML_TRUE); /* default false */
394 : :
395 : 1 : req->NameID = ses->nameid; /* or tgtnameid? */
396 : :
397 : 1 : env = zxid_wsc_call(cf, ses, epr, env, 0);
398 [ - + # # ]: 1 : if (!env || !env->Body) {
399 : 1 : ERR("Identity Mapping call failed envelope=%p", env);
400 : 1 : return 0;
401 : : }
402 [ # # ]: 0 : if (!env->Body->NameIDMappingResponse) {
403 [ # # ]: 0 : ERR("No Identity Mapping Response at_eid(%s)", STRNULLCHK(at_eid));
404 : 0 : return 0;
405 : : }
406 : :
407 : 0 : tok = zx_NEW_sec_Token(cf->ctx, 0);
408 [ # # ]: 0 : if (env->Body->NameIDMappingResponse->NameID) {
409 : 0 : ERR("*** NOT IMPLEMENTED NameIDMappingResponse has NameID %p", tok);
410 : :
411 [ # # ]: 0 : } else if (env->Body->NameIDMappingResponse->EncryptedID) {
412 : 0 : ERR("*** NOT IMPLEMENTED NameIDMappingResponse has EncryptedID %p", tok);
413 : :
414 : : } else {
415 : 0 : ERR("NameIDMappingResponse did not contain any ID %p", tok);
416 : 0 : return 0;
417 : : }
418 : :
419 [ # # # ]: 0 : switch (how) {
420 : : case 0:
421 [ # # # # ]: 0 : D("Invocation token set %p", tok);
422 : 0 : ses->call_invoktok = tok;
423 : 0 : break;
424 : : case 1:
425 [ # # # # ]: 0 : D("Target Identity token set %p", tok);
426 : 0 : ses->call_tgttok = tok;
427 : : break;
428 : : }
429 : 0 : return tok;
430 : : }
431 : :
432 : : /*() SAML NameID Mapping Service: Issue token in response to receiving a token */
433 : :
434 : : /* Called by: zxid_sp_soap_dispatch */
435 : : struct zx_sp_NameIDMappingResponse_s* zxid_nidmap_do(zxid_conf* cf, struct zx_sp_NameIDMappingRequest_s* req)
436 : 0 : {
437 : 0 : struct zx_sp_NameIDMappingResponse_s* resp = zx_NEW_sp_NameIDMappingResponse(cf->ctx,0);
438 : : struct zx_str* issue_to;
439 : : struct zx_str* affil;
440 : : char allow_create;
441 : : char* nid_fmt;
442 : : zxid_nid* nameid;
443 : : char* logop;
444 : 0 : int len, n_mapped = 0;
445 : : char uid[ZXID_MAX_BUF];
446 : : char sp_name_buf[1024];
447 : 0 : D_INDENT("nidmap: ");
448 : :
449 : : /* *** there should be some strict access control policies here, otherwise
450 : : * privacy can be lost by consulting nameids directly via this service. */
451 : :
452 : 0 : nameid = zxid_decrypt_nameid(cf, req->NameID, req->EncryptedID);
453 [ # # ]: 0 : affil = nameid->SPNameQualifier ? &nameid->SPNameQualifier->g : zxid_my_ent_id(cf);
454 : :
455 : 0 : zxid_nice_sha1(cf, sp_name_buf, sizeof(sp_name_buf), affil, affil, 7);
456 [ # # # # : 0 : len = read_all(sizeof(uid)-1, uid, "idp_map_nid2uid", 1, "%s" ZXID_NID_DIR "%s/%.*s", cf->path, sp_name_buf, ZX_GET_CONTENT_LEN(nameid), ZX_GET_CONTENT_S(nameid));
# # # # #
# # # ]
457 [ # # ]: 0 : if (!len) {
458 [ # # # # : 0 : ERR("Can not find reverse mapping for SP,SHA1(%s) nid(%.*s)", sp_name_buf, ZX_GET_CONTENT_LEN(nameid), ZX_GET_CONTENT_S(nameid));
# # # # #
# # # ]
459 : 0 : resp->Status = zxid_mk_Status(cf, &resp->gg, "Fail", 0, 0);
460 : 0 : D_DEDENT("nidmap: ");
461 : 0 : return resp;
462 : : }
463 : :
464 : : /* Figure out destination */
465 : :
466 [ # # ]: 0 : if (req->NameIDPolicy) {
467 : 0 : issue_to = &req->NameIDPolicy->SPNameQualifier->g;
468 [ # # # # : 0 : nid_fmt = ZX_STR_EQ(&req->NameIDPolicy->Format->g, SAML2_TRANSIENT_NID_FMT) ? "trnsnt" : "prstnt";
# # ]
469 [ # # # # : 0 : allow_create = XML_TRUE_TEST(&req->NameIDPolicy->AllowCreate->g) ? '1':'0';
# # # # #
# ]
470 : : } else {
471 : 0 : issue_to = 0;
472 : : }
473 : :
474 [ # # ]: 0 : if (!issue_to) {
475 : 0 : ERR("No NameIDPolicy->SPNameQualifier %p", req->NameIDPolicy);
476 : 0 : resp->Status = zxid_mk_Status(cf, &resp->gg, "Fail", 0, 0);
477 : 0 : D_DEDENT("nidmap: ");
478 : 0 : return resp;
479 : : }
480 : 0 : zxid_nice_sha1(cf, sp_name_buf, sizeof(sp_name_buf), issue_to, issue_to, 7);
481 : :
482 : : /* Check for federation */
483 : :
484 : 0 : nameid = zxid_check_fed(cf, issue_to, uid, allow_create, 0, 0, 0, sp_name_buf);
485 [ # # ]: 0 : if (nameid) {
486 [ # # # # ]: 0 : if (nid_fmt && !strcmp(nid_fmt, "trnsnt")) {
487 [ # # # # : 0 : D("Despite old fed, using transient due to nid_fmt(%s)", STRNULLCHKD(nid_fmt));
# # ]
488 : 0 : zxid_mk_transient_nid(cf, nameid, sp_name_buf, uid);
489 : 0 : logop = "ITNIDMAP";
490 : : } else
491 : 0 : logop = "IFNIDMAP";
492 : : } else {
493 [ # # # # ]: 0 : D("No nameid (because of no federation), using transient %d", 0);
494 : 0 : nameid = zx_NEW_sa_NameID(cf->ctx,0);
495 : 0 : zxid_mk_transient_nid(cf, nameid, sp_name_buf, uid);
496 : 0 : logop = "ITNIDMAP";
497 : : }
498 : :
499 [ # # # # : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, ZX_GET_CONTENT(nameid), "N", "K", logop, 0, "n=%d", n_mapped);
# # ]
500 : 0 : resp->Status = zxid_OK(cf, &resp->gg);
501 : 0 : D_DEDENT("nidmap: ");
502 : 0 : return resp;
503 : : }
504 : :
505 : : /* EOF -- zxidim.c */
|