Branch data Line data Source code
1 : : /* zxidpool.c - Attribute 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: zxidpool.c,v 1.7 2009-11-24 23:53:40 sampo Exp $
10 : : *
11 : : * 4.9.2009, forked from zxidsimp.c --Sampo
12 : : * 1.2.2010, added ses_to methods --Sampo
13 : : * 21.5.2010, added local attribute authority and local EPRs feature --Sampo
14 : : */
15 : :
16 : : #include "platform.h"
17 : :
18 : : #include <memory.h>
19 : : #include <string.h>
20 : : #include <errno.h>
21 : :
22 : : #include "errmac.h"
23 : : #include "zx.h"
24 : : #include "zxid.h"
25 : : #include "zxidpriv.h"
26 : : #include "zxidutil.h"
27 : : #include "zxidconf.h"
28 : : #include "c/zx-sa-data.h"
29 : :
30 : : /*(i) Convert attributes from (session) pool to LDIF entry, applying OUTMAP.
31 : : * This is used by zxid_simple() SSO successful code to generate return
32 : : * value, but can also be used later to regenerate the LDIF
33 : : * given the pool. See zxid_ses_to_pool() for how to create the pool.
34 : : *
35 : : * N.B. More complete documentation is available in <<link: zxid-simple.pd>> (*** fixme) */
36 : :
37 : : /* Called by: */
38 : : static struct zx_str* zxid_pool_to_ldif(zxid_conf* cf, struct zxid_attr* pool)
39 : 11 : {
40 : : char* p;
41 : : char* name;
42 : 11 : char* idpnid = 0;
43 : 11 : char* affid = 0;
44 : 11 : int len = 0, name_len;
45 : : struct zxid_map* map;
46 : : struct zxid_attr* at;
47 : : struct zxid_attr* av;
48 : : struct zx_str* ss;
49 : :
50 : : /* Length computation pass */
51 : :
52 [ + + ]: 508 : for (at = pool; at; at = at->n) {
53 : 497 : map = zxid_find_map(cf->outmap, at->name);
54 [ + + ]: 497 : if (map) {
55 [ + + ]: 153 : if (map->rule == ZXID_MAP_RULE_DEL) {
56 [ + - - + ]: 3 : D("attribute(%s) filtered out by del rule in OUTMAP", at->name);
57 : 3 : continue;
58 : : }
59 : 150 : at->map_val = zxid_map_val(cf, 0, 0, map, at->name, at->val);
60 [ + - + + : 153 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
+ - + - ]
61 : 3 : name_len = strlen(map->dst);
62 : : } else {
63 : 147 : name_len = strlen(at->name);
64 : : }
65 : 150 : len += name_len + sizeof(": \n")-1 + at->map_val->len;
66 : : DD("len1=%d", len);
67 : :
68 [ - + ]: 150 : for (av = at->nv; av; av = av->n) {
69 : 0 : av->map_val = zxid_map_val(cf, 0, 0, map, at->name, av->val);
70 : 0 : len += name_len + sizeof(": \n")-1 + av->map_val->len;
71 : : DD("len2=%d", len);
72 : : }
73 : : } else {
74 : 344 : name_len = strlen(at->name);
75 [ + + ]: 344 : len += name_len + sizeof(": \n")-1 + (at->val?strlen(at->val):0);
76 : : DD("len3=%d name_len=%d name(%s)", len, name_len, at->name);
77 [ - + ]: 344 : for (av = at->nv; av; av = av->n) {
78 [ # # ]: 0 : len += name_len + sizeof(": \n")-1 + (av->val?strlen(av->val):0);
79 : : DD("len4=%d", len);
80 : : }
81 : : }
82 : :
83 [ + + ]: 494 : if (!strcmp(at->name, "idpnid")) idpnid = at->val;
84 [ + + ]: 483 : else if (!strcmp(at->name, "affid")) affid = at->val;
85 : : }
86 [ + - + - ]: 11 : len += sizeof("dn: idpnid=,affid=\n")-1 + (idpnid?strlen(idpnid):0) + (affid?strlen(affid):0);
87 : : DD("lenFin=%d", p-ss->s);
88 : :
89 : : /* Attribute rendering pass */
90 : :
91 : 11 : ss = zx_new_len_str(cf->ctx, len);
92 : 11 : p = ss->s;
93 : :
94 : 11 : memcpy(p, "dn: idpnid=", sizeof("dn: idpnid=")-1);
95 : 11 : p += sizeof("dn: idpnid=")-1;
96 [ + - ]: 11 : if (idpnid) {
97 : 11 : strcpy(p, idpnid);
98 : 11 : p += strlen(idpnid);
99 : : }
100 : 11 : memcpy(p, ",affid=", sizeof(",affid=")-1);
101 : 11 : p += sizeof(",affid=")-1;
102 [ + - ]: 11 : if (affid) {
103 : 11 : strcpy(p, affid);
104 : 11 : p += strlen(affid);
105 : : }
106 : 11 : *p++ = '\n';
107 : :
108 : : DD("len 0=%d", p-ss->s);
109 : :
110 [ + + ]: 508 : for (at = pool; at; at = at->n) {
111 : 497 : map = zxid_find_map(cf->outmap, at->name);
112 [ + + ]: 497 : if (map) {
113 [ + + ]: 153 : if (map->rule == ZXID_MAP_RULE_DEL)
114 : 3 : continue;
115 [ + - + + : 153 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
+ - + - ]
116 : 3 : name = map->dst;
117 : : } else {
118 : 147 : name = at->name;
119 : : }
120 : :
121 : 150 : name_len = strlen(name);
122 : 150 : strcpy(p, name);
123 : 150 : p += name_len;
124 : 150 : *p++ = ':';
125 : 150 : *p++ = ' ';
126 : 150 : memcpy(p, at->map_val->s, at->map_val->len);
127 : 150 : p += at->map_val->len;
128 : 150 : *p++ = '\n';
129 : :
130 : : DD("len 1=%d", p-ss->s);
131 : :
132 [ - + ]: 150 : for (av = at->nv; av; av = av->n) {
133 : 0 : strcpy(p, name);
134 : 0 : p += name_len;
135 : 0 : *p++ = ':';
136 : 0 : *p++ = ' ';
137 : 0 : memcpy(p, av->map_val->s, av->map_val->len);
138 : 0 : p += av->map_val->len;
139 : 0 : *p++ = '\n';
140 : :
141 : : DD("len 2=%d", p-ss->s);
142 : : }
143 : :
144 : :
145 : : } else {
146 : 344 : name_len = strlen(at->name);
147 : 344 : strcpy(p, at->name);
148 : 344 : p += name_len;
149 : 344 : *p++ = ':';
150 : 344 : *p++ = ' ';
151 [ + + ]: 344 : if (at->val) {
152 : 314 : strcpy(p, at->val);
153 : 314 : p += strlen(at->val);
154 : : }
155 : 344 : *p++ = '\n';
156 : :
157 : : DD("len 3=%d name_len=%d name(%s)", p-ss->s, name_len, at->name);
158 : :
159 [ - + ]: 344 : for (av = at->nv; av; av = av->n) {
160 : 0 : strcpy(p, at->name);
161 : 0 : p += name_len;
162 : 0 : *p++ = ':';
163 : 0 : *p++ = ' ';
164 [ # # ]: 0 : if (at->val) {
165 : 0 : strcpy(p, av->val);
166 : 0 : p += strlen(av->val);
167 : : }
168 : 0 : *p++ = '\n';
169 : :
170 [ # # # # ]: 0 : D("len 4=%d", p-ss->s);
171 : : }
172 : :
173 : : }
174 : : }
175 : : DD("len Fin=%d", p-ss->s);
176 : :
177 [ - + # # ]: 11 : ASSERTOP(p, ==, ss->s+len);
178 : 11 : return ss;
179 : : }
180 : :
181 : : /*() Convert attributes from (session) pool to JSON, applying OUTMAP.
182 : : * *** Need to check escaping JSON values, e.g. " or \n */
183 : :
184 : : /* Called by: zxid_ses_to_json */
185 : : static struct zx_str* zxid_pool_to_json(zxid_conf* cf, struct zxid_attr* pool)
186 : 0 : {
187 : : char* p;
188 : : char* name;
189 : 0 : int len = sizeof("{")-1, name_len;
190 : : struct zxid_map* map;
191 : : struct zxid_attr* at;
192 : : struct zxid_attr* av;
193 : : struct zx_str* ss;
194 : :
195 : : /* Length computation pass */
196 : :
197 [ # # ]: 0 : for (at = pool; at; at = at->n) {
198 : 0 : map = zxid_find_map(cf->outmap, at->name);
199 [ # # ]: 0 : if (map) {
200 [ # # ]: 0 : if (map->rule == ZXID_MAP_RULE_DEL) {
201 [ # # # # ]: 0 : D("attribute(%s) filtered out by del rule in OUTMAP", at->name);
202 : 0 : continue;
203 : : }
204 : 0 : at->map_val = zxid_map_val(cf, 0, 0, map, at->name, at->val);
205 [ # # # # : 0 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
# # # # ]
206 : 0 : name_len = strlen(map->dst);
207 : : } else {
208 : 0 : name_len = strlen(at->name);
209 : : }
210 : :
211 [ # # ]: 0 : if (at->nv) { /* Multivalue requires array */
212 : 0 : len += name_len + sizeof("\"\":[\"\"],")-1 + at->map_val->len;
213 [ # # ]: 0 : for (av = at->nv; av; av = av->n) {
214 : 0 : av->map_val = zxid_map_val(cf, 0, 0, map, at->name, av->val);
215 : 0 : len += name_len + sizeof(",\"\"")-1 + av->map_val->len;
216 : : }
217 : : } else {
218 : 0 : len += name_len + sizeof("\"\":\"\",")-1 + at->map_val->len;
219 : : }
220 : : } else {
221 : 0 : name_len = strlen(at->name);
222 [ # # ]: 0 : if (at->nv) { /* Multivalue requires array */
223 [ # # ]: 0 : len += name_len + sizeof("\"\":[\"\"],")-1 + (at->val?strlen(at->val):0);
224 [ # # ]: 0 : for (av = at->nv; av; av = av->n)
225 [ # # ]: 0 : len += name_len + sizeof(",\"\"")-1 + (av->val?strlen(av->val):0);
226 : : } else {
227 [ # # ]: 0 : len += name_len + sizeof("\"\":\"\",")-1 + (at->val?strlen(at->val):0);
228 : : }
229 : : }
230 : : }
231 : :
232 : : /* Attribute rendering pass */
233 : :
234 : 0 : ss = zx_new_len_str(cf->ctx, len);
235 : 0 : p = ss->s;
236 : 0 : *p++ = '{';
237 : :
238 [ # # ]: 0 : for (at = pool; at; at = at->n) {
239 : 0 : map = zxid_find_map(cf->outmap, at->name);
240 [ # # ]: 0 : if (map) {
241 [ # # ]: 0 : if (map->rule == ZXID_MAP_RULE_DEL)
242 : 0 : continue;
243 [ # # # # : 0 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
# # # # ]
244 : 0 : name = map->dst;
245 : : } else {
246 : 0 : name = at->name;
247 : : }
248 : :
249 : 0 : *p++ = '"';
250 : 0 : strcpy(p, name);
251 : 0 : p += strlen(name);
252 : 0 : *p++ = '"';
253 : 0 : *p++ = ':';
254 [ # # ]: 0 : if (at->nv) {
255 : 0 : *p++ = '[';
256 : 0 : *p++ = '"';
257 : 0 : memcpy(p, at->map_val->s, at->map_val->len);
258 : 0 : p += at->map_val->len;
259 : 0 : *p++ = '"';
260 [ # # ]: 0 : for (av = at->nv; av; av = av->n) {
261 : 0 : *p++ = ',';
262 : 0 : *p++ = '"';
263 : 0 : memcpy(p, av->map_val->s, av->map_val->len);
264 : 0 : p += av->map_val->len;
265 : 0 : *p++ = '"';
266 : : }
267 : 0 : *p++ = ']';
268 : : } else {
269 : 0 : *p++ = '"';
270 : 0 : memcpy(p, at->map_val->s, at->map_val->len);
271 : 0 : p += at->map_val->len;
272 : 0 : *p++ = '"';
273 : : }
274 : :
275 : : } else {
276 : 0 : *p++ = '"';
277 : 0 : strcpy(p, at->name);
278 : 0 : p += strlen(at->name);
279 : 0 : *p++ = '"';
280 : 0 : *p++ = ':';
281 [ # # ]: 0 : if (at->nv) {
282 : 0 : *p++ = '[';
283 : 0 : *p++ = '"';
284 [ # # ]: 0 : if (at->val) {
285 : 0 : strcpy(p, at->val);
286 : 0 : p += strlen(at->val);
287 : : }
288 : 0 : *p++ = '"';
289 [ # # ]: 0 : for (av = at->nv; av; av = av->n) {
290 : 0 : *p++ = ',';
291 : 0 : *p++ = '"';
292 [ # # ]: 0 : if (at->val) {
293 : 0 : strcpy(p, av->val);
294 : 0 : p += strlen(av->val);
295 : : }
296 : 0 : *p++ = '"';
297 : : }
298 : 0 : *p++ = ']';
299 : : } else {
300 : 0 : *p++ = '"';
301 [ # # ]: 0 : if (at->val) {
302 : 0 : strcpy(p, at->val);
303 : 0 : p += strlen(at->val);
304 : : }
305 : 0 : *p++ = '"';
306 : : }
307 : : }
308 : 0 : *p++ = ',';
309 : : }
310 : 0 : *p = '}'; /* Overwrites last comma */
311 [ # # # # ]: 0 : ASSERTOP(p, ==, ss->s+len);
312 : 0 : return ss;
313 : : }
314 : :
315 : : /*() Convert attributes from (session) pool to query string, applying OUTMAP.
316 : : * *** Need to check multivalue handling. Now all values are simply blurted
317 : : * out as separate name=value pairs.
318 : : * *** Need to figure out how to distinguish query string return from
319 : : * other returns, like redirect. Perhaps arrange dn field always first? */
320 : :
321 : : /* Called by: zxid_ses_to_qs */
322 : : static struct zx_str* zxid_pool_to_qs(zxid_conf* cf, struct zxid_attr* pool)
323 : 3 : {
324 : : char* p;
325 : : char* name;
326 : 3 : int len = sizeof("dn=QS1&")-1, name_len;
327 : : struct zxid_map* map;
328 : : struct zxid_attr* at;
329 : : struct zxid_attr* av;
330 : : struct zx_str* ss;
331 : :
332 : : /* Length computation pass */
333 : :
334 [ + + ]: 156 : for (at = pool; at; at = at->n) {
335 : 153 : map = zxid_find_map(cf->outmap, at->name);
336 [ - + ]: 153 : if (map) {
337 [ # # ]: 0 : if (map->rule == ZXID_MAP_RULE_DEL) {
338 [ # # # # ]: 0 : D("attribute(%s) filtered out by del rule in OUTMAP", at->name);
339 : 0 : continue;
340 : : }
341 : 0 : at->map_val = zxid_map_val(cf, 0, 0, map, at->name, at->val);
342 [ # # # # : 0 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
# # # # ]
343 : 0 : name_len = strlen(map->dst);
344 : : } else {
345 : 0 : name_len = strlen(at->name);
346 : : }
347 : 0 : len += name_len + sizeof("=&")-1 + zx_url_encode_len(at->map_val->len,at->map_val->s)-1;
348 [ # # ]: 0 : for (av = at->nv; av; av = av->n) {
349 : 0 : av->map_val = zxid_map_val(cf, 0, 0, map, at->name, av->val);
350 : 0 : len += name_len + sizeof("=&")-1 + zx_url_encode_len(av->map_val->len,av->map_val->s)-1;
351 : : }
352 [ # # # # ]: 0 : D("len=%d name_len=%d %s", len, name_len, at->name);
353 : : } else {
354 : 153 : name_len = strlen(at->name);
355 [ + + ]: 153 : len += name_len + sizeof("=&")-1 + (at->val?zx_url_encode_len(strlen(at->val),at->val)-1:0);
356 [ + - + + : 153 : D("len=%d name_len=%d %s (nomap) url_enc_len=%d", len, name_len, at->name, (at->val?zx_url_encode_len(strlen(at->val),at->val)-1:0));
- + ]
357 [ - + ]: 153 : for (av = at->nv; av; av = av->n)
358 [ # # ]: 0 : len += name_len + sizeof("=&")-1 + (av->val?zx_url_encode_len(strlen(av->val),av->val)-1:0);
359 : : }
360 : : }
361 : :
362 : : /* Attribute rendering pass */
363 : :
364 : : DD("HERE %d", 0);
365 : :
366 : 3 : ss = zx_new_len_str(cf->ctx, len);
367 : 3 : p = ss->s;
368 : 3 : memcpy(p, "dn=QS1&", sizeof("dn=QS1&")-1);
369 : 3 : p += sizeof("dn=QS1&")-1;
370 : :
371 [ + + ]: 156 : for (at = pool; at; at = at->n) {
372 : 153 : map = zxid_find_map(cf->outmap, at->name);
373 [ - + ]: 153 : if (map) {
374 [ # # ]: 0 : if (map->rule == ZXID_MAP_RULE_DEL)
375 : 0 : continue;
376 [ # # # # : 0 : if (map->dst && *map->dst && map->src && map->src[0] != '*') {
# # # # ]
377 : 0 : name = map->dst;
378 : : } else {
379 : 0 : name = at->name;
380 : : }
381 : :
382 : 0 : name_len = strlen(name);
383 : 0 : strcpy(p, name);
384 : 0 : p += name_len;
385 : 0 : *p++ = '=';
386 : 0 : p = zx_url_encode_raw(at->map_val->len, at->map_val->s, p);
387 : 0 : *p++ = '&';
388 : :
389 [ # # ]: 0 : for (av = at->nv; av; av = av->n) {
390 : 0 : strcpy(p, name);
391 : 0 : p += name_len;
392 : 0 : *p++ = '=';
393 : 0 : p = zx_url_encode_raw(av->map_val->len, av->map_val->s, p);
394 : 0 : *p++ = '&';
395 : : }
396 : : } else {
397 : 153 : name_len = strlen(at->name);
398 : 153 : strcpy(p, at->name);
399 : 153 : p += name_len;
400 : 153 : *p++ = '=';
401 [ + + ]: 153 : if (at->val)
402 : 135 : p = zx_url_encode_raw(strlen(at->val), at->val, p);
403 : 153 : *p++ = '&';
404 : :
405 [ - + ]: 153 : for (av = at->nv; av; av = av->n) {
406 : 0 : strcpy(p, at->name);
407 : 0 : p += name_len;
408 : 0 : *p++ = '=';
409 [ # # ]: 0 : if (at->val)
410 : 0 : p = zx_url_encode_raw(strlen(av->val), av->val, p);
411 : 0 : *p++ = '&';
412 : : }
413 : : }
414 : : }
415 [ + - - + ]: 3 : D("p=%p == %p ss=%p len=%d", p, ss->s+len, ss->s, len);
416 [ + - - + ]: 3 : D("p(%.*s)", len, ss->s);
417 [ - + # # ]: 3 : ASSERTOP(p, ==, ss->s+len);
418 : 3 : *p = 0; /* Zap last & */
419 : 3 : return ss;
420 : : }
421 : :
422 : : /*() Convert attributes from session to LDIF, applying OUTMAP. */
423 : :
424 : : /* Called by: */
425 : 11 : struct zx_str* zxid_ses_to_ldif(zxid_conf* cf, zxid_ses* ses) {
426 [ + - ]: 11 : return zxid_pool_to_ldif(cf, ses?ses->at:0);
427 : : }
428 : :
429 : : /*() Convert attributes from session to JSON, applying OUTMAP. */
430 : :
431 : : /* Called by: zxid_simple_ab_pep */
432 : 0 : struct zx_str* zxid_ses_to_json(zxid_conf* cf, zxid_ses* ses) {
433 [ # # ]: 0 : return zxid_pool_to_json(cf, ses?ses->at:0);
434 : : }
435 : :
436 : : /*() Convert attributes from session to query string, applying OUTMAP. */
437 : :
438 : : /* Called by: zxid_simple_ab_pep */
439 : 3 : struct zx_str* zxid_ses_to_qs(zxid_conf* cf, zxid_ses* ses) {
440 [ + - ]: 3 : return zxid_pool_to_qs(cf, ses?ses->at:0);
441 : : }
442 : :
443 : : /*() Add values, applying NEED, WANT, and INMAP */
444 : :
445 : : /* Called by: zxid_add_a7n_at_to_pool x2 */
446 : : static int zxid_add_at_values(zxid_conf* cf, zxid_ses* ses, struct zx_sa_Attribute_s* at, char* name, struct zx_str* issuer)
447 : 1386 : {
448 : : struct zx_str* ss;
449 : : struct zxid_map* map;
450 : : struct zx_sa_AttributeValue_s* av;
451 : :
452 : : /* Attribute must be needed or wanted */
453 : :
454 [ + - - + ]: 1386 : if (!zxid_is_needed(cf->need, name) && !zxid_is_needed(cf->want, name)) {
455 [ # # # # ]: 0 : D("attribute(%s) neither needed nor wanted", name);
456 : 0 : return 0;
457 : : }
458 : :
459 : 1386 : map = zxid_find_map(cf->inmap, name);
460 [ - + # # ]: 1386 : if (map && map->rule == ZXID_MAP_RULE_DEL) {
461 [ # # # # ]: 0 : D("attribute(%s) filtered out by del rule in INMAP", name);
462 : 0 : return 0;
463 : : }
464 : :
465 [ - + # # : 1386 : if (map && map->dst && *map->dst && map->src && map->src[0] != '*') {
# # # # #
# ]
466 : 0 : ses->at = zxid_new_at(cf, ses->at, strlen(map->dst), map->dst, 0, 0, "mapped");
467 : : } else {
468 : 1386 : ses->at = zxid_new_at(cf, ses->at, strlen(name), name, 0, 0, "as is");
469 : : }
470 : 1386 : ses->at->orig = at;
471 : 1386 : ses->at->issuer = issuer;
472 : :
473 : 1386 : for (av = at->AttributeValue;
474 [ + + + - ]: 4158 : av && av->gg.g.tok == zx_sa_AttributeValue_ELEM;
475 : 1386 : av = (struct zx_sa_AttributeValue_s*)ZX_NEXT(av)) {
476 [ + - + - : 1386 : D("Adding value: %p", ZX_GET_CONTENT(av));
+ + + + -
+ ]
477 [ + + + - ]: 1386 : if (av->EndpointReference || av->ResourceOffering)
478 : : continue; /* Skip bootstraps. They are handled elsewhere, see zxid_snarf_eprs_from_ses(). */
479 [ + - + + : 1302 : if (ZX_GET_CONTENT(av)) {
+ + ]
480 [ + - + - : 1062 : ss = zxid_map_val_ss(cf, ses, 0, map, ses->at->name, ZX_GET_CONTENT(av));
+ - ]
481 [ - + ]: 1062 : if (ses->at->val) {
482 [ # # # # ]: 0 : D("map val(%.*s)", ss->len, ss->s);
483 : 0 : ses->at->nv = zxid_new_at(cf, ses->at->nv, 0, 0, ss->len, ss->s, "multival");
484 : : } else {
485 [ + - - + ]: 1062 : D("copy val(%.*s)", ss->len, ss->s);
486 : 1062 : COPYVAL(ses->at->val, ss->s, ss->s+ss->len);
487 : : }
488 : : }
489 : : }
490 : : // *** check that value is not null, add empty string
491 : 1386 : return 1;
492 : : }
493 : :
494 : : /*() Add Attribute Statements of an Assertion to pool, applying NEED, WANT, and INMAP */
495 : :
496 : : /* Called by: zxid_ses_to_pool */
497 : : static void zxid_add_a7n_at_to_pool(zxid_conf* cf, zxid_ses* ses, zxid_a7n* a7n)
498 : 87 : {
499 : : struct zx_sa_Attribute_s* at;
500 : : struct zx_sa_AttributeStatement_s* as;
501 [ + + ]: 87 : if (!a7n)
502 : 26 : return;
503 : :
504 : 61 : for (as = a7n->AttributeStatement;
505 [ + + + - ]: 183 : as && as->gg.g.tok == zx_sa_AttributeStatement_ELEM;
506 : 61 : as = (struct zx_sa_AttributeStatement_s*)ZX_NEXT(as)) {
507 : 61 : for (at = as->Attribute;
508 [ + + + - ]: 1508 : at && at->gg.g.tok == zx_sa_Attribute_ELEM;
509 : 1386 : at = (struct zx_sa_Attribute_s*)ZX_NEXT(at)) {
510 [ + - ]: 1386 : if (at->Name)
511 [ + - + - : 1386 : zxid_add_at_values(cf, ses, at, zx_str_to_c(cf->ctx, &at->Name->g), ZX_GET_CONTENT(a7n->Issuer));
+ - ]
512 [ - + ]: 1386 : if (at->FriendlyName)
513 [ # # # # : 0 : zxid_add_at_values(cf, ses, at, zx_str_to_c(cf->ctx, &at->FriendlyName->g), ZX_GET_CONTENT(a7n->Issuer));
# # ]
514 : : }
515 : : }
516 : : }
517 : :
518 : : /*() Add simple attribute to pool, applying NEED, WANT, and INMAP */
519 : :
520 : : /* Called by: zxid_add_ldif_at2ses, zxid_add_qs_to_ses, zxid_ses_to_pool x25 */
521 : : void zxid_add_attr_to_ses(zxid_conf* cf, zxid_ses* ses, char* at_name, struct zx_str* val)
522 : 2257 : {
523 : : struct zxid_map* map;
524 [ + + ]: 2257 : if (!val)
525 : 222 : val = zx_dup_str(cf->ctx, "-");
526 : :
527 [ + + + - ]: 4514 : if (zxid_is_needed(cf->need, at_name) || zxid_is_needed(cf->want, at_name)) {
528 : 2257 : map = zxid_find_map(cf->inmap, at_name);
529 [ - + # # ]: 2257 : if (map && map->rule == ZXID_MAP_RULE_DEL) {
530 [ # # # # ]: 0 : D("attribute(%s) filtered out by del rule in INMAP", at_name);
531 : : } else {
532 [ - + # # : 2257 : if (map && map->dst && *map->dst && map->src && map->src[0] != '*') {
# # # # #
# ]
533 : 0 : ses->at = zxid_new_at(cf, ses->at, strlen(map->dst), map->dst, val->len, val->s, "mapd2");
534 : : } else {
535 : 2257 : ses->at = zxid_new_at(cf, ses->at, strlen(at_name), at_name, val->len, val->s, "as is2");
536 : : }
537 : : }
538 : : } else {
539 [ # # # # ]: 0 : D("attribute(%s) neither needed nor wanted", at_name);
540 : : }
541 : 2257 : }
542 : :
543 : : /*() Parse LDIF format and insert attributes to linked list. Return new head of the list.
544 : : * *** illegal input causes corrupt pointer. For example query string input causes corruption. */
545 : :
546 : : /* Called by: zxid_ses_to_pool x3 */
547 : : static void zxid_add_ldif_at2ses(zxid_conf* cf, zxid_ses* ses, const char* prefix, char* p, char* lk)
548 : 67 : {
549 : : char* name;
550 : : char* val;
551 : : char* nbuf;
552 : : char name_buf[ZXID_MAX_USER];
553 : : int len;
554 [ - + ]: 67 : if (prefix) {
555 : 0 : strncpy(name_buf, prefix, sizeof(name_buf)-1);
556 [ # # ]: 0 : nbuf = name_buf + MIN(strlen(prefix), sizeof(name_buf)-1);
557 : : } else
558 : 67 : nbuf = name_buf;
559 : :
560 [ + - ]: 268 : for (; p; ++p) {
561 : 268 : name = p;
562 : 268 : p = strstr(p, ": ");
563 [ + + ]: 268 : if (!p)
564 : 67 : break;
565 : 201 : len = MIN(p-name, sizeof(name_buf)-(nbuf-name_buf)-1);
566 : 201 : memcpy(nbuf, name, len);
567 : 201 : nbuf[len]=0;
568 : :
569 : 201 : val = p+2;
570 : 201 : p = strchr(val, '\n'); /* *** parsing LDIF is fragile if values are multiline */
571 [ + - ]: 201 : len = p?(p-val):strlen(val);
572 [ + + - + ]: 201 : D("%s: ATTR(%s)=VAL(%.*s)", lk, name_buf, len, val);
573 : 201 : zxid_add_attr_to_ses(cf, ses, name_buf, zx_dup_len_str(cf->ctx, len, val));
574 : : }
575 : 67 : }
576 : :
577 : : /*() Copy user's local EPRs to his current session.
578 : : * This function implements a feature where user can have at
579 : : * some site some long term EPRs (with long term credential). When SSO
580 : : * is made, these EPRs are copied to user's session's EPR
581 : : * cache and thus made available. The persistent user EPRs could
582 : : * be used to implement stuff like subscriptions.
583 : : *
584 : : * The ".all" user's EPRs provide a mechanism to add to all users of
585 : : * a given SP some EPR. Naturally such EPR can not have per user
586 : : * or short time credential. This can have security implications.
587 : : *
588 : : * cf:: Config object for cf->path, and for memory allocation
589 : : * ses:: Session object. ses->sid is used to determine desitmation directory.
590 : : * path:: Path to the user directory (in /var/zxid/user/<sha1_safe_base64(idpnid)>/)
591 : : */
592 : :
593 : : /* Called by: zxid_ses_to_pool x3 */
594 : : static void zxid_cp_usr_eprs2ses(zxid_conf* cf, zxid_ses* ses, struct zx_str* path)
595 : 209 : {
596 : : char bs_dir[ZXID_MAX_BUF];
597 : : char ses_path[ZXID_MAX_BUF];
598 : : DIR* dir;
599 : : struct dirent * de;
600 [ + - + - : 209 : if (!ses->sid || !*ses->sid || !path)
- + ]
601 : 0 : return; /* No valid session. Nothing to do. */
602 : :
603 : 209 : snprintf(bs_dir, sizeof(bs_dir), "%.*s/.bs", path->len, path->s);
604 : 209 : bs_dir[sizeof(bs_dir)-1] = 0; /* must terminate manually as on win32 nul is not guaranteed */
605 : 209 : dir = opendir(bs_dir);
606 [ + + ]: 209 : if (!dir) {
607 [ + - - + ]: 142 : D("Local bootstrap dir(%s) does not exist", bs_dir);
608 : 142 : return;
609 : : }
610 [ + + ]: 335 : while (de = readdir(dir)) {
611 [ - + # # ]: 201 : if (ONE_OF_2(de->d_name[0], '.', 0)) /* skip . and .. and .foo */
612 : : continue;
613 : :
614 : 0 : snprintf(bs_dir, sizeof(bs_dir), "%.*s/.bs/%s", path->len, path->s, de->d_name);
615 : 0 : bs_dir[sizeof(bs_dir)-1] = 0; /* must terminate manually as on win32 nul is not guaranteed */
616 : 0 : snprintf(ses_path, sizeof(ses_path), "%.*s" ZXID_SES_DIR "%s/%s", path->len, path->s, ses->sid, de->d_name);
617 : 0 : ses_path[sizeof(ses_path)-1] = 0; /* must term manually as on win32 nul is not guaranteed */
618 : 0 : copy_file(bs_dir, ses_path, "EPRS2ses", 1);
619 : : }
620 : 67 : closedir(dir);
621 : : }
622 : :
623 : : /*(i) Process attributes from the AttributeStatements of the session
624 : : * SSO Assertion and insert them to the pool. NEED, WANT, and INMAP
625 : : * are applied. The pool is suitable for use by PEP or eventually
626 : : * rendering to LDIF (or JSON). This function also implements
627 : : * local attribute authority. */
628 : :
629 : : /* Called by: zxid_as_call_ses, zxid_fetch_ses, zxid_simple_ab_pep, zxid_wsc_valid_re_env, zxid_wsp_validate_env */
630 : : void zxid_ses_to_pool(zxid_conf* cf, zxid_ses* ses)
631 : 87 : {
632 : : char* src;
633 : : char* dst;
634 : : char* lim;
635 : 87 : struct zx_str* issuer = 0;
636 : : struct zx_str* affid;
637 : : struct zx_str* nid;
638 : 87 : struct zx_str* tgtissuer = 0;
639 : : struct zx_str* tgtaffid;
640 : : struct zx_str* tgtnid;
641 : : struct zx_str* accr;
642 : : struct zx_str* path;
643 : : struct zx_sa_AuthnStatement_s* as;
644 : : struct zx_sa_Assertion_s* a7n;
645 : : struct zx_sa_Assertion_s* tgta7n;
646 : : char* buf;
647 : : char sha1_name[28];
648 : :
649 : 87 : D_INDENT("ses2pool: ");
650 : 87 : zxid_get_ses_sso_a7n(cf, ses);
651 : 87 : a7n = ses->a7n;
652 [ + + - + ]: 87 : D("adding a7n %p to pool", a7n);
653 : 87 : zxid_add_a7n_at_to_pool(cf, ses, a7n);
654 : :
655 : : /* Format some pseudo attributes that describe the SSO */
656 : :
657 [ + + ]: 87 : if (a7n) {
658 : 61 : zxid_add_attr_to_ses(cf, ses, "ssoa7n", zx_easy_enc_elem_opt(cf, &a7n->gg));
659 [ + - + - : 61 : issuer = ZX_GET_CONTENT(a7n->Issuer);
+ - ]
660 : : }
661 : 87 : zxid_add_attr_to_ses(cf, ses, "issuer", issuer);
662 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "ssoa7npath",zx_dup_str(cf->ctx, STRNULLCHK(ses->sso_a7n_path)));
663 : :
664 [ + + + - ]: 87 : affid = ses->nameid&&ses->nameid->NameQualifier?&ses->nameid->NameQualifier->g:0;
665 [ + + + - : 87 : nid = ZX_GET_CONTENT(ses->nameid);
+ - ]
666 : 87 : zxid_add_attr_to_ses(cf, ses, "affid", affid);
667 : 87 : zxid_add_attr_to_ses(cf, ses, "idpnid", nid);
668 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "nidfmt", zx_dup_str(cf->ctx, ses->nidfmt?"P":"T"));
669 [ + + ]: 87 : if (nid) {
670 : 61 : zxid_user_sha1_name(cf, affid, nid, sha1_name);
671 : 61 : path = zx_strf(cf->ctx, "%s" ZXID_USER_DIR "%s", cf->path, sha1_name);
672 : 61 : zxid_add_attr_to_ses(cf, ses, "localpath", path);
673 : 61 : buf = read_all_alloc(cf->ctx, "splocal_user_at", 0, 0, "%.*s/.bs/.at", path->len, path->s);
674 [ - + ]: 61 : if (buf) {
675 : 0 : zxid_add_ldif_at2ses(cf, ses, "local_", buf, "splocal_user_at");
676 : 0 : ZX_FREE(cf->ctx, buf);
677 : : }
678 : 61 : zxid_cp_usr_eprs2ses(cf, ses, path);
679 : : }
680 : :
681 : : /* Format pseudo attrs that describe the target, defaulting to the SSO identity. */
682 : :
683 [ + + ]: 87 : if (ses->tgta7n)
684 : 37 : tgta7n = ses->tgta7n;
685 : : else
686 : 50 : tgta7n = a7n;
687 [ + + ]: 87 : if (tgta7n) {
688 : 61 : zxid_add_attr_to_ses(cf, ses, "tgta7n", zx_easy_enc_elem_opt(cf, &a7n->gg));
689 [ + - + - : 61 : tgtissuer = ZX_GET_CONTENT(tgta7n->Issuer);
+ - ]
690 : : }
691 [ + + ]: 87 : if (tgtissuer)
692 : 61 : zxid_add_attr_to_ses(cf, ses, "tgtissuer", tgtissuer);
693 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "tgta7npath",zx_dup_str(cf->ctx, STRNULLCHK(ses->tgt_a7n_path)));
694 : :
695 [ + + + - ]: 87 : tgtaffid = ses->tgtnameid&&ses->tgtnameid->NameQualifier?&ses->tgtnameid->NameQualifier->g:0;
696 [ + + + - : 87 : tgtnid = ZX_GET_CONTENT(ses->tgtnameid);
+ - ]
697 [ + + ]: 87 : if (!tgtissuer) tgtissuer = issuer; /* Default: requestor is the target */
698 [ + + ]: 87 : if (!tgtaffid) tgtaffid = affid;
699 [ + + ]: 87 : if (!tgtnid) tgtnid = nid;
700 : 87 : zxid_add_attr_to_ses(cf, ses, "tgtaffid", tgtaffid);
701 : 87 : zxid_add_attr_to_ses(cf, ses, "tgtnid", tgtnid);
702 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "tgtfmt", zx_dup_str(cf->ctx, ses->tgtfmt?"P":"T"));
703 [ + + ]: 87 : if (tgtnid) {
704 : 61 : zxid_user_sha1_name(cf, tgtaffid, tgtnid, sha1_name);
705 : 61 : path = zx_strf(cf->ctx, "%s" ZXID_USER_DIR "%s", cf->path, sha1_name);
706 : 61 : zxid_add_attr_to_ses(cf, ses, "tgtpath", path);
707 : 61 : buf = read_all_alloc(cf->ctx, "sptgt_user_at", 0, 0, "%.*s/.bs/.at", path->len, path->s);
708 [ - + ]: 61 : if (buf) {
709 : 0 : zxid_add_ldif_at2ses(cf, ses, "tgt_", buf, "sptgt_user_at");
710 : 0 : ZX_FREE(cf->ctx, buf);
711 : : }
712 : 61 : zxid_cp_usr_eprs2ses(cf, ses, path);
713 : : }
714 : :
715 [ + + + - : 87 : accr = a7n&&(as = a7n->AuthnStatement)&&as->AuthnContext?ZX_GET_CONTENT(as->AuthnContext->AuthnContextClassRef):0;
+ - + + +
- + - ]
716 : : //accr = a7n&&a7n->AuthnStatement&&a7n->AuthnStatement->AuthnContext&&a7n->AuthnStatement->AuthnContext->AuthnContextClassRef&&a7n->AuthnStatement->AuthnContext->AuthnContextClassRef->content&&a7n->AuthnStatement->AuthnContext->AuthnContextClassRef->content?a7n->AuthnStatement->AuthnContext->AuthnContextClassRef->content:0;
717 : 87 : zxid_add_attr_to_ses(cf, ses, "authnctxlevel", accr);
718 : :
719 : 87 : buf = read_all_alloc(cf->ctx, "splocal.all", 0, 0, "%s" ZXID_USER_DIR ".all/.bs/.at" , cf->path);
720 [ + + ]: 87 : if (buf) {
721 : 67 : zxid_add_ldif_at2ses(cf, ses, 0, buf, "splocal.all");
722 : 67 : ZX_FREE(cf->ctx, buf);
723 : : }
724 : 87 : path = zx_strf(cf->ctx, "%s" ZXID_USER_DIR ".all", cf->path);
725 : 87 : zxid_cp_usr_eprs2ses(cf, ses, path);
726 : :
727 : 87 : zxid_add_attr_to_ses(cf, ses, "eid", zxid_my_ent_id(cf));
728 : 87 : zxid_add_attr_to_ses(cf, ses, "sigres", zx_strf(cf->ctx, "%x", ses->sigres));
729 : 87 : zxid_add_attr_to_ses(cf, ses, "ssores", zx_strf(cf->ctx, "%x", ses->ssores));
730 [ + - + - ]: 87 : if (ses->sid && *ses->sid) {
731 [ + - ]: 87 : zxid_add_attr_to_ses(cf, ses, "sesid", zx_dup_str(cf->ctx, STRNULLCHK(ses->sid)));
732 [ + - ]: 87 : zxid_add_attr_to_ses(cf, ses, "sespath", zx_strf(cf->ctx, "%s" ZXID_SES_DIR "%s", cf->path, STRNULLCHK(ses->sid)));
733 : : }
734 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "sesix", zx_dup_str(cf->ctx, STRNULLCHK(ses->sesix)));
735 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "setcookie", zx_dup_str(cf->ctx, STRNULLCHK(ses->setcookie)));
736 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "cookie", zx_dup_str(cf->ctx, STRNULLCHK(ses->cookie)));
737 : 87 : zxid_add_attr_to_ses(cf, ses, "msgid", ses->wsp_msgid);
738 : :
739 [ + + ]: 87 : zxid_add_attr_to_ses(cf, ses, "rs", zx_dup_str(cf->ctx, STRNULLCHK(ses->rs)));
740 : 87 : src = dst = ses->at->val;
741 : 87 : lim = ses->at->val + strlen(ses->at->val);
742 [ + + + - : 87 : URL_DECODE(dst, src, lim);
+ - - + #
# # # # #
# # + - +
- + - - +
# # # # +
- + - + -
- + - + +
+ ]
743 : 87 : *dst = 0;
744 [ + + - + ]: 87 : D("RelayState(%s)", ses->at->val);
745 : 87 : D_DEDENT("ses2pool: ");
746 : 87 : }
747 : :
748 : : /*(i) Add Attributes from Querty String to Session attribute pool
749 : : * The qs argument is parsed according to the CGI Query String rules
750 : : * and the attributes are added to the session. If apply_map is 1, the
751 : : * INMAP configuration is applied. While this may seem a hassle, it
752 : : * allows for specification of the values as safe_base64, etc. If values
753 : : * are to be added verbatim, just specify 0 (all other values reserved).
754 : : * The input argument qs gets modified in-situ due to URL decoding and
755 : : * nul termination. Make sure to duplicate any string constant before calling.
756 : : * Returns 1 on success, 0 on failure (return value often not checked). */
757 : :
758 : : /* Called by: zxid_az_base_cf_ses, zxid_az_cf_ses */
759 : : int zxid_add_qs_to_ses(zxid_conf* cf, zxid_ses* ses, char* qs, int apply_map)
760 : 12 : {
761 : : char *p, *n, *v, *val, *name;
762 [ + - - + ]: 12 : if (!qs || !ses)
763 : 0 : return 0;
764 : :
765 [ + + - + ]: 12 : D("qs(%s) len=%d", qs, strlen(qs));
766 [ + - + + ]: 35 : while (qs && *qs) {
767 [ - + ]: 11 : for (; *qs == '&'; ++qs) ; /* Skip over & or && */
768 [ + - ]: 11 : if (!*qs) break;
769 : :
770 : 11 : qs = strchr(name = qs, '='); /* Scan name (until '=') */
771 [ + - ]: 11 : if (!qs) break;
772 [ - + ]: 11 : if (qs == name) { /* Key was an empty string: skip it */
773 : 0 : qs = strchr(qs, '&'); /* Scan value (until '&') *** or '?' */
774 : 0 : continue;
775 : : }
776 [ + - - + ]: 11 : for (; name < qs && *name <= ' '; ++name) ; /* Skip over initial whitespace before name */
777 : 11 : n = p = name;
778 [ - + # # : 11 : URL_DECODE(p, name, qs);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # - + +
+ ]
779 : 11 : *p = 0; /* Nul-term n (name) */
780 : :
781 [ + + + - ]: 11 : for (val = ++qs; *qs && *qs != '&'; ++qs) ; /* Skip over = and scan value till '&' */
782 : 11 : v = p = val;
783 [ - + # # : 11 : URL_DECODE(p, val, qs);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # - + +
+ ]
784 : :
785 [ - + ]: 11 : if (*qs)
786 : 0 : ++qs;
787 : 11 : *p = 0; /* Nul-term v (value) */
788 : :
789 [ + - ]: 11 : if (apply_map) {
790 [ + - - + ]: 11 : D("map %s=%s", n,v);
791 : 11 : zxid_add_attr_to_ses(cf, ses, n, zx_dup_str(cf->ctx, v));
792 : : } else {
793 [ # # # # ]: 0 : D("asis %s=%s", n,v);
794 : 0 : ses->at = zxid_new_at(cf, ses->at, v-n-1, n, p-v, v, "as is");
795 : : }
796 : : }
797 : 12 : return 1;
798 : : }
799 : :
800 : : /*(i) Given session object (see zxid_simple_cf_ses() or zxid_fetch_ses()),
801 : : * return n'th value (ix=0 is first) of given attribute, if any, from the
802 : : * session common attribute pool. If apply_map is 0, the value is returned
803 : : * as is. If it is 1 then OUTMAP is applied (the
804 : : * attribute name is in the internal namespace). Other apply_map values
805 : : * are reserved. */
806 : :
807 : : /* Called by: */
808 : : struct zx_str* zxid_get_at(zxid_conf* cf, zxid_ses* ses, char* atname, int ix, int apply_map)
809 : 0 : {
810 : : struct zxid_attr* at;
811 : : struct zxid_attr* av;
812 [ # # # # : 0 : if (!cf || !ses || !atname) {
# # ]
813 : 0 : ERR("Missing args cf=%p ses=%p atname=%p", cf, ses, atname);
814 : 0 : return 0;
815 : : }
816 [ # # ]: 0 : for (at = ses->at; at; at = at->n) {
817 [ # # ]: 0 : if (!strcmp(at->name, atname)) {
818 [ # # # # ]: 0 : for (av = at; av && ix; --ix, av = av->nv) ;
819 [ # # ]: 0 : if (av) {
820 [ # # ]: 0 : if (apply_map) {
821 : 0 : return zx_dup_str(cf->ctx, at->val); /* *** */
822 : : } else
823 : 0 : return zx_dup_str(cf->ctx, at->val);
824 : : }
825 : : }
826 : : }
827 : 0 : return 0;
828 : : }
829 : :
830 : : /* EOF -- zxidpool.c */
|