Branch data Line data Source code
1 : : /* zxidepr.c - Handwritten functions for client side EPR and bootstrap handling
2 : : * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 : : * Copyright (c) 2007-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: zxidepr.c,v 1.19 2009-11-29 12:23:06 sampo Exp $
10 : : *
11 : : * 5.2.2007, created --Sampo
12 : : * 7.10.2008, added documentation --Sampo
13 : : *
14 : : * See also: zxidsimp.c (attributes to LDIF), and zxida7n.c (general attribute querying)
15 : : *
16 : : * N.B. Like session storage, the epr cache makes case preserving assumption about
17 : : * underlying filesystem. Case insensitive filesystem will insignificantly increase
18 : : * chances of naming collitions.
19 : : *
20 : : * See also zxiddi.c for discovery server code.
21 : : */
22 : :
23 : : #include "platform.h" /* for dirent.h */
24 : :
25 : : #include <sys/types.h>
26 : : #include <sys/stat.h>
27 : : #include <fcntl.h>
28 : : #include <string.h>
29 : : #include <stdio.h>
30 : :
31 : : #include "errmac.h"
32 : : #include "zxid.h"
33 : : #include "zxidpriv.h"
34 : : #include "zxidutil.h"
35 : : #include "zxidconf.h"
36 : : #include "saml2.h"
37 : : #include "c/zx-ns.h"
38 : : #include "c/zx-a-data.h"
39 : :
40 : : /*() Fold service type (or any URN or URL) to file name. */
41 : :
42 : : /* Called by: zxid_di_query, zxid_find_epr, zxid_nice_sha1, zxid_reg_svc */
43 : : void zxid_fold_svc(char* p, int len)
44 : 2223 : {
45 [ + + + + ]: 67696 : for (; *p && len; ++p, --len)
46 [ + + + + : 65473 : if (ONE_OF_6(*p, ':','/',',','?','&','='))
+ - + + +
- + + ]
47 : 8580 : *p = '_';
48 : 2223 : }
49 : :
50 : : /*() Compute (and fold) unique nice sha1 name according to NAME,SHA1
51 : : *
52 : : * This name format is designed to ensure unique name, while
53 : : * maintainting human readability. This is
54 : : * useful in the common case where WSC wants to call a specific type of web service.
55 : : *
56 : : * cf:: ZXID configuration object, also used for memory allocation
57 : : * buf:: result parameter. The buffer, which must have been allocated, will be
58 : : * modified to have the path. The path will be nul terminated.
59 : : * buf_len:: The length of the buf (including nul termination), usually sizeof(buf)
60 : : * name:: Often Service name or SP Entity ID
61 : : * cont:: content of EPR or the SP EntityID, used to compute sha1 hash that becomes part
62 : : * of the file name
63 : : * ign_prefix:: How many characters to ignore from beginning of name: 0 or 7 (http://)
64 : : * return:: 0 on success (the real return value is returned via ~buf~ result parameter) */
65 : :
66 : : /* Called by: zxid_epr_path, zxid_get_affil_and_sp_name_buf, zxid_idp_map_nid2uid, zxid_imreq, zxid_nidmap_do x2, zxid_sso_issue_a7n */
67 : : int zxid_nice_sha1(zxid_conf* cf, char* buf, int buf_len,
68 : : struct zx_str* name, struct zx_str* cont, int ign_prefix)
69 : 1888 : {
70 : : char* p;
71 : : char* q;
72 : : int len;
73 : : char sha1_cont[28];
74 : 1888 : sha1_safe_base64(sha1_cont, cont->len, cont->s);
75 : 1888 : sha1_cont[27] = 0;
76 : 1888 : len = snprintf(buf, buf_len, "%.*s,%s",
77 : : MAX(name->len-ign_prefix,0), name->s+ign_prefix, sha1_cont);
78 : 1888 : buf[buf_len-1] = 0; /* must terminate manually as on win32 termination is not guaranteed */
79 : :
80 : : /* 012345678
81 : : * http://
82 : : * https:// */
83 : :
84 : : /* Sanity scan the name part (svc or eid), folding dangerous chars to _. */
85 : :
86 : 1888 : p = buf;
87 : 1888 : q = MIN(p + MAX(name->len-7,0), buf + buf_len);
88 : 1888 : zxid_fold_svc(p, q-p);
89 : 1888 : return 0;
90 : : }
91 : :
92 : : /*() Compute (and fold) unique EPR name according to /var/zxid/ses/SESID/SVC,SHA1
93 : : *
94 : : * This name format is designed to ensure unique name for each EPR, while
95 : : * also making it easy to determine the service type from the name. This is
96 : : * useful in the common case where WSC wants to call a specific type of web service.
97 : : *
98 : : * cf:: ZXID configuration object, also used for memory allocation
99 : : * dir:: Directory, such as "ses/"
100 : : * sid:: Session ID whose EPR cache the file is/will be located
101 : : * buf:: result parameter. The buffer, which must have been allocated, will be
102 : : * modified to have the path. The path will be nul terminated.
103 : : * buf_len:: The length of the buf (including nul termination), usually sizeof(buf)
104 : : * svc:: Service name
105 : : * cont:: content of EPR, used to compute sha1 hash that becomes part of the file name
106 : : * return:: 0 on success (the real return value is returned via ~buf~ result parameter)
107 : : *
108 : : * N.B. This function relies on specific, ANSI documented, functioning
109 : : * of snprintf(3) library function. Unfortunately, it has been found that
110 : : * on some platforms this function only works correctly in the 'C' locale. If
111 : : * you suspect this to be the case, you may want to try
112 : : *
113 : : * export LANG=C
114 : : *
115 : : * especially if you get errors about multibyte characters. */
116 : :
117 : : /* Called by: zxid_cache_epr, zxid_snarf_eprs_from_ses */
118 : : int zxid_epr_path(zxid_conf* cf, char* dir, char* sid,
119 : : char* buf, int buf_len, struct zx_str* svc, struct zx_str* cont)
120 : 101 : {
121 : 101 : int len = snprintf(buf, buf_len, "%s%s%s/", cf->path, dir, sid);
122 : 101 : buf[buf_len-1] = 0; /* must terminate manually as on win32 termination is not guaranteed */
123 [ - + ]: 101 : if (len <= 0) {
124 : 0 : perror("snprintf");
125 : 0 : ERR("Broken snprintf? Impossible to compute length of string. Be sure to `export LANG=C' if you get errors about multibyte characters. Length returned: %d", len);
126 [ # # # # ]: 0 : if (buf && buf_len > 0)
127 : 0 : buf[0] = 0;
128 : 0 : return 1;
129 : : }
130 : 101 : return zxid_nice_sha1(cf, buf+len, buf_len - len, svc, cont, 0);
131 : : }
132 : :
133 : : /*() Serialize EPR data structure to XML and write it to session's EPR cache under
134 : : * file name that is both unique and indicates the service type.
135 : : *
136 : : * cf:: ZXID configuration object, also used for memory allocation
137 : : * ses:: Session object in whose EPR cache the file will be located
138 : : * epr:: XML data structure representing the EPR
139 : : * return:: 1 on success, 0 on failure */
140 : :
141 : : /* Called by: main, zxid_get_epr, zxid_snarf_eprs */
142 : : int zxid_cache_epr(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr)
143 : 101 : {
144 : : fdtype fd;
145 : : struct zx_str* ss;
146 : : char path[ZXID_MAX_BUF];
147 : :
148 [ + - + - : 101 : if (!ses || !ses->sid || !ses->sid[0]) {
- + ]
149 : 0 : ERR("Valid session required %p", ses);
150 : 0 : return 0;
151 : : }
152 [ + - + - : 101 : if (!epr || !epr->Metadata || !epr->Metadata->ServiceType) {
- + ]
153 : 0 : ERR("EPR is not a ID-WSF 2.0 Bootstrap: no Metadata %p", epr);
154 : 0 : return 0;
155 : : }
156 : 101 : ss = zx_easy_enc_elem_opt(cf, &epr->gg);
157 [ - + ]: 101 : if (!ss) {
158 : 0 : ERR("Encoding EndpointReference failed %p", epr);
159 : 0 : return 0;
160 : : }
161 [ + - + - : 101 : zxid_epr_path(cf, ZXID_SES_DIR, ses->sid, path, sizeof(path),
+ - ]
162 : : ZX_GET_CONTENT(epr->Metadata->ServiceType), ss);
163 : : //fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
164 : 101 : fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxid_cache_epr", 1, "%s", path);
165 [ - + ]: 101 : if (fd == BADFD) {
166 : 0 : perror("open for write cache_epr");
167 : 0 : ERR("EPR path(%s) creation failed", path);
168 [ - + ]: 101 : } else if (write_all_fd(fd, ss->s, ss->len) == -1) {
169 : 0 : perror("Trouble writing EPR");
170 : : }
171 : 101 : close_file(fd, (const char*)__FUNCTION__);
172 : 101 : zx_str_free(cf->ctx, ss);
173 : 101 : return 1;
174 : : }
175 : :
176 : : /*() Look into attribute statements of a SSO assertion and extract anything
177 : : * that looks like EPR, storing results in the session for later reference.
178 : : *
179 : : * cf:: ZXID configuration object, also used for memory allocation
180 : : * ses:: Session object in whose EPR cache will be populated
181 : : *
182 : : * N.B. This approach ignores the official attribute names totally. Anything
183 : : * that looks like an EPR and that is strcturally in right place will work.
184 : : * Typical name /var/zxid/ses/SESID/SVCTYPE,SHA1 */
185 : :
186 : : /* Called by: zxid_as_call_ses, zxid_snarf_eprs_from_ses */
187 : : void zxid_snarf_eprs(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr)
188 : 1072 : {
189 : : struct zx_str* ss;
190 : : struct zx_str* urlss;
191 : 1072 : int wsf20 = 0;
192 [ + + + - ]: 1158 : for (; epr && epr->gg.g.tok == zx_a_EndpointReference_ELEM; epr = (zxid_epr*)epr->gg.g.n) {
193 [ + - + - : 86 : ss = ZX_GET_CONTENT(epr->Metadata->ServiceType);
+ - ]
194 [ + - + - : 86 : urlss = ZX_GET_CONTENT(epr->Address);
+ - ]
195 [ + + + - : 86 : D("%d: EPR svc(%.*s) url(%.*s)", wsf20, ss?ss->len:0, ss?ss->s:"", urlss?urlss->len:0, urlss?urlss->s:"");
+ - + - +
- - + ]
196 [ + - ]: 86 : if (zxid_cache_epr(cf, ses, epr)) {
197 : 86 : ++wsf20;
198 [ + + + - : 86 : D("%d: EPR cached svc(%.*s) url(%.*s)", wsf20, ss?ss->len:0, ss?ss->s:"", urlss?urlss->len:0, urlss?urlss->s:"");
+ - + - +
- - + ]
199 : : }
200 : : }
201 [ + + - + ]: 1072 : D("TOTAL wsf20 EPRs snarfed: %d", wsf20);
202 : 1072 : }
203 : :
204 : : /*() Look into attribute statements of a SSO assertion and extract anything
205 : : * that looks like EPR, storing results in the session for later reference.
206 : : *
207 : : * cf:: ZXID configuration object, also used for memory allocation
208 : : * ses:: Session object in whose EPR cache will be populated
209 : : *
210 : : * N.B. This approach ignores the official attribute names totally. Anything
211 : : * that looks like an EPR and that is strcturally in right place will work.
212 : : * Typical name /var/zxid/ses/SESID/SVCTYPE,SHA1 */
213 : :
214 : : /* Called by: zxid_sp_anon_finalize, zxid_sp_sso_finalize, zxid_wsc_valid_re_env, zxid_wsp_validate_env */
215 : : void zxid_snarf_eprs_from_ses(zxid_conf* cf, zxid_ses* ses)
216 : 62 : {
217 : : struct zx_sa_AttributeStatement_s* as;
218 : : struct zx_sa_Attribute_s* at;
219 : : struct zx_sa_AttributeValue_s* av;
220 : 62 : int wsf11 = 0;
221 : :
222 : 62 : D_INDENT("snarf_eprs: ");
223 : 62 : zxid_get_ses_sso_a7n(cf, ses);
224 [ + + ]: 62 : if (ses->a7n)
225 : 52 : for (as = ses->a7n->AttributeStatement;
226 [ + + + + ]: 154 : as && as->gg.g.tok == zx_sa_AttributeStatement_ELEM;
227 : 50 : as = (struct zx_sa_AttributeStatement_s*)as->gg.g.n)
228 : 50 : for (at = as->Attribute;
229 [ + + + + ]: 1157 : at && at->gg.g.tok == zx_sa_Attribute_ELEM;
230 : 1057 : at = (struct zx_sa_Attribute_s*)at->gg.g.n)
231 : 1057 : for (av = at->AttributeValue;
232 [ + + + + ]: 3171 : av && av->gg.g.tok == zx_sa_AttributeValue_ELEM;
233 : 1057 : av = (struct zx_sa_AttributeValue_s*)av->gg.g.n) {
234 : 1057 : zxid_snarf_eprs(cf, ses, av->EndpointReference);
235 [ - + ]: 1057 : if (av->ResourceOffering) {
236 : 0 : ++wsf11;
237 [ # # # # ]: 0 : D("Detected wsf11 resource offering. %d", wsf11);
238 : : #if 0
239 : : ss = zx_easy_enc_elem_opt(cf, &av->ResourceOffering->gg);
240 : : zxid_epr_path(cf, ZXID_SES_DIR, ses->sid, path, sizeof(path),
241 : : ZX_GET_CONTENT(av->EndpointReference->Metadata->ServiceType), ss);
242 : : fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
243 : : if (fd == -1) {
244 : : perror("open for write epr");
245 : : ERR("EPR path(%s) creation failed", path);
246 : : } else if (write_all_fd(fd, ss->s, ss->len) == -1) {
247 : : perror("Trouble writing EPR");
248 : : close__file(fd, __FUNCTION__);
249 : : }
250 : : zx_str_free(cf->ctx, ss);
251 : : #endif
252 : : }
253 : : }
254 : : #if 0
255 : : if (ses->a7n12)
256 : : for (as = ses->a7n->AttributeStatement;
257 : : as && as->gg.g.tok == zx_sa11_AttributeStatement_ELEM;
258 : : as = (struct zx_sa11_AttributeStatement_s*)as->gg.g.n)
259 : : for (at = as->Attribute;
260 : : at && at->gg.g.tok == zx_sa11_Attribute_ELEM;
261 : : at = (struct zx_sa11_Attribute_s*)at->gg.g.n)
262 : : for (av = at->AttributeValue;
263 : : av && av->gg.g.tok == zx_sa11_AttributeValue_ELEM;
264 : : av = (struct zx_sa11_AttributeValue_s*)av->gg.g.n) {
265 : : }
266 : : #endif
267 : 62 : D_DEDENT("snarf_eprs: ");
268 : 62 : }
269 : :
270 : : /*() Search the EPRs cached under the session for a match. First directory is searched
271 : : * for files whose name starts by service type. These files are opened and parsed
272 : : * as EPR and further checks are made. The nth match is returned. 1 means first.
273 : : * Typical name: /var/zxid/ses/SESID/SVCTYPE,SHA1
274 : : *
275 : : * cf:: ZXID configuration object, also used for memory allocation
276 : : * ses:: Session object in whose EPR cache the file is searched
277 : : * svc:: Service type (usually a URN)
278 : : * url:: (Optional) If provided, this argument has to match either
279 : : * the ProviderID, EntityID, or actual service endpoint URL.
280 : : * di_opt:: (Optional) Additional discovery options for selecting the service, query string format
281 : : * action:: (Optional) The action, or method, that must be invocable on the service
282 : : * n:: How manieth matching instance is returned. 1 means first
283 : : * return:: EPR data structure (or linked list of EPRs) on success, 0 on failure
284 : : *
285 : : * See also: zxid_print_session() in zxcall.c */
286 : :
287 : : /* Called by: main x2, zxid_get_epr x2 */
288 : : zxid_epr* zxid_find_epr(zxid_conf* cf, zxid_ses* ses, const char* svc, const char* url, const char* di_opt, const char* action, int n)
289 : 44 : {
290 : : struct zx_root_s* r;
291 : : struct zx_str* ss;
292 : : struct zx_str* pi;
293 : : int len, epr_len;
294 : : char path[ZXID_MAX_BUF];
295 : : char* epr_buf; /* MUST NOT come from stack. */
296 : : DIR* dir;
297 : : struct dirent * de;
298 : 44 : zxid_epr* epr = 0;
299 : 44 : struct zx_a_Metadata_s* md = 0;
300 : 44 : D_INDENT("find_epr: ");
301 : :
302 : : #if 1
303 [ + - - + ]: 44 : if (!svc || !*svc) {
304 : : /* *** Relax this to allow discovery of multiple or all service types */
305 : 0 : ERR("Must supply service type %p", svc);
306 : 0 : D_DEDENT("find_epr: ");
307 : 0 : return 0;
308 : : }
309 : : #endif
310 : :
311 [ - + ]: 44 : if (!name_from_path(path, sizeof(path), "%s" ZXID_SES_DIR "%s", cf->path, ses->sid)) {
312 : 0 : D_DEDENT("find_epr: ");
313 : 0 : return 0;
314 : : }
315 : :
316 [ + + - + ]: 44 : D("Looking in session dir(%s) svc(%s) pses=%p", path, svc, ses);
317 : 44 : dir = opendir(path);
318 [ - + ]: 44 : if (!dir) {
319 : 0 : perror("opendir to find epr in session");
320 : 0 : ERR("Opening session for find epr by opendir failed path(%s) sesptr=%p", path, ses);
321 : 0 : D_DEDENT("find_epr: ");
322 : 0 : return 0;
323 : : }
324 : :
325 : 44 : len = strlen(svc);
326 : 44 : len = MIN(len, sizeof(path)-1);
327 : 44 : memcpy(path, svc, len);
328 : 44 : path[len] = 0;
329 : 44 : zxid_fold_svc(path, len);
330 [ + + - + ]: 44 : D("Folded path prefix(%.*s) len=%d n=%d", len, path, len, n);
331 : :
332 [ + + ]: 267 : while (de = readdir(dir)) {
333 [ + + - + ]: 205 : D("%d Considering file(%s)", n, de->d_name);
334 [ + + ]: 205 : if (de->d_name[0] == '.') /* . .. and "hidden" files */
335 : 132 : continue;
336 [ - + ]: 73 : if (de->d_name[strlen(de->d_name)-1] == '~') /* Ignore backups from hand edited EPRs. */
337 : 0 : continue;
338 [ + + + - ]: 73 : if (memcmp(de->d_name, path, len) || de->d_name[len] != ',')
339 : : continue;
340 [ + + - + ]: 28 : D("%d Checking EPR content file(%s)", n, de->d_name);
341 : 28 : epr_buf = read_all_alloc(cf->ctx, "find_epr", 1, &epr_len,
342 : : "%s" ZXID_SES_DIR "%s/%s", cf->path, ses->sid, de->d_name);
343 [ - + ]: 28 : if (!epr_buf)
344 : 0 : continue;
345 : :
346 : 28 : r = zx_dec_zx_root(cf->ctx, epr_len, epr_buf, "find epr");
347 [ + - - + ]: 28 : if (!r || !r->EndpointReference) {
348 : 0 : ERR("No EPR found. Failed to parse epr_buf(%.*s)", epr_len, epr_buf);
349 : 0 : continue;
350 : : }
351 : 28 : epr = r->EndpointReference;
352 : 28 : ZX_FREE(cf->ctx, r);
353 [ + - + - : 28 : if (!ZX_SIMPLE_ELEM_CHK(epr->Address)) {
+ - + - +
- - + ]
354 : 0 : ERR("The EPR does not have <Address> element. Rejected. %p", epr->Address);
355 : 0 : continue;
356 : : }
357 : : /* *** add ID-WSF 1.1 handling */
358 : 28 : md = epr->Metadata;
359 [ + - + - : 28 : if (svc &&
+ - + - +
- + - + -
- + ]
360 : : (!md || !ZX_SIMPLE_ELEM_CHK(md->ServiceType))) {
361 : 0 : ERR("No Metadata %p or ServiceType. Failed to parse epr_buf(%.*s)", md, epr_len, epr_buf);
362 : 0 : continue;
363 : : }
364 [ + - + - : 28 : ss = ZX_GET_CONTENT(md->ServiceType);
+ - ]
365 [ + - + - : 28 : if (svc && (!ss || len != ss->len || memcmp(svc, ss->s, len))) {
+ - - + ]
366 [ # # # # : 0 : D("%d Internal svctype(%.*s) does not match desired(%s). Reject.", n, ss?ss->len:0, ss?ss->s:"", svc);
# # # # ]
367 : 0 : continue;
368 : : }
369 : :
370 [ + - + - : 28 : ss = ZX_GET_CONTENT(epr->Address);
+ - ]
371 [ + + + - : 28 : if (url && (!ss || strlen(url) != ss->len || memcmp(url, ss->s, ss->len))) {
+ + - + ]
372 [ + - + - : 3 : pi = md?ZX_GET_CONTENT(md->ProviderID):0;
+ - + - ]
373 [ + - + - : 3 : if (pi && (strlen(url) != pi->len || memcmp(url, pi->s, pi->len))) {
- + ]
374 [ # # # # : 0 : D("%d ProviderID(%.*s) or endpoint URL(%.*s) does not match desired url(%s). Reject.", n, pi->len, pi->s, ss?ss->len:0, ss?ss->s:"", url);
# # # # ]
375 : 0 : continue;
376 : : }
377 : : }
378 : :
379 : : /* *** Evaluate di_opt */
380 : :
381 : : /* *** Evaluate action */
382 : :
383 [ + + ]: 28 : if (--n)
384 : 2 : continue;
385 : :
386 [ + + + - : 26 : D("%d Found svc(%s) url(%.*s)", n, STRNULLCHK(svc), ZX_GET_CONTENT_LEN(epr->Address), ZX_GET_CONTENT_S(epr->Address));
+ - + - +
- + - + -
+ - - + ]
387 : 26 : closedir(dir);
388 : 26 : D_DEDENT("find_epr: ");
389 : 26 : return epr;
390 : : }
391 : 18 : closedir(dir);
392 : 18 : D_DEDENT("find_epr: ");
393 : 18 : return 0;
394 : : }
395 : :
396 : : /*(i) First search epr cache, and if miss, go discover an EPR over the net.
397 : : * This is the main work horse for WSCs wishing to call WSPs via EPR.
398 : : *
399 : : * cf:: ZXID configuration object, also used for memory allocation
400 : : * ses:: Session object in whose EPR cache the file will be searched
401 : : * svc:: Service type (usually the namespace URN)
402 : : * url:: (Optional) If provided, this argument has to match either
403 : : * the ProviderID, EntityID, or actual service endpoint URL.
404 : : * di_opt:: (Optional) Additional discovery options for selecting the service, query string format
405 : : * action:: (Optional) The action, or method, that must be invocable on the service
406 : : * n:: How manieth matching instance is returned. 1 means first
407 : : * return:: EPR data structure on success, 0 on failure (no discovery EPR in cache, or
408 : : * not found by the discovery service). If more than one were found, a linked list
409 : : * of EPRs is returned.
410 : : */
411 : :
412 : : /* Called by: main x5, zxcall_main, zxid_call, zxid_map_identity_token, zxid_nidmap_identity_token */
413 : : zxid_epr* zxid_get_epr(zxid_conf* cf, zxid_ses* ses, const char* svc, const char* url, const char* di_opt, const char* action, int n)
414 : 28 : {
415 : 28 : int wsf20 = 0;
416 : : struct zx_str* ss;
417 : : struct zx_str* urlss;
418 : : struct zx_e_Envelope_s* env;
419 : : zxid_epr* epr;
420 : 28 : epr = zxid_find_epr(cf, ses, svc, url, di_opt, action, n);
421 [ + + ]: 28 : if (epr)
422 : 10 : return epr;
423 [ + + ]: 18 : if (n > 1)
424 : 2 : return 0; /* Do not discover any more */
425 : :
426 [ + - ]: 16 : INFO("%d Discovering svc(%s)...", n, STRNULLCHK(svc));
427 : 16 : env = zx_NEW_e_Envelope(cf->ctx,0);
428 : 16 : env->Body = zx_NEW_e_Body(cf->ctx, &env->gg);
429 : 16 : env->Body->Query = zxid_mk_di_query(cf, &env->Body->gg, svc, url, di_opt, 0);
430 [ - + ]: 16 : if (ses->deleg_di_epr) {
431 : 0 : epr = ses->deleg_di_epr;
432 [ # # # # ]: 0 : D("%d: Using delegated discovery EPR", n);
433 : : } else {
434 : 16 : epr = zxid_find_epr(cf, ses, zx_xmlns_di, 0, 0, 0, n);
435 [ - + ]: 16 : if (!epr) {
436 [ # # ]: 0 : ERR("EPR for svc(%s) not found in cache and no discovery EPR in cache, thus no way to discover the svc.", STRNULLCHK(svc));
437 : 0 : return 0;
438 : : }
439 : : }
440 : 16 : env->Header = zx_NEW_e_Header(cf->ctx, &env->gg);
441 : 16 : env = zxid_wsc_call(cf, ses, epr, env, 0);
442 [ + - + - ]: 16 : if (env && env->Body) {
443 [ + - ]: 16 : if (env->Body->QueryResponse) {
444 : 16 : for (epr = env->Body->QueryResponse->EndpointReference;
445 [ + + + - ]: 47 : epr && epr->gg.g.tok == zx_a_EndpointReference_ELEM;
446 : 15 : epr = (zxid_epr*)ZX_NEXT(epr)) {
447 [ + - + - : 15 : ss = ZX_GET_CONTENT(epr->Metadata->ServiceType);
+ - ]
448 [ + - + - : 15 : urlss = ZX_GET_CONTENT(epr->Address);
+ - ]
449 [ + + + - : 15 : D("%d: EPR svc(%.*s) url(%.*s)", wsf20, ss?ss->len:0, ss?ss->s:"", urlss?urlss->len:0, urlss?urlss->s:"");
+ - + - +
- - + ]
450 [ + - ]: 15 : if (zxid_cache_epr(cf, ses, epr)) {
451 : 15 : ++wsf20;
452 [ + + + - : 15 : D("%d: EPR cached svc(%.*s) url(%.*s)", wsf20, ss?ss->len:0, ss?ss->s:"", urlss?urlss->len:0, urlss?urlss->s:"");
+ - + - +
- - + ]
453 : : }
454 : : }
455 : 16 : epr = env->Body->QueryResponse->EndpointReference;
456 : : } else {
457 : 0 : epr = 0;
458 : : }
459 [ + + ]: 16 : if (!epr)
460 [ + - ]: 1 : ERR("No end point discovered for svc(%s)", STRNULLCHK(svc));
461 [ + + - + ]: 16 : D("TOTAL wsf20 EPRs discovered: %d", wsf20);
462 : 16 : return epr;
463 : : }
464 : 0 : ERR("discovery call failed envelope=%p", env);
465 : 0 : return 0;
466 : : }
467 : :
468 : : /*() Accessor function for extracting endpoint address URL. */
469 : :
470 : : /* Called by: zxcall_main, zxid_print_session */
471 : 8 : struct zx_str* zxid_get_epr_address(zxid_conf* cf, zxid_epr* epr) {
472 [ - + ]: 8 : if (!epr)
473 : 0 : return 0;
474 [ + - + - : 8 : return ZX_GET_CONTENT(epr->Address);
+ - ]
475 : : }
476 : :
477 : : /*() Accessor function for extracting endpoint ProviderID. */
478 : :
479 : : /* Called by: zxcall_main, zxid_print_session */
480 : 6 : struct zx_str* zxid_get_epr_entid(zxid_conf* cf, zxid_epr* epr) {
481 [ + - - + ]: 6 : if (!epr || !epr->Metadata)
482 : 0 : return 0;
483 [ + - + - : 6 : return ZX_GET_CONTENT(epr->Metadata->ProviderID);
+ - ]
484 : : }
485 : :
486 : : /*() Accessor function for extracting endpoint Description (Abstract). */
487 : :
488 : : /* Called by: zxcall_main, zxid_print_session */
489 : 5 : struct zx_str* zxid_get_epr_desc(zxid_conf* cf, zxid_epr* epr) {
490 [ + - - + ]: 5 : if (!epr || !epr->Metadata)
491 : 0 : return 0;
492 [ + - + - : 5 : return ZX_GET_CONTENT(epr->Metadata->Abstract);
+ - ]
493 : : }
494 : :
495 : : /*() Accessor function for extracting security mechanism ID. */
496 : :
497 : : /* Called by: */
498 : 0 : struct zx_str* zxid_get_epr_secmech(zxid_conf* cf, zxid_epr* epr) {
499 : : struct zx_elem_s* secmech;
500 [ # # # # ]: 0 : if (!epr || !epr->Metadata)
501 : 0 : return 0;
502 [ # # # # ]: 0 : if (!epr->Metadata->SecurityContext
503 : : || (secmech = epr->Metadata->SecurityContext->SecurityMechID)) {
504 : 0 : ERR("Null EPR or EPR is missing Metadata, SecurityContext or SecurityMechID. %p", epr);
505 : 0 : return 0;
506 : : }
507 [ # # # # : 0 : return ZX_GET_CONTENT(secmech);
# # ]
508 : : }
509 : :
510 : : /*() Set security mechanism ID.
511 : : *
512 : : * WARNING! Usually security mechanism ID is set by the
513 : : * discovery process. Do not manipulate it unless you
514 : : * know what you are doing. If security mechanism requires
515 : : * a token, you need to arrange it separately, either via
516 : : * discovery (recommended) or using zxid_set_epr_token() (if
517 : : * you know what you are doing). */
518 : :
519 : : /* Called by: */
520 : 0 : void zxid_set_epr_secmech(zxid_conf* cf, zxid_epr* epr, const char* secmec) {
521 [ # # ]: 0 : if (!epr) {
522 : 0 : ERR("Null EPR. %p", epr);
523 : 0 : return;
524 : : }
525 [ # # ]: 0 : if (!epr->Metadata)
526 : 0 : epr->Metadata = zx_NEW_a_Metadata(cf->ctx, &epr->gg);
527 [ # # ]: 0 : if (!epr->Metadata->SecurityContext)
528 : 0 : epr->Metadata->SecurityContext = zx_NEW_di_SecurityContext(cf->ctx, &epr->Metadata->gg);
529 [ # # ]: 0 : if (secmec) {
530 : 0 : epr->Metadata->SecurityContext->SecurityMechID
531 : : = zx_dup_elem(cf->ctx, &epr->Metadata->SecurityContext->gg, zx_di_SecurityMechID_ELEM, secmec);
532 : 0 : INFO("SecurityMechID set to(%s)", secmec);
533 : : } else {
534 : 0 : epr->Metadata->SecurityContext->SecurityMechID
535 : : = zx_dup_elem(cf->ctx, &epr->Metadata->SecurityContext->gg, zx_di_SecurityMechID_ELEM, 0);
536 : 0 : INFO("SecurityMechID set null %d", 0);
537 : : }
538 : : }
539 : :
540 : : /*() Accessor function for extracting endpoint's (SAML2 assertion) token. */
541 : :
542 : : /* Called by: */
543 : 0 : zxid_tok* zxid_get_epr_token(zxid_conf* cf, zxid_epr* epr) {
544 [ # # # # : 0 : if (!epr || !epr->Metadata || !epr->Metadata->SecurityContext) {
# # ]
545 : 0 : ERR("Null EPR or EPR is missing Metadata or SecurityContext. %p", epr);
546 : 0 : return 0;
547 : : }
548 : 0 : return epr->Metadata->SecurityContext->Token;
549 : : }
550 : :
551 : : /*() Set endpoint's (SAML2 assertion) token.
552 : : *
553 : : * WARNING! Generally you should not call this function. Instead
554 : : * you should use discovery to obtain a token properly targeted
555 : : * to the destination of the EPR. This includes correct audience
556 : : * restriction, correct name id, and possible encryption of the
557 : : * token so that only destination can open it. Perticular things
558 : : * you should NOT do: just copy SSO token and pass it to web service
559 : : * call (the audience restriction will be wrong); just copy
560 : : * token that was received on WSP interface and use it on WSC interface. */
561 : :
562 : : /* Called by: */
563 : 0 : void zxid_set_epr_token(zxid_conf* cf, zxid_epr* epr, zxid_tok* tok) {
564 [ # # ]: 0 : if (!epr) {
565 : 0 : ERR("Null EPR. %p", epr);
566 : 0 : return;
567 : : }
568 [ # # ]: 0 : if (!epr->Metadata)
569 : 0 : epr->Metadata = zx_NEW_a_Metadata(cf->ctx, &epr->gg);
570 [ # # ]: 0 : if (!epr->Metadata->SecurityContext)
571 : 0 : epr->Metadata->SecurityContext = zx_NEW_di_SecurityContext(cf->ctx, &epr->Metadata->gg);
572 : 0 : epr->Metadata->SecurityContext->Token = tok;
573 : 0 : INFO("EPR token set %p", tok);
574 : : }
575 : :
576 : : /*() Constructor for "blank" EPR. Such EPR lacks security context so it is
577 : : * not directly usable for identity web service calls. However, it could
578 : : * be useful as a building block, or for non-identity web service.
579 : : * Also id, actor, and mustUnderstand fields need to be filled in by
580 : : * other means (we may eventually have defaults for some of these). */
581 : :
582 : : /* Called by: */
583 : : zxid_epr* zxid_new_epr(zxid_conf* cf, char* address, char* desc, char* entid, char* svctype)
584 : 0 : {
585 : 0 : zxid_epr* epr = zx_NEW_a_EndpointReference(cf->ctx,0);
586 [ # # ]: 0 : if (address) {
587 : 0 : epr->Address = zx_NEW_a_Address(cf->ctx, &epr->gg);
588 : 0 : zx_add_content(cf->ctx, &epr->Address->gg, zx_dup_str(cf->ctx, address));
589 : : }
590 [ # # # # : 0 : if (desc || entid || svctype) {
# # ]
591 : 0 : epr->Metadata = zx_NEW_a_Metadata(cf->ctx, &epr->gg);
592 [ # # ]: 0 : if (desc)
593 : 0 : epr->Metadata->Abstract
594 : : = zx_dup_elem(cf->ctx, &epr->Metadata->gg, zx_di_Abstract_ELEM, desc);
595 [ # # ]: 0 : if (entid)
596 : 0 : epr->Metadata->ProviderID
597 : : = zx_dup_elem(cf->ctx, &epr->Metadata->gg, zx_di_ProviderID_ELEM, entid);
598 [ # # ]: 0 : if (svctype)
599 : 0 : epr->Metadata->ServiceType
600 : : = zx_dup_elem(cf->ctx, &epr->Metadata->gg, zx_di_ServiceType_ELEM, svctype);
601 : : }
602 : 0 : return epr;
603 : : }
604 : :
605 : : /* Called by: */
606 : : zxid_epr* zxid_get_delegated_discovery_epr(zxid_conf* cf, zxid_ses* ses)
607 : 0 : {
608 : 0 : return ses->deleg_di_epr;
609 : : }
610 : :
611 : : /*(i) Allows explicit control over which Discovery Service is used, such
612 : : * as selecting somebody else's Discovery Service. This allows delegated
613 : : * access. */
614 : :
615 : : /* Called by: */
616 : : void zxid_set_delegated_discovery_epr(zxid_conf* cf, zxid_ses* ses, zxid_epr* epr)
617 : 0 : {
618 : 0 : ses->deleg_di_epr = epr;
619 : 0 : }
620 : :
621 : : /*() Get session's call invokation token. */
622 : :
623 : : /* Called by: */
624 : 0 : zxid_tok* zxid_get_call_invoktok(zxid_conf* cf, zxid_ses* ses) {
625 [ # # ]: 0 : if (!ses) {
626 : 0 : ERR("Null session. %p", ses);
627 : 0 : return 0;
628 : : }
629 : 0 : return ses->call_invoktok;
630 : : }
631 : :
632 : : /*() Set session's call invokation token. */
633 : :
634 : : /* Called by: */
635 : 0 : void zxid_set_call_invoktok(zxid_conf* cf, zxid_ses* ses, zxid_tok* tok) {
636 [ # # ]: 0 : if (!ses) {
637 : 0 : ERR("Null session. %p", ses);
638 : 0 : return;
639 : : }
640 : 0 : ses->call_invoktok = tok;
641 : : }
642 : :
643 : : /*() Get session's call target token. */
644 : :
645 : : /* Called by: */
646 : 0 : zxid_tok* zxid_get_call_tgttok(zxid_conf* cf, zxid_ses* ses) {
647 [ # # ]: 0 : if (!ses) {
648 : 0 : ERR("Null session. %p", ses);
649 : 0 : return 0;
650 : : }
651 : 0 : return ses->call_tgttok;
652 : : }
653 : :
654 : : /*() Set session's call target token. */
655 : :
656 : : /* Called by: */
657 : 0 : void zxid_set_call_tgttok(zxid_conf* cf, zxid_ses* ses, zxid_tok* tok) {
658 [ # # ]: 0 : if (!ses) {
659 : 0 : ERR("Null session. %p", ses);
660 : 0 : return;
661 : : }
662 : 0 : ses->call_tgttok = tok;
663 : : }
664 : :
665 : : /*() Serialize a token. */
666 : :
667 : : /* Called by: */
668 : 0 : struct zx_str* zxid_token2str(zxid_conf* cf, zxid_tok* tok) {
669 [ # # ]: 0 : if (!tok)
670 : 0 : return 0;
671 : 0 : return zx_easy_enc_elem_sig(cf, &tok->gg);
672 : : }
673 : :
674 : : /*() Parse string into token. */
675 : :
676 : : /* Called by: */
677 : 0 : zxid_tok* zxid_str2token(zxid_conf* cf, struct zx_str* ss) {
678 : : struct zx_root_s* r;
679 : : zxid_tok* tok;
680 : :
681 [ # # # # : 0 : if (!ss || !ss->len || !ss->s)
# # ]
682 : 0 : return 0;
683 : :
684 : 0 : r = zx_dec_zx_root(cf->ctx, ss->len, ss->s, "decode token");
685 [ # # ]: 0 : if (!r) {
686 : 0 : ERR("Failed to parse token buf(%.*s)", ss->len, ss->s);
687 : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "BADXML", 0, "bad token");
688 : 0 : return 0;
689 : : }
690 [ # # ]: 0 : if (r->Token)
691 : 0 : return r->Token;
692 : 0 : tok = zx_NEW_sec_Token(cf->ctx,0);
693 : 0 : tok->Assertion = r->Assertion;
694 : 0 : tok->EncryptedAssertion = r->EncryptedAssertion;
695 : 0 : tok->sa11_Assertion = r->sa11_Assertion;
696 : 0 : tok->ff12_Assertion = r->ff12_Assertion;
697 : 0 : return tok;
698 : : }
699 : :
700 : : /*() Serialize an assertion. */
701 : :
702 : : /* Called by: */
703 : 0 : struct zx_str* zxid_a7n2str(zxid_conf* cf, zxid_a7n* a7n) {
704 [ # # ]: 0 : if (!a7n)
705 : 0 : return 0;
706 : 0 : return zx_easy_enc_elem_sig(cf, &a7n->gg);
707 : : }
708 : :
709 : : /*() Parse string into assertion. */
710 : :
711 : : /* Called by: */
712 : 0 : zxid_a7n* zxid_str2a7n(zxid_conf* cf, struct zx_str* ss) {
713 : : struct zx_root_s* r;
714 : :
715 [ # # # # : 0 : if (!ss || !ss->len || !ss->s)
# # ]
716 : 0 : return 0;
717 : :
718 : 0 : r = zx_dec_zx_root(cf->ctx, ss->len, ss->s, "decode a7n");
719 [ # # ]: 0 : if (!r) {
720 : 0 : ERR("Failed to parse assertion buf(%.*s)", ss->len, ss->s);
721 : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "BADXML", 0, "bad a7n");
722 : 0 : return 0;
723 : : }
724 : 0 : return r->Assertion;
725 : : }
726 : :
727 : : /*() Serialize a NameID. */
728 : :
729 : : /* Called by: */
730 : 0 : struct zx_str* zxid_nid2str(zxid_conf* cf, zxid_nid* nid) {
731 [ # # ]: 0 : if (!nid)
732 : 0 : return 0;
733 : 0 : return zx_easy_enc_elem_sig(cf, &nid->gg);
734 : : }
735 : :
736 : : /*() Parse string into NameID. */
737 : :
738 : : /* Called by: */
739 : 0 : zxid_nid* zxid_str2nid(zxid_conf* cf, struct zx_str* ss) {
740 : : struct zx_root_s* r;
741 : :
742 [ # # # # : 0 : if (!ss || !ss->len || !ss->s)
# # ]
743 : 0 : return 0;
744 : :
745 : 0 : r = zx_dec_zx_root(cf->ctx, ss->len, ss->s, "decode nid");
746 [ # # ]: 0 : if (!r) {
747 : 0 : ERR("Failed to parse NameID buf(%.*s)", ss->len, ss->s);
748 : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "BADXML", 0, "bad nid");
749 : 0 : return 0;
750 : : }
751 : 0 : return r->NameID;
752 : : }
753 : :
754 : : /*() Get session's invoker nameid. */
755 : :
756 : : /* Called by: */
757 : 0 : zxid_nid* zxid_get_nameid(zxid_conf* cf, zxid_ses* ses) {
758 [ # # ]: 0 : if (!ses)
759 : 0 : return 0;
760 : 0 : return ses->nameid;
761 : : }
762 : :
763 : : /*() Set session's invoker nameid. */
764 : :
765 : : /* Called by: */
766 : 0 : void zxid_set_nameid(zxid_conf* cf, zxid_ses* ses, zxid_nid* nid) {
767 [ # # ]: 0 : if (!ses)
768 : 0 : return;
769 : 0 : ses->nameid = nid;
770 : : }
771 : :
772 : : /*() Get session's target nameid. */
773 : :
774 : : /* Called by: */
775 : 0 : zxid_nid* zxid_get_tgtnameid(zxid_conf* cf, zxid_ses* ses) {
776 [ # # ]: 0 : if (!ses)
777 : 0 : return 0;
778 : 0 : return ses->tgtnameid;
779 : : }
780 : :
781 : : /*() Set session's target nameid. */
782 : :
783 : : /* Called by: */
784 : 0 : void zxid_set_tgtnameid(zxid_conf* cf, zxid_ses* ses, zxid_nid* nid) {
785 [ # # ]: 0 : if (!ses)
786 : 0 : return;
787 : 0 : ses->tgtnameid = nid;
788 : : }
789 : :
790 : : /*() Get session's invoker assertion. */
791 : :
792 : : /* Called by: */
793 : 0 : zxid_a7n* zxid_get_a7n(zxid_conf* cf, zxid_ses* ses) {
794 [ # # ]: 0 : if (!ses)
795 : 0 : return 0;
796 : 0 : return ses->a7n;
797 : : }
798 : :
799 : : /*() Set session's invoker assertion. */
800 : :
801 : : /* Called by: */
802 : 0 : void zxid_set_a7n(zxid_conf* cf, zxid_ses* ses, zxid_a7n* a7n) {
803 [ # # ]: 0 : if (!ses)
804 : 0 : return;
805 : 0 : ses->a7n = a7n;
806 : : }
807 : :
808 : : /*() Get session's target assertion. */
809 : :
810 : : /* Called by: */
811 : 0 : zxid_a7n* zxid_get_tgta7n(zxid_conf* cf, zxid_ses* ses) {
812 [ # # ]: 0 : if (!ses)
813 : 0 : return 0;
814 : 0 : return ses->tgta7n;
815 : : }
816 : :
817 : : /*() Set session's target assertion. */
818 : :
819 : : /* Called by: */
820 : 0 : void zxid_set_tgta7n(zxid_conf* cf, zxid_ses* ses, zxid_a7n* a7n) {
821 [ # # ]: 0 : if (!ses)
822 : 0 : return;
823 : 0 : ses->tgta7n = a7n;
824 : : }
825 : :
826 : : /* EOF -- zxidepr.c */
|