File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / ntp_signd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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>