]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
kdig: add support for connecting over TLS with a client cert/keyfile pair
authorAlexander Schultz <derschultz@gmail.com>
Sat, 22 Jun 2019 01:01:17 +0000 (21:01 -0400)
committerDaniel Salzman <daniel.salzman@nic.cz>
Mon, 24 Jun 2019 18:56:31 +0000 (20:56 +0200)
doc/man/kdig.1in
doc/man_kdig.rst
src/utils/common/tls.c
src/utils/common/tls.h
src/utils/kdig/kdig_params.c

index 3237ac120e72519cd5a32b3c40feca2ce151f6b0..292e71b2a5cf6add6833e49d449d69ebe4273588 100644 (file)
@@ -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
index 689d0693af629787fee9470498583d4d3c13458f..0a99f297a8287f1d4702260a8fc66417aba3e7d9 100644 (file)
@@ -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).
 
index 90bc6cd12fb5866677336829a698aed0d21fe439..a609dee52b53c2ed1a61891bfe0ed2aa57960c6e 100644 (file)
@@ -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;
 }
 
index f360f4fe947566b4bc4d794e9f58cb98c023c928..818e4b4a524d0c121211491893c8f7b407279941 100644 (file)
@@ -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. */
index e945c2fe420551088ed1f5d88ba70785261c656f..049b848e3c6b08409fa6d6435fb6dd1534c3a140 100644 (file)
@@ -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"