---
* [Sec 2935] Deja Vu: Replay attack on authenticated broadcast mode. HStenn.
+* [Sec 2936] Skeleton Key: Any trusted key system can serve time. HStenn.
* [Sec 2937] ntpq: nextvar() missing length check. perlinger@ntp.org
* [Sec 2938] ntpq saveconfig command allows dangerous characters
in filenames. perlinger@ntp.org
This is potentially more dangerous if ntpq is run as root.
Credit: This weakness was discovered by Jonathan Gardner at Cisco ASIG.
+* Skeleton Key: Any trusted key system can serve time
+ Date Resolved: Stable (4.2.8p6) 19 Jan 2016
+ References: Sec 2936 / CVE-2015-7974
+ Affects: All ntp-4 releases up to, but not including 4.2.8p6, and
+ 4.3.0 up to, but not including 4.3.XX
+ CVSS: (AV:N/AC:H/Au:S/C:N/I:C/A:N) Base Score: 4.9
+ Summary: Symmetric key encryption uses a shared trusted key. The
+ reported title for this issue was "Missing key check allows
+ impersonation between authenticated peers" and the report claimed
+ "A key specified only for one server should only work to
+ authenticate that server, other trusted keys should be refused."
+ Except there has never been any correlation between this trusted
+ key and server v. clients machines and there has never been any
+ way to specify a key only for one server. We have treated this as
+ an enhancement request, and ntp-4.2.8p6 includes other checks and
+ tests to strengthen clients against attacks coming from broadcast
+ servers.
+ Mitigation:
+ Implement BCP-38.
+ If this scenario represents a real or a potential issue for you,
+ upgrade to 4.2.8p6, or later, from the NTP Project Download
+ Page or the NTP Public Services Project Download Page, and
+ use the new field in the ntp.keys file that specifies the list
+ of IPs that are allowed to serve time. Note that this alone
+ will not protect against time packets with forged source IP
+ addresses, however other changes in ntp-4.2.8p6 provide
+ significant mitigation against broadcast attacks. MITM attacks
+ are a different story.
+ If you are unable to upgrade:
+ Don't use broadcast mode if you cannot monitor your client
+ servers.
+ If you choose to use symmetric keys to authenticate time
+ packets in a hostile environment where ephemeral time
+ servers can be created, or if it is expected that malicious
+ time servers will participate in an NTP broadcast domain,
+ limit the number of participating systems that participate
+ in the shared-key group.
+ Monitor your ntpd instances.
+ Credit: This weakness was discovered by Matt Street of Cisco ASIG.
+
* Deja Vu: Replay attack on authenticated broadcast mode
Date Resolved: Stable (4.2.8p6) 19 Jan 2016
References: Sec 2935 / CVE-2015-7973
ntp_if.h \
ntp_intres.h \
ntp_io.h \
+ ntp_keyacc.h \
ntp_libopts.h \
ntp_lineedit.h \
ntp_lists.h \
#include "libntp.h" /* This needs Something above for GETDTABLESIZE */
+#include "ntp_keyacc.h"
+
/*
* Define FNDELAY and FASYNC using O_NONBLOCK and O_ASYNC if we need
* to (and can). This is here initially for QNX, but may help for
extern int qos;
SOCKET move_fd(SOCKET fd);
isc_boolean_t get_broadcastclient_flag(void);
-extern int is_ip_address(const char *, u_short, sockaddr_u *);
extern void sau_from_netaddr(sockaddr_u *, const isc_netaddr_t *);
extern void add_nic_rule(nic_rule_match match_type,
const char *if_name, int prefixlen,
--- /dev/null
+/*
+ * ntp_keyacc.h - key access stuff
+ */
+#ifndef NTP_KEYACC_H
+#define NTP_KEYACC_H
+
+typedef struct keyaccess KeyAccT;
+struct keyaccess {
+ KeyAccT * next;
+ sockaddr_u addr;
+};
+
+#endif /* NTP_KEYACC_H */
#include "ntp_malloc.h"
#include "ntp_string.h"
#include "ntp_syslog.h"
+#include "ntp_keyacc.h"
#ifdef __GNUC__
#define NTP_PRINTF(fmt, args) __attribute__((__format__(__printf__, fmt, args)))
extern size_t authencrypt (keyid_t, u_int32 *, size_t);
extern int authhavekey (keyid_t);
extern int authistrusted (keyid_t);
+extern int authistrustedip (keyid_t, sockaddr_u *);
extern int authreadkeys (const char *);
extern void authtrust (keyid_t, u_long);
extern int authusekey (keyid_t, int, const u_char *);
/* a_md5encrypt.c */
extern int MD5authdecrypt (int, const u_char *, u_int32 *, size_t, size_t);
extern size_t MD5authencrypt (int, const u_char *, u_int32 *, size_t);
-extern void MD5auth_setkey (keyid_t, int, const u_char *, size_t);
+extern void MD5auth_setkey (keyid_t, int, const u_char *, size_t, KeyAccT *c);
extern u_int32 addr2refid (sockaddr_u *);
/* emalloc.c */
extern int hextoint (const char *, u_long *);
extern const char * humanlogtime (void);
extern const char * humantime (time_t);
+extern int is_ip_address (const char *, u_short, sockaddr_u *);
extern char * mfptoa (u_int32, u_int32, short);
extern char * mfptoms (u_int32, u_int32, short);
extern const char * modetoa (size_t);
#define ASSOCID_MAX USHRT_MAX
typedef u_int32 keyid_t; /* cryptographic key ID */
#define KEYID_T_MAX (0xffffffff)
+
typedef u_int32 tstamp_t; /* NTP seconds timestamp */
/*
humandate.c \
icom.c \
iosignal.c \
+ is_ip_address.c \
lib_strbuf.c \
machines.c \
mktime.c \
#include "ntp_string.h"
#include "ntp_malloc.h"
#include "ntp_stdlib.h"
+#include "ntp_keyacc.h"
/*
* Structure to store keys in in the hash table.
symkey * hlink; /* next in hash bucket */
DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */
u_char * secret; /* shared secret */
+ KeyAccT * keyacclist; /* Private key access list */
u_long lifetime; /* remaining lifetime */
keyid_t keyid; /* key identifier */
u_short type; /* OpenSSL digest NID */
static u_short auth_log2(size_t);
static void auth_resize_hashtable(void);
-static void allocsymkey(symkey **, keyid_t, u_short,
- u_short, u_long, u_short, u_char *);
+static void allocsymkey(symkey **, keyid_t, u_short, u_short,
+ u_long, u_short, u_char *, KeyAccT *);
static void freesymkey(symkey *, symkey **);
#ifdef DEBUG
static void free_auth_mem(void);
u_short cache_secretsize; /* secret length */
int cache_type; /* OpenSSL digest NID */
u_short cache_flags; /* flags that wave */
+KeyAccT *cache_keyacclist; /* key access list */
/*
key_hash = NULL;
cache_keyid = 0;
cache_flags = 0;
+ cache_keyacclist = NULL;
for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
next_alloc = alloc->link;
free(alloc->mem);
u_short type,
u_long lifetime,
u_short secretsize,
- u_char * secret
+ u_char * secret,
+ KeyAccT * ka
)
{
symkey * sk;
sk->type = type;
sk->secretsize = secretsize;
sk->secret = secret;
+ sk->keyacclist = ka;
sk->lifetime = lifetime;
LINK_SLIST(*bucket, sk, hlink);
LINK_TAIL_DLIST(key_listhead, sk, llink);
cache_flags = sk->flags;
cache_secret = sk->secret;
cache_secretsize = sk->secretsize;
+ cache_keyacclist = sk->keyacclist;
return TRUE;
}
if (cache_keyid == id) {
cache_flags = 0;
cache_keyid = 0;
+ cache_keyacclist = NULL;
}
/*
} else {
lifetime = 0;
}
- allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL);
+ allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
}
return TRUE;
}
+
+/*
+ * authistrustedip - determine if the IP is OK for the keyid
+ */
+ int
+ authistrustedip(
+ keyid_t keyno,
+ sockaddr_u * sau
+ )
+{
+ symkey * sk;
+ symkey ** bucket;
+ KeyAccT * kal;
+ KeyAccT * k;
+
+ if (keyno == cache_keyid)
+ kal = cache_keyacclist;
+ else {
+ authkeyuncached++;
+ bucket = &key_hash[KEYHASH(keyno)];
+ for (sk = *bucket; sk != NULL; sk = sk->hlink) {
+ if (keyno == sk->keyid)
+ break;
+ }
+ if (NULL == sk || !(KEY_TRUSTED & sk->flags)) {
+ INSIST(!"authistrustedip: keyid not found/trusted!");
+ return FALSE;
+ }
+ kal = sk->keyacclist;
+ }
+
+ if (NULL == kal)
+ return TRUE;
+
+ for (k = kal; k; k = k->next) {
+ if (SOCK_EQ(&k->addr, sau))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
/* Note: There are two locations below where 'strncpy()' is used. While
* this function is a hazard by itself, it's essential that it is used
* here. Bug 1243 involved that the secret was filled with NUL bytes
keyid_t keyno,
int keytype,
const u_char *key,
- size_t len
+ size_t len,
+ KeyAccT *ka
)
{
symkey * sk;
sk->type = (u_short)keytype;
secretsize = len;
sk->secretsize = (u_short)secretsize;
+ sk->keyacclist = ka;
#ifndef DISABLE_BUG1243_FIX
memcpy(sk->secret, key, secretsize);
#else
if (cache_keyid == keyno) {
cache_flags = 0;
cache_keyid = 0;
+ cache_keyacclist = NULL;
}
return;
}
strncpy((char *)secret, (const char *)key, secretsize);
#endif
allocsymkey(bucket, keyno, 0, (u_short)keytype, 0,
- (u_short)secretsize, secret);
+ (u_short)secretsize, secret, ka);
#ifdef DEBUG
if (debug >= 4) {
size_t j;
#include <stdio.h>
#include <ctype.h>
+#include "ntpd.h" /* Only for DPRINTF */
#include "ntp_fp.h"
#include "ntp.h"
#include "ntp_syslog.h"
#include "ntp_stdlib.h"
+#include "ntp_keyacc.h"
#ifdef OPENSSL
#include "openssl/objects.h"
typedef struct keydata KeyDataT;
struct keydata {
KeyDataT *next; /* queue/stack link */
+ KeyAccT *keyacclist; /* key access list */
keyid_t keyid; /* stored key ID */
u_short keytype; /* stored key type */
u_short seclen; /* length of secret */
len = strlen(token);
if (len <= 20) { /* Bug 2537 */
next = emalloc(sizeof(KeyDataT) + len);
+ next->keyacclist = NULL;
next->keyid = keyno;
next->keytype = keytype;
next->seclen = len;
}
len = jlim/2; /* hmmmm.... what about odd length?!? */
next = emalloc(sizeof(KeyDataT) + len);
+ next->keyacclist = NULL;
next->keyid = keyno;
next->keytype = keytype;
next->seclen = len;
memcpy(next->secbuf, keystr, len);
}
+
+ token = nexttok(&line);
+DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL"));
+ if (token != NULL) { /* A comma-separated IP access list */
+ char *tp = token;
+
+ while (tp) {
+ char *i;
+ KeyAccT ka;
+
+ i = strchr(tp, (int)',');
+ if (i)
+ *i = '\0';
+DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp));
+
+ if (is_ip_address(tp, AF_UNSPEC, &ka.addr)) {
+ KeyAccT *kap;
+
+ kap = emalloc(sizeof(KeyAccT));
+ memcpy(kap, &ka, sizeof ka);
+ kap->next = next->keyacclist;
+ next->keyacclist = kap;
+ } else {
+ log_maybe(&nerr,
+ "authreadkeys: invalid IP address <%s> for key %d",
+ tp, keyno);
+ }
+
+ if (i) {
+ tp = i + 1;
+ } else {
+ tp = 0;
+ }
+ }
+ }
+
INSIST(NULL != next);
next->next = list;
list = next;
while (NULL != (next = list)) {
list = next->next;
MD5auth_setkey(next->keyid, next->keytype,
- next->secbuf, next->seclen);
+ next->secbuf, next->seclen, next->keyacclist);
/* purge secrets from memory before free()ing it */
memset(next, 0, sizeof(*next) + next->seclen);
free(next);
/* Mop up temporary storage before bailing out. */
while (NULL != (next = list)) {
list = next->next;
+
+ while (next->keyacclist) {
+ KeyAccT *kap = next->keyacclist;
+
+ next->keyacclist = kap->next;
+ free(kap);
+ }
+
/* purge secrets from memory before free()ing it */
memset(next, 0, sizeof(*next) + next->seclen);
free(next);
if (0 == len)
return 0;
- MD5auth_setkey(keyno, keytype, str, len);
+ MD5auth_setkey(keyno, keytype, str, len, NULL);
return 1;
}
--- /dev/null
+/*
+ * is_ip_address
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if 0
+#include <stdio.h>
+#include <signal.h>
+#ifdef HAVE_FNMATCH_H
+# include <fnmatch.h>
+# if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE)
+# define FNM_CASEFOLD FNM_IGNORECASE
+# endif
+#endif
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
+# include <sys/sockio.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+# include <sys/uio.h>
+#endif
+#endif
+
+#include "ntp_assert.h"
+#include "ntp_stdlib.h"
+#include "safecast.h"
+
+#if 0
+#include "ntp_machine.h"
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "iosignal.h"
+#include "ntp_lists.h"
+#include "ntp_refclock.h"
+#include "ntp_worker.h"
+#include "ntp_request.h"
+#include "timevalops.h"
+#include "timespecops.h"
+#include "ntpd-opts.h"
+#endif
+
+/* Don't include ISC's version of IPv6 variables and structures */
+#define ISC_IPV6_H 1
+#include <isc/mem.h>
+#include <isc/interfaceiter.h>
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+
+
+/*
+ * Code to tell if we have an IP address
+ * If we have then return the sockaddr structure
+ * and set the return value
+ * see the bind9/getaddresses.c for details
+ */
+int
+is_ip_address(
+ const char * host,
+ u_short af,
+ sockaddr_u * addr
+ )
+{
+ struct in_addr in4;
+ struct addrinfo hints;
+ struct addrinfo *result;
+ struct sockaddr_in6 *resaddr6;
+ char tmpbuf[128];
+ char *pch;
+
+ REQUIRE(host != NULL);
+ REQUIRE(addr != NULL);
+
+ ZERO_SOCK(addr);
+
+ /*
+ * Try IPv4, then IPv6. In order to handle the extended format
+ * for IPv6 scoped addresses (address%scope_ID), we'll use a local
+ * working buffer of 128 bytes. The length is an ad-hoc value, but
+ * should be enough for this purpose; the buffer can contain a string
+ * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
+ * addresses (up to 46 bytes), the delimiter character and the
+ * terminating NULL character.
+ */
+ if (AF_UNSPEC == af || AF_INET == af)
+ if (inet_pton(AF_INET, host, &in4) == 1) {
+ AF(addr) = AF_INET;
+ SET_ADDR4N(addr, in4.s_addr);
+
+ return TRUE;
+ }
+
+ if (AF_UNSPEC == af || AF_INET6 == af)
+ if (sizeof(tmpbuf) > strlen(host)) {
+ if ('[' == host[0]) {
+ strlcpy(tmpbuf, &host[1], sizeof(tmpbuf));
+ pch = strchr(tmpbuf, ']');
+ if (pch != NULL)
+ *pch = '\0';
+ } else {
+ strlcpy(tmpbuf, host, sizeof(tmpbuf));
+ }
+ ZERO(hints);
+ hints.ai_family = AF_INET6;
+ hints.ai_flags |= AI_NUMERICHOST;
+ if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) {
+ AF(addr) = AF_INET6;
+ resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr);
+ SET_ADDR6N(addr, resaddr6->sin6_addr);
+ SET_SCOPE(addr, resaddr6->sin6_scope_id);
+
+ freeaddrinfo(result);
+ return TRUE;
+ }
+ }
+ /*
+ * If we got here it was not an IP address
+ */
+ return FALSE;
+}
#
# EDIT THIS FILE WITH CAUTION (invoke-ntp.keys.texi)
#
-# It has been AutoGen-ed January 7, 2016 at 11:30:52 PM by AutoGen 5.18.5
+# It has been AutoGen-ed January 18, 2016 at 10:46:58 AM by AutoGen 5.18.5
# From the definitions ntp.keys.def
# and the template file agtexi-file.tpl
@end ignore
Key entries use a fixed format of the form
@example
-@kbd{keyno} @kbd{type} @kbd{key}
+@kbd{keyno} @kbd{type} @kbd{key} @kbd{opt_IP_list}
@end example
where
is the message digest algorithm,
and
@kbd{key}
-is the key itself.
+is the key itself, and
+@kbd{opt_IP_list}
+is an optional comma-separated list of IPs
+that are allowed to serve time.
+If
+@kbd{opt_IP_list}
+is empty,
+any properly-authenticated server message will be
+accepted.
The
@kbd{key}
-.TH ntp.keys 5man "07 Jan 2016" "4.2.8p5" "File Formats"
+.TH ntp.keys 5man "18 Jan 2016" "4.2.8p5" "File Formats"
.\"
.\" EDIT THIS FILE WITH CAUTION (ntp.man)
.\"
-.\" It has been AutoGen-ed January 7, 2016 at 11:30:41 PM by AutoGen 5.18.5
+.\" It has been AutoGen-ed January 18, 2016 at 10:47:00 AM by AutoGen 5.18.5
.\" From the definitions ntp.keys.def
.\" and the template file agman-file.tpl
.Sh NAME
.ne 2
.in +4
-\f\*[I-Font]keyno\f[] \f\*[I-Font]type\f[] \f\*[I-Font]key\f[]
+\f\*[I-Font]keyno\f[] \f\*[I-Font]type\f[] \f\*[I-Font]key\f[] \f\*[I-Font]opt_IP_list\f[]
.in -4
.sp \n(Ppu
.ne 2
is the message digest algorithm,
and
\f\*[I-Font]key\f[]
-is the key itself.
+is the key itself, and
+\f\*[I-Font]opt_IP_list\f[]
+is an optional comma-separated list of IPs
+that are allowed to serve time.
+If
+\f\*[I-Font]opt_IP_list\f[]
+is empty,
+any properly-authenticated server message will be
+accepted.
.sp \n(Ppu
.ne 2
.SH "AUTHORS"
The University of Delaware and Network Time Foundation
.SH "COPYRIGHT"
-Copyright (C) 1992-2015 The University of Delaware and Network Time Foundation all rights reserved.
+Copyright (C) 1992-2016 The University of Delaware and Network Time Foundation all rights reserved.
This program is released under the terms of the NTP license, <http://ntp.org/license>.
.SH "BUGS"
Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org
-.Dd January 7 2016
+.Dd January 18 2016
.Dt NTP_KEYS 5mdoc File Formats
-.Os SunOS 5.10
+.Os Linux 3.2.0-4-686-pae
.\" EDIT THIS FILE WITH CAUTION (ntp.mdoc)
.\"
-.\" It has been AutoGen-ed January 7, 2016 at 11:31:00 PM by AutoGen 5.18.5
+.\" It has been AutoGen-ed January 18, 2016 at 10:46:56 AM by AutoGen 5.18.5
.\" From the definitions ntp.keys.def
.\" and the template file agmdoc-file.tpl
.Sh NAME
as the configuration file.
Key entries use a fixed format of the form
.Pp
-.D1 Ar keyno type key
+.D1 Ar keyno type key opt_IP_list
.Pp
where
.Ar keyno
is the message digest algorithm,
and
.Ar key
-is the key itself.
+is the key itself, and
+.Ar opt_IP_list
+is an optional comma\-separated list of IPs
+that are allowed to serve time.
+If
+.Ar opt_IP_list
+is empty,
+any properly\-authenticated server message will be
+accepted.
.Pp
The
.Ar key
.Sh "AUTHORS"
The University of Delaware and Network Time Foundation
.Sh "COPYRIGHT"
-Copyright (C) 1992\-2015 The University of Delaware and Network Time Foundation all rights reserved.
+Copyright (C) 1992\-2016 The University of Delaware and Network Time Foundation all rights reserved.
This program is released under the terms of the NTP license, <http://ntp.org/license>.
.Sh "BUGS"
Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org
as the configuration file.
Key entries use a fixed format of the form
.Pp
-.D1 Ar keyno type key
+.D1 Ar keyno type key opt_IP_list
.Pp
where
.Ar keyno
is the message digest algorithm,
and
.Ar key
-is the key itself.
+is the key itself, and
+.Ar opt_IP_list
+is an optional comma-separated list of IPs
+that are allowed to serve time.
+If
+.Ar opt_IP_list
+is empty,
+any properly-authenticated server message will be
+accepted.
.Pp
The
.Ar key
<title>NTP Symmetric Key</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="NTP Symmetric Key">
-<meta name="generator" content="makeinfo 4.7">
+<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="top" href="#Top">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<meta http-equiv="Content-Style-Type" content="text/css">
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
- span.sc { font-variant:small-caps }
- span.roman { font-family: serif; font-weight: normal; }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family:serif; font-weight:normal; }
+ span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
</head>
<body>
<h1 class="settitle">NTP Symmetric Key</h1>
<div class="node">
+<a name="Top"></a>
<p><hr>
-<a name="Top"></a>Next: <a rel="next" accesskey="n" href="#ntp_002ekeys-Description">ntp.keys Description</a>,
+Next: <a rel="next" accesskey="n" href="#ntp_002ekeys-Description">ntp.keys Description</a>,
Previous: <a rel="previous" accesskey="p" href="#dir">(dir)</a>,
Up: <a rel="up" accesskey="u" href="#dir">(dir)</a>
-<br>
+
</div>
<h2 class="unnumbered">NTP's Symmetric Key File User Manual</h2>
</ul>
<div class="node">
+<a name="ntp.keys-Description"></a>
+<a name="ntp_002ekeys-Description"></a>
<p><hr>
-<a name="ntp_002ekeys-Description"></a>Previous: <a rel="previous" accesskey="p" href="#Top">Top</a>,
+Previous: <a rel="previous" accesskey="p" href="#Top">Top</a>,
Up: <a rel="up" accesskey="u" href="#Top">Top</a>
-<br>
+
</div>
<!-- node-name, next, previous, up -->
be specified in a configuration file, by default <code>/etc/ntp.keys</code>.
<div class="node">
-<p><hr>
+<a name="ntp.keys-Notes"></a>
<a name="ntp_002ekeys-Notes"></a>
-<br>
+<p><hr>
+
+
</div>
<h3 class="section">Notes about ntp.keys</h3>
as the configuration file.
Key entries use a fixed format of the form
-<pre class="example"> <kbd>keyno</kbd> <kbd>type</kbd> <kbd>key</kbd>
+<pre class="example"> <kbd>keyno</kbd> <kbd>type</kbd> <kbd>key</kbd> <kbd>opt_IP_list</kbd>
</pre>
<p>where
<kbd>keyno</kbd>
is the message digest algorithm,
and
<kbd>key</kbd>
-is the key itself.
+is the key itself, and
+<kbd>opt_IP_list</kbd>
+is an optional comma-separated list of IPs
+that are allowed to serve time.
+If
+<kbd>opt_IP_list</kbd>
+is empty,
+any properly-authenticated server message will be
+accepted.
<p>The
<kbd>key</kbd>
</ul>
<div class="node">
+<a name="ntp.keys-Files"></a>
+<a name="ntp_002ekeys-Files"></a>
<p><hr>
-<a name="ntp_002ekeys-Files"></a>Next: <a rel="next" accesskey="n" href="#ntp_002ekeys-See-Also">ntp.keys See Also</a>,
+Next: <a rel="next" accesskey="n" href="#ntp_002ekeys-See-Also">ntp.keys See Also</a>,
Up: <a rel="up" accesskey="u" href="#ntp_002ekeys-Notes">ntp.keys Notes</a>
-<br>
+
</div>
<h4 class="subsection">ntp.keys Files</h4>
<dl>
-<dt><span class="file">/etc/ntp.keys</span><dd>the default name of the configuration file
+<dt><samp><span class="file">/etc/ntp.keys</span></samp><dd>the default name of the configuration file
</dl>
<div class="node">
+<a name="ntp.keys-See-Also"></a>
+<a name="ntp_002ekeys-See-Also"></a>
<p><hr>
-<a name="ntp_002ekeys-See-Also"></a>Next: <a rel="next" accesskey="n" href="#ntp_002ekeys-Notes">ntp.keys Notes</a>,
+Next: <a rel="next" accesskey="n" href="#ntp_002ekeys-Notes">ntp.keys Notes</a>,
Previous: <a rel="previous" accesskey="p" href="#ntp_002ekeys-Files">ntp.keys Files</a>,
Up: <a rel="up" accesskey="u" href="#ntp_002ekeys-Notes">ntp.keys Notes</a>
-<br>
+
</div>
<h4 class="subsection">ntp.keys See Also</h4>
<code>ntpdc(1ntpdcmdoc)</code>,
<code>sntp(1sntpmdoc)</code>
<div class="node">
+<a name="ntp.keys-Notes"></a>
+<a name="ntp_002ekeys-Notes"></a>
<p><hr>
-<a name="ntp_002ekeys-Notes"></a>Previous: <a rel="previous" accesskey="p" href="#ntp_002ekeys-See-Also">ntp.keys See Also</a>,
+Previous: <a rel="previous" accesskey="p" href="#ntp_002ekeys-See-Also">ntp.keys See Also</a>,
Up: <a rel="up" accesskey="u" href="#ntp_002ekeys-Notes">ntp.keys Notes</a>
-<br>
+
</div>
<h4 class="subsection">ntp.keys Notes</h4>
-.TH ntp.keys 5 "07 Jan 2016" "4.2.8p5" "File Formats"
+.TH ntp.keys 5 "18 Jan 2016" "4.2.8p5" "File Formats"
.\"
.\" EDIT THIS FILE WITH CAUTION (ntp.man)
.\"
-.\" It has been AutoGen-ed January 7, 2016 at 11:30:41 PM by AutoGen 5.18.5
+.\" It has been AutoGen-ed January 18, 2016 at 10:47:00 AM by AutoGen 5.18.5
.\" From the definitions ntp.keys.def
.\" and the template file agman-file.tpl
.Sh NAME
.ne 2
.in +4
-\f\*[I-Font]keyno\f[] \f\*[I-Font]type\f[] \f\*[I-Font]key\f[]
+\f\*[I-Font]keyno\f[] \f\*[I-Font]type\f[] \f\*[I-Font]key\f[] \f\*[I-Font]opt_IP_list\f[]
.in -4
.sp \n(Ppu
.ne 2
is the message digest algorithm,
and
\f\*[I-Font]key\f[]
-is the key itself.
+is the key itself, and
+\f\*[I-Font]opt_IP_list\f[]
+is an optional comma-separated list of IPs
+that are allowed to serve time.
+If
+\f\*[I-Font]opt_IP_list\f[]
+is empty,
+any properly-authenticated server message will be
+accepted.
.sp \n(Ppu
.ne 2
.SH "AUTHORS"
The University of Delaware and Network Time Foundation
.SH "COPYRIGHT"
-Copyright (C) 1992-2015 The University of Delaware and Network Time Foundation all rights reserved.
+Copyright (C) 1992-2016 The University of Delaware and Network Time Foundation all rights reserved.
This program is released under the terms of the NTP license, <http://ntp.org/license>.
.SH "BUGS"
Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org
-.Dd January 7 2016
+.Dd January 18 2016
.Dt NTP_KEYS 5 File Formats
-.Os SunOS 5.10
+.Os Linux 3.2.0-4-686-pae
.\" EDIT THIS FILE WITH CAUTION (ntp.mdoc)
.\"
-.\" It has been AutoGen-ed January 7, 2016 at 11:31:00 PM by AutoGen 5.18.5
+.\" It has been AutoGen-ed January 18, 2016 at 10:46:56 AM by AutoGen 5.18.5
.\" From the definitions ntp.keys.def
.\" and the template file agmdoc-file.tpl
.Sh NAME
as the configuration file.
Key entries use a fixed format of the form
.Pp
-.D1 Ar keyno type key
+.D1 Ar keyno type key opt_IP_list
.Pp
where
.Ar keyno
is the message digest algorithm,
and
.Ar key
-is the key itself.
+is the key itself, and
+.Ar opt_IP_list
+is an optional comma\-separated list of IPs
+that are allowed to serve time.
+If
+.Ar opt_IP_list
+is empty,
+any properly\-authenticated server message will be
+accepted.
.Pp
The
.Ar key
.Sh "AUTHORS"
The University of Delaware and Network Time Foundation
.Sh "COPYRIGHT"
-Copyright (C) 1992\-2015 The University of Delaware and Network Time Foundation all rights reserved.
+Copyright (C) 1992\-2016 The University of Delaware and Network Time Foundation all rights reserved.
This program is released under the terms of the NTP license, <http://ntp.org/license>.
.Sh "BUGS"
Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org
memcpy(&keyid, dgst, 4);
keyid = ntohl(keyid);
if (lifetime != 0) {
- MD5auth_setkey(keyno, crypto_nid, dgst, len);
+ MD5auth_setkey(keyno, crypto_nid, dgst, len, NULL);
authtrust(keyno, lifetime);
}
DPRINTF(2, ("session_key: %s > %s %08x %08x hash %08x life %lu\n",
}
-/*
- * Code to tell if we have an IP address
- * If we have then return the sockaddr structure
- * and set the return value
- * see the bind9/getaddresses.c for details
- */
-int
-is_ip_address(
- const char * host,
- u_short af,
- sockaddr_u * addr
- )
-{
- struct in_addr in4;
- struct addrinfo hints;
- struct addrinfo *result;
- struct sockaddr_in6 *resaddr6;
- char tmpbuf[128];
- char *pch;
-
- REQUIRE(host != NULL);
- REQUIRE(addr != NULL);
-
- ZERO_SOCK(addr);
-
- /*
- * Try IPv4, then IPv6. In order to handle the extended format
- * for IPv6 scoped addresses (address%scope_ID), we'll use a local
- * working buffer of 128 bytes. The length is an ad-hoc value, but
- * should be enough for this purpose; the buffer can contain a string
- * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
- * addresses (up to 46 bytes), the delimiter character and the
- * terminating NULL character.
- */
- if (AF_UNSPEC == af || AF_INET == af)
- if (inet_pton(AF_INET, host, &in4) == 1) {
- AF(addr) = AF_INET;
- SET_ADDR4N(addr, in4.s_addr);
-
- return TRUE;
- }
-
- if (AF_UNSPEC == af || AF_INET6 == af)
- if (sizeof(tmpbuf) > strlen(host)) {
- if ('[' == host[0]) {
- strlcpy(tmpbuf, &host[1], sizeof(tmpbuf));
- pch = strchr(tmpbuf, ']');
- if (pch != NULL)
- *pch = '\0';
- } else {
- strlcpy(tmpbuf, host, sizeof(tmpbuf));
- }
- ZERO(hints);
- hints.ai_family = AF_INET6;
- hints.ai_flags |= AI_NUMERICHOST;
- if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) {
- AF(addr) = AF_INET6;
- resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr);
- SET_ADDR6N(addr, resaddr6->sin6_addr);
- SET_SCOPE(addr, resaddr6->sin6_scope_id);
-
- freeaddrinfo(result);
- return TRUE;
- }
- }
- /*
- * If we got here it was not an IP address
- */
- return FALSE;
-}
-
-
/*
* interface list enumerator - visitor pattern
*/
return; /* Drop any other kiss code packets */
}
+ /*
+ * If:
+ * - this is a *cast (uni-, broad-, or m-) server packet
+ * - and it's authenticated
+ * then see if the sender's IP is trusted for this keyid.
+ * If it is, great - nothing special to do here.
+ * Otherwise, we should report and bail.
+ */
+
+ switch (hismode) {
+ case MODE_SERVER: /* server mode */
+ case MODE_BROADCAST: /* broadcast mode */
+ case MODE_ACTIVE: /* symmetric active mode */
+ if ( is_authentic == AUTH_OK
+ && !authistrustedip(skeyid, &peer->srcadr)) {
+ report_event(PEVNT_AUTH, peer, "authIP");
+ peer->badauth++;
+ return;
+ }
+ break;
+
+ case MODE_UNSPEC: /* unspecified (old version) */
+ case MODE_PASSIVE: /* symmetric passive mode */
+ case MODE_CLIENT: /* client mode */
+#if 0 /* At this point, MODE_CONTROL is overloaded by MODE_BCLIENT */
+ case MODE_CONTROL: /* control mode */
+#endif
+ case MODE_PRIVATE: /* private mode */
+ case MODE_BCLIENT: /* broadcast client mode */
+ break;
+ default:
+ break;
+ }
+
/*
* That was hard and I am sweaty, but the packet is squeaky
* We need to add a MD5-key in addition to setting the
* trust, because authhavekey() requires type != 0.
*/
- MD5auth_setkey(keyno, KEYTYPE, NULL, 0);
+ MD5auth_setkey(keyno, KEYTYPE, NULL, 0, NULL);
authtrust(keyno, TRUE);