diff options
Diffstat (limited to 'contrib/ntp/libntp')
-rw-r--r-- | contrib/ntp/libntp/Makefile.am | 1 | ||||
-rw-r--r-- | contrib/ntp/libntp/Makefile.in | 22 | ||||
-rw-r--r-- | contrib/ntp/libntp/a_md5encrypt.c | 4 | ||||
-rw-r--r-- | contrib/ntp/libntp/authkeys.c | 326 | ||||
-rw-r--r-- | contrib/ntp/libntp/authreadkeys.c | 103 | ||||
-rw-r--r-- | contrib/ntp/libntp/is_ip_address.c | 40 | ||||
-rw-r--r-- | contrib/ntp/libntp/ntp_intres.c | 48 | ||||
-rw-r--r-- | contrib/ntp/libntp/ntp_worker.c | 2 | ||||
-rw-r--r-- | contrib/ntp/libntp/recvbuff.c | 28 | ||||
-rw-r--r-- | contrib/ntp/libntp/work_fork.c | 7 | ||||
-rw-r--r-- | contrib/ntp/libntp/work_thread.c | 23 |
11 files changed, 332 insertions, 272 deletions
diff --git a/contrib/ntp/libntp/Makefile.am b/contrib/ntp/libntp/Makefile.am index a3b50e1..26a4709 100644 --- a/contrib/ntp/libntp/Makefile.am +++ b/contrib/ntp/libntp/Makefile.am @@ -36,6 +36,7 @@ libisc_SRCS = \ $(srcdir)/../lib/isc/unix/time.c \ $(srcdir)/../lib/isc/sha1.c \ $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c \ $(NULL) if PTHREADS diff --git a/contrib/ntp/libntp/Makefile.in b/contrib/ntp/libntp/Makefile.in index 5cf5703..9125c19 100644 --- a/contrib/ntp/libntp/Makefile.in +++ b/contrib/ntp/libntp/Makefile.in @@ -182,6 +182,7 @@ am__libntp_a_SOURCES_DIST = systime.c a_md5encrypt.c adjtime.c \ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \ $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c \ $(srcdir)/../lib/isc/pthreads/mutex.c am__objects_1 = @PTHREADS_TRUE@am__objects_2 = mutex.$(OBJEXT) @@ -196,7 +197,7 @@ am__objects_3 = assertions.$(OBJEXT) buffer.$(OBJEXT) \ result.$(OBJEXT) stdio.$(OBJEXT) stdtime.$(OBJEXT) \ strerror.$(OBJEXT) task.$(OBJEXT) thread.$(OBJEXT) \ time.$(OBJEXT) sha1.$(OBJEXT) sockaddr.$(OBJEXT) \ - $(am__objects_1) $(am__objects_2) + tsmemcmp.$(OBJEXT) $(am__objects_1) $(am__objects_2) am__objects_4 = a_md5encrypt.$(OBJEXT) adjtime.$(OBJEXT) \ atoint.$(OBJEXT) atolfp.$(OBJEXT) atouint.$(OBJEXT) \ audio.$(OBJEXT) authkeys.$(OBJEXT) authreadkeys.$(OBJEXT) \ @@ -264,6 +265,7 @@ am__libntpsim_a_SOURCES_DIST = systime_s.c a_md5encrypt.c adjtime.c \ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \ $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c \ $(srcdir)/../lib/isc/pthreads/mutex.c am_libntpsim_a_OBJECTS = systime_s.$(OBJEXT) $(am__objects_4) libntpsim_a_OBJECTS = $(am_libntpsim_a_OBJECTS) @@ -631,7 +633,8 @@ libisc_SRCS = $(srcdir)/../lib/isc/assertions.c \ $(srcdir)/../lib/isc/task.c \ $(srcdir)/../lib/isc/$(LIBISC_PTHREADS_NOTHREADS)/thread.c \ $(srcdir)/../lib/isc/unix/time.c $(srcdir)/../lib/isc/sha1.c \ - $(srcdir)/../lib/isc/sockaddr.c $(NULL) $(am__append_1) + $(srcdir)/../lib/isc/sockaddr.c \ + $(srcdir)/../lib/isc/tsmemcmp.c $(NULL) $(am__append_1) libntp_a_SRCS = \ a_md5encrypt.c \ adjtime.c \ @@ -862,6 +865,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timetoa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timevalops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsmemcmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uglydate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vint64ops.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/work_fork.Po@am__quote@ @@ -1323,6 +1327,20 @@ sockaddr.obj: $(srcdir)/../lib/isc/sockaddr.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.obj `if test -f '$(srcdir)/../lib/isc/sockaddr.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/sockaddr.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/sockaddr.c'; fi` +tsmemcmp.o: $(srcdir)/../lib/isc/tsmemcmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsmemcmp.o -MD -MP -MF $(DEPDIR)/tsmemcmp.Tpo -c -o tsmemcmp.o `test -f '$(srcdir)/../lib/isc/tsmemcmp.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/tsmemcmp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tsmemcmp.Tpo $(DEPDIR)/tsmemcmp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/tsmemcmp.c' object='tsmemcmp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsmemcmp.o `test -f '$(srcdir)/../lib/isc/tsmemcmp.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/tsmemcmp.c + +tsmemcmp.obj: $(srcdir)/../lib/isc/tsmemcmp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsmemcmp.obj -MD -MP -MF $(DEPDIR)/tsmemcmp.Tpo -c -o tsmemcmp.obj `if test -f '$(srcdir)/../lib/isc/tsmemcmp.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/tsmemcmp.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/tsmemcmp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tsmemcmp.Tpo $(DEPDIR)/tsmemcmp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../lib/isc/tsmemcmp.c' object='tsmemcmp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsmemcmp.obj `if test -f '$(srcdir)/../lib/isc/tsmemcmp.c'; then $(CYGPATH_W) '$(srcdir)/../lib/isc/tsmemcmp.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../lib/isc/tsmemcmp.c'; fi` + mutex.o: $(srcdir)/../lib/isc/pthreads/mutex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mutex.o -MD -MP -MF $(DEPDIR)/mutex.Tpo -c -o mutex.o `test -f '$(srcdir)/../lib/isc/pthreads/mutex.c' || echo '$(srcdir)/'`$(srcdir)/../lib/isc/pthreads/mutex.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mutex.Tpo $(DEPDIR)/mutex.Po diff --git a/contrib/ntp/libntp/a_md5encrypt.c b/contrib/ntp/libntp/a_md5encrypt.c index beaf6fd..618ccd9 100644 --- a/contrib/ntp/libntp/a_md5encrypt.c +++ b/contrib/ntp/libntp/a_md5encrypt.c @@ -10,7 +10,7 @@ #include "ntp_stdlib.h" #include "ntp.h" #include "ntp_md5.h" /* provides OpenSSL digest API */ - +#include "isc/string.h" /* * MD5authencrypt - generate message digest * @@ -92,7 +92,7 @@ MD5authdecrypt( "MAC decrypt: MAC length error"); return (0); } - return !memcmp(digest, (const char *)pkt + length + 4, len); + return !isc_tsmemcmp(digest, (const char *)pkt + length + 4, len); } /* diff --git a/contrib/ntp/libntp/authkeys.c b/contrib/ntp/libntp/authkeys.c index 36fdd8b..51337d5 100644 --- a/contrib/ntp/libntp/authkeys.c +++ b/contrib/ntp/libntp/authkeys.c @@ -30,7 +30,7 @@ struct savekey { u_long lifetime; /* remaining lifetime */ keyid_t keyid; /* key identifier */ u_short type; /* OpenSSL digest NID */ - u_short secretsize; /* secret octets */ + size_t secretsize; /* secret octets */ u_short flags; /* KEY_ flags that wave */ }; @@ -51,12 +51,12 @@ symkey_alloc * authallocs; #endif /* DEBUG */ static u_short auth_log2(size_t); -static void auth_resize_hashtable(void); -static void allocsymkey(symkey **, keyid_t, u_short, u_short, - u_long, u_short, u_char *, KeyAccT *); -static void freesymkey(symkey *, symkey **); +static void auth_resize_hashtable(void); +static void allocsymkey(keyid_t, u_short, + u_short, u_long, size_t, u_char *, KeyAccT *); +static void freesymkey(symkey *); #ifdef DEBUG -static void free_auth_mem(void); +static void free_auth_mem(void); #endif symkey key_listhead; /* list of all in-use keys */; @@ -93,14 +93,87 @@ int authnumfreekeys; /* * The key cache. We cache the last key we looked at here. + * Note: this should hold the last *trusted* key. Also the + * cache is only loaded when the digest type / MAC algorithm + * is valid. */ keyid_t cache_keyid; /* key identifier */ u_char *cache_secret; /* secret */ -u_short cache_secretsize; /* secret length */ +size_t cache_secretsize; /* secret length */ int cache_type; /* OpenSSL digest NID */ u_short cache_flags; /* flags that wave */ KeyAccT *cache_keyacclist; /* key access list */ +/* -------------------------------------------------------------------- + * manage key access lists + * -------------------------------------------------------------------- + */ +/* allocate and populate new access node and pushes it on the list. + * Returns the new head. + */ +KeyAccT* +keyacc_new_push( + KeyAccT * head, + const sockaddr_u * addr + ) +{ + KeyAccT * node = emalloc(sizeof(KeyAccT)); + + memcpy(&node->addr, addr, sizeof(sockaddr_u)); + node->next = head; + return node; +} + +/* ----------------------------------------------------------------- */ +/* pop and deallocate the first node of a list of access nodes, if + * the list is not empty. Returns the tail of the list. + */ +KeyAccT* +keyacc_pop_free( + KeyAccT *head + ) +{ + KeyAccT * next = NULL; + if (head) { + next = head->next; + free(head); + } + return next; +} + +/* ----------------------------------------------------------------- */ +/* deallocate the list; returns an empty list. */ +KeyAccT* +keyacc_all_free( + KeyAccT * head + ) +{ + while (head) + head = keyacc_pop_free(head); + return head; +} + +/* ----------------------------------------------------------------- */ +/* scan a list to see if it contains a given address. Return the + * default result value in case of an empty list. + */ +int /*BOOL*/ +keyacc_contains( + const KeyAccT *head, + const sockaddr_u *addr, + int defv) +{ + if (head) { + do { + if (SOCK_EQ(&head->addr, addr)) + return TRUE; + } while (NULL != (head = head->next)); + return FALSE; + } else { + return !!defv; + } +} + /* * init_auth - initialize internal data @@ -139,7 +212,7 @@ free_auth_mem(void) symkey_alloc * next_alloc; while (NULL != (sk = HEAD_DLIST(key_listhead, llink))) { - freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); + freesymkey(sk); } free(key_hash); key_hash = NULL; @@ -243,6 +316,21 @@ auth_log2(size_t x) return (u_short)r; } +static void +authcache_flush_id( + keyid_t id + ) +{ + if (cache_keyid == id) { + cache_keyid = 0; + cache_type = 0; + cache_flags = 0; + cache_secret = NULL; + cache_secretsize = 0; + cache_keyacclist = NULL; + } +} + /* * auth_resize_hashtable @@ -288,17 +376,20 @@ auth_resize_hashtable(void) */ static void allocsymkey( - symkey ** bucket, keyid_t id, u_short flags, u_short type, u_long lifetime, - u_short secretsize, + size_t secretsize, u_char * secret, KeyAccT * ka ) { symkey * sk; + symkey ** bucket; + + bucket = &key_hash[KEYHASH(id)]; + if (authnumfreekeys < 1) auth_moremem(-1); @@ -323,12 +414,19 @@ allocsymkey( */ static void freesymkey( - symkey * sk, - symkey ** bucket + symkey * sk ) { + symkey ** bucket; symkey * unlinked; + if (NULL == sk) + return; + + authcache_flush_id(sk->keyid); + keyacc_all_free(sk->keyacclist); + + bucket = &key_hash[KEYHASH(sk->keyid)]; if (sk->secret != NULL) { memset(sk->secret, '\0', sk->secretsize); free(sk->secret); @@ -354,37 +452,26 @@ auth_findkey( { symkey * sk; - for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { - if (id == sk->keyid) { + for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) + if (id == sk->keyid) return sk; - } - } - return NULL; } /* - * auth_havekey - return TRUE if the key id is zero or known + * auth_havekey - return TRUE if the key id is zero or known. The + * key needs not to be trusted. */ int auth_havekey( keyid_t id ) { - symkey * sk; - - if (0 == id || cache_keyid == id) { - return TRUE; - } - - for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { - if (id == sk->keyid) { - return TRUE; - } - } - - return FALSE; + return + (0 == id) || + (cache_keyid == id) || + (NULL != auth_findkey(id)); } @@ -400,35 +487,25 @@ authhavekey( symkey * sk; authkeylookups++; - if (0 == id || cache_keyid == id) { - return TRUE; - } + if (0 == id || cache_keyid == id) + return !!(KEY_TRUSTED & cache_flags); /* - * Seach the bin for the key. If found and the key type - * is zero, somebody marked it trusted without specifying - * a key or key type. In this case consider the key missing. + * Search the bin for the key. If not found, or found but the key + * type is zero, somebody marked it trusted without specifying a + * key or key type. In this case consider the key missing. */ authkeyuncached++; - for (sk = key_hash[KEYHASH(id)]; sk != NULL; sk = sk->hlink) { - if (id == sk->keyid) { - if (0 == sk->type) { - authkeynotfound++; - return FALSE; - } - break; - } + sk = auth_findkey(id); + if ((sk == NULL) || (sk->type == 0)) { + authkeynotfound++; + return FALSE; } /* - * If the key is not found, or if it is found but not trusted, - * the key is not considered found. + * If the key is not trusted, the key is not considered found. */ - if (NULL == sk) { - authkeynotfound++; - return FALSE; - } - if (!(KEY_TRUSTED & sk->flags)) { + if ( ! (KEY_TRUSTED & sk->flags)) { authnokey++; return FALSE; } @@ -456,7 +533,6 @@ authtrust( u_long trust ) { - symkey ** bucket; symkey * sk; u_long lifetime; @@ -464,12 +540,9 @@ authtrust( * Search bin for key; if it does not exist and is untrusted, * forget it. */ - bucket = &key_hash[KEYHASH(id)]; - for (sk = *bucket; sk != NULL; sk = sk->hlink) { - if (id == sk->keyid) - break; - } - if (!trust && NULL == sk) + + sk = auth_findkey(id); + if (!trust && sk == NULL) return; /* @@ -478,27 +551,22 @@ authtrust( * not to be trusted. */ if (sk != NULL) { - if (cache_keyid == id) { - cache_flags = 0; - cache_keyid = 0; - cache_keyacclist = NULL; - } - /* - * Key exists. If it is to be trusted, say so and - * update its lifetime. + * Key exists. If it is to be trusted, say so and update + * its lifetime. If no longer trusted, return it to the + * free list. Flush the cache first to be sure there are + * no discrepancies. */ + authcache_flush_id(id); if (trust > 0) { sk->flags |= KEY_TRUSTED; if (trust > 1) sk->lifetime = current_time + trust; else sk->lifetime = 0; - return; + } else { + freesymkey(sk); } - - /* No longer trusted, return it to the free list. */ - freesymkey(sk, bucket); return; } @@ -511,7 +579,7 @@ authtrust( } else { lifetime = 0; } - allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); + allocsymkey(id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL); } @@ -520,22 +588,17 @@ authtrust( */ int authistrusted( - keyid_t keyno + keyid_t id ) { symkey * sk; - symkey ** bucket; - if (keyno == cache_keyid) + if (id == cache_keyid) return !!(KEY_TRUSTED & cache_flags); authkeyuncached++; - bucket = &key_hash[KEYHASH(keyno)]; - for (sk = *bucket; sk != NULL; sk = sk->hlink) { - if (keyno == sk->keyid) - break; - } - if (NULL == sk || !(KEY_TRUSTED & sk->flags)) { + sk = auth_findkey(id); + if (sk == NULL || !(KEY_TRUSTED & sk->flags)) { authkeynotfound++; return FALSE; } @@ -553,38 +616,23 @@ authistrusted( ) { symkey * sk; - symkey ** bucket; - KeyAccT * kal; - KeyAccT * k; - if (keyno == cache_keyid) - kal = cache_keyacclist; - else { + /* That specific key was already used to authenticate the + * packet. Therefore, the key *must* exist... There's a chance + * that is not trusted, though. + */ + if (keyno == cache_keyid) { + return (KEY_TRUSTED & cache_flags) && + keyacc_contains(cache_keyacclist, sau, TRUE); + } else { authkeyuncached++; - bucket = &key_hash[KEYHASH(keyno)]; - for (sk = *bucket; sk != NULL; sk = sk->hlink) { - if (keyno == sk->keyid) - break; - } - if (NULL == sk || !(KEY_TRUSTED & sk->flags)) { - INSIST(!"authistrustedip: keyid not found/trusted!"); - return FALSE; - } - kal = sk->keyacclist; + sk = auth_findkey(keyno); + INSIST(NULL != sk); + return (KEY_TRUSTED & sk->flags) && + keyacc_contains(sk->keyacclist, sau, TRUE); } - - if (NULL == kal) - return TRUE; - - for (k = kal; k; k = k->next) { - if (SOCK_EQ(&k->addr, sau)) - return TRUE; - } - - return FALSE; } - /* Note: There are two locations below where 'strncpy()' is used. While * this function is a hazard by itself, it's essential that it is used * here. Bug 1243 involved that the secret was filled with NUL bytes @@ -601,71 +649,66 @@ MD5auth_setkey( keyid_t keyno, int keytype, const u_char *key, - size_t len, + size_t secretsize, KeyAccT *ka ) { symkey * sk; - symkey ** bucket; u_char * secret; - size_t secretsize; DEBUG_ENSURE(keytype <= USHRT_MAX); - DEBUG_ENSURE(len < 4 * 1024); + DEBUG_ENSURE(secretsize < 4 * 1024); /* * See if we already have the key. If so just stick in the * new value. */ - bucket = &key_hash[KEYHASH(keyno)]; - for (sk = *bucket; sk != NULL; sk = sk->hlink) { - if (keyno == sk->keyid) { + sk = auth_findkey(keyno); + if (sk != NULL && keyno == sk->keyid) { /* TALOS-CAN-0054: make sure we have a new buffer! */ - if (NULL != sk->secret) { - memset(sk->secret, 0, sk->secretsize); - free(sk->secret); - } - sk->secret = emalloc(len); - sk->type = (u_short)keytype; - secretsize = len; - sk->secretsize = (u_short)secretsize; + if (NULL != sk->secret) { + memset(sk->secret, 0, sk->secretsize); + free(sk->secret); + } + sk->secret = emalloc(secretsize + 1); + sk->type = (u_short)keytype; + sk->secretsize = secretsize; + /* make sure access lists don't leak here! */ + if (ka != sk->keyacclist) { + keyacc_all_free(sk->keyacclist); sk->keyacclist = ka; + } #ifndef DISABLE_BUG1243_FIX - memcpy(sk->secret, key, secretsize); + memcpy(sk->secret, key, secretsize); #else - /* >MUST< use 'strncpy()' here! See above! */ - strncpy((char *)sk->secret, (const char *)key, - secretsize); + /* >MUST< use 'strncpy()' here! See above! */ + strncpy((char *)sk->secret, (const char *)key, + secretsize); #endif - if (cache_keyid == keyno) { - cache_flags = 0; - cache_keyid = 0; - cache_keyacclist = NULL; - } - return; - } + authcache_flush_id(keyno); + return; } /* * Need to allocate new structure. Do it. */ - secretsize = len; - secret = emalloc(secretsize); + secret = emalloc(secretsize + 1); #ifndef DISABLE_BUG1243_FIX memcpy(secret, key, secretsize); #else /* >MUST< use 'strncpy()' here! See above! */ strncpy((char *)secret, (const char *)key, secretsize); #endif - allocsymkey(bucket, keyno, 0, (u_short)keytype, 0, - (u_short)secretsize, secret, ka); + allocsymkey(keyno, 0, (u_short)keytype, 0, + secretsize, secret, ka); #ifdef DEBUG if (debug >= 4) { size_t j; printf("auth_setkey: key %d type %d len %d ", (int)keyno, keytype, (int)secretsize); - for (j = 0; j < secretsize; j++) + for (j = 0; j < secretsize; j++) { printf("%02x", secret[j]); + } printf("\n"); } #endif @@ -697,10 +740,11 @@ auth_delkeys(void) free(sk->secret); sk->secret = NULL; /* TALOS-CAN-0054 */ } + sk->keyacclist = keyacc_all_free(sk->keyacclist); sk->secretsize = 0; sk->lifetime = 0; } else { - freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); + freesymkey(sk); } ITER_DLIST_END() } @@ -716,7 +760,7 @@ auth_agekeys(void) ITER_DLIST_BEGIN(key_listhead, sk, llink, symkey) if (sk->lifetime > 0 && current_time > sk->lifetime) { - freesymkey(sk, &key_hash[KEYHASH(sk->keyid)]); + freesymkey(sk); authkeyexpired++; } ITER_DLIST_END() diff --git a/contrib/ntp/libntp/authreadkeys.c b/contrib/ntp/libntp/authreadkeys.c index 1d4ee30..e9273ad 100644 --- a/contrib/ntp/libntp/authreadkeys.c +++ b/contrib/ntp/libntp/authreadkeys.c @@ -101,13 +101,33 @@ log_maybe( ...) { va_list ap; - if (++(*pnerr) <= nerr_loglimit) { + if ((NULL == pnerr) || (++(*pnerr) <= nerr_loglimit)) { va_start(ap, fmt); mvsyslog(LOG_ERR, fmt, ap); va_end(ap); } } +static void +free_keydata( + KeyDataT *node + ) +{ + KeyAccT *kap; + + if (node) { + while (node->keyacclist) { + kap = node->keyacclist; + node->keyacclist = kap->next; + free(kap); + } + + /* purge secrets from memory before free()ing it */ + memset(node, 0, sizeof(*node) + node->seclen); + free(node); + } +} + /* * authreadkeys - (re)read keys from a file. */ @@ -156,7 +176,7 @@ authreadkeys( * First is key number. See if it is okay. */ keyno = atoi(token); - if (keyno == 0) { + if (keyno < 1) { log_maybe(&nerr, "authreadkeys: cannot change key %s", token); @@ -180,6 +200,14 @@ authreadkeys( keyno); continue; } + + /* We want to silently ignore keys where we do not + * support the requested digest type. OTOH, we want to + * make sure the file is well-formed. That means we + * have to process the line completely and have to + * finally throw away the result... This is a bit more + * work, but it also results in better error detection. + */ #ifdef OPENSSL /* * The key type is the NID used by the message digest @@ -189,30 +217,28 @@ authreadkeys( */ keytype = keytype_from_text(token, NULL); if (keytype == 0) { - log_maybe(&nerr, + log_maybe(NULL, "authreadkeys: invalid type for key %d", keyno); - continue; - } - if (EVP_get_digestbynid(keytype) == NULL) { - log_maybe(&nerr, + } else if (EVP_get_digestbynid(keytype) == NULL) { + log_maybe(NULL, "authreadkeys: no algorithm for key %d", keyno); - continue; + keytype = 0; } #else /* !OPENSSL follows */ - /* * The key type is unused, but is required to be 'M' or * 'm' for compatibility. */ if (!(*token == 'M' || *token == 'm')) { - log_maybe(&nerr, + log_maybe(NULL, "authreadkeys: invalid type for key %d", keyno); - continue; + keytype = 0; + } else { + keytype = KEY_TYPE_MD5; } - keytype = KEY_TYPE_MD5; #endif /* !OPENSSL */ /* @@ -269,26 +295,22 @@ authreadkeys( } token = nexttok(&line); -DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL")); + DPRINTF(0, ("authreadkeys: full access list <%s>\n", (token) ? token : "NULL")); if (token != NULL) { /* A comma-separated IP access list */ char *tp = token; while (tp) { char *i; - KeyAccT ka; + sockaddr_u addr; i = strchr(tp, (int)','); if (i) *i = '\0'; -DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); + DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); - if (is_ip_address(tp, AF_UNSPEC, &ka.addr)) { - KeyAccT *kap; - - kap = emalloc(sizeof(KeyAccT)); - memcpy(kap, &ka, sizeof ka); - kap->next = next->keyacclist; - next->keyacclist = kap; + if (is_ip_address(tp, AF_UNSPEC, &addr)) { + next->keyacclist = keyacc_new_push( + next->keyacclist, &addr); } else { log_maybe(&nerr, "authreadkeys: invalid IP address <%s> for key %d", @@ -303,21 +325,25 @@ DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); } } + /* check if this has to be weeded out... */ + if (0 == keytype) { + free_keydata(next); + next = NULL; + continue; + } + INSIST(NULL != next); next->next = list; list = next; } fclose(fp); - if (nerr > nerr_maxlimit) { - msyslog(LOG_ERR, - "authreadkeys: rejecting file '%s' after %u errors (emergency break)", - file, nerr); - goto onerror; - } if (nerr > 0) { + const char * why = ""; + if (nerr > nerr_maxlimit) + why = " (emergency break)"; msyslog(LOG_ERR, - "authreadkeys: rejecting file '%s' after %u error(s)", - file, nerr); + "authreadkeys: rejecting file '%s' after %u error(s)%s", + file, nerr, why); goto onerror; } @@ -328,9 +354,8 @@ DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); list = next->next; MD5auth_setkey(next->keyid, next->keytype, next->secbuf, next->seclen, next->keyacclist); - /* purge secrets from memory before free()ing it */ - memset(next, 0, sizeof(*next) + next->seclen); - free(next); + next->keyacclist = NULL; /* consumed by MD5auth_setkey */ + free_keydata(next); } return (1); @@ -338,17 +363,7 @@ DPRINTF(0, ("authreadkeys: access list: <%s>\n", tp)); /* Mop up temporary storage before bailing out. */ while (NULL != (next = list)) { list = next->next; - - while (next->keyacclist) { - KeyAccT *kap = next->keyacclist; - - next->keyacclist = kap->next; - free(kap); - } - - /* purge secrets from memory before free()ing it */ - memset(next, 0, sizeof(*next) + next->seclen); - free(next); + free_keydata(next); } return (0); } diff --git a/contrib/ntp/libntp/is_ip_address.c b/contrib/ntp/libntp/is_ip_address.c index 1f21376..d36984c 100644 --- a/contrib/ntp/libntp/is_ip_address.c +++ b/contrib/ntp/libntp/is_ip_address.c @@ -7,53 +7,13 @@ # include <config.h> #endif -#if 0 -#include <stdio.h> -#include <signal.h> -#ifdef HAVE_FNMATCH_H -# include <fnmatch.h> -# if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE) -# define FNM_CASEFOLD FNM_IGNORECASE -# endif -#endif -#ifdef HAVE_SYS_PARAM_H -# include <sys/param.h> -#endif -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif -#ifdef HAVE_SYS_SOCKIO_H /* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */ -# include <sys/sockio.h> -#endif -#ifdef HAVE_SYS_UIO_H -# include <sys/uio.h> -#endif -#endif - #include "ntp_assert.h" #include "ntp_stdlib.h" #include "safecast.h" -#if 0 -#include "ntp_machine.h" -#include "ntpd.h" -#include "ntp_io.h" -#include "iosignal.h" -#include "ntp_lists.h" -#include "ntp_refclock.h" -#include "ntp_worker.h" -#include "ntp_request.h" -#include "timevalops.h" -#include "timespecops.h" -#include "ntpd-opts.h" -#endif - /* Don't include ISC's version of IPv6 variables and structures */ #define ISC_IPV6_H 1 -#include <isc/mem.h> -#include <isc/interfaceiter.h> #include <isc/netaddr.h> -#include <isc/result.h> #include <isc/sockaddr.h> diff --git a/contrib/ntp/libntp/ntp_intres.c b/contrib/ntp/libntp/ntp_intres.c index b0f5620..0b5bb75 100644 --- a/contrib/ntp/libntp/ntp_intres.c +++ b/contrib/ntp/libntp/ntp_intres.c @@ -201,8 +201,6 @@ static time_t next_res_init; /* === forward declarations === */ static u_int reserve_dnschild_ctx(void); static u_int get_dnschild_ctx(void); -static void alloc_dnsworker_context(u_int); -/* static void free_dnsworker_context(u_int); */ static dnsworker_ctx * get_worker_context(blocking_child *, u_int); static void scheduled_sleep(time_t, time_t, dnsworker_ctx *); @@ -949,47 +947,41 @@ get_dnschild_ctx(void) } -static void -alloc_dnsworker_context( - u_int idx - ) -{ - const size_t worker_context_sz = sizeof(*dnsworker_contexts[0]); - - REQUIRE(NULL == dnsworker_contexts[idx]); - dnsworker_contexts[idx] = emalloc_zero(worker_context_sz); -} - - static dnsworker_ctx * get_worker_context( blocking_child * c, u_int idx ) { - static size_t ps = sizeof(dnsworker_contexts[0]); - u_int min_new_alloc; - u_int new_alloc; - size_t octets; - size_t new_octets; + u_int min_new_alloc; + u_int new_alloc; + size_t octets; + size_t new_octets; + dnsworker_ctx * retv; + worker_global_lock(TRUE); + if (dnsworker_contexts_alloc <= idx) { min_new_alloc = 1 + idx; /* round new_alloc up to nearest multiple of 4 */ new_alloc = (min_new_alloc + 4) & ~(4 - 1); - new_octets = new_alloc * ps; - octets = dnsworker_contexts_alloc * ps; + new_octets = new_alloc * sizeof(dnsworker_ctx*); + octets = dnsworker_contexts_alloc * sizeof(dnsworker_ctx*); dnsworker_contexts = erealloc_zero(dnsworker_contexts, new_octets, octets); dnsworker_contexts_alloc = new_alloc; + retv = emalloc_zero(sizeof(dnsworker_ctx)); + dnsworker_contexts[idx] = retv; + } else if (NULL == (retv = dnsworker_contexts[idx])) { + retv = emalloc_zero(sizeof(dnsworker_ctx)); + dnsworker_contexts[idx] = retv; } - - if (NULL == dnsworker_contexts[idx]) - alloc_dnsworker_context(idx); - ZERO(*dnsworker_contexts[idx]); - dnsworker_contexts[idx]->c = c; - - return dnsworker_contexts[idx]; + + worker_global_lock(FALSE); + + ZERO(*retv); + retv->c = c; + return retv; } diff --git a/contrib/ntp/libntp/ntp_worker.c b/contrib/ntp/libntp/ntp_worker.c index 087f06c..d1d09c0 100644 --- a/contrib/ntp/libntp/ntp_worker.c +++ b/contrib/ntp/libntp/ntp_worker.c @@ -267,7 +267,7 @@ process_blocking_resp( void harvest_blocking_responses(void) { - int idx; + size_t idx; blocking_child* cp; u_int scseen, scdone; diff --git a/contrib/ntp/libntp/recvbuff.c b/contrib/ntp/libntp/recvbuff.c index 73ebe88..f888950 100644 --- a/contrib/ntp/libntp/recvbuff.c +++ b/contrib/ntp/libntp/recvbuff.c @@ -156,18 +156,15 @@ uninit_recvbuff(void) void freerecvbuf(recvbuf_t *rb) { - if (rb == NULL) { - msyslog(LOG_ERR, "freerecvbuff received NULL buffer"); - return; + if (rb) { + LOCK(); + rb->used--; + if (rb->used != 0) + msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used); + LINK_SLIST(free_recv_list, rb, link); + free_recvbufs++; + UNLOCK(); } - - LOCK(); - rb->used--; - if (rb->used != 0) - msyslog(LOG_ERR, "******** freerecvbuff non-zero usage: %d *******", rb->used); - LINK_SLIST(free_recv_list, rb, link); - free_recvbufs++; - UNLOCK(); } @@ -264,7 +261,7 @@ get_full_recv_buffer(void) */ void purge_recv_buffers_for_fd( - SOCKET fd + int fd ) { recvbuf_t *rbufp; @@ -277,7 +274,12 @@ purge_recv_buffers_for_fd( rbufp != NULL; rbufp = next) { next = rbufp->link; - if (rbufp->fd == fd) { +# ifdef HAVE_IO_COMPLETION_PORT + if (rbufp->dstadr == NULL && rbufp->fd == fd) +# else + if (rbufp->fd == fd) +# endif + { UNLINK_MID_FIFO(punlinked, full_recv_fifo, rbufp, link, recvbuf_t); INSIST(punlinked == rbufp); diff --git a/contrib/ntp/libntp/work_fork.c b/contrib/ntp/libntp/work_fork.c index 96c550e..6c9545a 100644 --- a/contrib/ntp/libntp/work_fork.c +++ b/contrib/ntp/libntp/work_fork.c @@ -451,7 +451,7 @@ fork_blocking_child( } } -#ifdef HAVE_DROPROOT +#if defined(HAVE_DROPROOT) && !defined(NEED_EARLY_FORK) /* defer the fork until after root is dropped */ if (droproot && !root_dropped) return; @@ -540,6 +540,11 @@ fork_blocking_child( } +void worker_global_lock(int inOrOut) +{ + (void)inOrOut; +} + #else /* !WORK_FORK follows */ char work_fork_nonempty_compilation_unit; #endif diff --git a/contrib/ntp/libntp/work_thread.c b/contrib/ntp/libntp/work_thread.c index 11e3267..82f6064 100644 --- a/contrib/ntp/libntp/work_thread.c +++ b/contrib/ntp/libntp/work_thread.c @@ -88,7 +88,27 @@ static int ensure_workresp_empty_slot(blocking_child *); static int queue_req_pointer(blocking_child *, blocking_pipe_header *); static void cleanup_after_child(blocking_child *); +static sema_type worker_mmutex; +static sem_ref worker_memlock; +/* -------------------------------------------------------------------- + * locking the global worker state table (and other global stuff) + */ +void +worker_global_lock( + int inOrOut) +{ + if (worker_memlock) { + if (inOrOut) + wait_for_sem(worker_memlock, NULL); + else + tickle_sem(worker_memlock); + } +} + +/* -------------------------------------------------------------------- + * implementation isolation wrapper + */ void exit_worker( int exitcode @@ -724,6 +744,9 @@ prepare_child_sems( blocking_child *c ) { + if (NULL == worker_memlock) + worker_memlock = create_sema(&worker_mmutex, 1, 1); + c->accesslock = create_sema(&c->sem_table[0], 1, 1); c->workitems_pending = create_sema(&c->sem_table[1], 0, 0); c->wake_scheduled_sleep = create_sema(&c->sem_table[2], 0, 1); |