Module Name:    src
Committed By:   agc
Date:           Mon Mar  1 07:41:57 UTC 2010

Added Files:
        src/crypto/external/bsd/netpgp/dist/src/hkpd: Makefile hkpd.c hkpd.h
            main.c

Log Message:
add an embryonic httpd key server (hkpd) to netpgp. this is based on the
discontinued draft for hkp servers, in lieu of any official rfc.

the post method for adding keys to the server has not been implemented.
not until i've gone through all of the implications, anyway.

hkp servers serve up pgp public keys over http. the default port is 11371,
but it can be any port, specifiable at run time. whilst this hkpd will
return valid html to browsers, it is aimed at the ''machine readable''
side, using the ''&options=mr'' option to the http get string.

this hkpd server will get hooked into the build at a later date.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/crypto/external/bsd/netpgp/dist/src/hkpd/Makefile \
    src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.c \
    src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.h \
    src/crypto/external/bsd/netpgp/dist/src/hkpd/main.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/crypto/external/bsd/netpgp/dist/src/hkpd/Makefile
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/hkpd/Makefile:1.1
--- /dev/null	Mon Mar  1 07:41:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/hkpd/Makefile	Mon Mar  1 07:41:56 2010
@@ -0,0 +1,11 @@
+# $NetBSD: Makefile,v 1.1 2010/03/01 07:41:56 agc Exp $
+
+PROG=hkpd
+SRCS=hkpd.c main.c
+CPPFLAGS+=-g # -DHAVE_CONFIG_H=1
+LDFLAGS+=-g
+LDADD+= -lnetpgp
+MKMAN=no
+WARNS=0 # anything over 0 will fail at the link stage with IDEA errors
+
+.include <bsd.prog.mk>
Index: src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.c
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.c:1.1
--- /dev/null	Mon Mar  1 07:41:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.c	Mon Mar  1 07:41:56 2010
@@ -0,0 +1,275 @@
+/*-
+ * Copyright (c) 2009,2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (a...@netbsd.org)
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <netpgp.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "hkpd.h"
+
+/* make the string have %xx -> %c */
+static size_t
+frompercent(char *in, size_t insize, char *out, size_t outsize)
+{
+	size_t	 outcc;
+	char	*next;
+	char	*pc;
+
+	outcc = 0;
+	for (pc = in ; (next = strchr(pc, '%')) != NULL ; pc = next + 3) {
+		(void) memcpy(&out[outcc], pc, (size_t)(next - pc));
+		outcc += (size_t)(next - pc);
+		out[outcc++] = (char)strtol(next + 1, NULL, 16);
+	}
+	(void) memcpy(&out[outcc], pc, insize - (int)(pc - in));
+	outcc += insize - (int)(pc - in);
+	out[outcc] = 0x0;
+	return outcc;
+}
+
+#define HKP_HTTP_LEVEL	"HTTP/1.0"
+#define HKP_NAME	"hkpd"
+#define HKP_MIME_GET	"application/pgp-keys"
+#define HKP_MIME_INDEX	"text/plain"
+#define HKP_MACHREAD	"info:1:1\r\n"
+
+#define HKP_SUCCESS	200
+#define HKP_NOT_FOUND	404
+
+/* make into html */
+static int
+htmlify(char *buf, size_t size, const int code, const int get, const char *title, const int mr, const char *body)
+{
+	return snprintf(buf, size,
+		"%s %d %s\r\n"
+		"Server: %s/%d\r\n"
+		"Content-type: %s\r\n"
+		"\r\n"
+		"%s"
+		"%s",
+		HKP_HTTP_LEVEL, code, (code == HKP_SUCCESS) ? "OK" : "not found",
+		HKP_NAME, HKPD_VERSION,
+		(get) ? HKP_MIME_GET : HKP_MIME_INDEX,
+		(get || !mr) ? "" : HKP_MACHREAD,
+		body);
+}
+
+/* send the response now */
+static int
+response(int sock, const int code, const char *search, const int get, char *buf, int cc, int mr)
+{
+	char	outbuf[BUFSIZ * 8];
+	char	item[BUFSIZ];
+	int	n;
+
+	if (buf == NULL) {
+		(void) snprintf(item, sizeof(item),
+			"Error handling request: No keys found for '%s'\r\n", search);
+		n = htmlify(outbuf, sizeof(outbuf), code, get,
+			"Error handling request\r\n",
+			mr,
+			item);
+	} else {
+		(void) snprintf(item, sizeof(item), "Search results for '%s'", search);
+		n = htmlify(outbuf, sizeof(outbuf), code, get,
+			item,
+			mr,
+			buf);
+	}
+	if (write(sock, outbuf, n) != n) {
+		(void) fprintf(stderr, "Short write\n");
+	}
+	return 1;
+}
+
+/**************************************************************************/
+
+/* bind the socket to the server */
+int
+hkpd_sock_bind(int sock, const char *hostname, const int port)
+{
+        struct addrinfo  hints;
+        struct addrinfo *res;
+        char             portstr[32];
+        int              rc = 0;
+
+        (void) memset(&hints, 0, sizeof(hints));
+        hints.ai_family = PF_INET;
+        hints.ai_socktype = SOCK_STREAM;
+        (void) snprintf(portstr, sizeof(portstr), "%d", port);
+        /* Attempt connection */
+#ifdef AI_NUMERICSERV
+        hints.ai_flags = AI_NUMERICSERV;
+#endif
+        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 ((rc = bind(sock, res->ai_addr, res->ai_addrlen)) < 0) {
+                (void) fprintf(stderr, "bind failed %d\n", errno);
+                freeaddrinfo(res);
+                return -1;
+        }
+        freeaddrinfo(res);
+        if (rc < 0) {
+                (void) fprintf(stderr, "bind() to %s:%d failed (rc %d)\n",
+				hostname, port, rc);
+        }
+        return rc;
+}
+
+/* get a socket (we'll bind it later) */
+int
+hkpd_sock_get(void)
+{
+	int	sock;
+	int	on = 1;
+
+	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		(void) fprintf(stderr,"hkpd_sock_get: can't get a socket\n");
+		return -1;
+        }
+	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+			(void *)&on, sizeof(on)) == -1) {
+		(void) fprintf(stderr,
+			"hkpd_sock_get: can't set SO_REUSEADDR\n");
+		return -1;
+	}
+	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+			(void *)&on, sizeof(on)) == -1) {
+		(void) fprintf(stderr,
+			"hkpd_sock_get: can't set SO_KEEPALIVE\n");
+		return -1;
+	}
+	return sock;
+}
+
+/* netpgp key daemon - does not return */
+int
+hkpd(netpgp_t *netpgp, int sock)
+{
+	struct sockaddr_in	from;
+	regmatch_t		searchmatches[10];
+	regmatch_t		opmatches[10];
+	regmatch_t		mrmatch[3];
+	socklen_t		fromlen;
+	regex_t			machreadterm;
+	regex_t			searchterm;
+	regex_t			opterm;
+	regex_t			get;
+	char			search[BUFSIZ];
+	char			buf[BUFSIZ];
+	char			*cp;
+	int			newsock;
+	int			code;
+	int			mr;
+	int			ok;
+	int			cc;
+	int			n;
+
+/* GET /pks/lookup?search=agc%40netbsd.org&op=index&options=mr HTTP/1.1\n */
+#define HTTPGET		"GET /pks/lookup\\?"
+#define OPTERM		"op=([a-zA-Z]+)"
+#define SEARCHTERM	"search=([^ \t&]+)"
+#define MACHREAD	"options=mr"
+
+	(void) regcomp(&get, HTTPGET, REG_EXTENDED);
+	(void) regcomp(&opterm, OPTERM, REG_EXTENDED);
+	(void) regcomp(&searchterm, SEARCHTERM, REG_EXTENDED);
+	(void) regcomp(&machreadterm, MACHREAD, REG_EXTENDED);
+	listen(sock, 32);
+	for (;;) {
+		/* read data from socket */
+		fromlen = sizeof(from);
+		newsock = accept(sock, (struct sockaddr *) &from, &fromlen);
+		cc = read(newsock, buf, sizeof(buf));
+		/* parse the request */
+		ok = 1;
+		if (regexec(&get, buf, 10, opmatches, 0) != 0) {
+			(void) fprintf(stderr, "not a valid get request\n");
+			ok = 0;
+		}
+		if (ok && regexec(&opterm, buf, 10, opmatches, 0) != 0) {
+			(void) fprintf(stderr, "no operation in request\n");
+			ok = 0;
+		}
+		if (ok) {
+			mr = (regexec(&machreadterm, buf, 3, mrmatch, 0) == 0);
+		}
+		if (ok && regexec(&searchterm, buf, 10, searchmatches, 0) != 0) {
+			(void) fprintf(stderr, "no search term in request\n");
+			ok = 0;
+		}
+		if (!ok) {
+			(void) close(newsock);
+			continue;
+		}
+		/* convert from %2f to / etc */
+		n = frompercent(&buf[searchmatches[1].rm_so],
+			(int)(searchmatches[1].rm_eo - searchmatches[1].rm_so),
+			search,
+			sizeof(search));
+		code = HKP_NOT_FOUND;
+		cc = 0;
+		if (strncmp(&buf[opmatches[1].rm_so], "vindex", 6) == 0 ||
+		    strncmp(&buf[opmatches[1].rm_so], "index", 5) == 0) {
+			cc = 0;
+			if ((cp = netpgp_get_key(netpgp, search, (mr) ? "mr" : "")) != NULL) {
+				cc = strlen(cp);
+				code = HKP_SUCCESS;
+			}
+			response(newsock, code, search, 0, cp, cc, mr);
+		} else if (strncmp(&buf[opmatches[1].rm_so], "get", 3) == 0) {
+			if ((cp = netpgp_export_key(netpgp, search)) != NULL) {
+				cc = strlen(cp);
+				code = HKP_SUCCESS;
+			}
+			response(newsock, code, search, 1, cp, cc, mr);
+		}
+		free(cp);
+		(void) close(newsock);
+	}
+}
Index: src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.h
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.h:1.1
--- /dev/null	Mon Mar  1 07:41:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/hkpd/hkpd.h	Mon Mar  1 07:41:56 2010
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2009,2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (a...@netbsd.org)
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+#ifndef HKPD_H_
+#define HKPD_H_	20091022
+
+#include <netpgp.h>
+
+#define HKPD_VERSION	20091022
+
+int hkpd_sock_bind(int, const char *, const int);
+int hkpd_sock_get(void);
+int hkpd(netpgp_t *, int);
+
+#endif
Index: src/crypto/external/bsd/netpgp/dist/src/hkpd/main.c
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/hkpd/main.c:1.1
--- /dev/null	Mon Mar  1 07:41:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/hkpd/main.c	Mon Mar  1 07:41:57 2010
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 2009,2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (a...@netbsd.org)
+ *
+ * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "hkpd.h"
+
+#define HAVE_DAEMON	1
+
+/* set the home directory value to "home/subdir" */
+static int
+set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet)
+{
+	struct stat	st;
+	char		d[MAXPATHLEN];
+
+	if (home == NULL) {
+		if (!quiet) {
+			(void) fprintf(stderr, "NULL HOME directory\n");
+		}
+		return 0;
+	}
+	(void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : "");
+	if (stat(d, &st) == 0) {
+		if ((st.st_mode & S_IFMT) == S_IFDIR) {
+			netpgp_setvar(netpgp, "homedir", d);
+			return 1;
+		}
+		(void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n",
+					d);
+		return 0;
+	}
+	if (!quiet) {
+		(void) fprintf(stderr,
+			"netpgp: warning homedir \"%s\" not found\n", d);
+	}
+	return 1;
+}
+
+int
+main(int argc, char **argv)
+{
+	netpgp_t	 netpgp;
+	char		*host;
+	int		 daemonise;
+	int		 port;
+	int		 sock;
+	int		 i;
+
+	(void) memset(&netpgp, 0x0, sizeof(netpgp));
+	/* set some defaults */
+	set_homedir(&netpgp, getenv("HOME"), "/.gnupg", 1);
+	port = 11371;
+	host = strdup("localhost");
+	daemonise = 1;
+	while ((i = getopt(argc, argv, "DH:Vh:p:v:")) != -1) {
+		switch(i) {
+		case 'D':
+			daemonise = 0;
+			break;
+		case 'H':
+			set_homedir(&netpgp, optarg, NULL, 0);
+			break;
+		case 'V':
+			printf("%s: Version %d\n", *argv, HKPD_VERSION);
+			exit(EXIT_SUCCESS);
+		case 'h':
+			(void) free(host);
+			host = strdup(optarg);
+			break;
+		case 'p':
+			port = atoi(optarg);
+			break;
+		case 'v':
+			netpgp_set_debug(optarg);
+			break;
+		default:
+			break;
+		}
+	}
+#ifdef HAVE_DAEMON
+	/* if we are supposed to be a daemon, detach from controlling tty */
+	if (daemonise && daemon(0, 0) < 0) {
+		(void) fprintf(stderr, "daemon() failed\n");
+		exit(EXIT_FAILURE);
+	}
+#endif 
+	if (!netpgp_init(&netpgp)) {
+		(void) fprintf(stderr, "can't initialise\n");
+		exit(EXIT_FAILURE);
+	}
+	if ((sock = hkpd_sock_get()) < 0) {
+		(void) fprintf(stderr,"hkpd: can't get a socket\n");
+		exit(EXIT_FAILURE);
+	}
+	if (hkpd_sock_bind(sock, host, port) < 0) {
+		(void) fprintf(stderr,"hkpd: can't connect socket\n");
+		exit(EXIT_FAILURE);
+	}
+	hkpd(&netpgp, sock);
+}

Reply via email to