From: Dave Hart Date: Thu, 12 Nov 2009 00:51:35 +0000 (+0000) Subject: Cleanup, fix ntp_intres when requestkey type means digests X-Git-Tag: NTP_4_2_5P244_RC~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=67a9f0f798da7e25c41dd2f810207ea98343ceea;p=thirdparty%2Fntp.git Cleanup, fix ntp_intres when requestkey type means digests larger than 16 octets. Add /lib to OpenSSL library search path, OpenSolaris has it there. bk: 4afb5c17_FCklSAA8sArpvcR3zWSIA --- diff --git a/configure.ac b/configure.ac index c9eb8972a..eafde1240 100644 --- a/configure.ac +++ b/configure.ac @@ -3249,7 +3249,7 @@ esac]) case "$ans" in no) ;; yes) # Look in: - ans="/usr/lib /usr/lib/openssl /usr/sfw/lib /usr/local/lib /usr/local/ssl/lib" + ans="/usr/lib /usr/lib/openssl /usr/sfw/lib /usr/local/lib /usr/local/ssl/lib /lib" ;; *) # Look where they said ;; @@ -3346,7 +3346,6 @@ case "$ntp_openssl" in esac AC_SUBST(LCRYPTO, [-lcrypto]) AC_DEFINE(OPENSSL, , [Use OpenSSL?]) - AC_CHECK_FUNCS([EVP_md2 EVP_mdc2]) esac # diff --git a/include/ntp_request.h b/include/ntp_request.h index 1d4e90ba4..8b6dbf3b6 100644 --- a/include/ntp_request.h +++ b/include/ntp_request.h @@ -136,7 +136,7 @@ struct req_pkt { /* struct conf_peer must fit */ l_fp tstamp; /* time stamp, for authentication */ keyid_t keyid; /* (optional) encryption key */ - char mac[MAX_MD5_LEN-sizeof(keyid_t)]; /* (optional) auth code */ + char mac[MAX_MAC_LEN-sizeof(keyid_t)]; /* (optional) auth code */ }; /* @@ -146,13 +146,16 @@ struct req_pkt { struct req_pkt_tail { l_fp tstamp; /* time stamp, for authentication */ keyid_t keyid; /* (optional) encryption key */ - char mac[MAX_MD5_LEN-sizeof(keyid_t)]; /* (optional) auth code */ + char mac[MAX_MAC_LEN-sizeof(keyid_t)]; /* (optional) auth code */ }; /* MODE_PRIVATE request packet header length before optional items. */ #define REQ_LEN_HDR (offsetof(struct req_pkt, data)) /* MODE_PRIVATE request packet fixed length without MAC. */ #define REQ_LEN_NOMAC (offsetof(struct req_pkt, keyid)) +/* MODE_PRIVATE req_pkt_tail minimum size (16 octet digest) */ +#define REQ_TAIL_MIN \ + (sizeof(struct req_pkt_tail) - (MAX_MAC_LEN - MAX_MD5_LEN)) /* * A MODE_PRIVATE response packet. The length here is variable, this diff --git a/include/ntpd.h b/include/ntpd.h index 86e0d8443..bdd574dd5 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -302,6 +302,8 @@ extern u_long numasyncmsgs; /* number of async messages we've sent */ /* ntp_intres.c */ extern keyid_t req_keyid; /* request keyid */ +extern int req_keytype; /* OpenSSL NID such as NID_md5 */ +extern size_t req_hashlen; /* digest size for req_keytype */ extern char * req_file; /* name of the file with configuration info */ #ifdef SYS_WINNT extern HANDLE ResolverEventHandle; diff --git a/libntp/authreadkeys.c b/libntp/authreadkeys.c index a64d4ef7e..91383d715 100644 --- a/libntp/authreadkeys.c +++ b/libntp/authreadkeys.c @@ -178,23 +178,25 @@ authreadkeys( MD5auth_setkey(keyno, keytype, (u_char *)token, len); } else { char hex[] = "0123456789abcdef"; - int temp; + u_char temp; char *ptr; + int jlim; - for (j = 0; j < len; j++) { + jlim = min(len, 2 * sizeof(keystr)); + for (j = 0; j < jlim; j++) { ptr = strchr(hex, tolower(token[j])); if (ptr == NULL) { msyslog(LOG_ERR, "authreadkeys: invalid hex digit for key %d", keyno); continue; } - temp = ptr - hex; + temp = (u_char)(ptr - hex); if (j & 1) keystr[j / 2] |= temp; else keystr[j / 2] = temp << 4; } - MD5auth_setkey(keyno, keytype, keystr, len / 2); + MD5auth_setkey(keyno, keytype, keystr, jlim / 2); } } fclose(fp); diff --git a/libntp/hextoint.c b/libntp/hextoint.c index 0d774eb4e..a2e8c043f 100644 --- a/libntp/hextoint.c +++ b/libntp/hextoint.c @@ -9,7 +9,7 @@ int hextoint( const char *str, - u_long *ival + u_long *pu ) { register u_long u; @@ -18,22 +18,24 @@ hextoint( cp = str; if (*cp == '\0') - return 0; + return 0; u = 0; while (*cp != '\0') { - if (!isxdigit((int)*cp)) - return 0; - if (u >= 0x10000000) - return 0; /* overflow */ + if (!isxdigit(*cp)) + return 0; + if (u & 0xF0000000) + return 0; /* overflow */ u <<= 4; - if (*cp <= '9') /* very ascii dependent */ - u += *cp++ - '0'; - else if (*cp >= 'a') - u += *cp++ - 'a' + 10; + if ('0' <= *cp && *cp <= '9') + u += *cp++ - '0'; + else if ('a' <= *cp && *cp <= 'f') + u += *cp++ - 'a' + 10; + else if ('A' <= *cp && *cp <= 'F') + u += *cp++ - 'A' + 10; else - u += *cp++ - 'A' + 10; + return 0; } - *ival = u; + *pu = u; return 1; } diff --git a/libntp/ssl_init.c b/libntp/ssl_init.c index 59ef8ff1a..c7bf7e63f 100644 --- a/libntp/ssl_init.c +++ b/libntp/ssl_init.c @@ -7,6 +7,7 @@ #ifdef HAVE_CONFIG_H #include #endif +#include #include #include #include @@ -56,14 +57,14 @@ ssl_check_version(void) */ int keytype_from_text( - const char *keytype_name, + const char *text, size_t *pdigest_len ) { int key_type; u_int digest_len; #ifdef OPENSSL - char digest[EVP_MAX_MD_SIZE]; + u_char digest[EVP_MAX_MD_SIZE]; char * upcased; char * pch; EVP_MD_CTX ctx; @@ -76,7 +77,7 @@ keytype_from_text( */ INIT_SSL(); LIB_GETBUF(upcased); - strncpy(upcased, keytype_name, LIB_BUFLENGTH); + strncpy(upcased, text, LIB_BUFLENGTH); for (pch = upcased; '\0' != *pch; pch++) *pch = (char)toupper(*pch); key_type = OBJ_sn2nid(upcased); @@ -84,7 +85,7 @@ keytype_from_text( key_type = 0; #endif - if (!key_type && 'm' == tolower(keytype_name[0])) + if (!key_type && 'm' == tolower(text[0])) key_type = NID_md5; if (!key_type) @@ -94,6 +95,17 @@ keytype_from_text( #ifdef OPENSSL EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type)); EVP_DigestFinal(&ctx, digest, &digest_len); + if (digest_len + sizeof(keyid_t) > MAX_MAC_LEN) { + fprintf(stderr, + "key type %s %u octet digests are too big, max %u\n", + keytype_name(key_type), digest_len, + MAX_MAC_LEN - sizeof(keyid_t)); + msyslog(LOG_ERR, + "key type %s %u octet digests are too big, max %u", + keytype_name(key_type), digest_len, + MAX_MAC_LEN - sizeof(keyid_t)); + return 0; + } #else digest_len = 16; #endif @@ -123,7 +135,7 @@ keytype_name( if (NULL == name) name = unknown_type; #else /* !OPENSSL follows */ - if (nid_MD5 == nid) + if (NID_md5 == nid) name = "MD5"; else name = unknown_type; diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index 88655b799..bcbf6c500 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -1707,11 +1707,15 @@ config_auth( struct config_tree *ptree ) { + extern int cache_type; /* authkeys.c */ #ifdef OPENSSL + u_char digest[EVP_MAX_MD_SIZE]; + u_int digest_len; + EVP_MD_CTX ctx; struct attr_val *my_val; - int item; + int item; #endif - int *key_val; + int * key_val; /* Crypto Command */ #ifdef OPENSSL @@ -1811,12 +1815,23 @@ config_auth( req_keyid = info_auth_keyid; /* if doesn't exist, make up one at random */ - if (!authhavekey(req_keyid)) { + if (authhavekey(req_keyid)) { + req_keytype = cache_type; +#ifndef OPENSSL + req_hashlen = 16; +#else /* OPENSSL follows */ + EVP_DigestInit(&ctx, EVP_get_digestbynid(req_keytype)); + EVP_DigestFinal(&ctx, digest, &digest_len); + req_hashlen = digest_len; +#endif + } else { int rankey; rankey = ntp_random(); - MD5auth_setkey(req_keyid, NID_md5, (u_char *)&rankey, - sizeof(rankey)); + req_keytype = NID_md5; + req_hashlen = 16; + MD5auth_setkey(req_keyid, req_keytype, + (u_char *)&rankey, sizeof(rankey)); authtrust(req_keyid, 1); } @@ -3362,7 +3377,7 @@ config_peers( status = get_multiple_netnums(curr_peer->addr->address, &peeraddr, &res, 0, t_UNK); -#if 0 /* Hack for debugging Deferred DNS */ +#ifdef FORCE_DEFER_DNS /* Hack for debugging Deferred DNS */ if (status == 1) { /* Deferring everything breaks refclocks. */ memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); diff --git a/ntpd/ntp_intres.c b/ntpd/ntp_intres.c index 44659a616..85f93e3c7 100644 --- a/ntpd/ntp_intres.c +++ b/ntpd/ntp_intres.c @@ -137,6 +137,8 @@ static SOCKET sockfd = INVALID_SOCKET; /* NT uses SOCKET */ /* stuff to be filled in by caller */ keyid_t req_keyid; /* request keyid */ +int req_keytype; /* OpenSSL NID such as NID_md5 */ +size_t req_hashlen; /* digest size for req_keytype */ char *req_file; /* name of the file with configuration info */ /* end stuff to be filled in */ @@ -496,7 +498,6 @@ findhostaddr( } if (entry->ce_name) { - if (0) msyslog(LOG_INFO, "findhostaddr: Trying %s", entry->ce_name); DPRINTF(2, ("findhostaddr: Resolving <%s>\n", entry->ce_name)); @@ -696,15 +697,21 @@ request( struct conf_peer *conf ) { - fd_set fdset; struct sock_timeval tvout; struct req_pkt reqpkt; - l_fp ts; + size_t req_len; + size_t total_len; /* req_len plus keyid & digest */ + fd_set fdset; + l_fp ts; + char * pch; + char * pchEnd; + l_fp * pts; + keyid_t *pkeyid; int n; #ifdef SYS_WINNT - HANDLE hReadWriteEvent = NULL; - BOOL ret; - DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait; + HANDLE hReadWriteEvent = NULL; + BOOL ret; + DWORD NumberOfBytesWritten, NumberOfBytesRead, dwWait; OVERLAPPED overlap; #endif /* SYS_WINNT */ @@ -735,34 +742,66 @@ request( /* * Make up a request packet with the configuration info */ - memset((char *)&reqpkt, 0, sizeof(reqpkt)); + memset(&reqpkt, 0, sizeof(reqpkt)); reqpkt.rm_vn_mode = RM_VN_MODE(0, 0, 0); reqpkt.auth_seq = AUTH_SEQ(1, 0); /* authenticated, no seq */ reqpkt.implementation = IMPL_XNTPD; /* local implementation */ reqpkt.request = REQ_CONFIG; /* configure a new peer */ reqpkt.err_nitems = ERR_NITEMS(0, 1); /* one item */ - reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(struct conf_peer)); + reqpkt.mbz_itemsize = MBZ_ITEMSIZE(sizeof(*conf)); /* Make sure mbz_itemsize <= sizeof reqpkt.data */ - if (sizeof(struct conf_peer) > sizeof (reqpkt.data)) { - msyslog(LOG_ERR, "Bletch: conf_peer is too big for reqpkt.data!"); + if (sizeof(*conf) > sizeof(reqpkt.data)) { + msyslog(LOG_ERR, + "Bletch: conf_peer is too big for reqpkt.data!"); resolver_exit(1); } - memmove(reqpkt.data, (char *)conf, sizeof(struct conf_peer)); - reqpkt.keyid = htonl(req_keyid); + memcpy(reqpkt.data, conf, sizeof(*conf)); + + if (sys_authenticate && req_hashlen > 16) { + pch = reqpkt.data; + /* 32-bit alignment */ + pch += (sizeof(*conf) + 3) & ~3; + pts = (void *)pch; + pkeyid = (void *)(pts + 1); + pchEnd = (void *)pkeyid; + req_len = pchEnd - (char *)&reqpkt; + pchEnd = (void *)(pkeyid + 1); + pchEnd += req_hashlen; + total_len = pchEnd - (char *)&reqpkt; + if (total_len > sizeof(reqpkt)) { + msyslog(LOG_ERR, + "intres total_len %u limit is %u (%u octet digest)\n", + total_len, sizeof(reqpkt), + req_hashlen); + resolver_exit(1); + } + } else { + pts = &reqpkt.tstamp; + pkeyid = &reqpkt.keyid; + req_len = REQ_LEN_NOMAC; + } + *pkeyid = htonl(req_keyid); get_systime(&ts); L_ADDUF(&ts, SKEWTIME); - HTONL_FP(&ts, &reqpkt.tstamp); - n = 0; - if (sys_authenticate) - n = authencrypt(req_keyid, (u_int32 *)&reqpkt, REQ_LEN_NOMAC); + HTONL_FP(&ts, pts); + if (sys_authenticate) { + n = authencrypt(req_keyid, (void *)&reqpkt, req_len); + if ((size_t)n != req_hashlen + sizeof(reqpkt.keyid)) { + msyslog(LOG_ERR, + "intres maclen %d expected %u\n", + n, req_hashlen + sizeof(reqpkt.keyid)); + resolver_exit(1); + } + req_len += n; + } /* * Done. Send it. */ #ifndef SYS_WINNT - n = send(sockfd, (char *)&reqpkt, (unsigned)(REQ_LEN_NOMAC + n), 0); + n = send(sockfd, (char *)&reqpkt, req_len, 0); if (n < 0) { msyslog(LOG_ERR, "send to NTP server failed: %m"); return 0; /* maybe should exit */ @@ -780,7 +819,7 @@ request( */ overlap.Offset = overlap.OffsetHigh = (DWORD)0; overlap.hEvent = hReadWriteEvent; - ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, REQ_LEN_NOMAC + n, + ret = WriteFile((HANDLE)sockfd, (char *)&reqpkt, req_len, NULL, (LPOVERLAPPED)&overlap); if ((ret == FALSE) && (GetLastError() != ERROR_IO_PENDING)) { msyslog(LOG_ERR, "send to NTP server failed: %m"); @@ -818,17 +857,14 @@ request( n = select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout); - if (n < 0) - { + if (n < 0) { if (errno != EINTR) - msyslog(LOG_ERR, "select() fails: %m"); + msyslog(LOG_ERR, "select() fails: %m"); return 0; - } - else if (n == 0) - { + } else if (n == 0) { #ifdef DEBUG if (debug) - msyslog(LOG_INFO, "select() returned 0."); + msyslog(LOG_INFO, "ntp_intres select() returned 0."); #endif return 0; } @@ -1151,7 +1187,8 @@ doconfigure( #endif #if defined(HAVE_RES_INIT) || defined(HAVE___RES_INIT) - if (dores) res_init(); /* Reload /etc/resolv.conf - bug 1226 */ + if (dores) /* Reload /etc/resolv.conf - bug 1226 */ + res_init(); #endif ce = confentries; while (ce != NULL) { @@ -1182,7 +1219,10 @@ doconfigure( removeentry(ceremove); continue; } - // Failed case. Should bump counter and give up. + /* + * Failed case. Should bump counter and give + * up. + */ #ifdef DEBUG if (debug > 1) { msyslog(LOG_INFO, diff --git a/ntpd/ntp_request.c b/ntpd/ntp_request.c index 0fe81c3d5..454e3bfe6 100644 --- a/ntpd/ntp_request.c +++ b/ntpd/ntp_request.c @@ -538,7 +538,7 @@ process_private( if (recv_len < (REQ_LEN_HDR + (INFO_ITEMSIZE(inpkt->mbz_itemsize) * INFO_NITEMS(inpkt->err_nitems)) + - sizeof(*tailinpkt))) { + REQ_TAIL_MIN)) { req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } @@ -575,13 +575,13 @@ process_private( */ if (!INFO_IS_AUTH(inpkt->auth_seq) || !info_auth_keyid || ntohl(tailinpkt->keyid) != info_auth_keyid) { - DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %lu maclen %u\n", + DPRINTF(5, ("failed auth %d info_auth_keyid %u pkt keyid %u maclen %u\n", INFO_IS_AUTH(inpkt->auth_seq), info_auth_keyid, ntohl(tailinpkt->keyid), mac_len)); #ifdef DEBUG msyslog(LOG_DEBUG, - "process_private: failed auth %d info_auth_keyid %u pkt keyid %lu maclen %u\n", + "process_private: failed auth %d info_auth_keyid %u pkt keyid %u maclen %u\n", INFO_IS_AUTH(inpkt->auth_seq), info_auth_keyid, ntohl(tailinpkt->keyid), mac_len); diff --git a/ntpdc/layout.std b/ntpdc/layout.std index ad5ed3f51..8d538d15f 100644 --- a/ntpdc/layout.std +++ b/ntpdc/layout.std @@ -1,4 +1,4 @@ -sizeof(struct req_pkt) = 212 +sizeof(struct req_pkt) = 216 offsetof(rm_vn_mode) = 0 offsetof(auth_seq) = 1 offsetof(implementation) = 2 @@ -10,7 +10,7 @@ offsetof(tstamp) = 184 offsetof(keyid) = 192 offsetof(mac) = 196 -sizeof(struct req_pkt_tail) = 28 +sizeof(struct req_pkt_tail) = 32 offsetof(tstamp) = 0 offsetof(keyid) = 8 offsetof(mac) = 12 diff --git a/ntpdc/ntpdc.c b/ntpdc/ntpdc.c index b84579d46..1c722d186 100644 --- a/ntpdc/ntpdc.c +++ b/ntpdc/ntpdc.c @@ -1807,7 +1807,7 @@ keytype( { const char * digest_name; size_t digest_len; - int keytype; + int key_type; if (!pcmd->nargs) { fprintf(fp, "keytype is %s with %u octet digests\n", @@ -1818,9 +1818,9 @@ keytype( digest_name = pcmd->argval[0].string; digest_len = 0; - keytype = keytype_from_text(digest_name, &digest_len); + key_type = keytype_from_text(digest_name, &digest_len); - if (!keytype) { + if (!key_type) { fprintf(fp, "keytype must be 'md5'%s\n", #ifdef OPENSSL " or a digest type provided by OpenSSL"); @@ -1830,7 +1830,7 @@ keytype( return; } - info_auth_keytype = keytype; + info_auth_keytype = key_type; info_auth_hashlen = digest_len; }