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>