/* Check whether the given fpr is in our trustdb. We expect FPR to be an all uppercase hexstring of 40 characters. */ gpg_error_t agent_istrusted (ctrl_t ctrl, const char *fpr, int *r_disabled) { gpg_error_t err; trustitem_t *ti; size_t len; unsigned char fprbin[20]; if (r_disabled) *r_disabled = 0; if ( hexcolon2bin (fpr, fprbin, 20) < 0 ) return gpg_error (GPG_ERR_INV_VALUE); if (!trusttable) { err = read_trustfiles (); if (err) { log_error (_("error reading list of trusted root certificates\n")); return err; } } if (trusttable) { for (ti=trusttable, len = trusttablesize; len; ti++, len--) if (!memcmp (ti->fpr, fprbin, 20)) { if (ti->flags.disabled && r_disabled) *r_disabled = 1; if (ti->flags.relax) { err = agent_write_status (ctrl, "TRUSTLISTFLAG", "relax", NULL); if (err) return err; } else if (ti->flags.cm) { err = agent_write_status (ctrl, "TRUSTLISTFLAG", "cm", NULL); if (err) return err; } return ti->flags.disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0; } } return gpg_error (GPG_ERR_NOT_TRUSTED); }
static void test_hexcolon2bin (void) { static const char *valid[] = { "00112233445566778899aabbccddeeff11223344", "00112233445566778899AABBCCDDEEFF11223344", "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44", "00112233445566778899AABBCCDDEEFF11223344 blah", "00112233445566778899AABBCCDDEEFF11223344\tblah", "00112233445566778899AABBCCDDEEFF11223344\nblah", NULL }; static const char *invalid[] = { "00112233445566778899aabbccddeeff1122334", "00112233445566778899AABBCCDDEEFF1122334", "00112233445566778899AABBCCDDEEFG11223344", ":00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44", "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44:", "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:3344", "00:1122:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44", "0011:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44", "00 11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44", "00:11 22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:11:22:33:44", "00112233445566778899aabbccddeeff112233445", "00112233445566778899aabbccddeeff1122334455", "00112233445566778899aabbccddeeff11223344blah", NULL }; static const char *valid2[] = { "00", "00 x", NULL }; static const char *invalid2[] = { "", "0", "00:", ":00", "0:0", "00x", " 00", NULL }; unsigned char buffer[20]; int len; int i; for (i=0; valid[i]; i++) { len = hexcolon2bin (valid[i], buffer, sizeof buffer); if (len < 0) fail (i); if (memcmp (buffer, ("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa" "\xbb\xcc\xdd\xee\xff\x11\x22\x33\x44"), 20)) fail (i); } if (hexcolon2bin (valid[0], buffer, sizeof buffer) != 40) fail (0); if (hexcolon2bin (valid[3], buffer, sizeof buffer) != 41) fail (0); for (i=0; invalid[i]; i++) { len = hexcolon2bin (invalid[i], buffer, sizeof buffer); if (!(len < 0)) fail (i); } for (i=0; valid2[i]; i++) { len = hexcolon2bin (valid2[i], buffer, 1); if (len < 0) fail (i); if (memcmp (buffer, "\x00", 1)) fail (i); } if (hexcolon2bin (valid2[0], buffer, 1) != 2) fail (0); if (hexcolon2bin (valid2[1], buffer, 1) != 3) fail (0); for (i=0; invalid2[i]; i++) { len = hexcolon2bin (invalid2[i], buffer, 1); if (!(len < 0)) fail (i); } }
static gpg_error_t read_one_trustfile (const char *fname, int allow_include, trustitem_t **addr_of_table, size_t *addr_of_tablesize, int *addr_of_tableidx) { gpg_error_t err = 0; estream_t fp; int n, c; char *p, line[256]; trustitem_t *table, *ti; int tableidx; size_t tablesize; int lnr = 0; table = *addr_of_table; tablesize = *addr_of_tablesize; tableidx = *addr_of_tableidx; fp = es_fopen (fname, "r"); if (!fp) { err = gpg_error_from_syserror (); log_error (_("error opening `%s': %s\n"), fname, gpg_strerror (err)); goto leave; } while (es_fgets (line, DIM(line)-1, fp)) { lnr++; n = strlen (line); if (!n || line[n-1] != '\n') { /* Eat until end of line. */ while ( (c=es_getc (fp)) != EOF && c != '\n') ; err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG : GPG_ERR_INCOMPLETE_LINE); log_error (_("file `%s', line %d: %s\n"), fname, lnr, gpg_strerror (err)); continue; } line[--n] = 0; /* Chop the LF. */ if (n && line[n-1] == '\r') line[--n] = 0; /* Chop an optional CR. */ /* Allow for empty lines and spaces */ for (p=line; spacep (p); p++) ; if (!*p || *p == '#') continue; if (!strncmp (p, "include-default", 15) && (!p[15] || spacep (p+15))) { char *etcname; gpg_error_t err2; if (!allow_include) { log_error (_("statement \"%s\" ignored in `%s', line %d\n"), "include-default", fname, lnr); continue; } /* fixme: Should check for trailing garbage. */ etcname = make_filename (gnupg_sysconfdir (), "trustlist.txt", NULL); if ( !strcmp (etcname, fname) ) /* Same file. */ log_info (_("statement \"%s\" ignored in `%s', line %d\n"), "include-default", fname, lnr); else if ( access (etcname, F_OK) && errno == ENOENT ) { /* A non existent system trustlist is not an error. Just print a note. */ log_info (_("system trustlist `%s' not available\n"), etcname); } else { err2 = read_one_trustfile (etcname, 0, &table, &tablesize, &tableidx); if (err2) err = err2; } xfree (etcname); continue; } if (tableidx == tablesize) /* Need more space. */ { trustitem_t *tmp; size_t tmplen; tmplen = tablesize + 20; tmp = xtryrealloc (table, tmplen * sizeof *table); if (!tmp) { err = gpg_error_from_syserror (); goto leave; } table = tmp; tablesize = tmplen; } ti = table + tableidx; memset (&ti->flags, 0, sizeof ti->flags); if (*p == '!') { ti->flags.disabled = 1; p++; while (spacep (p)) p++; } n = hexcolon2bin (p, ti->fpr, 20); if (n < 0) { log_error (_("bad fingerprint in `%s', line %d\n"), fname, lnr); err = gpg_error (GPG_ERR_BAD_DATA); continue; } p += n; for (; spacep (p); p++) ; /* Process the first flag which needs to be the first for backward compatibility. */ if (!*p || *p == '*' ) { ti->flags.for_smime = 1; ti->flags.for_pgp = 1; } else if ( *p == 'P' || *p == 'p') { ti->flags.for_pgp = 1; } else if ( *p == 'S' || *p == 's') { ti->flags.for_smime = 1; } else { log_error (_("invalid keyflag in `%s', line %d\n"), fname, lnr); err = gpg_error (GPG_ERR_BAD_DATA); continue; } p++; if ( *p && !spacep (p) ) { log_error (_("invalid keyflag in `%s', line %d\n"), fname, lnr); err = gpg_error (GPG_ERR_BAD_DATA); continue; } /* Now check for more key-value pairs of the form NAME[=VALUE]. */ while (*p) { for (; spacep (p); p++) ; if (!*p) break; n = strcspn (p, "= \t"); if (p[n] == '=') { log_error ("assigning a value to a flag is not yet supported; " "in `%s', line %d\n", fname, lnr); err = gpg_error (GPG_ERR_BAD_DATA); p++; } else if (n == 5 && !memcmp (p, "relax", 5)) ti->flags.relax = 1; else if (n == 2 && !memcmp (p, "cm", 2)) ti->flags.cm = 1; else log_error ("flag `%.*s' in `%s', line %d ignored\n", n, p, fname, lnr); p += n; } tableidx++; } if ( !err && !es_feof (fp) ) { err = gpg_error_from_syserror (); log_error (_("error reading `%s', line %d: %s\n"), fname, lnr, gpg_strerror (err)); } leave: es_fclose (fp); *addr_of_table = table; *addr_of_tablesize = tablesize; *addr_of_tableidx = tableidx; return err; }