Skip to content

Commit

Permalink
Allow cookie settings to be reconfigurable
Browse files Browse the repository at this point in the history
  • Loading branch information
wtoorop committed Aug 27, 2024
1 parent 7a34e20 commit 65a5d64
Show file tree
Hide file tree
Showing 11 changed files with 424 additions and 90 deletions.
88 changes: 2 additions & 86 deletions nsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -902,49 +902,6 @@ bind8_stats (struct nsd *nsd)
}
#endif /* BIND8_STATS */

static
int cookie_secret_file_read(nsd_type* nsd) {
cookie_secret_type cookie_secrets[NSD_COOKIE_HISTORY_SIZE];
char secret[NSD_COOKIE_SECRET_SIZE * 2 + 2/*'\n' and '\0'*/];
char const* file = nsd->options->cookie_secret_file
? nsd->options->cookie_secret_file : COOKIESECRETSFILE;
FILE* f;
size_t count = 0;

f = fopen(file, "r");
/* a non-existing cookie file is not an error */
if( f == NULL ) { return errno != EPERM; }
/* cookie secret file exists and is readable */
for( count = 0; count < NSD_COOKIE_HISTORY_SIZE; count++ ) {
size_t secret_len = 0;
ssize_t decoded_len = 0;
if( fgets(secret, sizeof(secret), f) == NULL ) { break; }
secret_len = strlen(secret);
if( secret_len == 0 ) { break; }
assert( secret_len <= sizeof(secret) );
secret_len = secret[secret_len - 1] == '\n' ? secret_len - 1 : secret_len;
if( secret_len != NSD_COOKIE_SECRET_SIZE * 2 ) {
fclose(f);
return 0;
}
/* needed for `hex_pton`; stripping potential `\n` */
secret[secret_len] = '\0';
decoded_len = hex_pton(secret, cookie_secrets[count].cookie_secret,
NSD_COOKIE_SECRET_SIZE);
if( decoded_len != NSD_COOKIE_SECRET_SIZE ) {
fclose(f);
return 0;
}
}
fclose(f);
if(count && nsd->cookie_secrets_source <= COOKIE_SECRETS_FROM_FILE) {
nsd->cookie_count = count;
memcpy(nsd->cookie_secrets, cookie_secrets, sizeof(cookie_secrets));
nsd->cookie_secrets_source = COOKIE_SECRETS_FROM_FILE;
}
return 1;
}

extern char *optarg;
extern int optind;

Expand Down Expand Up @@ -986,6 +943,7 @@ main(int argc, char *argv[])
nsd.chrootdir = 0;
nsd.nsid = NULL;
nsd.nsid_len = 0;
nsd.do_answer_cookie = 0;
nsd.cookie_count = 0;
nsd.cookie_secrets_source = COOKIE_SECRETS_NONE;

Expand All @@ -994,7 +952,6 @@ main(int argc, char *argv[])
nsd.current_tcp_count = 0;
nsd.file_rotation_ok = 0;

nsd.do_answer_cookie = 1;

/* Set up our default identity to gethostname(2) */
if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
Expand Down Expand Up @@ -1271,43 +1228,7 @@ main(int argc, char *argv[])
#endif /* IPV6 MTU) */
#endif /* defined(INET6) */

nsd.do_answer_cookie = nsd.options->answer_cookie;
if(nsd.options->cookie_secret) {
ssize_t len = hex_pton(nsd.options->cookie_secret,
nsd.cookie_secrets[0].cookie_secret,
NSD_COOKIE_SECRET_SIZE);
if (len != NSD_COOKIE_SECRET_SIZE ) {
error("A cookie secret must be a 128 bit hex string");
}
nsd.cookie_count = 1;
nsd.cookie_secrets_source = COOKIE_SECRETS_FROM_CONFIG;
if(nsd.options->cookie_staging_secret) {
len = hex_pton(nsd.options->cookie_staging_secret,
nsd.cookie_secrets[1].cookie_secret,
NSD_COOKIE_SECRET_SIZE);
if (len != NSD_COOKIE_SECRET_SIZE ) {
error("A (staging) cookie secret must be a "
"128 bit hex string");
} else
nsd.cookie_count = 2;
}
} else {
size_t j;
size_t const cookie_secret_len = NSD_COOKIE_SECRET_SIZE;
/* Calculate a new random secret */
srandom(getpid() ^ time(NULL));

for( j = 0; j < NSD_COOKIE_HISTORY_SIZE; j++) {
#if defined(HAVE_SSL)
if (!RAND_status()
|| !RAND_bytes(nsd.cookie_secrets[j].cookie_secret, cookie_secret_len))
#endif
for (i = 0; i < cookie_secret_len; i++)
nsd.cookie_secrets[j].cookie_secret[i] = random_generate(256);
}
nsd.cookie_count = 1;
nsd.cookie_secrets_source = COOKIE_SECRETS_GENERATED;
}
reconfig_cookies(&nsd, nsd.options);

