static int openpgp_message_p (estream_t fp) { int ctb; ctb = es_getc (fp); if (ctb != EOF) { if (es_ungetc (ctb, fp)) log_fatal ("error ungetting first byte: %s\n", gpg_strerror (gpg_error_from_syserror ())); if ((ctb & 0x80)) { switch ((ctb & 0x40) ? (ctb & 0x3f) : ((ctb>>2)&0xf)) { case PKT_MARKER: case PKT_SYMKEY_ENC: case PKT_ONEPASS_SIG: case PKT_PUBKEY_ENC: case PKT_SIGNATURE: case PKT_COMMENT: case PKT_OLD_COMMENT: case PKT_PLAINTEXT: case PKT_COMPRESSED: case PKT_ENCRYPTED: return 1; /* Yes, this seems to be an OpenPGP message. */ default: break; } } } return 0; }
/* Search the keyserver identified by URI for keys matching PATTERN. On success R_FP has an open stream to read the data. */ gpg_error_t ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, estream_t *r_fp) { gpg_error_t err; KEYDB_SEARCH_DESC desc; char fprbuf[2+40+1]; char *hostport = NULL; char *request = NULL; estream_t fp = NULL; int reselect; unsigned int httpflags; char *httphost = NULL; unsigned int tries = SEND_REQUEST_RETRIES; *r_fp = NULL; /* Remove search type indicator and adjust PATTERN accordingly. Note that HKP keyservers like the 0x to be present when searching by keyid. We need to re-format the fingerprint and keyids so to remove the gpg specific force-use-of-this-key flag ("!"). */ err = classify_user_id (pattern, &desc, 1); if (err) return err; switch (desc.mode) { case KEYDB_SEARCH_MODE_EXACT: case KEYDB_SEARCH_MODE_SUBSTR: case KEYDB_SEARCH_MODE_MAIL: case KEYDB_SEARCH_MODE_MAILSUB: pattern = desc.u.name; break; case KEYDB_SEARCH_MODE_SHORT_KID: snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]); pattern = fprbuf; break; case KEYDB_SEARCH_MODE_LONG_KID: snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX", (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]); pattern = fprbuf; break; case KEYDB_SEARCH_MODE_FPR16: bin2hex (desc.u.fpr, 16, fprbuf); pattern = fprbuf; break; case KEYDB_SEARCH_MODE_FPR20: case KEYDB_SEARCH_MODE_FPR: bin2hex (desc.u.fpr, 20, fprbuf); pattern = fprbuf; break; default: return gpg_error (GPG_ERR_INV_USER_ID); } /* Build the request string. */ reselect = 0; again: { char *searchkey; xfree (hostport); hostport = NULL; xfree (httphost); httphost = NULL; err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect, &hostport, &httpflags, &httphost); if (err) goto leave; searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS); if (!searchkey) { err = gpg_error_from_syserror (); goto leave; } xfree (request); request = strconcat (hostport, "/pks/lookup?op=index&options=mr&search=", searchkey, NULL); xfree (searchkey); if (!request) { err = gpg_error_from_syserror (); goto leave; } } /* Send the request. */ err = send_request (ctrl, request, hostport, httphost, httpflags, NULL, NULL, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1; goto again; } if (err) goto leave; err = dirmngr_status (ctrl, "SOURCE", hostport, NULL); if (err) goto leave; /* Peek at the response. */ { int c = es_getc (fp); if (c == -1) { err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF); log_error ("error reading response: %s\n", gpg_strerror (err)); goto leave; } if (c == '<') { /* The document begins with a '<': Assume a HTML response, which we don't support. */ err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING); goto leave; } es_ungetc (c, fp); } /* Return the read stream. */ *r_fp = fp; fp = NULL; leave: es_fclose (fp); xfree (request); xfree (hostport); xfree (httphost); return err; }