1 /* zxidconf.c - Handwritten functions for parsing ZXID configuration file
2 * Copyright (c) 2012-2016 Synergetics (sampo@synergetics.be), All Rights Reserved.
3 * Copyright (c) 2009-2011 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
4 * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
5 * Author: Sampo Kellomaki (sampo@iki.fi)
6 * This is confidential unpublished proprietary source code of the author.
7 * NO WARRANTY, not even implied warranties. Contains trade secrets.
8 * Distribution prohibited unless authorized in writing.
9 * Licensed under Apache License 2.0, see file COPYING.
10 * $Id: zxidconf.c,v 1.51 2010-01-08 02:10:09 sampo Exp $
11 *
12 * 12.8.2006, created --Sampo
13 * 16.1.2007, split from zxidlib.c --Sampo
14 * 27.3.2007, lazy reading of certificates --Sampo
15 * 22.2.2008, added path_supplied feature --Sampo
16 * 7.10.2008, added documentation --Sampo
17 * 29.8.2009, added Auto-Cert feature a.k.a. zxid_mk_self_signed_cert() --Sampo
18 * 4.9.2009, added NEED, WANT, INMAP, PEPMAP, OUTMAP, and ATTRSRC --Sampo
19 * 15.11.2009, added SHOW_CONF (o=d) option --Sampo
20 * 7.1.2010, added WSC and WSP signing options --Sampo
21 * 12.2.2010, added pthread locking --Sampo
22 * 31.5.2010, added 4 web service call PEPs --Sampo
23 * 21.4.2011, fixed DSA key reading and reading unqualified keys --Sampo
24 * 3.12.2011, added VPATH feature --Sampo
25 * 10.12.2011, added VURL and BUTTON_URL, deleted ORG_URL except for legacy check --Sampo
26 * 17.8.2012, added audit bus configuration --Sampo
27 * 16.2.2013, added WD option --Sampo
28 * 21.6.2013, added wsp_pat --Sampo
29 * 20.11.2013, added %d expansion for VURL, added ECHO for debug prints --Sampo
30 * 29.11.2013, added INCLUDE feature --Sampo
31 * 4.12.2013, changed URL to BURL --Sampo
32 * 11.4.2015, added UNIX_GRP_AZ_MAP --Sampo
33 * 18.12.2015, applied patch from soconnor, perceptyx, including detection of
34 * signature algorithm from certificate. --Sampo
35 * 8.1.2016, added configuration options for signature and digest algorithms --Sampo
36 */
37
38 #include "platform.h" /* needed on Win32 for pthread_mutex_lock() et al. */
39
40 #include <malloc.h>
41 #include <memory.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <sys/types.h>
45 #include <grp.h>
46 #ifdef USE_CURL
47 #include <curl/curl.h>
48 #endif
49
50 #include "errmac.h"
51 #include "zx.h"
52 #include "zxid.h"
53 #include "zxidutil.h"
54 #include "zxidconf.h"
55 #include "zxidpriv.h"
56 #include "c/zxidvers.h"
57
58 /* ============== Configuration ============== */
59 /* Eventually configuration will be read from some file, but for
60 * now, we settle for compilation time configuration, see zxidconf.h */
61
62 #ifdef USE_OPENSSL
63
64 #include <openssl/rand.h>
65 #include <openssl/x509.h>
66 #include <openssl/rsa.h>
67
68 #if 0
69 /*(-) Compute raw SHA1 digest hash over contents of a file.
70 *
71 * cf:: ZXID configuration object, used for deteminin path prefix and for memory allocation
72 * name:: Name of the file (under hierarchy defined by PATH configuration option)
73 * sha1:: A sha1 buffer which should be exactly 20 bytes (160 bits) long. The
74 * buffer will be modified in place by this function. */
75
76 /* Called by: zxid_init_conf */
77 void zxid_sha1_file(zxid_conf* cf, char* name, char* sha1)
78 {
79 int gotall;
80 char* buf;
81 ZERO(sha1, 20);
82 buf = read_all_alloc(cf->ctx, "sha1_file", 1, &gotall, "%s%s", cf->cpath, name);
83 if (!buf)
84 return;
85 SHA1(buf, gotall, sha1);
86 ZX_FREE(cf->ctx, buf);
87 }
88 #endif
89
zxid_extract_cert_pem(char * buf,char * name)90 char* zxid_extract_cert_pem(char* buf, char* name)
91 {
92 char* p;
93 char* e;
94 p = strstr(buf, PEM_CERT_START);
95 if (!p) {
96 ERR("No certificate found in file(%s)\n", name);
97 return 0;
98 }
99 p += sizeof(PEM_CERT_START) - 1;
100 if (*p == 0xd) ++p;
101 if (*p != 0xa) return 0;
102 ++p;
103
104 e = strstr(buf, PEM_CERT_END);
105 if (!e) return 0;
106 *e = 0;
107 return p;
108 }
109
110 /*() Extract a certificate as base64 textr from PEM encoded file. */
111
zxid_read_cert_pem(zxid_conf * cf,char * name,int siz,char * buf)112 char* zxid_read_cert_pem(zxid_conf* cf, char* name, int siz, char* buf)
113 {
114 int got = read_all(siz, buf, "read_cert", 1, "%s" ZXID_PEM_DIR "%s", cf->cpath, name);
115 if (!got && cf->auto_cert)
116 zxid_mk_self_sig_cert(cf, siz, buf, "read_cert", name);
117 return zxid_extract_cert_pem(buf, name);
118 }
119
120
121 /*() Extract a certificate from PEM encoded string. */
122
123 /* Called by: opt, test_mode, zxid_read_cert */
zxid_extract_cert(char * buf,char * name)124 X509* zxid_extract_cert(char* buf, char* name)
125 {
126 X509* x = 0; /* Forces d2i_X509() to alloc the memory. */
127 char* p;
128 char* e;
129 p = zxid_extract_cert_pem(buf, name);
130 if (!p)
131 return 0;
132 e = unbase64_raw(p, p+strlen(p), p, zx_std_index_64);
133 OpenSSL_add_all_algorithms();
134 if (!d2i_X509(&x, (const unsigned char**)&p /* *** compile warning */, e-p) || !x) {
135 ERR("DER decoding of X509 certificate failed.\n%d", 0);
136 return 0;
137 }
138 return x;
139 }
140
141 /*() Extract a certificate from PEM encoded file. */
142
143 /* Called by: hi_new_shuffler, zxid_idp_sso_desc x2, zxid_init_conf x3, zxid_lazy_load_sign_cert_and_pkey, zxid_sp_sso_desc x2, zxlog_write_line */
zxid_read_cert(zxid_conf * cf,char * name)144 X509* zxid_read_cert(zxid_conf* cf, char* name)
145 {
146 X509* x = 0; /* Forces d2i_X509() to alloc the memory. */
147 char buf[8192];
148 char* p;
149 char* e;
150 p = zxid_read_cert_pem(cf, name, sizeof(buf), buf);
151 if (!p)
152 return 0;
153 OpenSSL_add_all_algorithms();
154 e = unbase64_raw(p, p+strlen(p), p, zx_std_index_64);
155 if (!d2i_X509(&x, (const unsigned char**)&p /* *** compile warning */, e-p) || !x) {
156 ERR("DER decoding of X509 certificate failed.\n%d", 0);
157 return 0;
158 }
159 return x;
160 }
161
162 /*() Extract a private key from PEM encoded string.
163 * *** This function needs to expand to handle DSA and EC */
164
165 /* Called by: */
zxid_extract_private_key(char * buf,char * name)166 EVP_PKEY* zxid_extract_private_key(char* buf, char* name)
167 {
168 char* p;
169 char* e;
170 int typ;
171 EVP_PKEY* pk = 0; /* Forces d2i_PrivateKey() to alloc the memory. */
172 OpenSSL_add_all_algorithms();
173
174 if (p = strstr(buf, PEM_RSA_PRIV_KEY_START)) {
175 typ = EVP_PKEY_RSA;
176 e = PEM_RSA_PRIV_KEY_END;
177 p += sizeof(PEM_RSA_PRIV_KEY_START) - 1;
178 } else if (p = strstr(buf, PEM_DSA_PRIV_KEY_START)) {
179 typ = EVP_PKEY_DSA;
180 e = PEM_DSA_PRIV_KEY_END;
181 p += sizeof(PEM_DSA_PRIV_KEY_START) - 1;
182 } else if (p = strstr(buf, PEM_PRIV_KEY_START)) { /* Not official format, but sometimes seen. */
183 typ = EVP_PKEY_RSA;
184 e = PEM_PRIV_KEY_END;
185 p += sizeof(PEM_PRIV_KEY_START) - 1;
186 } else {
187 ERR("No private key found in file(%s). Looking for separator (%s) or (%s).\npem data(%s)", name, PEM_RSA_PRIV_KEY_START, PEM_DSA_PRIV_KEY_START, buf);
188 return 0;
189 }
190 if (*p == 0xd) ++p;
191 if (*p != 0xa) {
192 ERR("Bad privkey missing newline ch(0x%x) at %ld (%.*s) of buf(%s)", *p, (long)(p-buf), 5, p-2, buf);
193 return 0;
194 }
195 ++p;
196
197 e = strstr(buf, e);
198 if (!e) {
199 ERR("End marker not found, typ=%d", typ);
200 return 0;
201 }
202
203 zx_report_openssl_err("extract_private_key0"); /* *** seems something leaves errors on stack */
204 p = unbase64_raw(p, e, buf, zx_std_index_64);
205 if (!d2i_PrivateKey(typ, &pk, (const unsigned char**)&buf, p-buf) || !pk) {
206 zx_report_openssl_err("extract_private_key"); /* *** seems d2i can leave errors on stack */
207 ERR("DER decoding of private key failed.\n%d", 0);
208 return 0;
209 }
210 zx_report_openssl_err("extract_private_key2"); /* *** seems d2i can leave errors on stack */
211 return pk; /* RSA* rsa = EVP_PKEY_get1_RSA(pk); */
212 }
213
214 /*() Extract a private key from PEM encoded file. */
215
216 /* Called by: hi_new_shuffler, test_ibm_cert_problem x2, test_ibm_cert_problem_enc_dec x2, zxbus_mint_receipt x2, zxenc_privkey_dec, zxid_init_conf x3, zxid_lazy_load_sign_cert_and_pkey, zxlog_write_line x2 */
zxid_read_private_key(zxid_conf * cf,char * name)217 EVP_PKEY* zxid_read_private_key(zxid_conf* cf, char* name)
218 {
219 char buf[8192];
220 int got = read_all(sizeof(buf),buf,"read_private_key",1, "%s" ZXID_PEM_DIR "%s", cf->cpath, name);
221 if (!got && cf->auto_cert)
222 zxid_mk_self_sig_cert(cf, sizeof(buf), buf, "read_private_key", name);
223 return zxid_extract_private_key(buf, name);
224 }
225
226 /*() Lazy load signing certificate and private key. This reads them from disk
227 * if needed. If they do not exist and auto_cert is enabled, they will be
228 * generated on disk and then read. Once read from disk, they will be cached in
229 * memory.
230 *
231 * > N.B. If the cert does not yet exist, write access to disk will be needed.
232 * > If it already exists, read access is sufficient. Thus it is more secure
233 * > to pregenerate the certificate and then set the permissions so that
234 * > the process can read it, but can not alter it.
235 *
236 * cf:: Configuration object
237 * cert:: result parameter. If non null, the certificate will be extracted
238 * from file and pointer to the X509 data structure will be deposited
239 * to place pointed by this parameter. If null, certificate is neither
240 * extracted nor returned. The data structure should be freed by the
241 * caller.
242 * pkey:: result parameter. Must be specified. The private key data structure
243 * is extracted from the file and returned using this parameter. The
244 * data structure should be freed by the caller.
245 * logkey:: Free form string describing why the cert and private key are
246 * being requested. Used for logging and debugging.
247 * return:: Returns 1 on success and 0 on failure.
248 */
249
250 /* Called by: zxid_anoint_a7n, zxid_anoint_sso_resp, zxid_az_soap x3, zxid_idp_soap_dispatch x2, zxid_idp_sso, zxid_mk_art_deref, zxid_mk_at_cert, zxid_saml2_post_enc, zxid_saml2_redir_enc, zxid_sp_mni_soap, zxid_sp_slo_soap, zxid_sp_soap_dispatch x7, zxid_ssos_anreq, zxid_wsf_sign */
zxid_lazy_load_sign_cert_and_pkey(zxid_conf * cf,X509 ** cert,EVP_PKEY ** pkey,const char * logkey)251 int zxid_lazy_load_sign_cert_and_pkey(zxid_conf* cf, X509** cert, EVP_PKEY** pkey, const char* logkey)
252 {
253 LOCK(cf->mx, logkey);
254 if (cert) {
255 if (!(*cert = cf->sign_cert)) // Lazy load cert and private key
256 *cert = cf->sign_cert = zxid_read_cert(cf, "sign-nopw-cert.pem");
257 }
258 if (!(*pkey = cf->sign_pkey))
259 *pkey = cf->sign_pkey = zxid_read_private_key(cf, "sign-nopw-cert.pem");
260 UNLOCK(cf->mx, logkey);
261 if (cert && !*cert || !*pkey)
262 return 0;
263 return 1;
264 }
265
266 #endif /* USE_OPENSSL */
267
268 /*() Set obscure options of ZX and ZXID layers. Used to set debug options.
269 * Generally setting these options is not supported, but this function
270 * exists to avoid uncontrolled access to global variables. At least this
271 * way the unsupported activity will happen in one controlled place where
272 * it can be ignored, if need to be. You have been warned. */
273
274 /* Called by: main, zxid_fed_mgmt_cf, zxid_idp_list_cf_cgi, zxid_simple_cf_ses */
zxid_set_opt(zxid_conf * cf,int which,int val)275 int zxid_set_opt(zxid_conf* cf, int which, int val)
276 {
277 switch (which) {
278 case 1: errmac_debug = val; INFO("errmac_debug=%d",val); return val;
279 case 5: exit(val); /* This is typically used to force __gcov_flush() */
280 case 6: zxid_set_opt_cstr(cf, 6, "/var/zxid/log/log.dbg"); return 0;
281 #ifdef M_CHECK_ACTION /* glibc specific */
282 case 7: mallopt(M_CHECK_ACTION, val); return 0; /* val==3 enables cores on bad free() */
283 #endif
284 default: ERR("zxid_set_opt: this version " ZXID_REL " does not support which=%d val=%d (ignored)", which, val);
285 }
286 return -1;
287 }
288
289 /*() Set obscure options of ZX and ZXID layers. Used to set debug options.
290 * Generally setting these options is not supported, but this function
291 * exists to avoid uncontrolled access to global variables. At least this
292 * way the unsupported activity will happen in one controlled place where
293 * it can be ignored, if need to be. You have been warned. */
294
295 /* Called by: zxid_parse_conf_raw, zxid_set_opt */
zxid_set_opt_cstr(zxid_conf * cf,int which,char * val)296 char* zxid_set_opt_cstr(zxid_conf* cf, int which, char* val)
297 {
298 char buf[PATH_MAX];
299 switch (which) {
300 case 2: strncpy(errmac_instance, val, sizeof(errmac_instance)); return errmac_instance;
301 case 3: D_INDENT(val); return errmac_indent;
302 case 4: D_DEDENT(val); return errmac_indent;
303 case 6:
304 D("Forwarding debug output to file(%s) cwd(%s)", STRNULLCHK(val), getcwd(buf, sizeof(buf)));
305 errmac_debug_log = fopen(val, "a");
306 if (!errmac_debug_log) {
307 perror("zxid_set_opt_cstr: failed to open new log file");
308 fprintf(stderr, "zxid_set_opt_cstr: failed to open new log file(%s), euid=%d egid=%d cwd(%s)", STRNULLCHK(val), geteuid(), getegid(), getcwd(buf, sizeof(buf)));
309 exit(1);
310 }
311 INFO("zxid_set_opt_cstr: opened new log file(%s), rel=" ZXID_REL " euid=%d egid=%d cwd(%s)", STRNULLCHK(val), geteuid(), getegid(), getcwd(buf, sizeof(buf)));
312 return "";
313 default: ERR("zxid_set_opt_cstr: this version " ZXID_REL " does not support which=%d val(%s) (ignored)", which, STRNULLCHK(val));
314 }
315 return 0;
316 }
317
318 /*() Set the BURL configuration variable. Special accessor function to
319 * manipulate BURL config option. Manipulating this option is common in
320 * virtual hosting situations - hence this convenience function. You
321 * could use zxid_parse_conf() instead to manipulate BURL and some other
322 * options. */
323
324 /* Called by: main x2, zxidwspcgi_main */
zxid_url_set(zxid_conf * cf,const char * burl)325 void zxid_url_set(zxid_conf* cf, const char* burl)
326 {
327 if (!cf || !burl) {
328 ERR("NULL pointer as cf or url argument cf=%p url=%p", cf, burl);
329 return;
330 }
331 D("Setting url(%s)", burl);
332 cf->burl = zx_dup_cstr(cf->ctx, burl);
333 }
334
335 /* ================== Attribute Broker Config ================*/
336
337 #define IS_RULE(rule, val) (!memcmp((rule), (val), sizeof(val)-1) && (rule)[sizeof(val)-1] == '$')
338
339 /*() Create new (common pool) attribute and add it to a linked list */
340
341 /* Called by: zxid_add_at_vals x3, zxid_add_attr_to_ses x2, zxid_add_qs2ses, zxid_load_atsrc, zxid_load_need */
zxid_new_at(zxid_conf * cf,struct zxid_attr * at,int name_len,char * name,int val_len,char * val,char * lk)342 struct zxid_attr* zxid_new_at(zxid_conf* cf, struct zxid_attr* at, int name_len, char* name, int val_len, char* val, char* lk)
343 {
344 struct zxid_attr* aa = ZX_ZALLOC(cf->ctx, struct zxid_attr);
345 aa->n = at;
346 at = aa;
347 COPYVAL(at->name, name, name+name_len);
348 if (val)
349 COPYVAL(at->val, val, val+val_len);
350 D("%s:\tATTR(%.*s)=(%.*s)", lk, name_len, name, MIN(val_len, 80), STRNULLCHK(val));
351 return aa;
352 }
353
354 /*() Reverse of zxid_new_at(). */
355
356 /* Called by: zxid_free_atsrc, zxid_free_need */
zxid_free_at(struct zxid_conf * cf,struct zxid_attr * attr)357 void zxid_free_at(struct zxid_conf *cf, struct zxid_attr *attr)
358 {
359 while (attr) {
360 struct zxid_attr *next = attr->n;
361 ZX_FREE(cf->ctx, attr->name);
362 if (attr->val) ZX_FREE(cf->ctx, attr->val);
363 ZX_FREE(cf->ctx, attr);
364 attr = next;
365 }
366 }
367
368 /*() Parse need specification and add it to linked list
369 * A,B$usage$retention$oblig$ext;A,B$usage$retention$oblig$ext;...
370 */
371
372 /* Called by: zxid_init_conf x2, zxid_parse_conf_raw x2 */
zxid_load_need(zxid_conf * cf,struct zxid_need * need,char * v)373 struct zxid_need* zxid_load_need(zxid_conf* cf, struct zxid_need* need, char* v)
374 {
375 char* attrs;
376 char* usage;
377 char* retent;
378 char* oblig;
379 char* ext;
380 char* p = v;
381 char* a;
382 int len;
383 struct zxid_need* nn;
384
385 while (p && *p) {
386 attrs = p;
387 p = strchr(p, '$');
388 if (!p) {
389 ERR("Malformed NEED or WANT directive: attribute list at pos %d", ((int)(p-v)));
390 return need;
391 }
392
393 usage = ++p;
394 p = strchr(p, '$');
395 if (!p) {
396 ERR("Malformed NEED or WANT directive: usage missing at pos %d", ((int)(p-v)));
397 return need;
398 }
399
400 retent = ++p;
401 p = strchr(p, '$');
402 if (!p) {
403 ERR("Malformed NEED or WANT directive: retention missing at pos %d", ((int)(p-v)));
404 return need;
405 }
406
407 oblig = ++p;
408 p = strchr(p, '$');
409 if (!p) {
410 ERR("Malformed NEED or WANT directive: obligations missing at pos %d", ((int)(p-v)));
411 return need;
412 }
413
414 ext = ++p;
415 p = strchr(p, ';'); /* Stanza ends in separator ; or end of string nul */
416 if (!p)
417 p = ext + strlen(ext);
418
419 if (IS_RULE(usage, "reset")) {
420 INFO("Reset need %p", need);
421 zxid_free_need(cf, need);
422 need = 0;
423 if (!*p) break;
424 ++p;
425 continue;
426 }
427
428 nn = ZX_ZALLOC(cf->ctx, struct zxid_need);
429 nn->n = need;
430 need = nn;
431
432 COPYVAL(nn->usage, usage, retent-1);
433 COPYVAL(nn->retent, retent, oblig-1);
434 COPYVAL(nn->oblig, oblig, ext-1);
435 COPYVAL(nn->ext, ext, p);
436
437 DD("need attrs(%.*s) usage(%s) retent(%s) oblig(%s) ext(%s)", usage-attrs-1, attrs, nn->usage, nn->retent, nn->oblig, nn->ext);
438
439 for (a = attrs; ; a += len+1) {
440 len = strcspn(a, ",$");
441 nn->at = zxid_new_at(cf, nn->at, len, a, 0,0, "need/want");
442 if (a[len] == '$')
443 break;
444 }
445 if (!*p) break;
446 ++p;
447 }
448
449 return need;
450 }
451
452 /*() Reverse of zxid_load_need(). */
453
454 /* Called by: zxid_free_conf x2, zxid_load_need */
zxid_free_need(struct zxid_conf * cf,struct zxid_need * need)455 void zxid_free_need(struct zxid_conf *cf, struct zxid_need *need)
456 {
457 while (need) {
458 struct zxid_need *next = need->n;
459 ZX_FREE(cf->ctx, need->usage);
460 ZX_FREE(cf->ctx, need->retent);
461 ZX_FREE(cf->ctx, need->oblig);
462 ZX_FREE(cf->ctx, need->ext);
463 zxid_free_at(cf, need->at);
464 ZX_FREE(cf->ctx, need);
465 need = next;
466 }
467 }
468
469 /*() Parse map specification and add it to linked list
470 * srcns$A$rule$b$ext;src$A$rule$b$ext;...
471 * The list ends up being built in reverse order, which at runtime
472 * causes last stanzas to be evaluated first and first match is used.
473 * Thus you should place most specific rules last and most generic rules first.
474 * See also: zxid_find_map() and zxid_map_val()
475 */
476
477 /* Called by: zxid_init_conf x7, zxid_mk_usr_a7n_to_sp, zxid_parse_conf_raw x7, zxid_read_map */
zxid_load_map(zxid_conf * cf,struct zxid_map * map,char * v)478 struct zxid_map* zxid_load_map(zxid_conf* cf, struct zxid_map* map, char* v)
479 {
480 char* ns;
481 char* A;
482 char* rule;
483 char* b;
484 char* ext;
485 char* p = v;
486 int len;
487 struct zxid_map* mm;
488
489 DD("v(%s)", v);
490
491 while (p && *p) {
492 ns = p;
493 p = strchr(p, '$');
494 if (!p) {
495 ERR("Malformed MAP directive: source namespace missing at pos %d", ((int)(p-v)));
496 return map;
497 }
498
499 A = ++p;
500 p = strchr(p, '$');
501 if (!p) {
502 ERR("Malformed MAP directive: source attribute name missing at pos %d", ((int)(p-v)));
503 return map;
504 }
505
506 rule = ++p;
507 p = strchr(p, '$');
508 if (!p) {
509 ERR("Malformed MAP directive: rule missing at pos %d", ((int)(p-v)));
510 return map;
511 }
512
513 b = ++p;
514 p = strchr(p, '$');
515 if (!p) {
516 ERR("Malformed MAP directive: destination attribute name missing at pos %d", ((int)(p-v)));
517 return map;
518 }
519
520 ext = ++p;
521 len = strcspn(p, ";\n"); /* Stanza ends in separator ; or end of string nul */
522 p = ext + len;
523
524 if (IS_RULE(rule, "reset")) {
525 INFO("Reset map %p", map);
526 for (; map; map = mm) {
527 mm = map->n;
528 ZX_FREE(cf->ctx, map);
529 }
530 if (!*p) break;
531 ++p;
532 continue;
533 }
534
535 mm = ZX_ZALLOC(cf->ctx, struct zxid_map);
536 mm->n = map;
537 map = mm;
538
539 if (IS_RULE(rule, "") || IS_RULE(rule, "rename")) { mm->rule = ZXID_MAP_RULE_RENAME; }
540 else if (IS_RULE(rule, "del")) { mm->rule = ZXID_MAP_RULE_DEL; }
541 else if (IS_RULE(rule, "feidedec")) { mm->rule = ZXID_MAP_RULE_FEIDEDEC; }
542 else if (IS_RULE(rule, "feideenc")) { mm->rule = ZXID_MAP_RULE_FEIDEENC; }
543 else if (IS_RULE(rule, "unsb64-inf")) { mm->rule = ZXID_MAP_RULE_UNSB64_INF; }
544 else if (IS_RULE(rule, "def-sb64")) { mm->rule = ZXID_MAP_RULE_DEF_SB64; }
545 else if (IS_RULE(rule, "unsb64")) { mm->rule = ZXID_MAP_RULE_UNSB64; }
546 else if (IS_RULE(rule, "sb64")) { mm->rule = ZXID_MAP_RULE_SB64; }
547
548 else if (IS_RULE(rule, "a7n")) { mm->rule = ZXID_MAP_RULE_WRAP_A7N; }
549 else if (IS_RULE(rule, "a7n-feideenc")) { mm->rule = ZXID_MAP_RULE_WRAP_A7N | ZXID_MAP_RULE_FEIDEENC; }
550 else if (IS_RULE(rule, "a7n-def-sb64")) { mm->rule = ZXID_MAP_RULE_WRAP_A7N | ZXID_MAP_RULE_DEF_SB64; }
551 else if (IS_RULE(rule, "a7n-sb64")) { mm->rule = ZXID_MAP_RULE_WRAP_A7N | ZXID_MAP_RULE_SB64; }
552
553 else if (IS_RULE(rule, "x509")) { mm->rule = ZXID_MAP_RULE_WRAP_X509; }
554 else if (IS_RULE(rule, "x509-feideenc")) { mm->rule = ZXID_MAP_RULE_WRAP_X509 | ZXID_MAP_RULE_FEIDEENC; }
555 else if (IS_RULE(rule, "x509-def-sb64")) { mm->rule = ZXID_MAP_RULE_WRAP_X509 | ZXID_MAP_RULE_DEF_SB64; }
556 else if (IS_RULE(rule, "x509-sb64")) { mm->rule = ZXID_MAP_RULE_WRAP_X509 | ZXID_MAP_RULE_SB64; }
557
558 else if (IS_RULE(rule, "file")) { mm->rule = ZXID_MAP_RULE_WRAP_FILE; }
559 else if (IS_RULE(rule, "file-feideenc")) { mm->rule = ZXID_MAP_RULE_WRAP_FILE | ZXID_MAP_RULE_FEIDEENC; }
560 else if (IS_RULE(rule, "file-def-sb64")) { mm->rule = ZXID_MAP_RULE_WRAP_FILE | ZXID_MAP_RULE_DEF_SB64; }
561 else if (IS_RULE(rule, "file-sb64")) { mm->rule = ZXID_MAP_RULE_WRAP_FILE | ZXID_MAP_RULE_SB64; }
562
563 else {
564 ERR("Unknown map rule(%.*s) at col %d of (%s)", ((int)(b-rule)), rule, ((int)(rule-v)), v);
565 //ERR("sizeof(rename)=%d cmp=%d c(%c)", sizeof("rename"), memcmp(rule, "rename", sizeof("rename")-1), rule[sizeof("rename")]);
566 }
567
568 COPYVAL(mm->ns, ns, A-1);
569 COPYVAL(mm->src, A, rule-1);
570 COPYVAL(mm->dst, b, ext-1);
571 COPYVAL(mm->ext, ext, p);
572
573 DD("map ns(%s) src(%s) rule=%d dst(%s) ext(%s)", mm->ns, mm->src, mm->rule, mm->dst, mm->ext);
574 if (!*p || *p == '\n') break;
575 ++p;
576 }
577
578 return map;
579 }
580
581 /*() Parse unix_grp_az_map specification and add it to linked list
582 * srcns$A$rule$b$ext;src$A$rule$b$ext;...
583 * The list ends up being built in reverse order, which at runtime
584 * causes last stanzas to be evaluated first and first match is used.
585 * Thus you should place most specific rules last and most generic rules first.
586 * See also: zxid_find_map() and zxid_map_val()
587 */
588
589 /* Called by: zxid_init_conf x7, zxid_mk_usr_a7n_to_sp, zxid_parse_conf_raw x7, zxid_read_map */
zxid_load_unix_grp_az_map(zxid_conf * cf,struct zxid_map * map,char * v)590 struct zxid_map* zxid_load_unix_grp_az_map(zxid_conf* cf, struct zxid_map* map, char* v)
591 {
592 char* ns;
593 char* A;
594 char* val;
595 char* group;
596 char* ext;
597 char* p = v;
598 int len, n_grps, i;
599 struct zxid_map* mm;
600 struct group* grp;
601 gid_t* gids;
602
603 DD("v(%s)", v);
604
605 n_grps = getgroups(0,0);
606 gids = ZX_ALLOC(cf->ctx, (n_grps+1)*sizeof(gid_t));
607 getgroups(n_grps, gids);
608 gids[n_grps] = getegid(); /* getgroups(2) is not guaranteed to return egid */
609
610 while (p && *p) {
611 ns = p;
612 p = strchr(p, '$');
613 if (!p) {
614 ERR("Malformed UNIX_GRP_AZ_MAP directive: source namespace missing at pos %d", ((int)(p-v)));
615 return map;
616 }
617
618 A = ++p;
619 p = strchr(p, '$');
620 if (!p) {
621 ERR("Malformed UNIX_GRP_AZ_MAP directive: source attribute name missing at pos %d", ((int)(p-v)));
622 return map;
623 }
624
625 val = ++p;
626 p = strchr(p, '$');
627 if (!p) {
628 ERR("Malformed UNIX_GRP_AZ_MAP directive: value missing at pos %d", ((int)(p-v)));
629 return map;
630 }
631
632 group = ++p;
633 p = strchr(p, '$');
634 if (!p) {
635 ERR("Malformed UNIX_GRP_AZ_MAP directive: unix group name missing at pos %d", ((int)(p-v)));
636 return map;
637 }
638
639 ext = ++p;
640 len = strcspn(p, ";\n"); /* Stanza ends in separator ; or end of string nul */
641 p = ext + len;
642
643 mm = ZX_ZALLOC(cf->ctx, struct zxid_map);
644 mm->n = map;
645 map = mm;
646
647 COPYVAL(mm->ns, ns, A-1);
648 COPYVAL(mm->src, A, val-1);
649 COPYVAL(mm->dst, val, group-1);
650 COPYVAL(mm->ext, ext, p);
651
652 *(ext-1) = 0;
653 grp = getgrnam(group);
654 *(ext-1) = '$';
655 if (grp) {
656 for (i = 0; i <= n_grps; ++i)
657 if (grp->gr_gid == gids[i])
658 goto have_group;
659 ERR("UNIX_GRP_AZ_MAP: The current process does not belong to unix group name %s at pos %d (Config Error: see /etc/group for listing of groups)", group, ((int)(p-v)));
660 return map;
661 have_group:
662 mm->rule = grp->gr_gid;
663 } else {
664 ERR("UNIX_GRP_AZ_MAP: unix group name %s does not exist at pos %d (Config Error: see /etc/group for listing of groups)", group, ((int)(p-v)));
665 return map;
666 }
667
668 DD("map ns(%s) A(%s) val(%s) gid=%d ext(%s)", mm->ns, mm->src, mm->dst, mm->rule, mm->ext);
669 if (!*p || *p == '\n') break;
670 ++p;
671 }
672
673 ZX_FREE(cf->ctx, gids);
674 return map;
675 }
676
677 /*() Reverse of zxid_load_map(). */
678
679 /* Called by: zxid_free_conf x7 */
zxid_free_map(struct zxid_conf * cf,struct zxid_map * map)680 void zxid_free_map(struct zxid_conf *cf, struct zxid_map *map)
681 {
682 while (map) {
683 struct zxid_map *next = map->n;
684 ZX_FREE(cf->ctx, map->ns);
685 ZX_FREE(cf->ctx, map->src);
686 ZX_FREE(cf->ctx, map->dst);
687 ZX_FREE(cf->ctx, map->ext);
688 ZX_FREE(cf->ctx, map);
689 map = next;
690 }
691 }
692
693 /*() Parse comma separated strings (nul terminated) and add to linked list */
694
695 /* Called by: zxid_init_conf x4, zxid_load_obl_list, zxid_parse_conf_raw x4 */
zxid_load_cstr_list(zxid_conf * cf,struct zxid_cstr_list * l,char * p)696 struct zxid_cstr_list* zxid_load_cstr_list(zxid_conf* cf, struct zxid_cstr_list* l, char* p)
697 {
698 char* q;
699 struct zxid_cstr_list* cs;
700
701 for (; p && *p; (void)(*p && ++p)) {
702 q = p;
703 p = strchr(p, ',');
704 if (!p)
705 p = q + strlen(q);
706 cs = ZX_ZALLOC(cf->ctx, struct zxid_cstr_list);
707 cs->n = l;
708 l = cs;
709 COPYVAL(cs->s, q, p);
710 }
711 return l;
712 }
713
714 /*() Free list nodes and strings of zxid_cstr_list. */
715
716 /* Called by: zxid_free_conf x4, zxid_free_obl_list */
zxid_free_cstr_list(struct zxid_conf * cf,struct zxid_cstr_list * l)717 void zxid_free_cstr_list(struct zxid_conf* cf, struct zxid_cstr_list* l)
718 {
719 while (l) {
720 struct zxid_cstr_list* next = l->n;
721 ZX_FREE(cf->ctx, l->s);
722 ZX_FREE(cf->ctx, l);
723 l = next;
724 }
725 }
726
727 // *** print obl_list
728
729 /*() Parse and construct an obligations list with multiple values as cstr_list.
730 * The input string obl will be modified in place and used for long term reference,
731 * so do not pass a constant string or something that will be freed immadiately. */
732
733 /* Called by: zxid_eval_sol1, zxid_parse_conf_raw x2 */
zxid_load_obl_list(zxid_conf * cf,struct zxid_obl_list * ol,char * obl)734 struct zxid_obl_list* zxid_load_obl_list(zxid_conf* cf, struct zxid_obl_list* ol, char* obl)
735 {
736 struct zxid_obl_list* ob;
737 char *val, *name;
738 DD("obl(%s) len=%d", STRNULLCHK(obl), obl?strlen(obl):-1);
739 if (!obl)
740 return 0;
741 while (obl && *obl) {
742 obl = zxid_qs_nv_scan(obl, &name, &val, 1);
743 if (!name)
744 name = "NULL_NAM_ERRO";
745 if (!strcmp(name, "reset")) {
746 ol = 0;
747 continue;
748 }
749 ob = ZX_ZALLOC(cf->ctx, struct zxid_obl_list);
750 ob->name = name;
751 ob->vals = zxid_load_cstr_list(cf, 0, val);
752 ob->n = ol;
753 ol = ob;
754 D("ALLOC OBL(%s) %p", ol->name, ol);
755 }
756 return ol;
757 }
758
759 /*() Free list nodes and strings of zxid_obl_list. */
760
761 /* Called by: zxid_eval_sol1 x2 */
zxid_free_obl_list(struct zxid_conf * cf,struct zxid_obl_list * ol)762 void zxid_free_obl_list(struct zxid_conf* cf, struct zxid_obl_list* ol)
763 {
764 //return; /* *** LEAK temporary fix 20130319 --Sampo */
765 while (ol) {
766 struct zxid_obl_list* next = ol->n;
767 zxid_free_cstr_list(cf, ol->vals);
768 /* ZX_FREE(cf->ctx, ol->name); BAD IDEA: the name comes from external static storage */
769 D("FREE OBL(%s) %p", ol->name, ol);
770 ZX_FREE(cf->ctx, ol);
771 ol = next;
772 }
773 }
774
775 /*() Parse comma separated bus_urls and add to linked list */
776
777 /* Called by: zxid_init_conf, zxid_parse_conf_raw */
zxid_load_bus_url(zxid_conf * cf,struct zxid_bus_url * bu_root,char * p)778 struct zxid_bus_url* zxid_load_bus_url(zxid_conf* cf, struct zxid_bus_url* bu_root, char* p)
779 {
780 char* q;
781 struct zxid_bus_url* bu;
782
783 for (; p && *p; (void)(*p && ++p)) {
784 q = p;
785 p = strchr(p, ',');
786 if (!p)
787 p = q + strlen(q);
788 bu = ZX_ZALLOC(cf->ctx, struct zxid_bus_url);
789 bu->n = bu_root;
790 bu_root = bu;
791 COPYVAL(bu->s, q, p);
792 COPYVAL(bu->eid, q, p); /* *** convention is that contact URL and eid are the same?!? */
793 }
794 return bu_root;
795 }
796
797 /*() Reverse of zxid_load_bus_url(). */
798
799 /* Called by: zxid_free_conf */
zxid_free_bus_url(struct zxid_conf * cf,struct zxid_bus_url * bu)800 void zxid_free_bus_url(struct zxid_conf* cf, struct zxid_bus_url* bu)
801 {
802 struct zxid_bus_url* next;
803 while (bu) {
804 next = bu->n;
805 ZX_FREE(cf->ctx, bu->s);
806 ZX_FREE(cf->ctx, bu->eid);
807 ZX_FREE(cf->ctx, bu);
808 bu = next;
809 }
810 }
811
812 /*() Parse ATTRSRC specification and add it to linked list
813 * namespace$A,B$weight$accessparamURL$AAPMLref$otherLim$ext;namespace$A,B$weight$accessparamURL$AAPMLref$otherLim$ext;...
814 */
815
816 /* Called by: zxid_init_conf, zxid_parse_conf_raw */
zxid_load_atsrc(zxid_conf * cf,struct zxid_atsrc * atsrc,char * v)817 struct zxid_atsrc* zxid_load_atsrc(zxid_conf* cf, struct zxid_atsrc* atsrc, char* v)
818 {
819 char* ns;
820 char* attrs;
821 char* weight;
822 char* url;
823 char* aapml;
824 char* otherlim;
825 char* ext;
826 char* p = v;
827 char* a;
828 int len;
829 struct zxid_atsrc* as;
830
831 while (p && *p) {
832 ns = p;
833 p = strchr(p, '$');
834 if (!p) {
835 ERR("Malformed ATSRC directive: namespace missing at pos %d", ((int)(p-v)));
836 return atsrc;
837 }
838
839 attrs = ++p;
840 p = strchr(p, '$');
841 if (!p) {
842 ERR("Malformed ATSRC directive: attribute list missing at pos %d", ((int)(p-v)));
843 return atsrc;
844 }
845
846 weight = ++p;
847 p = strchr(p, '$');
848 if (!p) {
849 ERR("Malformed ATSRC directive: weight missing at pos %d", ((int)(p-v)));
850 return atsrc;
851 }
852
853 url = ++p;
854 p = strchr(p, '$');
855 if (!p) {
856 ERR("Malformed ATSRC directive: url missing at pos %d", ((int)(p-v)));
857 return atsrc;
858 }
859
860 aapml = ++p;
861 p = strchr(p, '$');
862 if (!p) {
863 ERR("Malformed ATSRC directive: aapml ref missing at pos %d", ((int)(p-v)));
864 return atsrc;
865 }
866
867 otherlim = ++p;
868 p = strchr(p, '$');
869 if (!p) {
870 ERR("Malformed ATSRC directive: otherlim missing at pos %d", ((int)(p-v)));
871 return atsrc;
872 }
873
874 ext = ++p;
875 p = strchr(p, ';'); /* Stanza ends in separator ; or end of string nul */
876 if (!p)
877 p = ext + strlen(ext);
878
879 if (IS_RULE(url, "reset")) {
880 INFO("Reset atsrc %p", atsrc);
881 zxid_free_atsrc(cf, atsrc);
882 atsrc = NULL;
883 if (!*p) break;
884 ++p;
885 continue;
886 }
887
888 as = ZX_ZALLOC(cf->ctx, struct zxid_atsrc);
889 as->n = atsrc;
890 atsrc = as;
891
892 COPYVAL(as->ns, ns, attrs-1);
893 COPYVAL(as->weight, weight, url-1);
894 COPYVAL(as->url, url, aapml-1);
895 COPYVAL(as->aapml, aapml, otherlim-1);
896 COPYVAL(as->otherlim, otherlim, ext-1);
897 COPYVAL(as->ext, ext, p);
898
899 D("atsrc ns(%s) attrs(%.*s) weight(%s) url(%s) aapml(%s) otherlim(%s) ext(%s)", as->ns, ((int)(weight-attrs-1)), attrs, as->weight, as->url, as->aapml, as->otherlim, as->ext);
900
901 for (a = attrs; ; a += len+1) {
902 len = strcspn(a, ",$");
903 as->at = zxid_new_at(cf, as->at, len, a, 0,0, "atsrc");
904 if (a[len] == '$')
905 break;
906 }
907 if (!*p) break;
908 ++p;
909 }
910
911 return atsrc;
912 }
913
914 /*() Reverse of zxid_load_atsrc(). */
915
916 /* Called by: zxid_free_conf, zxid_load_atsrc */
zxid_free_atsrc(struct zxid_conf * cf,struct zxid_atsrc * src)917 void zxid_free_atsrc(struct zxid_conf *cf, struct zxid_atsrc *src)
918 {
919 while (src) {
920 struct zxid_atsrc *next = src->n;
921 zxid_free_at(cf, src->at);
922 ZX_FREE(cf->ctx, src->ns);
923 ZX_FREE(cf->ctx, src->weight);
924 ZX_FREE(cf->ctx, src->url);
925 ZX_FREE(cf->ctx, src->aapml);
926 ZX_FREE(cf->ctx, src->otherlim);
927 ZX_FREE(cf->ctx, src->ext);
928 ZX_FREE(cf->ctx, src);
929 src = next;
930 }
931 }
932
933 /*() Check whether attribute is in a (needed or wanted) list. Just a linear
934 * scan as it is simple and good enough for handful of attributes. */
935
936 /* Called by: zxid_add_at_vals x2, zxid_add_attr_to_ses x2 */
zxid_is_needed(struct zxid_need * need,const char * name)937 struct zxid_need* zxid_is_needed(struct zxid_need* need, const char* name)
938 {
939 struct zxid_attr* at;
940 if (!name || !*name)
941 return 0;
942 for (; need; need = need->n)
943 for (at = need->at; at; at = at->n)
944 if (at->name[0] == '*' && !at->name[1] /* Wild card */
945 || !strcmp(at->name, name)) /* Match! */
946 return need;
947 return 0;
948 }
949
950 /*() Check whether attribute is in a (needed or wanted) list. Just a linear
951 * scan as it is simple and good enough for handful of attributes.
952 * The list ends up being built in reverse order, which at runtime
953 * causes last stanzas to be evaluated first and first match is used.
954 * Thus you should place most specific rules last and most generic rules first.
955 * See also: zxid_load_map() and zxid_map_val() */
956
957 /* Called by: pool2apache, zxid_add_at_vals, zxid_add_attr_to_ses, zxid_add_mapped_attr x2, zxid_pepmap_extract, zxid_pool2env, zxid_pool_to_json x2, zxid_pool_to_ldif x2, zxid_pool_to_qs x2 */
zxid_find_map(struct zxid_map * map,const char * name)958 struct zxid_map* zxid_find_map(struct zxid_map* map, const char* name)
959 {
960 if (!name || !*name)
961 return 0;
962 for (; map; map = map->n) {
963 DD("HERE src(%s)", STRNULLCHKNULL(map->src));
964 if (map->src[0] == '*' && !map->src[1] /* Wild card (only sensible for del and data xform) */
965 || !strcmp(map->src, name)) /* Match! */
966 return map;
967 }
968 return 0;
969 }
970
971 /*() Check whether name is in the list. Used for Local PDP white and black lists. */
972
973 /* Called by: zxid_eval_sol1, zxid_localpdp x4 */
zxid_find_cstr_list(struct zxid_cstr_list * cs,const char * name)974 struct zxid_cstr_list* zxid_find_cstr_list(struct zxid_cstr_list* cs, const char* name)
975 {
976 if (!name || !*name)
977 return 0;
978 for (; cs; cs = cs->n)
979 if (cs->s[0] == '*' && !cs->s[1] /* Wild card */
980 || !strcmp(cs->s, name)) /* Match! */
981 return cs;
982 return 0;
983 }
984
985 /*() Chech whether any of multivalues of an attribute is on the list. */
986
zxid_find_at_multival_on_cstr_list(struct zxid_cstr_list * cs,struct zxid_attr * at)987 struct zxid_cstr_list* zxid_find_at_multival_on_cstr_list(struct zxid_cstr_list* cs, struct zxid_attr* at)
988 {
989 struct zxid_cstr_list* ret;
990 for (; at; at = at->nv)
991 if ((ret = zxid_find_cstr_list(cs, at->val)))
992 return ret;
993 return 0;
994 }
995
996 /*() Check whether name is in the obligations list. */
997
998 /* Called by: zxid_eval_sol1 */
zxid_find_obl_list(struct zxid_obl_list * obl,const char * name)999 struct zxid_obl_list* zxid_find_obl_list(struct zxid_obl_list* obl, const char* name)
1000 {
1001 if (!name || !*name)
1002 return 0;
1003 for (; obl; obl = obl->n)
1004 if (obl->name[0] == '*' && !obl->name[1] /* Wild card */
1005 || !strcmp(obl->name, name)) /* Match! */
1006 return obl;
1007 return 0;
1008 }
1009
1010 /*() Check whether attribute is in pool. */
1011
1012 /* Called by: zxid_localpdp x2 */
zxid_find_at(struct zxid_attr * pool,const char * name)1013 struct zxid_attr* zxid_find_at(struct zxid_attr* pool, const char* name)
1014 {
1015 if (!name || !*name)
1016 return 0;
1017 for (; pool; pool = pool->n)
1018 if (!strcmp(pool->name, name)) /* Match! */
1019 return pool;
1020 return 0;
1021 }
1022
1023 /*() Check that the user, who is logged into session, maps to group.
1024 * This is used by UNIX_GRP_AZ_MAP to check that filesystem
1025 * permissions allow user to access a file (existence of g+r and
1026 * user mapping to the correct group).
1027 *
1028 * return:: 0=deny, 1=permit */
1029
zxid_unix_grp_az_check(zxid_conf * cf,zxid_ses * ses,int gid)1030 int zxid_unix_grp_az_check(zxid_conf* cf, zxid_ses* ses, int gid)
1031 {
1032 struct zxid_map* grp_map = 0;
1033 struct zxid_attr* at = 0;
1034
1035 if (!cf || !ses) {
1036 ERR("missing argument cf=%p", cf);
1037 return 0;
1038 }
1039 if (!ses->nid || !ses->nid[0]) {
1040 INFO("user not logged in ses->nid=%p", ses->nid);
1041 return 0;
1042 }
1043 for (grp_map = cf->unix_grp_az_map; grp_map; grp_map = grp_map->n) {
1044 if (grp_map->rule != gid)
1045 continue;
1046
1047 /* If affiliation filter is specified, check it. */
1048 if (grp_map->ns && strcmp(grp_map->ns, "") /* none of the wild card cases */
1049 && strcmp(grp_map->ns, "*") && strcmp(grp_map->ns, "**")) {
1050 at = zxid_find_at(ses->at, "affid");
1051 if (!at || !zx_match(grp_map->ns, at->val /*ses->nameid->NameQualifier*/))
1052 continue;
1053 }
1054
1055 /* If attribute filter is specified, check it. */
1056 if (grp_map->src && strcmp(grp_map->src, "") /* none of the wild card cases */
1057 && strcmp(grp_map->src, "*") && strcmp(grp_map->src, "**")) {
1058 at = zxid_find_at(ses->at, grp_map->src);
1059 if (!at || !zx_match(grp_map->dst, at->val /*ses->nameid->NameQualifier*/))
1060 continue;
1061 }
1062 D("%s=%s maps to gid=%d", STRNULLCHKD(grp_map?grp_map->src:0), STRNULLCHKD(at?at->val:0), gid);
1063 return 1;
1064 }
1065 INFO("user does not map to gid=%d", gid);
1066 return 0;
1067 }
1068
1069 /*() Given URL, return a newly allocated string corresponding
1070 * to the domain name part of the URL. Used to grab fedusername_suffix
1071 * from the url config option. */
1072
1073 /* Called by: zxid_parse_conf_raw */
zxid_grab_domain_name(zxid_conf * cf,const char * url)1074 char* zxid_grab_domain_name(zxid_conf* cf, const char* url)
1075 {
1076 char* dom;
1077 char* p;
1078 int len;
1079 if (!url || !*url)
1080 return 0;
1081 dom = strchr(url, ':');
1082 if (!dom || dom[1] != '/' || dom[2] != '/')
1083 return 0;
1084 dom += 3;
1085 /* After shipping https:// scan for domain name allowable characters. */
1086 len = strspn(dom, ".abcdefghijklmnopqrstuvwxyz0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ");
1087 p = ZX_ALLOC(cf->ctx, len+1);
1088 memcpy(p, dom, len);
1089 p[len] = 0;
1090 return p;
1091 }
1092
1093 struct zx_lock zxid_ent_cache_mx;
1094 int zxid_ent_cache_mx_init = 0;
1095
1096 /*(i) Initialize configuration object, which must have already been
1097 * allocated, to factory defaults (i.e. compiled in defaults, see
1098 * zxidconf.h). Config file is not read.
1099 *
1100 * cf:: Pointer to previously allocated configuration object
1101 * path:: Since this configuration option is so fundamental, it can
1102 * be supplied directly as argument. However, unlike zxid_new_conf()
1103 * this does not cause the config file to be read.
1104 * return:: 0 on success (currently, 2008, this function can not
1105 * fail - thus it is common to ignore the return value)
1106 *
1107 * N.B. This function does NOT initialize the ZX context object although
1108 * it is a field of this object. You MUST separately initialize
1109 * the ZX context object, e.g. using zx_reset_ctx() or zx_init_ctx(),
1110 * before you can use ZXID configuration object in any memory allocation prone
1111 * activity (which is nearly every function in this API).
1112 */
1113
1114 /* Called by: zxid_conf_to_cf_len, zxid_init_conf_ctx */
zxid_init_conf(zxid_conf * cf,const char * zxid_path)1115 int zxid_init_conf(zxid_conf* cf, const char* zxid_path)
1116 {
1117 DD("Initconf with path(%s)", zxid_path);
1118 cf->magic = ZXID_CONF_MAGIC;
1119 cf->cpath_len = zxid_path ? strlen(zxid_path) : 0;
1120 cf->cpath = ZX_ALLOC(cf->ctx, cf->cpath_len+1);
1121 memcpy(cf->cpath, zxid_path, cf->cpath_len);
1122 cf->cpath[cf->cpath_len] = 0;
1123 cf->nice_name = ZXID_NICE_NAME;
1124 cf->button_url = ZXID_BUTTON_URL;
1125 cf->pref_button_size = ZXID_PREF_BUTTON_SIZE;
1126 cf->org_name = ZXID_ORG_NAME;
1127 cf->locality = ZXID_LOCALITY;
1128 cf->state = ZXID_STATE;
1129 cf->country = ZXID_COUNTRY;
1130 cf->contact_org = ZXID_CONTACT_ORG;
1131 cf->contact_name = ZXID_CONTACT_NAME;
1132 cf->contact_email = ZXID_CONTACT_EMAIL;
1133 cf->contact_tel = ZXID_CONTACT_TEL;
1134 /* NB: Typically allocated by zxid_grab_domain_name(). */
1135 COPYVAL(cf->fedusername_suffix, ZXID_FEDUSERNAME_SUFFIX,
1136 ZXID_FEDUSERNAME_SUFFIX + strlen(ZXID_FEDUSERNAME_SUFFIX));
1137 cf->burl = ZXID_BURL;
1138 cf->non_standard_entityid = ZXID_NON_STANDARD_ENTITYID;
1139 cf->redirect_hack_imposed_url = ZXID_REDIRECT_HACK_IMPOSED_URL;
1140 cf->redirect_hack_zxid_url = ZXID_REDIRECT_HACK_ZXID_URL;
1141 cf->defaultqs = ZXID_DEFAULTQS;
1142 cf->wsp_pat = ZXID_WSP_PAT;
1143 cf->uma_pat = ZXID_UMA_PAT;
1144 cf->sso_pat = ZXID_SSO_PAT;
1145 cf->cdc_url = ZXID_CDC_URL;
1146 cf->cdc_choice = ZXID_CDC_CHOICE;
1147 cf->authn_req_sign = ZXID_AUTHN_REQ_SIGN;
1148 cf->want_sso_a7n_signed = ZXID_WANT_SSO_A7N_SIGNED;
1149 cf->want_authn_req_signed = ZXID_WANT_AUTHN_REQ_SIGNED;
1150 cf->sso_soap_sign = ZXID_SSO_SOAP_SIGN;
1151 cf->sso_soap_resp_sign = ZXID_SSO_SOAP_RESP_SIGN;
1152 cf->sso_sign = ZXID_SSO_SIGN;
1153 cf->wsc_sign = ZXID_WSC_SIGN;
1154 cf->wsp_sign = ZXID_WSP_SIGN;
1155 cf->oaz_jwt_sigenc_alg = ZXID_OAZ_JWT_SIGENC_ALG;
1156 cf->wspcgicmd = ZXID_WSPCGICMD;
1157 cf->nameid_enc = ZXID_NAMEID_ENC;
1158 cf->post_a7n_enc = ZXID_POST_A7N_ENC;
1159 cf->canon_inopt = ZXID_CANON_INOPT;
1160 if (cf->ctx) cf->ctx->canon_inopt = cf->canon_inopt;
1161 cf->enc_tail_opt = ZXID_ENC_TAIL_OPT;
1162 cf->enckey_opt = ZXID_ENCKEY_OPT;
1163 cf->valid_opt = ZXID_VALID_OPT;
1164 cf->idpatopt = ZXID_IDPATOPT;
1165 cf->idp_list_meth = ZXID_IDP_LIST_METH;
1166 cf->di_allow_create = ZXID_DI_ALLOW_CREATE;
1167 cf->di_nid_fmt = ZXID_DI_NID_FMT;
1168 cf->di_a7n_enc = ZXID_DI_A7N_ENC;
1169 cf->bootstrap_level = ZXID_BOOTSTRAP_LEVEL;
1170 cf->show_conf = ZXID_SHOW_CONF;
1171 #ifdef USE_OPENSSL
1172 if (zxid_path) {
1173 #if 0
1174 /* DO NOT ENABLE! The certificates and keys are read "just in time" if and when needed. */
1175 cf->sign_cert = zxid_read_cert(cf, "sign-nopw-cert.pem");
1176 cf->sign_pkey = zxid_read_private_key(cf, "sign-nopw-cert.pem");
1177 cf->enc_cert = zxid_read_cert(cf, "enc-nopw-cert.pem");
1178 cf->enc_pkey = zxid_read_private_key(cf, "enc-nopw-cert.pem");
1179 cf->log_sign_pkey = zxid_read_private_key(cf, "logsign-nopw-cert.pem");
1180 cf->log_enc_cert = zxid_read_cert(cf, "logenc-nopw-cert.pem");
1181 zxid_sha1_file(cf, "pem/logenc.key", cf->log_symkey);
1182 #endif
1183 }
1184 #else
1185 ERR("This copy of zxid was compiled to NOT use OpenSSL. Reading certificate and private key is not supported. Signing and signature verification are not supported either. Add -DUSE_OPENSSL and recompile. %d", 0);
1186 #endif
1187 cf->md_fetch = ZXID_MD_FETCH;
1188 cf->md_populate_cache = ZXID_MD_POPULATE_CACHE;
1189 cf->md_cache_first = ZXID_MD_CACHE_FIRST;
1190 cf->md_cache_last = ZXID_MD_CACHE_LAST;
1191 cf->md_authority = ZXID_MD_AUTHORITY;
1192 cf->load_cot_cache = ZXID_LOAD_COT_CACHE;
1193 cf->auto_cert = ZXID_AUTO_CERT;
1194 cf->ses_arch_dir = ZXID_SES_ARCH_DIR;
1195 cf->ses_cookie_name = ZXID_SES_COOKIE_NAME;
1196 cf->ptm_cookie_name = ZXID_PTM_COOKIE_NAME;
1197 cf->user_local = ZXID_USER_LOCAL;
1198 cf->idp_ena = ZXID_IDP_ENA;
1199 cf->idp_pxy_ena = ZXID_IDP_PXY_ENA;
1200 cf->imps_ena = ZXID_IMPS_ENA;
1201 cf->as_ena = ZXID_AS_ENA;
1202 cf->md_authority_ena = ZXID_MD_AUTHORITY_ENA;
1203 cf->backwards_compat_ena = ZXID_BACKWARDS_COMPAT_ENA;
1204 cf->pdp_ena = ZXID_PDP_ENA;
1205 cf->cpn_ena = ZXID_CPN_ENA;
1206 cf->az_opt = ZXID_AZ_OPT;
1207 cf->az_fail_mode = ZXID_AZ_FAIL_MODE;
1208
1209 cf->loguser = ZXID_LOGUSER;
1210 cf->log_level = ZXLOG_LEVEL;
1211 cf->log_err = ZXLOG_ERR; /* Log enables and signing and encryption flags (if USE_OPENSSL) */
1212 cf->log_act = ZXLOG_ACT;
1213 cf->log_issue_a7n = ZXLOG_ISSUE_A7N;
1214 cf->log_issue_msg = ZXLOG_ISSUE_MSG;
1215 cf->log_rely_a7n = ZXLOG_RELY_A7N;
1216 cf->log_rely_msg = ZXLOG_RELY_MSG;
1217 cf->log_err_in_act = ZXLOG_ERR_IN_ACT;
1218 cf->log_act_in_err = ZXLOG_ACT_IN_ERR;
1219 cf->log_sigfail_is_err = ZXLOG_SIGFAIL_IS_ERR;
1220 cf->bus_rcpt = ZXBUS_RCPT;
1221 cf->bus_url = zxid_load_bus_url(cf, 0, ZXID_BUS_URL);
1222 cf->bus_pw = ZXID_BUS_PW;
1223
1224 cf->sig_fatal = ZXID_SIG_FATAL;
1225 cf->nosig_fatal = ZXID_NOSIG_FATAL;
1226 cf->msg_sig_ok = ZXID_MSG_SIG_OK;
1227 cf->timeout_fatal = ZXID_TIMEOUT_FATAL;
1228 cf->audience_fatal = ZXID_AUDIENCE_FATAL;
1229 cf->dup_a7n_fatal = ZXID_DUP_A7N_FATAL;
1230 cf->dup_msg_fatal = ZXID_DUP_MSG_FATAL;
1231 cf->relto_fatal = ZXID_RELTO_FATAL;
1232 cf->wsp_nosig_fatal = ZXID_WSP_NOSIG_FATAL;
1233 cf->notimestamp_fatal = ZXID_NOTIMESTAMP_FATAL;
1234 cf->anon_ok = ZXID_ANON_OK;
1235 cf->optional_login_pat = ZXID_OPTIONAL_LOGIN_PAT;
1236 cf->required_authnctx = ZXID_REQUIRED_AUTHNCTX; /* NB: NULL. */
1237 cf->issue_authnctx = zxid_load_cstr_list(cf, 0, ZXID_ISSUE_AUTHNCTX);
1238 cf->idp_pref_acs_binding = ZXID_IDP_PREF_ACS_BINDING;
1239 cf->mandatory_attr = ZXID_MANDATORY_ATTR;
1240
1241 cf->before_slop = ZXID_BEFORE_SLOP;
1242 cf->after_slop = ZXID_AFTER_SLOP;
1243 cf->timeskew = ZXID_TIMESKEW;
1244 cf->a7nttl = ZXID_A7NTTL;
1245 cf->pdp_url = ZXID_PDP_URL;
1246 cf->pdp_call_url = ZXID_PDP_CALL_URL;
1247 cf->xasp_vers = ZXID_XASP_VERS;
1248 cf->trustpdp_url = ZXID_TRUSTPDP_URL;
1249
1250 cf->need = zxid_load_need(cf, 0, ZXID_NEED);
1251 cf->want = zxid_load_need(cf, 0, ZXID_WANT);
1252 cf->attrsrc = zxid_load_atsrc(cf, 0, ZXID_ATTRSRC);
1253 cf->inmap = zxid_load_map(cf, 0, ZXID_INMAP);
1254 cf->outmap = zxid_load_map(cf, 0, ZXID_OUTMAP);
1255 cf->pepmap = zxid_load_map(cf, 0, ZXID_PEPMAP);
1256 cf->pepmap_rqout = zxid_load_map(cf, 0, ZXID_PEPMAP_RQOUT);
1257 cf->pepmap_rqin = zxid_load_map(cf, 0, ZXID_PEPMAP_RQIN);
1258 cf->pepmap_rsout = zxid_load_map(cf, 0, ZXID_PEPMAP_RSOUT);
1259 cf->pepmap_rsin = zxid_load_map(cf, 0, ZXID_PEPMAP_RSIN);
1260
1261 cf->localpdp_role_permit = zxid_load_cstr_list(cf, 0, ZXID_LOCALPDP_ROLE_PERMIT);
1262 cf->localpdp_role_deny = zxid_load_cstr_list(cf, 0, ZXID_LOCALPDP_ROLE_DENY);
1263 cf->localpdp_idpnid_permit = zxid_load_cstr_list(cf, 0, ZXID_LOCALPDP_IDPNID_PERMIT);
1264 cf->localpdp_idpnid_deny = zxid_load_cstr_list(cf, 0, ZXID_LOCALPDP_IDPNID_DENY);
1265
1266 cf->wsc_localpdp_obl_pledge = ZXID_WSC_LOCALPDP_OBL_PLEDGE;
1267 cf->wsp_localpdp_obl_req = ZXID_WSP_LOCALPDP_OBL_REQ;
1268 cf->wsp_localpdp_obl_emit = ZXID_WSP_LOCALPDP_OBL_EMIT;
1269 cf->wsc_localpdp_obl_accept = ZXID_WSC_LOCALPDP_OBL_ACCEPT;
1270
1271 cf->unix_grp_az_map = zxid_load_unix_grp_az_map(cf, 0, ZXID_UNIX_GRP_AZ_MAP);
1272
1273 cf->redir_to_content = ZXID_REDIR_TO_CONTENT;
1274 cf->remote_user_ena = ZXID_REMOTE_USER_ENA;
1275 cf->max_soap_retry = ZXID_MAX_SOAP_RETRY;
1276 cf->mod_saml_attr_prefix = ZXID_MOD_SAML_ATTR_PREFIX;
1277 cf->wsc_soap_content_type = ZXID_WSC_SOAP_CONTENT_TYPE;
1278 cf->wsc_to_hdr = ZXID_WSC_TO_HDR;
1279 cf->wsc_replyto_hdr = ZXID_WSC_REPLYTO_HDR;
1280 cf->wsc_action_hdr = ZXID_WSC_ACTION_HDR;
1281 cf->soap_action_hdr = ZXID_SOAP_ACTION_HDR;
1282
1283 cf->bare_url_entityid = ZXID_BARE_URL_ENTITYID;
1284 cf->show_tech = ZXID_SHOW_TECH;
1285 cf->wd = ZXID_WD;
1286 cf->idp_sel_page = ZXID_IDP_SEL_PAGE;
1287 cf->idp_sel_templ_file= ZXID_IDP_SEL_TEMPL_FILE;
1288 cf->idp_sel_templ = ZXID_IDP_SEL_TEMPL;
1289 #if 0
1290 cf->idp_sel_start = ZXID_IDP_SEL_START;
1291 cf->idp_sel_new_idp = ZXID_IDP_SEL_NEW_IDP;
1292 cf->idp_sel_our_eid = ZXID_IDP_SEL_OUR_EID;
1293 cf->idp_sel_tech_user = ZXID_IDP_SEL_TECH_USER;
1294 cf->idp_sel_tech_site = ZXID_IDP_SEL_TECH_SITE;
1295 cf->idp_sel_footer = ZXID_IDP_SEL_FOOTER;
1296 cf->idp_sel_end = ZXID_IDP_SEL_END;
1297 #endif
1298
1299 cf->an_page = ZXID_AN_PAGE;
1300 cf->an_templ_file = ZXID_AN_TEMPL_FILE;
1301 cf->an_templ = ZXID_AN_TEMPL;
1302
1303 cf->post_templ_file = ZXID_POST_TEMPL_FILE;
1304 cf->post_templ = ZXID_POST_TEMPL;
1305
1306 cf->err_page = ZXID_ERR_PAGE;
1307 cf->err_templ_file = ZXID_ERR_TEMPL_FILE;
1308 cf->err_templ = ZXID_ERR_TEMPL;
1309
1310 cf->new_user_page = ZXID_NEW_USER_PAGE;
1311 cf->recover_passwd = ZXID_RECOVER_PASSWD;
1312 cf->atsel_page = ZXID_ATSEL_PAGE;
1313
1314 cf->mgmt_start = ZXID_MGMT_START;
1315 cf->mgmt_logout = ZXID_MGMT_LOGOUT;
1316 cf->mgmt_defed = ZXID_MGMT_DEFED;
1317 cf->mgmt_footer = ZXID_MGMT_FOOTER;
1318 cf->mgmt_end = ZXID_MGMT_END;
1319
1320 cf->xmldsig_sig_meth = ZXID_XMLDSIG_SIG_METH;
1321 cf->xmldsig_digest_algo = ZXID_XMLDSIG_DIGEST_ALGO;
1322 cf->samlsig_digest_algo = ZXID_SAMLSIG_DIGEST_ALGO;
1323 cf->blobsig_digest_algo = ZXID_BLOBSIG_DIGEST_ALGO;
1324
1325 LOCK_INIT(cf->mx);
1326 LOCK_INIT(cf->curl_mx);
1327 if (!zxid_ent_cache_mx_init) {
1328 LOCK_INIT(zxid_ent_cache_mx);
1329 zxid_ent_cache_mx_init = 1;
1330 }
1331
1332 #if 1
1333 DD("path(%.*s) cf->magic=%x", cf->cpath_len, cf->cpath, cf->magic);
1334 #else
1335 fprintf(stderr, "t %9s:%-3d %-16s %s d " "path(%.*s) cf->magic=%x" "\n",
1336 __FILE__, __LINE__, __FUNCTION__, ERRMAC_INSTANCE, cf->cpath_len, cf->cpath, cf->magic);
1337 fflush(stderr);
1338 #endif
1339 return 0;
1340 }
1341
1342 /*() Reverse of zxid_init_conf() and zxid_parse_conf_raw(). */
1343
1344 /* Called by: */
zxid_free_conf(zxid_conf * cf)1345 void zxid_free_conf(zxid_conf *cf)
1346 {
1347 zxid_free_need(cf, cf->need);
1348 zxid_free_need(cf, cf->want);
1349 zxid_free_atsrc(cf, cf->attrsrc);
1350 zxid_free_bus_url(cf, cf->bus_url);
1351 zxid_free_map(cf, cf->inmap);
1352 zxid_free_map(cf, cf->outmap);
1353 zxid_free_map(cf, cf->pepmap);
1354 zxid_free_map(cf, cf->pepmap_rqout);
1355 zxid_free_map(cf, cf->pepmap_rqin);
1356 zxid_free_map(cf, cf->pepmap_rsout);
1357 zxid_free_map(cf, cf->pepmap_rsin);
1358 zxid_free_cstr_list(cf, cf->localpdp_role_permit);
1359 zxid_free_cstr_list(cf, cf->localpdp_role_deny);
1360 zxid_free_cstr_list(cf, cf->localpdp_idpnid_permit);
1361 zxid_free_cstr_list(cf, cf->localpdp_idpnid_deny);
1362 zxid_free_cstr_list(cf, cf->issue_authnctx);
1363 zxid_free_map(cf, cf->unix_grp_az_map);
1364 if (cf->required_authnctx) {
1365 ZX_FREE(cf->ctx, cf->required_authnctx);
1366 }
1367 if (cf->fedusername_suffix) {
1368 ZX_FREE(cf->ctx, cf->fedusername_suffix);
1369 }
1370 if (cf->cpath) {
1371 ZX_FREE(cf->ctx, cf->cpath);
1372 }
1373 }
1374
1375 /*() Reset the doubly linked seen list and unknown_ns list to empty.
1376 * This is "light" version of zx_reset_ctx() that can be called
1377 * safely from inside lock. */
1378
1379 /* Called by: sig_validate, zx_prepare_dec_ctx, zx_reset_ctx, zxid_sp_sso_finalize */
zx_reset_ns_ctx(struct zx_ctx * ctx)1380 void zx_reset_ns_ctx(struct zx_ctx* ctx)
1381 {
1382 ctx->guard_seen_n.seen_n = &ctx->guard_seen_p;
1383 ctx->guard_seen_p.seen_p = &ctx->guard_seen_n;
1384 ctx->unknown_ns = 0;
1385 }
1386
1387 /*() Reset the seen doubly linked list to empty and initialize memory
1388 * allocation related function pointers to system malloc(3). Without
1389 * such initialization, any memory allocation activity as well as
1390 * any XML parsing activity is doomed to segmentation fault. */
1391
1392 /* Called by: dirconf, main x3, zx_init_ctx, zxid_az, zxid_az_base, zxid_simple_len */
zx_reset_ctx(struct zx_ctx * ctx)1393 void zx_reset_ctx(struct zx_ctx* ctx)
1394 {
1395 ZERO(ctx, sizeof(struct zx_ctx));
1396 LOCK_INIT(ctx->mx);
1397 ctx->malloc_func = &malloc;
1398 ctx->realloc_func = &realloc;
1399 ctx->free_func = &free;
1400 zx_reset_ns_ctx(ctx);
1401 }
1402
1403 /*() Allocate new ZX object and initialize it in standard
1404 * way, i.e. use malloc(3) for memory allocation. */
1405
1406 /* Called by: zxid_conf_to_cf_len, zxid_init_conf_ctx */
zx_init_ctx()1407 struct zx_ctx* zx_init_ctx()
1408 {
1409 struct zx_ctx* ctx;
1410 ctx = malloc(sizeof(struct zx_ctx));
1411 D("malloc %p size=%d", ctx, (int)sizeof(struct zx_ctx));
1412 if (!ctx) {
1413 ERR("out-of-memory in ctx alloc sizeof=%d", (int)sizeof(struct zx_ctx));
1414 return 0;
1415 }
1416 zx_reset_ctx(ctx);
1417 return ctx;
1418 }
1419
1420 /*() Reverse of zx_init_ctx().
1421 * N.B. As of now (20111210) does not free the dependency structures. This
1422 * may be added in future. */
1423
1424 /* Called by: */
zx_free_ctx(struct zx_ctx * ctx)1425 void zx_free_ctx(struct zx_ctx* ctx)
1426 {
1427 free(ctx);
1428 }
1429
1430 /*() Minimal initialization of
1431 * the context is performed. Certificate and key operations as well as
1432 * CURL initialization are omitted. However the zx_ctx is installed so
1433 * that memory allocation against the context should work.
1434 * Supplying zxid_path merely initializes the PATH config option,
1435 * but does not cause configuration file to be read.
1436 *
1437 * Just initializes the config object to factory defaults (see zxidconf.h).
1438 * Previous content of the config object is lost. */
1439
1440 /* Called by: zxid_conf_to_cf_len, zxid_new_conf */
zxid_init_conf_ctx(zxid_conf * cf,const char * zxid_path)1441 zxid_conf* zxid_init_conf_ctx(zxid_conf* cf, const char* zxid_path)
1442 {
1443 #if 0
1444 fprintf(stderr, "Waiting 60 secs for gdb attach...\n");
1445 sleep(60);
1446 #endif
1447 cf->ctx = zx_init_ctx();
1448 if (!cf->ctx)
1449 return 0;
1450 zxid_init_conf(cf, zxid_path);
1451 #ifdef USE_CURL
1452 if (zxid_path) {
1453 cf->curl = curl_easy_init();
1454 if (!cf->curl) {
1455 ERR("Failed to initialize libcurl %d",0);
1456 exit(2);
1457 }
1458 }
1459 #endif
1460 return cf;
1461 }
1462
1463 /*() Allocate conf object and initialize it with default config (config file is not read).
1464 * See zxid_new_conf_to_cf() for a more complete solution.
1465 * Just initializes the config object to factory defaults (see zxidconf.h).
1466 * Previous content of the config object is lost. */
1467
1468 /* Called by: attribute_sort_test, covimp_test, main x4, so_enc_dec, test_ibm_cert_problem, test_ibm_cert_problem_enc_dec, test_mode, timegm_test, timegm_tester, x509_test */
zxid_new_conf(const char * zxid_path)1469 zxid_conf* zxid_new_conf(const char* zxid_path)
1470 {
1471 /* *** unholy malloc()s: should use our own allocator! */
1472 zxid_conf* cf = malloc(sizeof(zxid_conf));
1473 if (!cf) {
1474 ERR("out-of-memory %d", (int)sizeof(zxid_conf));
1475 exit(1);
1476 }
1477 return zxid_init_conf_ctx(cf, zxid_path);
1478 }
1479
1480 /* ======================= CONF PARSING ======================== */
1481
1482 #if defined(ZXID_CONF_FILE) || defined(ZXID_CONF_FLAG)
1483
1484 #define SCAN_INT(v, lval) sscanf(v,"%i",&i); lval=i /* Safe for char, too. Decimal or hex 0x */
1485
1486 /*(-) Helper to evaluate a new PATH. check_file_exists helps to implement
1487 * the sematic where PATH is not changed unless corresponding zxid.conf
1488 * is found. This is used by VPATH. */
1489
1490 /* Called by: zxid_parse_conf_raw, zxid_parse_vpath */
zxid_parse_conf_path_raw(zxid_conf * cf,const char * v,int check_file_exists)1491 static void zxid_parse_conf_path_raw(zxid_conf* cf, const char* v, int check_file_exists)
1492 {
1493 int len;
1494 char *buf;
1495
1496 /* N.B: The buffer read here leaks on purpose as conf parsing takes references inside it. */
1497 buf = read_all_alloc(cf->ctx, "-parse_conf_raw", 1, &len, "%s" ZXID_CONF_FILE, v);
1498 if (!buf || !len)
1499 buf = read_all_alloc(cf->ctx, "-parse_conf_raw", 1, &len, "%szxid.conf", v);
1500 if (buf && len) {
1501 cf->cpath = (char*)v;
1502 cf->cpath_len = strlen(v);
1503 ++cf->cpath_supplied; /* Record level of recursion so we can avoid infinite recursion. */
1504 if (len)
1505 zxid_parse_conf_raw(cf, len, buf); /* Recurse */
1506 --cf->cpath_supplied;
1507 } else if (!check_file_exists) {
1508 cf->cpath = (char*)v; /* Set PATH anyway. */
1509 cf->cpath_len = strlen(v);
1510 }
1511 }
1512
1513 /*(-) Helper to parse an include file. check_file_exists helps to implement
1514 * the sematic where PATH is not changed unless corresponding zxid.conf
1515 * is found. This is used by VPATH. */
1516
1517 /* Called by: zxid_parse_conf_raw */
zxid_parse_inc(zxid_conf * cf,const char * inc_file,int check_file_exists)1518 static void zxid_parse_inc(zxid_conf* cf, const char* inc_file, int check_file_exists)
1519 {
1520 int len;
1521 char *buf;
1522
1523 /* N.B: The buffer read here leaks on purpose as conf parsing takes references inside it. */
1524 buf = read_all_alloc(cf->ctx, "-parse_inc", 1, &len, "%s", inc_file);
1525 if (buf && len) {
1526 ++cf->cpath_supplied; /* Record level of recursion so we can avoid infinite recursion. */
1527 if (len)
1528 zxid_parse_conf_raw(cf, len, buf); /* Recurse */
1529 --cf->cpath_supplied;
1530 } else if (check_file_exists) {
1531 ERR("Mandatory configuration include file(%s) not found. Aborting.", inc_file);
1532 DIE_ACTION(errno);
1533 } else {
1534 ERR("Optional configuration include file(%s) not found. Ignored.", inc_file);
1535 }
1536 }
1537
1538 int zxid_suppress_vpath_warning = 30;
1539
1540 /*() Helper to evaluate environment variables for VPATH and VURL.
1541 * squash_type: 0=VPATH, 1=VURL
1542 * Squashing conversts everything to lowercase and anything
1543 * not understood to underscore ("_"). In case of VURL squash,
1544 * URL characters [/:?&=] are left intact. */
1545
1546 /* Called by: zxid_expand_percent x4 */
zxid_eval_squash_env(char * vorig,const char * exp,char * env_hdr,char * out,char * lim,int squash_type)1547 static int zxid_eval_squash_env(char* vorig, const char* exp, char* env_hdr, char* out, char* lim, int squash_type)
1548 {
1549 int len;
1550 char* val = getenv(env_hdr);
1551 if (!val) {
1552 if (--zxid_suppress_vpath_warning > 0) ERR("VPATH or VURL(%s) %s expansion specified, but env(%s) not defined?!? Violation of CGI spec? SERVER_SOFTWARE(%s)", vorig, exp, env_hdr, STRNULLCHKQ(getenv("SERVER_SOFTWARE")));
1553 return 0;
1554 }
1555 len = strlen(val);
1556 if (out + len > lim) {
1557 ERR("TOO LONG: VPATH or VURL(%s) %s expansion specified env(%s) val(%s) does not fit, missing %ld bytes. SERVER_SOFTWARE(%s)", vorig, exp, env_hdr, val, (long)(lim - (out + len)), STRNULLCHKQ(getenv("SERVER_SOFTWARE")));
1558 return 0;
1559 }
1560
1561 /* Squash suspicious */
1562
1563 for (; *val; ++val, ++out)
1564 if (!squash_type && IN_RANGE(*val, 'A', 'Z')) {
1565 *out = *val - ('A' - 'a'); /* lowercase host names */
1566 } else if (IN_RANGE(*val, 'a', 'z') || IN_RANGE(*val, '0', '9') || ONE_OF_2(*val, '.', '-')) {
1567 *out = *val;
1568 } else if (squash_type == 1 && ONE_OF_5(*val, '/', ':', '?', '&', '=')) {
1569 *out = *val;
1570 } else {
1571 *out = '_';
1572 }
1573 return len;
1574 }
1575
1576 /*() Expand percent expansions as found in VPATH and VURL
1577 * squash_type: 0=VPATH, 1=VURL.
1578 * See CGI specification for environment variables such as
1579 * %h expands to HTTP_HOST (from Host header, e.g. Host: sp.foo.bar or Host: sp.foo.bar:8443)
1580 * %s expands to SCRIPT_NAME
1581 * %d expands to directory portion of SCRIPT_NAME
1582 */
1583
1584 /* Called by: zxid_parse_vpath, zxid_parse_vurl */
zxid_expand_percent(char * vorig,char * out,char * lim,int squash_type)1585 static char* zxid_expand_percent(char* vorig, char* out, char* lim, int squash_type)
1586 {
1587 int len;
1588 char* x;
1589 char* p;
1590 char* val;
1591 --lim;
1592 for (p = vorig; *p && out < lim; ++p) {
1593 if (*p != '%') {
1594 *out++ = *p;
1595 continue;
1596 }
1597 switch (*++p) {
1598 case 'a':
1599 val = getenv("SERVER_PORT");
1600 if (!val)
1601 val = "";
1602 if (!memcmp(val, "80", MIN(strlen(val), 2)) || !memcmp(val, "88", MIN(strlen(val), 2)))
1603 x = squash_type?"http://":"http_";
1604 else
1605 x = squash_type?"https://":"https_";
1606 if (out + strlen(x) >= lim)
1607 goto toobig;
1608 strcpy(out, x);
1609 out += strlen(out);
1610 break;
1611 case 'h': out += zxid_eval_squash_env(vorig, "%h", "HTTP_HOST", out, lim, squash_type); break;
1612 case 'P':
1613 val = getenv("SERVER_PORT");
1614 if (!val)
1615 val = "";
1616 if (!strcmp(val, "443") || !strcmp(val, "80"))
1617 break; /* omit default ports */
1618 if (out >= lim)
1619 goto toobig;
1620 *out++ = ':'; /* colon in front of port, e.g. :8080 */
1621 /* fall thru */
1622 case 'p': out += zxid_eval_squash_env(vorig,"%p", "SERVER_PORT", out, lim, squash_type); break;
1623 case 's': out += zxid_eval_squash_env(vorig,"%s", "SCRIPT_NAME", out, lim, squash_type); break;
1624 case 'd':
1625 len = zxid_eval_squash_env(vorig, "%d", "SCRIPT_NAME", out, lim, squash_type);
1626 for (out += len; len && out[-1] != '/'; --out, --len) ;
1627 break;
1628 case '%': *out++ = '%'; break;
1629 default:
1630 ERR("VPATH or VURL(%s): Syntactically wrong percent expansion character(%c) 0x%x, ignored", vorig, p[-1], p[-1]);
1631 }
1632 }
1633 *out = 0;
1634 return out;
1635 toobig:
1636 ERR("VPATH or VURL(%s) extrapolation does not fit in buffer", vorig);
1637 *out = 0;
1638 return out;
1639 }
1640
1641 /*(-) Convert, in place, $ to & as needed for WSC_LOCALPDP_PLEDGE */
1642
1643 /* Called by: zxid_parse_conf_raw x2 */
zxid_dollar_to_amp(char * p)1644 static char* zxid_dollar_to_amp(char* p)
1645 {
1646 char* ret = p;
1647 for (p = strchr(p, '$'); p; p = strchr(p, '$'))
1648 *p = '&';
1649 return ret;
1650 }
1651
1652 /*() Parse VPATH (virtual host) related config file.
1653 * If the file VPATHzxid.conf does not exist (note that the specified
1654 * VPATH usually ends in a slash ("/")), the PATH is not changed.
1655 * Effectively unconfigured VPATHs are handled by the default PATH. */
1656
1657 /* Called by: zxid_parse_conf_raw */
zxid_parse_vpath(zxid_conf * cf,char * vpath)1658 static int zxid_parse_vpath(zxid_conf* cf, char* vpath)
1659 {
1660 char newpath[PATH_MAX];
1661 char *np, *lim;
1662
1663 DD("VPATH inside file(%.*s) %d new(%s)", cf->cpath_len, cf->cpath, cf->cpath_supplied, vpath);
1664 if (cf->cpath_supplied && !memcmp(cf->cpath, vpath, cf->cpath_len)
1665 || cf->cpath_supplied > ZXID_PATH_MAX_RECURS_EXPAND_DEPTH) {
1666 D("Skipping VPATH inside file(%.*s) path_supplied=%d", cf->cpath_len, cf->cpath, cf->cpath_supplied);
1667 return 0;
1668 }
1669
1670 /* Check for relative path and prepend PATH if needed. */
1671
1672 np = newpath;
1673 lim = newpath + sizeof(newpath);
1674
1675 if (*vpath != '/') {
1676 if (cf->cpath_len > lim-np) {
1677 ERR("TOO LONG: CPATH(%.*s) len=%d does not fit in vpath buffer size=%ld", cf->cpath_len, cf->cpath, cf->cpath_len, (long)(lim-np));
1678 return 0;
1679 }
1680 memcpy(np, cf->cpath, cf->cpath_len);
1681 np += cf->cpath_len;
1682 }
1683
1684 zxid_expand_percent(vpath, np, lim, 0);
1685 if (--zxid_suppress_vpath_warning > 0) {
1686 INFO("VPATH(%s) alters CPATH(%s) to new CPATH(%s)", vpath, cf->cpath, newpath);
1687 }
1688 zxid_parse_conf_path_raw(cf, zx_dup_cstr(cf->ctx, newpath), 1);
1689 return 1;
1690 }
1691
1692 /*() Parse VURL (virtual host) to URL */
1693
1694 /* Called by: zxid_parse_conf_raw */
zxid_parse_vurl(zxid_conf * cf,char * vurl)1695 static int zxid_parse_vurl(zxid_conf* cf, char* vurl)
1696 {
1697 char newurl[PATH_MAX];
1698 zxid_expand_percent(vurl, newurl, newurl + sizeof(newurl), 1);
1699 if (--zxid_suppress_vpath_warning > 0) {
1700 INFO("VURL(%s) alters BURL(%s) to new BURL(%s)", vurl, cf->burl, newurl);
1701 }
1702 cf->burl = zx_dup_cstr(cf->ctx, newurl);
1703 return 1;
1704 }
1705
1706 /*(i) Parse partial configuration specifications, such as may occur
1707 * on command line or in a configuration file.
1708 *
1709 * Generally you should
1710 * call first zxid_new_conf(), or at least zxid_init_conf(), and
1711 * then call this function to apply modifications over the defaults.
1712 * The configuration options are named after the config options
1713 * that appear in zxidconf.h, except that prefix ZXID_ is removed.
1714 *
1715 * N.B. The qs memory must come from static or permanently allocated
1716 * source as direct pointers to inside it will be taken. The memory
1717 * will be modified to add nul terminations. Do not use stack based
1718 * memory like local variable (unless local of main()).
1719 * Do consider strdup() or similar before calling this function.
1720 *
1721 * cf:: Previously allocated and initialized ZXID configuration object
1722 * qs_len:: Query String length. -1 means nul terminated C string
1723 * qs:: Configuration data in extended CGI Query String format. "extended"
1724 * means newline can be used as separator, in addition to ampersand ("&")
1725 * This argument is modified in place, changing separators to nul string
1726 * terminations and performing URL decoding.
1727 * return:: -1 on failure, 0 on success */
1728
1729 /* Called by: zxid_conf_to_cf_len x4, zxid_parse_conf, zxid_parse_conf_path_raw */
zxid_parse_conf_raw(zxid_conf * cf,int qs_len,char * qs)1730 int zxid_parse_conf_raw(zxid_conf* cf, int qs_len, char* qs)
1731 {
1732 int i;
1733 int lineno;
1734 char *p, *n, *v;
1735 if (qs_len != -1 && qs[qs_len]) { /* *** access one past end of buffer */
1736 ERR("LIMITATION: The configuration strings MUST be nul terminated (even when length is supplied explicitly). qs_len=%d qs(%.*s)", qs_len, qs_len, qs);
1737 return -1;
1738 }
1739 for (lineno = 1; qs && *qs; ++lineno) {
1740 qs = zxid_qs_nv_scan(qs, &n, &v, 1);
1741 if (!n) {
1742 if (!qs)
1743 break;
1744 n = "NULL_NAME_ERR";
1745 }
1746
1747 if (!strcmp(n, ZXID_PATH_OPT)) goto path;
1748
1749 switch (n[0]) {
1750 case 'A': /* AUTHN_REQ_SIGN, ACT, AUDIENCE_FATAL, AFTER_SLOP */
1751 if (!strcmp(n, "AUTO_CERT")) { SCAN_INT(v, cf->auto_cert); break; }
1752 if (!strcmp(n, "AUTHN_REQ_SIGN")) { SCAN_INT(v, cf->authn_req_sign); break; }
1753 if (!strcmp(n, "ACT")) { SCAN_INT(v, cf->log_act); break; }
1754 if (!strcmp(n, "ACT_IN_ERR")) { SCAN_INT(v, cf->log_err_in_act); break; }
1755 if (!strcmp(n, "AUDIENCE_FATAL")) { SCAN_INT(v, cf->audience_fatal); break; }
1756 if (!strcmp(n, "AFTER_SLOP")) { SCAN_INT(v, cf->after_slop); break; }
1757 if (!strcmp(n, "ANON_OK")) { cf->anon_ok = v; D("anon_ok(%s)", cf->anon_ok); break; }
1758 if (!strcmp(n, "AN_PAGE")) { cf->an_page = v; break; }
1759 if (!strcmp(n, "AN_TEMPL_FILE")) { cf->an_templ_file = v; break; }
1760 if (!strcmp(n, "AN_TEMPL")) { cf->an_templ = v; break; }
1761 if (!strcmp(n, "ATSEL_PAGE")) { cf->atsel_page = v; break; }
1762 if (!strcmp(n, "ATTRSRC")) { cf->attrsrc = zxid_load_atsrc(cf, cf->attrsrc, v); break; }
1763 if (!strcmp(n, "A7NTTL")) { SCAN_INT(v, cf->a7nttl); break; }
1764 if (!strcmp(n, "AS_ENA")) { SCAN_INT(v, cf->as_ena); break; }
1765 if (!strcmp(n, "AZ_OPT")) { SCAN_INT(v, cf->az_opt); break; }
1766 if (!strcmp(n, "AZ_FAIL_MODE")) { SCAN_INT(v, cf->az_fail_mode); break; }
1767 goto badcf;
1768 case 'B': /* BEFORE_SLOP */
1769 if (!strcmp(n, "BURL")) { cf->burl = v; cf->fedusername_suffix = zxid_grab_domain_name(cf, cf->burl); break; }
1770 if (!strcmp(n, "BEFORE_SLOP")) { SCAN_INT(v, cf->before_slop); break; }
1771 if (!strcmp(n, "BOOTSTRAP_LEVEL")) { SCAN_INT(v, cf->bootstrap_level); break; }
1772 if (!strcmp(n, "BARE_URL_ENTITYID")) { SCAN_INT(v, cf->bare_url_entityid); break; }
1773 if (!strcmp(n, "BUTTON_URL")) {
1774 if (!strstr(v, "saml2_icon_468x60") && !strstr(v, "saml2_icon_150x60") && !strstr(v, "saml2_icon_16x16"))
1775 ERR("BUTTON_URL has to specify button image and the image filename MUST contain substring \"saml2_icon\" in it (see symlabs-saml-displayname-2008.pdf submitted to OASIS SSTC). Furthermore, this substring must specify the size, which must be one of 468x60, 150x60, or 16x16. Acceptable substrings are are \"saml2_icon_468x60\", \"saml2_icon_150x60\", \"saml2_icon_16x16\", e.g. \"https://your-domain.com/your-brand-saml2_icon_150x60.png\". Current value(%s) may be used despite this error. Only last acceptable specification of BUTTON_URL will be used. (conf line %d", v, lineno);
1776 if (!cf->button_url || strstr(v, cf->pref_button_size)) /* Pref overrides previous. */
1777 cf->button_url = v;
1778 break;
1779 }
1780 if (!strcmp(n, "BUS_URL")) { cf->bus_url = zxid_load_bus_url(cf, cf->bus_url, v); break; }
1781 if (!strcmp(n, "BUS_PW")) { cf->bus_pw = v; break; }
1782 if (!strcmp(n, "BACKWARDS_COMPAT_ENA")) { SCAN_INT(v, cf->backwards_compat_ena); break; }
1783 if (!strcmp(n, "BLOBSIG_DIGEST_ALGO")) { cf->blobsig_digest_algo = v; break; }
1784 goto badcf;
1785 case 'C': /* CDC_URL, CDC_CHOICE */
1786 if (!strcmp(n, "CPATH")) goto path;
1787 if (!strcmp(n, "CDC_URL")) { cf->cdc_url = v; break; }
1788 if (!strcmp(n, "CDC_CHOICE")) { SCAN_INT(v, cf->cdc_choice); break; }
1789 if (!strcmp(n, "CONTACT_ORG")) { cf->contact_org = v; break; }
1790 if (!strcmp(n, "CONTACT_NAME")) { cf->contact_name = v; break; }
1791 if (!strcmp(n, "CONTACT_EMAIL")) { cf->contact_email = v; break; }
1792 if (!strcmp(n, "CONTACT_TEL")) { cf->contact_tel = v; break; }
1793 if (!strcmp(n, "COUNTRY")) { cf->country = v; break; }
1794 if (!strcmp(n, "CANON_INOPT")) { SCAN_INT(v, cf->canon_inopt); if (cf->ctx) cf->ctx->canon_inopt = cf->canon_inopt; break; }
1795 if (!strcmp(n, "CPN_ENA")) { SCAN_INT(v, cf->cpn_ena); break; }
1796 goto badcf;
1797 case 'D': /* DUP_A7N_FATAL, DUP_MSG_FATAL */
1798 if (!strcmp(n, "DEFAULTQS")) { cf->defaultqs = v; break; }
1799 if (!strcmp(n, "DUP_A7N_FATAL")) { SCAN_INT(v, cf->dup_a7n_fatal); break; }
1800 if (!strcmp(n, "DUP_MSG_FATAL")) { SCAN_INT(v, cf->dup_msg_fatal); break; }
1801 if (!strcmp(n, "DI_ALLOW_CREATE")) { cf->di_allow_create = *v; break; }
1802 if (!strcmp(n, "DI_NID_FMT")) { SCAN_INT(v, cf->di_nid_fmt); break; }
1803 if (!strcmp(n, "DI_A7N_ENC")) { SCAN_INT(v, cf->di_a7n_enc); break; }
1804 if (!strcmp(n, "DEBUG")) { SCAN_INT(v, errmac_debug); INFO("errmac_debug:%d", errmac_debug); break; }
1805 if (!strcmp(n, "DEBUG_LOG")) { zxid_set_opt_cstr(cf, 6, v); break; }
1806 if (!strcmp(n, "D")) { D("D=%s (conf line %d)", v, lineno); break; }
1807 if (!strcmp(n, "DIE")) { ERR("DIE=%s (conf line %d)", v, lineno); DIE_ACTION(1); break; }
1808 goto badcf;
1809 case 'E': /* ERR, ERR_IN_ACT */
1810 if (!strcmp(n, "ERR")) { SCAN_INT(v, cf->log_err); break; }
1811 if (!strcmp(n, "ERR_IN_ACT")) { SCAN_INT(v, cf->log_err_in_act); break; }
1812 if (!strcmp(n, "ENC_TAIL_OPT")) { SCAN_INT(v, cf->enc_tail_opt); break; }
1813 if (!strcmp(n, "ENCKEY_OPT")) { SCAN_INT(v, cf->enckey_opt); break; }
1814 if (!strcmp(n, "ERR_PAGE")) { cf->err_page = v; break; }
1815 if (!strcmp(n, "ERR_TEMPL_FILE")) { cf->err_templ_file = v; break; }
1816 if (!strcmp(n, "ERR_TEMPL")) { cf->err_templ = v; break; }
1817 if (!strcmp(n, "ECHO")) { INFO("ECHO=%s (conf line %d)", v, lineno); break; }
1818 goto badcf;
1819 case 'F':
1820 if (!strcmp(n, "FEDUSERNAME_SUFFIX")) { cf->fedusername_suffix = v; break; }
1821 goto badcf;
1822 case 'I': /* ISSUE_A7N, ISSUE_MSG */
1823 if (!strcmp(n, "ISSUE_A7N")) { SCAN_INT(v, cf->log_issue_a7n); break; }
1824 if (!strcmp(n, "ISSUE_MSG")) { SCAN_INT(v, cf->log_issue_msg); break; }
1825 if (!strcmp(n, "ISSUE_AUTHNCTX")) { cf->issue_authnctx = zxid_load_cstr_list(cf, cf->issue_authnctx, v); break; }
1826 #if 0
1827 if (!strcmp(n, "IDP_SEL_START")) { cf->idp_sel_start = v; break; }
1828 if (!strcmp(n, "IDP_SEL_NEW_IDP")) { cf->idp_sel_new_idp = v; break; }
1829 if (!strcmp(n, "IDP_SEL_OUR_EID")) { cf->idp_sel_our_eid = v; break; }
1830 if (!strcmp(n, "IDP_SEL_TECH_USER")) { cf->idp_sel_tech_user =v; break; }
1831 if (!strcmp(n, "IDP_SEL_TECH_SITE")) { cf->idp_sel_tech_site =v; break; }
1832 if (!strcmp(n, "IDP_SEL_FOOTER")) { cf->idp_sel_footer = v; break; }
1833 if (!strcmp(n, "IDP_SEL_END")) { cf->idp_sel_end = v; break; }
1834 #endif
1835 if (!strcmp(n, "IDP_SEL_PAGE")) { cf->idp_sel_page = v; break; }
1836 if (!strcmp(n, "IDP_SEL_TEMPL_FILE")) { cf->idp_sel_templ_file = v; break; }
1837 if (!strcmp(n, "IDP_SEL_TEMPL")) { cf->idp_sel_templ = v; break; }
1838 if (!strcmp(n, "IDP_ENA")) { SCAN_INT(v, cf->idp_ena); break; }
1839 if (!strcmp(n, "IDP_PXY_ENA")) { SCAN_INT(v, cf->idp_pxy_ena); break; }
1840 if (!strcmp(n, "IMPS_ENA")) { SCAN_INT(v, cf->imps_ena); break; }
1841 if (!strcmp(n, "IDP_PREF_ACS_BINDING")) { cf->idp_pref_acs_binding = v; break; }
1842 if (!strcmp(n, "IDPATOPT")) { SCAN_INT(v, cf->idpatopt); break; }
1843 if (!strcmp(n, "IDP_LIST_METH")) { SCAN_INT(v, cf->idp_list_meth); break; }
1844 if (!strcmp(n, "INMAP")) { cf->inmap = zxid_load_map(cf, cf->inmap, v); break; }
1845 if (!strcmp(n, "INFO")) { INFO("INFO=%s (conf line %d)", v, lineno); break; }
1846 if (!strcmp(n, "INCLUDE")) { zxid_parse_inc(cf, v, 1); break; }
1847 goto badcf;
1848 case 'L': /* LEVEL (log level) */
1849 if (!strcmp(n, "LEVEL")) { SCAN_INT(v, cf->log_level); break; }
1850 if (!strcmp(n, "LOGUSER")) { SCAN_INT(v, cf->loguser); break; }
1851 if (!strcmp(n, "LOCALPDP_ROLE_PERMIT")) { cf->localpdp_role_permit = zxid_load_cstr_list(cf, cf->localpdp_role_permit, v); break; }
1852 if (!strcmp(n, "LOCALPDP_ROLE_DENY")) { cf->localpdp_role_deny = zxid_load_cstr_list(cf, cf->localpdp_role_deny, v); break; }
1853 if (!strcmp(n, "LOCALPDP_IDPNID_PERMIT")) { cf->localpdp_idpnid_permit = zxid_load_cstr_list(cf, cf->localpdp_idpnid_permit, v); break; }
1854 if (!strcmp(n, "LOCALPDP_IDPNID_DENY")) { cf->localpdp_idpnid_deny = zxid_load_cstr_list(cf, cf->localpdp_idpnid_deny, v); break; }
1855 if (!strcmp(n, "LOAD_COT_CACHE")) { cf->load_cot_cache = v; break; }
1856 if (!strcmp(n, "LOCALITY")) { cf->locality = v; break; }
1857 goto badcf;
1858 case 'M': /* MD_FETCH, MD_POPULATE_CACHE, MD_CACHE_FIRST, MD_CACHE_LAST */
1859 if (!strcmp(n, "MANDATORY_ATTR")) { cf->mandatory_attr = v; break; }
1860 if (!strcmp(n, "MD_FETCH")) { SCAN_INT(v, cf->md_fetch); break; }
1861 if (!strcmp(n, "MD_POPULATE_CACHE")) { SCAN_INT(v, cf->md_populate_cache); break; }
1862 if (!strcmp(n, "MD_CACHE_FIRST")) { SCAN_INT(v, cf->md_cache_first); break; }
1863 if (!strcmp(n, "MD_CACHE_LAST")) { SCAN_INT(v, cf->md_cache_last); break; }
1864 if (!strcmp(n, "MD_AUTHORITY_ENA")) { SCAN_INT(v, cf->md_authority_ena); break; }
1865 if (!strcmp(n, "MD_AUTHORITY")) { cf->md_authority = v; break; }
1866 if (!strcmp(n, "MGMT_START")) { cf->mgmt_start = v; break; }
1867 if (!strcmp(n, "MGMT_LOGOUT")) { cf->mgmt_logout = v; break; }
1868 if (!strcmp(n, "MGMT_DEFED")) { cf->mgmt_defed = v; break; }
1869 if (!strcmp(n, "MGMT_FOOTER")) { cf->mgmt_footer = v; break; }
1870 if (!strcmp(n, "MGMT_END")) { cf->mgmt_end = v; break; }
1871 if (!strcmp(n, "MSG_SIG_OK")) { SCAN_INT(v, cf->msg_sig_ok); break; }
1872 if (!strcmp(n, "MAX_SOAP_RETRY")) { SCAN_INT(v, cf->max_soap_retry); break; }
1873 if (!strcmp(n, "MOD_SAML_ATTR_PREFIX")) { cf->mod_saml_attr_prefix = v; break; }
1874
1875 goto badcf;
1876 case 'N': /* NAMEID_ENC, NICE_NAME, NOSIG_FATAL */
1877 if (!strcmp(n, "NAMEID_ENC")) { SCAN_INT(v, cf->nameid_enc); break; }
1878 if (!strcmp(n, "NICE_NAME")) { cf->nice_name = v; break; }
1879 if (!strcmp(n, "NON_STANDARD_ENTITYID")) { cf->non_standard_entityid = v; D("NON_STANDARD_ENTITYID set(%s)", v); break; }
1880 if (!strcmp(n, "NOSIG_FATAL")) { SCAN_INT(v, cf->nosig_fatal); break; }
1881 if (!strcmp(n, "NOTIMESTAMP_FATAL")) { SCAN_INT(v, cf->notimestamp_fatal); break; }
1882 if (!strcmp(n, "NEED")) { cf->need = zxid_load_need(cf, cf->need, v); break; }
1883 if (!strcmp(n, "NEW_USER_PAGE")) { cf->new_user_page = v; break; }
1884 goto badcf;
1885 case 'O': /* OUTMAP */
1886 if (!strcmp(n, "OUTMAP")) { cf->outmap = zxid_load_map(cf, cf->outmap, v); break; }
1887 if (!strcmp(n, "ORG_NAME")) { cf->org_name = v; break; }
1888 if (!strcmp(n, "ORG_URL")) {
1889 ERR("Discontinued configuration option ORG_URL supplied. This option has been deleted. Use BUTTON_URL instead, but note that the URL has to specify button image instead of home page (the image filename MUST contain substring \"saml2_icon\" in it). Current value(%s) (conf line %d)", v, lineno);
1890 cf->button_url = v;
1891 break;
1892 }
1893 if (!strcmp(n, "OAZ_JWT_SIGENC_ALG")) { cf->oaz_jwt_sigenc_alg = *v; break; }
1894 if (!strcmp(n, "OPT_INCLUDE")) { zxid_parse_inc(cf, v, 0); break; }
1895 if (!strcmp(n, "OPTIONAL_LOGIN_PAT")) { cf->optional_login_pat = v; D("optional_login_pat(%s)", cf->optional_login_pat); break; }
1896 goto badcf;
1897 case 'P': /* PATH (e.g. /var/zxid) */
1898 DD("PATH maybe n(%s)=v(%s)", n, v);
1899 if (!strcmp(n, "PATH")) {
1900 path:
1901 DD("CPATH inside file(%.*s) %d new(%s)", cf->cpath_len, cf->cpath, cf->cpath_supplied, v);
1902 if (cf->cpath_supplied && !memcmp(cf->cpath, v, cf->cpath_len)
1903 || cf->cpath_supplied > ZXID_PATH_MAX_RECURS_EXPAND_DEPTH) {
1904 D("Skipping CPATH inside file(%.*s) cpath_supplied=%d", cf->cpath_len, cf->cpath, cf->cpath_supplied);
1905 break;
1906 }
1907 zxid_parse_conf_path_raw(cf, v, 0);
1908 break;
1909 }
1910 if (!strcmp(n, "PDP_ENA")) { SCAN_INT(v, cf->pdp_ena); break; }
1911 if (!strcmp(n, "PDP_URL")) { cf->pdp_url = v; break; }
1912 if (!strcmp(n, "PDP_CALL_URL")) { cf->pdp_call_url = v; break; }
1913 if (!strcmp(n, "PEPMAP")) { cf->pepmap = zxid_load_map(cf, cf->pepmap, v); break; }
1914 if (!strcmp(n, "PEPMAP_RQOUT")) { cf->pepmap_rqout = zxid_load_map(cf, cf->pepmap_rqout, v); break; }
1915 if (!strcmp(n, "PEPMAP_RQIN")) { cf->pepmap_rqin = zxid_load_map(cf, cf->pepmap_rqin, v); break; }
1916 if (!strcmp(n, "PEPMAP_RSOUT")) { cf->pepmap_rsout = zxid_load_map(cf, cf->pepmap_rsout, v); break; }
1917 if (!strcmp(n, "PEPMAP_RSIN")) { cf->pepmap_rsin = zxid_load_map(cf, cf->pepmap_rsin, v); break; }
1918 if (!strcmp(n, "POST_A7N_ENC")) { SCAN_INT(v, cf->post_a7n_enc); break; }
1919 if (!strcmp(n, "POST_TEMPL_FILE")) { cf->post_templ_file = v; break; }
1920 if (!strcmp(n, "POST_TEMPL")) { cf->post_templ = v; break; }
1921 if (!strcmp(n, "PREF_BUTTON_SIZE")) {
1922 if (!strstr(v, "468x60") && !strstr(v, "150x60") && !strstr(v, "16x16"))
1923 ERR("PREF_BUTTON_SIZE should specify one of the standard button image sizes, such as 468x60, 150x60, or 16x16 (and the image filename MUST contain substring \"saml2_icon\" in it, see symlabs-saml-displayname-2008.pdf submitted to OASIS SSTC). Current value(%s) is used despite this error. (conf line %d", v, lineno);
1924 cf->pref_button_size = v;
1925 break;
1926 }
1927 if (!strcmp(n, "PTM_COOKIE_NAME")) { cf->ptm_cookie_name = (!v[0] || v[0]=='0' && !v[1]) ? 0 : v; break; }
1928 if (!strcmp(n, "PRAGMA")) { D("PRAGMA(%s)", v); break; }
1929 goto badcf;
1930 case 'R': /* RELY_A7N, RELY_MSG */
1931 if (!strcmp(n, "REDIRECT_HACK_IMPOSED_URL")) { cf->redirect_hack_imposed_url = v; break; }
1932 if (!strcmp(n, "REDIRECT_HACK_ZXID_URL")) {
1933 cf->redirect_hack_zxid_url = v;
1934 p = strchr(v, '?');
1935 if (p) {
1936 *p = 0;
1937 cf->redirect_hack_zxid_qs = p+1;
1938 }
1939 break;
1940 }
1941 if (!strcmp(n, "REDIR_TO_CONTENT")) { SCAN_INT(v, cf->redir_to_content); break; }
1942 if (!strcmp(n, "REMOTE_USER_ENA")) { SCAN_INT(v, cf->remote_user_ena); break; }
1943 if (!strcmp(n, "RELY_A7N")) { SCAN_INT(v, cf->log_rely_a7n); break; }
1944 if (!strcmp(n, "RELY_MSG")) { SCAN_INT(v, cf->log_rely_msg); break; }
1945 if (!strcmp(n, "REQUIRED_AUTHNCTX")) {
1946 /* Count how many */
1947 for (i=2, p=v; *p; ++p)
1948 if (*p == '$')
1949 ++i;
1950 cf->required_authnctx = zx_zalloc(cf->ctx, sizeof(char*) * i);
1951 /* Populate array with strings, stomping the separator char $ to nul termination. */
1952 for (i=0, p=v; *p; ++i) {
1953 cf->required_authnctx[i] = p;
1954 p = strchr(p, '$');
1955 if (!p)
1956 break;
1957 *p++ = 0;
1958 }
1959 break;
1960 }
1961 if (!strcmp(n, "RECOVER_PASSWD")) { cf->recover_passwd = v; break; }
1962 if (!strcmp(n, "RELTO_FATAL")) { SCAN_INT(v, cf->relto_fatal); break; }
1963 if (!strcmp(n, "RCPT")) { SCAN_INT(v, cf->bus_rcpt); break; }
1964 if (!strcmp(n, "REM")) { /* no-op */ break; }
1965 goto badcf;
1966 case 'S': /* SES_ARCH_DIR, SIGFAIL_IS_ERR, SIG_FATAL */
1967 if (!strcmp(n, "SES_ARCH_DIR")) { cf->ses_arch_dir = (!v[0] || v[0]=='0' && !v[1]) ? 0 : v; break; }
1968 if (!strcmp(n, "SES_COOKIE_NAME")) { cf->ses_cookie_name = (!v[0] || v[0]=='0' && !v[1]) ? 0 : v; break; }
1969 if (!strcmp(n, "SIGFAIL_IS_ERR")) { SCAN_INT(v, cf->log_sigfail_is_err); break; }
1970 if (!strcmp(n, "SIG_FATAL")) { SCAN_INT(v, cf->sig_fatal); break; }
1971 if (!strcmp(n, "SSO_SIGN")) { SCAN_INT(v, cf->sso_sign); break; }
1972 if (!strcmp(n, "SSO_SOAP_SIGN")) { SCAN_INT(v, cf->sso_soap_sign); break; }
1973 if (!strcmp(n, "SSO_SOAP_RESP_SIGN")) { SCAN_INT(v, cf->sso_soap_resp_sign); break; }
1974 if (!strcmp(n, "SHOW_CONF")) { SCAN_INT(v, cf->show_conf); break; }
1975 if (!strcmp(n, "SHOW_TECH")) { SCAN_INT(v, cf->show_tech); break; }
1976 if (!strcmp(n, "STATE")) { cf->state = v; break; }
1977 if (!strcmp(n, "SSO_PAT")) { cf->sso_pat = v; break; }
1978 if (!strcmp(n, "SOAP_ACTION_HDR")) { cf->soap_action_hdr = v; break; }
1979 if (!strcmp(n, "SAMLSIG_DIGEST_ALGO")) { cf->samlsig_digest_algo = v; break; }
1980 goto badcf;
1981 case 'T': /* TIMEOUT_FATAL */
1982 if (!strcmp(n, "TIMEOUT_FATAL")) { SCAN_INT(v, cf->timeout_fatal); break; }
1983 if (!strcmp(n, "TIMESKEW")) { SCAN_INT(v, cf->timeskew); break; }
1984 if (!strcmp(n, "TRUSTPDP_URL")) { cf->trustpdp_url = v; break; }
1985 goto badcf;
1986 case 'U': /* URL, USER_LOCAL */
1987 if (!strcmp(n, "URL")) { cf->burl = v; cf->fedusername_suffix = zxid_grab_domain_name(cf, cf->burl); break; }
1988 if (!strcmp(n, "USER_LOCAL")) { SCAN_INT(v, cf->user_local); break; }
1989 if (!strcmp(n, "UMA_PAT")) { cf->uma_pat = v; break; }
1990 if (!strcmp(n, "UNIX_GRP_AZ_MAP")) { cf->unix_grp_az_map = zxid_load_unix_grp_az_map(cf, cf->unix_grp_az_map, v); break; }
1991 goto badcf;
1992 case 'V': /* VALID_OPT */
1993 if (!strcmp(n, "VALID_OPT")) { SCAN_INT(v, cf->valid_opt); break; }
1994 if (!strcmp(n, "VPATH")) { zxid_parse_vpath(cf, v); break; }
1995 if (!strcmp(n, "VURL")) { zxid_parse_vurl(cf, v); break; }
1996 goto badcf;
1997 case 'W': /* WANT_SSO_A7N_SIGNED */
1998 if (!strcmp(n, "WANT")) { cf->want = zxid_load_need(cf, cf->want, v); break; }
1999 if (!strcmp(n, "WANT_SSO_A7N_SIGNED")) { SCAN_INT(v, cf->want_sso_a7n_signed); break; }
2000 if (!strcmp(n, "WANT_AUTHN_REQ_SIGNED")) { SCAN_INT(v, cf->want_authn_req_signed); break; }
2001 if (!strcmp(n, "WSC_SIGN")) { SCAN_INT(v, cf->wsc_sign); break; }
2002 if (!strcmp(n, "WSP_SIGN")) { SCAN_INT(v, cf->wsp_sign); break; }
2003 if (!strcmp(n, "WSPCGICMD")) { cf->wspcgicmd = v; break; }
2004 if (!strcmp(n, "WSP_NOSIG_FATAL")) { SCAN_INT(v, cf->wsp_nosig_fatal); break; }
2005 if (!strcmp(n, "WSC_LOCALPDP_OBL_PLEDGE")) { cf->wsc_localpdp_obl_pledge = zxid_dollar_to_amp(v); break; }
2006 if (!strcmp(n, "WSP_LOCALPDP_OBL_REQ")) { cf->wsp_localpdp_obl_req = zxid_load_obl_list(cf, cf->wsp_localpdp_obl_req, v); break; }
2007 if (!strcmp(n, "WSP_LOCALPDP_OBL_EMIT")) { cf->wsp_localpdp_obl_emit = zxid_dollar_to_amp(v); break; }
2008 if (!strcmp(n, "WSC_LOCALPDP_OBL_ACCEPT")) { cf->wsc_localpdp_obl_accept = zxid_load_obl_list(cf, cf->wsc_localpdp_obl_accept, v); break; }
2009 if (!strcmp(n, "WD")) { cf->wd = v; chdir(v); break; }
2010 if (!strcmp(n, "WSP_PAT")) { cf->wsp_pat = v; break; }
2011 if (!strcmp(n, "WSC_SOAP_CONTENT_TYPE")) { cf->wsc_soap_content_type = v; break; }
2012 if (!strcmp(n, "WSC_TO_HDR")) { cf->wsc_to_hdr = v; break; }
2013 if (!strcmp(n, "WSC_REPLYTO_HDR")) { cf->wsc_replyto_hdr = v; break; }
2014 if (!strcmp(n, "WSC_ACTION_HDR")) { cf->wsc_action_hdr = v; break; }
2015 if (!strcmp(n, "WARN")) { WARN("WARN=%s (conf line %d)", v, lineno); break; }
2016 goto badcf;
2017 case 'X': /* XASP_VERS */
2018 if (!strcmp(n, "XASP_VERS")) { cf->xasp_vers = v; break; }
2019 if (!strcmp(n, "XMLDSIG_SIG_METH")) { cf->xmldsig_sig_meth = v; break; }
2020 if (!strcmp(n, "XMLDSIG_DIGEST_ALGO")) { cf->xmldsig_digest_algo = v; break; }
2021 goto badcf;
2022 default:
2023 badcf:
2024 ERR("Unknown config option(%s) val(%s), ignored (conf line %d)", n, v, lineno);
2025 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "S", "BADCF", n, 0);
2026 }
2027 }
2028 return 0;
2029 }
2030
2031 /*() Wrapper with initial error checking for zxid_parse_conf_raw(), which see. */
2032
2033 /* Called by: opt x13, set_zxid_conf */
zxid_parse_conf(zxid_conf * cf,char * qs)2034 int zxid_parse_conf(zxid_conf* cf, char* qs)
2035 {
2036 if (!cf || !qs)
2037 return -1;
2038 return zxid_parse_conf_raw(cf, strlen(qs), qs);
2039 }
2040
2041 #endif
2042
2043 /*() Pretty print need or want chain.
2044 * *** leaks some ss and need nodes */
2045
2046 /* Called by: zxid_show_conf x2 */
zxid_show_need(zxid_conf * cf,struct zxid_need * np)2047 static struct zx_str* zxid_show_need(zxid_conf* cf, struct zxid_need* np)
2048 {
2049 struct zxid_attr* ap;
2050 struct zx_str* ss;
2051 struct zx_str* need = zx_dup_str(cf->ctx, "");
2052 for (; np; np = np->n) {
2053 ss = zx_dup_str(cf->ctx, "");
2054 for (ap = np->at; ap; ap = ap->n) {
2055 ss = zx_strf(cf->ctx, "%s,%.*s", STRNULLCHK(ap->name), ss->len, ss->s);
2056 }
2057 if (ss->len) { /* chop off last comma separator */
2058 ss->len -= 1;
2059 ss->s[ss->len] = 0;
2060 }
2061 need = zx_strf(cf->ctx, " attrs(%s)\n usage(%s)\n retent(%s)\n oblig(%s)\n ext(%s)$\n%.*s",
2062 ss->s, STRNULLCHK(np->usage), STRNULLCHK(np->retent),
2063 STRNULLCHK(np->oblig), STRNULLCHK(np->ext),
2064 need->len, need->s);
2065 ZX_FREE(cf->ctx, ss);
2066 }
2067 if (need->len) { /* chop off last dollar separator */
2068 need->len -= 2;
2069 need->s[need->len] = 0;
2070 }
2071 return need;
2072 }
2073
2074 /*() Pretty print map chain. */
2075
2076 /* Called by: zxid_show_conf x7 */
zxid_show_map(zxid_conf * cf,struct zxid_map * mp)2077 static struct zx_str* zxid_show_map(zxid_conf* cf, struct zxid_map* mp)
2078 {
2079 struct zx_str* inmap = zx_dup_str(cf->ctx, "");
2080 for (; mp; mp = mp->n) {
2081 inmap = zx_strf(cf->ctx, " rule=%d$ ns(%s)$ src(%s)$ dst(%s)$ ext(%s);\n%.*s", mp->rule, STRNULLCHK(mp->ns), STRNULLCHK(mp->src), STRNULLCHK(mp->dst), STRNULLCHK(mp->ext), inmap->len, inmap->s);
2082 }
2083 if (inmap->len) { /* chop off last semicolon separator */
2084 inmap->len -= 2;
2085 inmap->s[inmap->len] = 0;
2086 }
2087 return inmap;
2088 }
2089
2090
2091 /*() Pretty print cstr list as used in local PDP. */
2092
2093 /* Called by: zxid_show_conf x4 */
zxid_show_cstr_list(zxid_conf * cf,struct zxid_cstr_list * cp)2094 static struct zx_str* zxid_show_cstr_list(zxid_conf* cf, struct zxid_cstr_list* cp)
2095 {
2096 struct zx_str* ss = zx_dup_str(cf->ctx, "");
2097 for (; cp; cp = cp->n) {
2098 ss = zx_strf(cf->ctx, " %s,\n%.*s", STRNULLCHK(cp->s), ss->len, ss->s);
2099 }
2100 if (ss->len) { /* chop off last comma separator */
2101 ss->len -= 2;
2102 ss->s[ss->len] = 0;
2103 }
2104 return ss;
2105 }
2106
2107 /*() Pretty print bus_url list. */
2108
2109 /* Called by: zxid_show_conf */
zxid_show_bus_url(zxid_conf * cf,struct zxid_bus_url * cp)2110 static struct zx_str* zxid_show_bus_url(zxid_conf* cf, struct zxid_bus_url* cp)
2111 {
2112 struct zx_str* ss = zx_dup_str(cf->ctx, "");
2113 for (; cp; cp = cp->n) {
2114 ss = zx_strf(cf->ctx, " %s,\n%.*s", STRNULLCHK(cp->s), ss->len, ss->s);
2115 }
2116 if (ss->len) { /* chop off last comma separator */
2117 ss->len -= 2;
2118 ss->s[ss->len] = 0;
2119 }
2120 return ss;
2121 }
2122
2123 /*() Generate our SP CARML and return it as a string. */
2124
2125 /* Called by: opt x5, zxid_simple_show_conf */
zxid_show_conf(zxid_conf * cf)2126 struct zx_str* zxid_show_conf(zxid_conf* cf)
2127 {
2128 char* eid;
2129 char* p;
2130 struct zxid_attr* ap;
2131 struct zxid_atsrc* sp;
2132 struct zx_str* ss;
2133 struct zx_str* required_authnctx;
2134 struct zx_str* need;
2135 struct zx_str* want;
2136 struct zx_str* attrsrc;
2137 struct zx_str* bus_url;
2138 struct zx_str* inmap;
2139 struct zx_str* outmap;
2140 struct zx_str* pepmap;
2141 struct zx_str* pepmap_rqout;
2142 struct zx_str* pepmap_rqin;
2143 struct zx_str* pepmap_rsout;
2144 struct zx_str* pepmap_rsin;
2145 struct zx_str* localpdp_role_permit;
2146 struct zx_str* localpdp_role_deny;
2147 struct zx_str* localpdp_idpnid_permit;
2148 struct zx_str* localpdp_idpnid_deny;
2149 struct zx_str* issue_authnctx;
2150 struct zx_str* unix_grp_az_map;
2151 if (cf->log_level>0)
2152 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "W", "MYCONF", 0, 0);
2153
2154 if (!cf->show_conf) {
2155 return zx_strf(cf->ctx, "<title>Conf dump disabled</title><body bgcolor=white>Conf viewing disabled using SHOW_CONF=0 option.");
2156 }
2157
2158 /* N.B. The following way of "concatenating" strings leaks memory of the intermediate
2159 * results. We can't be bothered as the o=d is just a debug page. */
2160
2161 required_authnctx = zx_dup_str(cf->ctx, "");
2162 for (p = cf->required_authnctx ? *cf->required_authnctx:0; p; ++p) {
2163 required_authnctx = zx_strf(cf->ctx, " %s$\n%.*s", p, required_authnctx->len, required_authnctx->s);
2164 }
2165 if (required_authnctx->len) { /* chop off last dollar separator */
2166 required_authnctx->len -= 2;
2167 required_authnctx->s[required_authnctx->len] = 0;
2168 }
2169
2170 need = zxid_show_need(cf, cf->need);
2171 want = zxid_show_need(cf, cf->want);
2172
2173 attrsrc = zx_dup_str(cf->ctx, "");
2174 for (sp = cf->attrsrc; sp; sp = sp->n) {
2175 ss = zx_dup_str(cf->ctx, "");
2176 for (ap = sp->at; ap; ap = ap->n) {
2177 ss = zx_strf(cf->ctx, "%s,%.*s", STRNULLCHK(ap->name), ss->len, ss->s);
2178 }
2179 if (ss->len) { /* chop off last dollar separator */
2180 ss->len -= 1;
2181 ss->s[ss->len] = 0;
2182 }
2183 attrsrc = zx_strf(cf->ctx, " attrs(%s)\n ns(%s)\n weight(%s)\n burl(%s)\n aapml(%s)\n otherlim(%s)\n ext(%s)$\n%.*s", ss->s, STRNULLCHK(sp->ns), STRNULLCHK(sp->weight), STRNULLCHK(sp->url), STRNULLCHK(sp->aapml), STRNULLCHK(sp->otherlim), STRNULLCHK(sp->ext),
2184 attrsrc->len, attrsrc->s);
2185 }
2186 if (attrsrc->len) { /* chop off last dollar separator */
2187 attrsrc->len -= 2;
2188 attrsrc->s[attrsrc->len] = 0;
2189 }
2190
2191 bus_url = zxid_show_bus_url(cf, cf->bus_url);
2192
2193 inmap = zxid_show_map(cf, cf->inmap);
2194 outmap = zxid_show_map(cf, cf->outmap);
2195 pepmap = zxid_show_map(cf, cf->pepmap);
2196 pepmap_rqout = zxid_show_map(cf, cf->pepmap_rqout);
2197 pepmap_rqin = zxid_show_map(cf, cf->pepmap_rqin);
2198 pepmap_rsout = zxid_show_map(cf, cf->pepmap_rsout);
2199 pepmap_rsin = zxid_show_map(cf, cf->pepmap_rsin);
2200
2201 localpdp_role_permit = zxid_show_cstr_list(cf, cf->localpdp_role_permit);
2202 localpdp_role_deny = zxid_show_cstr_list(cf, cf->localpdp_role_deny);
2203 localpdp_idpnid_permit = zxid_show_cstr_list(cf, cf->localpdp_idpnid_permit);
2204 localpdp_idpnid_deny = zxid_show_cstr_list(cf, cf->localpdp_idpnid_deny);
2205
2206 issue_authnctx = zxid_show_cstr_list(cf, cf->issue_authnctx);
2207
2208 unix_grp_az_map = zxid_show_map(cf, cf->unix_grp_az_map);
2209
2210 eid = zxid_my_ent_id_cstr(cf);
2211
2212 return zx_strf(cf->ctx,
2213 "<title>Conf for %s</title><body bgcolor=white><h1>Conf for %s</h1>"
2214 "<p>Please see config file in %s" ZXID_CONF_FILE ", and documentation in zxid-conf.pd and zxidconf.h\n"
2215 "<p>[ <a href=\"?o=B\">Metadata</a> | <a href=\"?o=c\">CARML</a> | <a href=\"?o=d\">This Conf Dump</a> ]\n"
2216 "<p>Version: R" ZXID_REL " (" ZXID_COMPILE_DATE ")\n"
2217
2218 "<pre>"
2219 "DEBUG=0x%x\n"
2220 "CPATH=%s\n"
2221 "BURL=%s\n"
2222 "AFFILIATION=%s\n"
2223 "NICE_NAME=%s\n"
2224 "BUTTON_URL=%s\n"
2225 "PREF_BUTTON_SIZE=%s\n"
2226 "ORG_NAME=%s\n"
2227 "LOCALITY=%s\n"
2228 "STATE=%s\n"
2229 "COUNTRY=%s\n"
2230 "CONTACT_ORG=%s\n"
2231 "CONTACT_NAME=%s\n"
2232 "CONTACT_EMAIL=%s\n"
2233 "CONTACT_TEL=%s\n"
2234 "FEDUSERNAME_SUFFIX=%s\n"
2235 "#ZXID_CONF_FILE_ENA=%d (compile)\n"
2236 "#ZXID_CONF_FLAG=%d (compile)\n"
2237 "NON_STANDARD_ENTITYID=%s\n"
2238 "REDIRECT_HACK_IMPOSED_URL=%s\n"
2239 "REDIRECT_HACK_ZXID_URL=%s\n"
2240 "REDIRECT_HACK_ZXID_QS=%s\n"
2241 "DEFAULTQS=%s\n"
2242 "WSP_PAT=%s\n"
2243 "UMA_PAT=%s\n"
2244 "SSO_PAT=%s\n"
2245 "WSC_SOAP_CONTENT_TYPE=%s\n"
2246 "WSC_TO_HDR=%s\n"
2247 "WSC_REPLYTO_HDR=%s\n"
2248 "WSC_ACTION_HDR=%s\n"
2249 "SOAP_ACTION_HDR=%s\n"
2250 "CDC_URL=%s\n"
2251 "CDC_CHOICE=%d\n"
2252
2253 "LOAD_COT_CACHE=%s\n"
2254 "MD_FETCH=%d\n"
2255 "MD_POPULATE_CACHE=%d\n"
2256 "MD_CACHE_FIRST=%d\n"
2257 "MD_CACHE_LAST=%d\n"
2258 "MD_AUTHORITY=%s\n"
2259
2260 "AUTO_CERT=%d\n"
2261 "AUTHN_REQ_SIGN=%d\n"
2262 "WANT_AUTHN_REQ_SIGNED=%d\n"
2263 "WANT_SSO_A7N_SIGNED=%d\n"
2264 "SSO_SOAP_SIGN=%d\n"
2265 "SSO_SOAP_RESP_SIGN=%d\n"
2266 "SSO_SIGN=%x\n"
2267 "WSC_SIGN=%x\n"
2268 "WSP_SIGN=%x\n"
2269 "OAZ_JWT_SIGENC_ALG=%c\n"
2270 "WSPCGICMD=%s\n"
2271 "NAMEID_ENC=%x\n"
2272 "POST_A7N_ENC=%d\n"
2273 "CANON_INOPT=%x\n"
2274 "ENC_TAIL_OPT=%x\n"
2275 "ENCKEY_OPT=%d\n"
2276 "VALID_OPT=0x%x\n"
2277 "IDPATOPT=%d\n"
2278 "DI_ALLOW_CREATE=%d\n"
2279 "DI_NID_FMT=%d\n"
2280 "DI_A7N_ENC=%d\n"
2281 "BOOTSTRAP_LEVEL=%d\n"
2282 "SHOW_CONF=%x\n"
2283 "#ZXID_ID_BITS=%d (compile)\n"
2284 "#ZXID_ID_MAX_BITS=%d (compile)\n"
2285 "#ZXID_TRUE_RAND=%d (compile)\n"
2286 "SES_ARCH_DIR=%s\n"
2287 "SES_COOKIE_NAME=%s\n"
2288 "PTM_COOKIE_NAME=%s\n"
2289 "IPPORT=%s\n"
2290 "USER_LOCAL=%d\n"
2291 "IDP_ENA=%d\n"
2292 "IDP_PXY_ENA=%d\n"
2293 "IMPS_ENA=%d\n"
2294 "AS_ENA=%d\n"
2295 "MD_AUTHORITY_ENA=%d\n"
2296 "BACKWARDS_COMPAT_ENA=%d\n"
2297 "PDP_ENA=%d\n"
2298 "CPN_ENA=%d\n"
2299 "AZ_OPT=%d\n"
2300 "AZ_FAIL_MODE=%d\n"
2301 "#ZXID_MAX_BUF=%d (compile)\n"
2302
2303 /* *** should these be prefixed by LOG? */
2304 "LOG_ERR=%d\n"
2305 "LOG_ACT=%d\n"
2306 "LOG_ISSUE_A7N=%d\n"
2307 "LOG_ISSUE_MSG=%d\n"
2308 "LOG_RELY_A7N=%d\n"
2309 "LOG_RELY_MSG=%d\n"
2310 "LOG_ERR_IN_ACT=%d\n"
2311 "LOG_ACT_IN_ERR=%d\n"
2312 "LOG_SIGFAIL_IS_ERR=%d\n"
2313 "LOG_LEVEL=%d\n"
2314 "LOGUSER=%d\n"
2315
2316 "SIG_FATAL=%d\n"
2317 "NOSIG_FATAL=%d\n"
2318 "MSG_SIG_OK=%d\n"
2319 "TIMEOUT_FATAL=%d\n"
2320 "AUDIENCE_FATAL=%d\n"
2321 "DUP_A7N_FATAL=%d\n"
2322 "DUP_MSG_FATAL=%d\n"
2323 "RELTO_FATAL=%d\n"
2324 "WSP_NOSIG_FATAL=%d\n"
2325 "NOTIMESTAMP_FATAL=%d\n"
2326 "REDIR_TO_CONTENT=%d\n"
2327 "REMOTE_USER_ENA=%d\n"
2328 "MAX_SOAP_RETRY=%d\n"
2329
2330 "BEFORE_SLOP=%d\n"
2331 "AFTER_SLOP=%d\n"
2332 "TIMESKEW=%d\n"
2333 "A7NTTL=%d\n"
2334
2335 "ANON_OK=%s\n"
2336 "OPTIONAL_LOGIN_PAT=%s\n"
2337 "ISSUE_AUTHNCTX=%s\n"
2338 "IDP_PREF_ACS_BINDING=%s\n"
2339 "MANDATORY_ATTR=%s\n"
2340 "PDP_URL=%s\n"
2341 "PDP_CALL_URL=%s\n"
2342 "XASP_VERS=%s\n"
2343 "TRUSTPDP_URL=%s\n"
2344 "MOD_SAML_ATTR_PREFIX=%s\n"
2345 "BARE_URL_ENTITYID=%d\n"
2346 "SHOW_TECH=%d\n"
2347 "WD=%s\n"
2348
2349 "XMLDSIG_SIG_METH=%s\n"
2350 "XMLDSIG_DIGEST_ALGO=%s\n"
2351 "SAMLSIG_DIGEST_ALGO=%s\n"
2352 "BLOBSIG_DIGEST_ALGO=%s\n"
2353
2354 "IDP_LIST_METH=%d\n"
2355 "IDP_SEL_PAGE=%s\n"
2356 "IDP_SEL_TEMPL_FILE=%s\n"
2357 "</pre>"
2358 "<textarea cols=100 rows=20>"
2359 "IDP_SEL_TEMPL=%s\n"
2360 #if 0
2361 "IDP_SEL_START=%s\n"
2362 "IDP_SEL_NEW_IDP=%s\n"
2363 "IDP_SEL_OUR_EID=%s\n"
2364 "IDP_SEL_TECH_USER=%s\n"
2365 "IDP_SEL_TECH_SITE=%s\n"
2366 "IDP_SEL_FOOTER=%s\n"
2367 "IDP_SEL_END=%s\n"
2368 #endif
2369 "</textarea><pre>\n"
2370
2371 "AN_PAGE=%s\n"
2372 "AN_TEMPL_FILE=%s\n"
2373 "</pre><textarea cols=100 rows=20>"
2374 "AN_TEMPL=%s\n"
2375 "</textarea><pre>\n"
2376
2377 "POST_TEMPL_FILE=%s\n"
2378 "</pre><textarea cols=100 rows=7>"
2379 "POST_TEMPL=%s\n"
2380 "</textarea><pre>\n"
2381
2382 "ERR_PAGE=%s\n"
2383 "ERR_TEMPL_FILE=%s\n"
2384 "</pre><textarea cols=100 rows=7>"
2385 "ERR_TEMPL=%s\n"
2386 "</textarea><pre>\n"
2387
2388 "NEW_USER_PAGE=%s\n"
2389 "RECOVER_PASSWD=%s\n"
2390 "ATSEL_PAGE=%s\n"
2391
2392 "</pre><textarea cols=100 rows=15>"
2393 "MGMT_START=%s\n"
2394 "MGMT_LOGOUT=%s\n"
2395 "MGMT_DEFED=%s\n"
2396 "MGMT_FOOTER=%s\n"
2397 "MGMT_END=%s\n"
2398 "</textarea>"
2399
2400 "<pre>\n"
2401 "DBG=%s\n"
2402
2403 "REQUIRED_AUTHN_CTX=\n%s\n"
2404 "NEED=\n%s\n"
2405 "WANT=\n%s\n"
2406 "ATTRSRC=\n%s\n"
2407 "BUS_URL=\n%s\n"
2408 "BUS_PW=%s\n"
2409 "RCPT=%d\n"
2410 "INMAP=\n%s\n"
2411 "OUTMAP=\n%s\n"
2412 "PEPMAP=\n%s\n"
2413 "PEPMAP_RQOUT=\n%s\n"
2414 "PEPMAP_RQIN=\n%s\n"
2415 "PEPMAP_RSOUT=\n%s\n"
2416 "PEPMAP_RSIN=\n%s\n"
2417 "LOCALPDP_ROLE_PERMIT=\n%s\n"
2418 "LOCALPDP_ROLE_DENY=\n%s\n"
2419 "LOCALPDP_IDPNID_PERMIT=\n%s\n"
2420 "LOCALPDP_IDPNID_DENY=\n%s\n"
2421 "WSC_LOCALPDP_OBL_PLEDGE=%s\n"
2422 //"WSP_LOCALPDP_OBL_REQ=%s\n"
2423 "WSP_LOCALPDP_OBL_EMIT=%s\n"
2424 //"WSC_LOCALPDP_OBL_ACCEPT=%s\n"
2425 "UNIX_GRP_AZ_MAP=\n%s\n"
2426 "</pre>",
2427 cf->burl, eid,
2428 cf->cpath,
2429
2430 errmac_debug,
2431 cf->cpath,
2432 cf->burl,
2433 STRNULLCHK(cf->affiliation),
2434 STRNULLCHK(cf->nice_name),
2435 STRNULLCHK(cf->button_url),
2436 STRNULLCHK(cf->pref_button_size),
2437 STRNULLCHK(cf->org_name),
2438 STRNULLCHK(cf->locality),
2439 STRNULLCHK(cf->state),
2440 STRNULLCHK(cf->country),
2441 STRNULLCHK(cf->contact_org),
2442 STRNULLCHK(cf->contact_name),
2443 STRNULLCHK(cf->contact_email),
2444 STRNULLCHK(cf->contact_tel),
2445 STRNULLCHK(cf->fedusername_suffix),
2446 ZXID_CONF_FILE_ENA,
2447 ZXID_CONF_FLAG,
2448 STRNULLCHK(cf->non_standard_entityid),
2449 STRNULLCHK(cf->redirect_hack_imposed_url),
2450 STRNULLCHK(cf->redirect_hack_zxid_url),
2451 STRNULLCHK(cf->redirect_hack_zxid_qs),
2452 STRNULLCHK(cf->defaultqs),
2453 STRNULLCHK(cf->wsp_pat),
2454 STRNULLCHK(cf->uma_pat),
2455 STRNULLCHK(cf->sso_pat),
2456 STRNULLCHK(cf->wsc_soap_content_type),
2457 STRNULLCHK(cf->wsc_to_hdr),
2458 STRNULLCHK(cf->wsc_replyto_hdr),
2459 STRNULLCHK(cf->wsc_action_hdr),
2460 STRNULLCHK(cf->soap_action_hdr),
2461 STRNULLCHK(cf->cdc_url),
2462 cf->cdc_choice,
2463
2464 STRNULLCHK(cf->load_cot_cache),
2465 cf->md_fetch,
2466 cf->md_populate_cache,
2467 cf->md_cache_first,
2468 cf->md_cache_last,
2469 STRNULLCHK(cf->md_authority),
2470
2471 cf->auto_cert,
2472 cf->authn_req_sign,
2473 cf->want_authn_req_signed,
2474 cf->want_sso_a7n_signed,
2475 cf->sso_soap_sign,
2476 cf->sso_soap_resp_sign,
2477 cf->sso_sign,
2478 cf->wsc_sign,
2479 cf->wsp_sign,
2480 cf->oaz_jwt_sigenc_alg,
2481 cf->wspcgicmd,
2482 cf->nameid_enc,
2483 cf->post_a7n_enc,
2484 cf->canon_inopt,
2485 cf->enc_tail_opt,
2486 cf->enckey_opt,
2487 cf->valid_opt,
2488 cf->idpatopt,
2489 cf->di_allow_create,
2490 cf->di_nid_fmt,
2491 cf->di_a7n_enc,
2492 cf->bootstrap_level,
2493 cf->show_conf,
2494 ZXID_ID_BITS,
2495 ZXID_ID_MAX_BITS,
2496 ZXID_TRUE_RAND,
2497 STRNULLCHK(cf->ses_arch_dir),
2498 STRNULLCHK(cf->ses_cookie_name),
2499 STRNULLCHK(cf->ptm_cookie_name),
2500 STRNULLCHK(cf->ipport),
2501 cf->user_local,
2502 cf->idp_ena,
2503 cf->idp_pxy_ena,
2504 cf->imps_ena,
2505 cf->as_ena,
2506 cf->md_authority_ena,
2507 cf->backwards_compat_ena,
2508 cf->pdp_ena,
2509 cf->cpn_ena,
2510 cf->az_opt,
2511 cf->az_fail_mode,
2512 ZXID_MAX_BUF,
2513
2514 cf->log_err,
2515 cf->log_act,
2516 cf->log_issue_a7n,
2517 cf->log_issue_msg,
2518 cf->log_rely_a7n,
2519 cf->log_rely_msg,
2520 cf->log_err_in_act,
2521 cf->log_act_in_err,
2522 cf->log_sigfail_is_err,
2523 cf->log_level,
2524 cf->loguser,
2525
2526 cf->sig_fatal,
2527 cf->nosig_fatal,
2528 cf->msg_sig_ok,
2529 cf->timeout_fatal,
2530 cf->audience_fatal,
2531 cf->dup_a7n_fatal,
2532 cf->dup_msg_fatal,
2533 cf->relto_fatal,
2534 cf->wsp_nosig_fatal,
2535 cf->notimestamp_fatal,
2536 cf->redir_to_content,
2537 cf->remote_user_ena,
2538 cf->max_soap_retry,
2539
2540 cf->before_slop,
2541 cf->after_slop,
2542 cf->timeskew,
2543 cf->a7nttl,
2544
2545 STRNULLCHK(cf->anon_ok),
2546 STRNULLCHK(cf->optional_login_pat),
2547 issue_authnctx->s,
2548 STRNULLCHK(cf->idp_pref_acs_binding),
2549 STRNULLCHK(cf->mandatory_attr),
2550 STRNULLCHK(cf->pdp_url),
2551 STRNULLCHK(cf->pdp_call_url),
2552 STRNULLCHK(cf->xasp_vers),
2553 STRNULLCHK(cf->trustpdp_url),
2554 STRNULLCHK(cf->mod_saml_attr_prefix),
2555 cf->bare_url_entityid,
2556 cf->show_tech,
2557 STRNULLCHK(cf->wd),
2558 STRNULLCHK(cf->xmldsig_sig_meth),
2559 STRNULLCHK(cf->xmldsig_digest_algo),
2560 STRNULLCHK(cf->samlsig_digest_algo),
2561 STRNULLCHK(cf->blobsig_digest_algo),
2562
2563 cf->idp_list_meth,
2564 STRNULLCHK(cf->idp_sel_page),
2565 STRNULLCHK(cf->idp_sel_templ_file),
2566 STRNULLCHK(cf->idp_sel_templ),
2567 #if 0
2568 STRNULLCHK(cf->idp_sel_start),
2569 STRNULLCHK(cf->idp_sel_new_idp),
2570 STRNULLCHK(cf->idp_sel_our_eid),
2571 STRNULLCHK(cf->idp_sel_tech_user),
2572 STRNULLCHK(cf->idp_sel_tech_site),
2573 STRNULLCHK(cf->idp_sel_footer),
2574 STRNULLCHK(cf->idp_sel_end),
2575 #endif
2576 STRNULLCHK(cf->an_page),
2577 STRNULLCHK(cf->an_templ_file),
2578 STRNULLCHK(cf->an_templ),
2579
2580 STRNULLCHK(cf->post_templ_file),
2581 STRNULLCHK(cf->post_templ),
2582
2583 STRNULLCHK(cf->err_page),
2584 STRNULLCHK(cf->err_templ_file),
2585 STRNULLCHK(cf->err_templ),
2586
2587 STRNULLCHK(cf->new_user_page),
2588 STRNULLCHK(cf->recover_passwd),
2589 STRNULLCHK(cf->atsel_page),
2590
2591 STRNULLCHK(cf->mgmt_start),
2592 STRNULLCHK(cf->mgmt_logout),
2593 STRNULLCHK(cf->mgmt_defed),
2594 STRNULLCHK(cf->mgmt_footer),
2595 STRNULLCHK(cf->mgmt_end),
2596
2597 STRNULLCHK(cf->dbg),
2598
2599 required_authnctx->s,
2600 need->s,
2601 want->s,
2602 attrsrc->s,
2603 bus_url->s,
2604 STRNULLCHK(cf->bus_pw),
2605 cf->bus_rcpt,
2606 inmap->s,
2607 outmap->s,
2608 pepmap->s,
2609 pepmap_rqout->s,
2610 pepmap_rqin->s,
2611 pepmap_rsout->s,
2612 pepmap_rsin->s,
2613 localpdp_role_permit->s,
2614 localpdp_role_deny->s,
2615 localpdp_idpnid_permit->s,
2616 localpdp_idpnid_deny->s,
2617 STRNULLCHK(cf->wsc_localpdp_obl_pledge),
2618 //STRNULLCHK(cf->wsp_localpdp_obl_req),
2619 STRNULLCHK(cf->wsp_localpdp_obl_emit),
2620 //STRNULLCHK(cf->wsc_localpdp_obl_accept)
2621 unix_grp_az_map->s //,
2622 );
2623 }
2624
2625 /* EOF -- zxidconf.c */
2626