diff options
Diffstat (limited to 'contrib/ntp/ntpq/ntpq.c')
-rw-r--r-- | contrib/ntp/ntpq/ntpq.c | 337 |
1 files changed, 249 insertions, 88 deletions
diff --git a/contrib/ntp/ntpq/ntpq.c b/contrib/ntp/ntpq/ntpq.c index 547f3cc..17c2f17 100644 --- a/contrib/ntp/ntpq/ntpq.c +++ b/contrib/ntp/ntpq/ntpq.c @@ -2,10 +2,11 @@ * ntpq - query an NTP server using mode 6 commands */ #include <config.h> -#include <stdio.h> #include <ctype.h> #include <signal.h> #include <setjmp.h> +#include <stddef.h> +#include <stdio.h> #include <sys/types.h> #include <sys/time.h> #ifdef HAVE_UNISTD_H @@ -34,7 +35,15 @@ #include "openssl/evp.h" #include "openssl/objects.h" #include "openssl/err.h" +#ifdef SYS_WINNT +# include "openssl/opensslv.h" +# if !defined(HAVE_EVP_MD_DO_ALL_SORTED) && OPENSSL_VERSION_NUMBER > 0x10000000L +# define HAVE_EVP_MD_DO_ALL_SORTED 1 +# endif +#endif #include "libssl_compat.h" + +#define CMAC "AES128CMAC" #endif #include <ssl_applink.c> @@ -189,7 +198,7 @@ static int getarg (const char *, int, arg_v *); static int findcmd (const char *, struct xcmd *, struct xcmd *, struct xcmd **); static int rtdatetolfp (char *, l_fp *); -static int decodearr (char *, int *, l_fp *); +static int decodearr (char *, int *, l_fp *, int); static void help (struct parse *, FILE *); static int helpsort (const void *, const void *); static void printusage (struct xcmd *, FILE *); @@ -227,12 +236,23 @@ static void on_ctrlc (void); static int my_easprintf (char**, const char *, ...) NTP_PRINTF(2, 3); void ntpq_custom_opt_handler (tOptions *, tOptDesc *); +/* read a character from memory and expand to integer */ +static inline int +pgetc( + const char *cp + ) +{ + return (int)*(const unsigned char*)cp; +} + + #ifdef OPENSSL # ifdef HAVE_EVP_MD_DO_ALL_SORTED static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg ); # endif #endif +static char *insert_cmac(char *list); static char *list_digest_names(void); /* @@ -450,6 +470,7 @@ main( } #endif + #ifndef BUILD_AS_LIB int ntpqmain( @@ -484,14 +505,16 @@ ntpqmain( char *msg; list = list_digest_names(); - for (icmd = 0; icmd < sizeof(builtins)/sizeof(builtins[0]); icmd++) { - if (strcmp("keytype", builtins[icmd].keyword) == 0) + + for (icmd = 0; icmd < sizeof(builtins)/sizeof(*builtins); icmd++) { + if (strcmp("keytype", builtins[icmd].keyword) == 0) { break; + } } /* CID: 1295478 */ /* This should only "trip" if "keytype" is removed from builtins */ - INSIST(icmd < sizeof(builtins)/sizeof(builtins[0])); + INSIST(icmd < sizeof(builtins)/sizeof(*builtins)); #ifdef OPENSSL builtins[icmd].desc[0] = "digest-name"; @@ -584,9 +607,15 @@ ntpqmain( getcmds(); } else { for (ihost = 0; ihost < numhosts; ihost++) { - if (openhost(chosts[ihost].name, chosts[ihost].fam)) - for (icmd = 0; icmd < numcmds; icmd++) + if (openhost(chosts[ihost].name, chosts[ihost].fam)) { + if (ihost) + fputc('\n', current_output); + for (icmd = 0; icmd < numcmds; icmd++) { + if (icmd) + fputc('\n', current_output); docmd(ccmds[icmd]); + } + } } } #ifdef SYS_WINNT @@ -719,7 +748,7 @@ openhost( int err; err = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *)&optionValue, sizeof(optionValue)); + (void *)&optionValue, sizeof(optionValue)); if (err) { mfprintf(stderr, "setsockopt(SO_SYNCHRONOUS_NONALERT)" @@ -743,7 +772,7 @@ openhost( # ifdef SO_RCVBUF { int rbufsize = DATASIZE + 2048; /* 2K for slop */ if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, - &rbufsize, sizeof(int)) == -1) + (void *)&rbufsize, sizeof(int)) == -1) error("setsockopt"); } # endif @@ -2014,7 +2043,7 @@ rtdatetolfp( * d[d]-Mth-y[y[y[y]]] hh:mm:ss */ cp = str; - if (!isdigit((int)*cp)) { + if (!isdigit(pgetc(cp))) { if (*cp == '-') { /* * Catch special case @@ -2026,7 +2055,7 @@ rtdatetolfp( } cal.monthday = (u_char) (*cp++ - '0'); /* ascii dependent */ - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.monthday = (u_char)((cal.monthday << 3) + (cal.monthday << 1)); cal.monthday = (u_char)(cal.monthday + *cp++ - '0'); } @@ -2048,18 +2077,18 @@ rtdatetolfp( if (*cp++ != '-') return 0; - if (!isdigit((int)*cp)) + if (!isdigit(pgetc(cp))) return 0; cal.year = (u_short)(*cp++ - '0'); - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.year = (u_short)((cal.year << 3) + (cal.year << 1)); cal.year = (u_short)(*cp++ - '0'); } - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.year = (u_short)((cal.year << 3) + (cal.year << 1)); cal.year = (u_short)(cal.year + *cp++ - '0'); } - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.year = (u_short)((cal.year << 3) + (cal.year << 1)); cal.year = (u_short)(cal.year + *cp++ - '0'); } @@ -2072,26 +2101,26 @@ rtdatetolfp( return 1; } - if (*cp++ != ' ' || !isdigit((int)*cp)) + if (*cp++ != ' ' || !isdigit(pgetc(cp))) return 0; cal.hour = (u_char)(*cp++ - '0'); - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.hour = (u_char)((cal.hour << 3) + (cal.hour << 1)); cal.hour = (u_char)(cal.hour + *cp++ - '0'); } - if (*cp++ != ':' || !isdigit((int)*cp)) + if (*cp++ != ':' || !isdigit(pgetc(cp))) return 0; cal.minute = (u_char)(*cp++ - '0'); - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.minute = (u_char)((cal.minute << 3) + (cal.minute << 1)); cal.minute = (u_char)(cal.minute + *cp++ - '0'); } - if (*cp++ != ':' || !isdigit((int)*cp)) + if (*cp++ != ':' || !isdigit(pgetc(cp))) return 0; cal.second = (u_char)(*cp++ - '0'); - if (isdigit((int)*cp)) { + if (isdigit(pgetc(cp))) { cal.second = (u_char)((cal.second << 3) + (cal.second << 1)); cal.second = (u_char)(cal.second + *cp++ - '0'); } @@ -2215,34 +2244,36 @@ decodeuint( */ static int decodearr( - char *str, - int *narr, - l_fp *lfparr + char *cp, + int *narr, + l_fp *lfpa, + int amax ) { - register char *cp, *bp; - register l_fp *lfp; + char *bp; char buf[60]; - lfp = lfparr; - cp = str; *narr = 0; - while (*narr < 8) { - while (isspace((int)*cp)) - cp++; - if (*cp == '\0') - break; - - bp = buf; - while (!isspace((int)*cp) && *cp != '\0') - *bp++ = *cp++; - *bp++ = '\0'; + while (*narr < amax && *cp) { + if (isspace(pgetc(cp))) { + do + ++cp; + while (*cp && isspace(pgetc(cp))); + } else { + bp = buf; + do { + if (bp != (buf + sizeof(buf) - 1)) + *bp++ = *cp; + ++cp; + } while (*cp && !isspace(pgetc(cp))); + *bp = '\0'; - if (!decodetime(buf, lfp)) - return 0; - (*narr)++; - lfp++; + if (!decodetime(buf, lfpa)) + return 0; + ++(*narr); + ++lfpa; + } } return 1; } @@ -3049,7 +3080,7 @@ nextvar( /* * Space past commas and white space */ - while (cp < cpend && (*cp == ',' || isspace((int)*cp))) + while (cp < cpend && (*cp == ',' || isspace(pgetc(cp)))) cp++; if (cp >= cpend) return 0; @@ -3061,7 +3092,7 @@ nextvar( srclen = strcspn(cp, ",=\r\n"); srclen = min(srclen, (size_t)(cpend - cp)); len = srclen; - while (len > 0 && isspace((unsigned char)cp[len - 1])) + while (len > 0 && isspace(pgetc(&cp[len - 1]))) len--; if (len >= sizeof(name)) return 0; @@ -3087,7 +3118,7 @@ nextvar( * So far, so good. Copy out the value */ cp++; /* past '=' */ - while (cp < cpend && (isspace((unsigned char)*cp) && *cp != '\r' && *cp != '\n')) + while (cp < cpend && (isspace(pgetc(cp)) && *cp != '\r' && *cp != '\n')) cp++; np = cp; if ('"' == *np) { @@ -3108,7 +3139,7 @@ nextvar( /* * Trim off any trailing whitespace */ - while (len > 0 && isspace((unsigned char)value[len - 1])) + while (len > 0 && isspace(pgetc(&value[len - 1]))) len--; value[len] = '\0'; @@ -3191,7 +3222,7 @@ rawprint( */ if (cp == (cpend - 1) || *(cp + 1) != '\n') makeascii(1, cp, fp); - } else if (isspace((unsigned char)*cp) || isprint((unsigned char)*cp)) + } else if (isspace(pgetc(cp)) || isprint(pgetc(cp))) putc(*cp, fp); else makeascii(1, cp, fp); @@ -3399,7 +3430,7 @@ cookedprint( break; case TS: - if (!decodets(value, &lfp)) + if (!value || !decodets(value, &lfp)) output_raw = '?'; else output(fp, name, prettydate(&lfp)); @@ -3407,7 +3438,7 @@ cookedprint( case HA: /* fallthru */ case NA: - if (!decodenetnum(value, &hval)) { + if (!value || !decodenetnum(value, &hval)) { output_raw = '?'; } else if (fmt == HA){ output(fp, name, nntohost(&hval)); @@ -3417,7 +3448,9 @@ cookedprint( break; case RF: - if (decodenetnum(value, &hval)) { + if (!value) { + output_raw = '?'; + } else if (decodenetnum(value, &hval)) { if (ISREFCLOCKADR(&hval)) output(fp, name, refnumtoa(&hval)); @@ -3431,7 +3464,7 @@ cookedprint( break; case LP: - if (!decodeuint(value, &uval) || uval > 3) { + if (!value || !decodeuint(value, &uval) || uval > 3) { output_raw = '?'; } else { b[0] = (0x2 & uval) @@ -3446,7 +3479,7 @@ cookedprint( break; case OC: - if (!decodeuint(value, &uval)) { + if (!value || !decodeuint(value, &uval)) { output_raw = '?'; } else { snprintf(b, sizeof(b), "%03lo", uval); @@ -3455,14 +3488,14 @@ cookedprint( break; case AR: - if (!decodearr(value, &narr, lfparr)) + if (!value || !decodearr(value, &narr, lfparr, 8)) output_raw = '?'; else outputarr(fp, name, narr, lfparr); break; case FX: - if (!decodeuint(value, &uval)) + if (!value || !decodeuint(value, &uval)) output_raw = '?'; else output(fp, name, tstflags(uval)); @@ -3584,81 +3617,205 @@ ntpq_custom_opt_handler( * Obtain list of digest names */ +#if defined(OPENSSL) && !defined(HAVE_EVP_MD_DO_ALL_SORTED) +# if defined(_MSC_VER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +# define HAVE_EVP_MD_DO_ALL_SORTED +# endif +#endif + #ifdef OPENSSL # ifdef HAVE_EVP_MD_DO_ALL_SORTED +# define K_PER_LINE 8 +# define K_NL_PFX_STR "\n " +# define K_DELIM_STR ", " + struct hstate { char *list; const char **seen; int idx; }; -#define K_PER_LINE 8 -#define K_NL_PFX_STR "\n " -#define K_DELIM_STR ", " -static void list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg ) + + +static void +list_md_fn(const EVP_MD *m, const char *from, const char *to, void *arg) { - size_t len, n; - const char *name, *cp, **seen; + size_t len, n, digest_len; + const char *name, **seen; struct hstate *hstate = arg; - EVP_MD_CTX *ctx; - u_int digest_len; - u_char digest[EVP_MAX_MD_SIZE]; + char *cp; - if (!m) + /* m is MD obj, from is name or alias, to is base name for alias */ + if (!m || !from || to) { return; /* Ignore aliases */ + } + + /* Discard MACs that NTP won't accept. */ + /* Keep this consistent with keytype_from_text() in ssl_init.c. */ + if (EVP_MD_size(m) > (MAX_MAC_LEN - sizeof(keyid_t))) { + return; + } name = EVP_MD_name(m); /* Lowercase names aren't accepted by keytype_from_text in ssl_init.c */ - for( cp = name; *cp; cp++ ) { - if( islower((unsigned char)*cp) ) + for (cp = name; *cp; cp++) { + if (islower((unsigned char)*cp)) { return; + } } + len = (cp - name) + 1; /* There are duplicates. Discard if name has been seen. */ - for (seen = hstate->seen; *seen; seen++) - if (!strcmp(*seen, name)) + for (seen = hstate->seen; *seen; seen++) { + if (!strcmp(*seen, name)) { return; + } + } + n = (seen - hstate->seen) + 2; hstate->seen = erealloc(hstate->seen, n * sizeof(*seen)); hstate->seen[n-2] = name; hstate->seen[n-1] = NULL; - /* Discard MACs that NTP won't accept. - * Keep this consistent with keytype_from_text() in ssl_init.c. - */ - - ctx = EVP_MD_CTX_new(); - EVP_DigestInit(ctx, EVP_get_digestbyname(name)); - EVP_DigestFinal(ctx, digest, &digest_len); - EVP_MD_CTX_free(ctx); - if (digest_len > (MAX_MAC_LEN - sizeof(keyid_t))) - return; - - if (hstate->list != NULL) + if (hstate->list != NULL) { len += strlen(hstate->list); - len += (hstate->idx >= K_PER_LINE)? strlen(K_NL_PFX_STR): strlen(K_DELIM_STR); + } + + len += (hstate->idx >= K_PER_LINE) + ? strlen(K_NL_PFX_STR) + : strlen(K_DELIM_STR); if (hstate->list == NULL) { - hstate->list = (char *)emalloc(len); + hstate->list = (char *)emalloc(len); hstate->list[0] = '\0'; - } else + } else { hstate->list = (char *)erealloc(hstate->list, len); + } sprintf(hstate->list + strlen(hstate->list), "%s%s", - ((hstate->idx >= K_PER_LINE)? K_NL_PFX_STR : K_DELIM_STR), + ((hstate->idx >= K_PER_LINE) ? K_NL_PFX_STR : K_DELIM_STR), name); - if (hstate->idx >= K_PER_LINE) + + if (hstate->idx >= K_PER_LINE) { hstate->idx = 1; - else + } else { hstate->idx++; + } +} + + +/* Insert CMAC into SSL digests list */ +static char * +insert_cmac(char *list) +{ + int insert; + size_t len; + + + /* If list empty, we need to insert CMAC on new line */ + insert = (!list || !*list); + + if (insert) { + len = strlen(K_NL_PFX_STR) + strlen(CMAC); + list = (char *)erealloc(list, len + 1); + sprintf(list, "%s%s", K_NL_PFX_STR, CMAC); + } else { /* List not empty */ + /* Check if CMAC already in list - future proofing */ + const char *cmac_sn; + char *cmac_p; + + cmac_sn = OBJ_nid2sn(NID_cmac); + cmac_p = list; + insert = cmac_sn != NULL && *cmac_sn != '\0'; + + /* CMAC in list if found, followed by nul char or ',' */ + while (insert && NULL != (cmac_p = strstr(cmac_p, cmac_sn))) { + cmac_p += strlen(cmac_sn); + /* Still need to insert if not nul and not ',' */ + insert = *cmac_p && ',' != *cmac_p; + } + + /* Find proper insertion point */ + if (insert) { + char *last_nl; + char *point; + char *delim; + int found; + + /* Default to start if list empty */ + found = 0; + delim = list; + len = strlen(list); + + /* While new lines */ + while (delim < list + len && *delim && + !strncmp(K_NL_PFX_STR, delim, strlen(K_NL_PFX_STR))) { + point = delim + strlen(K_NL_PFX_STR); + + /* While digest names on line */ + while (point < list + len && *point) { + /* Another digest after on same or next line? */ + delim = strstr( point, K_DELIM_STR); + last_nl = strstr( point, K_NL_PFX_STR); + + /* No - end of list */ + if (!delim && !last_nl) { + delim = list + len; + } else + /* New line and no delim or before delim? */ + if (last_nl && (!delim || last_nl < delim)) { + delim = last_nl; + } + + /* Found insertion point where CMAC before entry? */ + if (strncmp(CMAC, point, delim - point) < 0) { + found = 1; + break; + } + + if (delim < list + len && *delim && + !strncmp(K_DELIM_STR, delim, strlen(K_DELIM_STR))) { + point += strlen(K_DELIM_STR); + } else { + break; + } + } /* While digest names on line */ + } /* While new lines */ + + /* If found in list */ + if (found) { + /* insert cmac and delim */ + /* Space for list could move - save offset */ + ptrdiff_t p_offset = point - list; + len += strlen(CMAC) + strlen(K_DELIM_STR); + list = (char *)erealloc(list, len + 1); + point = list + p_offset; + /* move to handle src/dest overlap */ + memmove(point + strlen(CMAC) + strlen(K_DELIM_STR), + point, strlen(point) + 1); + strncpy(point, CMAC, strlen(CMAC)); + strncpy(point + strlen(CMAC), K_DELIM_STR, strlen(K_DELIM_STR)); + } else { /* End of list */ + /* append delim and cmac */ + len += strlen(K_DELIM_STR) + strlen(CMAC); + list = (char *)erealloc(list, len + 1); + strcpy(list + strlen(list), K_DELIM_STR); + strcpy(list + strlen(list), CMAC); + } + } /* insert */ + } /* List not empty */ + + return list; } # endif #endif -static char *list_digest_names(void) + +static char * +list_digest_names(void) { char *list = NULL; @@ -3666,12 +3823,16 @@ static char *list_digest_names(void) # ifdef HAVE_EVP_MD_DO_ALL_SORTED struct hstate hstate = { NULL, NULL, K_PER_LINE+1 }; - hstate.seen = (const char **) emalloc_zero(1*sizeof( const char * )); // replaces -> calloc(1, sizeof( const char * )); + /* replace calloc(1, sizeof(const char *)) */ + hstate.seen = (const char **)emalloc_zero(sizeof(const char *)); INIT_SSL(); EVP_MD_do_all_sorted(list_md_fn, &hstate); list = hstate.list; free(hstate.seen); + + list = insert_cmac(list); /* Insert CMAC into SSL digests list */ + # else list = (char *)emalloc(sizeof("md5, others (upgrade to OpenSSL-1.0 for full list)")); strcpy(list, "md5, others (upgrade to OpenSSL-1.0 for full list)"); |