Annotation of embedaddon/ntp/ntpd/ntp_signd.c, revision 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>