mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 16:55:07 -05:00
Add support for different authentication hashes
Allow different hash functions to be used in the NTP and cmdmon protocols. This breaks the cmdmon protocol compatibility. Extended key file format is used to specify the hash functions for chronyd and new authhash command is added to chronyc. MD5 is the default and the only function included in the chrony source code, other functions will be available from libraries.
This commit is contained in:
164
keys.c
164
keys.c
@@ -34,11 +34,17 @@
|
||||
#include "keys.h"
|
||||
#include "conf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "local.h"
|
||||
#include "logging.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned long id;
|
||||
char *val;
|
||||
int len;
|
||||
int hash_id;
|
||||
int auth_delay;
|
||||
} Key;
|
||||
|
||||
#define MAX_KEYS 256
|
||||
@@ -47,7 +53,7 @@ static int n_keys;
|
||||
static Key keys[MAX_KEYS];
|
||||
|
||||
static int command_key_valid;
|
||||
static int command_key_pos;
|
||||
static int command_key_id;
|
||||
static int cache_valid;
|
||||
static unsigned long cache_key_id;
|
||||
static int cache_key_pos;
|
||||
@@ -75,6 +81,37 @@ KEY_Finalise(void)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
determine_hash_delay(int key_id)
|
||||
{
|
||||
NTP_Packet pkt;
|
||||
struct timeval before, after;
|
||||
unsigned long usecs, min_usecs=0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
LCL_ReadRawTime(&before);
|
||||
KEY_GenerateAuth(key_id, (unsigned char *)&pkt, NTP_NORMAL_PACKET_SIZE,
|
||||
(unsigned char *)&pkt.auth_data, sizeof (pkt.auth_data));
|
||||
LCL_ReadRawTime(&after);
|
||||
|
||||
usecs = (after.tv_sec - before.tv_sec) * 1000000 + (after.tv_usec - before.tv_usec);
|
||||
|
||||
if (i == 0 || usecs < min_usecs) {
|
||||
min_usecs = usecs;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
LOG(LOGS_INFO, LOGF_Keys, "authentication delay for key %d: %d useconds", key_id, min_usecs);
|
||||
#endif
|
||||
|
||||
/* Add on a bit extra to allow for copying, conversions etc */
|
||||
return min_usecs + (min_usecs >> 4);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Compare two keys */
|
||||
|
||||
static int
|
||||
@@ -102,16 +139,16 @@ compare_keys_by_id(const void *a, const void *b)
|
||||
void
|
||||
KEY_Reload(void)
|
||||
{
|
||||
int i, len1;
|
||||
int i, len1, fields;
|
||||
char *key_file;
|
||||
FILE *in;
|
||||
unsigned long key_id;
|
||||
char line[KEYLEN+1], keyval[KEYLEN+1];
|
||||
char line[KEYLEN+1], buf1[KEYLEN+1], buf2[KEYLEN+1];
|
||||
char *keyval, *hashname;
|
||||
|
||||
for (i=0; i<n_keys; i++) {
|
||||
Free(keys[i].val);
|
||||
}
|
||||
|
||||
n_keys = 0;
|
||||
|
||||
key_file = CNF_GetKeysFile();
|
||||
@@ -127,8 +164,21 @@ KEY_Reload(void)
|
||||
if (line[len1] == '\n') {
|
||||
line[len1] = '\0';
|
||||
}
|
||||
fields = sscanf(line, "%lu%" SKEYLEN "s%" SKEYLEN "s", &key_id, buf1, buf2);
|
||||
if (fields >= 2 && fields <= 3) {
|
||||
if (fields == 3) {
|
||||
hashname = buf1;
|
||||
keyval = buf2;
|
||||
} else {
|
||||
hashname = "MD5";
|
||||
keyval = buf1;
|
||||
}
|
||||
keys[n_keys].hash_id = HSH_GetHashId(hashname);
|
||||
if (keys[n_keys].hash_id < 0) {
|
||||
LOG(LOGS_WARN, LOGF_Keys, "Unknown hash function in key %d", key_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sscanf(line, "%lu%" SKEYLEN "s", &key_id, keyval) == 2) {
|
||||
keys[n_keys].id = key_id;
|
||||
keys[n_keys].len = strlen(keyval);
|
||||
keys[n_keys].val = MallocArray(char, 1 + keys[n_keys].len);
|
||||
@@ -149,6 +199,10 @@ KEY_Reload(void)
|
||||
command_key_valid = 0;
|
||||
cache_valid = 0;
|
||||
|
||||
for (i=0; i<n_keys; i++) {
|
||||
keys[i].auth_delay = determine_hash_delay(keys[i].id);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,30 +226,8 @@ lookup_key(unsigned long id)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
KEY_CommandKey(char **key, int *len)
|
||||
{
|
||||
unsigned long command_key_id;
|
||||
|
||||
if (!command_key_valid) {
|
||||
command_key_id = CNF_GetCommandKey();
|
||||
command_key_pos = lookup_key(command_key_id);
|
||||
command_key_valid = 1;
|
||||
}
|
||||
|
||||
if (command_key_pos >= 0) {
|
||||
*key = keys[command_key_pos].val;
|
||||
*len = keys[command_key_pos].len;
|
||||
} else {
|
||||
*key = "";
|
||||
*len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_GetKey(unsigned long key_id, char **key, int *len)
|
||||
static int
|
||||
get_key_pos(unsigned long key_id)
|
||||
{
|
||||
if (!cache_valid || key_id != cache_key_id) {
|
||||
cache_valid = 1;
|
||||
@@ -203,15 +235,19 @@ KEY_GetKey(unsigned long key_id, char **key, int *len)
|
||||
cache_key_id = key_id;
|
||||
}
|
||||
|
||||
if (cache_key_pos >= 0) {
|
||||
*key = keys[cache_key_pos].val;
|
||||
*len = keys[cache_key_pos].len;
|
||||
return 1;
|
||||
} else {
|
||||
*key = "";
|
||||
*len = 0;
|
||||
return 0;
|
||||
return cache_key_pos;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
unsigned long
|
||||
KEY_GetCommandKey(void)
|
||||
{
|
||||
if (!command_key_valid) {
|
||||
command_key_id = CNF_GetCommandKey();
|
||||
}
|
||||
|
||||
return command_key_id;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
@@ -239,3 +275,57 @@ KEY_KeyKnown(unsigned long key_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_GetAuthDelay(unsigned long key_id)
|
||||
{
|
||||
int key_pos;
|
||||
|
||||
key_pos = get_key_pos(key_id);
|
||||
|
||||
if (key_pos < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return keys[key_pos].auth_delay;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_GenerateAuth(unsigned long key_id, const unsigned char *data, int data_len,
|
||||
unsigned char *auth, int auth_len)
|
||||
{
|
||||
int key_pos;
|
||||
|
||||
key_pos = get_key_pos(key_id);
|
||||
|
||||
if (key_pos < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return UTI_GenerateNTPAuth(keys[key_pos].hash_id,
|
||||
(unsigned char *)keys[key_pos].val, keys[key_pos].len,
|
||||
data, data_len, auth, auth_len);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
KEY_CheckAuth(unsigned long key_id, const unsigned char *data, int data_len,
|
||||
const unsigned char *auth, int auth_len)
|
||||
{
|
||||
int key_pos;
|
||||
|
||||
key_pos = get_key_pos(key_id);
|
||||
|
||||
if (key_pos < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return UTI_CheckNTPAuth(keys[key_pos].hash_id,
|
||||
(unsigned char *)keys[key_pos].val, keys[key_pos].len,
|
||||
data, data_len, auth, auth_len);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user