X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fsecurity-util.c;h=4035cbad58d2876bd0be817aec96572b13001d4f;hb=d3b2175e084f88c8736ad7073eacbf4670147aec;hp=a55bafbbe22ed8c326b3faa8ccf50d864774e3ea;hpb=34197d9f46a5f4e944378cbb65fca32ee0eec7b9;p=debian%2Famanda diff --git a/common-src/security-util.c b/common-src/security-util.c index a55bafb..4035cba 100644 --- a/common-src/security-util.c +++ b/common-src/security-util.c @@ -25,7 +25,7 @@ */ /* - * $Id: security-util.c,v 1.25.2.10 2007/01/24 00:35:14 martinea Exp $ + * $Id: security-util.c,v 1.25 2006/07/22 12:04:47 martinea Exp $ * * sec-security.c - security and transport over sec or a sec-like command. * @@ -43,19 +43,6 @@ #include "stream.h" #include "version.h" -/* #define SEC_DEBUG */ -#define SHOW_SECURITY_DETAIL - -#ifdef SEC_DEBUG -# define secprintf(x) dbprintf(x) -#else -# ifdef __lint -# define secprintf(x) (void)(x) -# else -# define secprintf(x) -# endif -#endif - /* * Magic values for sec_conn->handle */ @@ -141,8 +128,8 @@ sec_close( assert(rh != NULL); - secprintf(("%s: sec: closing handle to %s\n", debug_prefix_time(NULL), - rh->hostname)); + auth_debug(1, ("%s: sec: closing handle to %s\n", debug_prefix_time(NULL), + rh->hostname)); if (rh->rs != NULL) { /* This may be null if we get here on an error */ @@ -219,7 +206,8 @@ stream_sendpkt( assert(rh != NULL); assert(pkt != NULL); - secprintf(("%s: sec: stream_sendpkt: enter\n", debug_prefix_time(NULL))); + auth_debug(1, ("%s: sec: stream_sendpkt: enter\n", + debug_prefix_time(NULL))); if (rh->rc->prefix_packet) s = rh->rc->prefix_packet(rh, pkt); @@ -233,10 +221,10 @@ 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, + ("%s: sec: stream_sendpkt: %s (%d) pkt_t (len " SIZE_T_FMT ") contains:\n\n\"%s\"\n\n", + debug_prefix_time(NULL), 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 +249,8 @@ stream_recvpkt( assert(rh != NULL); - secprintf(("%s: sec: recvpkt registered for %s\n", - debug_prefix_time(NULL), rh->hostname)); + auth_debug(1, ("%s: sec: recvpkt registered for %s\n", + debug_prefix_time(NULL), rh->hostname)); /* * Reset any pending timeout on this handle @@ -295,8 +283,8 @@ stream_recvpkt_timeout( assert(rh != NULL); - secprintf(("%s: sec: recvpkt timeout for %s\n", - debug_prefix_time(NULL), rh->hostname)); + auth_debug(1, ("%s: sec: recvpkt timeout for %s\n", + debug_prefix_time(NULL), rh->hostname)); stream_recvpkt_cancel(rh); (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT); @@ -311,8 +299,8 @@ 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, ("%s: sec: cancelling recvpkt for %s\n", + debug_prefix_time(NULL), rh->hostname)); assert(rh != NULL); @@ -337,11 +325,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, ("%s: sec: stream_write: writing " SIZE_T_FMT " bytes to %s:%d %d\n", + debug_prefix_time(NULL), 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,6 +414,7 @@ tcpm_stream_read_cancel( */ ssize_t tcpm_send_token( + struct tcp_conn *rc, int fd, int handle, char ** errmsg, @@ -436,9 +425,14 @@ tcpm_send_token( uint32_t netlength; struct iovec iov[3]; int nb_iov = 3; + int rval; + char *encbuf; + ssize_t encsize; assert(SIZEOF(netlength) == 4); + auth_debug(1, ("%s: tcpm_send_token: write %zd bytes to handle %d\n", + debug_prefix_time(NULL), len, handle)); /* * Format is: * 32 bit length (network byte order) @@ -453,16 +447,32 @@ tcpm_send_token( 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); @@ -480,6 +490,7 @@ tcpm_send_token( ssize_t tcpm_recv_token( + struct tcp_conn *rc, int fd, int * handle, char ** errmsg, @@ -496,15 +507,15 @@ tcpm_recv_token( if (errmsg) *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno), NULL); - secprintf(("%s: tcpm_recv_token: A return(-1)\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: tcpm_recv_token: A return(-1)\n", + debug_prefix_time(NULL))); return (-1); case 0: *size = 0; *handle = H_EOF; *errmsg = newvstralloc(*errmsg, "SOCKET_EOF", NULL); - secprintf(("%s: tcpm_recv_token: A return(0)\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: tcpm_recv_token: A return(0)\n", + debug_prefix_time(NULL))); return (0); default: break; @@ -514,20 +525,20 @@ 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; @@ -548,7 +559,7 @@ tcpm_recv_token( } else { *errmsg = newvstralloc(*errmsg, "tcpm_recv_token: invalid size", NULL); - dbprintf(("%s: tcpm_recv_token: invalid size %zd\n", + dbprintf(("%s: tcpm_recv_token: invalid size " SSIZE_T_FMT "\n", debug_prefix_time(NULL), *size)); } *size = -1; @@ -558,8 +569,8 @@ 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)); + auth_debug(1, ("%s: tcpm_recv_token: read EOF from %d\n", + debug_prefix_time(NULL), *handle)); *errmsg = newvstralloc(*errmsg, "EOF", NULL); return 0; @@ -569,21 +580,34 @@ tcpm_recv_token( if (errmsg) *errmsg = newvstralloc(*errmsg, "recv error: ", strerror(errno), NULL); - secprintf(("%s: tcpm_recv_token: B return(-1)\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: tcpm_recv_token: B return(-1)\n", + debug_prefix_time(NULL))); 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))); + auth_debug(1, ("%s: tcpm_recv_token: B return(0)\n", + debug_prefix_time(NULL))); return (0); default: break; } - secprintf(("%s: tcpm_recv_token: read %zd bytes from %d\n", - debug_prefix_time(NULL), *size, *handle)); + auth_debug(1, ("%s: tcpm_recv_token: read " SSIZE_T_FMT " bytes from %d\n", + debug_prefix_time(NULL), *size, *handle)); + + if (*size > 0 && rc->driver->data_decrypt != NULL) { + char *decbuf; + ssize_t decsize; + /* (the extra (void *) cast is to quiet type-punning warnings) */ + rc->driver->data_decrypt(rc, *buf, *size, (void **)(void *)&decbuf, &decsize); + if (*buf != decbuf) { + amfree(*buf); + *buf = decbuf; + } + *size = decsize; + } + return((*size)); } @@ -594,9 +618,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); } @@ -653,8 +677,8 @@ 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, ("%s: sec: stream_client: connected to stream %d\n", + debug_prefix_time(NULL), id)); return (rs); } @@ -701,8 +725,8 @@ 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, ("%s: sec: stream_server: created stream %d\n", + debug_prefix_time(NULL), rs->handle)); return (rs); } @@ -718,8 +742,8 @@ 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, ("%s: sec: tcpma_stream_close: closing stream %d\n", + debug_prefix_time(NULL), rs->handle)); if(rs->closed_by_network == 0 && rs->rc->write != -1) tcpm_stream_write(rs, &buf, 0); @@ -826,6 +850,7 @@ 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); @@ -901,13 +926,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 +961,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 +979,11 @@ bsd_recv_security_ok( /* * Request packets must come from a reserved port */ - if (ntohs(rh->peer.sin_port) >= IPPORT_RESERVED) { + port = SS_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); @@ -1045,7 +1074,7 @@ udpbsd_sendpkt( assert(rh != NULL); assert(pkt != NULL); - secprintf(("%s: udpbsd_sendpkt: enter\n", get_pname())); + auth_debug(1, ("%s: udpbsd_sendpkt: enter\n", get_pname())); /* * Initialize this datagram, and add the header */ @@ -1078,12 +1107,12 @@ 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, + ("%s: sec: udpbsd_sendpkt: %s (%d) pkt_t (len " SIZE_T_FMT ") contains:\n\n\"%s\"\n\n", + debug_prefix_time(NULL), 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), rh->hostname, strerror(errno)); @@ -1102,8 +1131,8 @@ udp_close( return; } - secprintf(("%s: udp: close handle '%s'\n", - debug_prefix_time(NULL), rh->proto_handle)); + auth_debug(1, ("%s: udp: close handle '%s'\n", + debug_prefix_time(NULL), rh->proto_handle)); udp_recvpkt_cancel(rh); if (rh->next) { @@ -1137,8 +1166,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, ("%s: udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n", + debug_prefix_time(NULL), cookie, fn, arg, timeout)); assert(rh != NULL); assert(fn != NULL); @@ -1199,16 +1228,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, ("%s: udp: receive handle '%s' netfd '%s'\n", + debug_prefix_time(NULL), 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 form same host\n")); + dump_sockaddr(&rh->peer); + dump_sockaddr(&rh->udp->peer); return; } @@ -1225,10 +1257,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 +1291,23 @@ int udp_inithandle( udp_handle_t * udp, struct sec_handle * rh, - struct hostent * he, + char * hostname, + struct sockaddr_storage *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); - } - - /* - * 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; - } - } + auth_debug(1, ("%s: udp_inithandle port %u handle %s sequence %d\n", + debug_prefix_time(NULL), (unsigned int)ntohs(port), + handle, sequence)); + assert(addr != NULL); - /* - * 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->hostname = stralloc(hostname); + memcpy(&rh->peer, addr, SIZEOF(rh->peer)); + SS_SET_PORT(&rh->peer, port); rh->prev = udp->bh_last; if (udp->bh_last) { @@ -1353,8 +1328,8 @@ 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, ("%s: udp: adding handle '%s'\n", + debug_prefix_time(NULL), rh->proto_handle)); return(0); } @@ -1371,11 +1346,14 @@ 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, ("%s: udp_netfd_read_callback(cookie=%p)\n", + debug_prefix_time(NULL), cookie)); assert(udp != NULL); #ifndef TEST /* { */ @@ -1399,8 +1377,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 +1387,44 @@ 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(("%s: Receive packet from unknown source", debug_prefix_time(NULL))); 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(("%s: getnameinfo failed: %s\n", + debug_prefix_time(NULL), 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 = SS_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, ("%s: bsd: closeX handle '%s'\n", + debug_prefix_time(NULL), rh->proto_handle)); amfree(rh); return; @@ -1456,25 +1451,27 @@ sec_tcp_conn_get( { struct tcp_conn *rc; - secprintf(("%s: sec_tcp_conn_get: %s\n", debug_prefix_time(NULL), hostname)); + auth_debug(1, ("%s: sec_tcp_conn_get: %s\n", + debug_prefix_time(NULL), 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, + ("%s: sec_tcp_conn_get: exists, refcnt to %s is now %d\n", + debug_prefix_time(NULL), + rc->hostname, rc->refcnt)); + return (rc); + } } - secprintf(("%s: sec_tcp_conn_get: creating new handle\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: sec_tcp_conn_get: creating new handle\n", + debug_prefix_time(NULL))); /* * We can't be creating a new handle if we are the client */ @@ -1494,6 +1491,7 @@ sec_tcp_conn_get( rc->accept_fn = NULL; rc->recv_security_ok = NULL; rc->prefix_packet = NULL; + rc->auth = 0; connq_append(rc); return (rc); } @@ -1510,14 +1508,14 @@ 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), + auth_debug(1, ("%s: sec_tcp_conn_put: decrementing refcnt for %s to %d\n", + debug_prefix_time(NULL), 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, ("%s: sec_tcp_conn_put: closing connection to %s\n", + debug_prefix_time(NULL), rc->hostname)); if (rc->read != -1) aclose(rc->read); if (rc->write != -1) @@ -1549,13 +1547,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", + auth_debug(1, + ("%s: sec: conn_read: incremented ev_read_refcnt to %d for %s\n", debug_prefix_time(NULL), 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, ("%s: sec: conn_read registering event handler for %s\n", + debug_prefix_time(NULL), 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 +1565,16 @@ sec_tcp_conn_read_cancel( { --rc->ev_read_refcnt; - secprintf(( - "%s: sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n", + auth_debug(1, + ("%s: sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n", debug_prefix_time(NULL), 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, + ("%s: sec: conn_read_cancel: releasing event handler for %s\n", + debug_prefix_time(NULL), rc->hostname)); event_release(rc->ev_read); rc->ev_read = NULL; } @@ -1595,8 +1594,8 @@ recvpkt_callback( assert(rh != NULL); - secprintf(("%s: sec: recvpkt_callback: %d\n", - debug_prefix_time(NULL), bufsize)); + auth_debug(1, ("%s: sec: recvpkt_callback: " SSIZE_T_FMT "\n", + debug_prefix_time(NULL), bufsize)); /* * We need to cancel the recvpkt request before calling * the callback because the callback may reschedule us. @@ -1618,8 +1617,8 @@ recvpkt_callback( } parse_pkt(&pkt, buf, (size_t)bufsize); - secprintf(( - "%s: sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n", + auth_debug(1, + ("%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)); if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0) @@ -1639,8 +1638,8 @@ 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, ("%s: sec: stream_read_callback_sync: handle %d\n", + debug_prefix_time(NULL), rs->handle)); /* * Make sure this was for us. If it was, then blow away the handle @@ -1649,12 +1648,12 @@ 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, ("%s: sec: stream_read_callback_sync: it was for us\n", + debug_prefix_time(NULL))); 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, ("%s: sec: stream_read_callback_sync: not for us\n", + debug_prefix_time(NULL))); return; } @@ -1666,16 +1665,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, ("%s: sec: stream_read_sync_callback: %s\n", + debug_prefix_time(NULL), 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", + auth_debug(1, + ("%s: sec: stream_read_callback_sync: read " SSIZE_T_FMT " bytes from %s:%d\n", debug_prefix_time(NULL), rs->rc->pktlen, rs->rc->hostname, rs->handle)); } @@ -1690,8 +1689,8 @@ 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, ("%s: sec: stream_read_callback: handle %d\n", + debug_prefix_time(NULL), rs->handle)); /* * Make sure this was for us. If it was, then blow away the handle @@ -1700,12 +1699,12 @@ 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, ("%s: sec: stream_read_callback: it was for us\n", + debug_prefix_time(NULL))); 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, ("%s: sec: stream_read_callback: not for us\n", + debug_prefix_time(NULL))); return; } @@ -1717,8 +1716,8 @@ 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, ("%s: sec: stream_read_callback: %s\n", + debug_prefix_time(NULL), 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 +1725,12 @@ 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), + auth_debug(1, ("%s: sec: stream_read_callback: read " SSIZE_T_FMT " bytes from %s:%d\n", + debug_prefix_time(NULL), 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, ("%s: sec: after callback stream_read_callback\n", + debug_prefix_time(NULL))); } /* @@ -1751,19 +1750,19 @@ sec_tcp_conn_read_callback( assert(cookie != NULL); - secprintf(("%s: sec: conn_read_callback\n", debug_prefix_time(NULL))); + auth_debug(1, ("%s: sec: conn_read_callback\n", debug_prefix_time(NULL))); /* 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, ("%s: sec: conn_read_callback: tcpm_recv_token returned " SSIZE_T_FMT "\n", + debug_prefix_time(NULL), 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, ("%s: sec: conn_read_callback: event_wakeup return %d\n", + debug_prefix_time(NULL), revent)); /* delete our 'accept' reference */ if (rc->accept_fn != NULL) { if(rc->refcnt != 1) { @@ -1780,16 +1779,17 @@ 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, + ("%s: 0 sec: conn_read_callback: event_wakeup return %d\n", + debug_prefix_time(NULL), 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, ("%s: sec: conn_read_callback: event_wakeup return " SSIZE_T_FMT "\n", + debug_prefix_time(NULL), rval)); rc->donotclose = 0; if (rc->handle == H_TAKEN || rc->pktlen == 0) { if(rc->refcnt == 0) amfree(rc); @@ -1810,10 +1810,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, ("%s: sec: new connection\n", debug_prefix_time(NULL))); 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, ("%s: sec: calling accept_fn\n", debug_prefix_time(NULL))); if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0) (*rc->accept_fn)(&rh->sech, NULL); else @@ -1829,8 +1829,8 @@ 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, ("%s: sec: parse_pkt: parsing buffer of " SSIZE_T_FMT " bytes\n", + debug_prefix_time(NULL), bufsize)); pkt->type = (pktype_t)*bufp++; bufsize--; @@ -1845,9 +1845,9 @@ 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, ("%s: sec: parse_pkt: %s (%d): \"%s\"\n", + debug_prefix_time(NULL), pkt_type2str(pkt->type), + pkt->type, pkt->body)); } /* @@ -1867,8 +1867,8 @@ pkthdr2str( 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, ("%s: bsd: pkthdr2str handle '%s'\n", + debug_prefix_time(NULL), rh->proto_handle)); /* check for truncation. If only we had asprintf()... */ assert(retbuf[strlen(retbuf) - 1] == '\n'); @@ -1971,7 +1971,7 @@ 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, @@ -2040,30 +2040,28 @@ check_user_ruserok( exit(1); } -#if defined(SHOW_SECURITY_DETAIL) /* { */ - { - char *dir = stralloc(pwd->pw_dir); + if (debug_auth >= 9) { + 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); + auth_debug(9, ("%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) { + auth_debug(9, ("%s: bsd: because you are running as root, ", + debug_prefix_time(NULL))); + 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, ("%s: Could not open /dev/null: %s\n", + debug_prefix_time(NULL), strerror(errno))); ec = 1; } else { ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN); @@ -2129,7 +2127,7 @@ check_user_ruserok( char * check_user_amandahosts( const char * host, - struct in_addr addr, + struct sockaddr_storage *addr, struct passwd * pwd, const char * remoteuser, const char * service) @@ -2147,15 +2145,20 @@ check_user_amandahosts( 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); amfree(ptmp); @@ -2195,9 +2198,8 @@ check_user_amandahosts( continue; } -#if defined(SHOW_SECURITY_DETAIL) /* { */ - secprintf(("%s: bsd: processing line: <%s>\n", debug_prefix(NULL), line)); -#endif /* } */ + auth_debug(9, ("%s: bsd: processing line: <%s>\n", + debug_prefix_time(NULL), line)); /* get the host out of the file */ if ((filehost = strtok(line, " \t")) == NULL) { amfree(line); @@ -2211,24 +2213,31 @@ 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 (addr->ss_family == (sa_family_t)AF_INET6) + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr, + ipstr, sizeof(ipstr)); + else +#endif + inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->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, ("%s: bsd: comparing \"%s\" with\n", + debug_prefix_time(NULL), filehost)); + auth_debug(9, ("%s: bsd: \"%s\" (%s)\n", host, + debug_prefix_time(NULL), hostmatch ? "match" : "no match")); + auth_debug(9, ("%s: bsd: and \"%s\" with\n", + fileuser, debug_prefix_time(NULL))); + auth_debug(9, ("%s: bsd: \"%s\" (%s)\n", remoteuser, + debug_prefix_time(NULL), usermatch ? "match" : "no match")); /* compare */ if (!hostmatch || !usermatch) { amfree(line); @@ -2289,14 +2298,14 @@ check_user_amandahosts( if (strcmp(service, "amindexd") == 0 || strcmp(service, "amidxtaped") == 0) { result = vstralloc("Please add \"amindexd amidxtaped\" to " - "the line in ", ptmp, NULL); + "the line in ", ptmp, " on the client", NULL); } 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); + ptmp, " on the client", NULL); } else { result = vstralloc(ptmp, ": ", "invalid service ", service, NULL); @@ -2314,105 +2323,54 @@ common_exit: /* return 1 on success, 0 on failure */ int check_security( - struct sockaddr_in *addr, + struct sockaddr_storage *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, + ("%s: check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n", + debug_prefix_time(NULL), 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", - "]", 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", + if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr), + hostname, NI_MAXHOST, NULL, 0, 0) != 0)) { + dbprintf(("%s: getnameinfo failed: %s\n", + debug_prefix_time(NULL), gai_strerror(result))); + *errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ", + "getnameinfo failed: ", gai_strerror(result), "]", 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) { + port = SS_GET_PORT(addr); + if (port >= IPPORT_RESERVED) { char number[NUM_STR_SIZE]; - snprintf(number, SIZEOF(number), "%u", - (unsigned int)ntohs(addr->sin_port)); + snprintf(number, SIZEOF(number), "%u", (unsigned int)port); *errstr = vstralloc("[", "host ", remotehost, ": ", "port ", number, " not secure", @@ -2431,16 +2389,12 @@ check_security( "bad bsd security line", "]", NULL); -#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') { @@ -2462,13 +2416,13 @@ check_security( if ((pwptr = getpwuid(myuid)) == NULL) error("error [getpwuid(%d) fails]", 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, ("%s: bsd security: remote host %s user %s local user %s\n", + debug_prefix_time(NULL), 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) { @@ -2505,8 +2459,8 @@ net_writev( if (n < 0) { if (errno != EINTR) return (-1); - secprintf(("%s: net_writev got EINTR\n", - debug_prefix(NULL))); + auth_debug(1, ("%s: net_writev got EINTR\n", + debug_prefix_time(NULL))); } else if (n == 0) { errno = EIO; @@ -2549,27 +2503,28 @@ net_read( ssize_t nread; size_t size = origsize; - secprintf(("%s: net_read: begin %d\n", debug_prefix_time(NULL), origsize)); + auth_debug(1, ("%s: net_read: begin " SIZE_T_FMT "\n", + debug_prefix_time(NULL), origsize)); while (size > 0) { - secprintf(("%s: net_read: while %d\n", - debug_prefix_time(NULL), size)); + auth_debug(1, ("%s: net_read: while " SIZE_T_FMT "\n", + debug_prefix_time(NULL), 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, ("%s: db: net_read: end return(-1)\n", + debug_prefix_time(NULL))); return (-1); } if (nread == 0) { - secprintf(("%s: net_read: end return(0)\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: net_read: end return(0)\n", + debug_prefix_time(NULL))); return (0); } buf += nread; size -= nread; } - secprintf(("%s: net_read: end %d\n", - debug_prefix_time(NULL), origsize)); + auth_debug(1, ("%s: net_read: end " SIZE_T_FMT "\n", + debug_prefix_time(NULL), origsize)); return ((ssize_t)origsize); } @@ -2583,11 +2538,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, ("%s: net_read_fillbuf: begin\n", debug_prefix_time(NULL))); FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = timeout; @@ -2597,25 +2552,25 @@ net_read_fillbuf( errno = ETIMEDOUT; /* FALLTHROUGH */ case -1: - secprintf(("%s: net_read_fillbuf: case -1\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: net_read_fillbuf: case -1\n", + debug_prefix_time(NULL))); return (-1); case 1: - secprintf(("%s: net_read_fillbuf: case 1\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: net_read_fillbuf: case 1\n", + debug_prefix_time(NULL))); assert(FD_ISSET(fd, &readfds)); break; default: - secprintf(("%s: net_read_fillbuf: case default\n", - debug_prefix_time(NULL))); + auth_debug(1, ("%s: net_read_fillbuf: case default\n", + debug_prefix_time(NULL))); 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, ("%s: net_read_fillbuf: end " SSIZE_T_FMT "\n", + debug_prefix_time(NULL), nread)); return (nread); } @@ -2637,8 +2592,8 @@ show_stat_info( char *group; if (stat(name, &sbuf) != 0) { - secprintf(("%s: bsd: cannot stat %s: %s\n", - debug_prefix_time(NULL), name, strerror(errno))); + auth_debug(1, ("%s: bsd: cannot stat %s: %s\n", + debug_prefix_time(NULL), name, strerror(errno))); amfree(name); return; } @@ -2654,10 +2609,133 @@ show_stat_info( } else { group = stralloc(grptr->gr_name); } - 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, ("%s: bsd: processing file: %s\n", debug_prefix_time(NULL), name)); + auth_debug(1, ("%s: bsd: owner=%s group=%s mode=%03o\n", + debug_prefix_time(NULL), owner, group, + (int) (sbuf.st_mode & 0777))); amfree(name); amfree(owner); amfree(group); } + +int +check_name_give_sockaddr( + const char *hostname, + struct sockaddr *addr, + char **errstr) +{ + struct addrinfo *res = NULL, *res1; + struct addrinfo hints; + int result; + +#ifdef WORKING_IPV6 + if ((addr)->sa_family == AF_INET6) + hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL; + else +#endif + hints.ai_flags = AI_CANONNAME; + hints.ai_family = addr->sa_family; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + result = getaddrinfo(hostname, NULL, &hints, &res); + if (result != 0) { + dbprintf(("check_name_give_sockaddr: getaddrinfo(%s): %s\n", hostname, gai_strerror(result))); + *errstr = newvstralloc(*errstr, + " getaddrinfo(", hostname, "): ", + gai_strerror(result), NULL); + return -1; + } + if (res->ai_canonname == NULL) { + dbprintf(("getaddrinfo(%s) did not return a canonical name\n", hostname)); + *errstr = newvstralloc(*errstr, + " getaddrinfo(", hostname, ") did not return a canonical name", NULL); + return -1; + } + + if (strncasecmp(hostname, res->ai_canonname, strlen(hostname)) != 0) { + auth_debug(1, ("%s: %s doesn't resolve to itself, it resolves to %s\n", + debug_prefix_time(NULL), + hostname, res->ai_canonname)); + *errstr = newvstralloc(*errstr, hostname, + _(" doesn't resolve to itself, it resolves to "), + res->ai_canonname, NULL); + return -1; + } + + for(res1=res; res1 != NULL; res1 = res1->ai_next) { + if (res1->ai_addr->sa_family == addr->sa_family) { + if (cmp_sockaddr((struct sockaddr_storage *)res1->ai_addr, (struct sockaddr_storage *)addr, 1) == 0) { + freeaddrinfo(res); + return 0; + } + } + } + + *errstr = newvstralloc(*errstr, + str_sockaddr((struct sockaddr_storage *)addr), + " doesn't resolve to ", + hostname, NULL); + freeaddrinfo(res); + return -1; +} + + +int +check_addrinfo_give_name( + struct addrinfo *res, + const char *hostname, + char **errstr) +{ + if (strncasecmp(hostname, res->ai_canonname, strlen(hostname)) != 0) { + dbprintf(("%s: %s doesn't resolve to itself, it resolv to %s\n", + debug_prefix_time(NULL), + hostname, res->ai_canonname)); + *errstr = newvstralloc(*errstr, hostname, + " doesn't resolve to itself, it resolv to ", + res->ai_canonname, NULL); + return -1; + } + + return 0; +} + +/* Try resolving the hostname, just to catch any potential + * problems down the road. This is used from most security_connect + * methods, many of which also want the canonical name. Returns + * 0 on success. + */ +int +try_resolving_hostname( + const char *hostname, + char **canonname) +{ + struct addrinfo hints; + struct addrinfo *gaires; + int res; + +#ifdef WORKING_IPV6 + hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL; + hints.ai_family = AF_UNSPEC; +#else + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_INET; +#endif + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + if ((res = getaddrinfo(hostname, NULL, &hints, &gaires)) != 0) { + return -1; + } + if (canonname && gaires && gaires->ai_canonname) + *canonname = stralloc(gaires->ai_canonname); + if (gaires) freeaddrinfo(gaires); + + return 0; +}