Branch data Line data Source code
1 : : /* zxidpep.c - Handwritten functions for XACML Policy Enforcement Point
2 : : * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 : : * Copyright (c) 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: zxidpep.c,v 1.10 2010-01-08 02:10:09 sampo Exp $
10 : : *
11 : : * 24.8.2009, created --Sampo
12 : : * 10.10.2009, added zxid_az() family --Sampo
13 : : * 12.2.2010, added locking to lazy loading --Sampo
14 : : * 31.5.2010, generalized to several PEPs model --Sampo
15 : : * 7.9.2010, merged patches from Stijn Lievens --Sampo
16 : : */
17 : :
18 : : #include "errmac.h"
19 : : #include "zxid.h"
20 : : #include "zxidpriv.h"
21 : : #include "zxidconf.h"
22 : : #include "saml2.h"
23 : : #include "c/zx-const.h"
24 : : #include "c/zx-ns.h"
25 : : #include "c/zx-data.h"
26 : : #include "c/zx-e-data.h"
27 : :
28 : : #if 0
29 : : #define XS_STRING "xs:string"
30 : : #else
31 : : #define XS_STRING "http://www.w3.org/2001/XMLSchema#string"
32 : : #endif
33 : :
34 : : /* ============== Policy Enforcement Point, Authorization Decision Query ============== */
35 : :
36 : : /*() Extract attributes from session pool according to pepmap, usually the PEPMAP
37 : : * configuration variable.
38 : : *
39 : : * cf:: the configuration will need to have ~PEPMAP~ and ~PDP_URL~ options
40 : : * set according to your situation.
41 : : * cgi:: if non-null, will receive error and status codes
42 : : * ses:: all attributes are obtained from the session. You may wish
43 : : * to add additional attributes that are not known by SSO.
44 : : * pepmap:: The map used to extract the attributes from the pool to the XACML request
45 : : * subj:: Value-result parameter. Linked list of subject attributes.
46 : : * rsrc:: Value-result parameter. Linked list of resource attributes.
47 : : * act:: Value-result parameter. Linked list of action attributes (usually just one attribute).
48 : : * env:: Value-result parameter. Linked list of environment attributes.
49 : : */
50 : :
51 : : /* Called by: zxid_pep_az_base_soap_pepmap, zxid_pep_az_soap_pepmap */
52 : : static void zxid_pepmap_extract(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, struct zxid_map* pepmap, struct zx_xac_Attribute_s** subj, struct zx_xac_Attribute_s** rsrc, struct zx_xac_Attribute_s** act, struct zx_xac_Attribute_s** env)
53 : 89 : {
54 : : struct zxid_map* map;
55 : : struct zxid_attr* at;
56 : : struct zxid_attr* av;
57 : : struct zx_xac_Attribute_s* xac_at;
58 : : char* name;
59 : :
60 [ + - + + ]: 4363 : for (at = ses?ses->at:0; at; at = at->n) {
61 : 4274 : map = zxid_find_map(pepmap, at->name);
62 [ - + ]: 4274 : if (!map) {
63 [ # # # # ]: 0 : D("ATTR(%s)=VAL(%s): Ignored due to no matching PEPMAP", at->name, at->val);
64 : 0 : continue;
65 : : }
66 : :
67 [ + + ]: 4274 : if (map->rule == ZXID_MAP_RULE_DEL) {
68 [ + + - + ]: 198 : D("attribute(%s) filtered out by del rule in PEPMAP", at->name);
69 : 198 : continue;
70 : : }
71 : :
72 : 4076 : at->map_val = zxid_map_val(cf, ses, 0, map, at->name, at->val);
73 [ + - + + : 4291 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
+ - + - ]
74 [ + + - + ]: 215 : D("renaming(%s) to(%s) orig_val(%s) map_val(%.*s)", at->name, map->dst, at->val, at->map_val->len, at->map_val->s);
75 : 215 : name = map->dst;
76 : : } else {
77 : 3861 : name = at->name;
78 : : }
79 : 4076 : xac_at = zxid_mk_xacml_simple_at(cf, 0,
80 : : zx_dup_str(cf->ctx, name),
81 : : zx_dup_str(cf->ctx, XS_STRING),
82 : : at->issuer, at->map_val);
83 [ + - + - ]: 8152 : if (map->ns && *map->ns) {
84 [ + + ]: 4076 : if (!strcmp(map->ns, "subj")) {
85 : 99 : ZX_NEXT(xac_at) = (void*)*subj;
86 : 99 : *subj = xac_at;
87 [ + + ]: 3977 : } else if (!strcmp(map->ns, "rsrc")) {
88 : 99 : ZX_NEXT(xac_at) = (void*)*rsrc;
89 : 99 : *rsrc = xac_at;
90 [ + + ]: 3878 : } else if (!strcmp(map->ns, "act")) {
91 : : #if 0
92 : : *act = xac_at; /* there can be only one */
93 : : #else
94 : 17 : ZX_NEXT(xac_at) = (void*)*act;
95 : 17 : *act = xac_at; /* We can have multiple attributes in the action section */
96 : : #endif
97 [ + - ]: 3861 : } else if (!strcmp(map->ns, "env")) {
98 : 3861 : ZX_NEXT(xac_at) = (void*)*env;
99 : 3861 : *env = xac_at;
100 : : } else {
101 : 0 : ERR("PEPMAP unknown ns(%s). Valid values are subj, rsrc, act, and env.", map->ns);
102 : : }
103 : : } else {
104 : 0 : ERR("PEPMAP entry lacks ns %p", map->ns);
105 : : }
106 : :
107 [ - + ]: 4076 : for (av = at->nv; av; av = av->n) {
108 : 0 : av->map_val = zxid_map_val(cf, ses, 0, map, at->name, av->val);
109 : 0 : xac_at = zxid_mk_xacml_simple_at(cf, 0,
110 : : zx_dup_str(cf->ctx, name),
111 : : zx_dup_str(cf->ctx, XS_STRING),
112 : : at->issuer, at->map_val);
113 [ # # # # ]: 0 : if (map->ns && *map->ns) {
114 [ # # ]: 0 : if (!strcmp(map->ns, "subj")) {
115 : 0 : ZX_NEXT(xac_at) = (void*)*subj;
116 : 0 : *subj = xac_at;
117 [ # # ]: 0 : } else if (!strcmp(map->ns, "rsrc")) {
118 : 0 : ZX_NEXT(xac_at) = (void*)*rsrc;
119 : 0 : *rsrc = xac_at;
120 [ # # ]: 0 : } else if (!strcmp(map->ns, "act")) {
121 : 0 : ERR("PEPMAP: Only one XACML action attribute allowed %d", 0);
122 [ # # ]: 0 : } else if (!strcmp(map->ns, "env")) {
123 : 0 : ZX_NEXT(xac_at) = (void*)*env;
124 : 0 : *env = xac_at;
125 : : } else {
126 : 0 : ERR("PEPMAP unknown ns(%s). Valid values are subj, rsrc, act, and env.", map->ns);
127 : : }
128 : : } else {
129 : 0 : ERR("PEPMAP entry lacks ns %p", map->ns);
130 : : }
131 : : }
132 : : }
133 : :
134 [ + + ]: 89 : if (!*act) {
135 : 72 : *act = zxid_mk_xacml_simple_at(cf, 0,
136 : : zx_dup_str(cf->ctx, "urn:oasis:names:tc:xacml:1.0:action:action-id"),
137 : : zx_dup_str(cf->ctx, XS_STRING),
138 : : 0,
139 : : zx_dup_str(cf->ctx, "urn:oasis:names:tc:xacml:1.0:action:implied-action"));
140 : : }
141 : 89 : }
142 : :
143 : : /*() Call Policy Decision Point (PDP) to obtain an authorization decision
144 : : * about a contemplated action on a resource. The attributes from the session
145 : : * pool, as filtered by PEPMAP are fed to the PDP as inputs
146 : : * for the decision. The call is using XACML SAML profile over SOAP.
147 : : *
148 : : * cf:: the configuration will need to have ~PEPMAP~ and ~PDP_URL~ options
149 : : * set according to your situation.
150 : : * cgi:: if non-null, will receive error and status codes
151 : : * ses:: all attributes are obtained from the session. You may wish
152 : : * to add additional attributes that are not known by SSO.
153 : : * pdp_url:: URL of the PDP to contact
154 : : * subj:: Linked list of subject attributes.
155 : : * rsrc:: Linked list of resource attributes.
156 : : * act:: Linked list of action attributes (usually just one attribute).
157 : : * env:: Linked list of environment attributes.
158 : : * returns:: SAML Response as data structure or null upon error.
159 : : */
160 : :
161 : : /* Called by: zxid_pep_az_base_soap_pepmap, zxid_pep_az_soap_pepmap */
162 : : static struct zx_sp_Response_s* zxid_az_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, const char* pdp_url, struct zx_xac_Attribute_s* subj, struct zx_xac_Attribute_s* rsrc, struct zx_xac_Attribute_s* act, struct zx_xac_Attribute_s* env)
163 : 89 : {
164 : : X509* sign_cert;
165 : : EVP_PKEY* sign_pkey;
166 : : struct zxsig_ref refs;
167 : : struct zx_root_s* r;
168 : : struct zx_e_Header_s* hdr;
169 : : struct zx_e_Body_s* body;
170 : : struct zx_wsse_Security_s* sec;
171 : : struct zx_str* ss;
172 : : struct zx_sp_Response_s* resp;
173 : :
174 : 89 : hdr = zx_NEW_e_Header(cf->ctx,0);
175 : : #if 0
176 : : hdr->Action = zx_NEW_a_Action(cf->ctx, &hdr->gg);
177 : : //zx_add_content(cf->ctx, &hdr->Action->gg, zx_dup_str(cf->ctx, "urn:oasis:names:tc:xacml:2.0:profile:saml2.0:v2:schema:protocol:cd-01"));
178 : : zx_add_content(cf->ctx, &hdr->Action->gg, zx_dup_str(cf->ctx, "urn:oasis:xacml:2.0:saml:protocol:schema:os"));
179 : :
180 : : //zx_add_content(cf->ctx, &hdr->Action->gg, zx_dup_str(cf->ctx, "SAML2XACMLAuthzRequest"));
181 : : //zx_add_content(cf->ctx, &hdr->Action->gg, zx_dup_str(cf->ctx, "http://ws.apache.org/axis2/TestPolicyPortType/authRequestRequest"));
182 : : hdr->Action->mustUnderstand = zx_ref_str(cf->ctx, XML_TRUE);
183 : : hdr->Action->actor = zx_ref_str(cf->ctx, SOAP_ACTOR_NEXT);
184 : : #endif
185 : :
186 : : /* Add our own token so PDP can do whatever PEP can (they are considered to be
187 : : * part of the same entity). This is TAS3 specific hack. */
188 : :
189 : 89 : sec = hdr->Security = zx_NEW_wsse_Security(cf->ctx, &hdr->gg);
190 : 89 : sec->actor = zx_ref_attr(cf->ctx, &sec->gg, zx_e_actor_ATTR, SOAP_ACTOR_NEXT);
191 : 89 : sec->mustUnderstand = zx_ref_attr(cf->ctx, &sec->gg, zx_e_mustUnderstand_ATTR, XML_TRUE);
192 : 89 : sec->Timestamp = zx_NEW_wsu_Timestamp(cf->ctx, &sec->gg);
193 : 89 : sec->Timestamp->Created = zx_NEW_wsu_Created(cf->ctx, &sec->Timestamp->gg);
194 : 89 : sec->Assertion = ses->tgta7n;
195 : 89 : zx_reverse_elem_lists(&sec->gg);
196 [ + + - + ]: 89 : D("tgta7n=%p", ses->tgta7n);
197 : :
198 : : /* Prepare request according to the version */
199 : :
200 : 89 : body = zx_NEW_e_Body(cf->ctx,0);
201 [ - + ]: 89 : if (!strcmp(cf->xasp_vers, "xac-soap")) {
202 : 0 : ZX_ADD_KID(body, xac_Request, zxid_mk_xac_az(cf, &body->gg, subj, rsrc, act, env));
203 : : #if 0
204 : : /* *** xac:Response does not have signature field */
205 : : if (cf->sso_soap_sign) {
206 : : ZERO(&refs, sizeof(refs));
207 : : refs.id = body->xac_Request->ID;
208 : : refs.canon = zx_EASY_ENC_SO_xac_Request(cf->ctx, body->xac_Request);
209 : : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert az xac-soap")) {
210 : : body->xac_Request->Signature = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
211 : : zx_add_kid(&body->xac_Request->gg, &body->xac_Request->Signature->gg);
212 : : }
213 : : zx_str_free(cf->ctx, refs.canon);
214 : : }
215 : : #endif
216 [ - + ]: 89 : } else if (!strcmp(cf->xasp_vers, "2.0-cd1")) {
217 : 0 : ZX_ADD_KID(body, xaspcd1_XACMLAuthzDecisionQuery, zxid_mk_az_cd1(cf, subj, rsrc, act, env));
218 [ # # ]: 0 : if (cf->sso_soap_sign) {
219 : 0 : ZERO(&refs, sizeof(refs));
220 : 0 : refs.id = &body->xaspcd1_XACMLAuthzDecisionQuery->ID->g;
221 : 0 : refs.canon = zx_easy_enc_elem_sig(cf, &body->xaspcd1_XACMLAuthzDecisionQuery->gg);
222 [ # # ]: 0 : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert az cd1")) {
223 : 0 : body->xaspcd1_XACMLAuthzDecisionQuery->Signature
224 : : = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
225 : 0 : zx_add_kid_after_sa_Issuer(&body->xaspcd1_XACMLAuthzDecisionQuery->gg, &body->xaspcd1_XACMLAuthzDecisionQuery->Signature->gg);
226 : : }
227 : 0 : zx_str_free(cf->ctx, refs.canon);
228 : : }
229 : : } else {
230 : 89 : ZX_ADD_KID(body, XACMLAuthzDecisionQuery, zxid_mk_az(cf, subj, rsrc, act, env));
231 [ + - ]: 89 : if (cf->sso_soap_sign) {
232 : 89 : ZERO(&refs, sizeof(refs));
233 : 89 : refs.id = &body->XACMLAuthzDecisionQuery->ID->g;
234 : 89 : refs.canon = zx_easy_enc_elem_sig(cf, &body->XACMLAuthzDecisionQuery->gg);
235 [ + - ]: 89 : if (zxid_lazy_load_sign_cert_and_pkey(cf, &sign_cert, &sign_pkey, "use sign cert az")) {
236 : 89 : body->XACMLAuthzDecisionQuery->Signature
237 : : = zxsig_sign(cf->ctx, 1, &refs, sign_cert, sign_pkey);
238 : 89 : zx_add_kid_after_sa_Issuer(&body->XACMLAuthzDecisionQuery->gg, &body->XACMLAuthzDecisionQuery->Signature->gg);
239 : : }
240 : 89 : zx_str_free(cf->ctx, refs.canon);
241 : : }
242 : : }
243 : :
244 : : /* Perform the network I/O for the call (connect to PDP) */
245 : :
246 : : #if 0
247 : : //ss = zx_ref_str(cf->ctx, "https://idpdemo.tas3.eu:8443/zxididp?o=S");
248 : : // http://192.168.136.42:1104/axis2/services/TestPolicy.PERMISAuthzServerHttpSoap12Endpoint/
249 : : // http://192.168.1.27:1104/axis2/services/TestPolicy?wsdl
250 : : // http://192.168.1.66:1104/axis2/services/TestPolicy.PERMISAuthzServerHttpEndpoint/
251 : : ss = zx_ref_str(cf->ctx, "http://192.168.1.27:1104/axis2/services/TestPolicy.PERMISAuthzServerHttpEndpoint/");
252 : : //ss = zx_ref_str(cf->ctx, "");
253 : : //ss = zx_ref_str(cf->ctx, "http://192.168.1.66:1104/axis2/services/TestPolicy.PERMISAuthzServerHttpEndpoint/");
254 : : //ss = zx_ref_str(cf->ctx, "http://192.168.1.27:1104/axis2/services/TestPolicy.PERMISAuthzServerHttpSoap12Endpoint/");
255 : : #else
256 : 89 : ss = zx_ref_str(cf->ctx, pdp_url);
257 : : #endif
258 : 89 : r = zxid_soap_call_hdr_body(cf, ss, hdr, body);
259 : : //r = zxid_idp_soap(cf, cgi, ses, idp_meta, ZXID_MNI_SVC, body);
260 [ + - + - : 89 : if (!r || !r->Envelope || !r->Envelope->Body || !r->Envelope->Body->Response) {
+ - - + ]
261 [ # # # # : 0 : ERR("Missing Response or other essential element %p %p %p %p", r, r?r->Envelope:0, r && r->Envelope?r->Envelope->Body:0, r && r->Envelope && r->Envelope->Body ? r->Envelope->Body->Response:0);
# # # # #
# # # ]
262 : 0 : return 0;
263 : : }
264 : :
265 : 89 : resp = r->Envelope->Body->Response;
266 : :
267 : : /* Parse response from the PDP. */
268 : :
269 [ - + ]: 89 : if (!zxid_saml_ok(cf, cgi, resp->Status, "AzResp")) {
270 : 0 : ERR("Response->Status no OK (%p)", resp->Status);
271 : 0 : return 0;
272 : : }
273 [ - + ]: 89 : if (!resp->Assertion) {
274 : 0 : ERR("No Assertion in the Response (%p)", resp);
275 : 0 : return 0;
276 : : }
277 : :
278 : 89 : return resp;
279 : : }
280 : :
281 : : /*(i) Call Policy Decision Point (PDP) to obtain an authorization decision
282 : : * about a contemplated action on a resource. The attributes from the session
283 : : * pool, as filtered by PEPMAP are fed to the PDP as inputs
284 : : * for the decision. The call is using XACML SAML profile over SOAP.
285 : : *
286 : : * cf:: the configuration will need to have ~PEPMAP~ and ~PDP_URL~ options
287 : : * set according to your situation.
288 : : * cgi:: if non-null, will receive error and status codes
289 : : * ses:: all attributes are obtained from the session. You may wish
290 : : * to add additional attributes that are not known by SSO.
291 : : * pdp_url:: URL of the PDP to contact
292 : : * pepmap:: The map used to extract the attributes from the pool to the XACML request
293 : : * returns:: 0 on error or deny (for any reason, e.g. indeterminate); in case of
294 : : * permit returns <xac:Response> as string, allowing the obligations to be extracted.
295 : : *
296 : : * For simpler API, see zxid_az() family of functions.
297 : : */
298 : :
299 : : /* Called by: zxid_call_epr, zxid_pep_az_soap, zxid_simple_ab_pep, zxid_simple_ses_active_cf, zxid_wsc_prepare_call, zxid_wsc_valid_re_env, zxid_wsp_decorate, zxid_wsp_validate_env */
300 : : char* zxid_pep_az_soap_pepmap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, const char* pdp_url, struct zxid_map* pepmap)
301 : 89 : {
302 : 89 : struct zx_xac_Attribute_s* subj = 0;
303 : 89 : struct zx_xac_Attribute_s* rsrc = 0;
304 : 89 : struct zx_xac_Attribute_s* act = 0;
305 : 89 : struct zx_xac_Attribute_s* env = 0;
306 : : struct zx_str* ss;
307 : : struct zx_sp_Response_s* resp;
308 : : struct zx_sa_Statement_s* stmt;
309 : : struct zx_xasa_XACMLAuthzDecisionStatement_s* az_stmt;
310 : : struct zx_xasacd1_XACMLAuthzDecisionStatement_s* az_stmt_cd1;
311 : : struct zx_elem_s* decision;
312 : : char* p;
313 : :
314 [ + - ]: 89 : if (cf->log_level>0)
315 [ + - + - : 89 : zxlog(cf, 0, 0, 0, 0, 0, 0, ses?ZX_GET_CONTENT(ses->nameid):0, "N", "W", "AZSOAP", ses?ses->sid:0, " ");
+ + + - +
- ]
316 : :
317 [ + - - + ]: 89 : if (!pdp_url || !*pdp_url) {
318 : 0 : ERR("No PDP_URL or PDP_CALL_URL set. Deny. %p", pdp_url);
319 : 0 : return 0;
320 : : }
321 : :
322 : 89 : zxid_pepmap_extract(cf, cgi, ses, pepmap, &subj, &rsrc, &act, &env);
323 : 89 : resp = zxid_az_soap(cf, cgi, ses, pdp_url, subj, rsrc, act, env);
324 [ + - - + ]: 89 : if (!resp || !resp->Assertion) {
325 : 0 : ERR("DENY due to malformed authorization response from PDP. Either no response or response lacking assertion. %p", resp);
326 : 0 : return 0;
327 : : }
328 : :
329 : 89 : az_stmt = resp->Assertion->XACMLAuthzDecisionStatement;
330 [ + - + - : 89 : if (az_stmt && az_stmt->Response && az_stmt->Response->Result) {
+ - ]
331 : 89 : decision = az_stmt->Response->Result->Decision;
332 [ + - + - : 89 : if (ZX_CONTENT_EQ_CONST(decision, "Permit")) {
+ - + - +
- ]
333 : 89 : ss = zx_easy_enc_elem_opt(cf, &az_stmt->Response->gg);
334 [ + - - + ]: 89 : if (!ss || !ss->len)
335 : 0 : return 0;
336 : 89 : p = ss->s;
337 : : DD("Permit azstmt(%s)", p);
338 : 89 : INFO("PERMIT found in azstmt len=%d", ss->len);
339 : 89 : ZX_FREE(cf->ctx, ss);
340 : 89 : return p;
341 : : }
342 : : }
343 : 0 : az_stmt_cd1 = resp->Assertion->xasacd1_XACMLAuthzDecisionStatement;
344 [ # # # # : 0 : if (az_stmt_cd1 && az_stmt_cd1->Response && az_stmt_cd1->Response->Result) {
# # ]
345 : 0 : decision = az_stmt_cd1->Response->Result->Decision;
346 [ # # # # : 0 : if (ZX_CONTENT_EQ_CONST(decision, "Permit")) {
# # # # #
# ]
347 : 0 : ss = zx_easy_enc_elem_opt(cf, &az_stmt_cd1->Response->gg);
348 [ # # # # ]: 0 : if (!ss || !ss->len)
349 : 0 : return 0;
350 : 0 : p = ss->s;
351 : 0 : ZX_FREE(cf->ctx, ss);
352 : : DD("Permit cd1(%s)", p);
353 : 0 : INFO("PERMIT found in azstmt_cd1 len=%d", ss->len);
354 : 0 : ZX_FREE(cf->ctx, ss);
355 : 0 : return p;
356 : : }
357 : : }
358 : 0 : stmt = resp->Assertion->Statement;
359 [ # # # # : 0 : if (stmt && stmt->Response && stmt->Response->Result) { /* Response here is xac:Response */
# # ]
360 : 0 : decision = stmt->Response->Result->Decision;
361 [ # # # # : 0 : if (ZX_CONTENT_EQ_CONST(decision, "Permit")) {
# # # # #
# ]
362 : 0 : ss = zx_easy_enc_elem_opt(cf, &stmt->Response->gg);
363 [ # # # # ]: 0 : if (!ss || !ss->len)
364 : 0 : return 0;
365 : 0 : p = ss->s;
366 [ # # # # ]: 0 : D("Permit stmt(%s)", p);
367 : 0 : INFO("PERMIT found in stmt len=%d", ss->len);
368 : 0 : ZX_FREE(cf->ctx, ss);
369 : 0 : return p;
370 : : }
371 : : }
372 : : /*if (resp->Assertion->AuthzDecisionStatement) { }*/
373 [ # # # # ]: 0 : D("Deny or error or no xac:Response in reply %d",0);
374 : 0 : INFO("DENY or error or no xac:Response from PDP %p %p %p", az_stmt, az_stmt_cd1, stmt);
375 : 0 : return 0;
376 : : }
377 : :
378 : : /*(i) Call Policy Decision Point (PDP) to obtain an authorization decision
379 : : * about a contemplated action on a resource. The attributes from the session
380 : : * pool, as filtered by PEPMAP are fed to the PDP as inputs
381 : : * for the decision. The call is using XACML SAML profile over SOAP.
382 : : *
383 : : * This is similar to zxid_pep_az_soap_pepmap() with the difference that the <xac:Response>
384 : : * element is returned even in the deny and indeterminate cases (null
385 : : * is still returned if there was an error). Effectively this +base+
386 : : * form does not make judgement about whether <xac:Response> means
387 : : * permit, deny, or something else.
388 : : *
389 : : * You should use this function if the Deny message contains interesting
390 : : * obligations (normally it does not).
391 : : *
392 : : * cf:: the configuration will need to have ~PEPMAP~ and ~PDP_URL~ options
393 : : * set according to your situation.
394 : : * cgi:: if non-null, will receive error and status codes
395 : : * ses:: all attributes are obtained from the session. You may wish
396 : : * to add additional attributes that are not known by SSO.
397 : : * pdp_url:: URL of the PDP to contact
398 : : * pepmap:: The map used to extract the attributes from the pool to the XACML request
399 : : * returns:: 0 on error; in case of deny (or indeterminate, etc.) as well as
400 : : * permit returns <xac:Response> as string, allowing the obligations to be extracted.
401 : : *
402 : : * For simpler API, see zxid_az_base() family of functions.
403 : : */
404 : :
405 : : /* Called by: zxid_pep_az_base_soap */
406 : : char* zxid_pep_az_base_soap_pepmap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, const char* pdp_url, struct zxid_map* pepmap)
407 : 0 : {
408 : 0 : struct zx_xac_Attribute_s* subj = 0;
409 : 0 : struct zx_xac_Attribute_s* rsrc = 0;
410 : 0 : struct zx_xac_Attribute_s* act = 0;
411 : 0 : struct zx_xac_Attribute_s* env = 0;
412 : : char* res;
413 : : struct zx_str* ss;
414 : : struct zx_sp_Response_s* resp;
415 : : struct zx_sa_Statement_s* stmt;
416 : : struct zx_xasa_XACMLAuthzDecisionStatement_s* az_stmt;
417 : : struct zx_xasacd1_XACMLAuthzDecisionStatement_s* az_stmt_cd1;
418 : :
419 [ # # ]: 0 : if (cf->log_level>0)
420 [ # # # # : 0 : zxlog(cf, 0, 0, 0, 0, 0, 0, ses?ZX_GET_CONTENT(ses->nameid):0, "N", "W", "AZSOAP", ses?ses->sid:0, " ");
# # # # #
# ]
421 : :
422 [ # # # # ]: 0 : if (!pdp_url || !*pdp_url) {
423 : 0 : ERR("No PDP_URL or PDP_CALL_URL set. Deny. %p", pdp_url);
424 : 0 : return 0;
425 : : }
426 : :
427 : 0 : zxid_pepmap_extract(cf, cgi, ses, pepmap, &subj, &rsrc, &act, &env);
428 : 0 : resp = zxid_az_soap(cf, cgi, ses, pdp_url, subj, rsrc, act, env);
429 [ # # ]: 0 : if (!resp)
430 : 0 : return 0;
431 : :
432 : 0 : az_stmt = resp->Assertion->XACMLAuthzDecisionStatement;
433 [ # # # # ]: 0 : if (az_stmt && az_stmt->Response) {
434 : 0 : ss = zx_easy_enc_elem_opt(cf, &az_stmt->Response->gg);
435 [ # # # # ]: 0 : if (!ss || !ss->len)
436 : 0 : return 0;
437 : 0 : res = ss->s;
438 : 0 : ZX_FREE(cf->ctx, ss);
439 [ # # # # ]: 0 : D("azstmt(%s)", res);
440 : 0 : return res;
441 : : }
442 : 0 : az_stmt_cd1 = resp->Assertion->xasacd1_XACMLAuthzDecisionStatement;
443 [ # # # # ]: 0 : if (az_stmt_cd1 && az_stmt_cd1->Response) {
444 : 0 : ss = zx_easy_enc_elem_opt(cf, &az_stmt_cd1->Response->gg);
445 [ # # # # ]: 0 : if (!ss || !ss->len)
446 : 0 : return 0;
447 : 0 : res = ss->s;
448 : 0 : ZX_FREE(cf->ctx, ss);
449 [ # # # # ]: 0 : D("cd1(%s)", res);
450 : 0 : return res;
451 : : }
452 : 0 : stmt = resp->Assertion->Statement;
453 [ # # # # ]: 0 : if (stmt && stmt->Response) { /* Response here is xac:Response */
454 : 0 : ss = zx_easy_enc_elem_opt(cf, &stmt->Response->gg);
455 [ # # # # ]: 0 : if (!ss || !ss->len)
456 : 0 : return 0;
457 : 0 : res = ss->s;
458 : 0 : ZX_FREE(cf->ctx, ss);
459 [ # # # # ]: 0 : D("stmt(%s)", res);
460 : 0 : return res;
461 : : }
462 : :
463 [ # # # # ]: 0 : D("Missing az related Response element %d",0);
464 : 0 : return 0;
465 : : }
466 : :
467 : : /*() Call Policy Decision Point (PDP) to obtain an authorization decision.
468 : : * Uses default PEPMAP to call zxid_pep_az_soap_pepmap(). */
469 : :
470 : : /* Called by: zxid_az_cf_ses */
471 : 12 : char* zxid_pep_az_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, const char* pdp_url) {
472 : 12 : return zxid_pep_az_soap_pepmap(cf, cgi, ses, pdp_url, cf->pepmap);
473 : : }
474 : :
475 : : /* Called by: zxid_az_base_cf_ses */
476 : 0 : char* zxid_pep_az_base_soap(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses, const char* pdp_url) {
477 : 0 : return zxid_pep_az_base_soap_pepmap(cf, cgi, ses, pdp_url, cf->pepmap);
478 : : }
479 : :
480 : : /*int zxid_az_cf_cgi_ses(zxid_conf* cf, zxid_cgi* cgi, zxid_ses* ses);*/
481 : :
482 : : /*(i) Call Policy Decision Point (PDP) to obtain an authorization decision
483 : : * about a contemplated action on a resource. The attributes from the session
484 : : * pool, as filtered by ~PEPMAP~ are fed to the PDP as inputs
485 : : * for the decision. Session object is passed in as an argument.
486 : : *
487 : : * cf:: the configuration will need to have ~PEPMAP~ and ~PDP_URL~ options
488 : : * set according to your situation.
489 : : * qs:: if non-null, will resceive error and status codes
490 : : * ses:: all attributes are obtained from the session. You may wish
491 : : * to add additional attributes that are not known by SSO.
492 : : * The session object, e.g. from zxid_get_ses()
493 : : * returns:: 0 on deny (for any reason, e.g. indeterminate), or string
494 : : * containing the obligations on permit.
495 : : *
496 : : * For simpler API, see zxid_az() family of functions.
497 : : */
498 : :
499 : : /* Called by: zxcall_main, zxid_az_cf */
500 : : char* zxid_az_cf_ses(zxid_conf* cf, const char* qs, zxid_ses* ses)
501 : 12 : {
502 : : zxid_cgi cgi;
503 : : char* ret;
504 [ - + # # ]: 12 : char* url = (cf->pdp_call_url&&*cf->pdp_call_url) ? cf->pdp_call_url : cf->pdp_url;
505 : 12 : D_INDENT("az: ");
506 : 12 : ZERO(&cgi, sizeof(cgi));
507 : : /*zxid_parse_cgi(&cgi, ""); DD("qs(%s) ses=%p", STRNULLCHKD(qs), ses);*/
508 [ + - + - ]: 12 : if (qs && ses)
509 : 12 : zxid_add_qs_to_ses(cf, ses, zx_dup_cstr(cf->ctx, qs), 1);
510 : 12 : ret = zxid_pep_az_soap(cf, &cgi, ses, url);
511 : 12 : D_DEDENT("az: ");
512 : 12 : return ret;
513 : : }
514 : :
515 : : /* Called by: zxid_az_base_cf */
516 : : char* zxid_az_base_cf_ses(zxid_conf* cf, const char* qs, zxid_ses* ses)
517 : 0 : {
518 : : zxid_cgi cgi;
519 : : char* ret;
520 [ # # # # ]: 0 : char* url = (cf->pdp_call_url&&*cf->pdp_call_url) ? cf->pdp_call_url : cf->pdp_url;
521 : 0 : D_INDENT("azb: ");
522 : 0 : ZERO(&cgi, sizeof(cgi));
523 : : /*zxid_parse_cgi(&cgi, ""); DD("qs(%s) ses=%p", STRNULLCHKD(qs), ses);*/
524 [ # # # # ]: 0 : if (qs && ses)
525 : 0 : zxid_add_qs_to_ses(cf, ses, zx_dup_cstr(cf->ctx, qs), 1);
526 : 0 : ret = zxid_pep_az_base_soap(cf, &cgi, ses, url);
527 : 0 : D_DEDENT("azb: ");
528 : 0 : return ret;
529 : : }
530 : :
531 : : /*(i) Call Policy Decision Point (PDP) to obtain an authorization decision
532 : : * about a contemplated action on a resource. The attributes from the session
533 : : * pool, as filtered by ~PEPMAP~ are fed to the PDP as inputs
534 : : * for the decision. Session is identified by a session id.
535 : : *
536 : : * cf:: the configuration will need to have ~PEPMAP~ and ~PDP_URL~ options
537 : : * set according to your situation.
538 : : * qs:: if non-null, will resceive error and status codes
539 : : * sid:: all attributes are obtained from the session. You may wish
540 : : * to add additional attributes that are not known by SSO. The
541 : : * session id, such as returned from SSO.
542 : : * returns:: 0 on deny (for any reason, e.g. indeterminate), or string
543 : : * containing the obligations on permit.
544 : : *
545 : : * For simpler API, see zxid_az() family of functions.
546 : : */
547 : :
548 : : /* Called by: zxid_az */
549 : : char* zxid_az_cf(zxid_conf* cf, const char* qs, const char* sid)
550 : 9 : {
551 : : zxid_ses ses;
552 : 9 : ZERO(&ses, sizeof(ses));
553 [ + - + - ]: 9 : if (sid && sid[0])
554 : 9 : zxid_get_ses(cf, &ses, sid);
555 : 9 : return zxid_az_cf_ses(cf, qs, &ses);
556 : : }
557 : :
558 : : /* Called by: zxid_az_base */
559 : : char* zxid_az_base_cf(zxid_conf* cf, const char* qs, const char* sid)
560 : 0 : {
561 : : zxid_ses ses;
562 : 0 : ZERO(&ses, sizeof(ses));
563 [ # # # # ]: 0 : if (sid && sid[0])
564 : 0 : zxid_get_ses(cf, &ses, sid);
565 : 0 : return zxid_az_base_cf_ses(cf, qs, &ses);
566 : : }
567 : :
568 : : /*() See zxid_az_cf() for description. Only difference is that the configuration
569 : : * is accepted as a string instead of an object. */
570 : :
571 : : /* Called by: */
572 : : char* zxid_az(const char* conf, const char* qs, const char* sid)
573 : 0 : {
574 : : struct zx_ctx ctx;
575 : : zxid_conf cf;
576 : 0 : zx_reset_ctx(&ctx);
577 : 0 : ZERO(&cf, sizeof(cf));
578 : 0 : cf.ctx = &ctx;
579 : 0 : zxid_conf_to_cf_len(&cf, -1, conf);
580 : 0 : return zxid_az_cf(&cf, qs, sid);
581 : : }
582 : :
583 : : /* Called by: */
584 : : char* zxid_az_base(const char* conf, const char* qs, const char* sid)
585 : 0 : {
586 : : struct zx_ctx ctx;
587 : : zxid_conf cf;
588 : 0 : zx_reset_ctx(&ctx);
589 : 0 : ZERO(&cf, sizeof(cf));
590 : 0 : cf.ctx = &ctx;
591 : 0 : zxid_conf_to_cf_len(&cf, -1, conf);
592 : 0 : return zxid_az_base_cf(&cf, qs, sid);
593 : : }
594 : :
595 : : /* EOF -- zxidpep.c */
|