122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/* Copyright (c) 2012, Jacob Appelbaum. 222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Copyright (c) 2012, The Tor Project, Inc. 322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Copyright (c) 2012, Christian Grothoff. */ 422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/* See LICENSE for licensing information */ 522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/* 622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans This file contains the license for tlsdate, 722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans a free software project to set your system clock securely. 822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans It also lists the licenses for other components used by tlsdate. 1022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 1122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans For more information about tlsdate, see https://github.com/ioerror/tlsdate 1222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 1322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans If you got this file as a part of a larger bundle, 1422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans there may be other license terms that you should be aware of. 1522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 1622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans=============================================================================== 1722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanstlsdate is distributed under this license: 1822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 1922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansCopyright (c) 2011-2012, Jacob Appelbaum <jacob@appelbaum.net> 2022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansCopyright (c) 2011-2012, The Tor Project, Inc. 2122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 2222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansRedistribution and use in source and binary forms, with or without 2322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansmodification, are permitted provided that the following conditions are 2422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansmet: 2522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 2622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Redistributions of source code must retain the above copyright 2722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansnotice, this list of conditions and the following disclaimer. 2822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 2922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Redistributions in binary form must reproduce the above 3022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscopyright notice, this list of conditions and the following disclaimer 3122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansin the documentation and/or other materials provided with the 3222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansdistribution. 3322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 3422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Neither the names of the copyright owners nor the names of its 3522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscontributors may be used to endorse or promote products derived from 3622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansthis software without specific prior written permission. 3722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 3822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 4022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 4122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 4222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 4422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 4522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 4622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 4722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 4822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans=============================================================================== 5022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah EvansIf you got tlsdate as a static binary with OpenSSL included, then you should 5122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansknow: 5222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 5322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans "This product includes software developed by the OpenSSL Project for use in 5422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans the OpenSSL Toolkit (http://www.openssl.org/)" 5522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 5622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans=============================================================================== 5722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans*/ 5822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 5922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** 6022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * \file tlsdate-helper.c 6122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * \brief Helper program that does the actual work of setting the system clock. 6222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans **/ 6322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 6422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/* 6522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * tlsdate is a tool for setting the system clock by hand or by communication 6622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * with the network. It does not set the RTC. It is designed to be as secure as 6722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * TLS (RFC 2246) but of course the security of TLS is often reduced to 6822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * whichever CA racket you believe is trustworthy. By default, tlsdate trusts 6922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * your local CA root store - so any of these companies could assist in a MITM 7022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * attack against you and you'd be screwed. 7122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 7222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * This tool is designed to be run by hand or as a system daemon. It must be 7322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * run as root or otherwise have the proper caps; it will not be able to set 7422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * the system time without running as root or another privileged user. 7522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 7622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 7722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "config.h" 7822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "src/tlsdate-helper-plan9.h" 7922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 8022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifndef USE_POLARSSL 8122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "src/proxy-bio-plan9.h" 8222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#else 8322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "src/proxy-polarssl.h" 8422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 8522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 8622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "src/compat/clock-plan9.h" 8722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 8822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifndef MAP_ANONYMOUS 8922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#define MAP_ANONYMOUS MAP_ANON 9022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 9122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 9222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifdef USE_POLARSSL 9322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "polarssl/entropy.h" 9422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "polarssl/ctr_drbg.h" 9522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#include "polarssl/ssl.h" 9622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 9722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 9822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 9922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvalidate_proxy_scheme(const char *scheme) 10022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 10122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!strcmp(scheme, "http")) 10222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return; 10322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!strcmp(scheme, "socks4")) 10422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return; 10522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!strcmp(scheme, "socks5")) 10622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return; 10722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("invalid proxy scheme\n"); 10822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 10922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 11022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 11122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvalidate_proxy_host(const char *host) 11222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 11322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const char *kValid = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 11422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans "abcdefghijklmnopqrstuvwxyz" 11522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans "0123456789" 11622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ".-"; 11722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (strspn(host, kValid) != strlen(host)) 11822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("invalid char in host\n"); 11922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 12022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 12122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 12222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvalidate_proxy_port(const char *port) 12322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 12422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans while (*port) 12522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!isdigit(*port++)) 12622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("invalid char in port\n"); 12722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 12822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 12922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 13022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansparse_proxy_uri(char *proxy, char **scheme, char **host, char **port) 13122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 13222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* Expecting a URI, so: <scheme> '://' <host> ':' <port> */ 13322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans *scheme = proxy; 13422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy = strstr(proxy, "://"); 13522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!proxy) 13622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("malformed proxy URI\n"); 13722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans *proxy = '\0'; /* terminate scheme string */ 13822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy += strlen("://"); 13922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 14022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans *host = proxy; 14122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy = strchr(proxy, ':'); 14222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!proxy) 14322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("malformed proxy URI\n"); 14422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans *proxy++ = '\0'; 14522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 14622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans *port = proxy; 14722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 14822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans validate_proxy_scheme(*scheme); 14922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans validate_proxy_host(*host); 15022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans validate_proxy_port(*port); 15122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 15222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 15322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifndef USE_POLARSSL 15422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 15522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanssetup_proxy(BIO *ssl) 15622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 15722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO *bio; 15822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *scheme; 15922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *proxy_host; 16022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *proxy_port; 16122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 16222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!proxy) 16322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return; 16422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* 16522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * grab the proxy's host and port out of the URI we have for it. We want the 16622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * underlying connect BIO to connect to this, not the target host and port, so 16722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * we squirrel away the target host and port in the proxy BIO (as the proxy 16822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * target) and swap out the connect BIO's target host and port so it'll 16922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * connect to the proxy instead. 17022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 17122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans parse_proxy_uri(proxy, &scheme, &proxy_host, &proxy_port); 17222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans bio = BIO_new_proxy(); 17322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO_proxy_set_type(bio, scheme); 17422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO_proxy_set_host(bio, host); 17522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO_proxy_set_port(bio, atoi(port)); 17622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans host = proxy_host; 17722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans port = proxy_port; 17822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO_push(ssl, bio); 17922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 18022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 18122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic BIO * 18222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansmake_ssl_bio(SSL_CTX *ctx) 18322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 18422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO *con = NULL; 18522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO *ssl = NULL; 18622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 18722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!(con = BIO_new(BIO_s_connect()))) 18822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("BIO_s_connect failed\n"); 18922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!(ssl = BIO_new_ssl(ctx, 1))) 19022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("BIO_new_ssl failed\n"); 19122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans setup_proxy(ssl); 19222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO_push(ssl, con); 19322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return ssl; 19422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 19522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 19622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** helper function for 'malloc' */ 19722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void * 19822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansxmalloc (size_t size) 19922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 20022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans void *ptr; 20122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 20222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == size) 20322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("xmalloc: zero size\n"); 20422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 20522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ptr = malloc(size); 20622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == ptr) 20722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("xmalloc: out of memory (allocating %zu bytes)\n", size); 20822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 20922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return ptr; 21022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 21122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 21222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 21322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** helper function for 'free' */ 21422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 21522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansxfree (void *ptr) 21622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 21722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == ptr) 21822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("xfree: NULL pointer given as argument\n"); 21922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 22022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans free(ptr); 22122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 22222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 22322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvoid 22422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansopenssl_time_callback (const SSL* ssl, int where, int ret) 22522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 22622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (where == SSL_CB_CONNECT_LOOP && 22722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (ssl->state == SSL3_ST_CR_SRVR_HELLO_A || ssl->state == SSL3_ST_CR_SRVR_HELLO_B)) 22822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 22922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* 23022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // XXX TODO: If we want to trust the remote system for time, 23122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // can we just read that time out of the remote system and if the 23222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // cert verifies, decide that the time is reasonable? 23322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Such a process seems to indicate that a once valid cert would be 23422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // forever valid - we stopgap that by ensuring it isn't less than 23522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // the latest compiled_time and isn't above max_reasonable_time... 23622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // XXX TODO: Solve eternal question about the Chicken and the Egg... 23722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 23822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t compiled_time = RECENT_COMPILE_DATE; 23922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t max_reasonable_time = MAX_REASONABLE_TIME; 24022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t server_time; 24122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: freezing time for x509 verification\n"); 24222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans memcpy(&server_time, ssl->s3->server_random, sizeof(uint32_t)); 24322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (compiled_time < ntohl(server_time) 24422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans && 24522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ntohl(server_time) < max_reasonable_time) 24622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 24722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: remote peer provided: %d, preferred over compile time: %d\n", 24822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ntohl(server_time), compiled_time); 24922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: freezing time with X509_VERIFY_PARAM_set_time\n"); 25022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509_VERIFY_PARAM_set_time(ssl->ctx->cert_store->param, 25122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (time_t) ntohl(server_time) + 86400); 25222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 25322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("V: the remote server is a false ticker! server: %d compile: %d\n", 25422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ntohl(server_time), compiled_time); 25522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 25622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 25722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 25822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 25922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 26022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansget_certificate_keybits (EVP_PKEY *public_key) 26122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 26222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* 26322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans In theory, we could use check_bitlen_dsa() and check_bitlen_rsa() 26422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 26522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t key_bits; 26622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans switch (public_key->type) 26722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 26822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_RSA: 26922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_RSA\n"); 27022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.rsa->n); 27122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 27222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_RSA2: 27322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_RSA2\n"); 27422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.rsa->n); 27522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 27622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_DSA: 27722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_DSA\n"); 27822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.dsa->p); 27922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 28022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_DSA1: 28122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_DSA1\n"); 28222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.dsa->p); 28322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 28422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_DSA2: 28522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_DSA2\n"); 28622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.dsa->p); 28722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 28822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_DSA3: 28922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_DSA3\n"); 29022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.dsa->p); 29122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 29222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_DSA4: 29322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_DSA4\n"); 29422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.dsa->p); 29522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 29622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_DH: 29722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_DH\n"); 29822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = BN_num_bits(public_key->pkey.dh->pub_key); 29922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 30022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case EVP_PKEY_EC: 30122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: key type: EVP_PKEY_EC\n"); 30222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = EVP_PKEY_bits(public_key); 30322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 30422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Should we also care about EVP_PKEY_HMAC and EVP_PKEY_CMAC? 30522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans default: 30622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = 0; 30722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("unknown public key type\n"); 30822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 30922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 31022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: keybits: %d\n", key_bits); 31122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return key_bits; 31222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 31322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 31422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 31522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansdns_label_count(char *label, char *delim) 31622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 31722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *label_tmp; 31822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *saveptr; 31922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *saveptr_tmp; 32022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t label_count; 32122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 32222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans label_tmp = strdup(label); 32322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans label_count = 0; 32422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans saveptr = NULL; 32522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans saveptr_tmp = NULL; 32622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans saveptr = strtok_r(label_tmp, delim, &saveptr); 32722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL != saveptr) 32822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 32922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Did we find our first label? 33022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (saveptr[0] != delim[0]) 33122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 33222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans label_count++; 33322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: label found; total label count: %d\n", label_count); 33422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 33522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans do 33622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 33722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Find all subsequent labels 33822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans label_count++; 33922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans saveptr_tmp = strtok_r(NULL, delim, &saveptr); 34022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: label found; total label count: %d\n", label_count); 34122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } while (NULL != saveptr_tmp); 34222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 34322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans free(label_tmp); 34422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return label_count; 34522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 34622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 34722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans// first we split strings on '.' 34822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans// then we call each split string a 'label' 34922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans// Do not allow '*' for the top level domain label; eg never allow *.*.com 35022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans// Do not allow '*' for subsequent subdomains; eg never allow *.foo.example.com 35122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans// Do allow *.example.com 35222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 35322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_wildcard_match_rfc2595 (const char *orig_hostname, 35422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const char *orig_cert_wild_card) 35522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 35622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *hostname; 35722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *hostname_to_free; 35822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *cert_wild_card; 35922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *cert_wild_card_to_free; 36022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *expected_label; 36122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *wildcard_label; 36222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *delim; 36322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *wildchar; 36422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t ok; 36522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t wildcard_encountered; 36622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t label_count; 36722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 36822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // First we copy the original strings 36922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans hostname = strdup(orig_hostname); 37022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans cert_wild_card = strdup(orig_cert_wild_card); 37122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans hostname_to_free = hostname; 37222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans cert_wild_card_to_free = cert_wild_card; 37322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans delim = strdup("."); 37422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans wildchar = strdup("*"); 37522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 37622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Inspecting '%s' for possible wildcard match against '%s'\n", 37722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans hostname, cert_wild_card); 37822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 37922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // By default we have not processed any labels 38022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans label_count = dns_label_count(cert_wild_card, delim); 38122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 38222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // By default we have no match 38322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = 0; 38422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans wildcard_encountered = 0; 38522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // First - do we have labels? If not, we refuse to even try to match 38622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if ((NULL != strpbrk(cert_wild_card, delim)) && 38722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (NULL != strpbrk(hostname, delim)) && 38822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (label_count <= ((uint32_t)RFC2595_MIN_LABEL_COUNT))) 38922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 39022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (wildchar[0] == cert_wild_card[0]) 39122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 39222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Found wildcard in at start of provided certificate name\n"); 39322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans do 39422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 39522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Skip over the bytes between the first char and until the next label 39622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans wildcard_label = strtok(cert_wild_card, delim); 39722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans expected_label = strtok(hostname, delim); 39822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL != wildcard_label && 39922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans NULL != expected_label && 40022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans NULL != hostname && 40122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans NULL != cert_wild_card) 40222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 40322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Now we only consider this wildcard valid if the rest of the 40422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // hostnames match verbatim 40522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Attempting match of '%s' against '%s'\n", 40622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans expected_label, wildcard_label); 40722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // This is the case where we have a label that begins with wildcard 40822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Furthermore, we only allow this for the first label 40922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (wildcard_label[0] == wildchar[0] && 41022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 0 == wildcard_encountered && 0 == ok) 41122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 41222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Forced match of '%s' against '%s'\n", expected_label, wildcard_label); 41322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans wildcard_encountered = 1; 41422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 41522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Attempting match of '%s' against '%s'\n", 41622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans hostname, cert_wild_card); 41722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == strcasecmp (expected_label, wildcard_label) && 41822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans label_count >= ((uint32_t)RFC2595_MIN_LABEL_COUNT)) 41922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 42022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = 1; 42122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: remaining labels match!\n"); 42222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 42322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 42422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = 0; 42522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: remaining labels do not match!\n"); 42622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 42722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 42822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 42922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 43022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // We hit this case when we have a mismatched number of labels 43122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: NULL label; no wildcard here\n"); 43222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 43322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 43422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } while (0 != wildcard_encountered && label_count <= RFC2595_MIN_LABEL_COUNT); 43522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 43622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Not a RFC 2595 wildcard\n"); 43722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 43822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 43922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Not a valid wildcard certificate\n"); 44022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = 0; 44122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 44222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Free our copies 44322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans free(wildchar); 44422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans free(delim); 44522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans free(hostname_to_free); 44622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans free(cert_wild_card_to_free); 44722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (wildcard_encountered & ok && label_count >= RFC2595_MIN_LABEL_COUNT) 44822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 44922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: wildcard match of %s against %s\n", 45022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans orig_hostname, orig_cert_wild_card); 45122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return (wildcard_encountered & ok); 45222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 45322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: wildcard match failure of %s against %s\n", 45422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans orig_hostname, orig_cert_wild_card); 45522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 0; 45622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 45722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 45822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 45922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 46022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifndef USE_POLARSSL 46122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** 46222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans This extracts the first commonName and checks it against hostname. 46322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans*/ 46422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 46522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_cn (SSL *ssl, const char *hostname) 46622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 46722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int ok = 0; 46822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int ret; 46922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *cn_buf; 47022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509 *certificate; 47122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509_NAME *xname; 47222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 47322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // We cast this to cast away g++ complaining about the following: 47422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // error: invalid conversion from ‘void*’ to ‘char*’ 47522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans cn_buf = (char *) xmalloc(TLSDATE_HOST_NAME_MAX + 1); 47622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 47722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans certificate = SSL_get_peer_certificate(ssl); 47822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == certificate) 47922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 48022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Unable to extract certificate\n"); 48122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 48222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 48322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans memset(cn_buf, '\0', (TLSDATE_HOST_NAME_MAX + 1)); 48422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans xname = X509_get_subject_name(certificate); 48522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ret = X509_NAME_get_text_by_NID(xname, NID_commonName, 48622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans cn_buf, TLSDATE_HOST_NAME_MAX); 48722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 48822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (-1 == ret || ret != (int) strlen(cn_buf)) 48922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 49022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Unable to extract commonName\n"); 49122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 49222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (strcasecmp(cn_buf, hostname)) 49322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 49422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: commonName mismatch! Expected: %s - received: %s\n", 49522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans hostname, cn_buf); 49622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 49722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: commonName matched: %s\n", cn_buf); 49822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = 1; 49922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 50022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 50122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509_NAME_free(xname); 50222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509_free(certificate); 50322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans xfree(cn_buf); 50422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 50522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return ok; 50622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 50722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 50822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** 50922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans Search for a hostname match in the SubjectAlternativeNames. 51022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans*/ 51122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 51222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_san (SSL *ssl, const char *hostname) 51322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 51422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509 *cert; 51522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int extcount, ok = 0; 51622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* What an OpenSSL mess ... */ 51722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == (cert = SSL_get_peer_certificate(ssl))) 51822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 51922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Getting certificate failed\n"); 52022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 52122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 52222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if ((extcount = X509_get_ext_count(cert)) > 0) 52322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 52422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int i; 52522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans for (i = 0; i < extcount; ++i) 52622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 52722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const char *extstr; 52822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509_EXTENSION *ext; 52922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ext = X509_get_ext(cert, i); 53022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans extstr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); 53122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 53222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!strcmp(extstr, "subjectAltName")) 53322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 53422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 53522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int j; 53622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans void *extvalstr; 53722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const unsigned char *tmp; 53822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 53922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans STACK_OF(CONF_VALUE) *val; 54022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans CONF_VALUE *nval; 54122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#if OPENSSL_VERSION_NUMBER >= 0x10000000L 54222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const 54322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 54422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509V3_EXT_METHOD *method; 54522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 54622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!(method = X509V3_EXT_get(ext))) 54722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 54822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 54922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 55022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 55122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans tmp = ext->value->data; 55222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (method->it) 55322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 55422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans extvalstr = ASN1_item_d2i(NULL, &tmp, ext->value->length, 55522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ASN1_ITEM_ptr(method->it)); 55622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 55722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans extvalstr = method->d2i(NULL, &tmp, ext->value->length); 55822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 55922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 56022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!extvalstr) 56122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 56222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 56322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 56422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 56522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (method->i2v) 56622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 56722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans val = method->i2v(method, extvalstr, NULL); 56822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans for (j = 0; j < sk_CONF_VALUE_num(val); ++j) 56922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 57022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans nval = sk_CONF_VALUE_value(val, j); 57122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if ((!strcasecmp(nval->name, "DNS") && 57222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans !strcasecmp(nval->value, hostname) ) || 57322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (!strcasecmp(nval->name, "iPAddress") && 57422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans !strcasecmp(nval->value, hostname))) 57522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 57622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: subjectAltName matched: %s, type: %s\n", nval->value, nval->name); /* We matched this; so it's safe to print */ 57722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = 1; 57822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 57922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 58022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Attempt to match subjectAltName DNS names 58122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (!strcasecmp(nval->name, "DNS")) 58222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 58322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ok = check_wildcard_match_rfc2595(hostname, nval->value); 58422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ok) 58522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 58622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 58722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 58822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 58922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: subjectAltName found but not matched: %s, type: %s\n", nval->value, nval->name); // XXX: Clean this string! 59022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 59122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 59222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 59322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: found non subjectAltName extension\n"); 59422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 59522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ok) 59622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 59722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 59822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 59922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 60022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 60122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: no X509_EXTENSION field(s) found\n"); 60222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 60322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509_free(cert); 60422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return ok; 60522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 60622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 60722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 60822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_name (SSL *ssl, const char *hostname) 60922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 61022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t ret; 61122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ret = check_cn(ssl, hostname); 61222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ret += check_san(ssl, hostname); 61322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != ret && 0 < ret) 61422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 61522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: hostname verification passed\n"); 61622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 61722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("hostname verification failed for host %s!\n", host); 61822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 61922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return ret; 62022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 62122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 62222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 62322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifdef USE_POLARSSL 62422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 62522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansverify_signature (ssl_context *ssl, const char *hostname) 62622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 62722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int ssl_verify_result; 62822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 62922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_verify_result = ssl_get_verify_result (ssl); 63022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ssl_verify_result & BADCERT_EXPIRED) 63122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 63222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("certificate has expired\n"); 63322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 63422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ssl_verify_result & BADCERT_REVOKED) 63522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 63622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("certificate has been revoked\n"); 63722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 63822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ssl_verify_result & BADCERT_CN_MISMATCH) 63922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 64022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("CN and subject AltName mismatch for certificate\n"); 64122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 64222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ssl_verify_result & BADCERT_NOT_TRUSTED) 64322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 64422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("certificate is self-signed or not signed by a trusted CA\n"); 64522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 64622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 64722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == ssl_verify_result) 64822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 64922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: verify success\n"); 65022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 65122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans else 65222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 65322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("certificate verification error: -0x%04x\n", -ssl_verify_result); 65422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 65522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 0; 65622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 65722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#else 65822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansuint32_t 65922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansverify_signature (SSL *ssl, const char *hostname) 66022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 66122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans long ssl_verify_result; 66222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509 *certificate; 66322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 66422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans certificate = SSL_get_peer_certificate(ssl); 66522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == certificate) 66622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 66722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Getting certificate failed\n"); 66822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 66922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // In theory, we verify that the cert is valid 67022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_verify_result = SSL_get_verify_result(ssl); 67122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans switch (ssl_verify_result) 67222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 67322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 67422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 67522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("certificate is self signed\n"); 67622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case X509_V_OK: 67722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: certificate verification passed\n"); 67822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 67922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans default: 68022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("certification verification error: %ld\n", 68122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_verify_result); 68222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 68322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 0; 68422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 68522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 68622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 68722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifdef USE_POLARSSL 68822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvoid 68922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_key_length (ssl_context *ssl) 69022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 69122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t key_bits; 69222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const x509_cert *certificate; 69322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans const rsa_context *public_key; 69422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char buf[1024]; 69522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 69622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans certificate = ssl_get_peer_cert (ssl); 69722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == certificate) 69822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 69922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Getting certificate failed\n"); 70022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 70122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 70222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans x509parse_dn_gets(buf, 1024, &certificate->subject); 70322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Certificate for subject '%s'\n", buf); 70422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 70522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans public_key = &certificate->rsa; 70622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == public_key) 70722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 70822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("public key extraction failure\n"); 70922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 71022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: public key is ready for inspection\n"); 71122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 71222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = mpi_msb (&public_key->N); 71322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (MIN_PUB_KEY_LEN >= key_bits) 71422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 71522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Unsafe public key size: %d bits\n", key_bits); 71622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 71722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: key length appears safe\n"); 71822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 71922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 72022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#else 72122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvoid 72222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_key_length (SSL *ssl) 72322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 72422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t key_bits; 72522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans X509 *certificate; 72622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans EVP_PKEY *public_key; 72722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans certificate = SSL_get_peer_certificate (ssl); 72822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == certificate) 72922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 73022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Getting certificate failed\n"); 73122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 73222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans public_key = X509_get_pubkey (certificate); 73322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == public_key) 73422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 73522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("public key extraction failure\n"); 73622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 73722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: public key is ready for inspection\n"); 73822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 73922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 74022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans key_bits = get_certificate_keybits (public_key); 74122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (MIN_PUB_KEY_LEN >= key_bits && public_key->type != EVP_PKEY_EC) 74222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 74322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Unsafe public key size: %d bits\n", key_bits); 74422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 74522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (public_key->type == EVP_PKEY_EC) 74622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if(key_bits >= MIN_ECC_PUB_KEY_LEN 74722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans && key_bits <= MAX_ECC_PUB_KEY_LEN) 74822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 74922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: ECC key length appears safe\n"); 75022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 75122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Unsafe ECC key size: %d bits\n", key_bits); 75222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 75322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: key length appears safe\n"); 75422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 75522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 75622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans EVP_PKEY_free (public_key); 75722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 75822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 75922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 76022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifdef USE_POLARSSL 76122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvoid 76222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansinspect_key (ssl_context *ssl, const char *hostname) 76322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 76422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verify_signature (ssl, hostname); 76522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 76622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // ssl_get_verify_result() already checks for CN / subjectAltName match 76722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // and reports the mismatch as error. So check_name() is not called 76822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 76922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#else 77022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvoid 77122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansinspect_key (SSL *ssl, const char *hostname) 77222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 77322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 77422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verify_signature (ssl, hostname); 77522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans check_name (ssl, hostname); 77622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 77722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 77822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 77922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifdef USE_POLARSSL 78022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansvoid 78122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evanscheck_timestamp (uint32_t server_time) 78222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 78322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t compiled_time = RECENT_COMPILE_DATE; 78422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t max_reasonable_time = MAX_REASONABLE_TIME; 78522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (compiled_time < server_time 78622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans && 78722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans server_time < max_reasonable_time) 78822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 78922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: remote peer provided: %d, preferred over compile time: %d\n", 79022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans server_time, compiled_time); 79122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 79222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("V: the remote server is a false ticker! server: %d compile: %d\n", 79322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans server_time, compiled_time); 79422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 79522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 79622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 79722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic int ssl_do_handshake_part(ssl_context *ssl) 79822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 79922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int ret = 0; 80022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 80122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* Only do steps till ServerHello is received */ 80222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans while (ssl->state != SSL_SERVER_HELLO) 80322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 80422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ret = ssl_handshake_step (ssl); 80522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != ret) 80622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 80722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("SSL handshake failed\n"); 80822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 80922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 81022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* Do ServerHello so we can skim the timestamp */ 81122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ret = ssl_handshake_step (ssl); 81222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != ret) 81322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 81422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("SSL handshake failed\n"); 81522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 81622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 81722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 0; 81822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 81922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 82022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** 82122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Run SSL handshake and store the resulting time value in the 82222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * 'time_map'. 82322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * 82422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * @param time_map where to store the current time 82522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 82622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 82722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansrun_ssl (uint32_t *time_map, int time_is_an_illusion) 82822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 82922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans entropy_context entropy; 83022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ctr_drbg_context ctr_drbg; 83122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_context ssl; 83222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_ctx proxy_ctx; 83322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans x509_cert cacert; 83422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans struct stat statbuf; 83522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int ret = 0, server_fd = 0; 83622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *pers = "tlsdate-helper"; 83722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 83822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans memset (&ssl, 0, sizeof(ssl_context)); 83922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans memset (&cacert, 0, sizeof(x509_cert)); 84022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 84122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: Using PolarSSL for SSL\n"); 84222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ca_racket) 84322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 84422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (-1 == stat (ca_cert_container, &statbuf)) 84522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 84622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Unable to stat CA certficate container %s\n", ca_cert_container); 84722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 84822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans else 84922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 85022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans switch (statbuf.st_mode & S_IFMT) 85122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 85222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case S_IFREG: 85322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 > x509parse_crtfile(&cacert, ca_cert_container)) 85422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf(stderr, "x509parse_crtfile failed\n"); 85522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 85622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case S_IFDIR: 85722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 > x509parse_crtpath(&cacert, ca_cert_container)) 85822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf(stderr, "x509parse_crtpath failed\n"); 85922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 86022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans default: 86122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Unable to load CA certficate container %s\n", ca_cert_container); 86222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 86322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 86422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 86522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 86622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans entropy_init (&entropy); 86722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != ctr_drbg_init (&ctr_drbg, entropy_func, &entropy, 86822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned char *) pers, strlen(pers))) 86922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 87022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Failed to initialize CTR_DRBG\n"); 87122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 87222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 87322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != ssl_init (&ssl)) 87422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 87522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("SSL initialization failed\n"); 87622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 87722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_set_endpoint (&ssl, SSL_IS_CLIENT); 87822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_set_rng (&ssl, ctr_drbg_random, &ctr_drbg); 87922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_set_ca_chain (&ssl, &cacert, NULL, hostname_to_verify); 88022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ca_racket) 88122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 88222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // You can do SSL_VERIFY_REQUIRED here, but then the check in 88322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // inspect_key() never happens as the ssl_handshake() will fail. 88422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_set_authmode (&ssl, SSL_VERIFY_OPTIONAL); 88522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 88622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 88722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (proxy) 88822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 88922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *scheme; 89022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *proxy_host; 89122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char *proxy_port; 89222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 89322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans parse_proxy_uri (proxy, &scheme, &proxy_host, &proxy_port); 89422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 89522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: opening socket to proxy %s:%s\n", proxy_host, proxy_port); 89622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != net_connect (&server_fd, proxy_host, atoi(proxy_port))) 89722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 89822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("SSL connection failed\n"); 89922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 90022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 90122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_init (&proxy_ctx); 90222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_set_bio (&proxy_ctx, net_recv, &server_fd, net_send, &server_fd); 90322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_set_host (&proxy_ctx, host); 90422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_set_port (&proxy_ctx, atoi(port)); 90522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_set_scheme (&proxy_ctx, scheme); 90622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 90722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_set_bio (&ssl, proxy_polarssl_recv, &proxy_ctx, proxy_polarssl_send, &proxy_ctx); 90822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 90922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: Handle proxy connection\n"); 91022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == proxy_ctx.f_connect (&proxy_ctx)) 91122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Proxy connection failed\n"); 91222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 91322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans else 91422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 91522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: opening socket to %s:%s\n", host, port); 91622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != net_connect (&server_fd, host, atoi(port))) 91722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 91822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("SSL connection failed\n"); 91922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 92022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 92122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_set_bio (&ssl, net_recv, &server_fd, net_send, &server_fd); 92222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 92322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 92422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: starting handshake\n"); 92522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != ssl_do_handshake_part (&ssl)) 92622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("SSL handshake first part failed\n"); 92722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 92822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t timestamp = ( (uint32_t) ssl.in_msg[6] << 24 ) 92922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans | ( (uint32_t) ssl.in_msg[7] << 16 ) 93022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans | ( (uint32_t) ssl.in_msg[8] << 8 ) 93122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans | ( (uint32_t) ssl.in_msg[9] ); 93222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans check_timestamp (timestamp); 93322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 93422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: continuing handshake\n"); 93522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* Continue with handshake */ 93622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans while (0 != (ret = ssl_handshake (&ssl))) 93722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 93822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (POLARSSL_ERR_NET_WANT_READ != ret && 93922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans POLARSSL_ERR_NET_WANT_WRITE != ret) 94022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 94122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("SSL handshake failed\n"); 94222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 94322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 94422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 94522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Verify the peer certificate against the CA certs on the local system 94622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ca_racket) { 94722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans inspect_key (&ssl, hostname_to_verify); 94822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 94922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Certificate verification skipped!\n"); 95022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 95122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans check_key_length (&ssl); 95222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 95322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans memcpy (time_map, ×tamp, sizeof(uint32_t)); 95422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy_polarssl_free (&proxy_ctx); 95522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_free (&ssl); 95622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans x509_free (&cacert); 95722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 95822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#else /* USE_POLARSSL */ 95922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** 96022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * Run SSL handshake and store the resulting time value in the 96122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * 'time_map'. 96222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * 96322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans * @param time_map where to store the current time 96422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 96522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansstatic void 96622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansrun_ssl (uint32_t *time_map, int time_is_an_illusion) 96722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 96822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO *s_bio; 96922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_CTX *ctx; 97022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL *ssl; 97122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans struct stat statbuf; 97222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 97322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_load_error_strings(); 97422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_library_init(); 97522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 97622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ctx = NULL; 97722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == strcmp("sslv23", protocol)) 97822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 97922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: using SSLv23_client_method()\n"); 98022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ctx = SSL_CTX_new(SSLv23_client_method()); 98122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else if (0 == strcmp("sslv3", protocol)) 98222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 98322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: using SSLv3_client_method()\n"); 98422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ctx = SSL_CTX_new(SSLv3_client_method()); 98522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else if (0 == strcmp("tlsv1", protocol)) 98622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 98722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: using TLSv1_client_method()\n"); 98822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ctx = SSL_CTX_new(TLSv1_client_method()); 98922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else 99022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Unsupported protocol `%s'\n", protocol); 99122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 99222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ctx == NULL) 99322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("OpenSSL failed to support protocol `%s'\n", protocol); 99422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 99522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: Using OpenSSL for SSL\n"); 99622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ca_racket) 99722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 99822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (-1 == stat(ca_cert_container, &statbuf)) 99922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 100022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Unable to stat CA certficate container %s\n", ca_cert_container); 100122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else 100222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 100322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans switch (statbuf.st_mode & S_IFMT) 100422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 100522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case S_IFREG: 100622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (1 != SSL_CTX_load_verify_locations(ctx, ca_cert_container, NULL)) 100722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf(stderr, "SSL_CTX_load_verify_locations failed\n"); 100822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 100922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans case S_IFDIR: 101022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container)) 101122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf(stderr, "SSL_CTX_load_verify_locations failed\n"); 101222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans break; 101322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans default: 101422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (1 != SSL_CTX_load_verify_locations(ctx, NULL, ca_cert_container)) 101522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 101622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf(stderr, "SSL_CTX_load_verify_locations failed\n"); 101722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("Unable to load CA certficate container %s\n", ca_cert_container); 101822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 101922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 102022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 102122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 102222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 102322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == (s_bio = make_ssl_bio(ctx))) 102422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("SSL BIO setup failed\n"); 102522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans BIO_get_ssl(s_bio, &ssl); 102622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == ssl) 102722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("SSL setup failed\n"); 102822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 102922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (time_is_an_illusion) 103022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 103122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_set_info_callback(ssl, openssl_time_callback); 103222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 103322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 103422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); 103522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb("V: opening socket to %s:%s\n", host, port); 103622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if ( (1 != BIO_set_conn_hostname(s_bio, host)) || 103722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (1 != BIO_set_conn_port(s_bio, port)) ) 103822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Failed to initialize connection to `%s:%s'\n", host, port); 103922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 104022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (NULL == BIO_new_fp(stdout, BIO_NOCLOSE)) 104122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("BIO_new_fp returned error, possibly: %s", strerror(errno)); 104222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 104322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // This should run in seccomp 104422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // eg: prctl(PR_SET_SECCOMP, 1); 104522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (1 != BIO_do_connect(s_bio)) /* XXX TODO: BIO_should_retry() later? */ 104622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("SSL connection failed\n"); 104722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (1 != BIO_do_handshake(s_bio)) 104822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("SSL handshake failed\n"); 104922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 105022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // Verify the peer certificate against the CA certs on the local system 105122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ca_racket) { 105222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans inspect_key (ssl, hostname_to_verify); 105322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 105422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Certificate verification skipped!\n"); 105522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 105622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans check_key_length(ssl); 105722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // from /usr/include/openssl/ssl3.h 105822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // ssl->s3->server_random is an unsigned char of 32 bits 105922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans memcpy(time_map, ssl->s3->server_random, sizeof (uint32_t)); 106022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_free(ssl); 106122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans SSL_CTX_free(ctx); 106222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 106322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif /* USE_POLARSSL */ 106422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/** drop root rights and become 'nobody' */ 106522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 106622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansint 106722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evansmain(int argc, char **argv) 106822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans{ 106922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t *time_map; 107022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans struct tlsdate_time start_time, end_time, warp_time; 107122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int status; 107222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans pid_t ssl_child; 107322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans long long rt_time_ms; 107422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans uint32_t server_time_s; 107522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int setclock; 107622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int showtime; 107722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int timewarp; 107822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans int leap; 107922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 108022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (argc != 12) 108122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 1; 108222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans host = argv[1]; 108322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans hostname_to_verify = argv[1]; 108422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans port = argv[2]; 108522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans protocol = argv[3]; 108622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ca_cert_container = argv[6]; 108722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ca_racket = (0 != strcmp ("unchecked", argv[4])); 108822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verbose = (0 != strcmp ("quiet", argv[5])); 108922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans setclock = (0 == strcmp ("setclock", argv[7])); 109022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans showtime = (0 == strcmp ("showtime", argv[8])); 109122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans timewarp = (0 == strcmp ("timewarp", argv[9])); 109222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans leap = (0 == strcmp ("leapaway", argv[10])); 109322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans proxy = (0 == strcmp ("none", argv[11]) ? NULL : argv[11]); 109422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 109522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (timewarp) 109622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 109722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 109822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: RECENT_COMPILE_DATE is %lu.%06lu\n", 109922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_SEC(&warp_time), 110022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_USEC(&warp_time)); 110122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 110222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (1 == setclock) { 110322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans clock_init_time(&warp_time, RECENT_COMPILE_DATE, 0); 110422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 110522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: we'll do the time warp another time - we're not setting clock\n"); 110622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 110722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 110822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 110922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* We are not going to set the clock, thus no need to stay root */ 111022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == setclock && 0 == timewarp) 111122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 1112aab9382297008c1d1b7cef361159a44885d52af0Gilad Arnold drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL); 111322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 111422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans/* 111522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans XXX: KILL ME 111622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // We cast the mmap value to remove this error when compiling with g++: 111722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // src/tlsdate-helper.c: In function ‘int main(int, char**)’: 111822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // src/tlsdate-helper.c:822:41: error: invalid conversion from ‘void*’ to ‘uint32_t 111922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans time_map = (uint32_t *) mmap (NULL, sizeof (uint32_t), 112022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans PROT_READ | PROT_WRITE, 112122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans MAP_SHARED | MAP_ANONYMOUS, -1, 0); 112222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (MAP_FAILED == time_map) 112322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 112422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf (stderr, "mmap failed: %s\n", 112522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans strerror (errno)); 112622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 1; 112722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 112822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans*/ 112922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* Get the current time from the system clock. */ 113022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != clock_get_real_time(&start_time)) 113122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 113222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Failed to read current time of day: %s\n", strerror (errno)); 113322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 113422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 113522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: time is currently %lu.%06lu\n", 113622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_SEC(&start_time), 113722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_NSEC(&start_time)); 113822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 113922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (((unsigned long) CLOCK_SEC(&start_time)) < ((unsigned long) CLOCK_SEC(&warp_time))) 114022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 114122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: local clock time is less than RECENT_COMPILE_DATE\n"); 114222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (timewarp) 114322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 114422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: Attempting to warp local clock into the future\n"); 114522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != clock_set_real_time(&warp_time)) 114622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 114722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("setting time failed: %s (Attempted to set clock to %lu.%06lu)\n", 114822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans strerror (errno), 114922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_SEC(&warp_time), 115022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_SEC(&warp_time)); 115122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 115222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != clock_get_real_time(&start_time)) 115322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 115422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Failed to read current time of day: %s\n", strerror (errno)); 115522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 115622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: time is currently %lu.%06lu\n", 115722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_SEC(&start_time), 115822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned long) CLOCK_NSEC(&start_time)); 115922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: It's just a step to the left...\n"); 116022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 116122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } else { 116222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: time is greater than RECENT_COMPILE_DATE\n"); 116322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 116422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 116522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* initialize to bogus value, just to be on the safe side */ 116622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans *time_map = 0; 116722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 116822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* Run SSL interaction in separate process (and not as 'root') */ 116922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans ssl_child = fork (); 117022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (-1 == ssl_child) 117122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("fork failed: %s\n", strerror (errno)); 117222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == ssl_child) 117322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 1174aab9382297008c1d1b7cef361159a44885d52af0Gilad Arnold drop_privs_to (UNPRIV_USER, UNPRIV_GROUP, NULL); 117522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans run_ssl (time_map, leap); 117622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* 117722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans XXX: should be a pipe close 117822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (void) munmap (time_map, sizeof (uint32_t)); 117922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 118022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans _exit (0); 118122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 118222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (ssl_child != waitpid (ssl_child, &status, 0)) 118322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("waitpid failed: %s\n", strerror (errno)); 118422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)) )) 118522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("child process failed in SSL handshake\n"); 118622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 118722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != clock_get_real_time(&end_time)) 118822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("Failed to read current time of day: %s\n", strerror (errno)); 118922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 119022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* calculate RTT */ 119122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans rt_time_ms = (CLOCK_SEC(&end_time) - CLOCK_SEC(&start_time)) * 1000 + (CLOCK_USEC(&end_time) - CLOCK_USEC(&start_time)) / 1000; 119222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (rt_time_ms < 0) 119322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans rt_time_ms = 0; /* non-linear time... */ 119422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#ifdef USE_POLARSSL 119522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans server_time_s = *time_map; 119622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#else 119722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans server_time_s = ntohl (*time_map); 119822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans#endif 119922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* 120022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans XXX: should be a pipe close 120122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans munmap (time_map, sizeof (uint32_t)); 120222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans */ 120322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: server time %u (difference is about %d s) was fetched in %lld ms\n", 120422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (unsigned int) server_time_s, 120522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans CLOCK_SEC(&start_time) - server_time_s, 120622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans rt_time_ms); 120722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 120822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* warning if the handshake took too long */ 120922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (rt_time_ms > TLS_RTT_THRESHOLD) { 121022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: the TLS handshake took more than %d msecs - consider using a different " \ 121122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans "server or run it again\n", TLS_RTT_THRESHOLD); 121222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 121322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 121422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (showtime) 121522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 121622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans struct tm ltm; 121722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans time_t tim = server_time_s; 121822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans char buf[256]; 121922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 122022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans localtime_r(&tim, <m); 122122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 == strftime(buf, sizeof buf, "%a %b %e %H:%M:%S %Z %Y", <m)) 122222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 122322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("strftime returned 0\n"); 122422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 122522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans fprintf(stdout, "%s\n", buf); 122622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 122722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 122822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans /* finally, actually set the time */ 122922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (setclock) 123022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans { 123122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans struct tlsdate_time server_time; 123222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 123322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans clock_init_time(&server_time, server_time_s + (rt_time_ms / 2 / 1000), 123422ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans (rt_time_ms / 2) % 1000); 123522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans 123622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // We should never receive a time that is before the time we were last 123722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // compiled; we subscribe to the linear theory of time for this program 123822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans // and this program alone! 123922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (CLOCK_SEC(&server_time) >= MAX_REASONABLE_TIME) 124022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die("remote server is a false ticker from the future!\n"); 124122ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (CLOCK_SEC(&server_time) <= RECENT_COMPILE_DATE) 124222ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans die ("remote server is a false ticker!\n"); 124322ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans if (0 != clock_set_real_time(&server_time)) 1244196fe4b14121ac68e41f64f8b53ab9d597b3cd47Fabian Keil die ("setting time failed: %s (Difference from server is about %d s)\n", 124522ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans strerror (errno), 124622ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans CLOCK_SEC(&start_time) - server_time_s); 124722ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans verb ("V: setting time succeeded\n"); 124822ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans } 124922ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans return 0; 125022ede40ad7f5b4d994ccbae7ef07b36bdf3fd497Noah Evans} 1251