1*ebfedea0SLionel Sambuc /*-
2*ebfedea0SLionel Sambuc * Copyright (c) 2010 Alistair Crooks <agc@NetBSD.org>
3*ebfedea0SLionel Sambuc * All rights reserved.
4*ebfedea0SLionel Sambuc *
5*ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
6*ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
7*ebfedea0SLionel Sambuc * are met:
8*ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
9*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
10*ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
11*ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
12*ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
13*ebfedea0SLionel Sambuc *
14*ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15*ebfedea0SLionel Sambuc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16*ebfedea0SLionel Sambuc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17*ebfedea0SLionel Sambuc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18*ebfedea0SLionel Sambuc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19*ebfedea0SLionel Sambuc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20*ebfedea0SLionel Sambuc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21*ebfedea0SLionel Sambuc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22*ebfedea0SLionel Sambuc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23*ebfedea0SLionel Sambuc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24*ebfedea0SLionel Sambuc */
25*ebfedea0SLionel Sambuc #include <sys/types.h>
26*ebfedea0SLionel Sambuc #include <sys/param.h>
27*ebfedea0SLionel Sambuc #include <sys/socket.h>
28*ebfedea0SLionel Sambuc
29*ebfedea0SLionel Sambuc #include <netinet/in.h>
30*ebfedea0SLionel Sambuc
31*ebfedea0SLionel Sambuc #include <errno.h>
32*ebfedea0SLionel Sambuc #include <inttypes.h>
33*ebfedea0SLionel Sambuc #include <netdb.h>
34*ebfedea0SLionel Sambuc #include <netpgp.h>
35*ebfedea0SLionel Sambuc #include <regex.h>
36*ebfedea0SLionel Sambuc #include <stdio.h>
37*ebfedea0SLionel Sambuc #include <stdlib.h>
38*ebfedea0SLionel Sambuc #include <string.h>
39*ebfedea0SLionel Sambuc #include <unistd.h>
40*ebfedea0SLionel Sambuc
41*ebfedea0SLionel Sambuc #include "hkpc.h"
42*ebfedea0SLionel Sambuc
43*ebfedea0SLionel Sambuc /* get a socket and connect it to the server */
44*ebfedea0SLionel Sambuc int
hkpc_connect(const char * hostname,const int port,const int fam)45*ebfedea0SLionel Sambuc hkpc_connect(const char *hostname, const int port, const int fam)
46*ebfedea0SLionel Sambuc {
47*ebfedea0SLionel Sambuc struct addrinfo hints;
48*ebfedea0SLionel Sambuc struct addrinfo *res;
49*ebfedea0SLionel Sambuc char portstr[32];
50*ebfedea0SLionel Sambuc int sock;
51*ebfedea0SLionel Sambuc int rc = 0;
52*ebfedea0SLionel Sambuc
53*ebfedea0SLionel Sambuc (void) memset(&hints, 0, sizeof(hints));
54*ebfedea0SLionel Sambuc hints.ai_family = (fam == 4) ? PF_INET : PF_INET6;
55*ebfedea0SLionel Sambuc hints.ai_socktype = SOCK_STREAM;
56*ebfedea0SLionel Sambuc (void) snprintf(portstr, sizeof(portstr), "%d", port);
57*ebfedea0SLionel Sambuc if ((rc = getaddrinfo(hostname, portstr, &hints, &res)) != 0) {
58*ebfedea0SLionel Sambuc hints.ai_flags = 0;
59*ebfedea0SLionel Sambuc if ((rc = getaddrinfo(hostname, "hkp", &hints, &res)) != 0) {
60*ebfedea0SLionel Sambuc (void) fprintf(stderr, "getaddrinfo: %s",
61*ebfedea0SLionel Sambuc gai_strerror(rc));
62*ebfedea0SLionel Sambuc return -1;
63*ebfedea0SLionel Sambuc }
64*ebfedea0SLionel Sambuc }
65*ebfedea0SLionel Sambuc if ((sock = socket((fam == 4) ? AF_INET : AF_INET6, SOCK_STREAM, 0)) < 0) {
66*ebfedea0SLionel Sambuc (void) fprintf(stderr, "socket failed %d\n", errno);
67*ebfedea0SLionel Sambuc freeaddrinfo(res);
68*ebfedea0SLionel Sambuc return -1;
69*ebfedea0SLionel Sambuc }
70*ebfedea0SLionel Sambuc if ((rc = connect(sock, res->ai_addr, res->ai_addrlen)) < 0) {
71*ebfedea0SLionel Sambuc (void) fprintf(stderr, "connect failed %d\n", errno);
72*ebfedea0SLionel Sambuc freeaddrinfo(res);
73*ebfedea0SLionel Sambuc return -1;
74*ebfedea0SLionel Sambuc }
75*ebfedea0SLionel Sambuc freeaddrinfo(res);
76*ebfedea0SLionel Sambuc if (rc < 0) {
77*ebfedea0SLionel Sambuc (void) fprintf(stderr, "connect() to %s:%d failed (rc %d)\n",
78*ebfedea0SLionel Sambuc hostname, port, rc);
79*ebfedea0SLionel Sambuc }
80*ebfedea0SLionel Sambuc return sock;
81*ebfedea0SLionel Sambuc }
82*ebfedea0SLionel Sambuc
83*ebfedea0SLionel Sambuc #define MB(x) ((x) * 1024 * 1024)
84*ebfedea0SLionel Sambuc
85*ebfedea0SLionel Sambuc /* get required info from the server */
86*ebfedea0SLionel Sambuc int
hkpc_get(char ** info,const char * server,const int port,const int family,const char * type,const char * userid)87*ebfedea0SLionel Sambuc hkpc_get(char **info, const char *server, const int port, const int family, const char *type, const char *userid)
88*ebfedea0SLionel Sambuc {
89*ebfedea0SLionel Sambuc char buf[MB(1)];
90*ebfedea0SLionel Sambuc int sock;
91*ebfedea0SLionel Sambuc int cc;
92*ebfedea0SLionel Sambuc int rc;
93*ebfedea0SLionel Sambuc
94*ebfedea0SLionel Sambuc if ((sock = hkpc_connect(server, port, family)) < 0) {
95*ebfedea0SLionel Sambuc (void) fprintf(stderr, "hkpc_get: can't connect to server '%s'\n", server);
96*ebfedea0SLionel Sambuc return -1;
97*ebfedea0SLionel Sambuc }
98*ebfedea0SLionel Sambuc cc = snprintf(buf, sizeof(buf), "GET /pks/lookup?op=%s&search=%s&options=json", type, userid);
99*ebfedea0SLionel Sambuc if (write(sock, buf, cc) != cc) {
100*ebfedea0SLionel Sambuc (void) fprintf(stderr, "hkpc_get: short write\n");
101*ebfedea0SLionel Sambuc return -1;
102*ebfedea0SLionel Sambuc }
103*ebfedea0SLionel Sambuc for (cc = 0 ; (rc = read(sock, &buf[cc], sizeof(buf) - cc)) > 0 ; cc += rc) {
104*ebfedea0SLionel Sambuc }
105*ebfedea0SLionel Sambuc *info = calloc(1, cc + 1);
106*ebfedea0SLionel Sambuc (void) memcpy(*info, buf, cc);
107*ebfedea0SLionel Sambuc (*info)[cc] = 0x0;
108*ebfedea0SLionel Sambuc (void) close(sock);
109*ebfedea0SLionel Sambuc return cc;
110*ebfedea0SLionel Sambuc }
111*ebfedea0SLionel Sambuc
112*ebfedea0SLionel Sambuc /* jump over http header, then pass the json to the key-formatting function */
113*ebfedea0SLionel Sambuc int
hkpc_print_key(FILE * fp,const char * op,const char * res)114*ebfedea0SLionel Sambuc hkpc_print_key(FILE *fp, const char *op, const char *res)
115*ebfedea0SLionel Sambuc {
116*ebfedea0SLionel Sambuc static regex_t text;
117*ebfedea0SLionel Sambuc static int compiled;
118*ebfedea0SLionel Sambuc regmatch_t matches[10];
119*ebfedea0SLionel Sambuc int ret;
120*ebfedea0SLionel Sambuc
121*ebfedea0SLionel Sambuc if (!compiled) {
122*ebfedea0SLionel Sambuc compiled = 1;
123*ebfedea0SLionel Sambuc (void) regcomp(&text, "\r\n\r\n", REG_EXTENDED);
124*ebfedea0SLionel Sambuc }
125*ebfedea0SLionel Sambuc if (regexec(&text, res, 10, matches, 0) != 0) {
126*ebfedea0SLionel Sambuc return 0;
127*ebfedea0SLionel Sambuc }
128*ebfedea0SLionel Sambuc if (strcmp(op, "index") == 0 || strcmp(op, "vindex") == 0) {
129*ebfedea0SLionel Sambuc ret = netpgp_format_json(fp, &res[(int)matches[0].rm_eo], 1);
130*ebfedea0SLionel Sambuc } else {
131*ebfedea0SLionel Sambuc (void) fprintf(fp, "%s\n", &res[(int)matches[0].rm_eo]);
132*ebfedea0SLionel Sambuc ret = 1;
133*ebfedea0SLionel Sambuc }
134*ebfedea0SLionel Sambuc return ret;
135*ebfedea0SLionel Sambuc }
136