3 /* Copyright 2008, Red Hat, Inc.
4 Copyright 2008, Andrew Tridgell.
5 Licenced under the same terms as NTP itself.
15 #include "ntp_stdlib.h"
16 #include "ntp_unixtime.h"
17 #include "ntp_control.h"
18 #include "ntp_string.h"
25 #endif /* HAVE_LIBSCF_H */
29 /* socket routines by tridge - from junkcode.samba.org */
32 connect to a unix domain socket
35 ux_socket_connect(const char *name
)
38 struct sockaddr_un addr
;
43 memset(&addr
, 0, sizeof(addr
));
44 addr
.sun_family
= AF_UNIX
;
45 strncpy(addr
.sun_path
, name
, sizeof(addr
.sun_path
));
47 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
52 if (connect(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)) == -1) {
62 keep writing until its all sent
65 write_all(int fd
, const void *buf
, size_t len
)
69 int n
= write(fd
, buf
, len
);
70 if (n
<= 0) return total
;
71 buf
= n
+ (char *)buf
;
79 keep reading until its all read
82 read_all(int fd
, void *buf
, size_t len
)
86 int n
= read(fd
, buf
, len
);
87 if (n
<= 0) return total
;
88 buf
= n
+ (char *)buf
;
96 send a packet in length prefix format
99 send_packet(int fd
, const char *buf
, uint32_t len
)
101 uint32_t net_len
= htonl(len
);
102 if (write_all(fd
, &net_len
, sizeof(net_len
)) != sizeof(net_len
)) return -1;
103 if (write_all(fd
, buf
, len
) != len
) return -1;
108 receive a packet in length prefix format
111 recv_packet(int fd
, char **buf
, uint32_t *len
)
113 if (read_all(fd
, len
, sizeof(*len
)) != sizeof(*len
)) return -1;
115 (*buf
) = emalloc(*len
);
116 if (read_all(fd
, *buf
, *len
) != *len
) {
125 struct recvbuf
*rbufp
, /* receive packet pointer */
133 /* We are here because it was detected that the client
134 * sent an all-zero signature, and we therefore know
135 * it's windows trying to talk to an AD server
137 * Because we don't want to dive into Samba's secrets
138 * database just to find the long-term kerberos key
139 * that is re-used as the NTP key, we instead hand the
140 * packet over to Samba to sign, and return to us.
142 * The signing method Samba will use is described by
143 * Microsoft in MS-SNTP, found here:
144 * http://msdn.microsoft.com/en-us/library/cc212930.aspx
148 struct samba_key_in
{
156 struct samba_key_out
{
163 char full_socket
[256];
168 memset(&samba_pkt
, 0, sizeof(samba_pkt
));
169 samba_pkt
.op
= 0; /* Sign message */
170 /* This will be echoed into the reply - a different
171 * impelementation might want multiple packets
172 * awaiting signing */
174 samba_pkt
.packet_id
= 1;
176 /* Swap the byte order back - it's actually little
177 * endian on the wire, but it was read above as
178 * network byte order */
179 samba_pkt
.key_id_le
= htonl(xkeyid
);
180 samba_pkt
.pkt
= *xpkt
;
182 snprintf(full_socket
, sizeof(full_socket
), "%s/socket", ntp_signd_socket
);
184 fd
= ux_socket_connect(full_socket
);
185 /* Only continue with this if we can talk to Samba */
187 /* Send old packet to Samba, expect response */
188 /* Packet to Samba is quite simple:
189 All values BIG endian except key ID as noted
190 [packet size as BE] - 4 bytes
191 [protocol version (0)] - 4 bytes
192 [packet ID] - 4 bytes
193 [operation (sign message=0)] - 4 bytes
194 [key id] - LITTLE endian (as on wire) - 4 bytes
195 [message to sign] - as marshalled, without signature
198 if (send_packet(fd
, (char *)&samba_pkt
, offsetof(struct samba_key_in
, pkt
) + LEN_PKT_NOMAC
) != 0) {
199 /* Huh? could not talk to Samba... */
204 if (recv_packet(fd
, &reply
, &reply_len
) != 0) {
211 /* Return packet is also simple:
212 [packet size] - network byte order - 4 bytes
213 [protocol version (0)] network byte order - - 4 bytes
214 [operation (signed success=3, failure=4)] network byte order - - 4 byte
215 (optional) [signed message] - as provided before, with signature appended
218 if (reply_len
<= sizeof(samba_reply
)) {
219 memcpy(&samba_reply
, reply
, reply_len
);
220 if (ntohl(samba_reply
.op
) == 3 && reply_len
> offsetof(struct samba_key_out
, pkt
)) {
221 sendlen
= reply_len
- offsetof(struct samba_key_out
, pkt
);
222 xpkt
= &samba_reply
.pkt
;
223 sendpkt(&rbufp
->recv_srcadr
, rbufp
->dstadr
, 0, xpkt
, sendlen
);
227 "transmit ntp_signd packet: at %ld %s->%s mode %d keyid %08x len %d\n",
228 current_time
, ntoa(&rbufp
->dstadr
->sin
),
229 ntoa(&rbufp
->recv_srcadr
), xmode
, xkeyid
, sendlen
);