X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fbsd-security.c;fp=common-src%2Fbsd-security.c;h=2d0766d6cacfcdc06769f2521221e776c6e38249;hb=12179dea039515c06168c0037d048566a3f623de;hp=60e63d3eecf49868d0f494838892fe2a8c15bfc4;hpb=94c03cae686e4196a345d72452fda2a5203768ce;p=debian%2Famanda diff --git a/common-src/bsd-security.c b/common-src/bsd-security.c index 60e63d3..2d0766d 100644 --- a/common-src/bsd-security.c +++ b/common-src/bsd-security.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: bsd-security.c,v 1.54 2006/03/09 16:51:41 martinea Exp $ + * $Id: bsd-security.c,v 1.75 2006/07/19 17:41:14 martinea Exp $ * * "BSD" security module */ @@ -36,6 +36,7 @@ #include "event.h" #include "packet.h" #include "security.h" +#include "security-util.h" #include "stream.h" #include "version.h" @@ -65,130 +66,24 @@ #define bsdprintf(p) printf p #endif /* } */ -/* - * This is the private handle data - */ -struct bsd_handle { - /* - * This must be first. Instances of bsd_handle will be cast to - * security_handle_t's. - */ - security_handle_t sech; - - /* - * protocol handle for this request. Each request gets its own - * handle, so we differentiate packets for them with a "handle" header - * in each packet. - * - */ - int event_id; /* unique event_id */ - char *proto_handle; - - /* - * sequence number. - */ - int sequence; - - /* - * The remote host we're transmitting to - */ - char hostname[256]; - struct sockaddr_in peer; - - /* - * Function to call when recvpkt detects new incoming data for this - * handle - */ - void (*fn) P((void *, pkt_t *, security_status_t)); - - /* - * Argument for previous function - */ - void *arg; - - /* - * read (EV_WAIT) handle for a recv - */ - event_handle_t *ev_read; - - /* - * Timeout handle for a recv - */ - event_handle_t *ev_timeout; - - struct bsd_handle *prev, *next; -}; - -struct bsd_handle *bh_first=NULL, *bh_last=NULL; - -/* - * This is the internal security_stream data - */ -struct bsd_stream { - /* - * This must be first, because instances of this will be cast - * to security_stream_t's outside of this module. - */ - security_stream_t secstr; - - /* - * This is the file descriptor which we will do io on - */ - int fd; - - /* - * This is the file descriptor which we will listen for incoming - * connections on (for streams which receive connections) - */ - int socket; - - /* - * This is the local port this stream is bound to - */ - int port; - - /* - * This is the read event handle for this data stream - */ - event_handle_t *ev_read; - - /* - * This is the function and argument that is called when this stream - * is readable. It is passed a buffer of data read. - */ - void (*fn) P((void *, void *, ssize_t)); - void *arg; - - /* - * This is the buffer that we read data into that will be passed - * to the read callback. - */ - char databuf[NETWORK_BLOCK_BYTES]; -}; - /* * Interface functions */ -static void bsd_connect P((const char *, - char *(*)(char *, void *), - void (*)(void *, security_handle_t *, security_status_t), void *)); -static void bsd_accept P((int, int, void (*)(security_handle_t *, pkt_t *))); -static void bsd_close P((void *)); -static int bsd_sendpkt P((void *, pkt_t *)); -static void bsd_recvpkt P((void *, - void (*)(void *, pkt_t *, security_status_t), void *, int)); -static void bsd_recvpkt_cancel P((void *)); - -static void *bsd_stream_server P((void *)); -static int bsd_stream_accept P((void *)); -static void *bsd_stream_client P((void *, int)); -static void bsd_stream_close P((void *)); -static int bsd_stream_auth P((void *)); -static int bsd_stream_id P((void *)); -static int bsd_stream_write P((void *, const void *, size_t)); -static void bsd_stream_read P((void *, void (*)(void *, void *, ssize_t), - void *)); -static void bsd_stream_read_cancel P((void *)); +static void bsd_connect(const char *, char *(*)(char *, void *), + void (*)(void *, security_handle_t *, security_status_t), + void *, void *); +static void bsd_accept(const struct security_driver *, int, int, + void (*)(security_handle_t *, pkt_t *)); +static void bsd_close(void *); +static void * bsd_stream_server(void *); +static int bsd_stream_accept(void *); +static void * bsd_stream_client(void *, int); +static void bsd_stream_close(void *); +static int bsd_stream_auth(void *); +static int bsd_stream_id(void *); +static void bsd_stream_read(void *, void (*)(void *, void *, ssize_t), void *); +static ssize_t bsd_stream_read_sync(void *, void **); +static void bsd_stream_read_cancel(void *); /* * This is our interface to the outside world @@ -198,142 +93,54 @@ const security_driver_t bsd_security_driver = { bsd_connect, bsd_accept, bsd_close, - bsd_sendpkt, - bsd_recvpkt, - bsd_recvpkt_cancel, + udpbsd_sendpkt, + udp_recvpkt, + udp_recvpkt_cancel, bsd_stream_server, bsd_stream_accept, bsd_stream_client, bsd_stream_close, bsd_stream_auth, bsd_stream_id, - bsd_stream_write, + tcp_stream_write, bsd_stream_read, + bsd_stream_read_sync, bsd_stream_read_cancel, + sec_close_connection_none, }; /* * This is data local to the datagram socket. We have one datagram * per process, so it is global. */ -static struct { - dgram_t dgram; /* datagram to read/write from */ - struct sockaddr_in peer; /* who sent it to us */ - pkt_t pkt; /* parsed form of dgram */ - char *handle; /* handle from recvd packet */ - int sequence; /* seq no of packet */ - event_handle_t *ev_read; /* read event handle from dgram */ - int refcnt; /* number of handles blocked for reading */ -} netfd; +static udp_handle_t netfd; +static int not_init = 1; /* generate new handles from here */ static int newhandle = 0; -static int newevent = 0; - -/* - * We register one event handler for our network fd which takes - * care of all of our async requests. When all async requests - * have either been satisfied or cancelled, we unregister our - * network event handler. - */ -#define netfd_addref() do { \ - if (netfd.refcnt++ == 0) { \ - assert(netfd.ev_read == NULL); \ - netfd.ev_read = event_register(netfd.dgram.socket, EV_READFD, \ - netfd_read_callback, NULL); \ - } \ - assert(netfd.refcnt > 0); \ -} while (0) - -/* - * If this is the last request to be removed, then remove the - * reader event from the netfd. - */ -#define netfd_delref() do { \ - assert(netfd.refcnt > 0); \ - if (--netfd.refcnt == 0) { \ - assert(netfd.ev_read != NULL); \ - event_release(netfd.ev_read); \ - netfd.ev_read = NULL; \ - } \ -} while (0) - -/* - * This is the function and argument that is called when new requests - * arrive on the netfd. - */ -static void (*accept_fn) P((security_handle_t *, pkt_t *)); /* * These are the internal helper functions */ -static char *check_user P((struct bsd_handle *, const char *)); -static int inithandle P((struct bsd_handle *, struct hostent *, - int, char *, int)); -static const char *pkthdr2str P((const struct bsd_handle *, const pkt_t *)); -static int str2pkthdr P((void)); -static void netfd_read_callback P((void *)); -static void recvpkt_callback P((void *)); -static void recvpkt_timeout P((void *)); -static int recv_security_ok P((struct bsd_handle *)); -static void stream_read_callback P((void *)); - - -#if defined(SHOW_SECURITY_DETAIL) /* { */ -/* - * Display stat() information about a file. - */ -void show_stat_info(a, b) - char *a, *b; -{ - char *name = vstralloc(a, b, NULL); - struct stat sbuf; - struct passwd *pwptr; - char *owner; - struct group *grptr; - char *group; - - if (stat(name, &sbuf) != 0) { - bsdprintf(("%s: cannot stat %s: %s\n", - debug_prefix_time(NULL), name, strerror(errno))); - amfree(name); - return; - } - if ((pwptr = getpwuid(sbuf.st_uid)) == NULL) { - owner = alloc(NUM_STR_SIZE + 1); - snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid); - } else { - owner = stralloc(pwptr->pw_name); - } - if ((grptr = getgrgid(sbuf.st_gid)) == NULL) { - group = alloc(NUM_STR_SIZE + 1); - snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid); - } else { - group = stralloc(grptr->gr_name); - } - bsdprintf(("%s: processing file: %s\n", debug_prefix(NULL), name)); - bsdprintf(("%s: owner=%s group=%s mode=%03o\n", - debug_prefix(NULL), owner, group, (int) (sbuf.st_mode & 0777))); - amfree(name); - amfree(owner); - amfree(group); -} -#endif /* } */ +static void stream_read_callback(void *); +static void stream_read_sync_callback(void *); /* * Setup and return a handle outgoing to a client */ + static void -bsd_connect(hostname, conf_fn, fn, arg) - const char *hostname; - char *(*conf_fn) P((char *, void *)); - void (*fn) P((void *, security_handle_t *, security_status_t)); - void *arg; -{ - struct bsd_handle *bh; +bsd_connect( + const char * hostname, + char * (*conf_fn)(char *, void *), + void (*fn)(void *, security_handle_t *, security_status_t), + void * arg, + void * datap) +{ + struct sec_handle *bh; struct servent *se; struct hostent *he; - int port; + in_port_t port = 0; struct timeval sequence_time; amanda_timezone dontcare; int sequence; @@ -341,31 +148,40 @@ bsd_connect(hostname, conf_fn, fn, arg) assert(hostname != NULL); - bh = alloc(sizeof(*bh)); + (void)conf_fn; /* Quiet unused parameter warning */ + (void)datap; /* Quiet unused parameter warning */ + + bh = alloc(SIZEOF(*bh)); bh->proto_handle=NULL; + bh->udp = &netfd; security_handleinit(&bh->sech, &bsd_security_driver); /* * Only init the socket once */ - if (netfd.dgram.socket == 0) { + if (not_init == 1) { uid_t euid; dgram_zero(&netfd.dgram); - + euid = geteuid(); - seteuid(0); + seteuid((uid_t)0); dgram_bind(&netfd.dgram, &port); seteuid(euid); + netfd.handle = NULL; + netfd.pkt.body = NULL; + netfd.recv_security_ok = &bsd_recv_security_ok; + netfd.prefix_packet = &bsd_prefix_packet; /* * We must have a reserved port. Bomb if we didn't get one. */ if (port >= IPPORT_RESERVED) { security_seterror(&bh->sech, - "unable to bind to a reserved port (got port %d)", - port); + "unable to bind to a reserved port (got port %u)", + (unsigned int)port); (*fn)(arg, &bh->sech, S_ERROR); return; } + not_init = 0; } if ((he = gethostbyname(hostname)) == NULL) { @@ -374,32 +190,42 @@ bsd_connect(hostname, conf_fn, fn, arg) (*fn)(arg, &bh->sech, S_ERROR); return; } + bsdprintf(("Resolved hostname=%s\n", hostname)); if ((se = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL) - port = htons(AMANDA_SERVICE_DEFAULT); + port = (in_port_t)htons(AMANDA_SERVICE_DEFAULT); else - port = se->s_port; + port = (in_port_t)se->s_port; amanda_gettimeofday(&sequence_time, &dontcare); sequence = (int)sequence_time.tv_sec ^ (int)sequence_time.tv_usec; - handle=malloc(15); - snprintf(handle,14,"000-%08x", newhandle++); - if (inithandle(bh, he, port, handle, sequence) < 0) + handle=alloc(15); + snprintf(handle, 14, "000-%08x", (unsigned)newhandle++); + if (udp_inithandle(&netfd, bh, he, port, handle, sequence) < 0) { (*fn)(arg, &bh->sech, S_ERROR); + amfree(bh->hostname); + amfree(bh); + } else (*fn)(arg, &bh->sech, S_OK); + amfree(handle); } /* * Setup to accept new incoming connections */ static void -bsd_accept(in, out, fn) - int in, out; - void (*fn) P((security_handle_t *, pkt_t *)); +bsd_accept( + const struct security_driver * driver, + int in, + int out, + void (*fn)(security_handle_t *, pkt_t *)) { assert(in >= 0 && out >= 0); assert(fn != NULL); + (void)out; /* Quiet unused parameter warning */ + (void)driver; /* Quiet unused parameter warning */ + /* * We assume in and out point to the same socket, and just use * in. @@ -411,983 +237,67 @@ bsd_accept(in, out, fn) * the recvpkt callback will call this function when it discovers * new incoming connections */ - accept_fn = fn; - - netfd_addref(); -} - -/* - * Given a hostname and a port, setup a bsd_handle - */ -static int -inithandle(bh, he, port, handle, sequence) - struct bsd_handle *bh; - struct hostent *he; - int port; - char *handle; - int sequence; -{ - int i; - - assert(he != NULL); - assert(port > 0); - - /* - * Save the hostname and port info - */ - strncpy(bh->hostname, he->h_name, sizeof(bh->hostname) - 1); - bh->hostname[sizeof(bh->hostname) - 1] = '\0'; - bh->peer.sin_addr = *(struct in_addr *)he->h_addr; - bh->peer.sin_port = port; - bh->peer.sin_family = AF_INET; - - bh->prev = bh_last; - if(bh_last) {bh->prev->next = bh;} - if(!bh_first) {bh_first = bh;} - bh->next = NULL; - bh_last = bh; - - /* - * Do a forward lookup of the hostname. This is unnecessary if we - * are initiating the connection, but is very serious if we are - * receiving. We want to make sure the hostname - * resolves back to the remote ip for security reasons. - */ - if ((he = gethostbyname(bh->hostname)) == NULL) { - security_seterror(&bh->sech, - "%s: could not resolve hostname", bh->hostname); - return (-1); - } - /* - * Make sure the hostname matches. This should always work. - */ - if (strncasecmp(bh->hostname, he->h_name, strlen(bh->hostname)) != 0) { - security_seterror(&bh->sech, - "%s: did not resolve to %s", bh->hostname, bh->hostname); - return (-1); - } - - /* - * Now look for a matching ip address. - */ - for (i = 0; he->h_addr_list[i] != NULL; i++) { - if (memcmp(&bh->peer.sin_addr, he->h_addr_list[i], - sizeof(struct in_addr)) == 0) { - break; - } - } - - /* - * If we didn't find it, try the aliases. This is a workaround for - * Solaris if DNS goes over NIS. - */ - if (he->h_addr_list[i] == NULL) { - const char *ipstr = inet_ntoa(bh->peer.sin_addr); - for (i = 0; he->h_aliases[i] != NULL; i++) { - if (strcmp(he->h_aliases[i], ipstr) == 0) - break; - } - /* - * No aliases either. Failure. Someone is fooling with us or - * DNS is messed up. - */ - if (he->h_aliases[i] == NULL) { - security_seterror(&bh->sech, - "DNS check failed: no matching ip address for %s", - bh->hostname); - return (-1); - } - } - - bh->sequence = sequence; - bh->event_id = newevent++; - bh->proto_handle = handle; - bh->fn = NULL; - bh->arg = NULL; - bh->ev_read = NULL; - bh->ev_timeout = NULL; - - bsdprintf(("%s: adding handle '%s'\n", - debug_prefix_time(NULL), bh->proto_handle)); + netfd.accept_fn = fn; + netfd.recv_security_ok = &bsd_recv_security_ok; + netfd.prefix_packet = &bsd_prefix_packet; + netfd.driver = &bsd_security_driver; - return(0); + udp_addref(&netfd, &udp_netfd_read_callback); } /* * Frees a handle allocated by the above */ static void -bsd_close(cookie) - void *cookie; +bsd_close( + void * cookie) { - struct bsd_handle *bh = cookie; + struct sec_handle *bh = cookie; if(bh->proto_handle == NULL) { return; } - bsdprintf(("%s: close handle '%s'\n", + bsdprintf(("%s: bsd: close handle '%s'\n", debug_prefix_time(NULL), bh->proto_handle)); - bsd_recvpkt_cancel(bh); + udp_recvpkt_cancel(bh); if(bh->next) { bh->next->prev = bh->prev; } else { - bh_last = bh->prev; + netfd.bh_last = bh->prev; } if(bh->prev) { bh->prev->next = bh->next; } else { - bh_first = bh->next; + netfd.bh_first = bh->next; } + amfree(bh->proto_handle); + amfree(bh->hostname); amfree(bh); } -/* - * Transmit a packet. Add security information first. - */ -static int -bsd_sendpkt(cookie, pkt) - void *cookie; - pkt_t *pkt; -{ - struct bsd_handle *bh = cookie; - struct passwd *pwd; - - assert(bh != NULL); - assert(pkt != NULL); - - /* - * Initialize this datagram, and add the header - */ - dgram_zero(&netfd.dgram); - dgram_cat(&netfd.dgram, pkthdr2str(bh, pkt)); - - /* - * Add the security info. This depends on which kind of packet we're - * sending. - */ - switch (pkt->type) { - case P_REQ: - /* - * Requests get sent with our username in the body - */ - if ((pwd = getpwuid(geteuid())) == NULL) { - security_seterror(&bh->sech, - "can't get login name for my uid %ld", (long)getuid()); - return (-1); - } - dgram_cat(&netfd.dgram, "SECURITY USER %s\n", pwd->pw_name); - break; - - default: - break; - } - - /* - * Add the body, and send it - */ - dgram_cat(&netfd.dgram, pkt->body); - if (dgram_send_addr(bh->peer, &netfd.dgram) != 0) { - security_seterror(&bh->sech, - "send %s to %s failed: %s", pkt_type2str(pkt->type), - bh->hostname, strerror(errno)); - return (-1); - } - return (0); -} - -/* - * Set up to receive a packet asynchronously, and call back when it has - * been read. - */ -static void -bsd_recvpkt(cookie, fn, arg, timeout) - void *cookie, *arg; - void (*fn) P((void *, pkt_t *, security_status_t)); - int timeout; -{ - struct bsd_handle *bh = cookie; - - assert(bh != NULL); - assert(fn != NULL); - - - /* - * Subsequent recvpkt calls override previous ones - */ - if (bh->ev_read == NULL) { - netfd_addref(); - bh->ev_read = event_register(bh->event_id, EV_WAIT, - recvpkt_callback, bh); - } - if (bh->ev_timeout != NULL) - event_release(bh->ev_timeout); - if (timeout < 0) - bh->ev_timeout = NULL; - else - bh->ev_timeout = event_register(timeout, EV_TIME, recvpkt_timeout, bh); - bh->fn = fn; - bh->arg = arg; -} - -/* - * Remove a async receive request on this handle from the queue. - * If it is the last one to be removed, then remove the event - * handler for our network fd - */ -static void -bsd_recvpkt_cancel(cookie) - void *cookie; -{ - struct bsd_handle *bh = cookie; - - assert(bh != NULL); - - if (bh->ev_read != NULL) { - netfd_delref(); - event_release(bh->ev_read); - bh->ev_read = NULL; - } - - if (bh->ev_timeout != NULL) { - event_release(bh->ev_timeout); - bh->ev_timeout = NULL; - } -} - -/* - * Callback for received packets. This is the function bsd_recvpkt - * registers with the event handler. It is called when the event handler - * realizes that data is waiting to be read on the network socket. - */ -static void -netfd_read_callback(cookie) - void *cookie; -{ - struct bsd_handle *bh; - struct hostent *he; - int a; - - assert(cookie == NULL); - -#ifndef TEST /* { */ - /* - * Receive the packet. - */ - dgram_zero(&netfd.dgram); - if (dgram_recv(&netfd.dgram, 0, &netfd.peer) < 0) - return; -#endif /* !TEST */ /* } */ - - /* - * Parse the packet. - */ - if (str2pkthdr() < 0) - return; - - /* - * If there are events waiting on this handle, we're done - */ - bh = bh_first; - while(bh != NULL && (strcmp(bh->proto_handle, netfd.handle) != 0 || - bh->sequence != netfd.sequence || - bh->peer.sin_addr.s_addr != netfd.peer.sin_addr.s_addr || - bh->peer.sin_port != netfd.peer.sin_port)) { - bh = bh->next; - } - if (bh && event_wakeup(bh->event_id) > 0) - return; - - /* - * If we didn't find a handle, then check for a new incoming packet. - * If no accept handler was setup, then just return. - */ - if (accept_fn == NULL) - return; - - he = gethostbyaddr((void *)&netfd.peer.sin_addr, - (int)sizeof(netfd.peer.sin_addr), AF_INET); - if (he == NULL) - return; - bh = alloc(sizeof(*bh)); - bh->proto_handle=NULL; - security_handleinit(&bh->sech, &bsd_security_driver); - a = inithandle(bh, - he, - netfd.peer.sin_port, - netfd.handle, - netfd.sequence); - if (a < 0) { - if(bh->next) { - bh->next->prev = bh->prev; - } - else { - bh_last = bh->prev; - } - if(bh->prev) { - bh->prev->next = bh->next; - } - else { - bh_first = bh->prev; - } - - bsdprintf(("%s: closeX handle '%s'\n", - debug_prefix_time(NULL), bh->proto_handle)); - - amfree(bh); - return; - } - /* - * Check the security of the packet. If it is bad, then pass NULL - * to the accept function instead of a packet. - */ - if (recv_security_ok(bh) < 0) - (*accept_fn)(&bh->sech, NULL); - else - (*accept_fn)(&bh->sech, &netfd.pkt); -} - -/* - * This is called when a handle is woken up because data read off of the - * net is for it. - */ -static void -recvpkt_callback(cookie) - void *cookie; -{ - struct bsd_handle *bh = cookie; - void (*fn) P((void *, pkt_t *, security_status_t)); - void *arg; - - assert(bh != NULL); - bsdprintf(("%s: receive handle '%s' netfd '%s'\n", - debug_prefix_time(NULL), bh->proto_handle,netfd.handle)); - - if(strcmp(bh->proto_handle,netfd.handle) != 0) assert(1); - - /* if it didn't come from the same host/port, forget it */ - if (memcmp(&bh->peer.sin_addr, &netfd.peer.sin_addr, - sizeof(netfd.peer.sin_addr)) != 0 || - bh->peer.sin_port != netfd.peer.sin_port) { - netfd.handle = NULL; - return; - } - - /* - * We need to cancel the recvpkt request before calling the callback - * because the callback may reschedule us. - */ - fn = bh->fn; - arg = bh->arg; - bsd_recvpkt_cancel(bh); - - /* - * Check the security of the packet. If it is bad, then pass NULL - * to the packet handling function instead of a packet. - */ - if (recv_security_ok(bh) < 0) - (*fn)(arg, NULL, S_ERROR); - else - (*fn)(arg, &netfd.pkt, S_OK); -} - -/* - * This is called when a handle times out before receiving a packet. - */ -static void -recvpkt_timeout(cookie) - void *cookie; -{ - struct bsd_handle *bh = cookie; - void (*fn) P((void *, pkt_t *, security_status_t)); - void *arg; - - assert(bh != NULL); - - assert(bh->ev_timeout != NULL); - fn = bh->fn; - arg = bh->arg; - bsd_recvpkt_cancel(bh); - (*fn)(arg, NULL, S_TIMEOUT); - -} - -/* - * Check the security of a received packet. Returns negative on security - * violation, or returns 0 if ok. Removes the security info from the pkt_t. - */ -static int -recv_security_ok(bh) - struct bsd_handle *bh; -{ - char *tok, *security, *body, *result; - pkt_t *pkt = &netfd.pkt; - - /* - * Set this preempively before we mangle the body. - */ - security_seterror(&bh->sech, - "bad SECURITY line: '%s'", pkt->body); - - /* - * Now, find the SECURITY line in the body, and parse it out - * into an argv. - */ - if (strncmp(pkt->body, "SECURITY", sizeof("SECURITY") - 1) == 0) { - tok = strtok(pkt->body, " "); - assert(strcmp(tok, "SECURITY") == 0); - /* security info goes until the newline */ - security = strtok(NULL, "\n"); - body = strtok(NULL, ""); - /* - * If the body is f-ked, then try to recover - */ - if (body == NULL) { - if (security != NULL) - body = security + strlen(security) + 2; - else - body = pkt->body; - } - } else { - security = NULL; - body = pkt->body; - } - - /* - * We need to do different things depending on which type of packet - * this is. - */ - switch (pkt->type) { - case P_REQ: - /* - * Request packets must come from a reserved port - */ - if (ntohs(bh->peer.sin_port) >= IPPORT_RESERVED) { - security_seterror(&bh->sech, - "host %s: port %d not secure", bh->hostname, - ntohs(bh->peer.sin_port)); - return (-1); - } - - /* - * Request packets contain a remote username. We need to check - * that we allow it in. - * - * They will look like: - * SECURITY USER [username] - */ - - /* there must be some security info */ - if (security == NULL) { - security_seterror(&bh->sech, - "no bsd SECURITY for P_REQ"); - return (-1); - } - - /* second word must be USER */ - if ((tok = strtok(security, " ")) == NULL) - return (-1); /* default errmsg */ - if (strcmp(tok, "USER") != 0) { - security_seterror(&bh->sech, - "REQ SECURITY line parse error, expecting USER, got %s", tok); - return (-1); - } - - /* the third word is the username */ - if ((tok = strtok(NULL, "")) == NULL) - return (-1); /* default errmsg */ - if ((result = check_user(bh, tok)) != NULL) { - security_seterror(&bh->sech, "%s", result); - amfree(result); - return (-1); - } - - /* we're good to go */ - break; - default: - break; - } - - /* - * If there is security info at the front of the packet, we need to - * shift the rest of the data up and nuke it. - */ - if (body != pkt->body) - memmove(pkt->body, body, strlen(body) + 1); - return (0); -} - -static char * -check_user(bh, remoteuser) - struct bsd_handle *bh; - const char *remoteuser; -{ - struct passwd *pwd; - char *r; - char *result = NULL; - char *localuser = NULL; - - /* lookup our local user name */ - if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) { - return vstralloc("getpwnam(", CLIENT_LOGIN, ") fails", NULL); - } - - /* - * Make a copy of the user name in case getpw* is called by - * any of the lower level routines. - */ - localuser = stralloc(pwd->pw_name); - -#ifndef USE_AMANDAHOSTS - r = check_user_ruserok(bh->hostname, pwd, remoteuser); -#else - r = check_user_amandahosts(bh->hostname, pwd, remoteuser); -#endif - if (r != NULL) { - result = vstralloc("access as ", localuser, " not allowed", - " from ", remoteuser, "@", bh->hostname, - ": ", r, - NULL); - amfree(r); - } - amfree(localuser); - return result; -} - -/* - * See if a remote user is allowed in. This version uses ruserok() - * and friends. - * - * Returns 0 on success, or negative on error. - */ -char * -check_user_ruserok(host, pwd, remoteuser) - const char *host; - struct passwd *pwd; - const char *remoteuser; -{ - int saved_stderr; - int fd[2]; - FILE *fError; - amwait_t exitcode; - pid_t ruserok_pid; - pid_t pid; - char *es; - char *result; - int ok; - char number[NUM_STR_SIZE]; - uid_t myuid = getuid(); - - /* - * note that some versions of ruserok (eg SunOS 3.2) look in - * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to - * chdir ourselves. Sigh. - * - * And, believe it or not, some ruserok()'s try an initgroup just - * for the hell of it. Since we probably aren't root at this point - * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner" - * into our stderr output even though the initgroup failure is not a - * problem and is expected. Thanks a lot. Not. - */ - if (pipe(fd) != 0) { - return stralloc2("pipe() fails: ", strerror(errno)); - } - if ((ruserok_pid = fork()) < 0) { - return stralloc2("fork() fails: ", strerror(errno)); - } else if (ruserok_pid == 0) { - int ec; - - close(fd[0]); - fError = fdopen(fd[1], "w"); - /* pamper braindead ruserok's */ - if (chdir(pwd->pw_dir) != 0) { - fprintf(fError, "chdir(%s) failed: %s", - pwd->pw_dir, strerror(errno)); - fclose(fError); - exit(1); - } - -#if defined(SHOW_SECURITY_DETAIL) /* { */ - { - char *dir = stralloc(pwd->pw_dir); - - bsdprintf(("%s: calling ruserok(%s, %d, %s, %s)\n", - debug_prefix_time(NULL), - host, myuid == 0, remoteuser, pwd->pw_name)); - if (myuid == 0) { - bsdprintf(("%s: because you are running as root, ", - debug_prefix(NULL))); - bsdprintf(("/etc/hosts.equiv will not be used\n")); - } else { - show_stat_info("/etc/hosts.equiv", NULL); - } - show_stat_info(dir, "/.rhosts"); - amfree(dir); - } -#endif /* } */ - - saved_stderr = dup(2); - close(2); - if (open("/dev/null", O_RDWR) == -1) { - dbprintf(("Could not open /dev/null: %s\n", - strerror(errno))); - ec = 1; - } else { - ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN); - if (ok < 0) { - ec = 1; - } else { - ec = 0; - } - } - (void)dup2(saved_stderr,2); - close(saved_stderr); - exit(ec); - } - close(fd[1]); - fError = fdopen(fd[0], "r"); - - result = NULL; - while ((es = agets(fError)) != NULL) { - if (result == NULL) { - result = stralloc(""); - } else { - strappend(result, ": "); - } - strappend(result, es); - } - close(fd[0]); - - while (1) { - if ((pid = wait(&exitcode)) == (pid_t) -1) { - if (errno == EINTR) { - continue; - } - amfree(result); - return stralloc2("ruserok wait failed: %s", strerror(errno)); - } - if (pid == ruserok_pid) { - break; - } - } - if (WIFSIGNALED(exitcode)) { - amfree(result); - snprintf(number, sizeof(number), "%d", WTERMSIG(exitcode)); - return stralloc2("ruserok child got signal ", number); - } - if (WEXITSTATUS(exitcode) == 0) { - amfree(result); - } else if (result == NULL) { - result = stralloc("ruserok failed"); - } - - return result; -} - -/* - * Check to see if a user is allowed in. This version uses .amandahosts - * Returns -1 on failure, or 0 on success. - */ -char * -check_user_amandahosts(host, pwd, remoteuser) - const char *host; - struct passwd *pwd; - const char *remoteuser; -{ - char *line = NULL; - char *filehost; - const char *fileuser; - char *ptmp = NULL; - char *result = NULL; - FILE *fp = NULL; - int found; - struct stat sbuf; - char n1[NUM_STR_SIZE]; - char n2[NUM_STR_SIZE]; - int hostmatch; - int usermatch; - uid_t localuid; - char *localuser = NULL; - - /* - * Save copies of what we need from the passwd structure in case - * any other code calls getpw*. - */ - localuid = pwd->pw_uid; - localuser = stralloc(pwd->pw_name); - - ptmp = stralloc2(pwd->pw_dir, "/.amandahosts"); -#if defined(SHOW_SECURITY_DETAIL) /* { */ - show_stat_info(ptmp, "");; -#endif /* } */ - if ((fp = fopen(ptmp, "r")) == NULL) { - result = vstralloc("cannot open ", ptmp, ": ", strerror(errno), NULL); - amfree(ptmp); - amfree(localuser); - return result; - } - - /* - * Make sure the file is owned by the Amanda user and does not - * have any group/other access allowed. - */ - if (fstat(fileno(fp), &sbuf) != 0) { - result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL); - goto common_exit; - } - if (sbuf.st_uid != localuid) { - snprintf(n1, sizeof(n1), "%ld", (long)sbuf.st_uid); - snprintf(n2, sizeof(n2), "%ld", (long)localuid); - result = vstralloc(ptmp, ": ", - "owned by id ", n1, - ", should be ", n2, - NULL); - goto common_exit; - } - if ((sbuf.st_mode & 077) != 0) { - result = stralloc2(ptmp, - ": incorrect permissions; file must be accessible only by its owner"); - goto common_exit; - } - - /* - * Now, scan the file for the host/user. - */ - found = 0; - while ((line = agets(fp)) != NULL) { -#if defined(SHOW_SECURITY_DETAIL) /* { */ - bsdprintf(("%s: processing line: <%s>\n", debug_prefix(NULL), line)); -#endif /* } */ - /* get the host out of the file */ - if ((filehost = strtok(line, " \t")) == NULL) { - amfree(line); - continue; - } - - /* get the username. If no user specified, then use the local user */ - if ((fileuser = strtok(NULL, " \t")) == NULL) { - fileuser = localuser; - } - - hostmatch = (strcasecmp(filehost, host) == 0); - usermatch = (strcasecmp(fileuser, remoteuser) == 0); -#if defined(SHOW_SECURITY_DETAIL) /* { */ - bsdprintf(("%s: comparing \"%s\" with\n", debug_prefix(NULL), filehost)); - bsdprintf(("%s: \"%s\" (%s)\n", host, - debug_prefix(NULL), hostmatch ? "match" : "no match")); - bsdprintf(("%s: and \"%s\" with\n", fileuser, debug_prefix(NULL))); - bsdprintf(("%s: \"%s\" (%s)\n", remoteuser, - debug_prefix(NULL), usermatch ? "match" : "no match")); -#endif /* } */ - amfree(line); - /* compare */ - if (hostmatch && usermatch) { - /* success */ - found = 1; - break; - } - } - if (! found) { - result = vstralloc(ptmp, ": ", - "\"", host, " ", remoteuser, "\"", - " entry not found", - NULL); - } - -common_exit: - - afclose(fp); - amfree(ptmp); - amfree(line); - amfree(localuser); - - return result; -} - -/* return 1 on success, 0 on failure */ -int -check_security(addr, str, cksum, errstr) -struct sockaddr_in *addr; -char *str; -unsigned long cksum; -char **errstr; -{ - char *remotehost = NULL, *remoteuser = NULL; - char *bad_bsd = NULL; - struct hostent *hp; - struct passwd *pwptr; - int myuid, i, j; - char *s, *fp; - int ch; - - *errstr = NULL; - - /* what host is making the request? */ - - hp = gethostbyaddr((char *)&addr->sin_addr, sizeof(addr->sin_addr), - AF_INET); - if(hp == NULL) { - /* XXX include remote address in message */ - *errstr = vstralloc("[", - "addr ", inet_ntoa(addr->sin_addr), ": ", - "hostname lookup failed", - "]", NULL); - return 0; - } - remotehost = stralloc(hp->h_name); - - /* Now let's get the hostent for that hostname */ - hp = gethostbyname( remotehost ); - if(hp == NULL) { - /* XXX include remote hostname in message */ - *errstr = vstralloc("[", - "host ", remotehost, ": ", - "hostname lookup failed", - "]", NULL); - amfree(remotehost); - return 0; - } - - /* Verify that the hostnames match -- they should theoretically */ - if( strncasecmp( remotehost, hp->h_name, strlen(remotehost)+1 ) != 0 ) { - *errstr = vstralloc("[", - "hostnames do not match: ", - remotehost, " ", hp->h_name, - "]", NULL); - amfree(remotehost); - return 0; - } - - /* Now let's verify that the ip which gave us this hostname - * is really an ip for this hostname; or is someone trying to - * break in? (THIS IS THE CRUCIAL STEP) - */ - for (i = 0; hp->h_addr_list[i]; i++) { - if (memcmp(hp->h_addr_list[i], - (char *) &addr->sin_addr, sizeof(addr->sin_addr)) == 0) - break; /* name is good, keep it */ - } - - /* If we did not find it, your DNS is messed up or someone is trying - * to pull a fast one on you. :( - */ - - /* Check even the aliases list. Work around for Solaris if dns goes over NIS */ - - if( !hp->h_addr_list[i] ) { - for (j = 0; hp->h_aliases[j] !=0 ; j++) { - if ( strcmp(hp->h_aliases[j],inet_ntoa(addr->sin_addr)) == 0) - break; /* name is good, keep it */ - } - if( !hp->h_aliases[j] ) { - *errstr = vstralloc("[", - "ip address ", inet_ntoa(addr->sin_addr), - " is not in the ip list for ", remotehost, - "]", - NULL); - amfree(remotehost); - return 0; - } - } - - /* next, make sure the remote port is a "reserved" one */ - - if(ntohs(addr->sin_port) >= IPPORT_RESERVED) { - char number[NUM_STR_SIZE]; - - snprintf(number, sizeof(number), "%d", ntohs(addr->sin_port)); - *errstr = vstralloc("[", - "host ", remotehost, ": ", - "port ", number, " not secure", - "]", NULL); - amfree(remotehost); - return 0; - } - - /* extract the remote user name from the message */ - - s = str; - ch = *s++; - - bad_bsd = vstralloc("[", - "host ", remotehost, ": ", - "bad bsd security line", - "]", NULL); - -#define sc "USER " - if(strncmp(s - 1, sc, sizeof(sc)-1) != 0) { - *errstr = bad_bsd; - bad_bsd = NULL; - amfree(remotehost); - return 0; - } - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc - - skip_whitespace(s, ch); - if(ch == '\0') { - *errstr = bad_bsd; - bad_bsd = NULL; - amfree(remotehost); - return 0; - } - fp = s - 1; - skip_non_whitespace(s, ch); - s[-1] = '\0'; - remoteuser = stralloc(fp); - s[-1] = ch; - amfree(bad_bsd); - - /* lookup our local user name */ - - myuid = getuid(); - if((pwptr = getpwuid(myuid)) == NULL) - error("error [getpwuid(%d) fails]", myuid); - - dbprintf(("bsd security: remote host %s user %s local user %s\n", - remotehost, remoteuser, pwptr->pw_name)); - -#ifndef USE_AMANDAHOSTS - s = check_user_ruserok(remotehost, pwptr, remoteuser); -#else - s = check_user_amandahosts(remotehost, pwptr, remoteuser); -#endif - - if (s != NULL) { - *errstr = vstralloc("[", - "access as ", pwptr->pw_name, " not allowed", - " from ", remoteuser, "@", remotehost, - ": ", s, "]", NULL); - } - amfree(s); - amfree(remotehost); - amfree(remoteuser); - return *errstr == NULL; -} - - /* * Create the server end of a stream. For bsd, this means setup a tcp * socket for receiving a connection. */ static void * -bsd_stream_server(h) - void *h; +bsd_stream_server( + void * h) { - struct bsd_stream *bs = NULL; #ifndef TEST /* { */ - struct bsd_handle *bh = h; + struct sec_stream *bs = NULL; + struct sec_handle *bh = h; assert(bh != NULL); - bs = alloc(sizeof(*bs)); + bs = alloc(SIZEOF(*bs)); security_streaminit(&bs->secstr, &bsd_security_driver); - bs->socket = stream_server(&bs->port, STREAM_BUFSIZE, STREAM_BUFSIZE); + bs->socket = stream_server(&bs->port, (size_t)STREAM_BUFSIZE, + (size_t)STREAM_BUFSIZE, 0); if (bs->socket < 0) { security_seterror(&bh->sech, "can't create server stream: %s", strerror(errno)); @@ -1396,8 +306,10 @@ bsd_stream_server(h) } bs->fd = -1; bs->ev_read = NULL; -#endif /* !TEST */ /* } */ return (bs); +#else + return (NULL); +#endif /* !TEST */ /* } */ } /* @@ -1405,17 +317,17 @@ bsd_stream_server(h) * block on accept() */ static int -bsd_stream_accept(s) - void *s; +bsd_stream_accept( + void * s) { #ifndef TEST /* { */ - struct bsd_stream *bs = s; + struct sec_stream *bs = s; assert(bs != NULL); assert(bs->socket != -1); assert(bs->fd < 0); - bs->fd = stream_accept(bs->socket, 30, -1, -1); + bs->fd = stream_accept(bs->socket, 30, STREAM_BUFSIZE, STREAM_BUFSIZE); if (bs->fd < 0) { security_stream_seterror(&bs->secstr, "can't accept new stream connection: %s", strerror(errno)); @@ -1429,32 +341,26 @@ bsd_stream_accept(s) * Return a connected stream */ static void * -bsd_stream_client(h, id) - void *h; - int id; +bsd_stream_client( + void * h, + int id) { - struct bsd_stream *bs = NULL; + struct sec_stream *bs = NULL; #ifndef TEST /* { */ - struct bsd_handle *bh = h; + struct sec_handle *bh = h; #ifdef DUMPER_SOCKET_BUFFERING - int rcvbuf = sizeof(bs->databuf) * 2; + size_t rcvbuf = SIZEOF(bs->databuf) * 2; #endif assert(bh != NULL); - if (id < 0) { - security_seterror(&bh->sech, - "%d: invalid security stream id", id); - return (NULL); - } - - bs = alloc(sizeof(*bs)); + bs = alloc(SIZEOF(*bs)); security_streaminit(&bs->secstr, &bsd_security_driver); - bs->fd = stream_client(bh->hostname, id, STREAM_BUFSIZE, STREAM_BUFSIZE, - &bs->port, 0); + bs->fd = stream_client(bh->hostname, (in_port_t)id, + STREAM_BUFSIZE, STREAM_BUFSIZE, &bs->port, 0); if (bs->fd < 0) { security_seterror(&bh->sech, - "can't connect stream to %s port %d: %s", bh->hostname, + "can't connect stream to %s port %hd: %s", bh->hostname, id, strerror(errno)); amfree(bs); return (NULL); @@ -1462,7 +368,7 @@ bsd_stream_client(h, id) bs->socket = -1; /* we're a client */ bs->ev_read = NULL; #ifdef DUMPER_SOCKET_BUFFERING - setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, sizeof(rcvbuf)); + setsockopt(bs->fd, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf, SIZEOF(rcvbuf)); #endif #endif /* !TEST */ /* } */ return (bs); @@ -1472,10 +378,10 @@ bsd_stream_client(h, id) * Close and unallocate resources for a stream */ static void -bsd_stream_close(s) - void *s; +bsd_stream_close( + void * s) { - struct bsd_stream *bs = s; + struct sec_stream *bs = s; assert(bs != NULL); @@ -1491,9 +397,10 @@ bsd_stream_close(s) * Authenticate a stream. bsd streams have no authentication */ static int -bsd_stream_auth(s) - void *s; +bsd_stream_auth( + void * s) { + (void)s; /* Quiet unused parameter warning */ return (0); /* success */ } @@ -1502,37 +409,14 @@ bsd_stream_auth(s) * Returns the stream id for this stream. This is just the local port. */ static int -bsd_stream_id(s) - void *s; +bsd_stream_id( + void * s) { - struct bsd_stream *bs = s; + struct sec_stream *bs = s; assert(bs != NULL); - return (bs->port); -} - -/* - * Write a chunk of data to a stream. Blocks until completion. - */ -static int -bsd_stream_write(s, buf, size) - void *s; - const void *buf; - size_t size; -{ -#ifndef TEST /* { */ - struct bsd_stream *bs = s; - - assert(bs != NULL); - - if (fullwrite(bs->fd, buf, size) < 0) { - security_stream_seterror(&bs->secstr, - "write error on stream %d: %s", bs->port, strerror(errno)); - return (-1); - } -#endif /* !TEST */ /* } */ - return (0); + return ((int)bs->port); } /* @@ -1540,11 +424,12 @@ bsd_stream_write(s, buf, size) * and arg when completed. */ static void -bsd_stream_read(s, fn, arg) - void *s, *arg; - void (*fn) P((void *, void *, ssize_t)); +bsd_stream_read( + void * s, + void (*fn)(void *, void *, ssize_t), + void * arg) { - struct bsd_stream *bs = s; + struct sec_stream *bs = s; /* * Only one read request can be active per stream. @@ -1552,41 +437,52 @@ bsd_stream_read(s, fn, arg) if (bs->ev_read != NULL) event_release(bs->ev_read); - bs->ev_read = event_register(bs->fd, EV_READFD, stream_read_callback, bs); + bs->ev_read = event_register((event_id_t)bs->fd, EV_READFD, stream_read_callback, bs); bs->fn = fn; bs->arg = arg; } /* - * Cancel a previous stream read request. It's ok if we didn't - * have a read scheduled. + * Read a chunk of data to a stream. Blocks until completion. */ -static void -bsd_stream_read_cancel(s) - void *s; +static ssize_t +bsd_stream_read_sync( + void * s, + void ** buf) { - struct bsd_stream *bs = s; + struct sec_stream *bs = s; assert(bs != NULL); - if (bs->ev_read != NULL) { - event_release(bs->ev_read); - bs->ev_read = NULL; + /* + * Only one read request can be active per stream. + */ + if(bs->ev_read != NULL) { + return -1; } + bs->ev_read = event_register((event_id_t)bs->fd, EV_READFD, + stream_read_sync_callback, bs); + event_wait(bs->ev_read); + *buf = bs->databuf; + return (bs->len); } + /* - * Callback for bsd_stream_read + * Callback for bsd_stream_read_sync */ static void -stream_read_callback(arg) - void *arg; +stream_read_sync_callback( + void * s) { - struct bsd_stream *bs = arg; + struct sec_stream *bs = s; ssize_t n; assert(bs != NULL); + bsdprintf(("%s: bsd: stream_read_callback_sync: fd %d\n", + debug_prefix_time(NULL), bs->fd)); + /* * Remove the event first, in case they reschedule it in the callback. */ @@ -1595,101 +491,51 @@ stream_read_callback(arg) n = read(bs->fd, bs->databuf, sizeof(bs->databuf)); } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN))); if (n < 0) - security_stream_seterror(&bs->secstr, strerror(errno)); - (*bs->fn)(bs->arg, bs->databuf, n); + security_stream_seterror(&bs->secstr, strerror(errno)); + bs->len = n; } /* - * Convert a packet header into a string + * Cancel a previous stream read request. It's ok if we didn't + * have a read scheduled. */ -static const char * -pkthdr2str(bh, pkt) - const struct bsd_handle *bh; - const pkt_t *pkt; +static void +bsd_stream_read_cancel( + void * s) { - static char retbuf[256]; - - assert(bh != NULL); - assert(pkt != NULL); + struct sec_stream *bs = s; - snprintf(retbuf, sizeof(retbuf), "Amanda %d.%d %s HANDLE %s SEQ %d\n", - VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type), - bh->proto_handle, bh->sequence); - - bsdprintf(("%s: pkthdr2str handle '%s'\n", - debug_prefix_time(NULL), bh->proto_handle)); - - /* check for truncation. If only we had asprintf()... */ - assert(retbuf[strlen(retbuf) - 1] == '\n'); - - return (retbuf); + assert(bs != NULL); + if (bs->ev_read != NULL) { + event_release(bs->ev_read); + bs->ev_read = NULL; + } } /* - * Parses out the header line in 'str' into the pkt and handle - * Returns negative on parse error. + * Callback for bsd_stream_read */ -static int -str2pkthdr() +static void +stream_read_callback( + void * arg) { - char *str; - const char *tok; - pkt_t *pkt; - - pkt = &netfd.pkt; - - assert(netfd.dgram.cur != NULL); - str = stralloc(netfd.dgram.cur); - - /* "Amanda %d.%d HANDLE %s SEQ %d\n" */ - - /* Read in "Amanda" */ - if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0) - goto parse_error; - - /* nothing is done with the major/minor numbers currently */ - if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL) - goto parse_error; - - /* Read in the packet type */ - if ((tok = strtok(NULL, " ")) == NULL) - goto parse_error; - pkt_init(pkt, pkt_str2type(tok), ""); - if (pkt->type == (pktype_t)-1) - goto parse_error; - - /* Read in "HANDLE" */ - if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0) - goto parse_error; - - /* parse the handle */ - if ((tok = strtok(NULL, " ")) == NULL) - goto parse_error; - netfd.handle = stralloc(tok); - - /* Read in "SEQ" */ - if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0) - goto parse_error; + struct sec_stream *bs = arg; + ssize_t n; - /* parse the sequence number */ - if ((tok = strtok(NULL, "\n")) == NULL) - goto parse_error; - netfd.sequence = atoi(tok); + assert(bs != NULL); - /* Save the body, if any */ - if ((tok = strtok(NULL, "")) != NULL) - pkt_cat(pkt, "%s", tok); + /* + * Remove the event first, in case they reschedule it in the callback. + */ + bsd_stream_read_cancel(bs); + do { + n = read(bs->fd, bs->databuf, SIZEOF(bs->databuf)); + } while ((n < 0) && ((errno == EINTR) || (errno == EAGAIN))); - amfree(str); - return (0); + if (n < 0) + security_stream_seterror(&bs->secstr, strerror(errno)); -parse_error: -#if 0 /* XXX we have no way of passing this back up */ - security_seterror(&bh->sech, - "parse error in packet header : '%s'", origstr); -#endif - amfree(str); - return (-1); + (*bs->fn)(bs->arg, bs->databuf, n); } #endif /* BSD_SECURITY */ /* } */ @@ -1701,12 +547,19 @@ parse_error: * drag in util.o just for the test program. */ int -bind_portrange(s, addrp, first_port, last_port, proto) - int s; - struct sockaddr_in *addrp; - int first_port, last_port; - char *proto; -{ +bind_portrange( + int s, + struct sockaddr_in *addrp, + in_port_t first_port, + in_port_t last_port, + char * proto) +{ + (void)s; /* Quiet unused parameter warning */ + (void)addrp; /* Quiet unused parameter warning */ + (void)first_port; /* Quiet unused parameter warning */ + (void)last_port; /* Quiet unused parameter warning */ + (void)proto; /* Quiet unused parameter warning */ + return 0; } @@ -1714,8 +567,8 @@ bind_portrange(s, addrp, first_port, last_port, proto) * Construct a datestamp (YYYYMMDD) from a time_t. */ char * -construct_datestamp(t) - time_t *t; +construct_datestamp( + time_t * t) { struct tm *tm; char datestamp[3*NUM_STR_SIZE]; @@ -1727,7 +580,7 @@ construct_datestamp(t) when = *t; } tm = localtime(&when); - snprintf(datestamp, sizeof(datestamp), + snprintf(datestamp, SIZEOF(datestamp), "%04d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); return stralloc(datestamp); } @@ -1736,8 +589,8 @@ construct_datestamp(t) * Construct a timestamp (YYYYMMDDHHMMSS) from a time_t. */ char * -construct_timestamp(t) - time_t *t; +construct_timestamp( + time_t * t) { struct tm *tm; char timestamp[6*NUM_STR_SIZE]; @@ -1749,7 +602,7 @@ construct_timestamp(t) when = *t; } tm = localtime(&when); - snprintf(timestamp, sizeof(timestamp), + snprintf(timestamp, SIZEOF(timestamp), "%04d%02d%02d%02d%02d%02d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -1763,14 +616,17 @@ construct_timestamp(t) const security_driver_t krb4_security_driver = {}; const security_driver_t krb5_security_driver = {}; const security_driver_t rsh_security_driver = {}; +const security_driver_t ssh_security_driver = {}; +const security_driver_t bsdtcp_security_driver = {}; +const security_driver_t bsdudp_security_driver = {}; /* * This function will be called to accept the connection and is used * to report success or failure. */ -static void fake_accept_function(handle, pkt) - security_handle_t *handle; - pkt_t *pkt; +static void fake_accept_function( + security_handle_t * handle, + pkt_t * pkt) { if (pkt == NULL) { fputs(handle->error, stdout); @@ -1781,12 +637,14 @@ static void fake_accept_function(handle, pkt) } int -main (argc, argv) +main ( + int argc, + char ** argv) { char *remoteuser; char *remotehost; struct hostent *hp; - struct bsd_handle *bh; + struct sec_handle *bh; void *save_cur; struct passwd *pwent; @@ -1808,6 +666,7 @@ main (argc, argv) if (geteuid() == 0) { if(client_uid == (uid_t) -1) { error("error [cannot find user %s in passwd file]\n", CLIENT_LOGIN); + /*NOTREACHED*/ } initgroups(CLIENT_LOGIN, client_gid); setgid(client_gid); @@ -1820,19 +679,28 @@ main (argc, argv) fputs("Remote user: ", stdout); fflush(stdout); } - if ((remoteuser = agets(stdin)) == NULL) { - return 0; - } + do { + amfree(remoteuser); + remoteuser = agets(stdin); + if (remoteuser == NULL) + return 0; + } while (remoteuser[0] == '\0'); if (isatty(0)) { fputs("Remote host: ", stdout); fflush(stdout); } - if ((remotehost = agets(stdin)) == NULL) { - return 0; - } + + do { + amfree(remotehost); + remotehost = agets(stdin); + if (remotehost == NULL) + return 0; + } while (remotehost[0] == '\0'); set_pname("security"); + dbopen(NULL); + startclock(); if ((hp = gethostbyname(remotehost)) == NULL) { @@ -1841,14 +709,15 @@ main (argc, argv) } memcpy((char *)&netfd.peer.sin_addr, (char *)hp->h_addr, - sizeof(hp->h_addr)); + SIZEOF(hp->h_addr)); /* * Fake that it is coming from a reserved port. */ netfd.peer.sin_port = htons(IPPORT_RESERVED - 1); - bh = alloc(sizeof(*bh)); + bh = alloc(SIZEOF(*bh)); bh->proto_handle=NULL; + bh->udp = &netfd; netfd.pkt.type = P_REQ; dgram_zero(&netfd.dgram); save_cur = netfd.dgram.cur; /* cheating */ @@ -1856,8 +725,10 @@ main (argc, argv) dgram_cat(&netfd.dgram, "SECURITY USER %s\n", remoteuser); netfd.dgram.cur = save_cur; /* cheating */ - accept_fn = fake_accept_function; - netfd_read_callback(NULL); + netfd.accept_fn = fake_accept_function; + netfd.recv_security_ok = &bsd_recv_security_ok; + netfd.prefix_packet = &bsd_prefix_packet; + udp_netfd_read_callback(&netfd); return 0; }