Imported Upstream version 2.6.0p2
[debian/amanda] / common-src / security-util.c
index a55bafbbe22ed8c326b3faa8ccf50d864774e3ea..77e5d0c8c914a8daac3996b5ffb0797e20d582f5 100644 (file)
@@ -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.
  *
 #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,10 +224,9 @@ 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));
@@ -261,8 +251,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 +284,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 +299,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,11 +324,11 @@ 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);
        return (-1);
@@ -426,19 +413,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 +442,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 = net_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 +489,7 @@ tcpm_send_token(
 
 ssize_t
 tcpm_recv_token(
+    struct tcp_conn    *rc,
     int                fd,
     int *      handle,
     char **    errmsg,
@@ -494,17 +504,14 @@ 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;
@@ -514,42 +521,40 @@ tcpm_recv_token(
     *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) &&
+       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] = (*size   >> 24) & 0xFF;
-           s[1] = (*size   >> 16) & 0xFF;
-           s[2] = (*size   >>  8) & 0xFF;
-           s[3] = (*size        ) & 0xFF;
+           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(s[i]) && s[i] != '\n') {
+           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;
+               default:
+                        dbprintf(_("read: %c\n"), s[i]); i++; s[i]=' ';
+                        break;
                }
            }
            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));
+           *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size: %s"), s);
+           dbprintf(_("tcpm_recv_token: invalid size %s\n"), 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));
+           *errmsg = newvstrallocf(*errmsg, _("tcpm_recv_token: invalid size"));
+           dbprintf(_("tcpm_recv_token: invalid size %zd\n"), *size);
        }
        *size = -1;
        return -1;
@@ -558,32 +563,38 @@ tcpm_recv_token(
     *buf = 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);
+       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 %zd 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));
 }
 
@@ -594,9 +605,9 @@ tcpm_close_connection(
 {
     struct sec_handle *rh = h;
 
-    hostname = hostname;
+    (void)hostname;
 
-    if(rh->rc->toclose == 0) {
+    if (rh && rh->rc && rh->rc->toclose == 0) {
        rh->rc->toclose = 1;
        sec_tcp_conn_put(rh->rc);
     }
@@ -633,7 +644,7 @@ tcpma_stream_client(
 
     if (id <= 0) {
        security_seterror(&rh->sech,
-           "%d: invalid security stream id", id);
+           _("%d: invalid security stream id"), id);
        return (NULL);
     }
 
@@ -653,8 +664,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);
 }
@@ -691,7 +701,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 +711,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,8 +727,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);
@@ -756,11 +764,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 +799,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);
        }
@@ -826,12 +834,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);
@@ -855,7 +864,7 @@ tcp_stream_write(
 
     if (fullwrite(rs->fd, buf, size) < 0) {
         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);
@@ -875,7 +884,7 @@ 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);
     }
@@ -901,13 +910,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 +945,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);
@@ -951,10 +963,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 +975,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 +991,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 +999,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 +1015,7 @@ 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(security_line);
            return (-1);        /* default errmsg */
        }
@@ -1045,7 +1058,7 @@ 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
      */
@@ -1063,10 +1076,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:
@@ -1078,14 +1091,13 @@ udpbsd_sendpkt(
      */
     dgram_cat(&rh->udp->dgram, 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 +1114,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 +1148,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 +1210,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 +1239,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 +1273,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);
-    }
-
-    /*
-     * 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);
-    }
+    auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"),
+                  (unsigned int)ntohs(port), handle, sequence);
+    assert(addr != NULL);
 
-    /*
-     * 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;
-       }
-    }
+    rh->hostname = stralloc(hostname);
+    copy_sockaddr(&rh->peer, addr);
+    SU_SET_PORT(&rh->peer, port);
 
-    /*
-     * 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 +1310,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 +1327,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 +1357,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 +1367,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;
@@ -1456,25 +1430,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
      */
@@ -1494,6 +1467,9 @@ 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;
     connq_append(rc);
     return (rc);
 }
@@ -1510,14 +1486,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)
@@ -1549,13 +1523,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 +1541,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 +1569,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,7 +1579,7 @@ 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:
@@ -1618,10 +1591,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 +1612,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 +1621,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;
     }
 
@@ -1666,18 +1636,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));
+       auth_debug(1, _("sec: stream_read_sync_callback: %s\n"), rs->rc->errmsg);
        security_stream_seterror(&rs->secstr, 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);
 }
 
 /*
@@ -1690,8 +1658,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
@@ -1700,12 +1667,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,8 +1682,7 @@ 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));
+       auth_debug(1, _("sec: stream_read_callback: %s\n"), rs->rc->errmsg);
        security_stream_seterror(&rs->secstr, rs->rc->errmsg);
        if(rs->closed_by_me == 0 && rs->closed_by_network == 0)
            sec_tcp_conn_put(rs->rc);
@@ -1726,12 +1690,10 @@ stream_read_callback(
        (*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 +1713,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));
+       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;
@@ -1780,16 +1742,15 @@ 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));
+       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));
+    auth_debug(1, _("sec: conn_read_callback: event_wakeup return %zd\n"), rval);
     rc->donotclose = 0;
     if (rc->handle == H_TAKEN || rc->pktlen == 0) {
        if(rc->refcnt == 0) amfree(rc);
@@ -1810,10 +1771,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 +1790,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 +1805,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 +1822,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 +1917,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 +1929,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 +1945,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 +1962,6 @@ check_user_ruserok(
     char *es;
     char *result;
     int ok;
-    char number[NUM_STR_SIZE];
     uid_t myuid = getuid();
 
     /*
@@ -2019,51 +1976,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 +2032,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 +2056,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 +2072,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 +2090,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 +2118,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 +2141,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 +2155,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 +2237,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 client"), 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 +2260,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 +2317,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 +2344,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);
@@ -2505,8 +2387,7 @@ net_writev(
        if (n < 0) {
            if (errno != EINTR)
                return (-1);
-           secprintf(("%s: net_writev got EINTR\n",
-                      debug_prefix(NULL)));
+           auth_debug(1, _("net_writev got EINTR\n"));
        }
        else if (n == 0) {
            errno = EIO;
@@ -2519,7 +2400,7 @@ net_writev(
             */
            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;
+               delta = ((size_t)n < (size_t)iov->iov_len) ? n : (ssize_t)iov->iov_len;
                /* subtract from the total num bytes written */
                n -= delta;
                assert(n >= 0);
@@ -2549,27 +2430,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 +2460,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 +2474,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 +2504,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;
 }