From: Harlan Stenn Date: Mon, 18 Jan 2016 11:55:56 +0000 (+0000) Subject: [Sec 2936] Skeleton Key: Any trusted key system can serve time. HStenn. X-Git-Tag: NTP_4_2_8P6~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb7f8bd8b90845c42237632a3e2f1b0c767731a4;p=thirdparty%2Fntp.git [Sec 2936] Skeleton Key: Any trusted key system can serve time. HStenn. bk: 569cd2ccRluJHjvqRvxDmstIPiBftA --- diff --git a/ChangeLog b/ChangeLog index 7f336f64d..d71ee3572 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ --- * [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 diff --git a/NEWS b/NEWS index e90024109..c759e898c 100644 --- a/NEWS +++ b/NEWS @@ -171,6 +171,46 @@ following X low- and Y medium-severity vulnerabilities: 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 diff --git a/include/Makefile.am b/include/Makefile.am index d8b4dd2b5..521ac146c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -36,6 +36,7 @@ noinst_HEADERS = \ ntp_if.h \ ntp_intres.h \ ntp_io.h \ + ntp_keyacc.h \ ntp_libopts.h \ ntp_lineedit.h \ ntp_lists.h \ diff --git a/include/ntp_io.h b/include/ntp_io.h index 5950f0035..d34d60a80 100644 --- a/include/ntp_io.h +++ b/include/ntp_io.h @@ -40,6 +40,8 @@ #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 @@ -83,7 +85,6 @@ typedef enum { 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, diff --git a/include/ntp_keyacc.h b/include/ntp_keyacc.h new file mode 100644 index 000000000..730c310ac --- /dev/null +++ b/include/ntp_keyacc.h @@ -0,0 +1,13 @@ +/* + * 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 */ diff --git a/include/ntp_stdlib.h b/include/ntp_stdlib.h index d735b41f4..98ac69eb4 100644 --- a/include/ntp_stdlib.h +++ b/include/ntp_stdlib.h @@ -16,6 +16,7 @@ #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))) @@ -69,6 +70,7 @@ extern int authdecrypt (keyid_t, u_int32 *, size_t, size_t); 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 *); @@ -97,7 +99,7 @@ extern int ymd2yd (int, int, int); /* 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 */ @@ -141,6 +143,7 @@ extern int atouint (const char *, u_long *); 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); diff --git a/include/ntp_types.h b/include/ntp_types.h index a947f3057..7ff312547 100644 --- a/include/ntp_types.h +++ b/include/ntp_types.h @@ -218,6 +218,7 @@ typedef uint16_t associd_t; /* association ID */ #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 */ /* diff --git a/libntp/Makefile.am b/libntp/Makefile.am index 914badb5f..a3b50e129 100644 --- a/libntp/Makefile.am +++ b/libntp/Makefile.am @@ -70,6 +70,7 @@ libntp_a_SRCS = \ humandate.c \ icom.c \ iosignal.c \ + is_ip_address.c \ lib_strbuf.c \ machines.c \ mktime.c \ diff --git a/libntp/authkeys.c b/libntp/authkeys.c index 02725fb1b..36fdd8b7c 100644 --- a/libntp/authkeys.c +++ b/libntp/authkeys.c @@ -15,6 +15,7 @@ #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. @@ -25,6 +26,7 @@ struct savekey { 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 */ @@ -50,8 +52,8 @@ symkey_alloc * authallocs; 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); @@ -97,6 +99,7 @@ u_char *cache_secret; /* secret */ 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 */ /* @@ -142,6 +145,7 @@ free_auth_mem(void) 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); @@ -290,7 +294,8 @@ allocsymkey( u_short type, u_long lifetime, u_short secretsize, - u_char * secret + u_char * secret, + KeyAccT * ka ) { symkey * sk; @@ -304,6 +309,7 @@ allocsymkey( 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); @@ -435,6 +441,7 @@ authhavekey( cache_flags = sk->flags; cache_secret = sk->secret; cache_secretsize = sk->secretsize; + cache_keyacclist = sk->keyacclist; return TRUE; } @@ -474,6 +481,7 @@ authtrust( if (cache_keyid == id) { cache_flags = 0; cache_keyid = 0; + cache_keyacclist = NULL; } /* @@ -503,7 +511,7 @@ authtrust( } else { lifetime = 0; } - allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL); + allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); } @@ -534,6 +542,49 @@ authistrusted( 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 @@ -550,7 +601,8 @@ MD5auth_setkey( keyid_t keyno, int keytype, const u_char *key, - size_t len + size_t len, + KeyAccT *ka ) { symkey * sk; @@ -576,6 +628,7 @@ MD5auth_setkey( 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 @@ -586,6 +639,7 @@ MD5auth_setkey( if (cache_keyid == keyno) { cache_flags = 0; cache_keyid = 0; + cache_keyacclist = NULL; } return; } @@ -603,7 +657,7 @@ MD5auth_setkey( 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; diff --git a/libntp/authreadkeys.c b/libntp/authreadkeys.c index 95a357a8c..1d4ee3059 100644 --- a/libntp/authreadkeys.c +++ b/libntp/authreadkeys.c @@ -5,10 +5,12 @@ #include #include +#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" @@ -85,6 +87,7 @@ static void log_maybe(u_int*, const char*, ...) NTP_PRINTF(2, 3); 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 */ @@ -228,6 +231,7 @@ authreadkeys( 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; @@ -257,11 +261,48 @@ authreadkeys( } 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; @@ -286,7 +327,7 @@ authreadkeys( 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); @@ -297,6 +338,14 @@ authreadkeys( /* 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); diff --git a/libntp/authusekey.c b/libntp/authusekey.c index 0ccf522b2..ff449d3df 100644 --- a/libntp/authusekey.c +++ b/libntp/authusekey.c @@ -29,6 +29,6 @@ authusekey( if (0 == len) return 0; - MD5auth_setkey(keyno, keytype, str, len); + MD5auth_setkey(keyno, keytype, str, len, NULL); return 1; } diff --git a/libntp/is_ip_address.c b/libntp/is_ip_address.c new file mode 100644 index 000000000..1f2137645 --- /dev/null +++ b/libntp/is_ip_address.c @@ -0,0 +1,129 @@ +/* + * is_ip_address + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if 0 +#include +#include +#ifdef HAVE_FNMATCH_H +# include +# if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE) +# define FNM_CASEFOLD FNM_IGNORECASE +# endif +#endif +#ifdef HAVE_SYS_PARAM_H +# include +#endif +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance ) */ +# include +#endif +#ifdef HAVE_SYS_UIO_H +# include +#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 +#include +#include +#include +#include + + +/* + * 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; +} diff --git a/ntpd/invoke-ntp.keys.texi b/ntpd/invoke-ntp.keys.texi index b755d97a4..406188969 100644 --- a/ntpd/invoke-ntp.keys.texi +++ b/ntpd/invoke-ntp.keys.texi @@ -6,7 +6,7 @@ # # 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 @@ -37,7 +37,7 @@ as the configuration file. 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 @@ -47,7 +47,15 @@ is a positive integer (between 1 and 65534), 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} diff --git a/ntpd/ntp.keys.5man b/ntpd/ntp.keys.5man index bb0028bd1..58161b6b6 100644 --- a/ntpd/ntp.keys.5man +++ b/ntpd/ntp.keys.5man @@ -1,8 +1,8 @@ -.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 @@ -66,7 +66,7 @@ Key entries use a fixed format of the form .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 @@ -78,7 +78,15 @@ is a positive integer (between 1 and 65534), 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 @@ -160,7 +168,7 @@ the default name of the configuration file .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, . .SH "BUGS" Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org diff --git a/ntpd/ntp.keys.5mdoc b/ntpd/ntp.keys.5mdoc index 9524989cb..11e2fce92 100644 --- a/ntpd/ntp.keys.5mdoc +++ b/ntpd/ntp.keys.5mdoc @@ -1,9 +1,9 @@ -.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 @@ -44,7 +44,7 @@ The key file uses the same comment conventions 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 @@ -53,7 +53,15 @@ is a positive integer (between 1 and 65534), 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 @@ -147,7 +155,7 @@ it to autogen\-users@lists.sourceforge.net. Thank you. .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, . .Sh "BUGS" Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org diff --git a/ntpd/ntp.keys.def b/ntpd/ntp.keys.def index dcb3d55ea..efe774c2e 100644 --- a/ntpd/ntp.keys.def +++ b/ntpd/ntp.keys.def @@ -43,7 +43,7 @@ The key file uses the same comment conventions 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 @@ -52,7 +52,15 @@ is a positive integer (between 1 and 65534), 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 diff --git a/ntpd/ntp.keys.html b/ntpd/ntp.keys.html index 738f9e03e..3ecd36712 100644 --- a/ntpd/ntp.keys.html +++ b/ntpd/ntp.keys.html @@ -3,7 +3,7 @@ NTP Symmetric Key - + @@ -14,18 +14,20 @@ 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; } -->

NTP Symmetric Key

+


-Next: , +Next: , Previous: (dir), Up: (dir) -
+

NTP's Symmetric Key File User Manual

@@ -48,10 +50,12 @@ Up: (dir)
+ +


-Previous: Top, +Previous: Top, Up: Top -
+
@@ -61,9 +65,11 @@ Up: Top be specified in a configuration file, by default /etc/ntp.keys.
-


+ -
+


+ +

Notes about ntp.keys

@@ -93,7 +99,7 @@ may be arbitrarily set in the keys file. as the configuration file. Key entries use a fixed format of the form -
     keyno type key
+
     keyno type key opt_IP_list
 

where keyno @@ -102,7 +108,15 @@ is a positive integer (between 1 and 65534), is the message digest algorithm, and key -is the key itself. +is the key itself, and +opt_IP_list +is an optional comma-separated list of IPs +that are allowed to serve time. +If +opt_IP_list +is empty, +any properly-authenticated server message will be +accepted.

The key @@ -159,23 +173,27 @@ This software is released under the NTP license, <http://ntp.org/license>.

+ +


-Next: , +Next: , Up: ntp.keys Notes -
+

ntp.keys Files

-
/etc/ntp.keys
the default name of the configuration file +
/etc/ntp.keys
the default name of the configuration file
+ +


-Next: , +Next: , Previous: ntp.keys Files, Up: ntp.keys Notes -
+

ntp.keys See Also

@@ -186,10 +204,12 @@ Up: ntp.keys Notes ntpdc(1ntpdcmdoc), sntp(1sntpmdoc)
+ +


-Previous: ntp.keys See Also, +Previous: ntp.keys See Also, Up: ntp.keys Notes -
+

ntp.keys Notes

diff --git a/ntpd/ntp.keys.man.in b/ntpd/ntp.keys.man.in index 78d5f091d..95d290688 100644 --- a/ntpd/ntp.keys.man.in +++ b/ntpd/ntp.keys.man.in @@ -1,8 +1,8 @@ -.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 @@ -66,7 +66,7 @@ Key entries use a fixed format of the form .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 @@ -78,7 +78,15 @@ is a positive integer (between 1 and 65534), 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 @@ -160,7 +168,7 @@ the default name of the configuration file .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, . .SH "BUGS" Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org diff --git a/ntpd/ntp.keys.mdoc.in b/ntpd/ntp.keys.mdoc.in index 40c821e51..7a89ee435 100644 --- a/ntpd/ntp.keys.mdoc.in +++ b/ntpd/ntp.keys.mdoc.in @@ -1,9 +1,9 @@ -.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 @@ -44,7 +44,7 @@ The key file uses the same comment conventions 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 @@ -53,7 +53,15 @@ is a positive integer (between 1 and 65534), 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 @@ -147,7 +155,7 @@ it to autogen\-users@lists.sourceforge.net. Thank you. .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, . .Sh "BUGS" Please send bug reports to: http://bugs.ntp.org, bugs@ntp.org diff --git a/ntpd/ntp_crypto.c b/ntpd/ntp_crypto.c index 7dd39a7c9..86541bdc1 100644 --- a/ntpd/ntp_crypto.c +++ b/ntpd/ntp_crypto.c @@ -269,7 +269,7 @@ session_key( 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", diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index 4b6f4f85b..ee52b1a5c 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -724,78 +724,6 @@ addr_samesubnet( } -/* - * 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 */ diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 03c19144d..ad454099f 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -1597,6 +1597,40 @@ receive( 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 diff --git a/tests/libntp/authkeys.c b/tests/libntp/authkeys.c index bea3fe539..fd11ef623 100644 --- a/tests/libntp/authkeys.c +++ b/tests/libntp/authkeys.c @@ -72,7 +72,7 @@ AddTrustedKey(keyid_t keyno) * 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);