ntp: add support for MS-SNTP authentication in Samba
Add support for authenticating MS-SNTP responses in Samba (ntp_signd). Supported is currently only the old MS-SNTP authenticator field. It's disabled by default. It can be enabled with the --enable-ntp-signd configure option and the ntpsigndsocket directive, which specifies the location of the Samba ntp_signd socket.
This commit is contained in:
parent
2a8ce63fc7
commit
577aed4842
11 changed files with 514 additions and 12 deletions
14
conf.c
14
conf.c
|
@ -181,6 +181,9 @@ static IPAddr bind_cmd_address4, bind_cmd_address6;
|
|||
/* Path to the Unix domain command socket. */
|
||||
static char *bind_cmd_path;
|
||||
|
||||
/* Path to Samba (ntp_signd) socket. */
|
||||
static char *ntp_signd_socket = NULL;
|
||||
|
||||
/* Filename to use for storing pid of running chronyd, to prevent multiple
|
||||
* chronyds being started. */
|
||||
static char *pidfile;
|
||||
|
@ -361,6 +364,7 @@ CNF_Finalise(void)
|
|||
Free(leapsec_tz);
|
||||
Free(logdir);
|
||||
Free(bind_cmd_path);
|
||||
Free(ntp_signd_socket);
|
||||
Free(pidfile);
|
||||
Free(rtc_device);
|
||||
Free(rtc_file);
|
||||
|
@ -506,6 +510,8 @@ CNF_ParseLine(const char *filename, int number, char *line)
|
|||
parse_int(p, &min_sources);
|
||||
} else if (!strcasecmp(command, "noclientlog")) {
|
||||
no_client_log = parse_null(p);
|
||||
} else if (!strcasecmp(command, "ntpsigndsocket")) {
|
||||
parse_string(p, &ntp_signd_socket);
|
||||
} else if (!strcasecmp(command, "peer")) {
|
||||
parse_source(p, NTP_PEER, 0);
|
||||
} else if (!strcasecmp(command, "pidfile")) {
|
||||
|
@ -1736,6 +1742,14 @@ CNF_GetBindCommandAddress(int family, IPAddr *addr)
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
char *
|
||||
CNF_GetNtpSigndSocket(void)
|
||||
{
|
||||
return ntp_signd_socket;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
char *
|
||||
CNF_GetPidFile(void)
|
||||
{
|
||||
|
|
1
conf.h
1
conf.h
|
@ -76,6 +76,7 @@ extern void CNF_GetBindAddress(int family, IPAddr *addr);
|
|||
extern void CNF_GetBindAcquisitionAddress(int family, IPAddr *addr);
|
||||
extern void CNF_GetBindCommandAddress(int family, IPAddr *addr);
|
||||
extern char *CNF_GetBindCommandPath(void);
|
||||
extern char *CNF_GetNtpSigndSocket(void);
|
||||
extern char *CNF_GetPidFile(void);
|
||||
extern REF_LeapMode CNF_GetLeapSecMode(void);
|
||||
extern char *CNF_GetLeapSecTimezone(void);
|
||||
|
|
11
configure
vendored
11
configure
vendored
|
@ -99,6 +99,7 @@ For better control, use the options below.
|
|||
--without-seccomp Don't use seccomp even if it is available
|
||||
--disable-asyncdns Disable asynchronous name resolving
|
||||
--disable-forcednsretry Don't retry on permanent DNS error
|
||||
--enable-ntp-signd Enable support for MS-SNTP authentication in Samba
|
||||
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
|
||||
since 1970-01-01 [50*365 days ago]
|
||||
--with-user=USER Specify default chronyd user [root]
|
||||
|
@ -213,6 +214,7 @@ try_setsched=0
|
|||
try_lockmem=0
|
||||
feat_asyncdns=1
|
||||
feat_forcednsretry=1
|
||||
feat_ntp_signd=0
|
||||
ntp_era_split=""
|
||||
default_user="root"
|
||||
default_hwclockfile=""
|
||||
|
@ -317,6 +319,9 @@ do
|
|||
--disable-forcednsretry)
|
||||
feat_forcednsretry=0
|
||||
;;
|
||||
--enable-ntp-signd)
|
||||
feat_ntp_signd=1
|
||||
;;
|
||||
--with-ntp-era=* )
|
||||
ntp_era_split=`echo $option | sed -e 's/^.*=//;'`
|
||||
;;
|
||||
|
@ -432,6 +437,10 @@ fi
|
|||
if [ $feat_ntp = "1" ]; then
|
||||
add_def FEAT_NTP
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS ntp_core.o ntp_io.o ntp_sources.o"
|
||||
if [ $feat_ntp_signd = "1" ]; then
|
||||
add_def FEAT_SIGND
|
||||
EXTRA_OBJECTS="$EXTRA_OBJECTS ntp_signd.o"
|
||||
fi
|
||||
else
|
||||
feat_asyncdns=0
|
||||
fi
|
||||
|
@ -826,7 +835,7 @@ add_def MAIL_PROGRAM "\"$mail_program\""
|
|||
|
||||
common_features="`get_features IPV6 DEBUG`"
|
||||
chronyc_features="`get_features READLINE`"
|
||||
chronyd_features="`get_features CMDMON NTP REFCLOCK RTC PRIVDROP SCFILTER SECHASH ASYNCDNS`"
|
||||
chronyd_features="`get_features CMDMON NTP REFCLOCK RTC PRIVDROP SCFILTER SECHASH SIGND ASYNCDNS`"
|
||||
add_def CHRONYC_FEATURES "\"$chronyc_features $common_features\""
|
||||
add_def CHRONYD_FEATURES "\"$chronyd_features $common_features\""
|
||||
echo "Features : $chronyd_features $chronyc_features $common_features"
|
||||
|
|
|
@ -1760,6 +1760,20 @@ should result in lower and more consistent latency. It should not have
|
|||
significant impact on performance as *chronyd's* memory usage is modest. The
|
||||
*mlockall(2)* man page has more details.
|
||||
|
||||
[[ntpsigndsocket]]*ntpsigndsocket* _directory_::
|
||||
This directive specifies the location of the Samba *ntp_signd* socket when it
|
||||
is running as a Domain Controller (DC). If *chronyd* is compiled with this
|
||||
feature, responses to MS-SNTP clients will be signed by the *smbd* daemon. Note
|
||||
that MS-SNTP requests are not authenticated, so any NTP client can get
|
||||
responses authenticated with passwords of users in the domain. Access to the
|
||||
server should be carefully controlled.
|
||||
+
|
||||
An example of the directive is:
|
||||
+
|
||||
----
|
||||
ntpsigndsocket /var/lib/samba/ntp_signd
|
||||
----
|
||||
|
||||
[[pidfile]]*pidfile* _file_::
|
||||
*chronyd* always writes its process ID (PID) to a file, and checks this file on
|
||||
startup to see if another *chronyd* may already be running on the system. By
|
||||
|
|
|
@ -83,6 +83,7 @@ typedef enum {
|
|||
LOGF_Reference,
|
||||
LOGF_NtpIO,
|
||||
LOGF_NtpCore,
|
||||
LOGF_NtpSignd,
|
||||
LOGF_NtpSources,
|
||||
LOGF_Scheduler,
|
||||
LOGF_SourceStats,
|
||||
|
|
3
main.c
3
main.c
|
@ -35,6 +35,7 @@
|
|||
#include "local.h"
|
||||
#include "sys.h"
|
||||
#include "ntp_io.h"
|
||||
#include "ntp_signd.h"
|
||||
#include "ntp_sources.h"
|
||||
#include "ntp_core.h"
|
||||
#include "sources.h"
|
||||
|
@ -107,6 +108,7 @@ MAI_CleanupAndExit(void)
|
|||
TMC_Finalise();
|
||||
MNL_Finalise();
|
||||
CLG_Finalise();
|
||||
NSD_Finalise();
|
||||
NSR_Finalise();
|
||||
SST_Finalise();
|
||||
NCR_Finalise();
|
||||
|
@ -523,6 +525,7 @@ int main
|
|||
REF_Initialise();
|
||||
SST_Initialise();
|
||||
NSR_Initialise();
|
||||
NSD_Initialise();
|
||||
CLG_Initialise();
|
||||
MNL_Initialise();
|
||||
TMC_Initialise();
|
||||
|
|
26
ntp_core.c
26
ntp_core.c
|
@ -32,6 +32,7 @@
|
|||
#include "array.h"
|
||||
#include "ntp_core.h"
|
||||
#include "ntp_io.h"
|
||||
#include "ntp_signd.h"
|
||||
#include "memory.h"
|
||||
#include "sched.h"
|
||||
#include "reference.h"
|
||||
|
@ -919,24 +920,28 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
|||
|
||||
/* Authenticate the packet if needed */
|
||||
|
||||
if (auth_mode == AUTH_SYMMETRIC) {
|
||||
if (auth_mode == AUTH_SYMMETRIC || auth_mode == AUTH_MSSNTP) {
|
||||
/* Pre-compensate the transmit time by approx. how long it will
|
||||
take to generate the authentication data. */
|
||||
local_transmit.tv_usec += KEY_GetAuthDelay(key_id);
|
||||
local_transmit.tv_usec += auth_mode == AUTH_SYMMETRIC ?
|
||||
KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
|
||||
UTI_NormaliseTimeval(&local_transmit);
|
||||
UTI_TimevalToInt64(&local_transmit, &message.transmit_ts, &ts_fuzz);
|
||||
|
||||
if (auth_mode == AUTH_SYMMETRIC) {
|
||||
auth_len = KEY_GenerateAuth(key_id, (unsigned char *) &message,
|
||||
offsetof(NTP_Packet, auth_keyid),
|
||||
(unsigned char *)&message.auth_data, sizeof (message.auth_data));
|
||||
if (auth_len > 0) {
|
||||
(unsigned char *)&message.auth_data,
|
||||
sizeof (message.auth_data));
|
||||
if (!auth_len) {
|
||||
DEBUG_LOG(LOGF_NtpCore, "Could not generate auth data with key %"PRIu32, key_id);
|
||||
return 0;
|
||||
}
|
||||
message.auth_keyid = htonl(key_id);
|
||||
length += sizeof (message.auth_keyid) + auth_len;
|
||||
} else {
|
||||
DEBUG_LOG(LOGF_NtpCore,
|
||||
"Could not generate auth data with key %"PRIu32" to send packet",
|
||||
key_id);
|
||||
return 0;
|
||||
} else if (auth_mode == AUTH_MSSNTP) {
|
||||
/* MS-SNTP packets are signed (asynchronously) by ntp_signd */
|
||||
return NSD_SignAndSendPacket(key_id, &message, where_to, from, length);
|
||||
}
|
||||
} else {
|
||||
if (auth_mode == AUTH_CRYPTO_NAK) {
|
||||
|
@ -1755,6 +1760,9 @@ NCR_ProcessUnknown
|
|||
/* Reply with crypto-NAK */
|
||||
auth_mode = AUTH_CRYPTO_NAK;
|
||||
break;
|
||||
case AUTH_MSSNTP:
|
||||
/* Ignore the failure (MS-SNTP servers don't check client MAC) */
|
||||
break;
|
||||
default:
|
||||
/* Discard packets in other modes */
|
||||
DEBUG_LOG(LOGF_NtpCore, "NTP packet discarded auth_mode=%d", auth_mode);
|
||||
|
|
380
ntp_signd.c
Normal file
380
ntp_signd.c
Normal file
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2016
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Support for MS-SNTP authentication in Samba (ntp_signd)
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincl.h"
|
||||
|
||||
#include "array.h"
|
||||
#include "conf.h"
|
||||
#include "logging.h"
|
||||
#include "ntp_io.h"
|
||||
#include "ntp_signd.h"
|
||||
#include "sched.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Declarations per samba/source4/librpc/idl/ntp_signd.idl */
|
||||
|
||||
#define SIGND_VERSION 0
|
||||
|
||||
typedef enum {
|
||||
SIGN_TO_CLIENT = 0,
|
||||
ASK_SERVER_TO_SIGN = 1,
|
||||
CHECK_SERVER_SIGNATURE = 2,
|
||||
SIGNING_SUCCESS = 3,
|
||||
SIGNING_FAILURE = 4,
|
||||
} SigndOp;
|
||||
|
||||
typedef struct {
|
||||
uint32_t length;
|
||||
uint32_t version;
|
||||
uint32_t op;
|
||||
uint16_t packet_id;
|
||||
uint16_t _pad;
|
||||
uint32_t key_id;
|
||||
NTP_Packet packet_to_sign;
|
||||
} SigndRequest;
|
||||
|
||||
typedef struct {
|
||||
uint32_t length;
|
||||
uint32_t version;
|
||||
uint32_t op;
|
||||
uint32_t packet_id;
|
||||
NTP_Packet signed_packet;
|
||||
} SigndResponse;
|
||||
|
||||
typedef struct {
|
||||
NTP_Remote_Address remote_addr;
|
||||
NTP_Local_Address local_addr;
|
||||
|
||||
int sent;
|
||||
int received;
|
||||
int request_length;
|
||||
struct timeval request_tv;
|
||||
SigndRequest request;
|
||||
SigndResponse response;
|
||||
} SignInstance;
|
||||
|
||||
/* As the communication with ntp_signd is asynchronous, incoming packets are
|
||||
saved in a queue in order to avoid loss when they come in bursts */
|
||||
|
||||
#define MAX_QUEUE_LENGTH 16U
|
||||
#define NEXT_QUEUE_INDEX(index) (((index) + 1) % MAX_QUEUE_LENGTH)
|
||||
#define IS_QUEUE_EMPTY() (queue_head == queue_tail)
|
||||
|
||||
/* Fixed-size array of SignInstance */
|
||||
static ARR_Instance queue;
|
||||
static unsigned int queue_head;
|
||||
static unsigned int queue_tail;
|
||||
|
||||
#define INVALID_SOCK_FD -1
|
||||
|
||||
/* Unix domain socket connected to ntp_signd */
|
||||
static int sock_fd;
|
||||
|
||||
#define MIN_AUTH_DELAY 1.0e-5
|
||||
#define MAX_AUTH_DELAY 1.0e-2
|
||||
|
||||
/* Average time needed for signing one packet. This is used to adjust the
|
||||
transmit timestamp in NTP packets. The timestamp won't be very accurate as
|
||||
the delay is variable, but it should be good enough for MS-SNTP clients. */
|
||||
static double auth_delay;
|
||||
|
||||
/* Flag indicating if the MS-SNTP authentication is enabled */
|
||||
static int enabled;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void read_write_socket(int sock_fd, int event, void *anything);
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
close_socket(void)
|
||||
{
|
||||
SCH_RemoveFileHandler(sock_fd);
|
||||
close(sock_fd);
|
||||
sock_fd = INVALID_SOCK_FD;
|
||||
|
||||
/* Empty the queue */
|
||||
queue_head = queue_tail = 0;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static int
|
||||
open_socket(void)
|
||||
{
|
||||
struct sockaddr_un s;
|
||||
|
||||
if (sock_fd >= 0)
|
||||
return 1;
|
||||
|
||||
sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock_fd < 0) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Could not open signd socket : %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
UTI_FdSetCloexec(sock_fd);
|
||||
SCH_AddFileHandler(sock_fd, SCH_FILE_INPUT, read_write_socket, NULL);
|
||||
|
||||
s.sun_family = AF_UNIX;
|
||||
if (snprintf(s.sun_path, sizeof (s.sun_path), "%s/socket",
|
||||
CNF_GetNtpSigndSocket()) >= sizeof (s.sun_path)) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "signd socket path too long");
|
||||
close_socket();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (connect(sock_fd, (struct sockaddr *)&s, sizeof (s)) < 0) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Could not connect to signd : %s", strerror(errno));
|
||||
close_socket();
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Connected to signd");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
process_response(SignInstance *inst)
|
||||
{
|
||||
struct timeval tv;
|
||||
double delay;
|
||||
|
||||
if (ntohs(inst->request.packet_id) != ntohl(inst->response.packet_id)) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Invalid response ID");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ntohl(inst->response.op) != SIGNING_SUCCESS) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Signing failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the file descriptor is still valid */
|
||||
if (!NIO_IsServerSocket(inst->local_addr.sock_fd)) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Invalid NTP socket");
|
||||
return;
|
||||
}
|
||||
|
||||
SCH_GetLastEventTime(NULL, NULL, &tv);
|
||||
UTI_DiffTimevalsToDouble(&delay, &tv, &inst->request_tv);
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Signing succeeded (delay %f)", delay);
|
||||
|
||||
/* Send the signed NTP packet */
|
||||
NIO_SendPacket(&inst->response.signed_packet, &inst->remote_addr, &inst->local_addr,
|
||||
ntohl(inst->response.length) + sizeof (inst->response.length) -
|
||||
offsetof(SigndResponse, signed_packet));
|
||||
|
||||
/* Update exponential moving average of the authentication delay */
|
||||
delay = CLAMP(MIN_AUTH_DELAY, delay, MAX_AUTH_DELAY);
|
||||
auth_delay += 0.1 * (delay - auth_delay);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
read_write_socket(int sock_fd, int event, void *anything)
|
||||
{
|
||||
SignInstance *inst;
|
||||
uint32_t response_length;
|
||||
int s;
|
||||
|
||||
inst = ARR_GetElement(queue, queue_head);
|
||||
|
||||
if (event == SCH_FILE_OUTPUT) {
|
||||
assert(!IS_QUEUE_EMPTY());
|
||||
assert(inst->sent < inst->request_length);
|
||||
|
||||
if (!inst->sent)
|
||||
SCH_GetLastEventTime(NULL, NULL, &inst->request_tv);
|
||||
|
||||
s = send(sock_fd, (char *)&inst->request + inst->sent,
|
||||
inst->request_length - inst->sent, 0);
|
||||
|
||||
if (s < 0) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "signd socket error: %s", strerror(errno));
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Sent %d bytes to signd", s);
|
||||
inst->sent += s;
|
||||
|
||||
/* Try again later if the request is not complete yet */
|
||||
if (inst->sent < inst->request_length)
|
||||
return;
|
||||
|
||||
/* Disable output and wait for a response */
|
||||
SCH_SetFileHandlerEvents(sock_fd, SCH_FILE_INPUT);
|
||||
}
|
||||
|
||||
if (event == SCH_FILE_INPUT) {
|
||||
if (IS_QUEUE_EMPTY()) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Unexpected signd response");
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(inst->received < sizeof (inst->response));
|
||||
s = recv(sock_fd, (char *)&inst->response + inst->received,
|
||||
sizeof (inst->response) - inst->received, 0);
|
||||
|
||||
if (s <= 0) {
|
||||
if (s < 0)
|
||||
DEBUG_LOG(LOGF_NtpSignd, "signd socket error: %s", strerror(errno));
|
||||
else
|
||||
DEBUG_LOG(LOGF_NtpSignd, "signd socket closed");
|
||||
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Received %d bytes from signd", s);
|
||||
inst->received += s;
|
||||
|
||||
if (inst->received < sizeof (inst->response.length))
|
||||
return;
|
||||
|
||||
response_length = ntohl(inst->response.length) + sizeof (inst->response.length);
|
||||
|
||||
if (response_length < offsetof(SigndResponse, signed_packet) ||
|
||||
response_length > sizeof (SigndResponse)) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Invalid response length");
|
||||
close_socket();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for more data if not complete yet */
|
||||
if (inst->received < response_length)
|
||||
return;
|
||||
|
||||
process_response(inst);
|
||||
|
||||
/* Move the head and enable output for the next packet */
|
||||
queue_head = NEXT_QUEUE_INDEX(queue_head);
|
||||
if (!IS_QUEUE_EMPTY())
|
||||
SCH_SetFileHandlerEvents(sock_fd, SCH_FILE_INPUT | SCH_FILE_OUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NSD_Initialise()
|
||||
{
|
||||
sock_fd = INVALID_SOCK_FD;
|
||||
auth_delay = MIN_AUTH_DELAY;
|
||||
enabled = CNF_GetNtpSigndSocket() && CNF_GetNtpSigndSocket()[0];
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
queue = ARR_CreateInstance(sizeof (SignInstance));
|
||||
ARR_SetSize(queue, MAX_QUEUE_LENGTH);
|
||||
queue_head = queue_tail = 0;
|
||||
|
||||
LOG(LOGS_INFO, LOGF_NtpSignd, "MS-SNTP authentication enabled");
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
NSD_Finalise()
|
||||
{
|
||||
if (!enabled)
|
||||
return;
|
||||
if (sock_fd != INVALID_SOCK_FD)
|
||||
close_socket();
|
||||
ARR_DestroyInstance(queue);
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
extern int NSD_GetAuthDelay(uint32_t key_id)
|
||||
{
|
||||
return auth_delay * 1.0e6;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int
|
||||
NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length)
|
||||
{
|
||||
SignInstance *inst;
|
||||
|
||||
if (!enabled) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "signd disabled");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (queue_head == NEXT_QUEUE_INDEX(queue_tail)) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "signd queue full");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (length != NTP_NORMAL_PACKET_LENGTH) {
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Invalid packet length");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!open_socket())
|
||||
return 0;
|
||||
|
||||
inst = ARR_GetElement(queue, queue_tail);
|
||||
inst->remote_addr = *remote_addr;
|
||||
inst->local_addr = *local_addr;
|
||||
inst->sent = 0;
|
||||
inst->received = 0;
|
||||
inst->request_length = offsetof(SigndRequest, packet_to_sign) + length;
|
||||
|
||||
/* The length field doesn't include itself */
|
||||
inst->request.length = htonl(inst->request_length - sizeof (inst->request.length));
|
||||
inst->request.version = htonl(SIGND_VERSION);
|
||||
inst->request.op = htonl(SIGN_TO_CLIENT);
|
||||
inst->request.packet_id = htons(queue_tail);
|
||||
inst->request._pad = 0;
|
||||
inst->request.key_id = htonl(key_id);
|
||||
|
||||
memcpy(&inst->request.packet_to_sign, packet, length);
|
||||
|
||||
/* Enable output if there was no pending request */
|
||||
if (IS_QUEUE_EMPTY())
|
||||
SCH_SetFileHandlerEvents(sock_fd, SCH_FILE_INPUT | SCH_FILE_OUTPUT);
|
||||
|
||||
queue_tail = NEXT_QUEUE_INDEX(queue_tail);
|
||||
|
||||
DEBUG_LOG(LOGF_NtpSignd, "Packet added to signd queue (%u:%u)",
|
||||
queue_head, queue_tail);
|
||||
|
||||
return 1;
|
||||
}
|
44
ntp_signd.h
Normal file
44
ntp_signd.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
||||
|
||||
**********************************************************************
|
||||
* Copyright (C) Miroslav Lichvar 2016
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
**********************************************************************
|
||||
|
||||
=======================================================================
|
||||
|
||||
Header for MS-SNTP authentication via Samba (ntp_signd) */
|
||||
|
||||
#ifndef GOT_NTP_SIGND_H
|
||||
#define GOT_NTP_SIGND_H
|
||||
|
||||
#include "addressing.h"
|
||||
#include "ntp.h"
|
||||
|
||||
/* Initialisation function */
|
||||
extern void NSD_Initialise(void);
|
||||
|
||||
/* Finalisation function */
|
||||
extern void NSD_Finalise(void);
|
||||
|
||||
/* Function to get an estimate of delay due to signing */
|
||||
extern int NSD_GetAuthDelay(uint32_t key_id);
|
||||
|
||||
/* Function to sign an NTP packet and send it */
|
||||
extern int NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length);
|
||||
|
||||
#endif
|
27
stubs.c
27
stubs.c
|
@ -38,6 +38,7 @@
|
|||
#include "ntp_core.h"
|
||||
#include "ntp_io.h"
|
||||
#include "ntp_sources.h"
|
||||
#include "ntp_signd.h"
|
||||
#include "privops.h"
|
||||
#include "refclock.h"
|
||||
#include "sched.h"
|
||||
|
@ -367,3 +368,29 @@ RCL_ReportSource(RPT_SourceReport *report, struct timeval *now)
|
|||
}
|
||||
|
||||
#endif /* !FEAT_REFCLOCK */
|
||||
|
||||
#ifndef FEAT_SIGND
|
||||
|
||||
void
|
||||
NSD_Initialise(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NSD_Finalise(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
NSD_GetAuthDelay(uint32_t key_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* !FEAT_SIGND */
|
||||
|
|
|
@ -6,6 +6,7 @@ cd ../..
|
|||
|
||||
for opts in \
|
||||
"--enable-debug" \
|
||||
"--enable-ntp-signd" \
|
||||
"--enable-scfilter" \
|
||||
"--disable-asyncdns" \
|
||||
"--disable-ipv6" \
|
||||
|
|
Loading…
Reference in a new issue