Skip to content

Commit fbedcb1

Browse files
author
Patrick Pelletier (on chives)
committed
get https example building, running, and documented
1 parent 44cef1f commit fbedcb1

9 files changed

Lines changed: 212 additions & 24 deletions

File tree

Makefile.am

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,12 @@ AUTOMAKE_OPTIONS = \
77
--warnings=error \
88
--warnings=no-portability
99

10-
noinst_PROGRAMS = \
11-
#
10+
ACLOCAL_AMFLAGS = -I bld/m4
1211

13-
if HAVE_LIBEVENT
14-
noinst_PROGRAMS += \
12+
noinst_PROGRAMS = \
1513
https-client \
1614
https-server \
1715
#
18-
endif
1916

2017
https_client_SOURCES = \
2118
https-client.c \
@@ -33,5 +30,5 @@ noinst_HEADERS = \
3330
openssl_hostname_validation.h \
3431
#
3532

36-
AM_CFLAGS += $(LIBEVENT_CFLAGS)
37-
AM_LDFLAGS += $(LIBEVENT_LIBS)
33+
AM_CFLAGS = $(LIBEVENT_CFLAGS) $(OPENSSL_CFLAGS)
34+
AM_LDFLAGS = $(OPENSSL_LDFLAGS) $(LIBEVENT_LIBS) $(OPENSSL_LIBS)

README.txt

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
ppelletier@chives:~/src/https-example$ uname -a
2+
Linux chives 2.6.32-34-generic #77-Ubuntu SMP Tue Sep 13 19:39:17 UTC 2011 x86_64 GNU/Linux
3+
4+
start the server:
5+
6+
ppelletier@chives:~/src/https-example$ ./https-server
7+
Using OpenSSL version "OpenSSL 1.0.1c 10 May 2012"
8+
and libevent version "2.1.2-alpha-dev"
9+
Loading certificate chain from 'server-certificate-chain.pem'
10+
and private key from 'server-private-key.pem'
11+
Listening on 0.0.0.0:8421
12+
13+
run the client... it works!
14+
15+
ppelletier@chives:~/src/https-example$ ./https-client
16+
Using OpenSSL version "OpenSSL 1.0.1c 10 May 2012"
17+
and libevent version "2.1.2-alpha-dev"
18+
https server 'localhost' has this certificate, which looks good to me:
19+
/C=US/ST=CA/L=Los Angeles/O=Oblong Industries/OU=Plasma/CN=localhost
20+
server said: Hi 127.0.0.1! I liked your passcode.
21+
22+
do the same thing with curl instead of with the client:
23+
24+
ppelletier@chives:~/src/https-example$ curl -k -d 'passcode=R23' https://localhost:8421/
25+
Hi 127.0.0.1! I liked your passcode.
26+
27+
Now, change the "#if 1" on line 214 of https-client.c to "#if 0", to
28+
get rid of the special hack that turns "localhost" into "127.0.0.1",
29+
in order to avoid IPv6. Here's what happens:
30+
31+
ppelletier@chives:~/src/https-example$ ./https-client
32+
Using OpenSSL version "OpenSSL 1.0.1c 10 May 2012"
33+
and libevent version "2.1.2-alpha-dev"
34+
code=0 POST failed
35+
server said:
36+
37+
Next, change the "#if 0" on line 100 of https-client.c to "#if 1", to
38+
enable retries:
39+
40+
ppelletier@chives:~/src/https-example$ ./https-client
41+
Using OpenSSL version "OpenSSL 1.0.1c 10 May 2012"
42+
and libevent version "2.1.2-alpha-dev"
43+
[warn] Epoll ADD(1) on fd 7 failed. Old events were 0; read change was 1 (add); write change was 0 (none): Bad file descriptor
44+
[warn] Epoll ADD(4) on fd 7 failed. Old events were 0; read change was 0 (none); write change was 1 (add): Bad file descriptor
45+
code=0 POST failed
46+
socket error = Bad file descriptor (9)
47+
server said: (null)

autogen.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
#
4+
# Force everything to the abspath of this script
5+
#
6+
srcdir=$(cd $(dirname $0) && pwd)
7+
8+
autoreconf --verbose --install --force $srcdir

