From: Dave Hart Date: Wed, 11 Nov 2009 12:36:24 +0000 (+0000) Subject: [Bug 1003] ntpdc unconfig command doesn't prompt for keyid. X-Git-Tag: NTP_4_2_5P244_RC~4^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ae9c6c80416d33cae2cd1da58d26716269d92fbe;p=thirdparty%2Fntp.git [Bug 1003] ntpdc unconfig command doesn't prompt for keyid. [Bug 1376] Enable authenticated ntpq and ntpdc using newly-available digest types. ntp-keygen, Autokey OpenSSL build vs. run version mismatch is now a non-fatal warning. bk: 4afaafc8TYNwbwA9mbO7Rxxd9jNAgg --- diff --git a/ChangeLog b/ChangeLog index cc7814630..16c88538a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +* [Bug 1003] ntpdc unconfig command doesn't prompt for keyid. +* [Bug 1376] Enable authenticated ntpq and ntpdc using newly-available + digest types. +* ntp-keygen, Autokey OpenSSL build vs. run version mismatch is now a + non-fatal warning. (4.2.5p242-RC) 2009/11/10 Released by Harlan Stenn * [Bug 1363] CID 92 clarify fallthrough case in clk_trimtsip.c * [Bug 1366] ioctl(TIOCSCTTY, 0) fails on NetBSD *[0-2].* > 3.99.7. diff --git a/include/ntp_request.h b/include/ntp_request.h index 643904071..1d4e90ba4 100644 --- a/include/ntp_request.h +++ b/include/ntp_request.h @@ -5,6 +5,7 @@ #ifndef NTP_REQUEST_H #define NTP_REQUEST_H +#include "stddef.h" #include "ntp_types.h" #include "recvbuff.h" @@ -135,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(u_int32)]; /* (optional) auth code */ + char mac[MAX_MD5_LEN-sizeof(keyid_t)]; /* (optional) auth code */ }; /* @@ -145,22 +146,20 @@ 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(u_int32)]; /* (optional) auth code */ + char mac[MAX_MD5_LEN-sizeof(keyid_t)]; /* (optional) auth code */ }; -/* - * Input packet lengths. One with the mac, one without. - */ -#define REQ_LEN_HDR 8 /* 4 * u_char + 2 * u_short */ -#define REQ_LEN_MAC (sizeof(struct req_pkt)) -#define REQ_LEN_NOMAC (sizeof(struct req_pkt) - MAX_MD5_LEN) +/* 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)) /* - * A response packet. The length here is variable, this is a - * maximally sized one. Note that this implementation doesn't + * A MODE_PRIVATE response packet. The length here is variable, this + * is a maximally sized one. Note that this implementation doesn't * authenticate responses. */ -#define RESP_HEADER_SIZE (8) +#define RESP_HEADER_SIZE (offsetof(struct resp_pkt, data)) #define RESP_DATA_SIZE (500) struct resp_pkt { diff --git a/include/ntp_stdlib.h b/include/ntp_stdlib.h index 3685f686c..f2024fb16 100644 --- a/include/ntp_stdlib.h +++ b/include/ntp_stdlib.h @@ -37,11 +37,13 @@ extern void msyslog (int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); /* - * When building without OpenSSL, use one constant #define, NID_md5, - * for the keytype. MD5 is the only digest supported without OpenSSL. + * When building without OpenSSL, use a few macros of theirs to + * minimize source differences in NTP. */ #ifndef OPENSSL #define NID_md5 4 /* from openssl/objects.h */ +/* from openssl/evp.h */ +#define EVP_MAX_MD_SIZE 64 /* longest known is SHA512 */ #endif extern void auth_delkeys (void); @@ -169,6 +171,9 @@ extern int ssl_init_done; #else /* !OPENSSL follows */ #define INIT_SSL() do {} while (0) #endif +extern int keytype_from_text (const char *, size_t *); +extern const char *keytype_name (int); + /* lib/isc/win32/strerror.c * diff --git a/libntp/a_md5encrypt.c b/libntp/a_md5encrypt.c index 0b1264e12..bd30ba2c6 100644 --- a/libntp/a_md5encrypt.c +++ b/libntp/a_md5encrypt.c @@ -28,7 +28,7 @@ MD5authencrypt( int length /* packet length */ ) { - u_char digest[32]; + u_char digest[EVP_MAX_MD_SIZE]; u_int len; #ifdef OPENSSL EVP_MD_CTX ctx; @@ -73,7 +73,7 @@ MD5authdecrypt( int size /* MAC size */ ) { - u_char digest[32]; + u_char digest[EVP_MAX_MD_SIZE]; u_int len; #ifdef OPENSSL EVP_MD_CTX ctx; diff --git a/libntp/authreadkeys.c b/libntp/authreadkeys.c index 38f25b2b6..e757bd859 100644 --- a/libntp/authreadkeys.c +++ b/libntp/authreadkeys.c @@ -127,18 +127,13 @@ authreadkeys( continue; } #ifdef OPENSSL - /* - * If the key type is 'M' or 'm', it is replaced by 'MD5". - * In any case, it must be one of the algorithms supported - * by OpenSSL. The key type is the NID used by the message - * digest algorithm. Ther are a number of inconsistencies in - * the OpenSSL database. We attempt to discover them here - * and prevent use of inconsistent data. + * 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. */ - if (strcmp(token, "M") == 0 || strcmp(token, "m") == 0) - token = "MD5"; - keytype = OBJ_sn2nid(token); + keytype = keytype_from_text(token, NULL); if (keytype == 0 || keytype > 255) { msyslog(LOG_ERR, "authreadkeys: invalid type for key %d", keyno); diff --git a/libntp/ssl_init.c b/libntp/ssl_init.c index 73c94a61a..59ef8ff1a 100644 --- a/libntp/ssl_init.c +++ b/libntp/ssl_init.c @@ -9,10 +9,9 @@ #endif #include #include +#include -#ifndef OPENSSL -int ssl_init__non_empty_compliation_unit; -#else /* OPENSSL follows */ +#ifdef OPENSSL #include "openssl/err.h" #include "openssl/rand.h" @@ -36,15 +35,99 @@ void ssl_check_version(void) { if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) { - msyslog(LOG_ERR, + msyslog(LOG_WARNING, "OpenSSL version mismatch. Built against %lx, you have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); fprintf(stderr, "OpenSSL version mismatch. Built against %lx, you have %lx\n", OPENSSL_VERSION_NUMBER, SSLeay()); - exit (-1); } INIT_SSL(); } #endif /* OPENSSL */ + + +/* + * keytype_from_text returns OpenSSL NID for digest by name, and + * optionally the associated digest length. + * + * Used by ntpd authreadkeys(), ntpq and ntpdc keytype() + */ +int +keytype_from_text( + const char *keytype_name, + size_t *pdigest_len + ) +{ + int key_type; + u_int digest_len; +#ifdef OPENSSL + char digest[EVP_MAX_MD_SIZE]; + char * upcased; + char * pch; + EVP_MD_CTX ctx; + + /* + * OpenSSL digest short names are capitalized, so uppercase the + * digest name before passing to OBJ_sn2nid(). If it is not + * recognized but begins with 'M' use NID_md5 to be consistent + * with past behavior. + */ + INIT_SSL(); + LIB_GETBUF(upcased); + strncpy(upcased, keytype_name, LIB_BUFLENGTH); + for (pch = upcased; '\0' != *pch; pch++) + *pch = (char)toupper(*pch); + key_type = OBJ_sn2nid(upcased); +#else + key_type = 0; +#endif + + if (!key_type && 'm' == tolower(keytype_name[0])) + key_type = NID_md5; + + if (!key_type) + return 0; + + if (NULL != pdigest_len) { +#ifdef OPENSSL + EVP_DigestInit(&ctx, EVP_get_digestbynid(key_type)); + EVP_DigestFinal(&ctx, digest, &digest_len); +#else + digest_len = 16; +#endif + *pdigest_len = digest_len; + } + + return key_type; +} + + +/* + * keytype_name returns OpenSSL short name for digest by NID. + * + * Used by ntpq and ntpdc keytype() + */ +const char * +keytype_name( + int nid + ) +{ + static const char unknown_type[] = "(unknown key type)"; + const char *name; + +#ifdef OPENSSL + INIT_SSL(); + name = OBJ_nid2sn(nid); + if (NULL == name) + name = unknown_type; +#else /* !OPENSSL follows */ + if (nid_MD5 == nid) + name = "MD5"; + else + name = unknown_type; +#endif + return name; +} + diff --git a/ntpd/keyword-gen.c b/ntpd/keyword-gen.c index 76fb990a0..6486d34eb 100644 --- a/ntpd/keyword-gen.c +++ b/ntpd/keyword-gen.c @@ -450,10 +450,10 @@ create_scan_states( exit(2); } } else { - my_state = sst_highwater++; - while (my_state < COUNTOF(sst) - && sst[my_state].finishes_token) + do my_state = sst_highwater++; + while (my_state < COUNTOF(sst) + && sst[my_state].finishes_token); if (my_state >= COUNTOF(sst)) { fprintf(stderr, "fatal, keyword scanner state array " @@ -493,9 +493,9 @@ create_scan_states( sst[token] = sst[my_state]; memset(&sst[my_state], 0, sizeof(sst[my_state])); - sst_highwater--; - while (sst[sst_highwater].finishes_token) + do sst_highwater--; + while (sst[sst_highwater].finishes_token); my_state = token; if (prev_char_s) sst[prev_char_s].other_next_s = my_state; diff --git a/ntpd/ntp_intres.c b/ntpd/ntp_intres.c index be8d24e21..3323b00b7 100644 --- a/ntpd/ntp_intres.c +++ b/ntpd/ntp_intres.c @@ -723,7 +723,7 @@ request( FD_SET(sockfd, &fdset); while (select(sockfd + 1, &fdset, (fd_set *)0, (fd_set *)0, &tvout) > 0) { - recv(sockfd, (char *)&reqpkt, REQ_LEN_MAC, 0); + recv(sockfd, (char *)&reqpkt, sizeof(reqpkt), 0); FD_ZERO(&fdset); FD_SET(sockfd, &fdset); } diff --git a/ntpd/ntp_request.c b/ntpd/ntp_request.c index e9b0952cb..0fe81c3d5 100644 --- a/ntpd/ntp_request.c +++ b/ntpd/ntp_request.c @@ -62,7 +62,8 @@ static struct req_proc univ_codes[] = { }; static void req_ack (sockaddr_u *, struct interface *, struct req_pkt *, int); -static char * prepare_pkt (sockaddr_u *, struct interface *, struct req_pkt *, u_int); +static char * prepare_pkt (sockaddr_u *, struct interface *, + struct req_pkt *, size_t); static char * more_pkt (void); static void flush_pkt (void); static void peer_list (sockaddr_u *, struct interface *, struct req_pkt *); @@ -278,13 +279,10 @@ prepare_pkt( sockaddr_u *srcadr, struct interface *inter, struct req_pkt *pkt, - u_int structsize + size_t structsize ) { -#ifdef DEBUG - if (debug > 3) - printf("request: preparing pkt\n"); -#endif + DPRINTF(4, ("request: preparing pkt\n")); /* * Fill in the implementation, request and itemsize fields @@ -322,21 +320,18 @@ more_pkt(void) * If we were using the extra buffer, send the packet. */ if (usingexbuf) { -#ifdef DEBUG - if (debug > 2) - printf("request: sending pkt\n"); -#endif + DPRINTF(3, ("request: sending pkt\n")); rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, MORE_BIT, reqver); rpkt.auth_seq = AUTH_SEQ(0, seqno); rpkt.err_nitems = htons((u_short)nitems); sendpkt(toaddr, frominter, -1, (struct pkt *)&rpkt, - RESP_HEADER_SIZE+databytes); + RESP_HEADER_SIZE + databytes); numresppkts++; /* * Copy data out of exbuf into the packet. */ - memmove(&rpkt.data[0], exbuf, (unsigned)itemsize); + memcpy(&rpkt.data[0], exbuf, (unsigned)itemsize); seqno++; databytes = 0; nitems = 0; @@ -346,10 +341,7 @@ more_pkt(void) databytes += itemsize; nitems++; if (databytes + itemsize <= RESP_DATA_SIZE) { -#ifdef DEBUG - if (debug > 3) - printf("request: giving him more data\n"); -#endif + DPRINTF(4, ("request: giving him more data\n")); /* * More room in packet. Give him the * next address. @@ -360,12 +352,9 @@ more_pkt(void) * No room in packet. Give him the extra * buffer unless this was the last in the sequence. */ -#ifdef DEBUG - if (debug > 3) - printf("request: into extra buffer\n"); -#endif + DPRINTF(4, ("request: into extra buffer\n")); if (seqno == MAXSEQ) - return (char *)0; + return NULL; else { usingexbuf = 1; return exbuf; @@ -380,17 +369,14 @@ more_pkt(void) static void flush_pkt(void) { -#ifdef DEBUG - if (debug > 2) - printf("request: flushing packet, %d items\n", nitems); -#endif + DPRINTF(3, ("request: flushing packet, %d items\n", nitems)); /* * Must send the last packet. If nothing in here and nothing * has been sent, send an error saying no data to be found. */ if (seqno == 0 && nitems == 0) - req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, - INFO_ERR_NODATA); + req_ack(toaddr, frominter, (struct req_pkt *)&rpkt, + INFO_ERR_NODATA); else { rpkt.rm_vn_mode = RM_VN_MODE(RESP_BIT, 0, reqver); rpkt.auth_seq = AUTH_SEQ(0, seqno); @@ -412,6 +398,8 @@ get_packet_mode(struct recvbuf *rbufp) struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt; return (INFO_MODE(inpkt->rm_vn_mode)); } + + /* * process_private - process private mode (7) packets */ @@ -428,19 +416,22 @@ process_private( struct req_proc *proc; int ec; short temp_size; + l_fp ftmp; + double dtemp; + size_t recv_len; + size_t noslop_len; + size_t mac_len; /* * Initialize pointers, for convenience */ + recv_len = rbufp->recv_length; inpkt = (struct req_pkt *)&rbufp->recv_pkt; srcadr = &rbufp->recv_srcadr; inter = rbufp->dstadr; -#ifdef DEBUG - if (debug > 2) - printf("process_private: impl %d req %d\n", - inpkt->implementation, inpkt->request); -#endif + DPRINTF(3, ("process_private: impl %d req %d\n", + inpkt->implementation, inpkt->request)); /* * Do some sanity checks on the packet. Return a format @@ -467,10 +458,10 @@ process_private( * Get the appropriate procedure list to search. */ if (inpkt->implementation == IMPL_UNIV) - proc = univ_codes; + proc = univ_codes; else if ((inpkt->implementation == IMPL_XNTPD) || (inpkt->implementation == IMPL_XNTPD_OLD)) - proc = ntp_codes; + proc = ntp_codes; else { req_ack(srcadr, inter, inpkt, INFO_ERR_IMPL); return; @@ -482,7 +473,7 @@ process_private( */ while (proc->request_code != NO_REQUEST) { if (proc->request_code == (short) inpkt->request) - break; + break; proc++; } if (proc->request_code == NO_REQUEST) { @@ -490,10 +481,7 @@ process_private( return; } -#ifdef DEBUG - if (debug > 3) - printf("found request in tables\n"); -#endif + DPRINTF(4, ("found request in tables\n")); /* * If we need data, check to see if we have some. If we @@ -512,21 +500,15 @@ process_private( !(inpkt->implementation == IMPL_XNTPD && inpkt->request == REQ_CONFIG && temp_size == sizeof(struct old_conf_peer))) { -#ifdef DEBUG - if (debug > 2) - printf("process_private: wrong item size, received %d, should be %d or %d\n", - temp_size, proc->sizeofitem, proc->v6_sizeofitem); -#endif + DPRINTF(3, ("process_private: wrong item size, received %d, should be %d or %d\n", + temp_size, proc->sizeofitem, proc->v6_sizeofitem)); req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } if ((proc->sizeofitem != 0) && - ((temp_size * INFO_NITEMS(inpkt->err_nitems)) > - (rbufp->recv_length - REQ_LEN_HDR))) { -#ifdef DEBUG - if (debug > 2) - printf("process_private: not enough data\n"); -#endif + ((size_t)(temp_size * INFO_NITEMS(inpkt->err_nitems)) > + (recv_len - REQ_LEN_HDR))) { + DPRINTF(3, ("process_private: not enough data\n")); req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } @@ -552,55 +534,73 @@ process_private( * time stamp. */ if (proc->needs_auth && sys_authenticate) { - l_fp ftmp; - double dtemp; - if (rbufp->recv_length < (REQ_LEN_HDR + + if (recv_len < (REQ_LEN_HDR + (INFO_ITEMSIZE(inpkt->mbz_itemsize) * INFO_NITEMS(inpkt->err_nitems)) + sizeof(*tailinpkt))) { req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; - } - tailinpkt = (void *)((char *)&rbufp->recv_pkt + - rbufp->recv_length - sizeof(*tailinpkt)); + } + + /* + * For 16-octet digests, regardless of itemsize and + * nitems, authenticated requests are a fixed size + * with the timestamp, key ID, and digest located + * at the end of the packet. Because the key ID + * determining the digest size precedes the digest, + * for larger digests the fixed size request scheme + * is abandoned and the timestamp, key ID, and digest + * are located relative to the start of the packet, + * with the digest size determined by the packet size. + */ + noslop_len = REQ_LEN_HDR + + INFO_ITEMSIZE(inpkt->mbz_itemsize) * + INFO_NITEMS(inpkt->err_nitems) + + sizeof(inpkt->tstamp); + /* 32-bit alignment */ + noslop_len = (noslop_len + 3) & ~3; + if (recv_len > (noslop_len + MAX_MAC_LEN)) + mac_len = 20; + else + mac_len = recv_len - noslop_len; + + tailinpkt = (void *)((char *)inpkt + recv_len - + (mac_len + sizeof(inpkt->tstamp))); /* - * If this guy is restricted from doing this, don't let him - * If wrong key was used, or packet doesn't have mac, return. + * If this guy is restricted from doing this, don't let + * him. If the wrong key was used, or packet doesn't + * have mac, return. */ - if (!INFO_IS_AUTH(inpkt->auth_seq) || info_auth_keyid == 0 + 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", + INFO_IS_AUTH(inpkt->auth_seq), + info_auth_keyid, + ntohl(tailinpkt->keyid), mac_len)); #ifdef DEBUG - if (debug > 4) - printf("failed auth %d info_auth_keyid %lu pkt keyid %lu\n", - INFO_IS_AUTH(inpkt->auth_seq), - (u_long)info_auth_keyid, - (u_long)ntohl(tailinpkt->keyid)); msyslog(LOG_DEBUG, - "process_private: failed auth %d info_auth_keyid %lu pkt keyid %lu\n", + "process_private: failed auth %d info_auth_keyid %u pkt keyid %lu maclen %u\n", INFO_IS_AUTH(inpkt->auth_seq), - (u_long)info_auth_keyid, - (u_long)ntohl(tailinpkt->keyid)); + info_auth_keyid, + ntohl(tailinpkt->keyid), mac_len); #endif req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); return; } - if (rbufp->recv_length > REQ_LEN_MAC) { -#ifdef DEBUG - if (debug > 4) - printf("bad pkt length %d\n", - rbufp->recv_length); -#endif - msyslog(LOG_ERR, "process_private: bad pkt length %d", - rbufp->recv_length); + if (recv_len > REQ_LEN_NOMAC + MAX_MAC_LEN) { + DPRINTF(5, ("bad pkt length %d\n", recv_len)); + msyslog(LOG_ERR, + "process_private: bad pkt length %d", + recv_len); req_ack(srcadr, inter, inpkt, INFO_ERR_FMT); return; } if (!mod_okay || !authhavekey(info_auth_keyid)) { + DPRINTF(5, ("failed auth mod_okay %d\n", + mod_okay)); #ifdef DEBUG - if (debug > 4) - printf("failed auth mod_okay %d\n", mod_okay); msyslog(LOG_DEBUG, "process_private: failed auth mod_okay %d\n", mod_okay); @@ -630,22 +630,14 @@ process_private( * So far so good. See if decryption works out okay. */ if (!authdecrypt(info_auth_keyid, (u_int32 *)inpkt, - rbufp->recv_length - sizeof(struct req_pkt_tail) + - REQ_LEN_HDR, sizeof(struct req_pkt_tail) - REQ_LEN_HDR)) { -#ifdef DEBUG - if (debug > 4) - printf("authdecrypt failed\n"); -#endif + recv_len - mac_len, mac_len)) { + DPRINTF(5, ("authdecrypt failed\n")); req_ack(srcadr, inter, inpkt, INFO_ERR_AUTH); return; } } -#ifdef DEBUG - if (debug > 3) - printf("process_private: all okay, into handler\n"); -#endif - + DPRINTF(3, ("process_private: all okay, into handler\n")); /* * Packet is okay. Call the handler to send him data. */ diff --git a/ntpdc/ntpdc.c b/ntpdc/ntpdc.c index d789aa9bc..b84579d46 100644 --- a/ntpdc/ntpdc.c +++ b/ntpdc/ntpdc.c @@ -3,7 +3,7 @@ */ #include - +#include #include #include #include @@ -50,7 +50,8 @@ static const char * prompt = "ntpdc> "; /* prompt to ask him about */ static u_long info_auth_keyid; static int keyid_entered = 0; -static int info_auth_keytype = NID_md5; /* MD5 */ +static int info_auth_keytype = NID_md5; /* MD5 */ +static size_t info_auth_hashlen = 16; /* MD5 */ u_long current_time; /* needed by authkeys; not used */ /* @@ -71,10 +72,10 @@ int ntpdcmain (int, char **); * Built in command handler declarations */ static int openhost (const char *); -static int sendpkt (char *, int); +static int sendpkt (void *, size_t); static void growpktdata (void); static int getresponse (int, int, int *, int *, char **, int); -static int sendrequest (int, int, int, int, int, char *); +static int sendrequest (int, int, int, u_int, size_t, char *); static void getcmds (void); static RETSIGTYPE abortcmd (int); static void docmd (const char *); @@ -619,11 +620,11 @@ openhost( */ static int sendpkt( - char *xdata, - int xdatalen + void * xdata, + size_t xdatalen ) { - if (send(sockfd, xdata, (size_t)xdatalen, 0) == -1) { + if (send(sockfd, xdata, xdatalen, 0) == -1) { warning("write to %s failed", currenthost, ""); return -1; } @@ -639,11 +640,7 @@ static void growpktdata(void) { pktdatasize += INCDATASIZE; - pktdata = (char *)realloc(pktdata, (unsigned)pktdatasize); - if (pktdata == 0) { - (void) fprintf(stderr, "%s: realloc() failed!\n", progname); - exit(1); - } + pktdata = erealloc(pktdata, (size_t)pktdatasize); } @@ -695,9 +692,9 @@ getresponse( again: if (firstpkt) - tvo = tvout; + tvo = tvout; else - tvo = tvsout; + tvo = tvsout; FD_SET(sockfd, &fds); n = select(sockfd+1, &fds, (fd_set *)0, (fd_set *)0, &tvo); @@ -808,7 +805,8 @@ getresponse( pad = esize - size; else pad = 0; - if ((datasize = items*size) > (n-RESP_HEADER_SIZE)) { + datasize = items * size; + if ((size_t)datasize > (n-RESP_HEADER_SIZE)) { if (debug) printf( "Received items %d, size %d (total %d), data in packet is %d\n", @@ -854,7 +852,7 @@ getresponse( if ((datap + datasize + (pad * items)) > (pktdata + pktdatasize)) { int offset = datap - pktdata; growpktdata(); - *rdata = pktdata; /* might have been realloced ! */ + *rdata = pktdata; /* might have been realloced ! */ datap = pktdata + offset; } /* @@ -862,9 +860,9 @@ getresponse( * items. This is so we can play nice with older implementations */ - tmp_data = (char *)rpkt.data; - for(i = 0; i keyid > 0) - info_auth_keyid = ((struct conf_peer *)qpkt.data)->keyid; - else { - key_id = getkeyid("Keyid: "); - if (key_id == 0) { - (void) fprintf(stderr, - "Invalid key identifier\n"); - return 1; - } - info_auth_keyid = key_id; - } - } - if (!authistrusted(info_auth_keyid)) { - pass = getpass("MD5 Password: "); - if (*pass == '\0') { - (void) fprintf(stderr, - "Invalid password\n"); - return (1); - } - authusekey(info_auth_keyid, info_auth_keytype, - (u_char *)pass); - authtrust(info_auth_keyid, 1); + if (info_auth_keyid == 0) { + key_id = getkeyid("Keyid: "); + if (!key_id) { + fprintf(stderr, "Invalid key identifier\n"); + return 1; } - qpkt.auth_seq = AUTH_SEQ(1, 0); - get_systime(&ts); - L_ADD(&ts, &delay_time); - ptstamp = (void *)((char *)&qpkt + req_pkt_size - - sizeof(qpkt.tstamp)); - HTONL_FP(&ts, ptstamp); - maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt, - req_pkt_size); - if (maclen == 0) { - (void) fprintf(stderr, "Key not found\n"); - return (1); + info_auth_keyid = key_id; + } + if (!authistrusted(info_auth_keyid)) { + snprintf(pass_prompt, sizeof(pass_prompt), + "%s Password: ", + keytype_name(info_auth_keytype)); + pass = getpass(pass_prompt); + if ('\0' == pass[0]) { + fprintf(stderr, "Invalid password\n"); + return 1; } - return sendpkt((char *)&qpkt, (int)(req_pkt_size + maclen)); + authusekey(info_auth_keyid, info_auth_keytype, + (u_char *)pass); + authtrust(info_auth_keyid, 1); } - /*NOTREACHED*/ + qpkt.auth_seq = AUTH_SEQ(1, 0); + if (info_auth_hashlen > 16) { + /* + * Only ntpd which expects REQ_LEN_NOMAC plus maclen + * octets in an authenticated request using a 16 octet + * digest (that is, a newer ntpd) will handle digests + * larger than 16 octets, so for longer digests, do + * not attempt to shorten the requests for downlevel + * ntpd compatibility. + */ + if (REQ_LEN_NOMAC != req_pkt_size) + return 1; + reqsize = REQ_LEN_HDR + datasize + sizeof(*ptstamp); + /* align to 32 bits */ + reqsize = (reqsize + 3) & ~3; + } else + reqsize = req_pkt_size; + ptstamp = (void *)((char *)&qpkt + reqsize); + ptstamp--; + get_systime(&ts); + L_ADD(&ts, &delay_time); + HTONL_FP(&ts, ptstamp); + maclen = authencrypt(info_auth_keyid, (void *)&qpkt, reqsize); + if (!maclen) { + fprintf(stderr, "Key not found\n"); + return 1; + } else if (maclen != (info_auth_hashlen + sizeof(keyid_t))) { + fprintf(stderr, + "%d octet MAC, %u expected with %u octet digest\n", + maclen, (info_auth_hashlen + sizeof(keyid_t)), + info_auth_hashlen); + return 1; + } + return sendpkt(&qpkt, reqsize + maclen); } @@ -1026,7 +1062,7 @@ again: */ res = sendrequest(implcode, reqcode, auth, qitems, qsize, qdata); if (res != 0) - return res; + return res; /* * Get the response. If we got a standard error, print a message @@ -1064,36 +1100,36 @@ again: /* log error message if not told to be quiet */ if ((res > 0) && (((1 << res) & quiet_mask) == 0)) { switch(res) { - case INFO_ERR_IMPL: + case INFO_ERR_IMPL: /* Give us a chance to try the older implementation. */ if (implcode == IMPL_XNTPD) break; (void) fprintf(stderr, "***Server implementation incompatable with our own\n"); break; - case INFO_ERR_REQ: + case INFO_ERR_REQ: (void) fprintf(stderr, "***Server doesn't implement this request\n"); break; - case INFO_ERR_FMT: + case INFO_ERR_FMT: (void) fprintf(stderr, "***Server reports a format error in the received packet (shouldn't happen)\n"); break; - case INFO_ERR_NODATA: + case INFO_ERR_NODATA: (void) fprintf(stderr, "***Server reports data not found\n"); break; - case INFO_ERR_AUTH: + case INFO_ERR_AUTH: (void) fprintf(stderr, "***Permission denied\n"); break; - case ERR_TIMEOUT: + case ERR_TIMEOUT: (void) fprintf(stderr, "***Request timed out\n"); break; - case ERR_INCOMPLETE: + case ERR_INCOMPLETE: (void) fprintf(stderr, "***Response from server was incomplete\n"); break; - default: + default: (void) fprintf(stderr, "***Server returns unknown error code %d\n", res); break; @@ -1769,21 +1805,34 @@ keytype( FILE *fp ) { - if (pcmd->nargs == 0) - fprintf(fp, "keytype is %s\n", - (info_auth_keytype == NID_md5) ? "MD5" : "???"); - else - switch (*(pcmd->argval[0].string)) { - case 'm': - case 'M': - info_auth_keytype = NID_md5; - break; + const char * digest_name; + size_t digest_len; + int keytype; + + if (!pcmd->nargs) { + fprintf(fp, "keytype is %s with %u octet digests\n", + keytype_name(info_auth_keytype), + info_auth_hashlen); + return; + } - default: - fprintf(fp, "keytype must be 'md5'\n"); - } -} + digest_name = pcmd->argval[0].string; + digest_len = 0; + keytype = keytype_from_text(digest_name, &digest_len); + + if (!keytype) { + fprintf(fp, "keytype must be 'md5'%s\n", +#ifdef OPENSSL + " or a digest type provided by OpenSSL"); +#else + ""); +#endif + return; + } + info_auth_keytype = keytype; + info_auth_hashlen = digest_len; +} /* diff --git a/ntpdc/ntpdc_ops.c b/ntpdc/ntpdc_ops.c index 62b44ed71..0d26a65c4 100644 --- a/ntpdc/ntpdc_ops.c +++ b/ntpdc/ntpdc_ops.c @@ -1332,7 +1332,7 @@ doconfig( struct parse *pcmd, FILE *fp, int mode, - int refc + int refc ) { struct conf_peer cpeer; @@ -1359,7 +1359,7 @@ again: maxpoll = NTP_MAXDPOLL; numtyp = 1; if (refc) - numtyp = 5; + numtyp = 5; if (impl_ver == IMPL_XNTPD) sendsize = sizeof(struct conf_peer); diff --git a/ntpq/ntpq-subs.c b/ntpq/ntpq-subs.c index b983e72d3..3c1b31384 100644 --- a/ntpq/ntpq-subs.c +++ b/ntpq/ntpq-subs.c @@ -1067,7 +1067,7 @@ printassoc( break; case PEVNT_RATE: - last_event = "raate_exceeded"; + last_event = "rate_exceeded"; break; case PEVNT_DENY: diff --git a/ntpq/ntpq.c b/ntpq/ntpq.c index 15290a1f1..33b1c9204 100644 --- a/ntpq/ntpq.c +++ b/ntpq/ntpq.c @@ -18,6 +18,7 @@ #include "ntp_stdlib.h" #include "ntp_assert.h" #include "ntp_lineedit.h" +#include "ntp_debug.h" #include "isc/net.h" #include "isc/result.h" #include @@ -67,7 +68,8 @@ s_char sys_precision; /* local clock precision (log2 s) */ */ u_long info_auth_keyid = 0; -static int info_auth_keytype = NID_md5; /* MD5 */ +static int info_auth_keytype = NID_md5; /* MD5 */ +static size_t info_auth_hashlen = 16; /* MD5 */ u_long current_time; /* needed by authkeys; not used */ /* @@ -249,7 +251,7 @@ int ntpqmain (int, char **); */ static int openhost (const char *); -static int sendpkt (char *, int); +static int sendpkt (void *, size_t); static int getresponse (int, int, u_short *, int *, char **, int); static int sendrequest (int, int, int, int, char *); static char * tstflags (u_long); @@ -788,13 +790,11 @@ openhost( */ static int sendpkt( - char *xdata, - int xdatalen + void * xdata, + size_t xdatalen ) { - if (debug >= 3) - printf("Sending %d octets\n", xdatalen); - + DPRINTF(3, ("Sending %u octets\n", xdatalen)); if (send(sockfd, xdata, (size_t)xdatalen, 0) == -1) { warning("write to %s failed", currenthost, ""); @@ -803,13 +803,15 @@ sendpkt( if (debug >= 4) { int first = 8; + char *cdata = xdata; + printf("Packet data:\n"); while (xdatalen-- > 0) { if (first-- == 0) { printf("\n"); first = 7; } - printf(" %02x", *xdata++ & 0xff); + printf(" %02x", *cdata++ & 0xff); } printf("\n"); } @@ -1216,15 +1218,19 @@ sendrequest( ) { struct ntp_control qpkt; - int pktsize; + int pktsize; + u_long key_id; + char pass_prompt[32]; + char * pass; + int maclen; /* * Check to make sure the data will fit in one packet */ if (qsize > CTL_MAX_DATA_LEN) { - (void) fprintf(stderr, - "***Internal error! qsize (%d) too large\n", - qsize); + fprintf(stderr, + "***Internal error! qsize (%d) too large\n", + qsize); return 1; } @@ -1245,7 +1251,7 @@ sendrequest( * If we have data, copy and pad it out to a 32-bit boundary. */ if (qsize > 0) { - memcpy(qpkt.data, qdata, (unsigned)qsize); + memcpy(qpkt.data, qdata, (size_t)qsize); pktsize += qsize; while (pktsize & (sizeof(u_int32) - 1)) { qpkt.data[qsize++] = 0; @@ -1258,55 +1264,60 @@ sendrequest( * we're going to have to think about it a little. */ if (!auth && !always_auth) { - return sendpkt((char *)&qpkt, pktsize); - } else { - char * pass = "\0"; - int maclen = 0; + return sendpkt(&qpkt, pktsize); + } - /* - * Pad out packet to a multiple of 8 octets to be sure - * receiver can handle it. - */ - while (pktsize & 7) { - qpkt.data[qsize++] = 0; - pktsize++; - } + /* + * Pad out packet to a multiple of 8 octets to be sure + * receiver can handle it. + */ + while (pktsize & 7) { + qpkt.data[qsize++] = 0; + pktsize++; + } - /* - * Get the keyid and the password if we don't have one. - */ - if (info_auth_keyid == 0) { - int u_keyid = getkeyid("Keyid: "); - if (u_keyid == 0 || u_keyid > NTP_MAXKEY) { - (void) fprintf(stderr, - "Invalid key identifier\n"); - return 1; - } - info_auth_keyid = u_keyid; + /* + * Get the keyid and the password if we don't have one. + */ + if (info_auth_keyid == 0) { + key_id = getkeyid("Keyid: "); + if (key_id == 0 || key_id > NTP_MAXKEY) { + fprintf(stderr, + "Invalid key identifier\n"); + return 1; } - if (!authistrusted(info_auth_keyid)) { - pass = getpass("MD5 Password: "); - if (*pass == '\0') { - (void) fprintf(stderr, - "Invalid password\n"); - return (1); - } - authusekey(info_auth_keyid, info_auth_keytype, (const u_char *)pass); - authtrust(info_auth_keyid, 1); + info_auth_keyid = key_id; + } + if (!authistrusted(info_auth_keyid)) { + snprintf(pass_prompt, sizeof(pass_prompt), + "%s Password: ", + keytype_name(info_auth_keytype)); + pass = getpass(pass_prompt); + if ('\0' == pass[0]) { + fprintf(stderr, "Invalid password\n"); + return 1; } + authusekey(info_auth_keyid, info_auth_keytype, + (u_char *)pass); + authtrust(info_auth_keyid, 1); + } - /* - * Do the encryption. - */ - maclen = authencrypt(info_auth_keyid, (u_int32 *)&qpkt, - pktsize); - if (maclen == 0) { - (void) fprintf(stderr, "Key not found\n"); - return (1); - } - return sendpkt((char *)&qpkt, pktsize + maclen); + /* + * Do the encryption. + */ + maclen = authencrypt(info_auth_keyid, (void *)&qpkt, pktsize); + if (!maclen) { + fprintf(stderr, "Key not found\n"); + return 1; + } else if ((size_t)maclen != (info_auth_hashlen + sizeof(keyid_t))) { + fprintf(stderr, + "%d octet MAC, %u expected with %u octet digest\n", + maclen, (info_auth_hashlen + sizeof(keyid_t)), + info_auth_hashlen); + return 1; } - /*NOTREACHED*/ + + return sendpkt((char *)&qpkt, pktsize + maclen); } @@ -2376,21 +2387,34 @@ keytype( FILE *fp ) { - if (pcmd->nargs == 0) - fprintf(fp, "keytype is %s\n", - (info_auth_keytype == NID_md5) ? "MD5" : "???"); - else - switch (*(pcmd->argval[0].string)) { - case 'm': - case 'M': - info_auth_keytype = NID_md5; - break; + const char * digest_name; + size_t digest_len; + int key_type; + + if (!pcmd->nargs) { + fprintf(fp, "keytype is %s with %u octet digests\n", + keytype_name(info_auth_keytype), + info_auth_hashlen); + return; + } - default: - fprintf(fp, "keytype must be 'md5'\n"); - } -} + digest_name = pcmd->argval[0].string; + digest_len = 0; + key_type = keytype_from_text(digest_name, &digest_len); + if (!key_type) { + fprintf(fp, "keytype must be 'md5'%s\n", +#ifdef OPENSSL + " or a digest type provided by OpenSSL"); +#else + ""); +#endif + return; + } + + info_auth_keytype = key_type; + info_auth_hashlen = digest_len; +} /*