Annotation of embedaddon/ntp/ntpd/ntp_signd.c, revision 1.1.1.1
1.1 misho 1: /* Copyright 2008, Red Hat, Inc.
2: Copyright 2008, Andrew Tridgell.
3: Licenced under the same terms as NTP itself.
4: */
5: #ifdef HAVE_CONFIG_H
6: #include <config.h>
7: #endif
8:
9: #ifdef HAVE_NTP_SIGND
10:
11: #include "ntpd.h"
12: #include "ntp_io.h"
13: #include "ntp_stdlib.h"
14: #include "ntp_unixtime.h"
15: #include "ntp_control.h"
16: #include "ntp_string.h"
17:
18: #include <stdio.h>
19: #include <stddef.h>
20: #ifdef HAVE_LIBSCF_H
21: #include <libscf.h>
22: #include <unistd.h>
23: #endif /* HAVE_LIBSCF_H */
24:
25: #include <sys/un.h>
26:
27: /* socket routines by tridge - from junkcode.samba.org */
28:
29: /*
30: connect to a unix domain socket
31: */
32: static int
33: ux_socket_connect(const char *name)
34: {
35: int fd;
36: struct sockaddr_un addr;
37: if (!name) {
38: return -1;
39: }
40:
41: memset(&addr, 0, sizeof(addr));
42: addr.sun_family = AF_UNIX;
43: strncpy(addr.sun_path, name, sizeof(addr.sun_path));
44:
45: fd = socket(AF_UNIX, SOCK_STREAM, 0);
46: if (fd == -1) {
47: return -1;
48: }
49:
50: if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
51: close(fd);
52: return -1;
53: }
54:
55: return fd;
56: }
57:
58:
59: /*
60: keep writing until its all sent
61: */
62: static int
63: write_all(int fd, const void *buf, size_t len)
64: {
65: size_t total = 0;
66: while (len) {
67: int n = write(fd, buf, len);
68: if (n <= 0) return total;
69: buf = n + (char *)buf;
70: len -= n;
71: total += n;
72: }
73: return total;
74: }
75:
76: /*
77: keep reading until its all read
78: */
79: static int
80: read_all(int fd, void *buf, size_t len)
81: {
82: size_t total = 0;
83: while (len) {
84: int n = read(fd, buf, len);
85: if (n <= 0) return total;
86: buf = n + (char *)buf;
87: len -= n;
88: total += n;
89: }
90: return total;
91: }
92:
93: /*
94: send a packet in length prefix format
95: */
96: static int
97: send_packet(int fd, const char *buf, uint32_t len)
98: {
99: uint32_t net_len = htonl(len);
100: if (write_all(fd, &net_len, sizeof(net_len)) != sizeof(net_len)) return -1;
101: if (write_all(fd, buf, len) != len) return -1;
102: return 0;
103: }
104:
105: /*
106: receive a packet in length prefix format
107: */
108: static int
109: recv_packet(int fd, char **buf, uint32_t *len)
110: {
111: if (read_all(fd, len, sizeof(*len)) != sizeof(*len)) return -1;
112: *len = ntohl(*len);
113: (*buf) = emalloc(*len);
114: if (read_all(fd, *buf, *len) != *len) {
115: free(*buf);
116: return -1;
117: }
118: return 0;
119: }
120:
121: void
122: send_via_ntp_signd(
123: struct recvbuf *rbufp, /* receive packet pointer */
124: int xmode,
125: keyid_t xkeyid,
126: int flags,
127: struct pkt *xpkt
128: )
129: {
130:
131: /* We are here because it was detected that the client
132: * sent an all-zero signature, and we therefore know
133: * it's windows trying to talk to an AD server
134: *
135: * Because we don't want to dive into Samba's secrets
136: * database just to find the long-term kerberos key
137: * that is re-used as the NTP key, we instead hand the
138: * packet over to Samba to sign, and return to us.
139: *
140: * The signing method Samba will use is described by
141: * Microsoft in MS-SNTP, found here:
142: * http://msdn.microsoft.com/en-us/library/cc212930.aspx
143: */
144:
145: int fd, sendlen;
146: struct samba_key_in {
147: uint32_t version;
148: uint32_t op;
149: uint32_t packet_id;
150: uint32_t key_id_le;
151: struct pkt pkt;
152: } samba_pkt;
153:
154: struct samba_key_out {
155: uint32_t version;
156: uint32_t op;
157: uint32_t packet_id;
158: struct pkt pkt;
159: } samba_reply;
160:
161: char full_socket[256];
162:
163: char *reply = NULL;
164: uint32_t reply_len;
165:
166: memset(&samba_pkt, 0, sizeof(samba_pkt));
167: samba_pkt.op = 0; /* Sign message */
168: /* This will be echoed into the reply - a different
169: * impelementation might want multiple packets
170: * awaiting signing */
171:
172: samba_pkt.packet_id = 1;
173:
174: /* Swap the byte order back - it's actually little
175: * endian on the wire, but it was read above as
176: * network byte order */
177: samba_pkt.key_id_le = htonl(xkeyid);
178: samba_pkt.pkt = *xpkt;
179:
180: snprintf(full_socket, sizeof(full_socket), "%s/socket", ntp_signd_socket);
181:
182: fd = ux_socket_connect(full_socket);
183: /* Only continue with this if we can talk to Samba */
184: if (fd != -1) {
185: /* Send old packet to Samba, expect response */
186: /* Packet to Samba is quite simple:
187: All values BIG endian except key ID as noted
188: [packet size as BE] - 4 bytes
189: [protocol version (0)] - 4 bytes
190: [packet ID] - 4 bytes
191: [operation (sign message=0)] - 4 bytes
192: [key id] - LITTLE endian (as on wire) - 4 bytes
193: [message to sign] - as marshalled, without signature
194: */
195:
196: if (send_packet(fd, (char *)&samba_pkt, offsetof(struct samba_key_in, pkt) + LEN_PKT_NOMAC) != 0) {
197: /* Huh? could not talk to Samba... */
198: close(fd);
199: return;
200: }
201:
202: if (recv_packet(fd, &reply, &reply_len) != 0) {
203: if (reply) {
204: free(reply);
205: }
206: close(fd);
207: return;
208: }
209: /* Return packet is also simple:
210: [packet size] - network byte order - 4 bytes
211: [protocol version (0)] network byte order - - 4 bytes
212: [operation (signed success=3, failure=4)] network byte order - - 4 byte
213: (optional) [signed message] - as provided before, with signature appended
214: */
215:
216: if (reply_len <= sizeof(samba_reply)) {
217: memcpy(&samba_reply, reply, reply_len);
218: if (ntohl(samba_reply.op) == 3 && reply_len > offsetof(struct samba_key_out, pkt)) {
219: sendlen = reply_len - offsetof(struct samba_key_out, pkt);
220: xpkt = &samba_reply.pkt;
221: sendpkt(&rbufp->recv_srcadr, rbufp->dstadr, 0, xpkt, sendlen);
222: #ifdef DEBUG
223: if (debug)
224: printf(
225: "transmit ntp_signd packet: at %ld %s->%s mode %d keyid %08x len %d\n",
226: current_time, ntoa(&rbufp->dstadr->sin),
227: ntoa(&rbufp->recv_srcadr), xmode, xkeyid, sendlen);
228: #endif
229: }
230: }
231:
232: if (reply) {
233: free(reply);
234: }
235: close(fd);
236:
237: }
238: }
239: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>