aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/testcode/petal.c
diff options
context:
space:
mode:
authoranonimal <anonimal@i2pmail.org>2017-06-28 21:07:24 +0000
committeranonimal <anonimal@i2pmail.org>2018-03-18 15:52:19 +0000
commit84c5a9ba481d7a33cc0fd0ca43867b61d127d907 (patch)
treef05d3d3f107da02005b4a61f0e5074c113a7165c /external/unbound/testcode/petal.c
parentMerge pull request #3416 (diff)
downloadmonero-84c5a9ba481d7a33cc0fd0ca43867b61d127d907.tar.xz
Unbound: remove unbound from in-tree source
We'll instead use a git submodule to pull from our unbound repo.
Diffstat (limited to 'external/unbound/testcode/petal.c')
-rw-r--r--external/unbound/testcode/petal.c669
1 files changed, 0 insertions, 669 deletions
diff --git a/external/unbound/testcode/petal.c b/external/unbound/testcode/petal.c
deleted file mode 100644
index b30549365..000000000
--- a/external/unbound/testcode/petal.c
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * petal.c - https daemon that is small and beautiful.
- *
- * Copyright (c) 2010, NLnet Labs. All rights reserved.
- *
- * This software is open source.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 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.
- *
- * Neither the name of the NLNET LABS nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
- * HOLDER 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.
- */
-
-/**
- * \file
- *
- * HTTP1.1/SSL server.
- */
-
-#include "config.h"
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_OPENSSL_SSL_H
-#include <openssl/ssl.h>
-#endif
-#ifdef HAVE_OPENSSL_ERR_H
-#include <openssl/err.h>
-#endif
-#ifdef HAVE_OPENSSL_RAND_H
-#include <openssl/rand.h>
-#endif
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <ctype.h>
-#include <signal.h>
-#if defined(UNBOUND_ALLOC_LITE) || defined(UNBOUND_ALLOC_STATS)
-#ifdef malloc
-#undef malloc
-#endif
-#ifdef free
-#undef free
-#endif
-#endif /* alloc lite or alloc stats */
-
-/** verbosity for this application */
-static int verb = 0;
-
-/** Give petal usage, and exit (1). */
-static void
-usage(void)
-{
- printf("Usage: petal [opts]\n");
- printf(" https daemon serves files from ./'host'/filename\n");
- printf(" (no hostname: from the 'default' directory)\n");
- printf("-a addr bind to this address, 127.0.0.1\n");
- printf("-p port port number, default 443\n");
- printf("-k keyfile SSL private key file (PEM), petal.key\n");
- printf("-c certfile SSL certificate file (PEM), petal.pem\n");
- printf("-v more verbose\n");
- printf("-h show this usage help\n");
- printf("Version %s\n", PACKAGE_VERSION);
- printf("BSD licensed, see LICENSE in source package for details.\n");
- printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
- exit(1);
-}
-
-/** fatal exit */
-static void print_exit(const char* str) {printf("error %s\n", str); exit(1);}
-/** print errno */
-static void log_errno(const char* str)
-{printf("error %s: %s\n", str, strerror(errno));}
-
-/** parse a text IP address into a sockaddr */
-static int
-parse_ip_addr(char* str, int port, struct sockaddr_storage* ret, socklen_t* l)
-{
- socklen_t len = 0;
- struct sockaddr_storage* addr = NULL;
- struct sockaddr_in6 a6;
- struct sockaddr_in a;
- uint16_t p = (uint16_t)port;
- int fam = 0;
- memset(&a6, 0, sizeof(a6));
- memset(&a, 0, sizeof(a));
-
- if(inet_pton(AF_INET6, str, &a6.sin6_addr) > 0) {
- /* it is an IPv6 */
- fam = AF_INET6;
- a6.sin6_family = AF_INET6;
- a6.sin6_port = (in_port_t)htons(p);
- addr = (struct sockaddr_storage*)&a6;
- len = (socklen_t)sizeof(struct sockaddr_in6);
- }
- if(inet_pton(AF_INET, str, &a.sin_addr) > 0) {
- /* it is an IPv4 */
- fam = AF_INET;
- a.sin_family = AF_INET;
- a.sin_port = (in_port_t)htons(p);
- addr = (struct sockaddr_storage*)&a;
- len = (socklen_t)sizeof(struct sockaddr_in);
- }
- if(!len) print_exit("cannot parse addr");
- *l = len;
- memmove(ret, addr, len);
- return fam;
-}
-
-/** close the fd */
-static void
-fd_close(int fd)
-{
-#ifndef USE_WINSOCK
- close(fd);
-#else
- closesocket(fd);
-#endif
-}
-
-/**
- * Read one line from SSL
- * zero terminates.
- * skips "\r\n" (but not copied to buf).
- * @param ssl: the SSL connection to read from (blocking).
- * @param buf: buffer to return line in.
- * @param len: size of the buffer.
- * @return 0 on error, 1 on success.
- */
-static int
-read_ssl_line(SSL* ssl, char* buf, size_t len)
-{
- size_t n = 0;
- int r;
- int endnl = 0;
- while(1) {
- if(n >= len) {
- if(verb) printf("line too long\n");
- return 0;
- }
- if((r = SSL_read(ssl, buf+n, 1)) <= 0) {
- if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
- /* EOF */
- break;
- }
- if(verb) printf("could not SSL_read\n");
- return 0;
- }
- if(endnl && buf[n] == '\n') {
- break;
- } else if(endnl) {
- /* bad data */
- if(verb) printf("error: stray linefeeds\n");
- return 0;
- } else if(buf[n] == '\r') {
- /* skip \r, and also \n on the wire */
- endnl = 1;
- continue;
- } else if(buf[n] == '\n') {
- /* skip the \n, we are done */
- break;
- } else n++;
- }
- buf[n] = 0;
- return 1;
-}
-
-/** process one http header */
-static int
-process_one_header(char* buf, char* file, size_t flen, char* host, size_t hlen,
- int* vs)
-{
- if(strncasecmp(buf, "GET ", 4) == 0) {
- char* e = strstr(buf, " HTTP/1.1");
- if(!e) e = strstr(buf, " http/1.1");
- if(!e) {
- e = strstr(buf, " HTTP/1.0");
- if(!e) e = strstr(buf, " http/1.0");
- if(!e) e = strrchr(buf, ' ');
- if(!e) e = strrchr(buf, '\t');
- if(e) *vs = 10;
- }
- if(e) *e = 0;
- if(strlen(buf) < 4) return 0;
- (void)strlcpy(file, buf+4, flen);
- } else if(strncasecmp(buf, "Host: ", 6) == 0) {
- (void)strlcpy(host, buf+6, hlen);
- }
- return 1;
-}
-
-/** read http headers and process them */
-static int
-read_http_headers(SSL* ssl, char* file, size_t flen, char* host, size_t hlen,
- int* vs)
-{
- char buf[1024];
- file[0] = 0;
- host[0] = 0;
- while(read_ssl_line(ssl, buf, sizeof(buf))) {
- if(verb>=2) printf("read: %s\n", buf);
- if(buf[0] == 0)
- return 1;
- if(!process_one_header(buf, file, flen, host, hlen, vs))
- return 0;
- }
- return 0;
-}
-
-/** setup SSL context */
-static SSL_CTX*
-setup_ctx(char* key, char* cert)
-{
- SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
- if(!ctx) print_exit("out of memory");
- (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
- (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
- if(!SSL_CTX_use_certificate_chain_file(ctx, cert))
- print_exit("cannot read cert");
- if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM))
- print_exit("cannot read key");
- if(!SSL_CTX_check_private_key(ctx))
- print_exit("private key is not correct");
-#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
- if (!SSL_CTX_set_ecdh_auto(ctx,1))
- if(verb>=1) printf("failed to set_ecdh_auto, not enabling ECDHE\n");
-#elif defined(USE_ECDSA)
- if(1) {
- EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
- if (!ecdh) {
- if(verb>=1) printf("could not find p256, not enabling ECDHE\n");
- } else {
- if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
- if(verb>=1) printf("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE\n");
- }
- EC_KEY_free(ecdh);
- }
- }
-#endif
- if(!SSL_CTX_load_verify_locations(ctx, cert, NULL))
- print_exit("cannot load cert verify locations");
- return ctx;
-}
-
-/** setup listening TCP */
-static int
-setup_fd(char* addr, int port)
-{
- struct sockaddr_storage ad;
- socklen_t len;
- int fd;
- int c = 1;
- int fam = parse_ip_addr(addr, port, &ad, &len);
- fd = socket(fam, SOCK_STREAM, 0);
- if(fd == -1) {
- log_errno("socket");
- return -1;
- }
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- (void*)&c, (socklen_t) sizeof(int)) < 0) {
- log_errno("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
- }
- if(bind(fd, (struct sockaddr*)&ad, len) == -1) {
- log_errno("bind");
- fd_close(fd);
- return -1;
- }
- if(listen(fd, 5) == -1) {
- log_errno("listen");
- fd_close(fd);
- return -1;
- }
- return fd;
-}
-
-/** setup SSL connection to the client */
-static SSL*
-setup_ssl(int s, SSL_CTX* ctx)
-{
- SSL* ssl = SSL_new(ctx);
- if(!ssl) return NULL;
- SSL_set_accept_state(ssl);
- (void)SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
- if(!SSL_set_fd(ssl, s)) {
- SSL_free(ssl);
- return NULL;
- }
- return ssl;
-}
-
-/** check a file name for safety */
-static int
-file_name_is_safe(char* s)
-{
- size_t l = strlen(s);
- if(s[0] != '/')
- return 0; /* must start with / */
- if(strstr(s, "/../"))
- return 0; /* no updirs in URL */
- if(l>=3 && s[l-1]=='.' && s[l-2]=='.' && s[l-3]=='/')
- return 0; /* ends with /.. */
- return 1;
-}
-
-/** adjust host and filename */
-static void
-adjust_host_file(char* host, char* file)
-{
- size_t i, len;
- /* remove a port number if present */
- if(strrchr(host, ':'))
- *strrchr(host, ':') = 0;
- /* lowercase */
- len = strlen(host);
- for(i=0; i<len; i++)
- host[i] = tolower((unsigned char)host[i]);
- len = strlen(file);
- for(i=0; i<len; i++)
- file[i] = tolower((unsigned char)file[i]);
-}
-
-/** check a host name for safety */
-static int
-host_name_is_safe(char* s)
-{
- if(strchr(s, '/'))
- return 0;
- if(strcmp(s, "..") == 0)
- return 0;
- if(strcmp(s, ".") == 0)
- return 0;
- return 1;
-}
-
-/** provide file in whole transfer */
-static void
-provide_file_10(SSL* ssl, char* fname)
-{
- char* buf, *at;
- size_t len, avail, header_reserve=1024;
- FILE* in = fopen(fname,
-#ifndef USE_WINSOCK
- "r"
-#else
- "rb"
-#endif
- );
- size_t r;
- const char* rcode = "200 OK";
- if(!in) {
- char hdr[1024];
- rcode = "404 File not found";
- snprintf(hdr, sizeof(hdr), "HTTP/1.1 %s\r\n\r\n", rcode);
- r = strlen(hdr);
- if(SSL_write(ssl, hdr, (int)r) <= 0) {
- /* write failure */
- }
- return;
- }
- fseek(in, 0, SEEK_END);
- len = (size_t)ftell(in);
- fseek(in, 0, SEEK_SET);
- /* plus some space for the header */
- buf = (char*)malloc(len+header_reserve);
- if(!buf) {
- fclose(in);
- return;
- }
- avail = len+header_reserve;
- at = buf;
- snprintf(at, avail, "HTTP/1.1 %s\r\n", rcode);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Server: petal/%s\r\n", PACKAGE_VERSION);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Content-Length: %u\r\n", (unsigned)len);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- if(avail < len) { /* robust */
- free(buf);
- fclose(in);
- return;
- }
- if(fread(at, 1, len, in) != len) {
- free(buf);
- fclose(in);
- return;
- }
- fclose(in);
- at += len;
- avail -= len;
- if(SSL_write(ssl, buf, at-buf) <= 0) {
- /* write failure */
- }
- free(buf);
-}
-
-/** provide file over SSL, chunked encoding */
-static void
-provide_file_chunked(SSL* ssl, char* fname)
-{
- char buf[16384];
- char* tmpbuf = NULL;
- char* at = buf;
- size_t avail = sizeof(buf);
- size_t r;
- FILE* in = fopen(fname,
-#ifndef USE_WINSOCK
- "r"
-#else
- "rb"
-#endif
- );
- const char* rcode = "200 OK";
- if(!in) {
- rcode = "404 File not found";
- }
-
- /* print headers */
- snprintf(at, avail, "HTTP/1.1 %s\r\n", rcode);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Server: petal/%s\r\n", PACKAGE_VERSION);
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Transfer-Encoding: chunked\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "Connection: close\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- if(avail < 16) { /* robust */
- if(in) fclose(in);
- return;
- }
-
- do {
- size_t red;
- free(tmpbuf);
- tmpbuf = malloc(avail-16);
- if(!tmpbuf)
- break;
- /* read chunk; space-16 for xxxxCRLF..CRLF0CRLFCRLF (3 spare)*/
- red = in?fread(tmpbuf, 1, avail-16, in):0;
- /* prepare chunk */
- snprintf(at, avail, "%x\r\n", (unsigned)red);
- r = strlen(at);
- if(verb >= 3)
- {printf("chunk len %x\n", (unsigned)red); fflush(stdout);}
- at += r;
- avail -= r;
- if(red != 0) {
- if(red > avail) break; /* robust */
- memmove(at, tmpbuf, red);
- at += red;
- avail -= red;
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- }
- if(in && feof(in) && red != 0) {
- snprintf(at, avail, "0\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- }
- if(!in || feof(in)) {
- snprintf(at, avail, "\r\n");
- r = strlen(at);
- at += r;
- avail -= r;
- }
- /* send chunk */
- if(SSL_write(ssl, buf, at-buf) <= 0) {
- /* SSL error */
- break;
- }
-
- /* setup for next chunk */
- at = buf;
- avail = sizeof(buf);
- } while(in && !feof(in) && !ferror(in));
-
- free(tmpbuf);
- if(in) fclose(in);
-}
-
-/** provide service to the ssl descriptor */
-static void
-service_ssl(SSL* ssl, struct sockaddr_storage* from, socklen_t falen)
-{
- char file[1024];
- char host[1024];
- char combined[2048];
- int vs = 11;
- if(!read_http_headers(ssl, file, sizeof(file), host, sizeof(host),
- &vs))
- return;
- adjust_host_file(host, file);
- if(host[0] == 0 || !host_name_is_safe(host))
- (void)strlcpy(host, "default", sizeof(host));
- if(!file_name_is_safe(file)) {
- return;
- }
- snprintf(combined, sizeof(combined), "%s%s", host, file);
- if(verb) {
- char out[100];
- void* a = &((struct sockaddr_in*)from)->sin_addr;
- if(falen != (socklen_t)sizeof(struct sockaddr_in))
- a = &((struct sockaddr_in6*)from)->sin6_addr;
- out[0]=0;
- (void)inet_ntop((int)((struct sockaddr_in*)from)->sin_family,
- a, out, (socklen_t)sizeof(out));
- printf("%s requests %s\n", out, combined);
- fflush(stdout);
- }
- if(vs == 10)
- provide_file_10(ssl, combined);
- else provide_file_chunked(ssl, combined);
-}
-
-/** provide ssl service */
-static void
-do_service(char* addr, int port, char* key, char* cert)
-{
- SSL_CTX* sslctx = setup_ctx(key, cert);
- int fd = setup_fd(addr, port);
- int go = 1;
- if(fd == -1) print_exit("could not setup sockets");
- if(verb) {printf("petal start\n"); fflush(stdout);}
- while(go) {
- struct sockaddr_storage from;
- socklen_t flen = (socklen_t)sizeof(from);
- int s = accept(fd, (struct sockaddr*)&from, &flen);
- if(verb) fflush(stdout);
- if(s != -1) {
- SSL* ssl = setup_ssl(s, sslctx);
- if(verb) fflush(stdout);
- if(ssl) {
- service_ssl(ssl, &from, flen);
- if(verb) fflush(stdout);
- SSL_shutdown(ssl);
- SSL_free(ssl);
- }
- fd_close(s);
- } else if (verb >=2) log_errno("accept");
- if(verb) fflush(stdout);
- }
- /* if we get a kill signal, the process dies and the OS reaps us */
- if(verb) printf("petal end\n");
- fd_close(fd);
- SSL_CTX_free(sslctx);
-}
-
-/** getopt global, in case header files fail to declare it. */
-extern int optind;
-/** getopt global, in case header files fail to declare it. */
-extern char* optarg;
-
-/** Main routine for petal */
-int main(int argc, char* argv[])
-{
- int c;
- int port = 443;
- char* addr = "127.0.0.1", *key = "petal.key", *cert = "petal.pem";
-#ifdef USE_WINSOCK
- WSADATA wsa_data;
- if((c=WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
- { printf("WSAStartup failed\n"); exit(1); }
- atexit((void (*)(void))WSACleanup);
-#endif
-
- /* parse the options */
- while( (c=getopt(argc, argv, "a:c:k:hp:v")) != -1) {
- switch(c) {
- case 'a':
- addr = optarg;
- break;
- case 'c':
- cert = optarg;
- break;
- case 'k':
- key = optarg;
- break;
- case 'p':
- port = atoi(optarg);
- break;
- case 'v':
- verb++;
- break;
- case '?':
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if(argc != 0)
- usage();
-
-#ifdef SIGPIPE
- (void)signal(SIGPIPE, SIG_IGN);
-#endif
-#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
- ERR_load_crypto_strings();
-#endif
- ERR_load_SSL_strings();
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
- OpenSSL_add_all_algorithms();
-#else
- OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
- | OPENSSL_INIT_ADD_ALL_DIGESTS
- | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
-#endif
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
- (void)SSL_library_init();
-#else
- (void)OPENSSL_init_ssl(0, NULL);
-#endif
-
- do_service(addr, port, key, cert);
-
-#ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
- CRYPTO_cleanup_all_ex_data();
-#endif
-#ifdef HAVE_ERR_FREE_STRINGS
- ERR_free_strings();
-#endif
- return 0;
-}