From: Alexander Schultz Date: Sat, 22 Jun 2019 01:01:17 +0000 (-0400) Subject: kdig: add support for connecting over TLS with a client cert/keyfile pair X-Git-Tag: v2.9.0~242 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a63ece0127cc4fd5bcb2bcef5a307613dd19299c;p=thirdparty%2Fknot-dns.git kdig: add support for connecting over TLS with a client cert/keyfile pair --- diff --git a/doc/man/kdig.1in b/doc/man/kdig.1in index 3237ac120e..292e71b2a5 100644 --- a/doc/man/kdig.1in +++ b/doc/man/kdig.1in @@ -257,6 +257,12 @@ Use TLS with a remote server hostname check. \fB+\fP[\fBno\fP]\fBtls\-sni\fP=\fISTR\fP Use TLS with a Server Name Indication. .TP +\fB+\fP[\fBno\fP]\fBtls\-keyfile\fP=\fIFILE\fP +Use TLS with a client keyfile. +.TP +\fB+\fP[\fBno\fP]\fBtls\-certfile\fP=\fIFILE\fP +Use TLS with a client certfile. +.TP \fB+\fP[\fBno\fP]\fBnsid\fP Request the nameserver identifier (NSID). .TP diff --git a/doc/man_kdig.rst b/doc/man_kdig.rst index 689d0693af..0a99f297a8 100644 --- a/doc/man_kdig.rst +++ b/doc/man_kdig.rst @@ -236,6 +236,12 @@ Options **+**\ [\ **no**\ ]\ **tls-sni**\ =\ *STR* Use TLS with a Server Name Indication. +**+**\ [\ **no**\ ]\ **tls-keyfile**\ =\ *FILE* + Use TLS with a client keyfile. + +**+**\ [\ **no**\ ]\ **tls-certfile**\ =\ *FILE* + Use TLS with a client certfile. + **+**\ [\ **no**\ ]\ **nsid** Request the nameserver identifier (NSID). diff --git a/src/utils/common/tls.c b/src/utils/common/tls.c index 90bc6cd12f..a609dee52b 100644 --- a/src/utils/common/tls.c +++ b/src/utils/common/tls.c @@ -65,6 +65,22 @@ int tls_params_copy(tls_params_t *dst, const tls_params_t *src) } } + if (src->keyfile != NULL) { + dst->keyfile = strdup(src->keyfile); + if (dst->keyfile == NULL) { + tls_params_clean(dst); + return KNOT_ENOMEM; + } + } + + if (src->certfile != NULL) { + dst->certfile = strdup(src->certfile); + if (dst->certfile == NULL) { + tls_params_clean(dst); + return KNOT_ENOMEM; + } + } + ptrnode_t *n = NULL; WALK_LIST(n, src->ca_files) { char *src_file = (char *)n->d; @@ -106,6 +122,8 @@ void tls_params_clean(tls_params_t *params) free(params->hostname); free(params->sni); + free(params->keyfile); + free(params->certfile); memset(params, 0, sizeof(*params)); } @@ -301,6 +319,33 @@ int tls_ctx_init(tls_ctx_t *ctx, const tls_params_t *params, int wait) gnutls_certificate_set_verify_function(ctx->credentials, verify_certificate); + // Setup client keypair if specified. Both key and cert files must be provided. + if (params->keyfile != NULL && params->certfile != NULL) { + // First, try PEM. + ret = gnutls_certificate_set_x509_key_file(ctx->credentials, + params->certfile, params->keyfile, GNUTLS_X509_FMT_PEM); + if (ret != GNUTLS_E_SUCCESS) { + // If PEM didn't work, try DER. + ret = gnutls_certificate_set_x509_key_file(ctx->credentials, + params->certfile, params->keyfile, GNUTLS_X509_FMT_DER); + } + + if (ret != GNUTLS_E_SUCCESS) { + WARN("TLS, failed to add client certfile '%s' and keyfile '%s'\n", + params->certfile, params->keyfile); + return KNOT_ERROR; + } else { + DBG("TLS, added client certfile '%s' and keyfile '%s'\n", + params->certfile, params->keyfile); + } + } else if (params->keyfile != NULL) { + WARN("TLS, cannot use client keyfile without a certfile\n"); + return KNOT_ERROR; + } else if (params->certfile != NULL) { + WARN("TLS, cannot use client certfile without a keyfile\n"); + return KNOT_ERROR; + } + return KNOT_EOK; } diff --git a/src/utils/common/tls.h b/src/utils/common/tls.h index f360f4fe94..818e4b4a52 100644 --- a/src/utils/common/tls.h +++ b/src/utils/common/tls.h @@ -35,6 +35,10 @@ typedef struct { char *hostname; /*! Optional server name indicator. */ char *sni; + /*! Optional client keyfile name. */ + char *keyfile; + /*! Optional client certfile name. */ + char *certfile; } tls_params_t; /*! \brief TLS context. */ diff --git a/src/utils/kdig/kdig_params.c b/src/utils/kdig/kdig_params.c index e945c2fe42..049b848e3c 100644 --- a/src/utils/kdig/kdig_params.c +++ b/src/utils/kdig/kdig_params.c @@ -737,6 +737,46 @@ static int opt_notls_sni(const char *arg, void *query) return KNOT_EOK; } +static int opt_tls_keyfile(const char *arg, void *query) +{ + query_t *q = query; + + free(q->tls.keyfile); + q->tls.keyfile = strdup(arg); + + return opt_tls(arg, query); +} + +static int opt_notls_keyfile(const char *arg, void *query) +{ + query_t *q = query; + + free(q->tls.keyfile); + q->tls.keyfile = NULL; + + return KNOT_EOK; +} + +static int opt_tls_certfile(const char *arg, void *query) +{ + query_t *q = query; + + free(q->tls.certfile); + q->tls.certfile = strdup(arg); + + return opt_tls(arg, query); +} + +static int opt_notls_certfile(const char *arg, void *query) +{ + query_t *q = query; + + free(q->tls.certfile); + q->tls.certfile = NULL; + + return KNOT_EOK; +} + static int opt_nsid(const char *arg, void *query) { query_t *q = query; @@ -1229,6 +1269,12 @@ static const param_t kdig_opts2[] = { { "tls-sni", ARG_REQUIRED, opt_tls_sni }, { "notls-sni", ARG_NONE, opt_notls_sni }, + { "tls-keyfile", ARG_REQUIRED, opt_tls_keyfile }, + { "notls-keyfile", ARG_NONE, opt_notls_keyfile }, + + { "tls-certfile", ARG_REQUIRED, opt_tls_certfile }, + { "notls-certfile", ARG_NONE, opt_notls_certfile }, + { "nsid", ARG_NONE, opt_nsid }, { "nonsid", ARG_NONE, opt_nonsid }, @@ -1931,6 +1977,8 @@ static void print_help(void) " +[no]tls-pin=BASE64 Use TLS with pinned certificate.\n" " +[no]tls-hostname=STR Use TLS with remote server hostname.\n" " +[no]tls-sni=STR Use TLS with Server Name Indication.\n" + " +[no]tls-keyfile=FILE Use TLS with a client keyfile.\n" + " +[no]tls-certfile=FILE Use TLS with a client certfile.\n" " +[no]nsid Request NSID.\n" " +[no]bufsize=B Set EDNS buffer size.\n" " +[no]padding[=N] Pad with EDNS(0) (default or specify size).\n"