+---
+* [Bug 3689] Extension for MD5, SHA-1 and other keys <perlinger@ntp.org>
+ - ntp{q,dc} now use the same password processing as ntpd does in the key
+ file, so havin a binary secret >= 11 bytes is possible for all keys.
+ (This is a different approach to the roblem than suggested)
+
---
(4.2.8p15) 2020/06/23 Released by Harlan Stenn <stenn@ntp.org>
typedef void (*ctrl_c_fn)(void);
/* authkeys.c */
+#define AUTHPWD_UNSPEC 0
+#define AUTHPWD_PLAIN 1
+#define AUTHPWD_HEX 2
+
extern void auth_delkeys (void);
extern int auth_havekey (keyid_t);
+extern size_t authdecodepw (u_char *dst, size_t dstlen, const char *src, int fmt);
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);
cache_secret, cache_secretsize,
pkt, length, size);
}
+
+/* password decoding helpers */
+static size_t
+pwdecode_plain(
+ u_char * dst,
+ size_t dstlen,
+ const char * src
+ )
+{
+ size_t srclen = strlen(src);
+ if (srclen > dstlen) {
+ errno = ENOMEM;
+ return (size_t)-1;
+ }
+ memcpy(dst, src, srclen);
+ return srclen;
+}
+
+static size_t
+pwdecode_hex(
+ u_char * dst,
+ size_t dstlen,
+ const char * src
+ )
+{
+ static const char hex[] = "00112233445566778899AaBbCcDdEeFf";
+
+ size_t srclen = strlen(src);
+ size_t reslen = (srclen >> 1) + (srclen & 1);
+ u_char tmp;
+ char *ptr;
+ size_t j;
+
+ if (reslen > dstlen) {
+ errno = ENOMEM;
+ reslen = (size_t)-1;
+ } else {
+ for (j = 0; j < srclen; ++j) {
+ tmp = *(const unsigned char*)(src + j);
+ ptr = strchr(hex, tmp);
+ if (ptr == NULL) {
+ errno = EINVAL;
+ reslen = (size_t)-1;
+ break;
+ }
+ tmp = (u_char)((ptr - hex) > 1);
+ if (j & 1)
+ dst[j >> 1] |= tmp;
+ else
+ dst[j >> 1] = tmp << 4;
+ }
+ }
+ return reslen;
+}
+/*
+ * authdecodepw - decode plaintext or hex-encoded password to binary
+ * secret. Returns size of secret in bytes or -1 on error.
+ */
+size_t
+authdecodepw(
+ u_char * dst,
+ size_t dstlen,
+ const char * src,
+ int fmt
+ )
+{
+ size_t reslen;
+
+ if ( !(dst && dstlen && src)) {
+ errno = EINVAL;
+ reslen = (size_t)-1;
+ } else {
+ switch (fmt) {
+ case AUTHPWD_UNSPEC:
+ if (strlen(src) <= 20)
+ reslen = pwdecode_plain(dst, dstlen, src);
+ else
+ reslen = pwdecode_hex(dst, dstlen, src);
+ break;
+ case AUTHPWD_PLAIN:
+ reslen = pwdecode_plain(dst, dstlen, src);
+ break;
+ case AUTHPWD_HEX:
+ reslen = pwdecode_hex(dst, dstlen, src);
+ break;
+ default:
+ errno = EINVAL;
+ reslen = (size_t)-1;
+ }
+ }
+ return reslen;
+}
*/
while (*cp == ' ' || *cp == '\t')
cp++;
-
+
/*
* Save this and space to end of token
*/
while (*cp != '\0' && *cp != '\n' && *cp != ' '
&& *cp != '\t' && *cp != '#')
cp++;
-
+
/*
* If token length is zero return an error, else set end of
* token to zero and return start.
*/
if (starttok == cp)
return NULL;
-
+
if (*cp == ' ' || *cp == '\t')
*cp++ = '\0';
else
*cp = '\0';
-
+
*str = cp;
return starttok;
}
)
{
KeyAccT *kap;
-
+
if (node) {
while (node->keyacclist) {
kap = node->keyacclist;
keyid_t keyno;
int keytype;
char buf[512]; /* lots of room for line */
- u_char keystr[32]; /* Bug 2537 */
+ u_char keystr[64]; /* Bug 2537 */
size_t len;
- size_t j;
u_int nerr;
KeyDataT *list = NULL;
KeyDataT *next = NULL;
token = nexttok(&line);
if (token == NULL)
continue;
-
+
/*
* First is key number. See if it is okay.
*/
* have to process the line completely and have to
* finally throw away the result... This is a bit more
* work, but it also results in better error detection.
- */
+ */
#ifdef OPENSSL
/*
- * The key type is the NID used by the message digest
+ * The key type is the NID used by the message digest
* algorithm. There are a number of inconsistencies in
* the OpenSSL database. We attempt to discover them
* here and prevent use of inconsistent data later.
continue;
}
next = NULL;
- 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;
- memcpy(next->secbuf, token, len);
- } else {
- static const char hex[] = "0123456789abcdef";
- u_char temp;
- char *ptr;
- size_t jlim;
-
- jlim = min(len, 2 * sizeof(keystr));
- for (j = 0; j < jlim; j++) {
- ptr = strchr(hex, tolower((unsigned char)token[j]));
- if (ptr == NULL)
- break; /* abort decoding */
- temp = (u_char)(ptr - hex);
- if (j & 1)
- keystr[j / 2] |= temp;
- else
- keystr[j / 2] = temp << 4;
- }
- if (j < jlim) {
+ len = authdecodepw(keystr, sizeof(keystr), token, AUTHPWD_UNSPEC);
+ if (len > sizeof(keystr)) {
+ switch (errno) {
+ case ENOMEM:
+ log_maybe(&nerr,
+ "authreadkeys: passwd too long for key %d",
+ keyno);
+ break;
+ case EINVAL:
log_maybe(&nerr,
- "authreadkeys: invalid hex digit for key %d",
+ "authreadkeys: passwd has bad char for key %d",
keyno);
- continue;
+ break;
+ default:
+ log_maybe(&nerr,
+ "authreadkeys: unknown errno %d for key %d",
+ errno, keyno);
+ break;
}
- 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);
+ continue;
}
+ 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);
if (token != NULL) { /* A comma-separated IP access list */
next = NULL;
continue;
}
-
+
INSIST(NULL != next);
next->next = list;
list = next;
#include "ntp_stdlib.h"
/*
- * Types of ascii representations for keys. "Standard" means a 64 bit
- * hex number in NBS format, i.e. with the low order bit of each byte
- * a parity bit. "NTP" means a 64 bit key in NTP format, with the
- * high order bit of each byte a parity bit. "Ascii" means a 1-to-8
- * character string whose ascii representation is used as the key.
+ * Only used by ntp{q,dc} to set the key/algo/secret triple to use.
+ * Uses the same decoding scheme ntpd uses for keys in the key file.
*/
int
authusekey(
)
{
size_t len;
-
- len = strlen((const char *)str);
- if (0 == len)
+ u_char buf[64];
+
+ len = authdecodepw(buf, sizeof(buf), (const char*)str,
+ AUTHPWD_UNSPEC);
+ if (len < 1 || len > sizeof(buf))
return 0;
-
- MD5auth_setkey(keyno, keytype, str, len, NULL);
+
+ MD5auth_setkey(keyno, keytype, buf, len, NULL);
+ memset(buf, 0, sizeof(buf));
return 1;
}