summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/libntp/authkeys.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/libntp/authkeys.c')
-rw-r--r--contrib/ntp/libntp/authkeys.c105
1 files changed, 91 insertions, 14 deletions
diff --git a/contrib/ntp/libntp/authkeys.c b/contrib/ntp/libntp/authkeys.c
index f7462a2..36fdd8b 100644
--- a/contrib/ntp/libntp/authkeys.c
+++ b/contrib/ntp/libntp/authkeys.c
@@ -15,6 +15,7 @@
#include "ntp_string.h"
#include "ntp_malloc.h"
#include "ntp_stdlib.h"
+#include "ntp_keyacc.h"
/*
* Structure to store keys in in the hash table.
@@ -25,6 +26,7 @@ struct savekey {
symkey * hlink; /* next in hash bucket */
DECL_DLIST_LINK(symkey, llink); /* for overall & free lists */
u_char * secret; /* shared secret */
+ KeyAccT * keyacclist; /* Private key access list */
u_long lifetime; /* remaining lifetime */
keyid_t keyid; /* key identifier */
u_short type; /* OpenSSL digest NID */
@@ -48,13 +50,13 @@ struct symkey_alloc_tag {
symkey_alloc * authallocs;
#endif /* DEBUG */
-static inline u_short auth_log2(double x);
-static void auth_resize_hashtable(void);
-static void allocsymkey(symkey **, keyid_t, u_short,
- u_short, u_long, u_short, u_char *);
-static void freesymkey(symkey *, symkey **);
+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 **);
#ifdef DEBUG
-static void free_auth_mem(void);
+static void free_auth_mem(void);
#endif
symkey key_listhead; /* list of all in-use keys */;
@@ -97,6 +99,7 @@ u_char *cache_secret; /* secret */
u_short cache_secretsize; /* secret length */
int cache_type; /* OpenSSL digest NID */
u_short cache_flags; /* flags that wave */
+KeyAccT *cache_keyacclist; /* key access list */
/*
@@ -142,6 +145,7 @@ free_auth_mem(void)
key_hash = NULL;
cache_keyid = 0;
cache_flags = 0;
+ cache_keyacclist = NULL;
for (alloc = authallocs; alloc != NULL; alloc = next_alloc) {
next_alloc = alloc->link;
free(alloc->mem);
@@ -210,10 +214,33 @@ auth_prealloc_symkeys(
}
-static inline u_short
-auth_log2(double x)
+static u_short
+auth_log2(size_t x)
{
- return (u_short)(log10(x) / log10(2));
+ /*
+ ** bithack to calculate floor(log2(x))
+ **
+ ** This assumes
+ ** - (sizeof(size_t) is a power of two
+ ** - CHAR_BITS is a power of two
+ ** - returning zero for arguments <= 0 is OK.
+ **
+ ** Does only shifts, masks and sums in integer arithmetic in
+ ** log2(CHAR_BIT*sizeof(size_t)) steps. (that is, 5/6 steps for
+ ** 32bit/64bit size_t)
+ */
+ int s;
+ int r = 0;
+ size_t m = ~(size_t)0;
+
+ for (s = sizeof(size_t) / 2 * CHAR_BIT; s != 0; s >>= 1) {
+ m <<= s;
+ if (x & m)
+ r += s;
+ else
+ x <<= s;
+ }
+ return (u_short)r;
}
@@ -234,7 +261,7 @@ auth_resize_hashtable(void)
symkey * sk;
totalkeys = authnumkeys + authnumfreekeys;
- hashbits = auth_log2(totalkeys / 4.0) + 1;
+ hashbits = auth_log2(totalkeys / 4) + 1;
hashbits = max(4, hashbits);
hashbits = min(15, hashbits);
@@ -267,7 +294,8 @@ allocsymkey(
u_short type,
u_long lifetime,
u_short secretsize,
- u_char * secret
+ u_char * secret,
+ KeyAccT * ka
)
{
symkey * sk;
@@ -281,6 +309,7 @@ allocsymkey(
sk->type = type;
sk->secretsize = secretsize;
sk->secret = secret;
+ sk->keyacclist = ka;
sk->lifetime = lifetime;
LINK_SLIST(*bucket, sk, hlink);
LINK_TAIL_DLIST(key_listhead, sk, llink);
@@ -412,6 +441,7 @@ authhavekey(
cache_flags = sk->flags;
cache_secret = sk->secret;
cache_secretsize = sk->secretsize;
+ cache_keyacclist = sk->keyacclist;
return TRUE;
}
@@ -451,6 +481,7 @@ authtrust(
if (cache_keyid == id) {
cache_flags = 0;
cache_keyid = 0;
+ cache_keyacclist = NULL;
}
/*
@@ -480,7 +511,7 @@ authtrust(
} else {
lifetime = 0;
}
- allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL);
+ allocsymkey(bucket, id, KEY_TRUSTED, 0, lifetime, 0, NULL, NULL);
}
@@ -511,6 +542,49 @@ authistrusted(
return TRUE;
}
+
+/*
+ * authistrustedip - determine if the IP is OK for the keyid
+ */
+ int
+ authistrustedip(
+ keyid_t keyno,
+ sockaddr_u * sau
+ )
+{
+ symkey * sk;
+ symkey ** bucket;
+ KeyAccT * kal;
+ KeyAccT * k;
+
+ if (keyno == cache_keyid)
+ kal = cache_keyacclist;
+ 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;
+ }
+
+ 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
@@ -527,7 +601,8 @@ MD5auth_setkey(
keyid_t keyno,
int keytype,
const u_char *key,
- size_t len
+ size_t len,
+ KeyAccT *ka
)
{
symkey * sk;
@@ -553,6 +628,7 @@ MD5auth_setkey(
sk->type = (u_short)keytype;
secretsize = len;
sk->secretsize = (u_short)secretsize;
+ sk->keyacclist = ka;
#ifndef DISABLE_BUG1243_FIX
memcpy(sk->secret, key, secretsize);
#else
@@ -563,6 +639,7 @@ MD5auth_setkey(
if (cache_keyid == keyno) {
cache_flags = 0;
cache_keyid = 0;
+ cache_keyacclist = NULL;
}
return;
}
@@ -580,7 +657,7 @@ MD5auth_setkey(
strncpy((char *)secret, (const char *)key, secretsize);
#endif
allocsymkey(bucket, keyno, 0, (u_short)keytype, 0,
- (u_short)secretsize, secret);
+ (u_short)secretsize, secret, ka);
#ifdef DEBUG
if (debug >= 4) {
size_t j;
OpenPOWER on IntegriCloud