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>