if (nsd.nsid_len == 0 && nsd.options->nsid) {
if (strlen(nsd.options->nsid) % 2 != 0) {
Expand Down Expand Up @@ -1610,11 +1531,6 @@ main(int argc, char *argv[])
}
#endif /* HAVE_SSL */

if(nsd.cookie_secrets_source < COOKIE_SECRETS_FROM_FILE
&& (!nsd.options->cookie_secret_file || nsd.options->cookie_secret_file[0])
&& !cookie_secret_file_read(&nsd) ) {
log_msg(LOG_ERR, "cookie secret file corrupt or not readable");
}
/* Unless we're debugging, fork... */
if (!nsd.debug) {
int fd;
Expand Down
5 changes: 5 additions & 0 deletions options.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ parse_options_file(struct nsd_options* opt, const char* file,

opt->configfile = region_strdup(opt->region, file);

/* Semantic errors */
if(opt->cookie_staging_secret && !opt->cookie_secret) {
c_error("a cookie-staging-secret cannot be configured without "
"also providing a cookie-secret");
}
RBTREE_FOR(pat, struct pattern_options*, opt->patterns)
{
struct pattern_options* old_pat =
Expand Down
2 changes: 1 addition & 1 deletion options.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ struct nsd_options {
/** cookie staging secret */
char *cookie_staging_secret;
/** path to cookie secret store */
char const* cookie_secret_file;
char *cookie_secret_file;
/** enable verify */
int verify_enable;
/** list of ip addresses used to serve zones for verification */
Expand Down
65 changes: 62 additions & 3 deletions remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -1969,21 +1969,80 @@ repat_options_changed(xfrd_state_type* xfrd, struct nsd_options* newopt)
return 0;
}

static int opt_str_changed(const char* old, const char* new)
{ return !old ? ( !new ? 0 : 1 ) : ( !new ? 1 : strcasecmp(old, new) ); }

/** true if cookie options are different that can be set via repat. */
static int
repat_cookie_options_changed(struct nsd_options* old, struct nsd_options* new)
{
return old->answer_cookie != new->answer_cookie
|| opt_str_changed( old->cookie_secret
, new->cookie_secret)
|| opt_str_changed( old->cookie_staging_secret
, new->cookie_staging_secret)
|| opt_str_changed( old->cookie_secret_file
, new->cookie_secret_file);
}

static void opt_strcpy(region_type* region, char** dst, const char* src)
{
assert(dst);

if(!*dst) {
if(src)
*dst = region_strdup(region, src);

} else if(!src) {
region_recycle(region, *dst, strlen(*dst)+1);
*dst = NULL;

} else if(strcasecmp(*dst, src)) {
region_recycle(region, *dst, strlen(*dst)+1);
*dst = region_strdup(region, src);
}
}

/** check if global options have changed */
static void
repat_options(xfrd_state_type* xfrd, struct nsd_options* newopt)
{
struct nsd_options* oldopt = xfrd->nsd->options;

if(repat_options_changed(xfrd, newopt)) {
/* update our options */
#ifdef RATELIMIT
xfrd->nsd->options->rrl_ratelimit = newopt->rrl_ratelimit;
xfrd->nsd->options->rrl_whitelist_ratelimit = newopt->rrl_whitelist_ratelimit;
xfrd->nsd->options->rrl_slip = newopt->rrl_slip;
oldopt->rrl_ratelimit = newopt->rrl_ratelimit;
oldopt->rrl_whitelist_ratelimit = newopt->rrl_whitelist_ratelimit;
oldopt->rrl_slip = newopt->rrl_slip;
#endif
task_new_opt_change(xfrd->nsd->task[xfrd->nsd->mytask],
xfrd->last_task, newopt);
xfrd_set_reload_now(xfrd);
}
if(repat_cookie_options_changed(oldopt, newopt)) {
/* update our options */
oldopt->answer_cookie = newopt->answer_cookie;
opt_strcpy( oldopt->region
, &oldopt->cookie_secret
, newopt->cookie_secret);
opt_strcpy( oldopt->region
, &oldopt->cookie_staging_secret
, newopt->cookie_staging_secret);
opt_strcpy( oldopt->region
, &oldopt->cookie_secret_file
, newopt->cookie_secret_file);

xfrd->nsd->cookie_count = 0;
xfrd->nsd->cookie_secrets_source = COOKIE_SECRETS_NONE;
reconfig_cookies(xfrd->nsd, newopt);
task_new_cookies( xfrd->nsd->task[xfrd->nsd->mytask]
, xfrd->last_task
, xfrd->nsd->do_answer_cookie
, xfrd->nsd->cookie_count
, xfrd->nsd->cookie_secrets);
xfrd_set_reload_now(xfrd);
}
}

/** print errors over ssl, gets pointer-to-pointer to ssl, so it can set
Expand Down
15 changes: 15 additions & 0 deletions tpkg/dns-cookies.tdir/dns-cookies.by-config.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
server:
username: ""
zonesdir: ""
xfrdfile: ""
logfile: "nsd.log"
ip-address: lo

include: "cookiesecrets.conf"

remote-control:
control-enable: yes
control-key-file: "dns-cookies.nsd_control.key"
control-cert-file: "dns-cookies.nsd_control.pem"
server-key-file: "dns-cookies.nsd_server.key"
server-cert-file: "dns-cookies.nsd_server.pem"
22 changes: 22 additions & 0 deletions tpkg/dns-cookies.tdir/dns-cookies.nsd_control.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqzCCAhMCFBPBN+c2KtT5mAvLhxdCKNiMyNAKMA0GCSqGSIb3DQEBCwUAMA4x
DDAKBgNVBAMMA25zZDAeFw0xOTA0MjUxNTEzMjdaFw0yOTA0MjIxNTEzMjdaMBYx
FDASBgNVBAMMC25zZC1jb250cm9sMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
igKCAYEAp6tA9X7sVaSMYtQh8FkQLhXERl05wDDxKr+Sqap/mctNoh27f7Y37act
gIkjw0FqJByrg73j1bqoVvRwJMWCrQCYP/oAw66rG4FDSN3jBg8lCeXz4qJETiZn
ZQRdWeJyjap6mm6Gj1CzWqmKq9bH+sJEEpXEA/rQM8PL1fSm5RXExSo47RoemL8j
afZd3j/JPUSunj/2/TLRKvJsCJV2JLFLQFvt/4G56C++ExQKsuN6QpfExZmC5cEH
hpYQBk5AfvbSqwzxGgldFQLyboA22spvh3uxVrYJj1bMDfO8Ij5d0Ku/rulsZVoa
ukudr/hhmI56A2IkYZemYdTMAeCrflYJD9TPx0eXzPtLoPJIyUlJ7MCu0rgN+FbH
7jDM1GC9zpQyBtLr97/rNHzk+z2N2WcgYbDhBW13Dv9QkIb2+ZPxhu2W5OTNEdu4
+SHZOtYdPXN7NssiS2ZSIp8+ohkRzZgc8hsPr0yjt78IlzR5DVayz6vev9aRjdao
0vlAroIvAgMBAAEwDQYJKoZIhvcNAQELBQADggGBADc3NTIs6gf+//qcdyTR4hYc
oF53cJ4nWRMmoOJIk4ojF77rzoD2UjQye1X0gpZx55UYyu6O/Mq40krPX4FbMSzA
zLAyzuUPwJGdcgjvvlmSym/LAwTXwGYF32S/qKtpJKFSWny08JBt7DT8fV2P00zE
bV6ozg5HKukEcd2dQczsE3+gHwx7P+jsBBnWZzIgCkPwp4amzpahbQZRH2v9OboX
c1zR/8xXaYbes/BdqzzudhFV/Xd9wHH2EV4mRKPvQMY87FV6eGKYNL2UvPfr4/SH
yiIvd4Rw/vgMtpH9cYMov1v2Qkk9qvV9w5OPYu/4HzCVGssbkUPQX0AAWrUYIdo4
ZqEAzyr1/IevTRYtsA4qkqJqgFfwRmNQH2blRX3vzgNvj2+v4DjvC+HYHuwzkwl8
rbbs+9Ta+SBljSIPFb1+OMBAvgin/kAaYRxfQs6yrIO5abIBm+gfEiFLaP9yqerE
L+oT94EwsPMPVJ09yuVrjVUU430GMS2uqgTIj35TPQ==
-----END CERTIFICATE-----
22 changes: 22 additions & 0 deletions tpkg/dns-cookies.tdir/dns-cookies.nsd_server.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDozCCAgsCFCAZislHgIerlrBBkLFt/ZOkKYVZMA0GCSqGSIb3DQEBCwUAMA4x
DDAKBgNVBAMMA25zZDAeFw0xOTA0MjUxNTEzMjdaFw0yOTA0MjIxNTEzMjdaMA4x
DDAKBgNVBAMMA25zZDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMS8
uXxVCNTo112z3ENd99N/yuQJYk6umwp0ue3nc0CG5j2Y+12xmdEZ1OO3GddRkgCP
abQyK0onTU7B82qlmZ+N9fyFY8KyJEYM/ef2jlkaL+H8JnEuar22FetJd/ODWS6p
heAQw8UrdjC09vo1sRRCtolJtmF2XsIn0PM2h5o3wFpaPE5SuY87dEHNKj7+Zwgu
psLY2+zh7pdzd0KJVuoWTnNSmVRHgXRC3naFPU8jMs4Twb5KgF1qLYvwsFo92DE4
/y+8zX0PRdR1up+u2PpbTvCGnSCz4mYogFSKy6lIdxC9l36vgXCd0LwA48i/ReUx
9wGlqIuomIDBnIHaivZOoY/s4rjMV+jrIM388UxM2Qh4TxK9/Ul+o/3x8yT+GhkM
QABywJr9qfT/6BGXmbL1j7AVmKVCyoDGdCQ2YX9unXawdZqU2qkULBt/OHVGUfX/
4ss07M8IHNj0OyRuoFYO9tyqAYZQ9IPg5QvF3cYkcmg2yT180qF4C1rpsdNjoQID
AQABMA0GCSqGSIb3DQEBCwUAA4IBgQB+WGMopDqNkv7yDAO8Ik2EWieDqxTshqR4
bT1do9zsC9WDrIVxoVcn+dtlIpEQl8MN9U5DTKBbRgk3grOwUsg2kC0Gujv3vAyQ
bF+jxjHWd1xzrbQ+QUgz07P1OMFWxMzECL2L2078UZbawFqKqlmNv5avUk27G8nB
GrujT/pUOIpRXC+rao8e14R84dPJLZuGm9IAeEBQIIdhY9sjFRyoQdCUubyKPpkm
/fpcDMkt7PzZ4nTovj4NUxnnoUGonpXuj0pHA/RDDJkPYaRrND4OGldQXdZ9LJNM
pROL6aCZ5iog74OY8yutVzCgGge9vZLkysceVP7Lyks9/fEAtIuozmulp9TUQAeR
MVdDOcREWRd0vFNtAC9xSloRqV+66CzrFHwkSMpLo+gdgcAZ8s33rgQk+I4gfavU
jPWMZVcZHXevtWuTRnxfOpMkbwiRyr2J8m549K7OKZgr+JRhdJTev4lvXVyfFia4
zr6UOK4exZWP6VDXb4IyZbJh+LMjmws=
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions tpkg/dns-cookies.tdir/dns-cookies.test
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ unshare -rUn bash dns-cookies.test.A3 || exit 1

echo "Starting test A4"
unshare -rUn bash dns-cookies.test.A4 || exit 1

echo "Starting test C1"
unshare -rUn bash dns-cookies.test.C1 || exit 1


Loading

0 comments on commit 65a5d64

Please sign in to comment.