aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrandon P. Enochs <enochs.brandon@gmail.com>2018-10-27 18:55:59 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-10-27 18:57:37 +0200
commita541314b1f5e7392608cdef91e9098330823ed31 (patch)
treea1c57bb25beac34dbfa5f8a24bc0c796befd2982
parent4329116b6d036b19a92cabf51dc388fab4787b53 (diff)
downloadbusybox-w32-a541314b1f5e7392608cdef91e9098330823ed31.tar.gz
busybox-w32-a541314b1f5e7392608cdef91e9098330823ed31.tar.bz2
busybox-w32-a541314b1f5e7392608cdef91e9098330823ed31.zip
ntpd: add support for MD5/SHA1 message authentication
Add support for MD5 message authentication as described in RFC 5905. This patch also supports SHA1 authentication. The key file format is the same file format as used by ntpd. The configuration file format follows standard Unix conventions (# comments) with lines consist of the following fields separated by whitespace: <key identifier, [1,65535]> <SHA1|MD5> <an ASCII string of up to 20 characters|an octet string [a-zA-F0-9] of up to 40 characters>. https://www.ietf.org/rfc/rfc5905.txt function old new delta ntp_init 473 987 +514 hash - 125 +125 recv_and_process_peer_pkt 889 961 +72 packed_usage 33066 33130 +64 ntpd_main 1226 1277 +51 find_key_entry - 29 +29 add_peers 195 207 +12 recv_and_process_client_pkt 509 514 +5 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 6/0 up/down: 872/0) Total: 872 bytes Signed-off-by: Brandon P. Enochs <enochs.brandon@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ntpd.c266
1 files changed, 241 insertions, 25 deletions
diff --git a/networking/ntpd.c b/networking/ntpd.c
index 1ebdc34c3..354bff897 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -62,13 +62,19 @@
62//config: help 62//config: help
63//config: Make ntpd look in /etc/ntp.conf for peers. Only "server address" 63//config: Make ntpd look in /etc/ntp.conf for peers. Only "server address"
64//config: is supported. 64//config: is supported.
65//config:config FEATURE_NTP_AUTH
66//config: bool "Support md5/sha1 message authentication codes"
67//config: default n
68//config: depends on NTPD
65 69
66//applet:IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) 70//applet:IF_NTPD(APPLET(ntpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
67 71
68//kbuild:lib-$(CONFIG_NTPD) += ntpd.o 72//kbuild:lib-$(CONFIG_NTPD) += ntpd.o
69 73
70//usage:#define ntpd_trivial_usage 74//usage:#define ntpd_trivial_usage
71//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..." 75//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l] [-I IFACE")"] [-S PROG]"
76//usage: IF_NOT_FEATURE_NTP_AUTH(" [-p PEER]...")
77//usage: IF_FEATURE_NTP_AUTH(" [-k KEYFILE] [-p [keyno:N:]PEER]...")
72//usage:#define ntpd_full_usage "\n\n" 78//usage:#define ntpd_full_usage "\n\n"
73//usage: "NTP client/server\n" 79//usage: "NTP client/server\n"
74//usage: "\n -d Verbose (may be repeated)" 80//usage: "\n -d Verbose (may be repeated)"
@@ -76,8 +82,16 @@
76//usage: "\n -q Quit after clock is set" 82//usage: "\n -q Quit after clock is set"
77//usage: "\n -N Run at high priority" 83//usage: "\n -N Run at high priority"
78//usage: "\n -w Do not set time (only query peers), implies -n" 84//usage: "\n -w Do not set time (only query peers), implies -n"
79//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" 85//usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 min"
86//usage: IF_NOT_FEATURE_NTP_AUTH(
80//usage: "\n -p PEER Obtain time from PEER (may be repeated)" 87//usage: "\n -p PEER Obtain time from PEER (may be repeated)"
88//usage: )
89//usage: IF_FEATURE_NTP_AUTH(
90//usage: "\n -k FILE Key file (ntp.keys compatible)"
91//usage: "\n -p [keyno:NUM:]PEER"
92//usage: "\n Obtain time from PEER (may be repeated)"
93//usage: "\n Use key NUM for authentication"
94//usage: )
81//usage: IF_FEATURE_NTPD_CONF( 95//usage: IF_FEATURE_NTPD_CONF(
82//usage: "\n If -p is not given, 'server HOST' lines" 96//usage: "\n If -p is not given, 'server HOST' lines"
83//usage: "\n from /etc/ntp.conf are used" 97//usage: "\n from /etc/ntp.conf are used"
@@ -228,14 +242,18 @@
228/* Parameter averaging constant */ 242/* Parameter averaging constant */
229#define AVG 4 243#define AVG 4
230 244
245#define MAX_KEY_NUMBER 65535
246#define KEYID_SIZE sizeof(uint32_t)
231 247
232enum { 248enum {
233 NTP_VERSION = 4, 249 NTP_VERSION = 4,
234 NTP_MAXSTRATUM = 15, 250 NTP_MAXSTRATUM = 15,
235 251
236 NTP_DIGESTSIZE = 16, 252 NTP_MD5_DIGESTSIZE = 16,
237 NTP_MSGSIZE_NOAUTH = 48, 253 NTP_MSGSIZE_NOAUTH = 48,
238 NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE), 254 NTP_MSGSIZE_MD5_AUTH = NTP_MSGSIZE_NOAUTH + KEYID_SIZE + NTP_MD5_DIGESTSIZE,
255 NTP_SHA1_DIGESTSIZE = 20,
256 NTP_MSGSIZE_SHA1_AUTH = NTP_MSGSIZE_NOAUTH + KEYID_SIZE + NTP_SHA1_DIGESTSIZE,
239 257
240 /* Status Masks */ 258 /* Status Masks */
241 MODE_MASK = (7 << 0), 259 MODE_MASK = (7 << 0),
@@ -288,7 +306,7 @@ typedef struct {
288 l_fixedpt_t m_rectime; 306 l_fixedpt_t m_rectime;
289 l_fixedpt_t m_xmttime; 307 l_fixedpt_t m_xmttime;
290 uint32_t m_keyid; 308 uint32_t m_keyid;
291 uint8_t m_digest[NTP_DIGESTSIZE]; 309 uint8_t m_digest[ENABLE_FEATURE_NTP_AUTH ? NTP_SHA1_DIGESTSIZE : NTP_MD5_DIGESTSIZE];
292} msg_t; 310} msg_t;
293 311
294typedef struct { 312typedef struct {
@@ -297,9 +315,26 @@ typedef struct {
297 double d_dispersion; 315 double d_dispersion;
298} datapoint_t; 316} datapoint_t;
299 317
318#if ENABLE_FEATURE_NTP_AUTH
319enum {
320 HASH_MD5,
321 HASH_SHA1,
322};
323typedef struct {
324 unsigned id; //try uint16_t?
325 smalluint type;
326 smalluint msg_size;
327 smalluint key_length;
328 char key[0];
329} key_entry_t;
330#endif
331
300typedef struct { 332typedef struct {
301 len_and_sockaddr *p_lsa; 333 len_and_sockaddr *p_lsa;
302 char *p_dotted; 334 char *p_dotted;
335#if ENABLE_FEATURE_NTP_AUTH
336 key_entry_t *key_entry;
337#endif
303 int p_fd; 338 int p_fd;
304 int datapoint_idx; 339 int datapoint_idx;
305 uint32_t lastpkt_refid; 340 uint32_t lastpkt_refid;
@@ -337,13 +372,14 @@ enum {
337 OPT_q = (1 << 1), 372 OPT_q = (1 << 1),
338 OPT_N = (1 << 2), 373 OPT_N = (1 << 2),
339 OPT_x = (1 << 3), 374 OPT_x = (1 << 3),
375 OPT_k = (1 << 4) * ENABLE_FEATURE_NTP_AUTH,
340 /* Insert new options above this line. */ 376 /* Insert new options above this line. */
341 /* Non-compat options: */ 377 /* Non-compat options: */
342 OPT_w = (1 << 4), 378 OPT_w = (1 << (4+ENABLE_FEATURE_NTP_AUTH)),
343 OPT_p = (1 << 5), 379 OPT_p = (1 << (5+ENABLE_FEATURE_NTP_AUTH)),
344 OPT_S = (1 << 6), 380 OPT_S = (1 << (6+ENABLE_FEATURE_NTP_AUTH)),
345 OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER, 381 OPT_l = (1 << (7+ENABLE_FEATURE_NTP_AUTH)) * ENABLE_FEATURE_NTPD_SERVER,
346 OPT_I = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER, 382 OPT_I = (1 << (8+ENABLE_FEATURE_NTP_AUTH)) * ENABLE_FEATURE_NTPD_SERVER,
347 /* We hijack some bits for other purposes */ 383 /* We hijack some bits for other purposes */
348 OPT_qq = (1 << 31), 384 OPT_qq = (1 << 31),
349}; 385};
@@ -816,8 +852,12 @@ resolve_peer_hostname(peer_t *p)
816 return lsa; 852 return lsa;
817} 853}
818 854
855#if !ENABLE_FEATURE_NTP_AUTH
856#define add_peers(s, key_entry) \
857 add_peers(s)
858#endif
819static void 859static void
820add_peers(const char *s) 860add_peers(const char *s, key_entry_t *key_entry)
821{ 861{
822 llist_t *item; 862 llist_t *item;
823 peer_t *p; 863 peer_t *p;
@@ -846,6 +886,7 @@ add_peers(const char *s)
846 } 886 }
847 } 887 }
848 888
889 IF_FEATURE_NTP_AUTH(p->key_entry = key_entry;)
849 llist_add_to(&G.ntp_peers, p); 890 llist_add_to(&G.ntp_peers, p);
850 G.peer_cnt++; 891 G.peer_cnt++;
851} 892}
@@ -870,6 +911,48 @@ do_sendto(int fd,
870 return 0; 911 return 0;
871} 912}
872 913
914#if ENABLE_FEATURE_NTP_AUTH
915static void
916hash(key_entry_t *key_entry, const msg_t *msg, uint8_t *output)
917{
918 union {
919 md5_ctx_t m;
920 sha1_ctx_t s;
921 } ctx;
922 unsigned hash_size = sizeof(*msg) - sizeof(msg->m_keyid) - sizeof(msg->m_digest);
923
924 switch (key_entry->type) {
925 case HASH_MD5:
926 md5_begin(&ctx.m);
927 md5_hash(&ctx.m, key_entry->key, key_entry->key_length);
928 md5_hash(&ctx.m, msg, hash_size);
929 md5_end(&ctx.m, output);
930 break;
931 default: /* it's HASH_SHA1 */
932 sha1_begin(&ctx.s);
933 sha1_hash(&ctx.s, key_entry->key, key_entry->key_length);
934 sha1_hash(&ctx.s, msg, hash_size);
935 sha1_end(&ctx.s, output);
936 break;
937 }
938}
939
940static void
941hash_peer(peer_t *p)
942{
943 p->p_xmt_msg.m_keyid = htonl(p->key_entry->id);
944 hash(p->key_entry, &p->p_xmt_msg, p->p_xmt_msg.m_digest);
945}
946
947static int
948hashes_differ(peer_t *p, const msg_t *msg)
949{
950 uint8_t digest[NTP_SHA1_DIGESTSIZE];
951 hash(p->key_entry, msg, digest);
952 return memcmp(digest, msg->m_digest, p->key_entry->msg_size - NTP_MSGSIZE_NOAUTH - KEYID_SIZE);
953}
954#endif
955
873static void 956static void
874send_query_to_peer(peer_t *p) 957send_query_to_peer(peer_t *p)
875{ 958{
@@ -946,9 +1029,18 @@ send_query_to_peer(peer_t *p)
946 */ 1029 */
947 p->reachable_bits <<= 1; 1030 p->reachable_bits <<= 1;
948 1031
1032#if ENABLE_FEATURE_NTP_AUTH
1033 if (p->key_entry)
1034 hash_peer(p);
949 if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, 1035 if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
950 &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 1036 &p->p_xmt_msg, !p->key_entry ? NTP_MSGSIZE_NOAUTH : p->key_entry->msg_size) == -1
951 ) { 1037 )
1038#else
1039 if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len,
1040 &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1
1041 )
1042#endif
1043 {
952 close(p->p_fd); 1044 close(p->p_fd);
953 p->p_fd = -1; 1045 p->p_fd = -1;
954 /* 1046 /*
@@ -1924,10 +2016,21 @@ recv_and_process_peer_pkt(peer_t *p)
1924 bb_perror_msg_and_die("recv(%s) error", p->p_dotted); 2016 bb_perror_msg_and_die("recv(%s) error", p->p_dotted);
1925 } 2017 }
1926 2018
1927 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 2019#if ENABLE_FEATURE_NTP_AUTH
2020 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH) {
2021 bb_error_msg("malformed packet received from %s", p->p_dotted);
2022 return;
2023 }
2024 if (p->key_entry && hashes_differ(p, &msg)) {
2025 bb_error_msg("invalid cryptographic hash received from %s", p->p_dotted);
2026 return;
2027 }
2028#else
2029 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH) {
1928 bb_error_msg("malformed packet received from %s", p->p_dotted); 2030 bb_error_msg("malformed packet received from %s", p->p_dotted);
1929 return; 2031 return;
1930 } 2032 }
2033#endif
1931 2034
1932 if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl 2035 if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl
1933 || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl 2036 || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl
@@ -2135,7 +2238,12 @@ recv_and_process_client_pkt(void /*int fd*/)
2135 from = xzalloc(to->len); 2238 from = xzalloc(to->len);
2136 2239
2137 size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len); 2240 size = recv_from_to(G_listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len);
2138 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { 2241#if ENABLE_FEATURE_NTP_AUTH
2242 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH && size != NTP_MSGSIZE_SHA1_AUTH)
2243#else
2244 if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE_MD5_AUTH)
2245#endif
2246 {
2139 char *addr; 2247 char *addr;
2140 if (size < 0) { 2248 if (size < 0) {
2141 if (errno == EAGAIN) 2249 if (errno == EAGAIN)
@@ -2278,6 +2386,19 @@ recv_and_process_client_pkt(void /*int fd*/)
2278 * with the -g and -q options. See the tinker command for other options. 2386 * with the -g and -q options. See the tinker command for other options.
2279 * Note: The kernel time discipline is disabled with this option. 2387 * Note: The kernel time discipline is disabled with this option.
2280 */ 2388 */
2389#if ENABLE_FEATURE_NTP_AUTH
2390static key_entry_t *
2391find_key_entry(llist_t *key_entries, unsigned id)
2392{
2393 while (key_entries) {
2394 key_entry_t *cur = (key_entry_t*) key_entries->data;
2395 if (cur->id == id)
2396 return cur;
2397 key_entries = key_entries->link;
2398 }
2399 bb_error_msg_and_die("key %u is not defined", id);
2400}
2401#endif
2281 2402
2282/* By doing init in a separate function we decrease stack usage 2403/* By doing init in a separate function we decrease stack usage
2283 * in main loop. 2404 * in main loop.
@@ -2286,6 +2407,10 @@ static NOINLINE void ntp_init(char **argv)
2286{ 2407{
2287 unsigned opts; 2408 unsigned opts;
2288 llist_t *peers; 2409 llist_t *peers;
2410#if ENABLE_FEATURE_NTP_AUTH
2411 llist_t *key_entries;
2412 char *key_file_path;
2413#endif
2289 2414
2290 srand(getpid()); 2415 srand(getpid());
2291 2416
@@ -2302,8 +2427,10 @@ static NOINLINE void ntp_init(char **argv)
2302 2427
2303 /* Parse options */ 2428 /* Parse options */
2304 peers = NULL; 2429 peers = NULL;
2430 IF_FEATURE_NTP_AUTH(key_entries = NULL;)
2305 opts = getopt32(argv, "^" 2431 opts = getopt32(argv, "^"
2306 "nqNx" /* compat */ 2432 "nqNx" /* compat */
2433 IF_FEATURE_NTP_AUTH("k:") /* compat */
2307 "wp:*S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ 2434 "wp:*S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
2308 IF_FEATURE_NTPD_SERVER("I:") /* compat */ 2435 IF_FEATURE_NTPD_SERVER("I:") /* compat */
2309 "d" /* compat */ 2436 "d" /* compat */
@@ -2311,11 +2438,11 @@ static NOINLINE void ntp_init(char **argv)
2311 "\0" 2438 "\0"
2312 "dd:wn" /* -d: counter; -p: list; -w implies -n */ 2439 "dd:wn" /* -d: counter; -p: list; -w implies -n */
2313 IF_FEATURE_NTPD_SERVER(":Il") /* -I implies -l */ 2440 IF_FEATURE_NTPD_SERVER(":Il") /* -I implies -l */
2314 , &peers, &G.script_name, 2441 IF_FEATURE_NTP_AUTH(, &key_file_path)
2315#if ENABLE_FEATURE_NTPD_SERVER 2442 , &peers, &G.script_name
2316 &G.if_name, 2443 IF_FEATURE_NTPD_SERVER(, &G.if_name)
2317#endif 2444 , &G.verbose
2318 &G.verbose); 2445 );
2319 2446
2320// if (opts & OPT_x) /* disable stepping, only slew is allowed */ 2447// if (opts & OPT_x) /* disable stepping, only slew is allowed */
2321// G.time_was_stepped = 1; 2448// G.time_was_stepped = 1;
@@ -2341,19 +2468,107 @@ static NOINLINE void ntp_init(char **argv)
2341 logmode = LOGMODE_NONE; 2468 logmode = LOGMODE_NONE;
2342 } 2469 }
2343 2470
2471#if ENABLE_FEATURE_NTP_AUTH
2472 if (opts & OPT_k) {
2473 char *tokens[4];
2474 parser_t *parser;
2475
2476 parser = config_open(key_file_path);
2477 while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL | PARSE_MIN_DIE) == 3) {
2478 key_entry_t *key_entry;
2479 char buffer[40];
2480 smalluint hash_type;
2481 smalluint msg_size;
2482 smalluint key_length;
2483 char *key;
2484
2485 if ((tokens[1][0] | 0x20) == 'm')
2486 /* supports 'M' and 'md5' formats */
2487 hash_type = HASH_MD5;
2488 else
2489 if (strncasecmp(tokens[1], "sha", 3) == 0)
2490 /* supports 'sha' and 'sha1' formats */
2491 hash_type = HASH_SHA1;
2492 else
2493 bb_error_msg_and_die("only MD5 and SHA1 keys supported");
2494/* man ntp.keys:
2495 * MD5 The key is 1 to 16 printable characters terminated by an EOL,
2496 * whitespace, or a # (which is the "start of comment" character).
2497 * SHA
2498 * SHA1
2499 * RMD160 The key is a hex-encoded ASCII string of 40 characters, which
2500 * is truncated as necessary.
2501 */
2502 key_length = strnlen(tokens[2], sizeof(buffer)+1);
2503 if (key_length >= sizeof(buffer)+1) {
2504 err:
2505 bb_error_msg_and_die("malformed key at line %u", parser->lineno);
2506 }
2507 if (hash_type == HASH_MD5) {
2508 key = tokens[2];
2509 msg_size = NTP_MSGSIZE_MD5_AUTH;
2510 } else /* it's hash_type == HASH_SHA1 */
2511 if (!(key_length & 1)) {
2512 key_length >>= 1;
2513 if (!hex2bin(buffer, tokens[2], key_length))
2514 goto err;
2515 key = buffer;
2516 msg_size = NTP_MSGSIZE_SHA1_AUTH;
2517 } else {
2518 goto err;
2519 }
2520 key_entry = xzalloc(sizeof(*key_entry) + key_length);
2521 key_entry->type = hash_type;
2522 key_entry->msg_size = msg_size;
2523 key_entry->key_length = key_length;
2524 memcpy(key_entry->key, key, key_length);
2525 key_entry->id = xatou_range(tokens[0], 1, MAX_KEY_NUMBER);
2526 llist_add_to(&key_entries, key_entry);
2527 }
2528 config_close(parser);
2529 }
2530#endif
2344 if (peers) { 2531 if (peers) {
2532#if ENABLE_FEATURE_NTP_AUTH
2533 while (peers) {
2534 char *peer = llist_pop(&peers);
2535 key_entry_t *key_entry = NULL;
2536 if (strncmp(peer, "keyno:", 6) == 0) {
2537 char *end;
2538 int key_id;
2539 peer += 6;
2540 end = strchr(peer, ':');
2541 *end = '\0';
2542 key_id = xatou_range(peer, 1, MAX_KEY_NUMBER);
2543 *end = ':';
2544 key_entry = find_key_entry(key_entries, key_id);
2545 peer = end + 1;
2546 }
2547 add_peers(peer, key_entry);
2548 }
2549#else
2345 while (peers) 2550 while (peers)
2346 add_peers(llist_pop(&peers)); 2551 add_peers(llist_pop(&peers), NULL);
2552#endif
2347 } 2553 }
2348#if ENABLE_FEATURE_NTPD_CONF 2554#if ENABLE_FEATURE_NTPD_CONF
2349 else { 2555 else {
2350 parser_t *parser; 2556 parser_t *parser;
2351 char *token[3]; 2557 char *token[3 + 2*ENABLE_FEATURE_NTP_AUTH];
2352 2558
2353 parser = config_open("/etc/ntp.conf"); 2559 parser = config_open("/etc/ntp.conf");
2354 while (config_read(parser, token, 3, 1, "# \t", PARSE_NORMAL)) { 2560 while (config_read(parser, token, 3 + 2*ENABLE_FEATURE_NTP_AUTH, 1, "# \t", PARSE_NORMAL)) {
2355 if (strcmp(token[0], "server") == 0 && token[1]) { 2561 if (strcmp(token[0], "server") == 0 && token[1]) {
2356 add_peers(token[1]); 2562# if ENABLE_FEATURE_NTP_AUTH
2563 key_entry_t *key_entry = NULL;
2564 if (token[2] && token[3] && strcmp(token[2], "key") == 0) {
2565 unsigned key_id = xatou_range(token[3], 1, MAX_KEY_NUMBER);
2566 key_entry = find_key_entry(key_entries, key_id);
2567 }
2568 add_peers(token[1], key_entry);
2569# else
2570 add_peers(token[1], NULL);
2571# endif
2357 continue; 2572 continue;
2358 } 2573 }
2359 bb_error_msg("skipping %s:%u: unimplemented command '%s'", 2574 bb_error_msg("skipping %s:%u: unimplemented command '%s'",
@@ -2394,6 +2609,7 @@ static NOINLINE void ntp_init(char **argv)
2394 | (1 << SIGCHLD) 2609 | (1 << SIGCHLD)
2395 , SIG_IGN 2610 , SIG_IGN
2396 ); 2611 );
2612//TODO: free unused elements of key_entries?
2397} 2613}
2398 2614
2399int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; 2615int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;