diff options
Diffstat (limited to 'contrib/ntp/ntpd/ntp_crypto.c')
-rw-r--r-- | contrib/ntp/ntpd/ntp_crypto.c | 323 |
1 files changed, 162 insertions, 161 deletions
diff --git a/contrib/ntp/ntpd/ntp_crypto.c b/contrib/ntp/ntpd/ntp_crypto.c index 7a5a100..2be501d 100644 --- a/contrib/ntp/ntpd/ntp_crypto.c +++ b/contrib/ntp/ntpd/ntp_crypto.c @@ -316,8 +316,8 @@ make_keylist( */ tstamp = crypto_time(); if (peer->keylist == NULL) - peer->keylist = emalloc(sizeof(keyid_t) * - NTP_MAXSESSION); + peer->keylist = eallocarray(NTP_MAXSESSION, + sizeof(keyid_t)); /* * Generate an initial key ID which is unique and greater than @@ -380,16 +380,14 @@ make_keylist( EVP_SignUpdate(&ctx, (u_char *)vp, 12); EVP_SignUpdate(&ctx, vp->ptr, sizeof(struct autokey)); if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { - vp->siglen = htonl(sign_siglen); + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); peer->flags |= FLAG_ASSOC; } } -#ifdef DEBUG - if (debug) - printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n", + DPRINTF(1, ("make_keys: %d %08x %08x ts %u fs %u poll %d\n", peer->keynumber, keyid, cookie, ntohl(vp->tstamp), - ntohl(vp->fstamp), peer->hpoll); -#endif + ntohl(vp->fstamp), peer->hpoll)); return (XEVNT_OK); } @@ -456,13 +454,9 @@ crypto_recv( // HMS: Why pkt[1] instead of ep->associd ? associd = (associd_t)ntohl(pkt[1]); rval = XEVNT_OK; -#ifdef DEBUG - if (debug) - printf( - "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n", + DPRINTF(1, ("crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n", peer->crypto, authlen, len, code >> 16, - associd); -#endif + associd)); /* * Check version number and field length. If bad, @@ -538,13 +532,9 @@ crypto_recv( rval = XEVNT_LEN; break; } -#ifdef DEBUG - if (debug) - printf( - "crypto_recv: ident host 0x%x %d server 0x%x %d\n", + DPRINTF(1, ("crypto_recv: ident host 0x%x %d server 0x%x %d\n", crypto_flags, peer->associd, fstamp, - peer->assoc); -#endif + peer->assoc)); temp32 = crypto_flags & CRYPTO_FLAG_MASK; /* @@ -617,10 +607,7 @@ crypto_recv( peer->assoc, peer->subject, OBJ_nid2ln(temp32)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -678,10 +665,7 @@ crypto_recv( OBJ_nid2ln(temp32), temp32, ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -718,10 +702,7 @@ crypto_recv( snprintf(statstr, sizeof(statstr), "iff %s fs %u", peer->issuer, ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -759,10 +740,7 @@ crypto_recv( snprintf(statstr, sizeof(statstr), "gq %s fs %u", peer->issuer, ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -799,10 +777,7 @@ crypto_recv( snprintf(statstr, sizeof(statstr), "mv %s fs %u", peer->issuer, ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; @@ -868,10 +843,7 @@ crypto_recv( "cook %x ts %u fs %u", peer->pcookie, ntohl(ep->tstamp), ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -930,10 +902,7 @@ crypto_recv( bp->key, ntohl(ep->tstamp), ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -970,10 +939,7 @@ crypto_recv( OBJ_nid2ln(temp32), temp32, ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -988,43 +954,32 @@ crypto_recv( * compare the value timestamps here, as they * can be updated by different servers. */ - if ((rval = crypto_verify(ep, NULL, peer)) != - XEVNT_OK) + rval = crypto_verify(ep, NULL, peer); + if ((rval != XEVNT_OK ) || + (vallen != 3*sizeof(uint32_t)) ) break; - /* - * If the packet leap values are more recent - * than the stored ones, install the new leap - * values and recompute the signatures. + /* Check if we can update the basic TAI offset + * for our current leap frame. This is a hack + * and ignores the time stamps in the autokey + * message. */ - if (leapsec_add_fix(ntohl(ep->pkt[0]), - ntohl(ep->pkt[1]), - ntohl(ep->pkt[2]), - NULL)) - { - leap_signature_t lsig; - - leapsec_getsig(&lsig); - tai_leap.tstamp = ep->tstamp; - tai_leap.fstamp = ep->fstamp; - tai_leap.vallen = ep->vallen; - crypto_update(); - mprintf_event(EVNT_TAI, peer, - "%d leap %s expire %s", lsig.taiof, - fstostr(lsig.ttime), - fstostr(lsig.etime)); - } + if (sys_leap != LEAP_NOTINSYNC) + leapsec_autokey_tai(ntohl(ep->pkt[0]), + rbufp->recv_time.l_ui, NULL); + tai_leap.tstamp = ep->tstamp; + tai_leap.fstamp = ep->fstamp; + crypto_update(); + mprintf_event(EVNT_TAI, peer, + "%d seconds", ntohl(ep->pkt[0])); peer->crypto |= CRYPTO_FLAG_LEAP; peer->flash &= ~TEST8; snprintf(statstr, sizeof(statstr), - "leap TAI offset %d at %u expire %u fs %u", - ntohl(ep->pkt[0]), ntohl(ep->pkt[1]), - ntohl(ep->pkt[2]), ntohl(ep->fstamp)); + "leap TAI offset %d at %u expire %u fs %u", + ntohl(ep->pkt[0]), ntohl(ep->pkt[1]), + ntohl(ep->pkt[2]), ntohl(ep->fstamp)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); break; /* @@ -1073,10 +1028,7 @@ crypto_recv( "%04x %d %02x %s", htonl(ep->opcode), associd, rval, eventstr(rval)); record_crypto_stats(&peer->srcadr, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_recv: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_recv: %s\n", statstr)); return (rval); } authlen += (len + 3) / 4 * 4; @@ -1421,19 +1373,12 @@ crypto_xmit( "%04x %d %02x %s", opcode, associd, rval, eventstr(rval)); record_crypto_stats(srcadr_sin, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_xmit: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_xmit: %s\n", statstr)); if (!(opcode & CRYPTO_RESP)) return (0); } -#ifdef DEBUG - if (debug) - printf( - "crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n", - crypto_flags, start, len, opcode >> 16, associd); -#endif + DPRINTF(1, ("crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n", + crypto_flags, start, len, opcode >> 16, associd)); return (len); } @@ -1645,8 +1590,10 @@ crypto_encrypt( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, vallen); - if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) { + NTP_INSIST(vallen <= sign_siglen); + vp->siglen = htonl(vallen); + } return (XEVNT_OK); } @@ -1858,7 +1805,7 @@ crypto_update(void) char statstr[NTP_MAXSTRLEN]; /* statistics for filegen */ u_int32 *ptr; u_int len; - leap_signature_t lsig; + leap_result_t leap_data; hostval.tstamp = htonl(crypto_time()); if (hostval.tstamp == 0) @@ -1877,8 +1824,10 @@ crypto_update(void) EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&pubkey, 12); EVP_SignUpdate(&ctx, pubkey.ptr, ntohl(pubkey.vallen)); - if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey)) - pubkey.siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + pubkey.siglen = htonl(len); + } } /* @@ -1896,8 +1845,10 @@ crypto_update(void) EVP_SignUpdate(&ctx, (u_char *)&cp->cert, 12); EVP_SignUpdate(&ctx, cp->cert.ptr, ntohl(cp->cert.vallen)); - if (EVP_SignFinal(&ctx, cp->cert.sig, &len, sign_pkey)) - cp->cert.siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, cp->cert.sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + cp->cert.siglen = htonl(len); + } } /* @@ -1906,33 +1857,86 @@ crypto_update(void) */ tai_leap.tstamp = hostval.tstamp; tai_leap.fstamp = hostval.fstamp; + + /* Get the leap second era. We might need a full lookup early + * after start, when the cache is not yet loaded. + */ + leapsec_frame(&leap_data); + if ( ! memcmp(&leap_data.ebase, &leap_data.ttime, sizeof(vint64))) { + time_t now = time(NULL); + uint32_t nowntp = (uint32_t)now + JAN_1970; + leapsec_query(&leap_data, nowntp, &now); + } + + /* Create the data block. The protocol does not work without. */ len = 3 * sizeof(u_int32); - if (tai_leap.ptr == NULL) + if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) { + free(tai_leap.ptr); tai_leap.ptr = emalloc(len); - tai_leap.vallen = htonl(len); + tai_leap.vallen = htonl(len); + } ptr = (u_int32 *)tai_leap.ptr; - leapsec_getsig(&lsig); - ptr[0] = htonl(lsig.taiof); - ptr[1] = htonl(lsig.ttime); - ptr[2] = htonl(lsig.etime); + if (leap_data.tai_offs > 10) { + /* create a TAI / leap era block. The end time is a + * fake -- maybe we can do better. + */ + ptr[0] = htonl(leap_data.tai_offs); + ptr[1] = htonl(leap_data.ebase.d_s.lo); + if (leap_data.ttime.d_s.hi >= 0) + ptr[2] = htonl(leap_data.ttime.D_s.lo + 7*86400); + else + ptr[2] = htonl(leap_data.ebase.D_s.lo + 25*86400); + } else { + /* no leap era available */ + memset(ptr, 0, len); + } if (tai_leap.sig == NULL) tai_leap.sig = emalloc(sign_siglen); EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12); EVP_SignUpdate(&ctx, tai_leap.ptr, len); - if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey)) - tai_leap.siglen = htonl(sign_siglen); - if (lsig.ttime > 0) - crypto_flags |= CRYPTO_FLAG_TAI; + if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + tai_leap.siglen = htonl(len); + } + crypto_flags |= CRYPTO_FLAG_TAI; + snprintf(statstr, sizeof(statstr), "signature update ts %u", ntohl(hostval.tstamp)); record_crypto_stats(NULL, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_update: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_update: %s\n", statstr)); } +/* + * crypto_update_taichange - eventually trigger crypto_update + * + * This is called when a change in 'sys_tai' is detected. This will + * happen shortly after a leap second is detected, but unhappily also + * early after system start; also, the crypto stuff might be unused and + * an unguarded call to crypto_update() causes a crash. + * + * This function makes sure that there already *is* a valid crypto block + * for the use with autokey, and only calls 'crypto_update()' if it can + * succeed. + * + * Returns void (no errors) + */ +void +crypto_update_taichange(void) +{ + static const u_int len = 3 * sizeof(u_int32); + + /* check if the signing digest algo is available */ + if (sign_digest == NULL || sign_pkey == NULL) + return; + + /* check size of TAI extension block */ + if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) + return; + + /* crypto_update should at least not crash here! */ + crypto_update(); +} /* * value_free - free value structure components. @@ -2164,8 +2168,10 @@ crypto_alice( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); + } return (XEVNT_OK); } @@ -2272,8 +2278,10 @@ crypto_bob( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, vallen); - if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey)) { + NTP_INSIST(vallen <= sign_siglen); + vp->siglen = htonl(vallen); + } return (XEVNT_OK); } @@ -2477,8 +2485,10 @@ crypto_alice2( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); + } return (XEVNT_OK); } @@ -2575,8 +2585,10 @@ crypto_bob2( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); + } return (XEVNT_OK); } @@ -2804,8 +2816,10 @@ crypto_alice3( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); + } return (XEVNT_OK); } @@ -2904,8 +2918,10 @@ crypto_bob3( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12); EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); + } return (XEVNT_OK); } @@ -3141,8 +3157,10 @@ cert_sign( EVP_SignInit(&ctx, sign_digest); EVP_SignUpdate(&ctx, (u_char *)vp, 12); EVP_SignUpdate(&ctx, vp->ptr, len); - if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) - vp->siglen = htonl(sign_siglen); + if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) { + NTP_INSIST(len <= sign_siglen); + vp->siglen = htonl(len); + } } #ifdef DEBUG if (debug > 1) @@ -3425,11 +3443,8 @@ cert_parse( ret->flags |= CERT_TRUST; else if (strcmp(pathbuf, "Private") == 0) ret->flags |= CERT_PRIV; -#if DEBUG - if (debug) - printf("cert_parse: %s: %s\n", - OBJ_nid2ln(temp), pathbuf); -#endif + DPRINTF(1, ("cert_parse: %s: %s\n", + OBJ_nid2ln(temp), pathbuf)); break; /* @@ -3440,12 +3455,10 @@ cert_parse( ret->grpkey = BN_bin2bn(&ext->value->data[2], ext->value->length - 2, NULL); /* fall through */ -#if DEBUG default: - if (debug) - printf("cert_parse: %s\n", - OBJ_nid2ln(temp)); -#endif + DPRINTF(1, ("cert_parse: %s\n", + OBJ_nid2ln(temp))); + break; } } if (strcmp(ret->subject, ret->issuer) == 0) { @@ -3630,9 +3643,9 @@ crypto_key( snprintf(statstr, sizeof(statstr), "%s mod %d", &linkname[2], EVP_PKEY_size(pkey) * 8); record_crypto_stats(addr, statstr); + + DPRINTF(1, ("crypto_key: %s\n", statstr)); #ifdef DEBUG - if (debug) - printf("crypto_key: %s\n", statstr); if (debug > 1) { if (pkey->type == EVP_PKEY_DSA) DSA_print_fp(stdout, pkey->pkey.dsa, 0); @@ -3747,10 +3760,7 @@ crypto_cert( snprintf(statstr, sizeof(statstr), "%s 0x%x len %lu", &linkname[2], ret->flags, len); record_crypto_stats(NULL, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_cert: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_cert: %s\n", statstr)); return (ret); } @@ -3820,12 +3830,8 @@ crypto_setup(void) arc4random_buf(&seed, sizeof(l_fp)); RAND_seed(&seed, sizeof(l_fp)); RAND_write_file(randfile); -#ifdef DEBUG - if (debug) - printf( - "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n", - SSLeay(), randfile, bytes); -#endif + DPRINTF(1, ("crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n", + SSLeay(), randfile, bytes)); } /* @@ -3954,10 +3960,7 @@ crypto_setup(void) snprintf(statstr, sizeof(statstr), "setup 0x%x host %s %s", crypto_flags, hostname, OBJ_nid2ln(cinfo->nid)); record_crypto_stats(NULL, statstr); -#ifdef DEBUG - if (debug) - printf("crypto_setup: %s\n", statstr); -#endif + DPRINTF(1, ("crypto_setup: %s\n", statstr)); } @@ -3972,10 +3975,8 @@ crypto_config( { int nid; -#ifdef DEBUG - if (debug > 1) - printf("crypto_config: item %d %s\n", item, cp); -#endif + DPRINTF(1, ("crypto_config: item %d %s\n", item, cp)); + switch (item) { /* |