Skip to content

Commit 65a5d64

Browse files
committed
Allow cookie settings to be reconfigurable
1 parent 7a34e20 commit 65a5d64

11 files changed

+424
-90
lines changed

nsd.c

+2-86
Original file line numberDiff line numberDiff line change
@@ -902,49 +902,6 @@ bind8_stats (struct nsd *nsd)
902902
}
903903
#endif /* BIND8_STATS */
904904

905-
static
906-
int cookie_secret_file_read(nsd_type* nsd) {
907-
cookie_secret_type cookie_secrets[NSD_COOKIE_HISTORY_SIZE];
908-
char secret[NSD_COOKIE_SECRET_SIZE * 2 + 2/*'\n' and '\0'*/];
909-
char const* file = nsd->options->cookie_secret_file
910-
? nsd->options->cookie_secret_file : COOKIESECRETSFILE;
911-
FILE* f;
912-
size_t count = 0;
913-
914-
f = fopen(file, "r");
915-
/* a non-existing cookie file is not an error */
916-
if( f == NULL ) { return errno != EPERM; }
917-
/* cookie secret file exists and is readable */
918-
for( count = 0; count < NSD_COOKIE_HISTORY_SIZE; count++ ) {
919-
size_t secret_len = 0;
920-
ssize_t decoded_len = 0;
921-
if( fgets(secret, sizeof(secret), f) == NULL ) { break; }
922-
secret_len = strlen(secret);
923-
if( secret_len == 0 ) { break; }
924-
assert( secret_len <= sizeof(secret) );
925-
secret_len = secret[secret_len - 1] == '\n' ? secret_len - 1 : secret_len;
926-
if( secret_len != NSD_COOKIE_SECRET_SIZE * 2 ) {
927-
fclose(f);
928-
return 0;
929-
}
930-
/* needed for `hex_pton`; stripping potential `\n` */
931-
secret[secret_len] = '\0';
932-
decoded_len = hex_pton(secret, cookie_secrets[count].cookie_secret,
933-
NSD_COOKIE_SECRET_SIZE);
934-
if( decoded_len != NSD_COOKIE_SECRET_SIZE ) {
935-
fclose(f);
936-
return 0;
937-
}
938-
}
939-
fclose(f);
940-
if(count && nsd->cookie_secrets_source <= COOKIE_SECRETS_FROM_FILE) {
941-
nsd->cookie_count = count;
942-
memcpy(nsd->cookie_secrets, cookie_secrets, sizeof(cookie_secrets));
943-
nsd->cookie_secrets_source = COOKIE_SECRETS_FROM_FILE;
944-
}
945-
return 1;
946-
}
947-
948905
extern char *optarg;
949906
extern int optind;
950907

@@ -986,6 +943,7 @@ main(int argc, char *argv[])
986943
nsd.chrootdir = 0;
987944
nsd.nsid = NULL;
988945
nsd.nsid_len = 0;
946+
nsd.do_answer_cookie = 0;
989947
nsd.cookie_count = 0;
990948
nsd.cookie_secrets_source = COOKIE_SECRETS_NONE;
991949

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

997-
nsd.do_answer_cookie = 1;
998955

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

1274-
nsd.do_answer_cookie = nsd.options->answer_cookie;
1275-
if(nsd.options->cookie_secret) {
1276-
ssize_t len = hex_pton(nsd.options->cookie_secret,
1277-
nsd.cookie_secrets[0].cookie_secret,
1278-
NSD_COOKIE_SECRET_SIZE);
1279-
if (len != NSD_COOKIE_SECRET_SIZE ) {
1280-
error("A cookie secret must be a 128 bit hex string");
1281-
}
1282-
nsd.cookie_count = 1;
1283-
nsd.cookie_secrets_source = COOKIE_SECRETS_FROM_CONFIG;
1284-
if(nsd.options->cookie_staging_secret) {
1285-
len = hex_pton(nsd.options->cookie_staging_secret,
1286-
nsd.cookie_secrets[1].cookie_secret,
1287-
NSD_COOKIE_SECRET_SIZE);
1288-
if (len != NSD_COOKIE_SECRET_SIZE ) {
1289-
error("A (staging) cookie secret must be a "
1290-
"128 bit hex string");
1291-
} else
1292-
nsd.cookie_count = 2;
1293-
}
1294-
} else {
1295-
size_t j;
1296-
size_t const cookie_secret_len = NSD_COOKIE_SECRET_SIZE;
1297-
/* Calculate a new random secret */
1298-
srandom(getpid() ^ time(NULL));
1299-
1300-
for( j = 0; j < NSD_COOKIE_HISTORY_SIZE; j++) {
1301-
#if defined(HAVE_SSL)
1302-
if (!RAND_status()
1303-
|| !RAND_bytes(nsd.cookie_secrets[j].cookie_secret, cookie_secret_len))
1304-
#endif
1305-
for (i = 0; i < cookie_secret_len; i++)
1306-
nsd.cookie_secrets[j].cookie_secret[i] = random_generate(256);
1307-
}
1308-
nsd.cookie_count = 1;
1309-
nsd.cookie_secrets_source = COOKIE_SECRETS_GENERATED;
1310-
}
1231+
reconfig_cookies(&nsd, nsd.options);
13111232

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