bld/m4/ax_check_openssl.m4

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# ===========================================================================
2+
# http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
3+
# ===========================================================================
4+
#
5+
# SYNOPSIS
6+
#
7+
# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
8+
#
9+
# DESCRIPTION
10+
#
11+
# Look for OpenSSL in a number of default spots, or in a user-selected
12+
# spot (via --with-openssl). Sets
13+
#
14+
# OPENSSL_INCLUDES to the include directives required
15+
# OPENSSL_LIBS to the -l directives required
16+
# OPENSSL_LDFLAGS to the -L or -R flags required
17+
#
18+
# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
19+
#
20+
# This macro sets OPENSSL_INCLUDES such that source files should use the
21+
# openssl/ directory in include directives:
22+
#
23+
# #include <openssl/hmac.h>
24+
#
25+
# LICENSE
26+
#
27+
# Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
28+
# Copyright (c) 2009,2010 Dustin J. Mitchell <dustin@zmanda.com>
29+
#
30+
# Copying and distribution of this file, with or without modification, are
31+
# permitted in any medium without royalty provided the copyright notice
32+
# and this notice are preserved. This file is offered as-is, without any
33+
# warranty.
34+
35+
#serial 8
36+
37+
AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL])
38+
AC_DEFUN([AX_CHECK_OPENSSL], [
39+
found=false
40+
AC_ARG_WITH([openssl],
41+
[AS_HELP_STRING([--with-openssl=DIR],
42+
[root of the OpenSSL directory])],
43+
[
44+
case "$withval" in
45+
"" | y | ye | yes | n | no)
46+
AC_MSG_ERROR([Invalid --with-openssl value])
47+
;;
48+
*) ssldirs="$withval"
49+
;;
50+
esac
51+
], [
52+
# if pkg-config is installed and openssl has installed a .pc file,
53+
# then use that information and don't search ssldirs
54+
AC_PATH_PROG([PKG_CONFIG], [pkg-config])
55+
if test x"$PKG_CONFIG" != x""; then
56+
OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
57+
if test $? = 0; then
58+
OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null`
59+
OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null`
60+
found=true
61+
fi
62+
fi
63+
64+
# no such luck; use some default ssldirs
65+
if ! $found; then
66+
ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr"
67+
fi
68+
]
69+
)
70+
71+
72+
# note that we #include <openssl/foo.h>, so the OpenSSL headers have to be in
73+
# an 'openssl' subdirectory
74+
75+
if ! $found; then
76+
OPENSSL_INCLUDES=
77+
for ssldir in $ssldirs; do
78+
AC_MSG_CHECKING([for openssl/ssl.h in $ssldir])
79+
if test -f "$ssldir/include/openssl/ssl.h"; then
80+
OPENSSL_INCLUDES="-I$ssldir/include"
81+
OPENSSL_LDFLAGS="-L$ssldir/lib"
82+
OPENSSL_LIBS="-lssl -lcrypto"
83+
found=true
84+
AC_MSG_RESULT([yes])
85+
break
86+
else
87+
AC_MSG_RESULT([no])
88+
fi
89+
done
90+
91+
# if the file wasn't found, well, go ahead and try the link anyway -- maybe
92+
# it will just work!
93+
fi
94+
95+
# try the preprocessor and linker with our new flags,
96+
# being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
97+
98+
AC_MSG_CHECKING([whether compiling and linking against OpenSSL works])
99+
echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
100+
"OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD
101+
102+
save_LIBS="$LIBS"
103+
save_LDFLAGS="$LDFLAGS"
104+
save_CPPFLAGS="$CPPFLAGS"
105+
LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
106+
LIBS="$OPENSSL_LIBS $LIBS"
107+
CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
108+
AC_LINK_IFELSE(
109+
[AC_LANG_PROGRAM([#include <openssl/ssl.h>], [SSL_new(NULL)])],
110+
[
111+
AC_MSG_RESULT([yes])
112+
$1
113+
], [
114+
AC_MSG_RESULT([no])
115+
$2
116+
])
117+
CPPFLAGS="$save_CPPFLAGS"
118+
LDFLAGS="$save_LDFLAGS"
119+
LIBS="$save_LIBS"
120+
121+
AC_SUBST([OPENSSL_INCLUDES])
122+
AC_SUBST([OPENSSL_LIBS])
123+
AC_SUBST([OPENSSL_LDFLAGS])
124+
])

configure.ac

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,6 @@ AC_CONFIG_MACRO_DIR([bld/m4])
1818
AC_PROG_CC
1919

2020

21-
# Shared lib versioning
22-
# CURRENT, REVISION, AGE
23-
# - library source changed -> increment REVISION
24-
# - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
25-
# - interfaces added -> increment AGE
26-
# - interfaces removed -> AGE = 0
27-
# sets YOVO_LT_LDFLAGS
28-
AS_LIBTOOL(YOVO, 2, 0, 0)
2921
LT_INIT
3022

3123
AM_CONDITIONAL([ENABLE_SHARED], [test "x$enable_shared" != xno])
@@ -35,6 +27,9 @@ AM_INIT_AUTOMAKE
3527
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
3628
m4_ifdef([AM_COLOR_TESTS], [AM_COLOR_TESTS([yes])])
3729

30+
# Detect OpenSSL
31+
AX_CHECK_OPENSSL
32+
3833
# check for libevent
3934
PKG_CHECK_MODULES([LIBEVENT], [libevent >= 2.1.2
4035
libevent_pthreads >= 2.1.2

https-client.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <openssl/ssl.h>
1414
#include <openssl/err.h>
1515

16-
#include "common.h"
16+
#include "https-common.h"
1717
#include "openssl_hostname_validation.h"
1818

1919
#include <stdbool.h>
@@ -96,6 +96,15 @@ static void launch_request (struct session *s)
9696
conn = evhttp_connection_base_bufferevent_new (
9797
base, 0, bev, s->host, s->port);
9898
evhttp_connection_set_timeout (conn, 60);
99+
100+
#if 0
101+
/* Retries defaults to 0, which seems bad, since some of the evhttp
102+
* code seems to assume that a retry will happen:
103+
* http://archives.seul.org/libevent/users/Jan-2013/msg00051.html
104+
* So, let's set retries to 1, in order to get past that case. */
105+
evhttp_connection_set_retries (conn, 1);
106+
#endif
107+
99108
s->c = conn;
100109
s->bev = bev;
101110

@@ -188,7 +197,7 @@ static char *client_do_post (const char *host, int port, const char *passcode)
188197

189198
/* Find the certificate authority (which we will use to
190199
* validate the server) and add it to the context. */
191-
SSL_CTX_load_verify_locations (sctx, "certs/certificate-authorities.pem", NULL);
200+
SSL_CTX_load_verify_locations (sctx, "certificate-authorities.pem", NULL);
192201

193202
SSL_CTX_set_verify (sctx, SSL_VERIFY_PEER, NULL);
194203
SSL_CTX_set_cert_verify_callback (sctx, cert_verify_callback, (void *) host);
@@ -202,13 +211,15 @@ static char *client_do_post (const char *host, int port, const char *passcode)
202211
s1.data_size = strlen (buf);
203212
free (urlencoded_passcode);
204213

214+
#if 1
205215
/* Sadly, "host" must currently be an address which resolves to an IPv4
206216
* address. (e. g. on my machine, "localhost" resolves to "::1" in
207217
* addition to "127.0.0.1", and it picks the IPv6 first.)
208218
* http://article.gmane.org/gmane.comp.lib.libevent.user/2671
209219
*/
210220
if (0 == strcmp (host, "localhost"))
211221
host = "127.0.0.1"; /* horribly ugly hack to avoid ::1 for localhost */
222+
#endif
212223

213224
s1.kind = EVHTTP_REQ_POST;
214225
s1.host = host;
@@ -235,7 +246,7 @@ int main (int argc, char **argv)
235246

236247
/* Send the passcode to the https server in a POST request. */
237248
char *result = client_do_post (host, COMMON_HTTPS_PORT, COMMON_PASSCODE);
238-
printf ("server said \"%s\"\n", result);
249+
printf ("server said: %s\n", result);
239250
free (result);
240251

241252
return EXIT_SUCCESS;

https-common.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33

44
#include <signal.h>
55

6-
#include "common.h"
6+
#include "https-common.h"
77

88
#include <openssl/ssl.h>
99
#include <openssl/err.h>
1010

11+
#include <event2/event.h>
12+
1113
void die_most_horribly_from_openssl_error (const char *func)
1214
{ fprintf (stderr, "%s failed:\n", func);
1315

@@ -44,4 +46,8 @@ void common_setup (void)
4446
SSL_library_init ();
4547
SSL_load_error_strings ();
4648
OpenSSL_add_all_algorithms ();
49+
50+
printf ("Using OpenSSL version \"%s\"\nand libevent version \"%s\"\n",
51+
SSLeay_version (SSLEAY_VERSION),
52+
event_get_version ());
4753
}

https-common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
/**
1313
* This is the string the client tells the server in the POST request.
1414
*/
15-
#define COMMON_PASSCODE "foo! bar! baz!"
15+
#define COMMON_PASSCODE "R23"
1616

1717
/**
1818
* If an OpenSSL function returns a return value indicating failure

https-server.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
1515
*/
1616

17-
#include "common.h"
17+
#include "https-common.h"
1818

1919
#include <stdio.h>
2020
#include <stdlib.h>
@@ -124,7 +124,7 @@ send_document_cb (struct evhttp_request *req, void *arg)
124124
const char *passcode = evhttp_find_header (&kv, "passcode");
125125
char response[256];
126126
evutil_snprintf (response, sizeof (response),
127-
"Hi %s! I %s your passcode.", peer_addr,
127+
"Hi %s! I %s your passcode.\n", peer_addr,
128128
(0 == strcmp (passcode, COMMON_PASSCODE)
129129
? "liked"
130130
: "didn't like"));
@@ -219,8 +219,8 @@ static int serve_some_http (void)
219219
die_most_horribly_from_openssl_error ("SSL_CTX_set_tmp_ecdh");
220220

221221
/* Find and set up our server certificate. */
222-
const char *certificate_chain = "certs/server-certificate-chain.pem";
223-
const char *private_key = "certs/server-private-key.pem";
222+
const char *certificate_chain = "server-certificate-chain.pem";
223+
const char *private_key = "server-private-key.pem";
224224
server_setup_certs (ctx, certificate_chain, private_key);
225225

226226
/* This is the magic that lets evhttp use SSL. */

0 commit comments

Comments
 (0)