X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fsecurity-util.c;h=2e0c0d03fe78c7cf46215886e6f0c79c40b9df40;hb=d923a3f5bd691defcb8a7013e8ba6521ea2ecca0;hp=a55bafbbe22ed8c326b3faa8ccf50d864774e3ea;hpb=34197d9f46a5f4e944378cbb65fca32ee0eec7b9;p=debian%2Famanda diff --git a/common-src/security-util.c b/common-src/security-util.c index a55bafb..2e0c0d0 100644 --- a/common-src/security-util.c +++ b/common-src/security-util.c @@ -25,7 +25,7 @@ */ /* - * $Id: security-util.c,v 1.25.2.10 2007/01/24 00:35:14 martinea Exp $ + * $Id: security-util.c,v 1.25 2006/07/22 12:04:47 martinea Exp $ * * sec-security.c - security and transport over sec or a sec-like command. * @@ -37,37 +37,15 @@ #include "util.h" #include "event.h" #include "packet.h" -#include "queue.h" #include "security.h" #include "security-util.h" #include "stream.h" -#include "version.h" - -/* #define SEC_DEBUG */ -#define SHOW_SECURITY_DETAIL - -#ifdef SEC_DEBUG -# define secprintf(x) dbprintf(x) -#else -# ifdef __lint -# define secprintf(x) (void)(x) -# else -# define secprintf(x) -# endif -#endif - -/* - * Magic values for sec_conn->handle - */ -#define H_TAKEN -1 /* sec_conn->tok was already read */ -#define H_EOF -2 /* this connection has been shut down */ +#include "sockaddr-util.h" /* * This is a queue of open connections */ -struct connq_s connq = { - TAILQ_HEAD_INITIALIZER(connq.tailq), 0 -}; +GSList *connq = NULL; static int newhandle = 1; static int newevent = 1; @@ -116,17 +94,21 @@ sec_stream_id( void sec_accept( const security_driver_t *driver, + char *(*conf_fn)(char *, void *), int in, int out, - void (*fn)(security_handle_t *, pkt_t *)) + void (*fn)(security_handle_t *, pkt_t *), + void *datap) { struct tcp_conn *rc; - rc = sec_tcp_conn_get("unknown",0); + rc = sec_tcp_conn_get("",0); /* no hostname yet */ rc->read = in; rc->write = out; rc->accept_fn = fn; rc->driver = driver; + rc->conf_fn = conf_fn; + rc->datap = datap; sec_tcp_conn_read(rc); } @@ -141,8 +123,7 @@ sec_close( assert(rh != NULL); - secprintf(("%s: sec: closing handle to %s\n", debug_prefix_time(NULL), - rh->hostname)); + auth_debug(1, _("sec: closing handle to %s\n"), rh->hostname); if (rh->rs != NULL) { /* This may be null if we get here on an error */ @@ -219,7 +200,7 @@ stream_sendpkt( assert(rh != NULL); assert(pkt != NULL); - secprintf(("%s: sec: stream_sendpkt: enter\n", debug_prefix_time(NULL))); + auth_debug(1, _("sec: stream_sendpkt: enter\n")); if (rh->rc->prefix_packet) s = rh->rc->prefix_packet(rh, pkt); @@ -233,13 +214,13 @@ stream_sendpkt( if (strlen(s) > 0) amfree(s); - secprintf(( - "%s: sec: stream_sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n", - debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->type, - strlen(pkt->body), pkt->body)); + auth_debug(1, + _("sec: stream_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"), + pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body); if (security_stream_write(&rh->rs->secstr, buf, len) < 0) { - security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr)); + security_seterror(&rh->sech, "%s", security_stream_geterror(&rh->rs->secstr)); + amfree(buf); return (-1); } amfree(buf); @@ -261,8 +242,7 @@ stream_recvpkt( assert(rh != NULL); - secprintf(("%s: sec: recvpkt registered for %s\n", - debug_prefix_time(NULL), rh->hostname)); + auth_debug(1, _("sec: recvpkt registered for %s\n"), rh->hostname); /* * Reset any pending timeout on this handle @@ -295,8 +275,7 @@ stream_recvpkt_timeout( assert(rh != NULL); - secprintf(("%s: sec: recvpkt timeout for %s\n", - debug_prefix_time(NULL), rh->hostname)); + auth_debug(1, _("sec: recvpkt timeout for %s\n"), rh->hostname); stream_recvpkt_cancel(rh); (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT); @@ -311,8 +290,7 @@ stream_recvpkt_cancel( { struct sec_handle *rh = cookie; - secprintf(("%s: sec: cancelling recvpkt for %s\n", - debug_prefix_time(NULL), rh->hostname)); + auth_debug(1, _("sec: cancelling recvpkt for %s\n"), rh->hostname); assert(rh != NULL); @@ -337,13 +315,13 @@ tcpm_stream_write( assert(rs != NULL); assert(rs->rc != NULL); - secprintf(("%s: sec: stream_write: writing %d bytes to %s:%d %d\n", - debug_prefix_time(NULL), size, rs->rc->hostname, rs->handle, - rs->rc->write)); + auth_debug(1, _("sec: stream_write: writing %zu bytes to %s:%d %d\n"), + size, rs->rc->hostname, rs->handle, + rs->rc->write); - if (tcpm_send_token(rs->rc->write, rs->handle, &rs->rc->errmsg, + if (tcpm_send_token(rs->rc, rs->rc->write, rs->handle, &rs->rc->errmsg, buf, size)) { - security_stream_seterror(&rs->secstr, rs->rc->errmsg); + security_stream_seterror(&rs->secstr, "%s", rs->rc->errmsg); return (-1); } return (0); @@ -367,7 +345,7 @@ tcpm_stream_read( * Only one read request can be active per stream. */ if (rs->ev_read == NULL) { - rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT, + rs->ev_read = event_register((event_id_t)rs->rc->event_id, EV_WAIT, stream_read_callback, rs); sec_tcp_conn_read(rs->rc); } @@ -375,6 +353,10 @@ tcpm_stream_read( rs->arg = arg; } +/* buffer for tcpm_stream_read_sync function */ +static ssize_t sync_pktlen; +static void *sync_pkt; + /* * Write a chunk of data to a stream. Blocks until completion. */ @@ -393,12 +375,15 @@ tcpm_stream_read_sync( if (rs->ev_read != NULL) { return -1; } - rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT, + sync_pktlen = 0; + sync_pkt = NULL; + rs->ev_read = event_register((event_id_t)rs->rc->event_id, EV_WAIT, stream_read_sync_callback, rs); sec_tcp_conn_read(rs->rc); event_wait(rs->ev_read); - *buf = rs->rc->pkt; - return (rs->rc->pktlen); + /* Can't use rs or rc, they can be freed */ + *buf = sync_pkt; + return (sync_pktlen); } /* @@ -426,19 +411,33 @@ tcpm_stream_read_cancel( */ ssize_t tcpm_send_token( + struct tcp_conn *rc, int fd, int handle, char ** errmsg, const void *buf, size_t len) { - uint32_t nethandle; - uint32_t netlength; + guint32 nethandle; + guint32 netlength; struct iovec iov[3]; int nb_iov = 3; + int rval; + char *encbuf; + ssize_t encsize; + int save_errno; + time_t logtime; assert(SIZEOF(netlength) == 4); + logtime = time(NULL); + if (rc && logtime > rc->logstamp + 10) { + g_debug("tcpm_send_token: data is still flowing"); + rc->logstamp = logtime; + } + + auth_debug(1, "tcpm_send_token: write %zd bytes to handle %d\n", + len, handle); /* * Format is: * 32 bit length (network byte order) @@ -449,29 +448,47 @@ tcpm_send_token( iov[0].iov_base = (void *)&netlength; iov[0].iov_len = SIZEOF(netlength); - nethandle = htonl((uint32_t)handle); + nethandle = htonl((guint32)handle); iov[1].iov_base = (void *)&nethandle; iov[1].iov_len = SIZEOF(nethandle); + encbuf = (char *)buf; + encsize = len; + if(len == 0) { nb_iov = 2; } else { - iov[2].iov_base = (void *)buf; - iov[2].iov_len = len; + if (rc->driver->data_encrypt == NULL) { + iov[2].iov_base = (void *)buf; + iov[2].iov_len = len; + } else { + /* (the extra (void *) cast is to quiet type-punning warnings) */ + rc->driver->data_encrypt(rc, (void *)buf, len, (void **)(void *)&encbuf, &encsize); + iov[2].iov_base = (void *)encbuf; + iov[2].iov_len = encsize; + netlength = htonl(encsize); + } nb_iov = 3; } - if (net_writev(fd, iov, nb_iov) < 0) { + rval = full_writev(fd, iov, nb_iov); + save_errno = errno; + if (len != 0 && rc->driver->data_encrypt != NULL && buf != encbuf) { + amfree(encbuf); + } + + if (rval < 0) { if (errmsg) - *errmsg = newvstralloc(*errmsg, "write error to ", - ": ", strerror(errno), NULL); + *errmsg = newvstrallocf(*errmsg, _("write error to: %s"), + strerror(save_errno)); return (-1); } return (0); } /* + * return -2 for incomplete packet * return -1 on error * return 0 on EOF: *handle = H_EOF && *size = 0 if socket closed * return 0 on EOF: *handle = handle && *size = 0 if stream closed @@ -480,110 +497,137 @@ tcpm_send_token( ssize_t tcpm_recv_token( + struct tcp_conn *rc, int fd, int * handle, char ** errmsg, char ** buf, - ssize_t * size, - int timeout) + ssize_t * size) { - unsigned int netint[2]; - - assert(SIZEOF(netint) == 8); - - switch (net_read(fd, &netint, SIZEOF(netint), timeout)) { - case -1: - if (errmsg) - *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno), - NULL); - secprintf(("%s: tcpm_recv_token: A return(-1)\n", - debug_prefix_time(NULL))); - return (-1); - case 0: - *size = 0; - *handle = H_EOF; - *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL); - secprintf(("%s: tcpm_recv_token: A return(0)\n", - debug_prefix_time(NULL))); - return (0); - default: - break; - } - - *size = (ssize_t)ntohl(netint[0]); - *handle = (int)ntohl(netint[1]); - /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */ - if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) { - if (isprint((*size ) & 0xFF) && - isprint((*size >> 8 ) & 0xFF) && - isprint((*size >> 16) & 0xFF) && - isprint((*size >> 24) & 0xFF) && - isprint((*handle ) & 0xFF) && - isprint((*handle >> 8 ) & 0xFF) && - isprint((*handle >> 16) & 0xFF) && - isprint((*handle >> 24) & 0xFF)) { - char s[101]; - int i; - s[0] = (*size >> 24) & 0xFF; - s[1] = (*size >> 16) & 0xFF; - s[2] = (*size >> 8) & 0xFF; - s[3] = (*size ) & 0xFF; - s[4] = (*handle >> 24) & 0xFF; - s[5] = (*handle >> 16) & 0xFF; - s[6] = (*handle >> 8 ) & 0xFF; - s[7] = (*handle ) & 0xFF; - i = 8; s[i] = ' '; - while(i<100 && isprint(s[i]) && s[i] != '\n') { - switch(net_read(fd, &s[i], 1, 0)) { - case -1: s[i] = '\0'; break; - case 0: s[i] = '\0'; break; - default: dbprintf(("read: %c\n", s[i])); i++; s[i]=' ';break; + ssize_t rval; + + assert(SIZEOF(rc->netint) == 8); + if (rc->size_header_read < (ssize_t)SIZEOF(rc->netint)) { + rval = read(fd, ((char *)&rc->netint) + rc->size_header_read, + SIZEOF(rc->netint) - rc->size_header_read); + if (rval == -1) { + if (errmsg) + *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), + strerror(errno)); + auth_debug(1, _("tcpm_recv_token: A return(-1)\n")); + return(-1); + } else if (rval == 0) { + *size = 0; + *handle = H_EOF; + *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF")); + auth_debug(1, _("tcpm_recv_token: A return(0)\n")); + return(0); + } else if (rval < (ssize_t)SIZEOF(rc->netint) - rc->size_header_read) { + rc->size_header_read += rval; + return(-2); + } + rc->size_header_read += rval; + amfree(rc->buffer); + *size = (ssize_t)ntohl(rc->netint[0]); + *handle = (int)ntohl(rc->netint[1]); + rc->buffer = NULL; + rc->size_buffer_read = 0; + + /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */ + if (*size > 128*NETWORK_BLOCK_BYTES || *size < 0) { + if (isprint((int)(*size ) & 0xFF) && + isprint((int)(*size >> 8 ) & 0xFF) && + isprint((int)(*size >> 16) & 0xFF) && + isprint((int)(*size >> 24) & 0xFF) && + isprint((*handle ) & 0xFF) && + isprint((*handle >> 8 ) & 0xFF) && + isprint((*handle >> 16) & 0xFF) && + isprint((*handle >> 24) & 0xFF)) { + char s[201]; + char *s1; + int i; + s[0] = ((int)(*size) >> 24) & 0xFF; + s[1] = ((int)(*size) >> 16) & 0xFF; + s[2] = ((int)(*size) >> 8) & 0xFF; + s[3] = ((int)(*size) ) & 0xFF; + s[4] = (*handle >> 24) & 0xFF; + s[5] = (*handle >> 16) & 0xFF; + s[6] = (*handle >> 8 ) & 0xFF; + s[7] = (*handle ) & 0xFF; + i = 8; s[i] = ' '; + while(i<200 && isprint((int)s[i]) && s[i] != '\n') { + switch(net_read(fd, &s[i], 1, 0)) { + case -1: s[i] = '\0'; break; + case 0: s[i] = '\0'; break; + default: + dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' '; + break; + } } + s[i] = '\0'; + s1 = quote_string(s); + *errmsg = newvstrallocf(*errmsg, + _("tcpm_recv_token: invalid size: %s"), s1); + dbprintf(_("tcpm_recv_token: invalid size %s\n"), s1); + amfree(s1); + } else { + *errmsg = newvstrallocf(*errmsg, + _("tcpm_recv_token: invalid size")); + dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size); } - s[i] = '\0'; - *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size: ", - s, NULL); - dbprintf(("%s: tcpm_recv_token: invalid size: %s\n", - debug_prefix_time(NULL), s)); - } else { - *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size", - NULL); - dbprintf(("%s: tcpm_recv_token: invalid size %zd\n", - debug_prefix_time(NULL), *size)); + *size = -1; + return -1; } - *size = -1; - return -1; - } - amfree(*buf); - *buf = alloc((size_t)*size); + rc->buffer = alloc((size_t)*size); - if(*size == 0) { - secprintf(("%s: tcpm_recv_token: read EOF from %d\n", - debug_prefix_time(NULL), *handle)); - *errmsg = newvstralloc(*errmsg, "EOF", - NULL); - return 0; + if (*size == 0) { + auth_debug(1, _("tcpm_recv_token: read EOF from %d\n"), *handle); + *errmsg = newvstrallocf(*errmsg, _("EOF")); + rc->size_header_read = 0; + return 0; + } } - switch (net_read(fd, *buf, (size_t)*size, timeout)) { - case -1: + + *size = (ssize_t)ntohl(rc->netint[0]); + *handle = (int)ntohl(rc->netint[1]); + + rval = read(fd, rc->buffer + rc->size_buffer_read, + (size_t)*size - rc->size_buffer_read); + if (rval == -1) { if (errmsg) - *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno), - NULL); - secprintf(("%s: tcpm_recv_token: B return(-1)\n", - debug_prefix_time(NULL))); + *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), + strerror(errno)); + auth_debug(1, _("tcpm_recv_token: B return(-1)\n")); return (-1); - case 0: + } else if (rval == 0) { *size = 0; - *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL); - secprintf(("%s: tcpm_recv_token: B return(0)\n", - debug_prefix_time(NULL))); + *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF")); + auth_debug(1, _("tcpm_recv_token: B return(0)\n")); return (0); - default: - break; + } else if (rval < (ssize_t)*size - rc->size_buffer_read) { + rc->size_buffer_read += rval; + return (-2); + } + rc->size_buffer_read += rval; + amfree(*buf); + *buf = rc->buffer; + rc->size_header_read = 0; + rc->size_buffer_read = 0; + rc->buffer = NULL; + + auth_debug(1, _("tcpm_recv_token: read %zd bytes from %d\n"), *size, *handle); + + if (*size > 0 && rc->driver->data_decrypt != NULL) { + void *decbuf; + ssize_t decsize; + rc->driver->data_decrypt(rc, *buf, *size, &decbuf, &decsize); + if (*buf != (char *)decbuf) { + amfree(*buf); + *buf = (char *)decbuf; + } + *size = decsize; } - secprintf(("%s: tcpm_recv_token: read %zd bytes from %d\n", - debug_prefix_time(NULL), *size, *handle)); return((*size)); } @@ -594,9 +638,9 @@ tcpm_close_connection( { struct sec_handle *rh = h; - hostname = hostname; + (void)hostname; - if(rh->rc->toclose == 0) { + if (rh && rh->rc && rh->rc->read >= 0 && rh->rc->toclose == 0) { rh->rc->toclose = 1; sec_tcp_conn_put(rh->rc); } @@ -633,11 +677,11 @@ tcpma_stream_client( if (id <= 0) { security_seterror(&rh->sech, - "%d: invalid security stream id", id); + _("%d: invalid security stream id"), id); return (NULL); } - rs = alloc(SIZEOF(*rs)); + rs = g_new0(struct sec_stream, 1); security_streaminit(&rs->secstr, rh->sech.driver); rs->handle = id; rs->ev_read = NULL; @@ -653,8 +697,7 @@ tcpma_stream_client( rh->rc = rs->rc; } - secprintf(("%s: sec: stream_client: connected to stream %d\n", - debug_prefix_time(NULL), id)); + auth_debug(1, _("sec: stream_client: connected to stream %d\n"), id); return (rs); } @@ -672,7 +715,7 @@ tcpma_stream_server( assert(rh != NULL); - rs = alloc(SIZEOF(*rs)); + rs = g_new0(struct sec_stream, 1); security_streaminit(&rs->secstr, rh->sech.driver); rs->closed_by_me = 0; rs->closed_by_network = 0; @@ -691,7 +734,7 @@ tcpma_stream_server( if (rs->rc->read < 0) { sec_tcp_conn_put(rs->rc); amfree(rs); - security_seterror(&rh->sech, "lost connection to %s", rh->hostname); + security_seterror(&rh->sech, _("lost connection to %s"), rh->hostname); return (NULL); } assert(strcmp(rh->hostname, rs->rc->hostname) == 0); @@ -701,8 +744,7 @@ tcpma_stream_server( */ rs->handle = 500000 - newhandle++; rs->ev_read = NULL; - secprintf(("%s: sec: stream_server: created stream %d\n", - debug_prefix_time(NULL), rs->handle)); + auth_debug(1, _("sec: stream_server: created stream %d\n"), rs->handle); return (rs); } @@ -718,14 +760,14 @@ tcpma_stream_close( assert(rs != NULL); - secprintf(("%s: sec: tcpma_stream_close: closing stream %d\n", - debug_prefix_time(NULL), rs->handle)); + auth_debug(1, _("sec: tcpma_stream_close: closing stream %d\n"), rs->handle); if(rs->closed_by_network == 0 && rs->rc->write != -1) tcpm_stream_write(rs, &buf, 0); security_stream_read_cancel(&rs->secstr); if(rs->closed_by_network == 0) sec_tcp_conn_put(rs->rc); + amfree(((security_stream_t *)rs)->error); amfree(rs); } @@ -742,7 +784,7 @@ tcp1_stream_server( assert(rh != NULL); - rs = alloc(SIZEOF(*rs)); + rs = g_new0(struct sec_stream, 1); security_streaminit(&rs->secstr, rh->sech.driver); rs->closed_by_me = 0; rs->closed_by_network = 0; @@ -756,11 +798,11 @@ tcp1_stream_server( rh->rc = sec_tcp_conn_get(rh->hostname, 1); rh->rc->driver = rh->sech.driver; rs->rc = rh->rc; - rs->socket = stream_server(&rs->port, STREAM_BUFSIZE, - STREAM_BUFSIZE, 0); + rs->socket = stream_server(SU_GET_FAMILY(&rh->udp->peer), &rs->port, + STREAM_BUFSIZE, STREAM_BUFSIZE, 0); if (rs->socket < 0) { security_seterror(&rh->sech, - "can't create server stream: %s", strerror(errno)); + _("can't create server stream: %s"), strerror(errno)); amfree(rs); return (NULL); } @@ -791,7 +833,7 @@ tcp1_stream_accept( 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", + _("can't accept new stream connection: %s"), strerror(errno)); return (-1); } @@ -814,7 +856,7 @@ tcp1_stream_client( assert(rh != NULL); - rs = alloc(SIZEOF(*rs)); + rs = g_new0(struct sec_stream, 1); security_streaminit(&rs->secstr, rh->sech.driver); rs->handle = id; rs->ev_read = NULL; @@ -826,12 +868,13 @@ tcp1_stream_client( } else { rh->rc = sec_tcp_conn_get(rh->hostname, 1); + rh->rc->driver = rh->sech.driver; rs->rc = rh->rc; rh->rc->read = stream_client(rh->hostname, (in_port_t)id, STREAM_BUFSIZE, STREAM_BUFSIZE, &rs->port, 0); if (rh->rc->read < 0) { security_seterror(&rh->sech, - "can't connect stream to %s port %d: %s", + _("can't connect stream to %s port %d: %s"), rh->hostname, id, strerror(errno)); amfree(rs); return (NULL); @@ -850,12 +893,19 @@ tcp_stream_write( size_t size) { struct sec_stream *rs = s; + time_t logtime; assert(rs != NULL); - if (fullwrite(rs->fd, buf, size) < 0) { + logtime = time(NULL); + if (rs && rs->rc && logtime > rs->rc->logstamp + 10) { + g_debug("tcp_stream_write: data is still flowing"); + rs->rc->logstamp = logtime; + } + + if (full_write(rs->fd, buf, size) < size) { security_stream_seterror(&rs->secstr, - "write error on stream %d: %s", rs->port, strerror(errno)); + _("write error on stream %d: %s"), rs->port, strerror(errno)); return (-1); } return (0); @@ -873,11 +923,11 @@ bsd_prefix_packet( if (pkt->type != P_REQ) return ""; - if ((pwd = getpwuid(getuid())) == NULL) { + if ((pwd = getpwuid(geteuid())) == NULL) { security_seterror(&rh->sech, - "can't get login name for my uid %ld", - (long)getuid()); - return(NULL); + _("can't get login name for my uid %ld"), + (long)geteuid()); + return ""; } buf = alloc(16+strlen(pwd->pw_name)); strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name))); @@ -901,13 +951,15 @@ bsd_recv_security_ok( char *tok, *security, *body, *result; char *service = NULL, *serviceX, *serviceY; char *security_line; + char *s, ch; size_t len; + in_port_t port; /* * Now, find the SECURITY line in the body, and parse it out * into an argv. */ - if (strncmp(pkt->body, "SECURITY ", SIZEOF("SECURITY ") - 1) == 0) { + if (strncmp_const(pkt->body, "SECURITY ") == 0) { security = pkt->body; len = 0; while(*security != '\n' && len < pkt->size) { @@ -934,8 +986,10 @@ bsd_recv_security_ok( * Now, find the SERVICE line in the body, and parse it out * into an argv. */ - if (strncmp(body, "SERVICE", SIZEOF("SERVICE") - 1) == 0) { - serviceX = stralloc(body + strlen("SERVICE ")); + s = body; + if (strncmp_const_skip(s, "SERVICE ", s, ch) == 0) { + ch=ch; + serviceX = stralloc(s); serviceY = strtok(serviceX, "\n"); if (serviceY) service = stralloc(serviceY); @@ -951,10 +1005,11 @@ bsd_recv_security_ok( /* * Request packets must come from a reserved port */ - if (ntohs(rh->peer.sin_port) >= IPPORT_RESERVED) { + port = SU_GET_PORT(&rh->peer); + if (port >= IPPORT_RESERVED) { security_seterror(&rh->sech, - "host %s: port %d not secure", rh->hostname, - ntohs(rh->peer.sin_port)); + _("host %s: port %u not secure"), rh->hostname, + (unsigned int)port); amfree(service); amfree(security_line); return (-1); @@ -962,7 +1017,7 @@ bsd_recv_security_ok( if (!service) { security_seterror(&rh->sech, - "packet as no SERVICE line"); + _("packet as no SERVICE line")); amfree(security_line); return (-1); } @@ -978,7 +1033,7 @@ bsd_recv_security_ok( /* there must be some security info */ if (security == NULL) { security_seterror(&rh->sech, - "no bsd SECURITY for P_REQ"); + _("no bsd SECURITY for P_REQ")); amfree(service); return (-1); } @@ -986,14 +1041,14 @@ bsd_recv_security_ok( /* second word must be USER */ if ((tok = strtok(security, " ")) == NULL) { security_seterror(&rh->sech, - "SECURITY line: %s", security_line); + _("SECURITY line: %s"), security_line); amfree(service); amfree(security_line); return (-1); /* default errmsg */ } if (strcmp(tok, "USER") != 0) { security_seterror(&rh->sech, - "REQ SECURITY line parse error, expecting USER, got %s", tok); + _("REQ SECURITY line parse error, expecting USER, got %s"), tok); amfree(service); amfree(security_line); return (-1); @@ -1002,7 +1057,8 @@ bsd_recv_security_ok( /* the third word is the username */ if ((tok = strtok(NULL, "")) == NULL) { security_seterror(&rh->sech, - "SECURITY line: %s", security_line); + _("SECURITY line: %s"), security_line); + amfree(service); amfree(security_line); return (-1); /* default errmsg */ } @@ -1045,12 +1101,12 @@ udpbsd_sendpkt( assert(rh != NULL); assert(pkt != NULL); - secprintf(("%s: udpbsd_sendpkt: enter\n", get_pname())); + auth_debug(1, _("udpbsd_sendpkt: enter\n")); /* * Initialize this datagram, and add the header */ dgram_zero(&rh->udp->dgram); - dgram_cat(&rh->udp->dgram, pkthdr2str(rh, pkt)); + dgram_cat(&rh->udp->dgram, "%s", pkthdr2str(rh, pkt)); /* * Add the security info. This depends on which kind of packet we're @@ -1063,10 +1119,10 @@ udpbsd_sendpkt( */ if ((pwd = getpwuid(geteuid())) == NULL) { security_seterror(&rh->sech, - "can't get login name for my uid %ld", (long)getuid()); + _("can't get login name for my uid %ld"), (long)getuid()); return (-1); } - dgram_cat(&rh->udp->dgram, "SECURITY USER %s\n", pwd->pw_name); + dgram_cat(&rh->udp->dgram, _("SECURITY USER %s\n"), pwd->pw_name); break; default: @@ -1076,16 +1132,15 @@ udpbsd_sendpkt( /* * Add the body, and send it */ - dgram_cat(&rh->udp->dgram, pkt->body); + dgram_cat(&rh->udp->dgram, "%s", pkt->body); - secprintf(( - "%s: sec: udpbsd_sendpkt: %s (%d) pkt_t (len %d) contains:\n\n\"%s\"\n\n", - debug_prefix_time(NULL), pkt_type2str(pkt->type), pkt->type, - strlen(pkt->body), pkt->body)); + auth_debug(1, + _("sec: udpbsd_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"), + pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body); - if (dgram_send_addr(rh->peer, &rh->udp->dgram) != 0) { + if (dgram_send_addr(&rh->peer, &rh->udp->dgram) != 0) { security_seterror(&rh->sech, - "send %s to %s failed: %s", pkt_type2str(pkt->type), + _("send %s to %s failed: %s"), pkt_type2str(pkt->type), rh->hostname, strerror(errno)); return (-1); } @@ -1102,8 +1157,7 @@ udp_close( return; } - secprintf(("%s: udp: close handle '%s'\n", - debug_prefix_time(NULL), rh->proto_handle)); + auth_debug(1, _("udp: close handle '%s'\n"), rh->proto_handle); udp_recvpkt_cancel(rh); if (rh->next) { @@ -1137,8 +1191,8 @@ udp_recvpkt( { struct sec_handle *rh = cookie; - secprintf(("%s: udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n", - debug_prefix(NULL), cookie, fn, arg, timeout)); + auth_debug(1, _("udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n"), + cookie, fn, arg, timeout); assert(rh != NULL); assert(fn != NULL); @@ -1199,16 +1253,19 @@ udp_recvpkt_callback( void (*fn)(void *, pkt_t *, security_status_t); void *arg; - secprintf(("%s: udp: receive handle '%s' netfd '%s'\n", - debug_prefix_time(NULL), rh->proto_handle, rh->udp->handle)); + auth_debug(1, _("udp: receive handle '%s' netfd '%s'\n"), + rh->proto_handle, rh->udp->handle); assert(rh != NULL); - if (strcmp(rh->proto_handle, rh->udp->handle) != 0) assert(1); + /* if it doesn't correspond to this handle, something is wrong */ + assert(strcmp(rh->proto_handle, rh->udp->handle) == 0); + /* if it didn't come from the same host/port, forget it */ - if (memcmp(&rh->peer.sin_addr, &rh->udp->peer.sin_addr, - SIZEOF(rh->udp->peer.sin_addr)) != 0 || - rh->peer.sin_port != rh->udp->peer.sin_port) { + if (cmp_sockaddr(&rh->peer, &rh->udp->peer, 0) != 0) { amfree(rh->udp->handle); + dbprintf(_("not from same host\n")); + dump_sockaddr(&rh->peer); + dump_sockaddr(&rh->udp->peer); return; } @@ -1225,10 +1282,11 @@ udp_recvpkt_callback( * to the packet handling function instead of a packet. */ if (rh->udp->recv_security_ok && - rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) + rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) { (*fn)(arg, NULL, S_ERROR); - else + } else { (*fn)(arg, &rh->udp->pkt, S_OK); + } } /* @@ -1258,81 +1316,23 @@ int udp_inithandle( udp_handle_t * udp, struct sec_handle * rh, - struct hostent * he, + char * hostname, + sockaddr_union *addr, in_port_t port, char * handle, int sequence) { - int i; - /* * Save the hostname and port info */ - secprintf(("%s: udp_inithandle port %u handle %s sequence %d\n", - debug_prefix_time(NULL), (unsigned int)ntohs(port), - handle, sequence)); - assert(he != NULL); - - rh->hostname = stralloc(he->h_name); - memcpy(&rh->peer.sin_addr, he->h_addr, SIZEOF(rh->peer.sin_addr)); - rh->peer.sin_port = port; - rh->peer.sin_family = (sa_family_t)AF_INET; - - /* - * 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(rh->hostname)) == NULL) { - secprintf(("%s: udp: bb\n", debug_prefix_time(NULL))); - security_seterror(&rh->sech, - "%s: could not resolve hostname", rh->hostname); - return (-1); - } + auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"), + (unsigned int)ntohs(port), handle, sequence); + assert(addr != NULL); - /* - * Make sure the hostname matches. This should always work. - */ - if (strncasecmp(rh->hostname, he->h_name, strlen(rh->hostname)) != 0) { - secprintf(("%s: udp: cc\n", debug_prefix_time(NULL))); - security_seterror(&rh->sech, - "%s: did not resolve to itself, it resolv to %s", - rh->hostname, he->h_name); - return (-1); - } + rh->hostname = stralloc(hostname); + copy_sockaddr(&rh->peer, addr); + SU_SET_PORT(&rh->peer, port); - /* - * Now look for a matching ip address. - */ - for (i = 0; he->h_addr_list[i] != NULL; i++) { - if (memcmp(&rh->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(rh->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(&rh->sech, - "DNS check failed: no matching ip address for %s", - rh->hostname); - return (-1); - } - } rh->prev = udp->bh_last; if (udp->bh_last) { @@ -1353,8 +1353,7 @@ udp_inithandle( rh->ev_read = NULL; rh->ev_timeout = NULL; - secprintf(("%s: udp: adding handle '%s'\n", - debug_prefix_time(NULL), rh->proto_handle)); + auth_debug(1, _("udp: adding handle '%s'\n"), rh->proto_handle); return(0); } @@ -1371,11 +1370,13 @@ udp_netfd_read_callback( { struct udp_handle *udp = cookie; struct sec_handle *rh; - struct hostent *he; int a; + char hostname[NI_MAXHOST]; + in_port_t port; + char *errmsg = NULL; + int result; - secprintf(("%s: udp_netfd_read_callback(cookie=%p)\n", - debug_prefix(NULL), cookie)); + auth_debug(1, _("udp_netfd_read_callback(cookie=%p)\n"), cookie); assert(udp != NULL); #ifndef TEST /* { */ @@ -1399,8 +1400,7 @@ udp_netfd_read_callback( rh = udp->bh_first; while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 || rh->sequence != udp->sequence || - rh->peer.sin_addr.s_addr != udp->peer.sin_addr.s_addr || - rh->peer.sin_port != udp->peer.sin_port)) { + cmp_sockaddr(&rh->peer, &udp->peer, 0) != 0)) { rh = rh->next; } if (rh && event_wakeup(rh->event_id) > 0) @@ -1410,26 +1410,43 @@ udp_netfd_read_callback( * If we didn't find a handle, then check for a new incoming packet. * If no accept handler was setup, then just return. */ - if (udp->accept_fn == NULL) + if (udp->accept_fn == NULL) { + dbprintf(_("Receive packet from unknown source")); return; + } - he = gethostbyaddr((void *)&udp->peer.sin_addr, - (socklen_t)sizeof(udp->peer.sin_addr), AF_INET); - if (he == NULL) - return; - rh = alloc(SIZEOF(*rh)); + rh = g_new0(struct sec_handle, 1); rh->proto_handle=NULL; rh->udp = udp; rh->rc = NULL; security_handleinit(&rh->sech, udp->driver); + + result = getnameinfo((struct sockaddr *)&udp->peer, SS_LEN(&udp->peer), + hostname, sizeof(hostname), NULL, 0, 0); + if (result != 0) { + dbprintf("getnameinfo failed: %s\n", + gai_strerror(result)); + security_seterror(&rh->sech, "getnameinfo failed: %s", + gai_strerror(result)); + return; + } + if (check_name_give_sockaddr(hostname, + (struct sockaddr *)&udp->peer, &errmsg) < 0) { + security_seterror(&rh->sech, "%s",errmsg); + amfree(errmsg); + amfree(rh); + return; + } + + port = SU_GET_PORT(&udp->peer); a = udp_inithandle(udp, rh, - he, - udp->peer.sin_port, + hostname, + &udp->peer, + port, udp->handle, udp->sequence); if (a < 0) { - secprintf(("%s: bsd: closeX handle '%s'\n", - debug_prefix_time(NULL), rh->proto_handle)); + auth_debug(1, _("bsd: closeX handle '%s'\n"), rh->proto_handle); amfree(rh); return; @@ -1454,31 +1471,32 @@ sec_tcp_conn_get( const char *hostname, int want_new) { - struct tcp_conn *rc; + GSList *iter; + struct tcp_conn *rc = NULL; - secprintf(("%s: sec_tcp_conn_get: %s\n", debug_prefix_time(NULL), hostname)); + auth_debug(1, _("sec_tcp_conn_get: %s\n"), hostname); if (want_new == 0) { - for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) { - if (strcasecmp(hostname, rc->hostname) == 0) - break; - } + for (iter = connq; iter != NULL; iter = iter->next) { + rc = (struct tcp_conn *)iter->data; + if (strcasecmp(hostname, rc->hostname) == 0) + break; + } - if (rc != NULL) { - rc->refcnt++; - secprintf(("%s: sec_tcp_conn_get: exists, refcnt to %s is now %d\n", - debug_prefix_time(NULL), - rc->hostname, rc->refcnt)); - return (rc); - } + if (iter != NULL) { + rc->refcnt++; + auth_debug(1, + _("sec_tcp_conn_get: exists, refcnt to %s is now %d\n"), + rc->hostname, rc->refcnt); + return (rc); + } } - secprintf(("%s: sec_tcp_conn_get: creating new handle\n", - debug_prefix_time(NULL))); + auth_debug(1, _("sec_tcp_conn_get: creating new handle\n")); /* * We can't be creating a new handle if we are the client */ - rc = alloc(SIZEOF(*rc)); + rc = g_new0(struct tcp_conn, 1); rc->read = rc->write = -1; rc->driver = NULL; rc->pid = -1; @@ -1494,7 +1512,11 @@ sec_tcp_conn_get( rc->accept_fn = NULL; rc->recv_security_ok = NULL; rc->prefix_packet = NULL; - connq_append(rc); + rc->auth = 0; + rc->conf_fn = NULL; + rc->datap = NULL; + rc->event_id = newevent++; + connq = g_slist_append(connq, rc); return (rc); } @@ -1510,14 +1532,12 @@ sec_tcp_conn_put( assert(rc->refcnt > 0); --rc->refcnt; - secprintf(("%s: sec_tcp_conn_put: decrementing refcnt for %s to %d\n", - debug_prefix_time(NULL), - rc->hostname, rc->refcnt)); + auth_debug(1, _("sec_tcp_conn_put: decrementing refcnt for %s to %d\n"), + rc->hostname, rc->refcnt); if (rc->refcnt > 0) { return; } - secprintf(("%s: sec_tcp_conn_put: closing connection to %s\n", - debug_prefix_time(NULL), rc->hostname)); + auth_debug(1, _("sec_tcp_conn_put: closing connection to %s\n"), rc->hostname); if (rc->read != -1) aclose(rc->read); if (rc->write != -1) @@ -1529,12 +1549,15 @@ sec_tcp_conn_put( event_release(rc->ev_read); if (rc->errmsg != NULL) amfree(rc->errmsg); - connq_remove(rc); + connq = g_slist_remove(connq, rc); amfree(rc->pkt); - if(!rc->donotclose) - amfree(rc); /* someone might still use it */ - /* eg. in sec_tcp_conn_read_callback if */ - /* event_wakeup call us. */ + if(!rc->donotclose) { + /* amfree(rc) */ + /* a memory leak occurs, but freeing it lead to memory + * corruption because it can still be used. + * We need to find a good place to free 'rc'. + */ + } } /* @@ -1549,13 +1572,13 @@ sec_tcp_conn_read( if (rc->ev_read != NULL) { rc->ev_read_refcnt++; - secprintf(( - "%s: sec: conn_read: incremented ev_read_refcnt to %d for %s\n", - debug_prefix_time(NULL), rc->ev_read_refcnt, rc->hostname)); + auth_debug(1, + _("sec: conn_read: incremented ev_read_refcnt to %d for %s\n"), + rc->ev_read_refcnt, rc->hostname); return; } - secprintf(("%s: sec: conn_read registering event handler for %s\n", - debug_prefix_time(NULL), rc->hostname)); + auth_debug(1, _("sec: conn_read registering event handler for %s\n"), + rc->hostname); rc->ev_read = event_register((event_id_t)rc->read, EV_READFD, sec_tcp_conn_read_callback, rc); rc->ev_read_refcnt = 1; @@ -1567,15 +1590,15 @@ sec_tcp_conn_read_cancel( { --rc->ev_read_refcnt; - secprintf(( - "%s: sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n", - debug_prefix_time(NULL), - rc->ev_read_refcnt, rc->hostname)); + auth_debug(1, + _("sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n"), + rc->ev_read_refcnt, rc->hostname); if (rc->ev_read_refcnt > 0) { return; } - secprintf(("%s: sec: conn_read_cancel: releasing event handler for %s\n", - debug_prefix_time(NULL), rc->hostname)); + auth_debug(1, + _("sec: conn_read_cancel: releasing event handler for %s\n"), + rc->hostname); event_release(rc->ev_read); rc->ev_read = NULL; } @@ -1595,8 +1618,7 @@ recvpkt_callback( assert(rh != NULL); - secprintf(("%s: sec: recvpkt_callback: %d\n", - debug_prefix_time(NULL), bufsize)); + auth_debug(1, _("sec: recvpkt_callback: %zd\n"), bufsize); /* * We need to cancel the recvpkt request before calling * the callback because the callback may reschedule us. @@ -1606,11 +1628,11 @@ recvpkt_callback( switch (bufsize) { case 0: security_seterror(&rh->sech, - "EOF on read from %s", rh->hostname); + _("EOF on read from %s"), rh->hostname); (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR); return; case -1: - security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr)); + security_seterror(&rh->sech, "%s", security_stream_geterror(&rh->rs->secstr)); (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR); return; default: @@ -1618,10 +1640,10 @@ recvpkt_callback( } parse_pkt(&pkt, buf, (size_t)bufsize); - secprintf(( - "%s: sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n", - debug_prefix_time(NULL), pkt_type2str(pkt.type), pkt.type, - rh->hostname, pkt.body)); + auth_debug(1, + _("sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n"), + pkt_type2str(pkt.type), pkt.type, + rh->hostname, pkt.body); if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0) (*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR); else @@ -1639,8 +1661,7 @@ stream_read_sync_callback( struct sec_stream *rs = s; assert(rs != NULL); - secprintf(("%s: sec: stream_read_callback_sync: handle %d\n", - debug_prefix_time(NULL), rs->handle)); + auth_debug(1, _("sec: stream_read_callback_sync: handle %d\n"), rs->handle); /* * Make sure this was for us. If it was, then blow away the handle @@ -1649,12 +1670,10 @@ stream_read_sync_callback( * If the handle is EOF, pass that up to our callback. */ if (rs->rc->handle == rs->handle) { - secprintf(("%s: sec: stream_read_callback_sync: it was for us\n", - debug_prefix_time(NULL))); + auth_debug(1, _("sec: stream_read_callback_sync: it was for us\n")); rs->rc->handle = H_TAKEN; } else if (rs->rc->handle != H_EOF) { - secprintf(("%s: sec: stream_read_callback_sync: not for us\n", - debug_prefix_time(NULL))); + auth_debug(1, _("sec: stream_read_callback_sync: not for us\n")); return; } @@ -1665,19 +1684,21 @@ stream_read_sync_callback( */ tcpm_stream_read_cancel(rs); + sync_pktlen = rs->rc->pktlen; + sync_pkt = malloc(sync_pktlen); + memcpy(sync_pkt, rs->rc->pkt, sync_pktlen); + if (rs->rc->pktlen <= 0) { - secprintf(("%s: sec: stream_read_sync_callback: %s\n", - debug_prefix_time(NULL), rs->rc->errmsg)); - security_stream_seterror(&rs->secstr, rs->rc->errmsg); + auth_debug(1, _("sec: stream_read_sync_callback: %s\n"), rs->rc->errmsg); + security_stream_seterror(&rs->secstr, "%s", rs->rc->errmsg); if(rs->closed_by_me == 0 && rs->closed_by_network == 0) sec_tcp_conn_put(rs->rc); rs->closed_by_network = 1; return; } - secprintf(( - "%s: sec: stream_read_callback_sync: read %zd bytes from %s:%d\n", - debug_prefix_time(NULL), - rs->rc->pktlen, rs->rc->hostname, rs->handle)); + auth_debug(1, + _("sec: stream_read_callback_sync: read %zd bytes from %s:%d\n"), + rs->rc->pktlen, rs->rc->hostname, rs->handle); } /* @@ -1688,10 +1709,16 @@ stream_read_callback( void * arg) { struct sec_stream *rs = arg; + time_t logtime; + assert(rs != NULL); - secprintf(("%s: sec: stream_read_callback: handle %d\n", - debug_prefix_time(NULL), rs->handle)); + logtime = time(NULL); + if (rs && rs->rc && logtime > rs->rc->logstamp + 10) { + g_debug("stream_read_callback: data is still flowing"); + rs->rc->logstamp = logtime; + } + auth_debug(1, _("sec: stream_read_callback: handle %d\n"), rs->handle); /* * Make sure this was for us. If it was, then blow away the handle @@ -1700,12 +1727,10 @@ stream_read_callback( * If the handle is EOF, pass that up to our callback. */ if (rs->rc->handle == rs->handle) { - secprintf(("%s: sec: stream_read_callback: it was for us\n", - debug_prefix_time(NULL))); + auth_debug(1, _("sec: stream_read_callback: it was for us\n")); rs->rc->handle = H_TAKEN; } else if (rs->rc->handle != H_EOF) { - secprintf(("%s: sec: stream_read_callback: not for us\n", - debug_prefix_time(NULL))); + auth_debug(1, _("sec: stream_read_callback: not for us\n")); return; } @@ -1717,21 +1742,18 @@ stream_read_callback( tcpm_stream_read_cancel(rs); if (rs->rc->pktlen <= 0) { - secprintf(("%s: sec: stream_read_callback: %s\n", - debug_prefix_time(NULL), rs->rc->errmsg)); - security_stream_seterror(&rs->secstr, rs->rc->errmsg); + auth_debug(1, _("sec: stream_read_callback: %s\n"), rs->rc->errmsg); + security_stream_seterror(&rs->secstr, "%s", rs->rc->errmsg); if(rs->closed_by_me == 0 && rs->closed_by_network == 0) sec_tcp_conn_put(rs->rc); rs->closed_by_network = 1; (*rs->fn)(rs->arg, NULL, rs->rc->pktlen); return; } - secprintf(("%s: sec: stream_read_callback: read %zd bytes from %s:%d\n", - debug_prefix_time(NULL), - rs->rc->pktlen, rs->rc->hostname, rs->handle)); + auth_debug(1, _("sec: stream_read_callback: read %zd bytes from %s:%d\n"), + rs->rc->pktlen, rs->rc->hostname, rs->handle); (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen); - secprintf(("%s: sec: after callback stream_read_callback\n", - debug_prefix_time(NULL))); + auth_debug(1, _("sec: after callback stream_read_callback\n")); } /* @@ -1751,24 +1773,29 @@ sec_tcp_conn_read_callback( assert(cookie != NULL); - secprintf(("%s: sec: conn_read_callback\n", debug_prefix_time(NULL))); + auth_debug(1, _("sec: conn_read_callback\n")); /* Read the data off the wire. If we get errors, shut down. */ - rval = tcpm_recv_token(rc->read, &rc->handle, &rc->errmsg, &rc->pkt, - &rc->pktlen, 60); - secprintf(("%s: sec: conn_read_callback: tcpm_recv_token returned %d\n", - debug_prefix_time(NULL), rval)); + rval = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, &rc->pkt, + &rc->pktlen); + auth_debug(1, _("sec: conn_read_callback: tcpm_recv_token returned %zd\n"), + rval); + + if (rval == -2) { + return; + } + if (rval < 0 || rc->handle == H_EOF) { rc->pktlen = rval; rc->handle = H_EOF; - revent = event_wakeup((event_id_t)rc); - secprintf(("%s: sec: conn_read_callback: event_wakeup return %d\n", - debug_prefix_time(NULL), revent)); + revent = event_wakeup((event_id_t)rc->event_id); + auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"), + revent); /* delete our 'accept' reference */ if (rc->accept_fn != NULL) { if(rc->refcnt != 1) { - dbprintf(("STRANGE, rc->refcnt should be 1, it is %d\n", - rc->refcnt)); + dbprintf(_("STRANGE, rc->refcnt should be 1, it is %d\n"), + rc->refcnt); rc->refcnt=1; } rc->accept_fn = NULL; @@ -1779,17 +1806,16 @@ sec_tcp_conn_read_callback( if(rval == 0) { rc->pktlen = 0; - revent = event_wakeup((event_id_t)rc); - secprintf(("%s: 0 sec: conn_read_callback: event_wakeup return %d\n", - debug_prefix_time(NULL), revent)); + revent = event_wakeup((event_id_t)rc->event_id); + auth_debug(1, + _("sec: conn_read_callback: event_wakeup return %d\n"), revent); return; } /* If there are events waiting on this handle, we're done */ rc->donotclose = 1; - revent = event_wakeup((event_id_t)rc); - secprintf(("%s: sec: conn_read_callback: event_wakeup return %d\n", - debug_prefix_time(NULL), rval)); + revent = event_wakeup((event_id_t)rc->event_id); + auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"), revent); rc->donotclose = 0; if (rc->handle == H_TAKEN || rc->pktlen == 0) { if(rc->refcnt == 0) amfree(rc); @@ -1799,10 +1825,14 @@ sec_tcp_conn_read_callback( assert(rc->refcnt > 0); /* If there is no accept fn registered, then drop the packet */ - if (rc->accept_fn == NULL) + if (rc->accept_fn == NULL) { + g_warning( + _("sec: conn_read_callback: %zd bytes for handle %d went unclaimed!"), + rc->pktlen, rc->handle); return; + } - rh = alloc(SIZEOF(*rh)); + rh = g_new0(struct sec_handle, 1); security_handleinit(&rh->sech, rc->driver); rh->hostname = stralloc(rc->hostname); rh->ev_timeout = NULL; @@ -1810,10 +1840,10 @@ sec_tcp_conn_read_callback( rh->peer = rc->peer; rh->rs = tcpma_stream_client(rh, rc->handle); - secprintf(("%s: sec: new connection\n", debug_prefix_time(NULL))); + auth_debug(1, _("sec: new connection\n")); pkt.body = NULL; parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen); - secprintf(("%s: sec: calling accept_fn\n", debug_prefix_time(NULL))); + auth_debug(1, _("sec: calling accept_fn\n")); if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0) (*rc->accept_fn)(&rh->sech, NULL); else @@ -1829,8 +1859,7 @@ parse_pkt( { const unsigned char *bufp = buf; - secprintf(("%s: sec: parse_pkt: parsing buffer of %d bytes\n", - debug_prefix_time(NULL), bufsize)); + auth_debug(1, _("sec: parse_pkt: parsing buffer of %zu bytes\n"), bufsize); pkt->type = (pktype_t)*bufp++; bufsize--; @@ -1845,9 +1874,8 @@ parse_pkt( } pkt->size = strlen(pkt->body); - secprintf(("%s: sec: parse_pkt: %s (%d): \"%s\"\n", - debug_prefix_time(NULL), pkt_type2str(pkt->type), - pkt->type, pkt->body)); + auth_debug(1, _("sec: parse_pkt: %s (%d): \"%s\"\n"), pkt_type2str(pkt->type), + pkt->type, pkt->body); } /* @@ -1863,12 +1891,11 @@ pkthdr2str( assert(rh != NULL); assert(pkt != NULL); - snprintf(retbuf, SIZEOF(retbuf), "Amanda %d.%d %s HANDLE %s SEQ %d\n", + g_snprintf(retbuf, SIZEOF(retbuf), _("Amanda %d.%d %s HANDLE %s SEQ %d\n"), VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type), rh->proto_handle, rh->sequence); - secprintf(("%s: bsd: pkthdr2str handle '%s'\n", - debug_prefix_time(NULL), rh->proto_handle)); + auth_debug(1, _("bsd: pkthdr2str handle '%s'\n"), rh->proto_handle); /* check for truncation. If only we had asprintf()... */ assert(retbuf[strlen(retbuf) - 1] == '\n'); @@ -1959,7 +1986,7 @@ check_user( /* lookup our local user name */ if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) { - return vstralloc("getpwnam(", CLIENT_LOGIN, ") fails", NULL); + return vstrallocf(_("getpwnam(%s) failed."), CLIENT_LOGIN); } /* @@ -1971,12 +1998,12 @@ check_user( #ifndef USE_AMANDAHOSTS r = check_user_ruserok(rh->hostname, pwd, remoteuser); #else - r = check_user_amandahosts(rh->hostname, rh->peer.sin_addr, pwd, remoteuser, service); + r = check_user_amandahosts(rh->hostname, &rh->peer, pwd, remoteuser, service); #endif if (r != NULL) { - result = vstralloc("user ", remoteuser, " from ", rh->hostname, - " is not allowed to execute the service ", - service, ": ", r, NULL); + result = vstrallocf( + _("user %s from %s is not allowed to execute the service %s: %s"), + remoteuser, rh->hostname, service, r); amfree(r); } amfree(localuser); @@ -1987,7 +2014,7 @@ check_user( * See if a remote user is allowed in. This version uses ruserok() * and friends. * - * Returns 0 on success, or negative on error. + * Returns NULL on success, or error message on error. */ char * check_user_ruserok( @@ -2004,7 +2031,6 @@ check_user_ruserok( char *es; char *result; int ok; - char number[NUM_STR_SIZE]; uid_t myuid = getuid(); /* @@ -2019,51 +2045,46 @@ check_user_ruserok( * problem and is expected. Thanks a lot. Not. */ if (pipe(fd) != 0) { - return stralloc2("pipe() fails: ", strerror(errno)); + return stralloc2(_("pipe() fails: "), strerror(errno)); } if ((ruserok_pid = fork()) < 0) { - return stralloc2("fork() fails: ", strerror(errno)); + return stralloc2(_("fork() fails: "), strerror(errno)); } else if (ruserok_pid == 0) { int ec; close(fd[0]); fError = fdopen(fd[1], "w"); if (!fError) { - error("Can't fdopen: %s", strerror(errno)); + error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } /* pamper braindead ruserok's */ if (chdir(pwd->pw_dir) != 0) { - fprintf(fError, "chdir(%s) failed: %s", + g_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); - - secprintf(("%s: bsd: calling ruserok(%s, %d, %s, %s)\n", - debug_prefix_time(NULL), - host, ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name)); - if (myuid == 0) { - secprintf(("%s: bsd: because you are running as root, ", - debug_prefix(NULL))); - secprintf(("/etc/hosts.equiv will not be used\n")); - } else { - show_stat_info("/etc/hosts.equiv", NULL); - } - show_stat_info(dir, "/.rhosts"); - amfree(dir); + if (debug_auth >= 9) { + char *dir = stralloc(pwd->pw_dir); + + auth_debug(9, _("bsd: calling ruserok(%s, %d, %s, %s)\n"), host, + ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name); + if (myuid == 0) { + auth_debug(9, _("bsd: because you are running as root, ")); + auth_debug(9, _("/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) { - secprintf(("%s: Could not open /dev/null: %s\n", - debug_prefix(NULL), strerror(errno))); + auth_debug(1, _("Could not open /dev/null: %s\n"), strerror(errno)); ec = 1; } else { ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN); @@ -2080,7 +2101,7 @@ check_user_ruserok( close(fd[1]); fError = fdopen(fd[0], "r"); if (!fError) { - error("Can't fdopen: %s", strerror(errno)); + error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } @@ -2104,19 +2125,15 @@ check_user_ruserok( while (pid != ruserok_pid) { if ((pid == (pid_t) -1) && (errno != EINTR)) { amfree(result); - return stralloc2("ruserok wait failed: %s", strerror(errno)); + return vstrallocf(_("ruserok wait failed: %s"), strerror(errno)); } pid = wait(&exitcode); } - if (WIFSIGNALED(exitcode)) { + if (!WIFEXITED(exitcode) || WEXITSTATUS(exitcode) != 0) { amfree(result); - snprintf(number, SIZEOF(number), "%d", WTERMSIG(exitcode)); - return stralloc2("ruserok child got signal ", number); - } - if (WEXITSTATUS(exitcode) == 0) { + result = str_exit_status("ruserok child", exitcode); + } else { amfree(result); - } else if (result == NULL) { - result = stralloc("ruserok failed"); } return result; @@ -2124,12 +2141,12 @@ check_user_ruserok( /* * Check to see if a user is allowed in. This version uses .amandahosts - * Returns -1 on failure, or 0 on success. + * Returns an error message on failure, or NULL on success. */ char * check_user_amandahosts( const char * host, - struct in_addr addr, + sockaddr_union *addr, struct passwd * pwd, const char * remoteuser, const char * service) @@ -2142,22 +2159,25 @@ check_user_amandahosts( FILE *fp = NULL; int found; struct stat sbuf; - char n1[NUM_STR_SIZE]; - char n2[NUM_STR_SIZE]; int hostmatch; int usermatch; char *aservice = NULL; +#ifdef WORKING_IPV6 + char ipstr[INET6_ADDRSTRLEN]; +#else + char ipstr[INET_ADDRSTRLEN]; +#endif - secprintf(("check_user_amandahosts(host=%s, pwd=%p, " - "remoteuser=%s, service=%s)\n", - host, pwd, remoteuser, service)); + auth_debug(1, _("check_user_amandahosts(host=%s, pwd=%p, " + "remoteuser=%s, service=%s)\n"), + host, pwd, remoteuser, service); ptmp = stralloc2(pwd->pw_dir, "/.amandahosts"); -#if defined(SHOW_SECURITY_DETAIL) /* { */ - show_stat_info(ptmp, "");; -#endif /* } */ + if (debug_auth >= 9) { + show_stat_info(ptmp, "");; + } if ((fp = fopen(ptmp, "r")) == NULL) { - result = vstralloc("cannot open ", ptmp, ": ", strerror(errno), NULL); + result = vstrallocf(_("cannot open %s: %s"), ptmp, strerror(errno)); amfree(ptmp); return result; } @@ -2167,21 +2187,16 @@ check_user_amandahosts( * have any group/other access allowed. */ if (fstat(fileno(fp), &sbuf) != 0) { - result = vstralloc("cannot fstat ", ptmp, ": ", strerror(errno), NULL); + result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno)); goto common_exit; } if (sbuf.st_uid != pwd->pw_uid) { - snprintf(n1, SIZEOF(n1), "%ld", (long)sbuf.st_uid); - snprintf(n2, SIZEOF(n2), "%ld", (long)pwd->pw_uid); - result = vstralloc(ptmp, ": ", - "owned by id ", n1, - ", should be ", n2, - NULL); + result = vstrallocf(_("%s: owned by id %ld, should be %ld"), + ptmp, (long)sbuf.st_uid, (long)pwd->pw_uid); goto common_exit; } if ((sbuf.st_mode & 077) != 0) { - result = stralloc2(ptmp, - ": incorrect permissions; file must be accessible only by its owner"); + result = vstrallocf(_("%s: incorrect permissions; file must be accessible only by its owner"), ptmp); goto common_exit; } @@ -2195,9 +2210,7 @@ check_user_amandahosts( continue; } -#if defined(SHOW_SECURITY_DETAIL) /* { */ - secprintf(("%s: bsd: processing line: <%s>\n", debug_prefix(NULL), line)); -#endif /* } */ + auth_debug(9, _("bsd: processing line: <%s>\n"), line); /* get the host out of the file */ if ((filehost = strtok(line, " \t")) == NULL) { amfree(line); @@ -2211,24 +2224,29 @@ check_user_amandahosts( hostmatch = (strcasecmp(filehost, host) == 0); /* ok if addr=127.0.0.1 and - * either localhost or localhost.domain is in .amandahost */ - if ( !hostmatch ) { - if (strcmp(inet_ntoa(addr), "127.0.0.1")== 0 && - (strcasecmp(filehost, "localhost")== 0 || - strcasecmp(filehost, "localhost.localdomain")== 0)) - { - hostmatch = 1; - } - } + * either localhost or localhost.domain is in .amandahost */ + if (!hostmatch && + (strcasecmp(filehost, "localhost")== 0 || + strcasecmp(filehost, "localhost.localdomain")== 0)) { +#ifdef WORKING_IPV6 + if (SU_GET_FAMILY(addr) == (sa_family_t)AF_INET6) + inet_ntop(AF_INET6, &addr->sin6.sin6_addr, + ipstr, sizeof(ipstr)); + else +#endif + inet_ntop(AF_INET, &addr->sin.sin_addr, + ipstr, sizeof(ipstr)); + if (strcmp(ipstr, "127.0.0.1") == 0 || + strcmp(ipstr, "::1") == 0) + hostmatch = 1; + } usermatch = (strcasecmp(fileuser, remoteuser) == 0); -#if defined(SHOW_SECURITY_DETAIL) /* { */ - secprintf(("%s: bsd: comparing \"%s\" with\n", debug_prefix(NULL), filehost)); - secprintf(("%s: bsd: \"%s\" (%s)\n", host, - debug_prefix(NULL), hostmatch ? "match" : "no match")); - secprintf(("%s: bsd: and \"%s\" with\n", fileuser, debug_prefix(NULL))); - secprintf(("%s: bsd: \"%s\" (%s)\n", remoteuser, - debug_prefix(NULL), usermatch ? "match" : "no match")); -#endif /* } */ + auth_debug(9, _("bsd: comparing \"%s\" with\n"), filehost); + auth_debug(9, _("bsd: \"%s\" (%s)\n"), host, + hostmatch ? _("match") : _("no match")); + auth_debug(9, _("bsd: and \"%s\" with\n"), fileuser); + auth_debug(9, _("bsd: \"%s\" (%s)\n"), remoteuser, + usermatch ? _("match") : _("no match")); /* compare */ if (!hostmatch || !usermatch) { amfree(line); @@ -2288,18 +2306,15 @@ check_user_amandahosts( if (! found) { if (strcmp(service, "amindexd") == 0 || strcmp(service, "amidxtaped") == 0) { - result = vstralloc("Please add \"amindexd amidxtaped\" to " - "the line in ", ptmp, NULL); + result = vstrallocf(_("Please add the line \"%s %s amindexd amidxtaped\" to %s on the server"), host, remoteuser, ptmp); } else if (strcmp(service, "amdump") == 0 || strcmp(service, "noop") == 0 || strcmp(service, "selfcheck") == 0 || strcmp(service, "sendsize") == 0 || strcmp(service, "sendbackup") == 0) { - result = vstralloc("Please add \"amdump\" to the line in ", - ptmp, NULL); + result = vstrallocf(_("Please add the line \"%s %s amdump\" to %s on the client"), host, remoteuser, ptmp); } else { - result = vstralloc(ptmp, ": ", - "invalid service ", service, NULL); + result = vstrallocf(_("%s: invalid service %s"), ptmp, service); } } @@ -2314,109 +2329,54 @@ common_exit: /* return 1 on success, 0 on failure */ int check_security( - struct sockaddr_in *addr, + sockaddr_union *addr, char * str, unsigned long cksum, char ** errstr) { char * remotehost = NULL, *remoteuser = NULL; char * bad_bsd = NULL; - struct hostent * hp; struct passwd * pwptr; uid_t myuid; - int i; - int j; char * s; char * fp; int ch; + char hostname[NI_MAXHOST]; + in_port_t port; + int result; (void)cksum; /* Quiet unused parameter warning */ - secprintf(("%s: check_security(addr=%p, str='%s', cksum=%ul, errstr=%p\n", - debug_prefix(NULL), addr, str, cksum, errstr)); + auth_debug(1, + _("check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n"), + addr, str, cksum, errstr); dump_sockaddr(addr); *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", + if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr), + hostname, NI_MAXHOST, NULL, 0, 0)) != 0) { + dbprintf(_("getnameinfo failed: %s\n"), + gai_strerror(result)); + *errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ", + "getnameinfo failed: ", gai_strerror(result), "]", 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); + remotehost = stralloc(hostname); + if( check_name_give_sockaddr(hostname, + (struct sockaddr *)addr, errstr) < 0) { 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), "%u", - (unsigned int)ntohs(addr->sin_port)); - *errstr = vstralloc("[", - "host ", remotehost, ": ", - "port ", number, " not secure", - "]", NULL); + port = SU_GET_PORT(addr); + if (port >= IPPORT_RESERVED) { + *errstr = vstrallocf(_("[host %s: port %u not secure]"), + remotehost, (unsigned int)port); amfree(remotehost); return 0; } @@ -2426,21 +2386,14 @@ check_security( s = str; ch = *s++; - bad_bsd = vstralloc("[", - "host ", remotehost, ": ", - "bad bsd security line", - "]", NULL); + bad_bsd = vstrallocf(_("[host %s: bad bsd security line]"), remotehost); -#define sc "USER " - if (strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) { + if (strncmp_const_skip(s - 1, "USER ", s, ch) != 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') { @@ -2460,22 +2413,20 @@ check_security( myuid = getuid(); if ((pwptr = getpwuid(myuid)) == NULL) - error("error [getpwuid(%d) fails]", myuid); + error(_("error [getpwuid(%d) fails]"), (int)myuid); - secprintf(("%s: bsd security: remote host %s user %s local user %s\n", - debug_prefix(NULL), remotehost, remoteuser, pwptr->pw_name)); + auth_debug(1, _("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, addr->sin_addr, pwptr, remoteuser, NULL); + s = check_user_amandahosts(remotehost, addr, pwptr, remoteuser, NULL); #endif if (s != NULL) { - *errstr = vstralloc("[", - "access as ", pwptr->pw_name, " not allowed", - " from ", remoteuser, "@", remotehost, - ": ", s, "]", NULL); + *errstr = vstrallocf(_("[access as %s not allowed from %s@%s: %s]"), + pwptr->pw_name, remoteuser, remotehost, s); } amfree(s); amfree(remotehost); @@ -2483,58 +2434,6 @@ check_security( return *errstr == NULL; } -/* - * Writes out the entire iovec - */ -ssize_t -net_writev( - int fd, - struct iovec * iov, - int iovcnt) -{ - ssize_t delta, n, total; - - assert(iov != NULL); - - total = 0; - while (iovcnt > 0) { - /* - * Write the iovec - */ - n = writev(fd, iov, iovcnt); - if (n < 0) { - if (errno != EINTR) - return (-1); - secprintf(("%s: net_writev got EINTR\n", - debug_prefix(NULL))); - } - else if (n == 0) { - errno = EIO; - return (-1); - } else { - total += n; - /* - * Iterate through each iov. Figure out what we still need - * to write out. - */ - for (; n > 0; iovcnt--, iov++) { - /* 'delta' is the bytes written from this iovec */ - delta = ((size_t)n < iov->iov_len) ? n : (ssize_t)iov->iov_len; - /* subtract from the total num bytes written */ - n -= delta; - assert(n >= 0); - /* subtract from this iovec */ - iov->iov_len -= delta; - iov->iov_base = (char *)iov->iov_base + delta; - /* if this iovec isn't empty, run the writev again */ - if (iov->iov_len > 0) - break; - } - } - } - return (total); -} - /* * Like read(), but waits until the entire buffer has been filled. */ @@ -2549,27 +2448,23 @@ net_read( ssize_t nread; size_t size = origsize; - secprintf(("%s: net_read: begin %d\n", debug_prefix_time(NULL), origsize)); + auth_debug(1, _("net_read: begin %zu\n"), origsize); while (size > 0) { - secprintf(("%s: net_read: while %d\n", - debug_prefix_time(NULL), size)); + auth_debug(1, _("net_read: while %zu\n"), size); nread = net_read_fillbuf(fd, timeout, buf, size); if (nread < 0) { - secprintf(("%s: db: net_read: end return(-1)\n", - debug_prefix_time(NULL))); + auth_debug(1, _("db: net_read: end return(-1)\n")); return (-1); } if (nread == 0) { - secprintf(("%s: net_read: end return(0)\n", - debug_prefix_time(NULL))); + auth_debug(1, _("net_read: end return(0)\n")); return (0); } buf += nread; size -= nread; } - secprintf(("%s: net_read: end %d\n", - debug_prefix_time(NULL), origsize)); + auth_debug(1, _("net_read: end %zu\n"), origsize); return ((ssize_t)origsize); } @@ -2583,11 +2478,11 @@ net_read_fillbuf( void * buf, size_t size) { - fd_set readfds; + SELECT_ARG_TYPE readfds; struct timeval tv; ssize_t nread; - secprintf(("%s: net_read_fillbuf: begin\n", debug_prefix_time(NULL))); + auth_debug(1, _("net_read_fillbuf: begin\n")); FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = timeout; @@ -2597,25 +2492,21 @@ net_read_fillbuf( errno = ETIMEDOUT; /* FALLTHROUGH */ case -1: - secprintf(("%s: net_read_fillbuf: case -1\n", - debug_prefix_time(NULL))); + auth_debug(1, _("net_read_fillbuf: case -1\n")); return (-1); case 1: - secprintf(("%s: net_read_fillbuf: case 1\n", - debug_prefix_time(NULL))); + auth_debug(1, _("net_read_fillbuf: case 1\n")); assert(FD_ISSET(fd, &readfds)); break; default: - secprintf(("%s: net_read_fillbuf: case default\n", - debug_prefix_time(NULL))); + auth_debug(1, _("net_read_fillbuf: case default\n")); assert(0); break; } nread = read(fd, buf, size); if (nread < 0) return (-1); - secprintf(("%s: net_read_fillbuf: end %d\n", - debug_prefix_time(NULL), nread)); + auth_debug(1, _("net_read_fillbuf: end %zd\n"), nread); return (nread); } @@ -2631,33 +2522,165 @@ show_stat_info( { char *name = vstralloc(a, b, NULL); struct stat sbuf; - struct passwd *pwptr; + struct passwd *pwptr G_GNUC_UNUSED; + struct passwd pw G_GNUC_UNUSED; char *owner; - struct group *grptr; + struct group *grptr G_GNUC_UNUSED; + struct group gr G_GNUC_UNUSED; char *group; + int buflen G_GNUC_UNUSED; + char *buf G_GNUC_UNUSED; if (stat(name, &sbuf) != 0) { - secprintf(("%s: bsd: cannot stat %s: %s\n", - debug_prefix_time(NULL), name, strerror(errno))); + auth_debug(1, _("bsd: cannot stat %s: %s\n"), 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 { + +#ifdef _SC_GETPW_R_SIZE_MAX + buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + if (buflen == -1) + buflen = 1024; +#else + buflen = 1024; +#endif + buf = malloc(buflen); + +#ifdef HAVE_GETPWUID_R + if (getpwuid_r(sbuf.st_uid, &pw, buf, buflen, &pwptr) == 0 && + pwptr != NULL) { owner = stralloc(pwptr->pw_name); + } else +#endif + { + owner = alloc(NUM_STR_SIZE + 1); + g_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid); } - if ((grptr = getgrgid(sbuf.st_gid)) == NULL) { - group = alloc(NUM_STR_SIZE + 1); - snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid); - } else { +#ifdef HAVE_GETGRGID_R + if (getgrgid_r(sbuf.st_gid, &gr, buf, buflen, &grptr) == 0 && + grptr != NULL) { group = stralloc(grptr->gr_name); + } else +#endif + { + group = alloc(NUM_STR_SIZE + 1); + g_snprintf(group, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid); } - secprintf(("%s: bsd: processing file: %s\n", debug_prefix(NULL), name)); - secprintf(("%s: bsd: owner=%s group=%s mode=%03o\n", - debug_prefix(NULL), owner, group, (int) (sbuf.st_mode & 0777))); + + auth_debug(1, _("bsd: processing file: %s\n"), name); + auth_debug(1, _("bsd: owner=%s group=%s mode=%03o\n"), + owner, group, + (int) (sbuf.st_mode & 0777)); amfree(name); amfree(owner); amfree(group); + amfree(buf); +} + +int +check_name_give_sockaddr( + const char *hostname, + struct sockaddr *addr, + char **errstr) +{ + int result; + struct addrinfo *res = NULL, *res1; + char *canonname; + + result = resolve_hostname(hostname, 0, &res, &canonname); + if (result != 0) { + dbprintf(_("check_name_give_sockaddr: resolve_hostname('%s'): %s\n"), hostname, gai_strerror(result)); + *errstr = newvstrallocf(*errstr, + _("check_name_give_sockaddr: resolve_hostname('%s'): %s"), + hostname, gai_strerror(result)); + goto error; + } + if (canonname == NULL) { + dbprintf(_("resolve_hostname('%s') did not return a canonical name\n"), hostname); + *errstr = newvstrallocf(*errstr, + _("check_name_give_sockaddr: resolve_hostname('%s') did not return a canonical name"), + hostname); + goto error; + } + + if (strncasecmp(hostname, canonname, strlen(hostname)) != 0) { + dbprintf(_("%s doesn't resolve to itself, it resolves to %s\n"), + hostname, canonname); + *errstr = newvstrallocf(*errstr, + _("%s doesn't resolve to itself, it resolves to %s"), + hostname, canonname); + goto error; + } + + for(res1=res; res1 != NULL; res1 = res1->ai_next) { + if (cmp_sockaddr((sockaddr_union *)res1->ai_addr, (sockaddr_union *)addr, 1) == 0) { + freeaddrinfo(res); + amfree(canonname); + return 0; + } + } + + g_debug("%s doesn't resolve to %s", + hostname, str_sockaddr((sockaddr_union *)addr)); + *errstr = newvstrallocf(*errstr, + "%s doesn't resolve to %s", + hostname, str_sockaddr((sockaddr_union *)addr)); +error: + if (res) freeaddrinfo(res); + amfree(canonname); + return -1; +} + +in_port_t +find_port_for_service( + char *service, + char *proto) +{ + in_port_t port; + char *s; + int all_numeric = 1; + + for (s=service; *s != '\0'; s++) { + if (!isdigit((int)*s)) { + all_numeric = 0; + } + } + + if (all_numeric == 1) { + port = atoi(service); + } else { + struct servent *sp; + + if ((sp = getservbyname(service, proto)) == NULL) { + port = 0; + } else { + port = (in_port_t)(ntohs((in_port_t)sp->s_port)); + } + } + + return port; +} + +char * +sec_get_authenticated_peer_name_gethostname( + security_handle_t *hdl G_GNUC_UNUSED) +{ + char *server_hostname; + server_hostname = malloc(1024); + if (gethostname(server_hostname, 1024) == 0) { + server_hostname[1023] = '\0'; + return server_hostname; + } + amfree(server_hostname); + return "localhost"; +} + +char * +sec_get_authenticated_peer_name_hostname( + security_handle_t *hdl) +{ + char *hostname = ((struct sec_handle *)hdl)->hostname; + if (!hostname) + hostname = ""; + return hostname; }