1613-
if(nsd.cookie_secrets_source < COOKIE_SECRETS_FROM_FILE
1614-
&& (!nsd.options->cookie_secret_file || nsd.options->cookie_secret_file[0])
1615-
&& !cookie_secret_file_read(&nsd) ) {
1616-
log_msg(LOG_ERR, "cookie secret file corrupt or not readable");
1617-
}
16181534
/* Unless we're debugging, fork... */
16191535
if (!nsd.debug) {
16201536
int fd;

options.c

+5
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ parse_options_file(struct nsd_options* opt, const char* file,
257257

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

260+
/* Semantic errors */
261+
if(opt->cookie_staging_secret && !opt->cookie_secret) {
262+
c_error("a cookie-staging-secret cannot be configured without "
263+
"also providing a cookie-secret");
264+
}
260265
RBTREE_FOR(pat, struct pattern_options*, opt->patterns)
261266
{
262267
struct pattern_options* old_pat =

options.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ struct nsd_options {
211211
/** cookie staging secret */
212212
char *cookie_staging_secret;
213213
/** path to cookie secret store */
214-
char const* cookie_secret_file;
214+
char *cookie_secret_file;
215215
/** enable verify */
216216
int verify_enable;
217217
/** list of ip addresses used to serve zones for verification */

remote.c

+62-3
Original file line numberDiff line numberDiff line change
@@ -1969,21 +1969,80 @@ repat_options_changed(xfrd_state_type* xfrd, struct nsd_options* newopt)
19691969
return 0;
19701970
}
19711971

1972+
static int opt_str_changed(const char* old, const char* new)
1973+
{ return !old ? ( !new ? 0 : 1 ) : ( !new ? 1 : strcasecmp(old, new) ); }
1974+
1975+
/** true if cookie options are different that can be set via repat. */
1976+
static int
1977+
repat_cookie_options_changed(struct nsd_options* old, struct nsd_options* new)
1978+
{
1979+
return old->answer_cookie != new->answer_cookie
1980+
|| opt_str_changed( old->cookie_secret
1981+
, new->cookie_secret)
1982+
|| opt_str_changed( old->cookie_staging_secret
1983+
, new->cookie_staging_secret)
1984+
|| opt_str_changed( old->cookie_secret_file
1985+
, new->cookie_secret_file);
1986+
}
1987+
1988+
static void opt_strcpy(region_type* region, char** dst, const char* src)
1989+
{
1990+
assert(dst);
1991+
1992+
if(!*dst) {
1993+
if(src)
1994+
*dst = region_strdup(region, src);
1995+
1996+
} else if(!src) {
1997+
region_recycle(region, *dst, strlen(*dst)+1);
1998+
*dst = NULL;
1999+
2000+
} else if(strcasecmp(*dst, src)) {
2001+
region_recycle(region, *dst, strlen(*dst)+1);
2002+
*dst = region_strdup(region, src);
2003+
}
2004+
}
2005+
19722006
/** check if global options have changed */
19732007
static void
19742008
repat_options(xfrd_state_type* xfrd, struct nsd_options* newopt)
19752009
{
2010+
struct nsd_options* oldopt = xfrd->nsd->options;
2011+
19762012
if(repat_options_changed(xfrd, newopt)) {
19772013
/* update our options */
19782014
#ifdef RATELIMIT
1979-
xfrd->nsd->options->rrl_ratelimit = newopt->rrl_ratelimit;
1980-
xfrd->nsd->options->rrl_whitelist_ratelimit = newopt->rrl_whitelist_ratelimit;
1981-
xfrd->nsd->options->rrl_slip = newopt->rrl_slip;
2015+
oldopt->rrl_ratelimit = newopt->rrl_ratelimit;
2016+
oldopt->rrl_whitelist_ratelimit = newopt->rrl_whitelist_ratelimit;
2017+
oldopt->rrl_slip = newopt->rrl_slip;
19822018
#endif
19832019
task_new_opt_change(xfrd->nsd->task[xfrd->nsd->mytask],
19842020
xfrd->last_task, newopt);
19852021
xfrd_set_reload_now(xfrd);
19862022
}
2023+
if(repat_cookie_options_changed(oldopt, newopt)) {
2024+
/* update our options */
2025+
oldopt->answer_cookie = newopt->answer_cookie;
2026+
opt_strcpy( oldopt->region
2027+
, &oldopt->cookie_secret
2028+
, newopt->cookie_secret);
2029+
opt_strcpy( oldopt->region
2030+
, &oldopt->cookie_staging_secret
2031+
, newopt->cookie_staging_secret);
2032+
opt_strcpy( oldopt->region
2033+
, &oldopt->cookie_secret_file
2034+
, newopt->cookie_secret_file);
2035+
2036+
xfrd->nsd->cookie_count = 0;
2037+
xfrd->nsd->cookie_secrets_source = COOKIE_SECRETS_NONE;
2038+
reconfig_cookies(xfrd->nsd, newopt);
2039+
task_new_cookies( xfrd->nsd->task[xfrd->nsd->mytask]
2040+
, xfrd->last_task
2041+
, xfrd->nsd->do_answer_cookie
2042+
, xfrd->nsd->cookie_count
2043+
, xfrd->nsd->cookie_secrets);
2044+
xfrd_set_reload_now(xfrd);
2045+
}
19872046
}
19882047

19892048
/** print errors over ssl, gets pointer-to-pointer to ssl, so it can set
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
server:
2+
username: ""
3+
zonesdir: ""
4+
xfrdfile: ""
5+
logfile: "nsd.log"
6+
ip-address: lo
7+
8+
include: "cookiesecrets.conf"
9+
10+
remote-control:
11+
control-enable: yes
12+
control-key-file: "dns-cookies.nsd_control.key"
13+
control-cert-file: "dns-cookies.nsd_control.pem"
14+
server-key-file: "dns-cookies.nsd_server.key"
15+
server-cert-file: "dns-cookies.nsd_server.pem"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDqzCCAhMCFBPBN+c2KtT5mAvLhxdCKNiMyNAKMA0GCSqGSIb3DQEBCwUAMA4x
3+
DDAKBgNVBAMMA25zZDAeFw0xOTA0MjUxNTEzMjdaFw0yOTA0MjIxNTEzMjdaMBYx
4+
FDASBgNVBAMMC25zZC1jb250cm9sMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
5+
igKCAYEAp6tA9X7sVaSMYtQh8FkQLhXERl05wDDxKr+Sqap/mctNoh27f7Y37act
6+
gIkjw0FqJByrg73j1bqoVvRwJMWCrQCYP/oAw66rG4FDSN3jBg8lCeXz4qJETiZn
7+
ZQRdWeJyjap6mm6Gj1CzWqmKq9bH+sJEEpXEA/rQM8PL1fSm5RXExSo47RoemL8j
8+
afZd3j/JPUSunj/2/TLRKvJsCJV2JLFLQFvt/4G56C++ExQKsuN6QpfExZmC5cEH
9+
hpYQBk5AfvbSqwzxGgldFQLyboA22spvh3uxVrYJj1bMDfO8Ij5d0Ku/rulsZVoa
10+
ukudr/hhmI56A2IkYZemYdTMAeCrflYJD9TPx0eXzPtLoPJIyUlJ7MCu0rgN+FbH
11+
7jDM1GC9zpQyBtLr97/rNHzk+z2N2WcgYbDhBW13Dv9QkIb2+ZPxhu2W5OTNEdu4
12+
+SHZOtYdPXN7NssiS2ZSIp8+ohkRzZgc8hsPr0yjt78IlzR5DVayz6vev9aRjdao
13+
0vlAroIvAgMBAAEwDQYJKoZIhvcNAQELBQADggGBADc3NTIs6gf+//qcdyTR4hYc
14+
oF53cJ4nWRMmoOJIk4ojF77rzoD2UjQye1X0gpZx55UYyu6O/Mq40krPX4FbMSzA
15+
zLAyzuUPwJGdcgjvvlmSym/LAwTXwGYF32S/qKtpJKFSWny08JBt7DT8fV2P00zE
16+
bV6ozg5HKukEcd2dQczsE3+gHwx7P+jsBBnWZzIgCkPwp4amzpahbQZRH2v9OboX
17+
c1zR/8xXaYbes/BdqzzudhFV/Xd9wHH2EV4mRKPvQMY87FV6eGKYNL2UvPfr4/SH
18+
yiIvd4Rw/vgMtpH9cYMov1v2Qkk9qvV9w5OPYu/4HzCVGssbkUPQX0AAWrUYIdo4
19+
ZqEAzyr1/IevTRYtsA4qkqJqgFfwRmNQH2blRX3vzgNvj2+v4DjvC+HYHuwzkwl8
20+
rbbs+9Ta+SBljSIPFb1+OMBAvgin/kAaYRxfQs6yrIO5abIBm+gfEiFLaP9yqerE
21+
L+oT94EwsPMPVJ09yuVrjVUU430GMS2uqgTIj35TPQ==
22+
-----END CERTIFICATE-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDozCCAgsCFCAZislHgIerlrBBkLFt/ZOkKYVZMA0GCSqGSIb3DQEBCwUAMA4x
3+
DDAKBgNVBAMMA25zZDAeFw0xOTA0MjUxNTEzMjdaFw0yOTA0MjIxNTEzMjdaMA4x
4+
DDAKBgNVBAMMA25zZDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMS8
5+
uXxVCNTo112z3ENd99N/yuQJYk6umwp0ue3nc0CG5j2Y+12xmdEZ1OO3GddRkgCP
6+
abQyK0onTU7B82qlmZ+N9fyFY8KyJEYM/ef2jlkaL+H8JnEuar22FetJd/ODWS6p
7+
heAQw8UrdjC09vo1sRRCtolJtmF2XsIn0PM2h5o3wFpaPE5SuY87dEHNKj7+Zwgu
8+
psLY2+zh7pdzd0KJVuoWTnNSmVRHgXRC3naFPU8jMs4Twb5KgF1qLYvwsFo92DE4
9+
/y+8zX0PRdR1up+u2PpbTvCGnSCz4mYogFSKy6lIdxC9l36vgXCd0LwA48i/ReUx
10+
9wGlqIuomIDBnIHaivZOoY/s4rjMV+jrIM388UxM2Qh4TxK9/Ul+o/3x8yT+GhkM
11+
QABywJr9qfT/6BGXmbL1j7AVmKVCyoDGdCQ2YX9unXawdZqU2qkULBt/OHVGUfX/
12+
4ss07M8IHNj0OyRuoFYO9tyqAYZQ9IPg5QvF3cYkcmg2yT180qF4C1rpsdNjoQID
13+
AQABMA0GCSqGSIb3DQEBCwUAA4IBgQB+WGMopDqNkv7yDAO8Ik2EWieDqxTshqR4
14+
bT1do9zsC9WDrIVxoVcn+dtlIpEQl8MN9U5DTKBbRgk3grOwUsg2kC0Gujv3vAyQ
15+
bF+jxjHWd1xzrbQ+QUgz07P1OMFWxMzECL2L2078UZbawFqKqlmNv5avUk27G8nB
16+
GrujT/pUOIpRXC+rao8e14R84dPJLZuGm9IAeEBQIIdhY9sjFRyoQdCUubyKPpkm
17+
/fpcDMkt7PzZ4nTovj4NUxnnoUGonpXuj0pHA/RDDJkPYaRrND4OGldQXdZ9LJNM
18+
pROL6aCZ5iog74OY8yutVzCgGge9vZLkysceVP7Lyks9/fEAtIuozmulp9TUQAeR
19+
MVdDOcREWRd0vFNtAC9xSloRqV+66CzrFHwkSMpLo+gdgcAZ8s33rgQk+I4gfavU
20+
jPWMZVcZHXevtWuTRnxfOpMkbwiRyr2J8m549K7OKZgr+JRhdJTev4lvXVyfFia4
21+
zr6UOK4exZWP6VDXb4IyZbJh+LMjmws=
22+
-----END CERTIFICATE-----

tpkg/dns-cookies.tdir/dns-cookies.test

+5
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ unshare -rUn bash dns-cookies.test.A3 || exit 1
2525

2626
echo "Starting test A4"
2727
unshare -rUn bash dns-cookies.test.A4 || exit 1
28+
29+
echo "Starting test C1"
30+
unshare -rUn bash dns-cookies.test.C1 || exit 1
31+
32+

0 commit comments

Comments
 (0)