1 /* zxidwsf.c - Handwritten nitty-gritty functions for Liberty ID-WSF Framework level
2 * Copyright (c) 2009-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: zxidwsc.c,v 1.19 2010-01-08 02:10:09 sampo Exp $
10 *
11 * 7.1.2007, created --Sampo
12 * 7.10.2008, added documentation --Sampo
13 * 7.1.2010, added WSC signing --Sampo
14 * 31.5.2010, added complex sig validation and hunt --Sampo
15 */
16
17 #include "platform.h" /* needed on Win32 for pthread_mutex_lock() et al. */
18 #include "errmac.h"
19 #include "zxid.h"
20 #include "zxidpriv.h"
21 #include "zxidconf.h"
22 #include "saml2.h"
23 #include "wsf.h"
24 #include "c/zx-const.h"
25 #include "c/zx-ns.h"
26 #include "c/zx-data.h"
27
28 #define XS_STRING "http://www.w3.org/2001/XMLSchema#string"
29 #define BOOL_STR_TEST(x) ((x) && (x) != '0')
30
31 /*() Try to map security mechanisms across different frame works. Low level
32 * function. This also makes some elementary checks as to whether the
33 * EPR is even capable of supporting the sec mech. */
34
35 /* Called by: covimp_test, zxid_wsc_prep_secmech */
zxid_map_sec_mech(zxid_epr * epr)36 int zxid_map_sec_mech(zxid_epr* epr)
37 {
38 int len;
39 const char* s;
40 struct zx_elem_s* secmechid;
41 if (!epr || !epr->Metadata || !epr->Metadata->SecurityContext) {
42 INFO("EPR lacks Metadata or SecurityContext. Forcing X509. %p", epr->Metadata);
43 return ZXID_SEC_MECH_X509;
44 }
45 secmechid = epr->Metadata->SecurityContext->SecurityMechID;
46 if (!ZX_SIMPLE_ELEM_CHK(secmechid)) {
47 if (epr->Metadata->SecurityContext->Token) {
48 INFO("EPR does not specify sec mech id. Forcing Bearer. %p", secmechid);
49 return ZXID_SEC_MECH_BEARER;
50 } else {
51 INFO("EPR lacks Token. Forcing X509. %p", secmechid);
52 return ZXID_SEC_MECH_X509;
53 }
54 }
55
56 len = ZX_GET_CONTENT_LEN(secmechid);
57 s = ZX_GET_CONTENT_S(secmechid);
58
59 D("mapping secmec(%.*s)", len, s);
60
61 #define SEC_MECH_TEST(ret, val) if (len == sizeof(val)-1 && !memcmp(s, val, sizeof(val)-1)) return ret;
62
63 SEC_MECH_TEST(ZXID_SEC_MECH_X509, WSF11_SEC_MECH_NULL_X509);
64 SEC_MECH_TEST(ZXID_SEC_MECH_X509, WSF11_SEC_MECH_TLS_X509);
65 SEC_MECH_TEST(ZXID_SEC_MECH_X509, WSF11_SEC_MECH_CLTLS_X509);
66
67 SEC_MECH_TEST(ZXID_SEC_MECH_NULL, WSF11_SEC_MECH_NULL_NULL);
68 SEC_MECH_TEST(ZXID_SEC_MECH_NULL, WSF11_SEC_MECH_TLS_NULL);
69 SEC_MECH_TEST(ZXID_SEC_MECH_NULL, WSF11_SEC_MECH_CLTLS_NULL);
70 SEC_MECH_TEST(ZXID_SEC_MECH_NULL, WSF20_SEC_MECH_NULL_NULL);
71 SEC_MECH_TEST(ZXID_SEC_MECH_NULL, WSF20_SEC_MECH_TLS_NULL);
72
73 SEC_MECH_TEST(ZXID_SEC_MECH_PEERS, WSF20_SEC_MECH_CLTLS_PEERS2);
74
75 if (!epr->Metadata->SecurityContext->Token) {
76 INFO("EPR lacks Token despite not being NULL or X509. Forcing X509. %.*s", len, s);
77 return ZXID_SEC_MECH_X509;
78 }
79
80 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF10_SEC_MECH_NULL_BEARER);
81 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF10_SEC_MECH_TLS_BEARER);
82 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF11_SEC_MECH_NULL_BEARER);
83 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF11_SEC_MECH_TLS_BEARER);
84 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF11_SEC_MECH_CLTLS_BEARER);
85 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF20_SEC_MECH_NULL_BEARER);
86 SEC_MECH_TEST(ZXID_SEC_MECH_BEARER, WSF20_SEC_MECH_TLS_BEARER);
87
88 SEC_MECH_TEST(ZXID_SEC_MECH_SAML, WSF11_SEC_MECH_NULL_SAML);
89 SEC_MECH_TEST(ZXID_SEC_MECH_SAML, WSF11_SEC_MECH_TLS_SAML);
90 SEC_MECH_TEST(ZXID_SEC_MECH_SAML, WSF11_SEC_MECH_CLTLS_SAML);
91 SEC_MECH_TEST(ZXID_SEC_MECH_SAML, WSF20_SEC_MECH_NULL_SAML2);
92 SEC_MECH_TEST(ZXID_SEC_MECH_SAML, WSF20_SEC_MECH_TLS_SAML2);
93 SEC_MECH_TEST(ZXID_SEC_MECH_SAML, WSF20_SEC_MECH_CLTLS_SAML2);
94
95 ERR("Unknown security mechanism(%.*s), taking a guess...", len, s);
96
97 if (len >= sizeof("Bearer")-1 && zx_memmem(s, len, "Bearer", sizeof("Bearer")-1))
98 return ZXID_SEC_MECH_BEARER;
99 if (len >= sizeof("SAML")-1 && zx_memmem(s, len, "SAML", sizeof("SAML")-1))
100 return ZXID_SEC_MECH_BEARER;
101 if (len >= sizeof("X509")-1 && zx_memmem(s, len, "X509", sizeof("X509")-1))
102 return ZXID_SEC_MECH_BEARER;
103
104 ERR("Unknown security mechanism(%.*s), uable to guess.", len, s);
105 return ZXID_SEC_MECH_NULL;
106 }
107
108 #define ZX_URI_Id_CMP(hdr) ((hdr) && (hdr)->Id && (hdr)->Id->g.len == sref->URI->g.len-1 && !memcmp((hdr)->Id->g.s, sref->URI->g.s+1, (hdr)->Id->g.len))
109 #define ZX_URI_id_CMP(hdr) ((hdr) && (hdr)->id && (hdr)->id->g.len == sref->URI->g.len-1 && !memcmp((hdr)->id->g.s, sref->URI->g.s+1, (hdr)->id->g.len))
110
111 /*() For purposes of signature validation, add references and xml data structures
112 * of all apparently signed message parts.
113 * See also: zxid_add_header_refs() and zxsig_sign() or zxid_chk_sig() + zxsig_validate() */
114
115 /* Called by: wsse_sec_validate, zxid_wsc_valid_re_env, zxid_wsp_validate_env */
zxid_hunt_sig_parts(zxid_conf * cf,int n_refs,struct zxsig_ref * refs,struct zx_ds_Reference_s * sref,struct zx_e_Header_s * hdr,struct zx_e_Body_s * bdy)116 int zxid_hunt_sig_parts(zxid_conf* cf, int n_refs, struct zxsig_ref* refs, struct zx_ds_Reference_s* sref, struct zx_e_Header_s* hdr, struct zx_e_Body_s* bdy)
117 {
118 for (; sref && n_refs < ZXID_N_WSF_SIGNED_HEADERS; sref = (void*)ZX_NEXT(sref)) {
119 if (sref->gg.g.tok != zx_ds_Reference_ELEM)
120 continue;
121 if (!sref->URI || !sref->URI->g.len || !sref->URI->g.s || !sref->URI->g.s[0]) {
122 ERR("Malformed signature: Reference is missing URI %p n_refs=%d", sref->URI, n_refs);
123 continue;
124 }
125 refs[n_refs].sref = sref;
126 refs[n_refs].blob = 0;
127
128 /* Addressing and Security Headers */
129
130 if (ZX_URI_Id_CMP(hdr->Framework)) {
131 D("Found ref URI(%.*s) Framework %d", sref->URI->g.len, sref->URI->g.s, n_refs);
132 refs[n_refs].blob = (struct zx_elem_s*)hdr->Framework;
133 ++n_refs;
134 continue;
135 }
136
137 if (hdr->Security) {
138 if (ZX_URI_Id_CMP(hdr->Security->Timestamp)) {
139 D("Found ref URI(%.*s) Timestamp %d", sref->URI->g.len, sref->URI->g.s, n_refs);
140 refs[n_refs].blob = (struct zx_elem_s*)hdr->Security->Timestamp;
141 ++n_refs;
142 continue;
143 }
144 if (ZX_URI_Id_CMP(hdr->Security->SecurityTokenReference)) {
145 D("Found ref URI(%.*s) SecurityTokenReference %d", sref->URI->g.len, sref->URI->g.s, n_refs);
146 refs[n_refs].blob = (struct zx_elem_s*)hdr->Security->SecurityTokenReference;
147 ++n_refs;
148 continue;
149 }
150 }
151
152 if (ZX_URI_Id_CMP(hdr->MessageID)) {
153 D("Found ref URI(%.*s) MessageID %d", sref->URI->g.len, sref->URI->g.s, n_refs);
154 refs[n_refs].blob = (struct zx_elem_s*)hdr->MessageID;
155 ++n_refs;
156 continue;
157 }
158
159 if (ZX_URI_Id_CMP(hdr->RelatesTo)) {
160 D("Found ref URI(%.*s) RelatesTo %d", sref->URI->g.len, sref->URI->g.s, n_refs);
161 refs[n_refs].blob = (struct zx_elem_s*)hdr->RelatesTo;
162 ++n_refs;
163 continue;
164 }
165
166 if (ZX_URI_Id_CMP(hdr->Action)) {
167 D("Found ref URI(%.*s) Action %d", sref->URI->g.len, sref->URI->g.s, n_refs);
168 refs[n_refs].blob = (struct zx_elem_s*)hdr->Action;
169 ++n_refs;
170 continue;
171 }
172
173 if (ZX_URI_Id_CMP(hdr->To)) {
174 D("Found ref URI(%.*s) To %d", sref->URI->g.len, sref->URI->g.s, n_refs);
175 refs[n_refs].blob = (struct zx_elem_s*)hdr->To;
176 ++n_refs;
177 continue;
178 }
179
180 if (ZX_URI_Id_CMP(hdr->ReplyTo)) {
181 D("Found ref URI(%.*s) ReplyTo %d", sref->URI->g.len, sref->URI->g.s, n_refs);
182 refs[n_refs].blob = (struct zx_elem_s*)hdr->ReplyTo;
183 ++n_refs;
184 continue;
185 }
186
187 if (ZX_URI_Id_CMP(hdr->From)) {
188 D("Found ref URI(%.*s) From %d", sref->URI->g.len, sref->URI->g.s, n_refs);
189 refs[n_refs].blob = (struct zx_elem_s*)hdr->From;
190 ++n_refs;
191 continue;
192 }
193
194 if (ZX_URI_Id_CMP(hdr->Sender)) {
195 D("Found ref URI(%.*s) Sender %d", sref->URI->g.len, sref->URI->g.s, n_refs);
196 refs[n_refs].blob = (struct zx_elem_s*)hdr->Sender;
197 ++n_refs;
198 continue;
199 }
200
201 if (ZX_URI_Id_CMP(hdr->FaultTo)) {
202 D("Found ref URI(%.*s) FaultTo %d", sref->URI->g.len, sref->URI->g.s, n_refs);
203 refs[n_refs].blob = (struct zx_elem_s*)hdr->FaultTo;
204 ++n_refs;
205 continue;
206 }
207
208 if (ZX_URI_Id_CMP(hdr->ReferenceParameters)) {
209 D("Found ref URI(%.*s) ReferenceParameters %d", sref->URI->g.len, sref->URI->g.s, n_refs);
210 refs[n_refs].blob = (struct zx_elem_s*)hdr->ReferenceParameters;
211 ++n_refs;
212 continue;
213 }
214
215 /* ID-WSF headers */
216
217 if (ZX_URI_Id_CMP(hdr->TargetIdentity)) {
218 D("Found ref URI(%.*s) TargetIdentity %d", sref->URI->g.len, sref->URI->g.s, n_refs);
219 refs[n_refs].blob = (struct zx_elem_s*)hdr->TargetIdentity;
220 ++n_refs;
221 continue;
222 }
223
224 if (ZX_URI_Id_CMP(hdr->UsageDirective)) {
225 D("Found ref URI(%.*s) UsageDirective %d", sref->URI->g.len, sref->URI->g.s, n_refs);
226 refs[n_refs].blob = (struct zx_elem_s*)hdr->UsageDirective;
227 ++n_refs;
228 continue;
229 }
230
231 if (ZX_URI_Id_CMP(hdr->UserInteraction)) {
232 D("Found ref URI(%.*s) UserInteraction %d", sref->URI->g.len, sref->URI->g.s, n_refs);
233 refs[n_refs].blob = (struct zx_elem_s*)hdr->UserInteraction;
234 ++n_refs;
235 continue;
236 }
237
238 if (ZX_URI_Id_CMP(hdr->ProcessingContext)) {
239 D("Found ref URI(%.*s) ProcessingContext %d", sref->URI->g.len, sref->URI->g.s, n_refs);
240 refs[n_refs].blob = (struct zx_elem_s*)hdr->ProcessingContext;
241 ++n_refs;
242 continue;
243 }
244
245 if (ZX_URI_Id_CMP(hdr->EndpointUpdate)) {
246 D("Found ref URI(%.*s) EndpointUpdate %d", sref->URI->g.len, sref->URI->g.s, n_refs);
247 refs[n_refs].blob = (struct zx_elem_s*)hdr->EndpointUpdate;
248 ++n_refs;
249 continue;
250 }
251
252 if (ZX_URI_Id_CMP(hdr->Timeout)) {
253 D("Found ref URI(%.*s) Timeout %d", sref->URI->g.len, sref->URI->g.s, n_refs);
254 refs[n_refs].blob = (struct zx_elem_s*)hdr->Timeout;
255 ++n_refs;
256 continue;
257 }
258
259 if (ZX_URI_Id_CMP(hdr->Consent)) {
260 D("Found ref URI(%.*s) Consent %d", sref->URI->g.len, sref->URI->g.s, n_refs);
261 refs[n_refs].blob = (struct zx_elem_s*)hdr->Consent;
262 ++n_refs;
263 continue;
264 }
265
266 if (ZX_URI_Id_CMP(hdr->ApplicationEPR)) {
267 D("Found ref URI(%.*s) ApplicationEPR %d", sref->URI->g.len, sref->URI->g.s, n_refs);
268 refs[n_refs].blob = (struct zx_elem_s*)hdr->ApplicationEPR;
269 ++n_refs;
270 continue;
271 }
272
273 if (ZX_URI_Id_CMP(hdr->RedirectRequest)) {
274 D("Found ref URI(%.*s) RedirectRequest %d", sref->URI->g.len, sref->URI->g.s, n_refs);
275 refs[n_refs].blob = (struct zx_elem_s*)hdr->RedirectRequest;
276 ++n_refs;
277 continue;
278 }
279
280 if (ZX_URI_Id_CMP(hdr->CredentialsContext)) {
281 D("Found ref URI(%.*s) CredentialsContext %d", sref->URI->g.len, sref->URI->g.s, n_refs);
282 refs[n_refs].blob = (struct zx_elem_s*)hdr->CredentialsContext;
283 ++n_refs;
284 continue;
285 }
286
287 /* TAS3 specifics */
288
289 if (ZX_URI_Id_CMP(hdr->Credentials)) {
290 D("Found ref URI(%.*s) Credentials %d", sref->URI->g.len, sref->URI->g.s, n_refs);
291 refs[n_refs].blob = (struct zx_elem_s*)hdr->Credentials;
292 ++n_refs;
293 continue;
294 }
295
296 if (ZX_URI_Id_CMP(hdr->ESLPolicies)) {
297 D("Found ref URI(%.*s) ESLPolicies %d", sref->URI->g.len, sref->URI->g.s, n_refs);
298 refs[n_refs].blob = (struct zx_elem_s*)hdr->ESLPolicies;
299 ++n_refs;
300 continue;
301 }
302
303 /* Old ID-WSF 1.2 Headers and App specific headers */
304
305 if (ZX_URI_id_CMP(hdr->Correlation)) {
306 D("Found ref URI(%.*s) Correlation %d", sref->URI->g.len, sref->URI->g.s, n_refs);
307 refs[n_refs].blob = (struct zx_elem_s*)hdr->Correlation;
308 ++n_refs;
309 continue;
310 }
311
312 if (ZX_URI_id_CMP(hdr->Provider)) {
313 D("Found ref URI(%.*s) Provider %d", sref->URI->g.len, sref->URI->g.s, n_refs);
314 refs[n_refs].blob = (struct zx_elem_s*)hdr->Provider;
315 ++n_refs;
316 continue;
317 }
318
319 if (ZX_URI_id_CMP(hdr->b12_ProcessingContext)) {
320 D("Found ref URI(%.*s) b12_ProcessingContext %d", sref->URI->g.len, sref->URI->g.s, n_refs);
321 refs[n_refs].blob = (struct zx_elem_s*)hdr->b12_ProcessingContext;
322 ++n_refs;
323 continue;
324 }
325
326 if (ZX_URI_id_CMP(hdr->b12_Consent)) {
327 D("Found ref URI(%.*s) b12_Consent %d", sref->URI->g.len, sref->URI->g.s, n_refs);
328 refs[n_refs].blob = (struct zx_elem_s*)hdr->b12_Consent;
329 ++n_refs;
330 continue;
331 }
332
333 if (ZX_URI_id_CMP(hdr->b12_UsageDirective)) {
334 D("Found ref URI(%.*s) b12_UsageDirective %d", sref->URI->g.len, sref->URI->g.s, n_refs);
335 refs[n_refs].blob = (struct zx_elem_s*)hdr->b12_UsageDirective;
336 ++n_refs;
337 continue;
338 }
339 #if 0
340 if (ZX_URI_id_CMP(hdr->TransactionID)) {
341 D("Found ref URI(%.*s) TransactionID %d", sref->URI->g.len, sref->URI->g.s, n_refs);
342 refs[n_refs].blob = (struct zx_elem_s*)hdr->TransactionID;
343 ++n_refs;
344 continue;
345 }
346 #endif
347 if (ZX_URI_id_CMP(bdy)) {
348 D("Found ref URI(%.*s) Body %d", sref->URI->g.len, sref->URI->g.s, n_refs);
349 refs[n_refs].blob = (struct zx_elem_s*)bdy;
350 ++n_refs;
351 continue;
352 }
353 }
354 return n_refs;
355 }
356
357 #define ZXID_ADD_WSU_ID(H,idval) MB if (!H->Id) \
358 H->Id = zx_ord_ins_at(&H->gg, zx_ref_attr(cf->ctx, 0, zx_wsu_Id_ATTR, idval)); \
359 refs[n_refs].id = &H->Id->g; \
360 refs[n_refs].canon = zx_easy_enc_elem_sig(cf, &H->gg); \
361 ++n_refs; ME
362
363 #define ZXID_ADD_ID(H,idval) MB if (!H->id) \
364 H->id = zx_ord_ins_at(&H->gg, zx_ref_attr(cf->ctx, 0, zx_id_ATTR, idval)); \
365 refs[n_refs].id = &H->id->g; \
366 refs[n_refs].canon = zx_easy_enc_elem_sig(cf, &H->gg); \
367 ++n_refs; ME
368
369
370 /*() For purposes of signing, add references and canon forms of all known SOAP headers.
371 * N.B. This function only works for preparing for signing.
372 * See also: zxsig_sign(), zxid_hunt_sig_parts() or zxid_chk_sig() + zxsig_validate() */
373
374 /* Called by: zxid_wsf_sign */
zxid_add_header_refs(zxid_conf * cf,int n_refs,struct zxsig_ref * refs,struct zx_e_Header_s * hdr)375 int zxid_add_header_refs(zxid_conf* cf, int n_refs, struct zxsig_ref* refs, struct zx_e_Header_s* hdr)
376 {
377 /* Addressing and Security Headers */
378
379 if (hdr->Framework)
380 ZXID_ADD_WSU_ID(hdr->Framework,"FWK");
381 if (hdr->Security && hdr->Security->Timestamp)
382 ZXID_ADD_WSU_ID(hdr->Security->Timestamp,"TS");
383 if (hdr->MessageID)
384 ZXID_ADD_WSU_ID(hdr->MessageID,"MID");
385 if (hdr->RelatesTo)
386 ZXID_ADD_WSU_ID(hdr->RelatesTo,"REL");
387 if (hdr->Action)
388 ZXID_ADD_WSU_ID(hdr->Action,"ACT");
389 if (hdr->To)
390 ZXID_ADD_WSU_ID(hdr->To,"TO");
391 if (hdr->ReplyTo)
392 ZXID_ADD_WSU_ID(hdr->ReplyTo,"REP");
393 if (hdr->From)
394 ZXID_ADD_WSU_ID(hdr->From,"FRM");
395 if (hdr->Sender)
396 ZXID_ADD_WSU_ID(hdr->Sender,"PRV");
397 if (hdr->FaultTo)
398 ZXID_ADD_WSU_ID(hdr->FaultTo,"FLT");
399 if (hdr->ReferenceParameters)
400 ZXID_ADD_WSU_ID(hdr->ReferenceParameters,"PAR");
401
402 /* ID-WSF headers */
403
404 if (hdr->TargetIdentity)
405 ZXID_ADD_WSU_ID(hdr->TargetIdentity,"TRG");
406 if (hdr->UsageDirective)
407 ZXID_ADD_WSU_ID(hdr->UsageDirective,"UD");
408 if (hdr->UserInteraction)
409 ZXID_ADD_WSU_ID(hdr->UserInteraction,"UI");
410 if (hdr->ProcessingContext)
411 ZXID_ADD_WSU_ID(hdr->ProcessingContext,"PC");
412 if (hdr->EndpointUpdate)
413 ZXID_ADD_WSU_ID(hdr->EndpointUpdate,"EP");
414 if (hdr->Timeout)
415 ZXID_ADD_WSU_ID(hdr->Timeout,"TI");
416 if (hdr->Consent)
417 ZXID_ADD_WSU_ID(hdr->Consent,"CON");
418 if (hdr->ApplicationEPR)
419 ZXID_ADD_WSU_ID(hdr->ApplicationEPR,"AEP");
420 if (hdr->RedirectRequest)
421 ZXID_ADD_WSU_ID(hdr->RedirectRequest,"RR");
422 if (hdr->CredentialsContext)
423 ZXID_ADD_WSU_ID(hdr->CredentialsContext,"CCX");
424
425 /* TAS3 specifics */
426
427 if (hdr->Credentials)
428 ZXID_ADD_WSU_ID(hdr->Credentials,"CRED");
429 if (hdr->ESLPolicies)
430 ZXID_ADD_WSU_ID(hdr->ESLPolicies,"ESL");
431
432 /* Old ID-WSF 1.2 Headers and App specific headers */
433
434 if (hdr->Correlation)
435 ZXID_ADD_ID(hdr->Correlation,"COR");
436 if (hdr->Provider)
437 ZXID_ADD_ID(hdr->Provider,"PROV12");
438 if (hdr->b12_ProcessingContext)
439 ZXID_ADD_ID(hdr->b12_ProcessingContext,"PC12");
440 if (hdr->b12_Consent)
441 ZXID_ADD_ID(hdr->b12_Consent,"CON12");
442 if (hdr->b12_UsageDirective)
443 ZXID_ADD_ID(hdr->b12_UsageDirective,"UD12");
444 #if 0
445 if (hdr->TransactionID)
446 ZXID_ADD_ID(hdr->TransactionID,"MM7TX"); /* *** mm7:TransactionID does not have id or Id */
447 #endif
448 return n_refs;
449 }
450
451 /*() Apply WSF style signature. */
452
453 /* Called by: zxid_wsc_prep_secmech x3, zxid_wsf_decor */
zxid_wsf_sign(zxid_conf * cf,int sign_flags,struct zx_wsse_Security_s * sec,struct zx_wsse_SecurityTokenReference_s * str,struct zx_e_Header_s * hdr,struct zx_e_Body_s * bdy)454 void zxid_wsf_sign(zxid_conf* cf, int sign_flags, struct zx_wsse_Security_s* sec, struct zx_wsse_SecurityTokenReference_s* str, struct zx_e_Header_s* hdr, struct zx_e_Body_s* bdy)
455 {
456 X509* sign_cert;
457 EVP_PKEY* sign_pkey;
458 int n_refs;
459 struct zxsig_ref refs[ZXID_N_WSF_SIGNED_HEADERS];
460
461 if (sign_flags) {
462 n_refs = 0;
463
464 if (sign_flags & ZXID_SIGN_HDR)
465 n_refs = zxid_add_header_refs(cf, n_refs, refs, hdr);
466
467 if (str)
468 ZXID_ADD_WSU_ID(str,"STR");
469
470 if (bdy && (sign_flags & ZXID_SIGN_BDY))
471 ZXID_ADD_ID(bdy,"BDY");
472
473 ASSERTOPI(ZXID_N_WSF_SIGNED_HEADERS, >=, n_refs);
474
475 if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert wsc")) {
476 sec->Signature = zxsig_sign(cf->ctx, n_refs, refs, sign_cert, sign_pkey, cf->xmldsig_sig_meth, cf->xmldsig_digest_algo);
477 zx_add_kid(&sec->gg, &sec->Signature->gg);
478 }
479 }
480 }
481
482 /*() Check ID-WSF Timestamp.
483 * The validity is controlled by configuration parameters BEFORE_SLOP and AFTER_SLOP.
484 * returns 1 on success, 0 on failure. */
485
486 /* Called by: zxid_wsc_valid_re_env, zxid_wsp_validate_env */
zxid_timestamp_chk(zxid_conf * cf,zxid_ses * ses,struct zx_wsu_Timestamp_s * ts,struct timeval * ourts,struct timeval * srcts,const char * ctlpt,const char * faultactor)487 int zxid_timestamp_chk(zxid_conf* cf, zxid_ses* ses, struct zx_wsu_Timestamp_s* ts, struct timeval* ourts, struct timeval* srcts, const char* ctlpt, const char* faultactor)
488 {
489 if (ts && ZX_SIMPLE_ELEM_CHK(ts->Created)) {
490 srcts->tv_sec = zx_date_time_to_secs(ZX_GET_CONTENT_S(ts->Created));
491
492 if (srcts->tv_sec >= ourts->tv_sec - cf->before_slop
493 && srcts->tv_sec <= ourts->tv_sec + cf->after_slop) {
494 D("Timestamp accepted src=%d our=%d before_slop=%d after_slop=%d", (int)srcts->tv_sec, (int)ourts->tv_sec, cf->before_slop, cf->after_slop);
495 } else {
496 if (cf->notimestamp_fatal) {
497 ERR("Timestamp rejected: src=%d our=%d before_slop=%d after_slop=%d secs", (int)srcts->tv_sec, (int)ourts->tv_sec, cf->before_slop, cf->after_slop);
498 zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, ctlpt, faultactor, "Message signature did not validate.", "StaleMsg", 0, 0, 0));
499 return 0;
500 } else {
501 INFO("Timestamp rejected: src=%d our=%d before_slop=%d after_slop=%d secs, but configured to ignore this (NOTIMESTAMP_FATAL=0)", (int)srcts->tv_sec, (int)ourts->tv_sec, cf->before_slop, cf->after_slop);
502 }
503 }
504
505 } else {
506 if (cf->notimestamp_fatal) {
507 ERR("No Security/Timestamp found. %p", ts);
508 zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, ctlpt, faultactor, "No unable to find wsse:Security/Timestamp.", "StaleMsg", 0, 0, 0));
509 return 0;
510 } else {
511 INFO("No Security/Timestamp found, but configured to ignore this (NOTIMESTAMP_FATAL=0). %p", ts);
512 D("No ts OK %p", ts);
513 }
514 }
515 return 1;
516 }
517
518 /*() Attach a SOL usage directive, unless the envelope already has UsageDirective
519 * header. If you wish to add other UsageDirectives, you must provide all of the
520 * usage directives to zxid_call() envelope argument.
521 * The obl argument typically comes from cf->wsc_localpdp_obl_pledge
522 * or cf->wsp_localpdp_obl_emit */
523
524 /* Called by: zxid_wsc_prep, zxid_wsf_decor */
zxid_attach_sol1_usage_directive(zxid_conf * cf,zxid_ses * ses,struct zx_e_Envelope_s * env,const char * attrid,const char * obl)525 void zxid_attach_sol1_usage_directive(zxid_conf* cf, zxid_ses* ses, struct zx_e_Envelope_s* env, const char* attrid, const char* obl)
526 {
527 struct zx_b_UsageDirective_s* ud;
528 if (!env || !env->Header) {
529 ERR("Malformed envelope %p", env);
530 return;
531 }
532 if (!attrid || !*attrid) {
533 ERR("attrid argument must be supplied %p", attrid);
534 return;
535 }
536 if (env->Header->UsageDirective) {
537 INFO("UsageDirective already set by caller %d",0);
538 return;
539 }
540 if (!obl || !*obl)
541 return;
542
543 env->Header->UsageDirective = ud = zx_NEW_b_UsageDirective(cf->ctx, &env->Header->gg);
544 ud->mustUnderstand = zx_ref_attr(cf->ctx, &ud->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
545 ud->actor = zx_ref_attr(cf->ctx, &ud->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
546 ud->Obligation = zx_NEW_xa_Obligation(cf->ctx, &ud->gg);
547 ud->Obligation->ObligationId = zx_ref_attr(cf->ctx, &ud->Obligation->gg, zx_ObligationId_ATTR, TAS3_SOL1_ENGINE);
548 ud->Obligation->FulfillOn = zx_ref_attr(cf->ctx, &ud->Obligation->gg, zx_FulfillOn_ATTR, "Permit");
549 ud->Obligation->AttributeAssignment = zx_NEW_xa_AttributeAssignment(cf->ctx, &ud->Obligation->gg);
550 ud->Obligation->AttributeAssignment->DataType = zx_ref_attr(cf->ctx, &ud->Obligation->AttributeAssignment->gg, zx_DataType_ATTR, XS_STRING);
551 ud->Obligation->AttributeAssignment->AttributeId = zx_dup_attr(cf->ctx, &ud->Obligation->AttributeAssignment->gg, zx_AttributeId_ATTR, attrid);
552 zx_add_content(cf->ctx, &ud->Obligation->AttributeAssignment->gg, zx_dup_str(cf->ctx, obl));
553 D("Attached (%s) obligations(%s)", attrid, obl);
554 }
555
556 /*() Evaluate pledges from UsageDirective against the configured SOL policy.
557 *
558 * cf:: zxid configuration object
559 * ses:: session object
560 * obl:: pledges from UsageDirective in the request
561 * req:: required policies, usually from cf->wsp_localpdp_obl_req or cf->wsc_localpdp_obl_accept
562 * return:: 0 if pladges fail, 1 if pledges are compatible with the required policies
563 *
564 * All clauses in req must be satisfied by obl. If obl pledges more than required, the excess
565 * is silently ignored. If comma separated list of values is specified either as
566 * obl or req, all values on obl (pledge) must be found in req, but not all values
567 * of req need to be found in obl. This semantic would allow, for example, req to specify
568 * all acceptable uses and require each use in pledges to match some use in req.
569 * Wild cards (any value, but not prefix, suffix, or substring) in req (and obl) are possible.
570 * Negation is not supported: if it is not explicitly listed as ok, then it is rejected.
571 */
572
573 /* Called by: zxid_wsp_validate_env */
zxid_eval_sol1(zxid_conf * cf,zxid_ses * ses,const char * obl,struct zxid_obl_list * req)574 int zxid_eval_sol1(zxid_conf* cf, zxid_ses* ses, const char* obl, struct zxid_obl_list* req)
575 {
576 char* oblig;
577 struct zxid_obl_list* ol;
578 struct zxid_obl_list* ob = 0;
579 struct zxid_cstr_list* cs = 0;
580
581 if (!obl) {
582 if (!req)
583 return 1;
584 ERR("Fail: no pledges supplied and pledges required %p", req);
585 return 0;
586 }
587
588 oblig = zx_dup_cstr(cf->ctx, obl); /* Will be modified in place so we need a copy */
589 ol = zxid_load_obl_list(cf, 0, oblig);
590 for (; req; req = req->n) {
591 ob = zxid_find_obl_list(ol, req->name);
592 if (!ob)
593 goto fail;
594 /* Validate every value of the pledge as accpteble in requirement. */
595 for (cs = ob->vals; cs; cs = cs->n)
596 if (!zxid_find_cstr_list(req->vals, cs->s))
597 goto fail;
598 }
599
600 INFO("OK: Pledges match requirements. Pledges(%s)", obl);
601 zxid_free_obl_list(cf, ol);
602 ZX_FREE(cf->ctx, oblig);
603 return 1;
604
605 fail:
606 ERR("Fail: missing required obligation(%s), value(%s). Pledge(%s)", req?req->name:"-", cs?cs->s:"*", STRNULLCHKD(obl));
607 zxid_free_obl_list(cf, ol);
608 ZX_FREE(cf->ctx, oblig);
609 return 0;
610 }
611
612 /*() Create Action attribute, which will be used by XACML authorization,
613 * by concatenating the namespace URL and first child of SOAP Body. As
614 * the first child usually is the action verb in many SOAP Requests,
615 * we get a usable action. This convention is also recommended
616 * in Liberty Alliance Data Services Template 2.1 section 9 "Actions".
617 *
618 * Example:
619 * ...<e:Body><di:Query xmlns:di="urn:liberty:disco:2006-08">...
620 * results
621 * Action=urn:liberty:disco:2006-08:Query
622 */
623
624 /* Called by: zxid_query_ctlpt_pdp */
zxid_add_action_from_body_child(zxid_conf * cf,zxid_ses * ses,struct zx_e_Envelope_s * env)625 void zxid_add_action_from_body_child(zxid_conf* cf, zxid_ses* ses, struct zx_e_Envelope_s* env)
626 {
627 struct zx_elem_s* el;
628 int len;
629 char* p;
630
631 /* Skip over any string data, like whitespace, that may precede the element. */
632 for (el = env->Body->gg.kids; el && el->g.tok == ZX_TOK_DATA; el = (struct zx_elem_s*)el->g.n) ;
633 if (!el) {
634 ERR("No Body child element could be found for setting Action %p", env->Body->gg.kids);
635 return;
636 }
637 len = el->g.len;
638 p = el->g.s;
639
640 D("Action from Body child ns(%s) name(%.*s)", el->ns->url, len, p);
641 if (p = memchr(p, ':', len)) {
642 ++p;
643 len -= p - el->g.s;
644 }
645 zxid_add_attr_to_ses(cf, ses, "Action", zx_strf(cf->ctx, "%s:%.*s", el->ns->url, len, p));
646 }
647
648 /*() Query Local PDP and remote PDP (if PDP_URL is defined). */
649
650 /* Called by: zxid_call_epr, zxid_wsc_prepare_call, zxid_wsc_valid_re_env, zxid_wsp_decorate, zxid_wsp_validate_env */
zxid_query_ctlpt_pdp(zxid_conf * cf,zxid_ses * ses,const char * az_cred,struct zx_e_Envelope_s * env,const char * ctlpt,const char * faultparty,struct zxid_map * pepmap)651 int zxid_query_ctlpt_pdp(zxid_conf* cf, zxid_ses* ses, const char* az_cred, struct zx_e_Envelope_s* env, const char* ctlpt, const char* faultparty, struct zxid_map* pepmap)
652 {
653 /* Populate action from first subelement of body */
654 if (env->Body && env->Body->gg.kids) {
655 zxid_add_action_from_body_child(cf, ses, env);
656 } else {
657 ERR("SOAP Body does not appear to have any subelements?!? %p", env->Body);
658 }
659
660 /* Populate other attributes, such as rs to indicate resource. */
661 if (az_cred)
662 zxid_add_qs2ses(cf, ses, zx_dup_cstr(cf->ctx, az_cred), 1);
663 zxid_add_qs2ses(cf, ses, zx_alloc_sprintf(cf->ctx, 0, "urn:tas3:ctlpt=%s", ctlpt), 1);
664
665 if (!zxid_localpdp(cf, ses)) {
666 ERR("%s: Deny by local PDP", ctlpt);
667 zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, ctlpt, faultparty, "Denied by local policy", TAS3_STATUS_DENY, 0, 0, 0));
668 return 0;
669 } else if (cf->pdp_url && *cf->pdp_url) {
670 if (!zxid_pep_az_soap_pepmap(cf, 0, ses, cf->pdp_url, pepmap, ctlpt)) {
671 ERR("%s: Deny", ctlpt);
672 zxid_set_fault(cf, ses, zxid_mk_fault(cf, 0, ctlpt, faultparty, "Denied by policy at PDP", TAS3_STATUS_DENY, 0, 0, 0));
673 return 0;
674 }
675 }
676 return 1;
677 }
678
679 /* EOF -- zxidwsf.c */
680