Skip to content
This repository has been archived by the owner on Jun 30, 2020. It is now read-only.

Commit

Permalink
Implement certificate authentication for GNUTLS
Browse files Browse the repository at this point in the history
This implements TLS certificate authentication in the GNUTLS
implementation.
It supports mutual authentication, and determining the peer
subject DN.

Signed-off-by: Patrick Uiterwijk <[email protected]>
  • Loading branch information
puiterwijk committed Mar 25, 2019
1 parent 72f2c71 commit b34b52b
Show file tree
Hide file tree
Showing 19 changed files with 959 additions and 27 deletions.
66 changes: 66 additions & 0 deletions bin/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,46 @@ clt_psk_cb(void *m, char **username, uint8_t **key)
return keydup(o, key);
}

static int
cert_cb(void *m,
char **cert_uri,
char **key_uri,
char **pin)
{
const options_t *o = m;

*cert_uri = strdup(o->crtf);
if (!*cert_uri)
return -1;
*key_uri = strdup(o->crtk);
if (!key_uri)
return -1;

return 0;
}

static int
clt_cert_cb(void *m,
const char **requested_ca_dn,
char **cert_uri,
char **key_uri,
char **pin)
{
// We just ignore "requested_ca_dn" for now.
return cert_cb(m, cert_uri, key_uri, pin);
}

static int
srv_cert_cb(void *m,
const char *servername,
char **cert_uri,
char **key_uri,
char **pin)
{
// We just ignore "servername" for now.
return cert_cb(m, cert_uri, key_uri, pin);
}

static status_t
on_conn(options_t *opts, int con, int in, int out, const struct addrinfo *ai)
{
Expand All @@ -160,6 +200,13 @@ on_conn(options_t *opts, int con, int in, int out, const struct addrinfo *ai)

if (opts->psku)
srv.psk = srv_psk_cb;
else if (opts->crtf)
{
srv.cert.getcert = srv_cert_cb;
srv.cert.client_certificate_request = opts->crtclientcert;
srv.cert.cafile = opts->crtca;
srv.cert.insecure = opts->crtinsec;
}

ret = non_setsockopt(con, IPPROTO_TLS,
TLS_SRV_HANDSHAKE, &srv, sizeof(srv));
Expand All @@ -168,6 +215,12 @@ on_conn(options_t *opts, int con, int in, int out, const struct addrinfo *ai)

if (opts->psku)
clt.psk = clt_psk_cb;
else if (opts->crtf) {
clt.cert.getcert = clt_cert_cb;
clt.cert.cafile = opts->crtca;
clt.cert.insecure = opts->crtinsec;
clt.cert.hostname = opts->host;
}

ret = non_setsockopt(con, IPPROTO_TLS,
TLS_CLT_HANDSHAKE, &clt, sizeof(clt));
Expand All @@ -178,6 +231,19 @@ on_conn(options_t *opts, int con, int in, int out, const struct addrinfo *ai)
shutdown(con, SHUT_RDWR);
return STATUS_FAILURE;
}

if (opts->verbose) {
// Print some useful information
socklen_t dnlen = 256;
char *peer_dn = malloc(sizeof(char) * dnlen);
ret = getsockopt(con, IPPROTO_TLS, TLS_OPT_PEER_SUBJECT_DN, peer_dn, &dnlen);
if (ret != 0) {
fprintf(stderr, "%m: Unable to get peer subject DN!\n");
shutdown(con, SHUT_RDWR);
return STATUS_FAILURE;
}
printf("Peer subject DN: %s\n", peer_dn);
}
}

