X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fsecurity-util.c;h=ee2f99c6f7032216fb6d66bdacd88b9d49cd609b;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=531ec867b19e033466a53405b8a4c719d44a58f9;hpb=12179dea039515c06168c0037d048566a3f623de;p=debian%2Famanda diff --git a/common-src/security-util.c b/common-src/security-util.c index 531ec86..ee2f99c 100644 --- a/common-src/security-util.c +++ b/common-src/security-util.c @@ -42,19 +42,7 @@ #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 +#include "sockaddr-util.h" /* * Magic values for sec_conn->handle @@ -116,9 +104,11 @@ 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; @@ -127,6 +117,8 @@ sec_accept( 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 +133,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 +210,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 +224,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 +252,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 +285,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 +300,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 +325,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 +355,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); } @@ -393,7 +381,7 @@ tcpm_stream_read_sync( if (rs->ev_read != NULL) { return -1; } - 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_sync_callback, rs); sec_tcp_conn_read(rs->rc); event_wait(rs->ev_read); @@ -426,19 +414,25 @@ 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; assert(SIZEOF(netlength) == 4); + auth_debug(1, "tcpm_send_token: write %zd bytes to handle %d\n", + len, handle); /* * Format is: * 32 bit length (network byte order) @@ -449,23 +443,39 @@ 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); + 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(errno)); return (-1); } return (0); @@ -480,6 +490,7 @@ tcpm_send_token( ssize_t tcpm_recv_token( + struct tcp_conn *rc, int fd, int * handle, char ** errmsg, @@ -494,62 +505,97 @@ tcpm_recv_token( 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))); + *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno)); + auth_debug(1, _("tcpm_recv_token: A return(-1)\n")); 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))); + *errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF")); + auth_debug(1, _("tcpm_recv_token: A return(0)\n")); return (0); default: break; } *size = (ssize_t)ntohl(netint[0]); - if (*size > NETWORK_BLOCK_BYTES) { - *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size", - NULL); - dbprintf(("%s: tcpm_recv_token: invalid size %d\n", - debug_prefix_time(NULL), *size)); + *handle = (int)ntohl(netint[1]); + /* 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[101]; + 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<100 && 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'; + *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size: %s"), s); + dbprintf(_("tcpm_recv_token: invalid size %s\n"), s); + } else { + *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size")); + dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size); + } *size = -1; return -1; } amfree(*buf); *buf = alloc((size_t)*size); - *handle = (int)ntohl(netint[1]); if(*size == 0) { - secprintf(("%s: tcpm_recv_token: read EOF from %d\n", - debug_prefix_time(NULL), *handle)); - *errmsg = newvstralloc(*errmsg, "EOF", - NULL); + auth_debug(1, _("tcpm_recv_token: read EOF from %d\n"), *handle); + *errmsg = newvstrallocf(*errmsg, _("EOF")); return 0; } switch (net_read(fd, *buf, (size_t)*size, timeout)) { case -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: *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; } - secprintf(("%s: tcpm_recv_token: read %ld bytes from %d\n", - debug_prefix_time(NULL), *size, *handle)); + 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; + } + return((*size)); } @@ -560,9 +606,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); } @@ -599,7 +645,7 @@ tcpma_stream_client( if (id <= 0) { security_seterror(&rh->sech, - "%hd: invalid security stream id", id); + _("%d: invalid security stream id"), id); return (NULL); } @@ -619,8 +665,7 @@ tcpma_stream_client( rh->rc = rs->rc; } - secprintf(("%s: sec: stream_client: connected to stream %hd\n", - debug_prefix_time(NULL), id)); + auth_debug(1, _("sec: stream_client: connected to stream %d\n"), id); return (rs); } @@ -657,20 +702,17 @@ 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); - //amfree(rh->hostname); - //rh->hostname = stralloc(rs->rc->hostname); /* * so as not to conflict with the amanda server's handle numbers, * we start at 500000 and work down */ 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); } @@ -686,8 +728,7 @@ 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); @@ -724,11 +765,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); } @@ -759,7 +800,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); } @@ -794,12 +835,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); @@ -821,9 +863,9 @@ tcp_stream_write( assert(rs != NULL); - if (fullwrite(rs->fd, buf, size) < 0) { + 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); @@ -843,9 +885,9 @@ bsd_prefix_packet( if ((pwd = getpwuid(getuid())) == NULL) { security_seterror(&rh->sech, - "can't get login name for my uid %ld", + _("can't get login name for my uid %ld"), (long)getuid()); - return(NULL); + return ""; } buf = alloc(16+strlen(pwd->pw_name)); strncpy(buf, "SECURITY USER ", (16 + strlen(pwd->pw_name))); @@ -869,13 +911,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) { @@ -902,8 +946,9 @@ 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) { + serviceX = stralloc(s); serviceY = strtok(serviceX, "\n"); if (serviceY) service = stralloc(serviceY); @@ -919,10 +964,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); @@ -930,7 +976,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); } @@ -946,7 +992,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); } @@ -954,14 +1000,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); @@ -970,7 +1016,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 */ } @@ -1013,12 +1060,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 @@ -1031,10 +1078,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: @@ -1044,16 +1091,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); } @@ -1070,8 +1116,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) { @@ -1105,8 +1150,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); @@ -1167,17 +1212,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); - //rh->udp->handle = NULL; + dbprintf(_("not from same host\n")); + dump_sockaddr(&rh->peer); + dump_sockaddr(&rh->udp->peer); return; } @@ -1194,10 +1241,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); + } } /* @@ -1227,81 +1275,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 %hd handle %s sequence %d\n", - debug_prefix_time(NULL), ntohs(port), - handle, sequence)); - assert(he != NULL); + auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"), + (unsigned int)ntohs(port), handle, sequence); + assert(addr != 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; + rh->hostname = stralloc(hostname); + copy_sockaddr(&rh->peer, addr); + SU_SET_PORT(&rh->peer, port); - /* - * 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); - } - - /* - * 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", - rh->hostname, he->h_name); - return (-1); - } - - /* - * 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) { @@ -1322,8 +1312,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); } @@ -1340,11 +1329,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 /* { */ @@ -1368,8 +1359,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) @@ -1379,26 +1369,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->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; @@ -1425,25 +1432,24 @@ sec_tcp_conn_get( { struct tcp_conn *rc; - 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 (rc = connq_first(); rc != NULL; rc = connq_next(rc)) { + 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 (rc != 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 */ @@ -1463,6 +1469,10 @@ sec_tcp_conn_get( rc->accept_fn = NULL; rc->recv_security_ok = NULL; rc->prefix_packet = NULL; + rc->auth = 0; + rc->conf_fn = NULL; + rc->datap = NULL; + rc->event_id = newevent++; connq_append(rc); return (rc); } @@ -1479,14 +1489,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) @@ -1500,10 +1508,13 @@ sec_tcp_conn_put( amfree(rc->errmsg); connq_remove(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'. + */ + } } /* @@ -1518,13 +1529,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; @@ -1536,15 +1547,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; } @@ -1564,8 +1575,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. @@ -1575,11 +1585,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: @@ -1587,10 +1597,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 @@ -1608,8 +1618,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 @@ -1618,12 +1627,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; } @@ -1635,18 +1642,16 @@ stream_read_sync_callback( tcpm_stream_read_cancel(rs); 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 %ld 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); } /* @@ -1659,8 +1664,7 @@ stream_read_callback( struct sec_stream *rs = arg; assert(rs != NULL); - secprintf(("%s: sec: stream_read_callback: handle %d\n", - debug_prefix_time(NULL), rs->handle)); + 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 @@ -1669,12 +1673,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; } @@ -1686,21 +1688,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 %ld 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")); } /* @@ -1720,23 +1719,24 @@ 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, + rval = tcpm_recv_token(rc, 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)); + auth_debug(1, _("sec: conn_read_callback: tcpm_recv_token returned %zd\n"), + rval); 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")); + dbprintf(_("STRANGE, rc->refcnt should be 1, it is %d\n"), + rc->refcnt); rc->refcnt=1; } rc->accept_fn = NULL; @@ -1747,17 +1747,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); @@ -1767,8 +1766,12 @@ 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)); security_handleinit(&rh->sech, rc->driver); @@ -1778,10 +1781,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 @@ -1797,8 +1800,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--; @@ -1813,9 +1815,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); } /* @@ -1831,12 +1832,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'); @@ -1875,7 +1875,7 @@ str2pkthdr( if ((tok = strtok(NULL, " ")) == NULL) goto parse_error; amfree(pkt->body); - pkt_init(pkt, pkt_str2type(tok), ""); + pkt_init_empty(pkt, pkt_str2type(tok)); if (pkt->type == (pktype_t)-1) goto parse_error; @@ -1927,7 +1927,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); } /* @@ -1939,12 +1939,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); @@ -1955,7 +1955,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( @@ -1972,7 +1972,6 @@ check_user_ruserok( char *es; char *result; int ok; - char number[NUM_STR_SIZE]; uid_t myuid = getuid(); /* @@ -1987,51 +1986,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); @@ -2048,7 +2042,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*/ } @@ -2072,19 +2066,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; @@ -2092,12 +2082,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) @@ -2110,22 +2100,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; } @@ -2135,21 +2128,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; } @@ -2163,9 +2151,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); @@ -2179,24 +2165,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); @@ -2256,18 +2247,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); } } @@ -2282,108 +2270,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); - 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); + remotehost = stralloc(hostname); + if( check_name_give_sockaddr(hostname, + (struct sockaddr *)addr, errstr) < 0) { 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), "%hd", (short)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; } @@ -2393,21 +2327,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') { @@ -2427,22 +2354,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); @@ -2450,58 +2375,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. */ @@ -2516,27 +2389,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); } @@ -2550,11 +2419,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; @@ -2564,25 +2433,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); } @@ -2598,33 +2463,111 @@ 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; + } + } + + dbprintf(_("%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; }