diff options
Diffstat (limited to 'networking/ntpd.c')
-rw-r--r-- | networking/ntpd.c | 266 |
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 | ||
232 | enum { | 248 | enum { |
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 | ||
294 | typedef struct { | 312 | typedef 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 | ||
319 | enum { | ||
320 | HASH_MD5, | ||
321 | HASH_SHA1, | ||
322 | }; | ||
323 | typedef 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 | |||
300 | typedef struct { | 332 | typedef 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 | ||
819 | static void | 859 | static void |
820 | add_peers(const char *s) | 860 | add_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 | ||
915 | static void | ||
916 | hash(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 | |||
940 | static void | ||
941 | hash_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 | |||
947 | static int | ||
948 | hashes_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 | |||
873 | static void | 956 | static void |
874 | send_query_to_peer(peer_t *p) | 957 | send_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 | ||
2390 | static key_entry_t * | ||
2391 | find_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 | ||
2399 | int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; | 2615 | int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; |