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