/*- * Copyright (c) 2010 Alistair Crooks * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hkpc.h" /* get a socket and connect it to the server */ int hkpc_connect(const char *hostname, const int port, const int fam) { struct addrinfo hints; struct addrinfo *res; char portstr[32]; int sock; int rc = 0; (void) memset(&hints, 0, sizeof(hints)); hints.ai_family = (fam == 4) ? PF_INET : PF_INET6; hints.ai_socktype = SOCK_STREAM; (void) snprintf(portstr, sizeof(portstr), "%d", port); if ((rc = getaddrinfo(hostname, portstr, &hints, &res)) != 0) { hints.ai_flags = 0; if ((rc = getaddrinfo(hostname, "hkp", &hints, &res)) != 0) { (void) fprintf(stderr, "getaddrinfo: %s", gai_strerror(rc)); return -1; } } if ((sock = socket((fam == 4) ? AF_INET : AF_INET6, SOCK_STREAM, 0)) < 0) { (void) fprintf(stderr, "socket failed %d\n", errno); freeaddrinfo(res); return -1; } if ((rc = connect(sock, res->ai_addr, res->ai_addrlen)) < 0) { (void) fprintf(stderr, "connect failed %d\n", errno); freeaddrinfo(res); return -1; } freeaddrinfo(res); if (rc < 0) { (void) fprintf(stderr, "connect() to %s:%d failed (rc %d)\n", hostname, port, rc); } return sock; } #define MB(x) ((x) * 1024 * 1024) /* get required info from the server */ int hkpc_get(char **info, const char *server, const int port, const int family, const char *type, const char *userid) { char buf[MB(1)]; int sock; int cc; int rc; if ((sock = hkpc_connect(server, port, family)) < 0) { (void) fprintf(stderr, "hkpc_get: can't connect to server '%s'\n", server); return -1; } cc = snprintf(buf, sizeof(buf), "GET /pks/lookup?op=%s&search=%s&options=json", type, userid); if (write(sock, buf, cc) != cc) { (void) fprintf(stderr, "hkpc_get: short write\n"); return -1; } for (cc = 0 ; (rc = read(sock, &buf[cc], sizeof(buf) - cc)) > 0 ; cc += rc) { } *info = calloc(1, cc + 1); (void) memcpy(*info, buf, cc); (*info)[cc] = 0x0; (void) close(sock); return cc; } /* jump over http header, then pass the json to the key-formatting function */ int hkpc_print_key(FILE *fp, const char *op, const char *res) { static regex_t text; static int compiled; regmatch_t matches[10]; int ret; if (!compiled) { compiled = 1; (void) regcomp(&text, "\r\n\r\n", REG_EXTENDED); } if (regexec(&text, res, 10, matches, 0) != 0) { return 0; } if (strcmp(op, "index") == 0 || strcmp(op, "vindex") == 0) { ret = netpgp_format_json(fp, &res[(int)matches[0].rm_eo], 1); } else { (void) fprintf(fp, "%s\n", &res[(int)matches[0].rm_eo]); ret = 1; } return ret; } .