1 /* zxcot.c - CoT (Circle-of-Trust) management tool: list CoT, add metadata to CoT
2 * Copyright (c) 2012 Synergetics SA (sampo@synergetics.be), All Rights Reserved.
3 * Copyright (c) 2009-2011 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
4 * This is confidential unpublished proprietary source code of the author.
5 * NO WARRANTY, not even implied warranties. Contains trade secrets.
6 * Distribution prohibited unless authorized in writing.
7 * Licensed under Apache License 2.0, see file COPYING.
8 * $Id: zxcot.c,v 1.5 2009-11-29 12:23:06 sampo Exp $
9 *
10 * 27.8.2009, created --Sampo
11 * 24.4.2012, obsoleted PATH=/var/zxid/idp. From now on, just use /var/zxid/ or VPATH --Sampo
12 */
13
14 #include "platform.h" /* for dirent.h */
15
16 #include <string.h>
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <sys/stat.h> /* for mkdir(2) */
21
22 #include "errmac.h"
23 #include "zx.h"
24 #include "zxid.h"
25 #include "zxidutil.h"
26 #include "zxidconf.h"
27 #include "c/zxidvers.h"
28 #include "c/zx-const.h"
29 #include "c/zx-ns.h"
30 #include "c/zx-data.h"
31
32 char* help =
33 "zxcot - Circle-of-Trust and metadata management tool R" ZXID_REL "\n\
34 Copyright (c) 2012-2013 Synergetics SA (sampo@synergetics.be), All Rights Reserved.\n\
35 Copyright (c) 2009-2011 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.\n\
36 NO WARRANTY, not even implied warranties. Licensed under Apache License v2.0\n\
37 See http://www.apache.org/licenses/LICENSE-2.0\n\
38 Send well researched bug reports to the author. Home: http://zxid.org\n\
39 \n\
40 Usage: zxcot [options] [cotdir] # Gives listing of metadata\n\
41 zxcot -c CPATH=/var/zxid/ -dirs # Creates directory hierarchy\n\
42 zxcot -a [options] [cotdir] <meta.xml # Import metadata\n\
43 zxcot -b [options] [dimddir] <epr.xml # Register EPR\n\
44 curl https://site.com/metadata.xml | zxcot -a [options] [cotdir]\n\
45 zxcot -g https://site.com/metadata.xml [options] [cotdir]\n\
46 zxcot -m [options] >meta.xml # Generate our own metadata\n\
47 zxcot -p https://site.com/metadata.xml\n\
48 [dir] CoT directory. Default /var/zxid/cot\n\
49 -c CONF Optional configuration string (default -c CPATH=/var/zxid/)\n\
50 Most of the configuration is read from " ZXID_CONF_PATH "\n\
51 N.B. If VURL and/or VPATH are used, you should set\n\
52 environment variables that affect virtualization, e.g.\n\
53 HTTP_HOST=example.com:8443 SERVER_PORT=8443 SCRIPT_NAME=zxidhlo zxcot -m\n\
54 -ci IdP conf, synonym for -c IDP_ENA=1\n\
55 -dirs Create configuration directory hierarchy\n\
56 -a Add (someone else's) metadata from stdin\n\
57 -b Register Web Service, add Service EPR from stdin\n\
58 -bs Register Web Service and Bootstrap, add Service EPR from stdin\n\
59 -e endpoint abstract entid servicetype Construct and dump EPR to stdout.\n\
60 -g URL Do HTTP(S) GET to URL (aka WKL) and add as metadata (if compiled w/libcurl)\n\
61 -sign Sign imported metadata (used with -a or -g). Used for Metadata Authority.\n\
62 -n Dryrun. Do not actually add the metadata. Instead print it to stdout.\n\
63 -s Swap columns, for easier sorting by URL\n\
64 -m Output metadata of this installation (our own metadata). Caveat: If your\n\
65 own code, or virtual hosting, sets options like URL, you need to supply\n\
66 them with appropriate -c CONF option. zxcot is not able to guess them!\n\
67 -p ENTID Print sha1 name corresponding to an entity ID.\n\
68 -v Verbose messages.\n\
69 -q Be extra quiet.\n\
70 -d Turn on debugging.\n\
71 -dc Dump configuration.\n\
72 -h This help message\n\
73 -- End of options\n\
74 \n\
75 HTTP_HOST=idp.cloud-identity.eu SCRIPT_NAME=/idp e2etacot -c 'CPATH=/d/relifex/e2eta/' -m\n\
76 zxcot -e http://idp.tas3.pt:8081/zxididp?o=S 'TAS3 Default Discovery Service (ID-WSF 2.0)' http://idp.tas3.pt:8081/zxididp?o=B urn:liberty:disco:2006-08 | zxcot -b\n\
77 \n";
78
79 #define ZXID_MAX_MD (256*1024)
80
81 int sign_md = 0;
82 int swap = 0;
83 int addmd = 0;
84 int regsvc = 0;
85 int regbs = 0;
86 int genmd = 0;
87 int dryrun = 0;
88 int inflate_flag = 2; /* Auto */
89 int verbose = 1;
90 char buf[ZXID_MAX_MD+1] = "PATH=/var/zxid/";
91 char* mdurl = 0;
92 char* entid = 0;
93 char* cotdir;
94 char* dimddir;
95 char* uiddir;
96 zxid_conf* cf = 0;
97
98 static void zx_mkdirs();
99
100 /* Called by: main x8, zxbusd_main, zxbuslist_main, zxbustailf_main, zxcall_main, zxcot_main, zxdecode_main */
opt(int * argc,char *** argv,char *** env)101 static void opt(int* argc, char*** argv, char*** env)
102 {
103 int len;
104 struct zx_str* ss;
105
106 if (*argc <= 1) goto path_to_dir;
107
108 while (1) {
109 ++(*argv); --(*argc);
110
111 if (!(*argc) || ((*argv)[0][0] != '-')) break; /* normal exit from options loop */
112
113 switch ((*argv)[0][1]) {
114 case '-': if ((*argv)[0][2]) break;
115 ++(*argv); --(*argc);
116 DD("End of options by --");
117 return; /* -- ends the options */
118
119 case 'a':
120 switch ((*argv)[0][2]) {
121 case '\0':
122 ++addmd;
123 continue;
124 }
125 break;
126
127 case 'b':
128 switch ((*argv)[0][2]) {
129 case 's':
130 ++regsvc;
131 ++regbs;
132 continue;
133 case '\0':
134 ++regsvc;
135 continue;
136 }
137 break;
138
139 case 'c':
140 switch ((*argv)[0][2]) {
141 case 'i':
142 switch ((*argv)[0][3]) {
143 case '\0':
144 cf->idp_ena = 1;
145 zxid_parse_conf(cf, buf); /* buf was statically initialised to "PATH=/var/zxid/" */
146 continue;
147 }
148 break;
149 case '\0':
150 ++(*argv); --(*argc);
151 if ((*argc) < 1) break;
152 zxid_parse_conf(cf, (*argv)[0]);
153 continue;
154 }
155 break;
156
157 case 'e':
158 switch ((*argv)[0][2]) {
159 case '\0':
160 if ((*argc) < 4) break;
161 printf(
162 "<a:EndpointReference xmlns:a=\"http://www.w3.org/2005/08/addressing\" "
163 "xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" "
164 "notOnOrAfter=\"2037-01-05T23:03:59.001Z\" "
165 "wsu:Id=\"EPRID92lFPo3ZNEt_3rHtJFoU\">"
166 "<a:Address>%s</a:Address>"
167 "<a:Metadata>"
168 "<sbf:Framework xmlns:sbf=\"urn:liberty:sb\" version=\"2.0\"></sbf:Framework>"
169 "<di:Abstract xmlns:di=\"urn:liberty:disco:2006-08\">%s</di:Abstract>"
170 "<di:ProviderID xmlns:di=\"urn:liberty:disco:2006-08\">%s</di:ProviderID>"
171 "<di:ServiceType xmlns:di=\"urn:liberty:disco:2006-08\">%s</di:ServiceType>"
172 "</a:Metadata>"
173 "</a:EndpointReference>", (*argv)[1], (*argv)[2], (*argv)[3], (*argv)[4]);
174 exit(0);
175 }
176 break;
177
178 case 'g':
179 switch ((*argv)[0][2]) {
180 case '\0':
181 ++(*argv); --(*argc);
182 if ((*argc) < 1) break;
183 mdurl = (*argv)[0];
184 ++addmd;
185 continue;
186 }
187 break;
188
189 case 'd':
190 switch ((*argv)[0][2]) {
191 case '\0':
192 ++errmac_debug;
193 continue;
194 case 'c':
195 ss = zxid_show_conf(cf);
196 fprintf(stderr, "\n======== CONF ========\n%.*s\n^^^^^^^^ CONF ^^^^^^^^\n",ss->len,ss->s);
197 continue;
198 }
199 if (!strcmp((*argv)[0],"-dirs")) {
200 zx_mkdirs();
201 exit(0);
202 }
203 break;
204
205 case 's':
206 switch ((*argv)[0][2]) {
207 case '\0':
208 ++swap;
209 continue;
210 case 'i':
211 if (!strcmp((*argv)[0],"-sign")) {
212 sign_md = 1;
213 continue;
214 }
215 break;
216 }
217 break;
218
219 case 'p':
220 switch ((*argv)[0][2]) {
221 case '\0':
222 ++(*argv); --(*argc);
223 if ((*argc) < 1) break;
224 entid = (*argv)[0];
225 continue;
226 }
227 break;
228
229 case 'm':
230 switch ((*argv)[0][2]) {
231 case '\0':
232 ++genmd;
233 continue;
234 }
235 break;
236
237 case 'n':
238 switch ((*argv)[0][2]) {
239 case '\0':
240 ++dryrun;
241 continue;
242 }
243 break;
244
245 #if 0
246 case 'l':
247 switch ((*argv)[0][2]) {
248 case 'i':
249 if (!strcmp((*argv)[0],"-license")) {
250 extern char* license;
251 fprintf(stderr, license);
252 exit(0);
253 }
254 break;
255 }
256 break;
257 #endif
258
259 case 'q':
260 switch ((*argv)[0][2]) {
261 case '\0':
262 verbose = 0;
263 continue;
264 }
265 break;
266
267 case 'v':
268 switch ((*argv)[0][2]) {
269 case '\0':
270 ++verbose;
271 continue;
272 }
273 break;
274
275 }
276 /* fall thru means unrecognized flag */
277 if (*argc)
278 fprintf(stderr, "Unrecognized flag `%s'\n", (*argv)[0]);
279 if (verbose>1) {
280 printf("%s", help);
281 exit(0);
282 }
283 fprintf(stderr, "%s", help);
284 /*fprintf(stderr, "version=0x%06x rel(%s)\n", zxid_version(), zxid_version_str());*/
285 exit(3);
286 }
287 if (*argc) {
288 uiddir = dimddir = cotdir = (*argv)[0];
289 len = strlen(cotdir);
290 if (cotdir[len-1] != '/') { /* Append slash as that is required */
291 cotdir = malloc(len+1);
292 strcpy(cotdir, (*argv)[0]);
293 cotdir[len] = '/';
294 cotdir[++len] = 0;
295 uiddir = dimddir = cotdir;
296 }
297 if (!strcmp(uiddir+len-sizeof("/dimd/")+1, "/dimd/")) {
298 uiddir = strdup(uiddir);
299 strcpy(uiddir+len-sizeof("/dimd/")+1, "/uid/");
300 }
301 } else {
302 path_to_dir:
303 len = strlen(cf->cpath);
304 cotdir = malloc(len+sizeof(ZXID_COT_DIR));
305 strcpy(cotdir, cf->cpath);
306 strcpy(cotdir+len, ZXID_COT_DIR);
307
308 dimddir = malloc(len+sizeof(ZXID_DIMD_DIR));
309 strcpy(dimddir, cf->cpath);
310 strcpy(dimddir+len, ZXID_DIMD_DIR);
311
312 uiddir = malloc(len+sizeof(ZXID_UID_DIR));
313 strcpy(uiddir, cf->cpath);
314 strcpy(uiddir+len, ZXID_UID_DIR);
315 }
316 }
317
318 /* --------- Make zxid config directories --------- */
319
320 static const char* mkdirs_list[] = {
321 "ses",
322 "user",
323 "uid",
324 "nid",
325 "log",
326 "log/rely",
327 "log/issue",
328 "pem",
329 "cot",
330 "inv",
331 "dimd",
332 "dcr",
333 "rsr",
334 "uid/.all",
335 "uid/.all/.bs",
336 "tmp",
337 "ch",
338 "ch/default",
339 "ch/default/.ack",
340 "ch/default/.del"
341 };
342
343 /* Called by: opt */
zx_mkdirs()344 static void zx_mkdirs()
345 {
346 char path[ZXID_MAX_BUF];
347 char* p;
348 const char** dir;
349 int len;
350 struct stat st;
351
352 #define ZXID_PATH_LENGTH_MARGIN (sizeof("ch/default/.del")+10) /* Accommodate longest subdir */
353 len = snprintf(path, sizeof(path)-ZXID_PATH_LENGTH_MARGIN, "%s", cf->cpath);
354 if (len > sizeof(path)-ZXID_PATH_LENGTH_MARGIN) {
355 ERR("CPATH %s too long. len=%d, space=%d", cf->cpath, len, (int)(sizeof(path)-ZXID_PATH_LENGTH_MARGIN));
356 exit(1);
357 }
358
359 for (p = path+len-1; p > path && *p != '/'; --p) ; /* Handle CPATH=/var/zxid/idp */
360
361 if (MKDIR(path, 02770) < 0) {
362 if (errno == EEXIST) {
363 INFO("Directory %s already exists. Will still try to create hierarchy under it.", path);
364 } else {
365 ERR("Failed to create directory hierarchy at %s: %d (%s) (perhaps nonexistent parent directory or permissions problem)", path, errno, STRERROR(errno));
366 exit(1);
367 }
368 } else {
369 D("Created %s", path);
370 }
371
372 for (dir = mkdirs_list; *dir; ++dir) {
373 len = snprintf(path, sizeof(path)-ZXID_PATH_LENGTH_MARGIN, "%s%s", cf->cpath, *dir);
374 if (MKDIR(path, 02770) < 0) {
375 ERR("Failed to create directory %s: %d (%s)", path, errno, STRERROR(errno));
376 } else {
377 D("Created %s", path);
378 }
379 }
380
381 len = snprintf(path, sizeof(path)-ZXID_PATH_LENGTH_MARGIN, "%s" ZXID_CONF_FILE, cf->cpath);
382 if (stat(path, &st)) { /* error return from stat means file does not exist, create example */
383 write_all_path_fmt("-dirs", sizeof(path), path, "%s%s", cf->cpath, ZXID_CONF_FILE,
384 "# This is example configuration file %s" ZXID_CONF_FILE "\n"
385 "# You should edit the values to suit your situation.\n"
386 "BURL=https://yourhost.example.com:8443/protected/saml\n"
387 "NICE_NAME=Configuration NICE_NAME: Set this to describe your site to humans, see %s" ZXID_CONF_FILE "\n"
388 "BUTTON_URL=https://example.com/YOUR_BRAND_saml2_icon_150x60.png\n"
389 "ORG_NAME=Unspecified ORG_NAME conf variable\n"
390 "LOCALITY=Lisboa\n"
391 "STATE=Lisboa\n"
392 "COUNTRY=PT\n"
393 "CONTACT_ORG=Your organization\n"
394 "CONTACT_NAME=Your Name\n"
395 "CONTACT_EMAIL=your@email.com\n"
396 "CONTACT_TEL=+351918731007\n", cf->cpath, cf->cpath);
397 }
398
399 INFO("Created directories. You should inspect their ownership and permissions to ensure the webserver can read and write them, yet outsiders can not access them. You may want to run chown -R www-data %s", cf->cpath);
400 }
401
402 /* --------------- reg_svc --------------- */
403
404 /*() IdP and Discovery. Register service metadata to /var/zxid/idpdimd/XX,
405 * and possibly boostrap to /var/zxid/idpuid/.all/.bs/YY
406 *
407 * bs_reg:: Register-also-as-bootstrap flag
408 * dry_run:: nonzero: do not write anything
409 * ddimd:: Discovery metadata directory, such as /var/zxid/idpdimd/
410 * duid:: uid dir such as /var/zxid/idpuid/
411 * returns:: 0 on success, nonzero on error. */
412
413 /* Called by: zxcot_main */
zxid_reg_svc(zxid_conf * cf,int bs_reg,int dry_run,const char * ddimd,const char * duid)414 static int zxid_reg_svc(zxid_conf* cf, int bs_reg, int dry_run, const char* ddimd, const char* duid)
415 {
416 char sha1_name[28];
417 char path[ZXID_MAX_BUF];
418 int got;
419 fdtype fd;
420 struct zx_root_s* r;
421 zxid_epr* epr;
422 struct zx_str* ss;
423 struct zx_str* tt;
424
425 read_all_fd(fdstdin, buf, sizeof(buf)-1, &got); /* Read EPR */
426 buf[got] = 0;
427
428 r = zx_dec_zx_root(cf->ctx, got, buf, "cot reg_svc");
429 if (!r || !r->EndpointReference) {
430 ERR("Failed to parse <EndpointReference> buf(%.*s)", got, buf);
431 return 1;
432 }
433 epr = r->EndpointReference;
434 if (!ZX_SIMPLE_ELEM_CHK(epr->Address)) {
435 ERR("<EndpointReference> MUST have <Address> element buf(%.*s)", got, buf);
436 return 1;
437 }
438 if (!epr->Metadata) {
439 ERR("<EndpointReference> MUST have <Metadata> element buf(%.*s)", got, buf);
440 return 1;
441 }
442 if (!ZX_SIMPLE_ELEM_CHK(epr->Metadata->ProviderID)) {
443 ERR("<EndpointReference> MUST have <Metadata> with <ProviderID> element buf(%.*s)", got, buf);
444 return 1;
445 }
446 if (!epr->Metadata->ServiceType) {
447 ERR("<EndpointReference> MUST have <ServiceType> element buf(%.*s)", got, buf);
448 return 1;
449 }
450
451 /* *** possibly add something here and double check the required fields are available. */
452
453 ss = zx_easy_enc_elem_opt(cf, &epr->gg);
454 if (!ss)
455 return 2;
456
457 #if 0
458 // *** wrong
459 tt = ZX_GET_CONTENT(epr->Metadata->ProviderID);
460 #else
461 tt = ZX_GET_CONTENT(epr->Metadata->ServiceType);
462 #endif
463 got = MIN(tt->len, sizeof(path)-1);
464 memcpy(path, tt?tt->s:"", got);
465 path[got] = 0;
466 zxid_fold_svc(path, got);
467
468 sha1_safe_base64(sha1_name, ss->len, ss->s);
469 sha1_name[27] = 0;
470
471 if (verbose)
472 fprintf(stderr, "Registering metadata in %s%s,%s\n", ddimd, path, sha1_name);
473
474 if (dry_run) {
475 if (verbose)
476 fprintf(stderr, "Register EPR dry run. Would have written to path(%s%s,%s). "
477 "You may also want to\n"
478 " touch %s.all/.bs/%s,%s\n\n", ddimd, path, sha1_name, uiddir, path, sha1_name);
479 fflush(stdin);
480 write_all_fd(fdstdout, ss->s, ss->len);
481 zx_str_free(cf->ctx, ss);
482 return 0;
483 }
484
485 D("Register EPR path(%s%s,%s) in discovery metadata.", ddimd, path, sha1_name);
486 fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxcot -b", 1,
487 "%s%s,%s", ddimd, path, sha1_name);
488 if (fd == BADFD) {
489 perror("open epr for registering");
490 ERR("Failed to open file for writing: sha1_name(%s,%s) to service registration", path, sha1_name);
491 zx_str_free(cf->ctx, ss);
492 return 1;
493 }
494
495 write_all_fd(fd, ss->s, ss->len);
496 zx_str_free(cf->ctx, ss);
497 close_file(fd, (const char*)__FUNCTION__);
498
499 if (bs_reg) {
500 if (verbose)
501 fprintf(stderr, "Activating bootstrap %s.all/.bs/%s,%s", duid, path, sha1_name);
502
503 if (!dryrun) {
504 fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxcot -bs", 1,
505 "%s.all/.bs/%s,%s", duid, path, sha1_name);
506 if (fd == BADFD) {
507 perror("open epr for bootstrap activation");
508 ERR("Failed to open file for writing: sha1_name(%s,%s) to bootstrap activation", path, sha1_name);
509 return 1;
510 }
511
512 write_all_fd(fd, "", 0);
513 close_file(fd, (const char*)__FUNCTION__);
514 }
515 } else {
516 D("You may also want to activate bootstrap by\n touch %s.all/.bs/%s,%s", duid, path, sha1_name);
517 }
518 return 0;
519 }
520
521 /* --------------- addmd --------------- */
522
523 /*() Add metadata of a partner to the Circle-of-Trust, represented by the CoT dir */
524
525 /* Called by: zxcot_main */
zxid_addmd(zxid_conf * cf,char * mdurl,int dry_run,const char * dcot)526 static int zxid_addmd(zxid_conf* cf, char* mdurl, int dry_run, const char* dcot)
527 {
528 int got;
529 fdtype fd;
530 char* p;
531 zxid_entity* ent;
532 struct zx_str* ss;
533
534 if (mdurl) {
535 ent = zxid_get_meta(cf, mdurl);
536 } else {
537 read_all_fd(fdstdin, buf, sizeof(buf)-1, &got);
538 buf[got] = 0;
539 p = buf;
540 ent = zxid_parse_meta(cf, &p, buf+got);
541 }
542
543 if (!ent) {
544 ERR("***** Parsing metadata failed %d", 0);
545 return 1;
546 }
547
548 for (; ent; ent = ent->n) {
549 ss = zx_easy_enc_elem_opt(cf, &ent->ed->gg);
550 if (!ss)
551 return 2;
552
553 if (dry_run) {
554 write_all_fd(fdstdout, ss->s, ss->len);
555 zx_str_free(cf->ctx, ss);
556 if (verbose>1)
557 printf("\n\nDry run ent(%s) to %s%s\n", ent->eid, dcot, ent->sha1_name);
558 continue;
559 }
560 if (verbose)
561 printf("Writing ent(%s) to %s%s\n", ent->eid, dcot, ent->sha1_name);
562
563 fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxcot -a", 1,
564 "%s%s", dcot, ent->sha1_name);
565 if (fd == BADFD) {
566 perror("open metadata for writing metadata to cache");
567 ERR("Failed to open file for writing: sha1_name(%s) to metadata cache", ent->sha1_name);
568 zx_str_free(cf->ctx, ss);
569 return 1;
570 }
571
572 write_all_fd(fd, ss->s, ss->len);
573 zx_str_free(cf->ctx, ss);
574 close_file(fd, (const char*)__FUNCTION__);
575 }
576 return 0;
577 }
578
579 /* --------------- genmd --------------- */
580
581 /*() Generate our own metadata */
582
583 /* Called by: zxcot_main */
zxid_genmd(zxid_conf * cf,int dry_run,const char * dcot)584 static int zxid_genmd(zxid_conf* cf, int dry_run, const char* dcot)
585 {
586 zxid_cgi cgi;
587 struct zx_str* meta = zxid_sp_meta(cf, &cgi);
588 ZERO(&cgi, sizeof(cgi));
589 printf("%.*s", meta->len, meta->s);
590 return 0;
591 }
592
593 /* --------------- lscot --------------- */
594
595 /*() Print a line of Circle-of-Trust listing */
596
597 /* Called by: zxid_lscot x2 */
zxid_lscot_line(zxid_conf * cf,int col_swap,const char * dcot,const char * den)598 static int zxid_lscot_line(zxid_conf* cf, int col_swap, const char* dcot, const char* den)
599 {
600 zxid_entity* ent;
601 char* p;
602 int got = read_all(ZXID_MAX_MD, buf, "zxcot line", 1, "%s%s", dcot, den);
603 if (!got) {
604 ERR("Zero data in file(%s%s). If cot directory does not exist consider running zxcot -dirs", dcot, den);
605 return 1;
606 }
607 p = buf;
608 ent = zxid_parse_meta(cf, &p, buf+got);
609 if (!ent) {
610 ERR("***** Parsing metadata failed for(%s%s)", dcot, den);
611 return 2;
612 }
613 while (ent) {
614 switch (col_swap) {
615 case 1: printf("%-50s %s%s %s\n", ent->eid, dcot, den, STRNULLCHKD(ent->dpy_name)); break;
616 case 2: printf("%s\n", ent->eid); break;
617 default: printf("%s%s %-50s %s\n", dcot, den, ent->eid, STRNULLCHKD(ent->dpy_name));
618 }
619 if (strcmp(*den?den:dcot, ent->sha1_name))
620 fprintf(stderr, "Filename(%s) does not match sha1_name(%s)\n", *den?den:dcot, ent->sha1_name);
621 ent = ent->n;
622 }
623 return 0;
624 }
625
626 /*() List the contents of the Circle-of-Trust, represented by the CoT directory,
627 * in various formats. */
628
629 /* Called by: zxcot_main */
zxid_lscot(zxid_conf * cf,int col_swap,const char * dcot)630 static int zxid_lscot(zxid_conf* cf, int col_swap, const char* dcot)
631 {
632 int got, ret;
633 char* p;
634 DIR* dir;
635 struct dirent* de;
636
637 dir = opendir(dcot);
638 if (!dir) {
639 perror("opendir for /var/zxid/cot (or other if configured) for loading cot cache");
640 D("failed path(%s)", dcot);
641
642 got = strlen(dcot);
643 p = ZX_ALLOC(cf->ctx, got+1);
644 memcpy(p, dcot, got-1);
645 p[got-1] = 0; /* chop off / */
646 got = zxid_lscot_line(cf, col_swap, p, "");
647 ZX_FREE(cf->ctx, p);
648 return got;
649 }
650
651 while (de = readdir(dir)) {
652 if (de->d_name[0] == '.' || de->d_name[strlen(de->d_name)-1] == '~')
653 continue;
654 ret = zxid_lscot_line(cf, col_swap, dcot, de->d_name);
655 if (!ONE_OF_2(ret, 0, 2))
656 return ret;
657 }
658 return 0;
659 }
660
661 /* ============== MAIN ============ */
662
663 #ifndef zxcot_main
664 #define zxcot_main main
665 #endif
666 extern int zxid_suppress_vpath_warning;
667
668 /*() Circle of Trust management tool */
669
670 /* Called by: */
zxcot_main(int argc,char ** argv,char ** env)671 int zxcot_main(int argc, char** argv, char** env)
672 {
673 strncpy(errmac_instance, "cot", sizeof(errmac_instance));
674 zxid_suppress_vpath_warning = 1;
675 cf = zxid_new_conf_to_cf(0);
676
677 opt(&argc, &argv, &env);
678
679 if (entid) {
680 char sha1_name[28];
681 sha1_safe_base64(sha1_name, strlen(entid), entid);
682 sha1_name[27] = 0;
683 printf("%s\n", sha1_name);
684 return 0;
685 }
686
687 if (addmd)
688 return zxid_addmd(cf, mdurl, dryrun, cotdir);
689
690 if (regsvc)
691 return zxid_reg_svc(cf, regbs, dryrun, dimddir, uiddir);
692
693 if (genmd)
694 return zxid_genmd(cf, dryrun, cotdir);
695
696 return zxid_lscot(cf, swap, cotdir);
697 }
698
699 /* EOF -- zxcot.c */
700