From: Harlan Stenn Date: Sat, 8 Apr 2000 04:06:57 +0000 (-0000) Subject: Many files: X-Git-Tag: NTP_4_0_99_J~44 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ce96ea0b2c80fd627cf8026a15621dcc2d0e9f72;p=thirdparty%2Fntp.git Many files: Dave improved the crypto stuff. bk: 38eeb061Q05XHxfPGD5DD4ib41Evug --- diff --git a/include/ntp.h b/include/ntp.h index 87d2202fe2..fcc003266a 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -151,13 +151,38 @@ typedef char s_char; #ifdef AUTOKEY /* - * THe autokey structure holds the data necessary to authenticate + * The autokey structure holds the data necessary to authenticate * the key IDs. */ -struct autokey { +struct autokey { /* network byte order */ + u_int32 tstamp; /* timestamp */ keyid_t key; /* key ID */ int seq; /* key number */ - u_int32 tstamp; /* timestamp (s) */ + u_int siglen; /* signature length */ + u_char *sig; /* signature */ +}; + +/* + * The cookie structure holds the current private value used to + * construct session keys. + */ +struct cookie { /* network byte order */ + u_int32 tstamp; /* timestamp */ + keyid_t key; /* key ID */ + u_int siglen; /* signature length */ + u_char *sig; /* signature */ +}; + +/* + * The value structure holds variable length data such as host + * name and public value. + */ +struct value { /* network byte order */ + u_int32 tstamp; /* timestamp */ + u_int vallen; /* value length */ + u_char *val; /* value */ + u_int siglen; /* signature length */ + u_char *sig; /* signature */ }; #endif /* AUTOKEY */ @@ -256,17 +281,15 @@ struct peer { #ifdef PUBKEY u_char *pubkey; /* public key */ #endif /* PUBKEY */ -#ifdef AUTOKEY keyid_t pkeyid; /* previous key ID */ +#ifdef AUTOKEY #define clear_to_zero pkeyid +#define crypto_to_zero pkeyid keyid_t hcookie; /* host cookie */ - keyid_t pcookie; /* peer cookie */ - int recseq; /* current key number */ + struct cookie pcookie; /* peer cookie */ struct autokey recauto; /* autokey */ u_int32 cmmd; /* peer command */ u_short assoc; /* association ID of peer */ - u_char *dh_public; /* Diffie-Hellman public value */ - u_char *dh_key; /* Diffie-Hellman agreed key */ /* * Variables used by authenticated server @@ -274,20 +297,18 @@ struct peer { keyid_t *keylist; /* session key ID list */ int keynumber; /* current key number */ struct autokey sndauto; /* autokey */ -#ifdef PUBKEY - u_char *sign; /* signature of keylist values */ - u_int signlen; /* length of signature */ -#endif /* PUBKEY */ #endif /* AUTOKEY */ /* * Ephemeral state variables */ u_int valid; /* valid update counter */ - u_int tailcnt; /* tailgate poll counter */ -#ifndef AUTOKEY +#ifdef AUTOKEY +#define end_crypto_to_zero valid +#else #define clear_to_zero valid #endif /* AUTOKEY */ + u_int tailcnt; /* tailgate poll counter */ u_char status; /* peer status */ u_char pollsw; /* what it says */ u_char reach; /* reachability register */ @@ -398,6 +419,11 @@ struct peer { #define END_CLEAR_TO_ZERO(p) ((char *)&((p)->end_clear_to_zero)) #define LEN_CLEAR_TO_ZERO (END_CLEAR_TO_ZERO((struct peer *)0) \ - CLEAR_TO_ZERO((struct peer *)0)) +#define CRYPTO_TO_ZERO(p) ((char *)&((p)->clear_to_zero)) +#define END_CRYPTO_TO_ZERO(p) ((char *)&((p)->end_clear_to_zero)) +#define LEN_CRYPTO_TO_ZERO (END_CRYPTO_TO_ZERO((struct peer *)0) \ + - CRYPTO_TO_ZERO((struct peer *)0)) + /* * Reference clock identifiers (for pps signal) */ diff --git a/include/ntp_control.h b/include/ntp_control.h index 864ce13eb6..b2084c8bbf 100644 --- a/include/ntp_control.h +++ b/include/ntp_control.h @@ -167,7 +167,9 @@ struct ntp_control { #define CS_PRIVATE 19 #define CS_PUBLIC 20 #define CS_DHPARAMS 21 -#define CS_MAXCODE CS_DHPARAMS +#define CS_HOSTNAM 22 +#define CS_REVTIME 23 +#define CS_MAXCODE CS_REVTIME #else #define CS_MAXCODE CS_VARLIST #endif /* PUBKEY */ @@ -216,10 +218,9 @@ struct ntp_control { #define CP_PUBLIC 38 #define CP_SESKEY 39 #define CP_SASKEY 40 -#define CP_AUTOSEQ 41 -#define CP_INITSEQ 42 -#define CP_INITKEY 43 -#define CP_INITTSP 44 +#define CP_INITSEQ 41 +#define CP_INITKEY 42 +#define CP_INITTSP 43 #define CP_MAXCODE CP_INITTSP #else #define CP_MAXCODE CP_VARLIST diff --git a/include/ntp_crypto.h b/include/ntp_crypto.h index 604b286b28..afb4047a98 100644 --- a/include/ntp_crypto.h +++ b/include/ntp_crypto.h @@ -29,6 +29,9 @@ #define CRYPTO_FLAG_PUBL 0x01 /* read peer public key from file */ #ifdef PUBKEY + +#define MAX_DH_LEN (DH_PRIME_LEN(1024)) /* max agreed key length */ + /* * Configuration codes */ @@ -51,12 +54,12 @@ extern keyid_t session_key P((struct sockaddr_in *, struct u_long)); extern void make_keylist P((struct peer *)); extern void key_expire P((struct peer *)); +extern void crypto_agree P((void)); #ifdef PUBKEY extern void crypto_init P((void)); extern void crypto_config P((int, char *)); extern void crypto_setup P((void)); extern int crypto_public P((struct peer *, u_char *)); -extern void crypto_agree P((void)); /* * Cryptographic values diff --git a/include/ntpd.h b/include/ntpd.h index 9535ad67b6..d60f1445d2 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -132,7 +132,8 @@ extern struct peer *peer_config P((struct sockaddr_in *, struct interface *, int extern void peer_reset P((struct peer *)); extern int peer_unconfig P((struct sockaddr_in *, struct interface *, int)); extern void unpeer P((struct peer *)); -extern void key_expire_all P((void)); +extern void clear_all P((void)); +extern void expire_all P((void)); extern struct peer *findmanycastpeer P((l_fp *)); extern void peer_config_manycast P((struct peer *, struct peer *)); @@ -179,6 +180,11 @@ extern void hack_restrict P((int, struct sockaddr_in *, struct sockaddr_in *, in extern void init_timer P((void)); extern void timer P((void)); extern void timer_clr_stats P((void)); +#ifdef AUTOKEY +extern char *sys_hostname; +extern u_int sys_hostnamelen; +extern l_fp sys_revoketime; +#endif /* AUTOKEY */ /* ntp_util.c */ extern void init_util P((void)); diff --git a/ntpd/ntp_control.c b/ntpd/ntp_control.c index a880c8b9a6..3b654d3b5d 100644 --- a/ntpd/ntp_control.c +++ b/ntpd/ntp_control.c @@ -116,6 +116,8 @@ static struct ctl_var sys_var[] = { { CS_PRIVATE, RO, "privatekey" }, /* 19 */ { CS_PUBLIC, RO, "publickey" }, /* 20 */ { CS_DHPARAMS, RO, "dhparams" }, /* 21 */ + { CS_HOSTNAM, RO, "hostname" }, /* 22 */ + { CS_REVTIME, RO, "revoketime"}, /* 23 */ #endif /* PUBKEY */ { 0, EOV, "" } }; @@ -148,6 +150,8 @@ static u_char def_sys_var[] = { CS_PRIVATE, CS_PUBLIC, CS_DHPARAMS, + CS_HOSTNAM, + CS_REVTIME, #endif /* PUBKEY */ 0 }; @@ -199,10 +203,9 @@ static struct ctl_var peer_var[] = { { CP_PUBLIC, RO, "publickey" }, /* 38 */ { CP_SESKEY, RO, "pcookie" }, /* 39 */ { CP_SASKEY, RO, "hcookie" }, /* 40 */ - { CP_AUTOSEQ, RO, "sequence" }, /* 41 */ - { CP_INITSEQ, RO, "initsequence" }, /* 42 */ - { CP_INITKEY, RO, "initkey" }, /* 43 */ - { CP_INITTSP, RO, "timestamp" }, /* 44 */ + { CP_INITSEQ, RO, "initsequence" }, /* 41 */ + { CP_INITKEY, RO, "initkey" }, /* 42 */ + { CP_INITTSP, RO, "timestamp" }, /* 43 */ #endif /* PUBKEY */ { 0, EOV, "" } }; @@ -244,7 +247,7 @@ static u_char def_peer_var[] = { #ifdef PUBKEY CP_PUBLIC, CP_SESKEY, - CP_AUTOSEQ, + CP_INITSEQ, #endif /* PUBKEY */ 0 }; @@ -1321,6 +1324,16 @@ ctl_putsys( ctl_putstr(sys_var[CS_DHPARAMS].text, dh_params_file, strlen(dh_params_file)); break; + + case CS_HOSTNAM: + if (sys_hostname != NULL) + ctl_putstr(sys_var[CS_HOSTNAM].text, + sys_hostname, sys_hostnamelen); + break; + + case CS_REVTIME: + ctl_putts(sys_var[CS_REVTIME].text, &sys_revoketime); + break; #endif /* PUBKEY */ } } @@ -1560,16 +1573,16 @@ ctl_putpeer( break; case CP_SESKEY: - if (peer->pcookie != NULL) - ctl_puthex(peer_var[CP_SESKEY].text, peer->pcookie); + if (peer->pcookie.key != NULL) + ctl_puthex(peer_var[CP_SESKEY].text, + peer->pcookie.key); if (peer->hcookie != NULL) ctl_puthex(peer_var[CP_SASKEY].text, peer->hcookie); break; - case CP_AUTOSEQ: + case CP_INITSEQ: if (peer->keylist == NULL) break; - ctl_putint(peer_var[CP_AUTOSEQ].text, peer->recseq); ctl_putint(peer_var[CP_INITSEQ].text, peer->recauto.seq); ctl_puthex(peer_var[CP_INITKEY].text, peer->recauto.key); ctl_putuint(peer_var[CP_INITTSP].text, peer->recauto.tstamp); diff --git a/ntpd/ntp_crypto.c b/ntpd/ntp_crypto.c index 2d39340b52..a8a7f66490 100644 --- a/ntpd/ntp_crypto.c +++ b/ntpd/ntp_crypto.c @@ -23,22 +23,23 @@ * +-------+-------+ +-------+-------+ +-------+-------+ * 1 | assoc ID | | assoc ID | | assoc ID | * +---------------+ +---------------+ +---------------+ - * 2 | current seq | | peer cookie | | value len | + * 2 | timestamp | | timestamp | | timestamp | * +---------------+ +---------------+ +---------------+ - * 3 | final seq | | signature len | | | + * 3 | final seq | | cookie | | value len | + * +---------------+ +---------------+ +---------------+ + * 4 | final key | | signature len | | | * +---------------+ +---------------+ = value = - * 4 | final key | | | | | + * 5 | signature len | | | | | * +---------------+ = signature = +---------------+ - * 4 | timestamp | | | CRYPTO_DH req/rsp - * +---------------+ +---------------+ CRYPTO_PUB rsp - * 5 | signature len | CRYPTO_PRIV rsp CRYPTO_NAME rsp - * +---------------+ - * 6 | | - * = signature = - * | | Other requests and responses have only the - * +---------------+ first two words. - * CRYPTO_AUTO rsp - * + * 6 | | | | | signature len | + * = signature = +---------------+ +---------------+ + * 7 | | CRYPTO_PRIV rsp | | + * +---------------+ = signature = + * CRYPTO_AUTO rsp | | + * +---------------+ + * CRYPTO_DH rsp + * CRYPTO_NAME rsp + * * CRYPTO_PUBL 1 request/respond for public key * CRYPTO_ASSOC 2 request/respond association ID * CRYPTO_AUTO 3 request/respond autokey values @@ -65,6 +66,8 @@ static u_char *dh_public; /* Diffie-Hellman public value */ static u_char *dh_private; /* Diffie-Hellman private value */ static R_RSA_PRIVATE_KEY private_key; /* RSA private key */ static R_RSA_PUBLIC_KEY public_key; /* RSA public key */ +static u_char *dh_sign = NULL; /* Diffie-Hellman public signature */ +static struct value host; /* host name, timestamp and signature */ int crypto_enable; /* master switch */ int crypto_flags; /* flags that wave cryptically */ @@ -80,6 +83,7 @@ static int crypto_read P((u_char *, u_char *, u_int)); static void crypto_line P((FILE *, u_char **, u_int *)); #endif /* PUBKEY */ + /* * session_key - generate session key * @@ -144,6 +148,7 @@ make_keylist( struct peer *peer /* peer structure pointer */ ) { + struct autokey *ap; /* autokey pointer */ keyid_t keyid; /* next key ID */ keyid_t cookie; /* private value */ l_fp tstamp; /* NTP timestamp */ @@ -152,7 +157,7 @@ make_keylist( #ifdef PUBKEY R_SIGNATURE_CTX ctx; /* signature context */ int rval; /* return value */ - u_int32 xpkt[3]; /* data in network byte order */ + u_int len; #endif /* PUBKEY */ /* @@ -161,7 +166,7 @@ make_keylist( L_CLR(&tstamp); if (sys_leap != LEAP_NOTINSYNC) get_systime(&tstamp); - if (peer->keylist == 0) + if (peer->keylist == NULL) peer->keylist = (keyid_t *)emalloc(sizeof(keyid_t) * NTP_MAXSESSION); @@ -188,14 +193,18 @@ make_keylist( ltemp = sys_automax; peer->hcookie = session_key(&peer->dstadr->sin, &peer->srcadr, 0, sys_private, 0); - if (peer->hmode == MODE_BROADCAST) + if (peer->hmode == MODE_BROADCAST) { cookie = 0; - else + } else { #ifdef PUBKEY - cookie = peer->pcookie; + cookie = peer->pcookie.key; #else - cookie = peer->hcookie ^ peer->pcookie; + if (peer->hmode == MODE_CLIENT) + cookie = peer->pcookie.key; + else + cookie = peer->hcookie ^ peer->pcookie.key; #endif /* PUBKEY */ + } for (i = 0; i < NTP_MAXSESSION; i++) { peer->keylist[i] = keyid; peer->keynumber = i; @@ -213,13 +222,15 @@ make_keylist( * then sign these values for later retrieval by the clients. Be * careful not to use invalid key media. */ - peer->sndauto.seq = peer->keynumber; - peer->sndauto.key = keyid; - peer->sndauto.tstamp = tstamp.l_ui; + ap = &peer->sndauto; + ap->tstamp = htonl(tstamp.l_ui); + ap->seq = htonl(peer->keynumber); + ap->key = htonl(keyid); + ap->siglen = 0; #if DEBUG if (debug) - printf("make_keys: %d %08x %u\n", peer->sndauto.seq, - peer->sndauto.key, peer->sndauto.tstamp); + printf("make_keys: %d %08x %08x ts %u\n", ntohl(ap->seq), + ntohl(ap->key), cookie, ntohl(ap->tstamp)); #endif #ifdef PUBKEY if(!crypto_enable) @@ -228,15 +239,12 @@ make_keylist( private_key.bits > MAX_RSA_MODULUS_BITS) { rval = -1; } else { - if (peer->sign == NULL) - peer->sign = emalloc(MAX_SIGNATURE_LEN); - xpkt[0] = htonl(peer->sndauto.seq); - xpkt[1] = htonl(peer->sndauto.key); - xpkt[2] = htonl(peer->sndauto.tstamp); + if (ap->sig == NULL) + ap->sig = emalloc(MAX_SIGNATURE_LEN); R_SignInit(&ctx, DA_MD5); - R_SignUpdate(&ctx, (u_char *)xpkt, 12); - rval = R_SignFinal(&ctx, peer->sign, &peer->signlen, - &private_key); + R_SignUpdate(&ctx, (u_char *)ap, 12); + rval = R_SignFinal(&ctx, ap->sig, &len, &private_key); + ap->siglen = htonl(len); } if (rval != 0) msyslog(LOG_ERR, "make_keylist: signature fails %x", @@ -249,7 +257,9 @@ make_keylist( * crypto_recv - parse extension fields * * This routine is called when the packet has been matched to an - * association and passed sanity, format and authentication checks. + * association and passed sanity, format and authentication checks. We + * believe the extension field values only if the public key is valid + * and the signature has valid length and is verified. */ void crypto_recv( @@ -258,16 +268,21 @@ crypto_recv( ) { u_int32 *pkt; /* packet pointer */ + struct autokey *ap; /* autokey pointer */ + struct cookie *cp; /* cookie pointer */ int has_mac; /* length of MAC field */ int authlen; /* offset of MAC field */ int len; /* extension field length */ u_int code; /* extension field opcode */ + u_int tstamp; /* extension field timestamp */ int i; u_int temp; #ifdef PUBKEY R_SIGNATURE_CTX ctx; /* signature context */ - u_int modulus; /* modulus length */ - int rval; /* return value */ + u_char dh_key[MAX_DH_LEN]; /* Diffie-Hellman agreed key */ + u_int modulus; + int rval; + int j; #endif /* PUBKEY */ /* @@ -280,12 +295,13 @@ crypto_recv( i = authlen / 4; len = ntohl(pkt[i]) & 0xffff; code = (ntohl(pkt[i]) >> 16) & 0xffff; + tstamp = ntohl(pkt[i + 2]); if (code & CRYPTO_RESP) peer->assoc = ntohl(pkt[i + 1]); #ifdef DEBUG if (debug) printf( - "crypto_recv: ext field offset %d length %d code %x assoc ID %d\n", + "crypto_recv: ext offset %d len %d code %x assoc ID %d\n", authlen, len, code, (u_int32)ntohl(pkt[i + 1])); #endif @@ -306,45 +322,43 @@ crypto_recv( * only if the timestamp is nonzero. */ case CRYPTO_AUTO | CRYPTO_RESP: + ap = (struct autokey *)&pkt[i + 2]; #ifdef PUBKEY - temp = ntohl(pkt[i + 6]); + temp = public_key.bits / 8; if (!crypto_enable) { rval = 0; - } else if (temp == 0 || peer->pubkey == NULL) { + } else if (tstamp < peer->recauto.tstamp) { + break; + } else if (peer->pubkey == NULL || temp != + ntohl(ap->siglen)) { rval = -1; } else { R_VerifyInit(&ctx, DA_MD5); - R_VerifyUpdate(&ctx, (char *)&pkt[i + - 3], 12); + R_VerifyUpdate(&ctx, (u_char *)ap, 12); rval = R_VerifyFinal(&ctx, - (char *)&pkt[i + 7], temp, + (u_char *)&ap->sig, temp, (R_RSA_PUBLIC_KEY *)peer->pubkey); } #ifdef DEBUG if (debug) printf( - "crypto_recv: verify %x autokey %d %d %08x %u (%u)\n", - rval, (u_int32)ntohl(pkt[i + 2]), - (u_int32)ntohl(pkt[i + 3]), - (u_int32)ntohl(pkt[i + 4]), - (u_int32)ntohl(pkt[i + 5]), + "crypto_recv: verify %x autokey %d %08x ts %u (%u)\n", + rval, ntohl(ap->seq), + ntohl(ap->key), tstamp, peer->recauto.tstamp); #endif - if (ntohl(pkt[i + 5]) < peer->recauto.tstamp) - break; if (rval != 0) { peer->flags &= ~FLAG_AUTOKEY; break; } - if (ntohl(pkt[i + 5]) != 0) + if (tstamp != 0) peer->flags |= FLAG_AUTOKEY; #endif /* PUBKEY */ peer->flash &= ~TEST10; - peer->recseq = ntohl(pkt[i + 2]); - peer->recauto.seq = ntohl(pkt[i + 3]); - peer->recauto.key = peer->pkeyid = ntohl(pkt[i + - 4]); - peer->recauto.tstamp = ntohl(pkt[i + 5]); + peer->recauto.tstamp = ntohl(ap->tstamp); + peer->recauto.seq = ntohl(ap->seq); + peer->recauto.key = ntohl(ap->key); + peer->pkeyid = peer->recauto.key; break; /* @@ -354,132 +368,148 @@ crypto_recv( * we mark as authentic only if the value is nonzero. */ case CRYPTO_PRIV | CRYPTO_RESP: + cp = (struct cookie *)&pkt[i + 2]; #ifdef PUBKEY - temp = ntohl(pkt[i + 3]); + temp = public_key.bits / 8; if (!crypto_enable) { rval = 0; - temp = ntohl(pkt[i + 2]); - } else if (temp == 0 || peer->pubkey == NULL) { + } else if (tstamp < peer->pcookie.tstamp) { + break; + } else if (peer->pubkey == NULL || temp != + ntohl(cp->siglen)) { rval = -1; - temp = 0; } else { R_VerifyInit(&ctx, DA_MD5); - R_VerifyUpdate(&ctx, (char *)&pkt[i + - 2], 4); + R_VerifyUpdate(&ctx, (u_char *)cp, 8); rval = R_VerifyFinal(&ctx, - (char *)&pkt[i + 4], temp, + (u_char *)&cp->sig, temp, (R_RSA_PUBLIC_KEY *)peer->pubkey); - temp = ntohl(pkt[i + 2]); } + temp = cp->key; #ifdef DEBUG if (debug) printf( - "crypto_recv: verify %x cookie %08x\n", - rval, temp); + "crypto_recv: verify %x cookie %08x ts %u\n", + rval, temp, tstamp); #endif if (rval != 0) { peer->flags &= ~FLAG_AUTOKEY; break; } - if (temp != 0) + if (tstamp != 0) peer->flags |= FLAG_AUTOKEY; #else - temp = ntohl(pkt[i + 2]); + temp = cp->key; #endif /* PUBKEY */ peer->flash &= ~TEST10; - if (temp != peer->pcookie) { + if (temp != peer->pcookie.key) { key_expire(peer); - peer->pcookie = temp; + peer->pcookie.tstamp = tstamp; + peer->pcookie.key = temp; } break; #ifdef PUBKEY /* - * Compute Diffie-Hellman key agreement in symmetric - * modes. We allocate space and save the public value to - * compute the signature later, Then we allocate space - * for the agreed key, run the agreement algorithm and - * stash the key value. We use only the first u_int32 - * for the host cookie. Wasteful. + * Verify Diffie-Hellman public value and compute key + * agreement in symmetric modes. We believe the + * value only if the public key is valid and the + * signature has valid length and is verified. */ case CRYPTO_DH: - temp = ntohl(pkt[i + 2]); - if (temp == 0 || temp != dh_params.primeLen) { + peer->cmmd = ntohl(pkt[i]); + /* fall through */ + + case CRYPTO_DH | CRYPTO_RESP: + temp = ntohl(pkt[i + 3]); + j = i + 4 + temp / 4; + if (tstamp < peer->pcookie.tstamp) { + break; + } else if (peer->pubkey == NULL || + ntohl(pkt[j]) != public_key.bits / 8) { rval = -1; + } else if (temp != dh_params.primeLen || + dh_public == NULL) { + rval = -2; + } else { + R_VerifyInit(&ctx, DA_MD5); + R_VerifyUpdate(&ctx, (u_char *)&pkt[i + + 2], temp + 8); + rval = R_VerifyFinal(&ctx, + (u_char *)&pkt[j + 1], + public_key.bits / 8, + (R_RSA_PUBLIC_KEY *)peer->pubkey); + } + + /* + * Run the agreement algorithm and stash the key + * value. We use only the first u_int32 for the + * host cookie. Wasteful. + */ + if (rval != 0) { temp = 0; } else { - if (peer->dh_public == NULL) - peer->dh_public = - (u_char *)emalloc(temp); - memcpy(peer->dh_public, - (char *)&pkt[i + 3], temp); - if (peer->dh_key == NULL) - peer->dh_key = - (u_char *)emalloc(temp); - rval = R_ComputeDHAgreedKey( - peer->dh_key, peer->dh_public, - dh_private, dh_keyLen, &dh_params); - temp = ntohl(*((u_int *)peer->dh_key)); + rval = R_ComputeDHAgreedKey(dh_key, + (u_char *)&pkt[i + 4], dh_private, + dh_keyLen, &dh_params); + temp = ntohl(*(u_int32 *)dh_key); } #ifdef DEBUG if (debug) printf( - "crypto_recv: d-h agree %x %08x\n", - rval, temp); + "crypto_recv: verify %x d-h %08x ts %u\n", + rval, temp, tstamp); #endif if (rval != 0) { peer->flags &= ~FLAG_AUTOKEY; + peer->cmmd = 0; break; } peer->flash &= ~TEST10; - if (temp != peer->pcookie) - peer->pcookie = 0; - peer->cmmd = ntohl(pkt[i]); + if (temp != peer->pcookie.key) { + key_expire(peer); + peer->pcookie.tstamp = tstamp; + peer->pcookie.key = temp; + } break; /* - * Verify signature of Diffie-Hellman public values in - * symmetric modes. The verification fails if the - * signature length does not match the modulus length or - * any of the public values or the agreed key is not - * valid. + * Receive remote host name and install public key from + * file. */ - case CRYPTO_DH | CRYPTO_RESP: - temp = ntohl(pkt[i + 2]); - if (temp == 0 || temp != dh_params.primeLen || - peer->pubkey == NULL || peer->dh_public == - NULL || dh_public == NULL || peer->dh_key == - NULL) { + case CRYPTO_NAME | CRYPTO_RESP: + temp = ntohl(pkt[i + 3]); + j = i + 4 + temp / 4; + if (tstamp < peer->pcookie.tstamp) { + break; + } else if (ntohl(pkt[j]) != public_key.bits / 8) + { rval = -1; - temp = 0; - } else { + } else if (crypto_public(peer, (char *)&pkt[i + + 4])) { R_VerifyInit(&ctx, DA_MD5); - R_VerifyUpdate(&ctx, - (u_char *)peer->dh_public, - dh_params.primeLen); - R_VerifyUpdate(&ctx, dh_public, - dh_params.primeLen); + + R_VerifyUpdate(&ctx, (char *)&pkt[i + + 2], 8 + temp); + rval = R_VerifyFinal(&ctx, - (u_char *)&pkt[i + 3], temp, + (u_char *)&pkt[j + 1], + public_key.bits / 8, (R_RSA_PUBLIC_KEY *)peer->pubkey); - temp = ntohl(*((u_int *)peer->dh_key)); + if (rval != 0) { + free(peer->pubkey); + peer->pubkey = NULL; + } + } else { + rval = -2; } #ifdef DEBUG if (debug) + printf( - "crypto_recv: d-h verify %x %08x\n", - rval, temp); + "crypto_recv: verify %x host %s ts %u\n", + rval, (char *)&pkt[i + 4], tstamp); #endif - if (rval != 0) { - peer->flags &= ~FLAG_AUTOKEY; - break; - } - peer->flash &= ~TEST10; - peer->flags |= FLAG_AUTOKEY; - if (temp != peer->pcookie) { - key_expire(peer); - peer->pcookie = temp; - } break; /* @@ -508,19 +538,6 @@ crypto_recv( ((R_RSA_PUBLIC_KEY *)peer->pubkey)->modulus, (u_char *)&(pkt[i + 4]), temp); break; - - /* - * Receive remote host name and install public key from - * file. - */ - case CRYPTO_NAME | CRYPTO_RESP: - temp = crypto_public(peer, (char *)&pkt[i + 3]); -#ifdef DEBUG - if (debug) - printf("crypto_recv: host %d %s\n", - temp, (char *)&pkt[i + 3]); -#endif - break; #endif /* PUBKEY */ /* @@ -558,13 +575,17 @@ crypto_xmit( ) { struct peer *peer; /* peer structure pointer */ + struct autokey *ap; /* autokey pointer */ + struct cookie *cp; /* cookie pointer */ int len; /* extension field length */ u_int opcode; /* extension field opcode */ int i; #ifdef PUBKEY R_SIGNATURE_CTX ctx; /* signature context */ + struct value *vp; /* value pointer */ int rval; /* return value */ u_int temp; + int j; #endif /* PUBKEY */ /* @@ -586,11 +607,7 @@ crypto_xmit( /* * Find peer and send autokey data and signature in broadcast - * server and symmetric modes. We send the data only if the peer - * exists and the make_keylist routine has previously - * constructed the list and successfully signed the data. Note - * that the timestamp is zero if the server has not - * synchronized. + * server and symmetric modes. */ case CRYPTO_AUTO | CRYPTO_RESP: peer = findpeerbyassoc(associd); @@ -598,108 +615,102 @@ crypto_xmit( opcode |= CRYPTO_ERROR; break; } - xpkt[i + 2] = htonl(peer->keynumber); - xpkt[i + 3] = htonl(peer->sndauto.seq); - xpkt[i + 4] = htonl(peer->sndauto.key); - xpkt[i + 5] = htonl(peer->sndauto.tstamp); - xpkt[i + 6] = 0; - len += 20; + ap = (struct autokey *)&xpkt[i + 2]; + ap->tstamp = peer->sndauto.tstamp; + ap->seq = peer->sndauto.seq; + ap->key = peer->sndauto.key; + ap->siglen = 0; + len += 16; #ifdef PUBKEY - if (peer->signlen == 0) + if (!crypto_enable) break; - xpkt[i + 6] = htonl(peer->signlen); - memcpy((u_char *)&xpkt[i + 7], peer->sign, - peer->signlen); - len += peer->signlen; + ap->siglen = peer->sndauto.siglen; + temp = ntohl(peer->sndauto.siglen); + if (temp > 0) + memcpy(&ap->sig, peer->sndauto.sig, temp); + len += temp; #endif /* PUBKEY */ break; /* - * Send peer cookie and signature in server mode. We send the - * signature only if the private key exists and is valid. Note - * that the cookie is zero of the server has not synchronized. + * Send peer cookie and signature in server mode. */ case CRYPTO_PRIV | CRYPTO_RESP: - xpkt[i + 2] = 0; - if (sys_leap != LEAP_NOTINSYNC) - xpkt[i + 2] = htonl(cookie); - xpkt[i + 3] = 0; - len += 8; + cp = (struct cookie *)&xpkt[i + 2]; + cp->tstamp = htonl(sys_revoketime.l_ui); + cp->key = htonl(cookie); + cp->siglen = 0; + len += 12; #ifdef PUBKEY + if (!crypto_enable) + break; + cp->siglen = htonl(public_key.bits / 8); if (private_key.bits < MIN_RSA_MODULUS_BITS || private_key.bits > MAX_RSA_MODULUS_BITS) { rval = -1; } else { R_SignInit(&ctx, DA_MD5); - R_SignUpdate(&ctx, (u_char *)&xpkt[i + 2], 4); - rval = R_SignFinal(&ctx, (u_char *)&xpkt[i + 4], + R_SignUpdate(&ctx, (u_char *)cp, 8); + rval = R_SignFinal(&ctx, (u_char *)&cp->sig, &temp, &private_key); } if (rval != 0) { + cp->siglen = 0; msyslog(LOG_ERR, - "crypto_xmit: signature fails %x", rval); + "crypto_xmit: cookie signature fails %x", + rval); break; } - xpkt[i + 3] = htonl(temp); len += temp; #endif /* PUBKEY */ break; #ifdef PUBKEY /* - * Send Diffie-Hellman public value in symmetric modes. We send - * only if the parameters have been initialized and the - * public/private values have been set up. + * Send Diffie-Hellman public value, timestamp and signature. */ case CRYPTO_DH: - xpkt[i + 2] = 0; - len += 4; - if (dh_params.primeLen == 0 || dh_public == NULL) + case CRYPTO_DH | CRYPTO_RESP: + vp = (struct value *)&xpkt[i + 2]; + vp->tstamp = htonl(sys_revoketime.l_ui); + vp->vallen = 0; + len += 8; + temp = dh_params.primeLen; + if (dh_sign == NULL) break; - xpkt[i + 2] = htonl(dh_params.primeLen); - memcpy((u_char *)&xpkt[i + 3], dh_public, - dh_params.primeLen); - len += dh_params.primeLen; + vp->vallen = htonl(temp); + memcpy((u_char *)&vp->val, dh_public, temp); + len += temp; + j = i + 4 + temp / 4; + temp = public_key.bits / 8; + xpkt[j++] = htonl(temp); + memcpy((u_char *)&xpkt[j], dh_sign, temp); + len += temp + 4; break; /* - * Find peer and send signature of Diffie-Hellman public values - * in symmetric modes. We send only if the public key exists and - * is valid and the public values exist. + * Send host name, timestamp and signature. */ - case CRYPTO_DH | CRYPTO_RESP: - peer = findpeerbyassoc(associd); - if (peer == NULL) { - opcode |= CRYPTO_ERROR; - break; - } - xpkt[i + 2] = 0; - len += 4; - if (private_key.bits < MIN_RSA_MODULUS_BITS || - private_key.bits > MAX_RSA_MODULUS_BITS || - dh_public == NULL || peer->dh_public == NULL) { - rval = -1; - } else { - R_SignInit(&ctx, DA_MD5); - R_SignUpdate(&ctx, dh_public, - dh_params.primeLen); - R_SignUpdate(&ctx, (u_char *)peer->dh_public, - dh_params.primeLen); - rval = R_SignFinal(&ctx, (u_char *)&xpkt[i + 3], - &temp, &private_key); - } - if (rval != 0) { - msyslog(LOG_ERR, - "crypto_xmit: signature fails %x", rval); + case CRYPTO_NAME | CRYPTO_RESP: + vp = (struct value *)&xpkt[i + 2]; + vp->tstamp = htonl(sys_revoketime.l_ui); + vp->vallen = host.vallen; + len += 8; + temp = ntohl(host.vallen); + if (temp == 0) break; - } - xpkt[i + 2] = htonl(temp); + memcpy((u_char *)&vp->val, host.val, temp); len += temp; + j = i + 4 + temp / 4; + temp = public_key.bits / 8; + xpkt[j++] = htonl(temp); + memcpy((u_char *)&xpkt[j], host.sig, temp); + len += temp + 4; break; /* * Send public key. We send the public key only if it exists and - * is valid. This is used in all modes, primarily for testing. + * is valid. This is used primarily for testing. */ case CRYPTO_PUBL | CRYPTO_RESP: xpkt[i + 2] = 0; @@ -714,16 +725,6 @@ crypto_xmit( (u_char *)&public_key.modulus, temp); len += temp + 4; break; - - /* - * Send host name. - */ - case CRYPTO_NAME | CRYPTO_RESP: - gethostname((char *)&xpkt[i + 3], MAXFILENAME); - temp = strlen((char *)&xpkt[i + 3]); - xpkt[i + 2] = htonl(temp); - len += temp + 4; - break; #endif /* PUBKEY */ /* @@ -746,7 +747,7 @@ crypto_xmit( #ifdef DEBUG if (debug) printf( - "crypto_xmit: ext field offset %d length %d code %x assoc ID %d\n", + "crypto_xmit: ext offset %d len %d code %x assoc ID %d\n", start, len, code, associd); #endif } @@ -755,6 +756,91 @@ crypto_xmit( #ifdef PUBKEY +/* + * crypto_agree - compute public and private Diffie-Hellman values from + * given prime and generator, then sign with private key. + */ +void +crypto_agree(void) +{ + u_int len, temp; + R_RANDOM_STRUCT randomstr; + R_SIGNATURE_CTX ctx; /* signature context */ + int rval; + int i; + + /* + * Sign host name and timestamp. + */ + host.tstamp = htonl(sys_revoketime.l_ui); + host.vallen = htonl(sys_hostnamelen); + host.val = sys_hostname; + host.siglen = dh_params.primeLen; + if (host.sig == NULL) + host.sig = emalloc(dh_params.primeLen); + R_SignInit(&ctx, DA_MD5); + R_SignUpdate(&ctx, (u_char *)&host, 8); + R_SignUpdate(&ctx, host.val, sys_hostnamelen); + rval = R_SignFinal(&ctx, host.sig, &temp, &private_key); + if (rval != 0) { + msyslog(LOG_ERR, + "crypto_agree: host signature fails %x", rval); + return; + } + + /* + * Compute Diffie-Hellman public value. Note that the length of + * the private value is set arbitrarily to half the prime + * length. + */ + if (dh_params.primeLen == 0) { + msyslog(LOG_ERR, + "unavailable d-h parameters"); + return; + } + R_RandomInit(&randomstr); + R_GetRandomBytesNeeded(&len, &randomstr); + for (i = 0; i < len; i++) { + temp = random(); + R_RandomUpdate(&randomstr, (u_char *)&temp, 1); + } + if (dh_private == NULL) + dh_private = (u_char *)emalloc(dh_keyLen); + if (dh_public == NULL) + dh_public = (u_char *)emalloc(dh_params.primeLen); + rval = R_SetupDHAgreement(dh_public, dh_private, dh_keyLen, + &dh_params, &randomstr); + if (rval != 0) { + msyslog(LOG_ERR, "invalid d-h parameters"); + return; + } + + /* + * Sigfie-Hellman public value and save for later. + */ + if (dh_sign == NULL) + dh_sign = emalloc(dh_params.primeLen); + R_SignInit(&ctx, DA_MD5); + R_SignUpdate(&ctx, (char *)&host.tstamp, 4); + temp = htonl(dh_params.primeLen); + R_SignUpdate(&ctx, (char *)&temp, 4); + R_SignUpdate(&ctx, dh_public, dh_params.primeLen); + rval = R_SignFinal(&ctx, dh_sign, &temp, &private_key); + if (rval != 0) { + msyslog(LOG_ERR, + "crypto_agree: d-h signature fails %x", rval); + return; + } +#ifdef DEBUG + if (debug) + printf( + "cypto_agree: host %s d-h prime %d gen %d\n", + host.val, dh_params.primeLen, + dh_params.generatorLen); +#endif +} + + /* * crypto_read - read RSA key, decode and check for errors */ @@ -784,7 +870,8 @@ crypto_read( } else if (*cp == '/') { strcpy(filename, cp); } else { - snprintf(filename, sizeof filename, "%s%s", keysdir, cp); + snprintf(filename, MAXFILENAME - 1, "%s%s", keysdir, + cp); } str = fopen(filename, "r"); if (str == NULL) { @@ -873,7 +960,7 @@ crypto_public( u_int keylen = sizeof(R_RSA_PUBLIC_KEY); char filename[MAXFILENAME]; - snprintf(filename, sizeof filename, "ntpkey_%s", cp); + snprintf(filename, MAXFILENAME - 1, "ntpkey_%s", cp); if (!crypto_read(filename, (u_char *)&keybuf, keylen)) return (0); if (peer->keystr != NULL) @@ -906,7 +993,7 @@ crypto_line( /* * Read key and length. Bail out if the length word doesn't - * match the decoded string length. + * match the decoded string length and in other cases. */ *key = NULL; *len = 0; @@ -919,6 +1006,8 @@ crypto_line( } if (sscanf(buf, "%d %s", &temp, encoded_key) != 2) return; + if (temp > MAX_DH_LEN) + return; temp2 = DECODED_CONTENT_LEN(strlen(encoded_key)); if (R_DecodePEMBlock(buf, &temp1, encoded_key, strlen(encoded_key))) @@ -957,7 +1046,7 @@ crypto_setup(void) */ if (public_key_file == NULL) { gethostname(hostname, MAXFILENAME); - snprintf(filename, sizeof filename, "ntpkey_%s", + snprintf(filename, MAXFILENAME - 1, "ntpkey_%s", hostname); public_key_file = emalloc(strlen(filename) + 1); strcpy(public_key_file, filename); @@ -973,7 +1062,7 @@ crypto_setup(void) if (*dh_params_file == '/') strcpy(filename, dh_params_file); else - snprintf(filename, sizeof filename, "%s%s", keysdir, + snprintf(filename, MAXFILENAME - 1, "%s%s", keysdir, dh_params_file); str = fopen(filename, "r"); @@ -998,47 +1087,6 @@ crypto_setup(void) } -/* - * crypto_agree - compute public and private Diffie-Hellman values from - * given prime and generator. - */ -void -crypto_agree(void) -{ - R_RANDOM_STRUCT randomstr; - u_int len, temp; - int rval, i; - - /* - * Note that the length of the private value is set arbitrarily - * to half the prime length. - */ - if (dh_params.primeLen == 0) - return; - R_RandomInit(&randomstr); - R_GetRandomBytesNeeded(&len, &randomstr); - for (i = 0; i < len; i++) { - temp = random(); - R_RandomUpdate(&randomstr, (u_char *)&temp, 1); - } - if (dh_private == NULL) - dh_private = (u_char *)emalloc(dh_keyLen); - if (dh_public == NULL) - dh_public = (u_char *)emalloc(dh_params.primeLen); - rval = R_SetupDHAgreement(dh_public, dh_private, dh_keyLen, - &dh_params, &randomstr); - if (rval != 0) - msyslog(LOG_ERR, "invalid Diffie-Hellman parameters"); -#ifdef DEBUG - if (debug) - printf( - "cypto_init: Diffie-Hellman prime %d generator %d key %d\n", - dh_params.primeLen, dh_params.generatorLen, - dh_keyLen); -#endif -} - - /* * crypto_config - configure crypto data. */ @@ -1103,6 +1151,7 @@ crypto_init(void) memset((char *)&private_key, 0, sizeof(private_key)); memset((char *)&public_key, 0, sizeof(public_key)); memset((char *)&dh_params, 0, sizeof(dh_params)); + memset((char *)&host, 0, sizeof(host)); } #endif /* PUBKEY */ #endif /* AUTOKEY */ diff --git a/ntpd/ntp_peer.c b/ntpd/ntp_peer.c index d614d8e488..ad0caca25b 100644 --- a/ntpd/ntp_peer.c +++ b/ntpd/ntp_peer.c @@ -10,9 +10,9 @@ #include "ntpd.h" #include "ntp_stdlib.h" -#ifdef PUBKEY +#ifdef AUTOKEY #include "ntp_crypto.h" -#endif /* PUBKEY */ +#endif /* AUTOKEY */ /* * Table of valid association combinations @@ -366,14 +366,13 @@ findmanycastpeer( return manycast_peer; } -#ifdef AUTOKEY + /* - * key_expire - expire all keys and roll a new private value. Note the - * 32-bit mask is necessary for 64-bit u_ints. + * clear_all - flush all time values and refresh Diffie-Hellman public + * value. */ void -key_expire_all( - ) +clear_all(void) { struct peer *peer, *next_peer; int n; @@ -384,18 +383,46 @@ key_expire_all( peer_clear(peer); } } +#ifdef DEBUG + if (debug) + printf("clear_all: at %lu\n", current_time); +#endif +} + + +#ifdef AUTOKEY +/* + * expire_all - flush all crypto data and update timestamp + */ +void +expire_all(void) +{ + struct peer *peer, *next_peer; + int n; + + for (n = 0; n < HASH_SIZE; n++) { + for (peer = peer_hash[n]; peer != 0; peer = next_peer) { + next_peer = peer->next; + key_expire(peer); + peer->pcookie.tstamp = 0; + } + } sys_private = (u_int32)RANDOM & 0xffffffff; + L_CLR(&sys_revoketime); + if (sys_leap != LEAP_NOTINSYNC) + get_systime(&sys_revoketime); #ifdef PUBKEY - crypto_agree(); + if (crypto_enable) + crypto_agree(); #endif /* PUBKEY */ #ifdef DEBUG if (debug) - printf("key_expire_all: at %lu private %08x next %lu\n", - current_time, sys_private, current_time + sys_revoke); + printf("expire_all: at %lu\n", current_time); #endif } #endif /* AUTOKEY */ + /* * unpeer - remove peer structure from hash table and free structure */ diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index 31f88029b3..a49495e47c 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -54,6 +54,10 @@ static double sys_maxd; /* select error (squares) */ static double sys_epsil; /* system error (squares) */ keyid_t sys_private; /* private value for session seed */ int sys_manycastserver; /* 1 => respond to manycast client pkts */ +#ifdef AUTOKEY +char *sys_hostname; /* gethostname() name */ +u_int sys_hostnamelen; /* name length (round to word) */ +#endif /* AUTOKEY */ /* * Statistics counters @@ -405,23 +409,34 @@ receive( * packets, the cookie was previously obtained * from the server. For symmetric modes, the * cookie was previously constructed using an - * agreement protocol. + * agreement protocol; however, should PKI be + * unavailable, we construct a fake agreement as + * the EXOR of the peer and host cookies. */ - if (hismode == MODE_BROADCAST) + if (hismode == MODE_BROADCAST) { pkeyid = 0; - else if (peer == 0) + } else if (peer == 0) { pkeyid = session_key( &rbufp->recv_srcadr, &rbufp->dstadr->sin, 0, sys_private, 0); - else if (hismode == MODE_CLIENT) + } else if (hismode == MODE_CLIENT) { pkeyid = peer->hcookie; - else + } else { #ifdef PUBKEY - pkeyid = peer->pcookie; + if (crypto_enable) + pkeyid = peer->pcookie.key; + else + pkeyid = peer->pcookie.key; + #else - pkeyid = peer->hcookie ^ peer->pcookie; + if (hismode == MODE_SERVER) + pkeyid = peer->pcookie.key; + else + pkeyid = peer->hcookie ^ + peer->pcookie.key; #endif /* PUBKEY */ + } /* * The session key includes both the public @@ -680,10 +695,21 @@ receive( (restrict_mask & RES_DONTTRUST)) /* test 9 */ peer->flash |= TEST9; /* access denied */ if (peer->flags & FLAG_AUTHENABLE) { + + /* + * Here we have a little bit of nastyness. Should + * authentication fail in client mode, it could either + * be a hacker attempting to jam the protocol, or it + * could be the server has just refreshed its keys. On + * the premiss the later is more likely than the former + * and that even the former can't do real evil, we + * simply ask for the cookie again. + */ if (!(peer->flags & FLAG_AUTHENTIC)) { /* test 5 */ peer->flash |= TEST5; /* auth failed */ #ifdef AUTOKEY - peer->pcookie = 0; + if (hismode == MODE_SERVER) + peer->pcookie.tstamp = 0; #endif /* AUTOKEY */ } else if (!(oflags & FLAG_AUTHENABLE)) { report_event(EVNT_PEERAUTH, peer); @@ -723,8 +749,6 @@ receive( } else if (hismode == MODE_SERVER) { if (skeyid == peer->keyid) peer->flash &= ~TEST10; - else - peer->hcookie = 0; } else { int i = 0; @@ -979,8 +1003,6 @@ clock_update(void) { u_char oleap; u_char ostratum; - int i; - struct peer *peer; /* * Reset/adjust the system clock. Do this only if there is a @@ -1001,24 +1023,19 @@ clock_update(void) ostratum = sys_stratum; switch (local_clock(sys_peer, sys_offset, sys_epsil)) { - case -1: - /* - * Clock is too screwed up. Just exit for now. - */ + /* + * Clock is too screwed up. Just exit for now. + */ + case -1: report_event(EVNT_SYSFAULT, (struct peer *)0); exit(1); /*NOTREACHED*/ - case 1: - /* - * Clock was stepped. Clear filter registers - * of all peers. - */ - for (i = 0; i < HASH_SIZE; i++) { - for (peer = peer_hash[i]; peer != 0; - peer =peer->next) - peer_clear(peer); - } + /* + * Clock was stepped. Flush all time values of all peers. + */ + case 1: + clear_all(); NLOG(NLOG_SYNCSTATUS) msyslog(LOG_INFO, "synchronisation lost"); sys_peer = 0; @@ -1026,13 +1043,13 @@ clock_update(void) report_event(EVNT_CLOCKRESET, (struct peer *)0); break; - default: - /* - * Update the system stratum, leap bits, root delay, - * root dispersion, reference ID and reference time. We - * also update select dispersion and max frequency - * error. - */ + /* + * Update the system stratum, leap bits, root delay, root + * dispersion, reference ID and reference time. We also update + * select dispersion and max frequency error. If the leap + * changes, we gotta reroll the keys. + */ + default: sys_stratum = sys_peer->stratum + 1; if (sys_stratum == 1) sys_refid = sys_peer->refid; @@ -1042,16 +1059,11 @@ clock_update(void) sys_rootdelay = sys_peer->rootdelay + fabs(sys_peer->delay); sys_leap = leap_consensus; - - /* - * This is cute. If the leap changes, we gotta reroll - * the keys. - */ - if (sys_leap != oleap) - key_expire_all(); } - if (oleap != sys_leap) + if (oleap != sys_leap) { report_event(EVNT_SYNCCHG, (struct peer *)0); + expire_all(); + } if (ostratum != sys_stratum) report_event(EVNT_PEERSTCHG, (struct peer *)0); } @@ -1148,14 +1160,6 @@ peer_clear( #endif #ifdef AUTOKEY key_expire(peer); -#ifdef PUBKEY - if (peer->sign != NULL) - free(peer->sign); - if (peer->dh_public != NULL) - free(peer->dh_public); - if (peer->dh_key != NULL) - free(peer->dh_key); -#endif /* PUBKEY */ #endif /* AUTOKEY */ /* @@ -1180,15 +1184,6 @@ peer_clear( peer->filter_epoch[i] = current_time; } poll_update(peer, peer->minpoll); - - /* - * Since we have a chance to correct possible funniness in - * our selection of interfaces on a multihomed host, do so - * by setting us to no particular interface. - * WARNING: do so only in non-broadcast mode! - */ - if (peer->hmode != MODE_BROADCAST) - peer->dstadr = any_interface; } @@ -1859,7 +1854,7 @@ peer_xmit( * are contained in extension fields, each including a * 4-octet length/code word followed by a 4-octet * association ID and optional additional data. Optional - * data includes a 4-octet data length field followd by + * data includes a 4-octet data length field followed by * the data itself. Request messages are sent from a * configured association; response messages can be sent * from a configured association or can take the fast @@ -1955,8 +1950,7 @@ peer_xmit( case MODE_ACTIVE: case MODE_PASSIVE: #ifdef PUBKEY - if (crypto_enable && peer->cmmd != 0 && - peer->cmmd >> 16 != CRYPTO_DH) { + if (crypto_enable && peer->cmmd != 0) { sendlen += crypto_xmit((u_int32 *)&xpkt, sendlen, (peer->cmmd >> 16) | CRYPTO_RESP, peer->hcookie, @@ -1968,29 +1962,11 @@ peer_xmit( sendlen += crypto_xmit((u_int32 *)&xpkt, sendlen, CRYPTO_NAME, peer->hcookie, peer->assoc); - } else -#endif /* PUBKEY */ - if (peer->recauto.tstamp == 0) { - sendlen += crypto_xmit((u_int32 *)&xpkt, - sendlen, CRYPTO_AUTO, peer->hcookie, - peer->assoc); - } else if (peer->keynumber == peer->sndauto.seq) - { - sendlen += crypto_xmit((u_int32 *)&xpkt, - sendlen, CRYPTO_AUTO | CRYPTO_RESP, - peer->hcookie, peer->associd); -#ifdef PUBKEY - } else if (peer->pcookie == 0) { + } else if (peer->pcookie.tstamp == 0) { sendlen += crypto_xmit((u_int32 *)&xpkt, sendlen, CRYPTO_DH, peer->hcookie, peer->assoc); #else - } else if (peer->pcookie == 0) { - sendlen += crypto_xmit((u_int32 *)&xpkt, - sendlen, CRYPTO_PRIV, peer->hcookie, - peer->assoc); -#endif /* PUBKEY */ - } if (peer->cmmd != 0) { sendlen += crypto_xmit((u_int32 *)&xpkt, sendlen, (peer->cmmd >> 16) | @@ -1998,6 +1974,21 @@ peer_xmit( peer->associd); peer->cmmd = 0; } + if (peer->pcookie.tstamp == 0) { + sendlen += crypto_xmit((u_int32 *)&xpkt, + sendlen, CRYPTO_PRIV, peer->hcookie, + peer->assoc); +#endif /* PUBKEY */ + } else if (peer->recauto.tstamp == 0) { + sendlen += crypto_xmit((u_int32 *)&xpkt, + sendlen, CRYPTO_AUTO, peer->hcookie, + peer->assoc); + } else if (peer->keynumber == peer->sndauto.seq) + { + sendlen += crypto_xmit((u_int32 *)&xpkt, + sendlen, CRYPTO_AUTO | CRYPTO_RESP, + peer->hcookie, peer->associd); + } break; /* @@ -2007,7 +1998,8 @@ peer_xmit( * client/server exchange to avoid having to wait until * the next key list regeneration. Otherwise, the poor * dude may die a lingering death until becoming - * unreachable and attempting rebirth. + * unreachable and attempting rebirth. Note that we ask + * for the cookie at each key list regeneration anyway. */ case MODE_CLIENT: if (peer->cmmd != 0) { @@ -2025,7 +2017,8 @@ peer_xmit( peer->assoc); } else #endif /* PUBKEY */ - if (peer->pcookie == 0) { + if (peer->pcookie.tstamp == 0 || + peer->keynumber == peer->sndauto.seq) { sendlen += crypto_xmit((u_int32 *)&xpkt, sendlen, CRYPTO_PRIV, peer->hcookie, peer->assoc); diff --git a/ntpd/ntp_timer.c b/ntpd/ntp_timer.c index 8d0e128127..af68c9ef7f 100644 --- a/ntpd/ntp_timer.c +++ b/ntpd/ntp_timer.c @@ -10,7 +10,7 @@ #include #include #include - +#include #include "ntp_machine.h" #include "ntpd.h" #include "ntp_stdlib.h" @@ -19,6 +19,10 @@ # include "ntp_timer.h" #endif +#ifdef PUBKEY +#include "ntp_crypto.h" +#endif /* PUBKEY */ + /* * These routines provide support for the event timer. The timer is * implemented by an interrupt routine which sets a flag once every @@ -44,6 +48,7 @@ static u_long hourly_timer; /* hour timer */ #ifdef AUTOKEY static u_long revoke_timer; /* keys revoke timer */ u_long sys_revoke = 1 << KEY_REVOKE; /* keys revoke timeout */ +l_fp sys_revoketime; /* last key revoke time */ #endif /* AUTOKEY */ /* @@ -208,7 +213,7 @@ void timer(void) { register struct peer *peer, *next_peer; - int n; + u_int n; current_time += (1<