while (poll(pfds, 2, -1) >= 0) {
Expand Down
44 changes: 41 additions & 3 deletions bin/opt.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@
#include <stdio.h>
#include <string.h>

static const char *sopts = "46hlknubTc:e:U:K:";
typedef enum {
OPT_SSL_CERT = 1,
OPT_SSL_KEY = 2,
OPT_SSL_INSECURE = 3,
OPT_SSL_TRUSTFILE = 4,
OPT_SSL_CLIENT_CERT_REQUEST = 5,
OPT_SSL_CLIENT_CERT_REQUIRE = 6,
} long_opts_keys;

static const char *sopts = "46hlknubTc:e:U:K:v";
static const struct option lopts[] = {
{ "verbose", no_argument, .val = 'v' },
{ "ipv4", no_argument, .val = '4' },
{ "ipv6", no_argument, .val = '6' },
{ "help", no_argument, .val = 'h' },
Expand All @@ -40,6 +50,14 @@ static const struct option lopts[] = {

{ "psk-user", required_argument, .val = 'U' },
{ "psk-key", required_argument, .val = 'K' },

{ "ssl-cert", required_argument, .val = OPT_SSL_CERT },
{ "ssl-key", required_argument, .val = OPT_SSL_KEY },
{ "ssl-insecure", no_argument, .val = OPT_SSL_INSECURE },
{ "ssl-trustfile", required_argument, .val = OPT_SSL_TRUSTFILE },
{ "ssl-client-cert-request", no_argument, .val = OPT_SSL_CLIENT_CERT_REQUEST },
{ "ssl-client-cert-require", no_argument, .val = OPT_SSL_CLIENT_CERT_REQUIRE },

{}
};

Expand All @@ -48,6 +66,7 @@ static const struct {
const char *doc;
const char *arg;
} docs[] = {
{'v', "Enable verbose info"},
{'4', "Use IPv4 only"},
{'6', "Use IPv6 only"},
{'c', "Execute the given shell command", "CMD"},
Expand All @@ -59,6 +78,14 @@ static const struct {
{'T', "Use TLS or DTLS instead of TCP or UDP"},
{'U', "Pre-Shared Key authentication username", "NAME"},
{'K', "Pre-Shared Key authentication key (hex)", "HEX"},

{OPT_SSL_CERT, "Certificate file"},
{OPT_SSL_KEY, "Certificate key"},
{OPT_SSL_INSECURE, "Disable certificate validation"},
{OPT_SSL_TRUSTFILE, "Certificate Authority trust file"},
{OPT_SSL_CLIENT_CERT_REQUEST, "Request client certificate"},
{OPT_SSL_CLIENT_CERT_REQUIRE, "Require client certificate"},

{}
};

Expand All @@ -76,6 +103,7 @@ opts_parse(options_t *opts, int argc, char **argv)
switch (c) {
case 'h': goto usage;

case 'v': opts->verbose = true; break;
case '4': opts->ipv4 = true; break;
case '6': opts->ipv6 = true; break;
case 'l': opts->listen = true; break;
Expand All @@ -85,6 +113,12 @@ opts_parse(options_t *opts, int argc, char **argv)
case 'c': opts->exec = optarg; opts->shell = true; break;
case 'e': opts->exec = optarg; opts->shell = false; break;
case 'U': opts->psku = optarg; break;
case OPT_SSL_CERT: opts->crtf = optarg; break;
case OPT_SSL_KEY: opts->crtk = optarg; break;
case OPT_SSL_INSECURE: opts->crtinsec = true; break;
case OPT_SSL_TRUSTFILE: opts->crtca = optarg; break;
case OPT_SSL_CLIENT_CERT_REQUEST: opts->crtclientcert = 1; break;
case OPT_SSL_CLIENT_CERT_REQUIRE: opts->crtclientcert = 2; break;

case 'K':
opts->pskk = optarg;
Expand Down Expand Up @@ -148,8 +182,12 @@ opts_parse(options_t *opts, int argc, char **argv)
sprintf(lterm, "%s[=%s]", lopts[i].name, docs[j].arg);
}

fprintf(stderr, " -%c%-7s --%-18s %s\n",
docs[j].val, sterm, lterm, docs[j].doc);
if ((docs[j].val >= 'a' && docs[j].val <= 'z') || (docs[j].val >= 'A' && docs[j].val <= 'Z') || (docs[j].val >= '0' && docs[j].val <= '9'))
fprintf(stderr, " -%c%-7s --%-18s %s\n",
docs[j].val, sterm, lterm, docs[j].doc);
else
fprintf(stderr, " --%-18s %s\n",
lterm, docs[j].doc);
}
}
return false;
Expand Down
6 changes: 6 additions & 0 deletions bin/opt.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ typedef struct {
const char *exec;
const char *psku;
const char *pskk;
const char *crtf;
const char *crtk;
const char *crtca;

bool listen : 1;
bool block : 1;
Expand All @@ -37,6 +40,9 @@ typedef struct {
bool ipv6 : 1;
bool udp : 1;
bool tls : 1;
bool verbose : 1;
bool crtinsec : 1;
int crtclientcert;
} options_t;

bool
Expand Down
Loading

0 comments on commit b34b52b

Please sign in to comment.