Commit 5719692d authored by Daniel Salzman's avatar Daniel Salzman
Browse files

Merge branch 'keymgr-tsig-generate' into 'master'

keymgr, TSIG key generation

Implement 'keymgr tsig generate'.

See merge request !420
parents da5c10ca 17ce2685
......@@ -37,10 +37,15 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
\fBkeymgr\fP [\fIglobal\-options\fP] [\fIcommand\fP\&...] \fBhelp\fP
.SH DESCRIPTION
.sp
The \fBkeymgr\fP utility serves for DNSSEC keys and KASP (Key And
Signature Policy) management in Knot DNS server. The configuration is stored
in a so called KASP database. The database is simply a directory in the
file\-system containing files in the JSON format.
The \fBkeymgr\fP utility serves for key management in Knot DNS server.
.sp
Primarily functions for DNSSEC keys and KASP (Key And Signature Policy)
management are provided. However the utility also provides functions for
TSIG key generation.
.sp
The DNSSEC and KASP configuration is stored in a so called KASP database.
The database is simply a directory in the file\-system containing files in the
JSON format.
.sp
The operations are organized into commands and subcommands. A command
specifies the operation to be performed with the KASP database. It is usually
......@@ -75,6 +80,9 @@ way how a zone is signed.
\fBkeystore\fP ...
Operations with private key store content. The private key store holds
private key material separately from zone metadata.
.TP
\fBtsig\fP ...
Operations with TSIG keys.
.UNINDENT
.SS zone commands
.INDENT 0.0
......@@ -225,6 +233,19 @@ file\-based key store is supported. This command is subject to change.
\fBkeystore\fP \fBlist\fP
List private keys in the key store.
.UNINDENT
.SS tsig commands
.INDENT 0.0
.TP
\fBtsig\fP \fBgenerate\fP \fIname\fP [\fBalgorithm\fP \fIid\fP] [\fBsize\fP \fIbits\fP]
Generate new TSIG key and print it on the standard output. The algorithm
defaults to \fIhmac\-sha256\fP\&. The default key size is determined optimally based
on the selected algorithm.
.sp
The generated key is printed out in the server configuration format to allow
direct inclusion into the server configuration. The first line of the output
contains a comment with the key in the one\-line key format accepted by client
utilities.
.UNINDENT
.SH EXAMPLES
.INDENT 0.0
.IP 1. 3
......@@ -328,6 +349,18 @@ $ keymgr zone key generate example.com algorithm rsasha256 size 1024
.fi
.UNINDENT
.UNINDENT
.IP 8. 3
Generate a TSIG key named \fIoperator.key\fP:
.INDENT 3.0
.INDENT 3.5
.sp
.nf
.ft C
$ keymgr tsig generate operator.key algorithm hmac\-sha512
.ft P
.fi
.UNINDENT
.UNINDENT
.UNINDENT
.SH SEE ALSO
.sp
......
......@@ -115,33 +115,33 @@ Export the configuration database to a file.
.SH EXAMPLES
.SS Setup a key file for remote control
.INDENT 0.0
.IP 1. 3
Generate a key:
.INDENT 3.0
.INDENT 3.5
.sp
.nf
.ft C
$ dnssec\-keygen \-a hmac\-md5 \-b 256 \-n HOST knotc\-key
$ keymgr tsig generate knotc\-key > knotc\-key.conf
.ft P
.fi
.UNINDENT
.UNINDENT
.IP 2. 3
Extract a secret in base64 format and create a key file:
.INDENT 3.0
.sp
The generated key file contains a key in the server configuration format and
thus can be directly included into the server configuration file.
.sp
Knot DNS utilities accept one\-line format which is included in the generated
key file on the first line as a comment. It can be extracted easily:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
$ echo "knotc\-key hmac\-md5 <secret>" > knotc.key
$ head \-1 knotc\-key.conf | sed \(aqs/^#\es*//\(aq > knotc.key
.ft P
.fi
.UNINDENT
.UNINDENT
.UNINDENT
.sp
Make sure the key can be read/written only by the owner for security reasons.
Make sure the key file can be read only by the owner for security reasons.
.SS Reload server remotely
.INDENT 0.0
.INDENT 3.5
......
......@@ -174,7 +174,7 @@ Zone name/server guessing, if the zone name/server is not specified.
.sp
Empty line doesn\(aqt send the update.
.sp
Bind\-like key format (\fBddns\-confgen\fP output) is not supported.
BIND\-like key format (\fBddns\-confgen\fP output) is not supported.
.UNINDENT
.UNINDENT
.SH EXAMPLES
......
.. highlight:: console
keymgr – DNSSEC key management utility
======================================
keymgr – Key management utility
===============================
Synopsis
--------
......@@ -13,10 +13,15 @@ Synopsis
Description
-----------
The :program:`keymgr` utility serves for DNSSEC keys and KASP (Key And
Signature Policy) management in Knot DNS server. The configuration is stored
in a so called KASP database. The database is simply a directory in the
file-system containing files in the JSON format.
The :program:`keymgr` utility serves for key management in Knot DNS server.
Primarily functions for DNSSEC keys and KASP (Key And Signature Policy)
management are provided. However the utility also provides functions for
TSIG key generation.
The DNSSEC and KASP configuration is stored in a so called KASP database.
The database is simply a directory in the file-system containing files in the
JSON format.
The operations are organized into commands and subcommands. A command
specifies the operation to be performed with the KASP database. It is usually
......@@ -25,7 +30,7 @@ available subcommands in that area. The listing of available command arguments
is not supported yet.
Command and argument names are parsed in a smart way. Only a beginning
of a name can be entered and it will be recognized. The specified part of
of a name can be entered and it will be recognized. The specified part of
a name must be unique amongst the other names.
Global options
......@@ -53,6 +58,9 @@ Main commands
Operations with private key store content. The private key store holds
private key material separately from zone metadata.
**tsig** ...
Operations with TSIG keys.
zone commands
.............
......@@ -190,6 +198,19 @@ file-based key store is supported. This command is subject to change.
**keystore** **list**
List private keys in the key store.
tsig commands
.............
**tsig** **generate** *name* [**algorithm** *id*] [**size** *bits*]
Generate new TSIG key and print it on the standard output. The algorithm
defaults to *hmac-sha256*. The default key size is determined optimally based
on the selected algorithm.
The generated key is printed out in the server configuration format to allow
direct inclusion into the server configuration. The first line of the output
contains a comment with the key in the one-line key format accepted by client
utilities.
Examples
--------
......@@ -238,6 +259,10 @@ Examples
$ keymgr zone key generate example.com algorithm rsasha256 size 2048 ksk
$ keymgr zone key generate example.com algorithm rsasha256 size 1024
8. Generate a TSIG key named *operator.key*::
$ keymgr tsig generate operator.key algorithm hmac-sha512
See Also
--------
......
......@@ -95,15 +95,19 @@ Examples
Setup a key file for remote control
...................................
1. Generate a key::
::
$ keymgr tsig generate knotc-key > knotc-key.conf
$ dnssec-keygen -a hmac-md5 -b 256 -n HOST knotc-key
The generated key file contains a key in the server configuration format and
thus can be directly included into the server configuration file.
2. Extract a secret in base64 format and create a key file::
Knot DNS utilities accept one-line format which is included in the generated
key file on the first line as a comment. It can be extracted easily::
$ echo "knotc-key hmac-md5 <secret>" > knotc.key
$ head -1 knotc-key.conf | sed 's/^#\s*//' > knotc.key
Make sure the key can be read/written only by the owner for security reasons.
Make sure the key file can be read only by the owner for security reasons.
Reload server remotely
......................
......
......@@ -148,7 +148,7 @@ Differences with regard to ISC nsupdate:
Empty line doesn't send the update.
Bind-like key format (:program:`ddns-confgen` output) is not supported.
BIND-like key format (:program:`ddns-confgen` output) is not supported.
Examples
--------
......
......@@ -15,12 +15,12 @@ Knot DNS for BIND users
Automatic DNSSEC signing
------------------------
Migrating automatically signed zones from Bind to Knot DNS is very
Migrating automatically signed zones from BIND to Knot DNS is very
easy due to the fact that Knot DNS is able to use DNSSEC keys
generated by Bind.
generated by BIND.
1. To obtain current content of the zone which is being migrated,
request Bind to flush the zone into the zone file: ``rndc flush
request BIND to flush the zone into the zone file: ``rndc flush
example.com``.
*Note:* If dynamic updates (DDNS) are enabled for the given zone, you
......@@ -33,7 +33,7 @@ generated by Bind.
3. We recommend to store DNSSEC keys for each zone in a separate
directory. For this purpose, create a directory
``example.com.keys`` in the zones storage directory. Then copy all
DNSSEC keys (``*.key`` and ``*.private``) from Bind key directory
DNSSEC keys (``*.key`` and ``*.private``) from BIND key directory
(configured as ``key-directory``) into the newly created one.
4. Add the zone into the Knot DNS configuration file. Zone
......
......@@ -137,6 +137,11 @@ dnssec_tsig_algorithm_t dnssec_tsig_algorithm_from_name(const char *name);
*/
const char *dnssec_tsig_algorithm_to_name(dnssec_tsig_algorithm_t algorithm);
/*!
* Get optimal size of a TSIG algorithm.
*/
int dnssec_tsig_optimal_key_size(dnssec_tsig_algorithm_t algorithm);
struct dnssec_tsig_ctx;
/*!
......
......@@ -17,6 +17,7 @@
#include <assert.h>
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
......@@ -143,6 +144,17 @@ const char *dnssec_tsig_algorithm_to_name(dnssec_tsig_algorithm_t algorithm)
return (found ? found->name : NULL);
}
_public_
int dnssec_tsig_optimal_key_size(dnssec_tsig_algorithm_t tsig)
{
gnutls_mac_algorithm_t mac = algorithm_to_gnutls(tsig);
if (mac == GNUTLS_MAC_UNKNOWN) {
return 0;
}
return gnutls_mac_get_key_size(mac) * CHAR_BIT;
}
_public_
int dnssec_tsig_new(dnssec_tsig_ctx_t **ctx_ptr,
dnssec_tsig_algorithm_t algorithm,
......
......@@ -16,6 +16,7 @@
#include "cmdparse/value.h"
#include "dnssec/key.h"
#include "dnssec/tsig.h"
#include "print.h"
#include <assert.h>
......@@ -159,6 +160,29 @@ int value_algorithm(int argc, char *argv[], const parameter_t *p, void *data)
return -1;
}
int value_tsig_algorithm(int argc, char *argv[], const parameter_t *p, void *data)
{
assert(p);
assert(data);
if (argc < 1) {
error_missing_option(p);
return -1;
}
dnssec_tsig_algorithm_t *algorithm = data + p->offset;
char *input = argv[0];
dnssec_tsig_algorithm_t match = dnssec_tsig_algorithm_from_name(input);
if (match == DNSSEC_TSIG_UNKNOWN) {
error("Invalid value for '%s'.", p->name);
return -1;
}
*algorithm = match;
return 1;
}
int value_key_size(int argc, char *argv[], const parameter_t *p, void *data)
{
assert(p);
......
......@@ -38,6 +38,11 @@ int value_string(int argc, char *argv[], const parameter_t *p, void *data);
*/
int value_algorithm(int argc, char *argv[], const parameter_t *p, void *data);
/*!
* dnssec_tsig_algorithm_t
*/
int value_tsig_algorithm(int argc, char *argv[], const parameter_t *p, void *data);
/*!
* unsigned int
*/
......
......@@ -16,6 +16,7 @@
#include <assert.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -25,6 +26,7 @@
#include <dnssec/error.h>
#include <dnssec/kasp.h>
#include <dnssec/keystore.h>
#include <dnssec/tsig.h>
#include "cmdparse/command.h"
#include "cmdparse/parameter.h"
......@@ -1252,6 +1254,108 @@ static int cmd_keystore_list(int argc, char *argv[])
return 0;
}
/*!
* Print TSIG key in client and server format.
*/
static void print_tsig(dnssec_tsig_algorithm_t mac, const char *name,
const dnssec_binary_t *secret)
{
assert(name);
assert(secret);
const char *mac_name = dnssec_tsig_algorithm_to_name(mac);
assert(mac_name);
// client format (as a comment)
printf("# %s:%s:%.*s\n", mac_name, name, (int)secret->size, secret->data);
// server format
printf("key:\n");
printf(" - id: %s\n", name);
printf(" algorithm: %s\n", mac_name);
printf(" secret: %.*s\n", (int)secret->size, secret->data);
}
/*
* keymgr tsig generate <name> [algorithm <algorithm>] [size <size>]
*/
static int cmd_tsig_generate(int argc, char *argv[])
{
if (argc < 1) {
error("TSIG key name has to be specified.");
return 1;
}
struct config {
dnssec_tsig_algorithm_t algorithm;
unsigned size;
};
static const parameter_t params[] = {
#define o(member) offsetof(struct config, member)
{ "algorithm", value_tsig_algorithm, .offset = o(algorithm) },
{ "size", value_key_size, .offset = o(size) },
{ NULL }
#undef o
};
struct config config = {
.algorithm = DNSSEC_TSIG_HMAC_SHA256
};
_cleanup_free_ char *name = dname_ascii_normalize_copy(argv[0]);
if (!name) {
error("Invalid TSIG key name.");
return 1;
}
if (parse_parameters(params, argc - 1, argv + 1, &config) != 0) {
return 1;
}
// round up bits to bytes
config.size = (config.size + CHAR_BIT - 1) / CHAR_BIT * CHAR_BIT;
int optimal_size = dnssec_tsig_optimal_key_size(config.algorithm);
assert(optimal_size > 0);
if (config.size == 0) {
config.size = optimal_size;
}
if (config.size != optimal_size) {
error("Notice: Optimal key size for %s is %d bits.",
dnssec_tsig_algorithm_to_name(config.algorithm),
optimal_size);
}
assert(config.size % CHAR_BIT == 0);
_cleanup_binary_ dnssec_binary_t key = { 0 };
int r = dnssec_binary_alloc(&key, config.size / CHAR_BIT);
if (r != DNSSEC_EOK) {
error("Failed to allocate memory.");
return 1;
}
r = gnutls_rnd(GNUTLS_RND_KEY, key.data, key.size);
if (r != 0) {
error("Failed to generate secret the key.");
return 1;
}
_cleanup_binary_ dnssec_binary_t key_b64 = { 0 };
r = dnssec_binary_to_base64(&key, &key_b64);
if (r != DNSSEC_EOK) {
error("Failed to convert the key to Base64.");
return 1;
}
print_tsig(config.algorithm, name, &key_b64);
return 0;
}
static int cmd_keystore(int argc, char *argv[])
{
static const command_t commands[] = {
......@@ -1262,6 +1366,16 @@ static int cmd_keystore(int argc, char *argv[])
return subcommand(commands, argc, argv);
}
static int cmd_tsig(int argc, char *argv[])
{
static const command_t commands[] = {
{ "generate", cmd_tsig_generate },
{ NULL }
};
return subcommand(commands, argc, argv);
}
static void print_help(void)
{
printf("TBD.\n");
......@@ -1326,6 +1440,7 @@ int main(int argc, char *argv[])
{ "zone", cmd_zone },
{ "policy", cmd_policy },
{ "keystore", cmd_keystore },
{ "tsig", cmd_tsig },
{ NULL }
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment