X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fbsd-security.c;h=8953f1f9308e72bf3a951bda549a45258cef2f46;hb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;hp=18102ba63b47d3dc163d966595a28f95e1205440;hpb=d3b2175e084f88c8736ad7073eacbf4670147aec;p=debian%2Famanda diff --git a/common-src/bsd-security.c b/common-src/bsd-security.c index 18102ba..8953f1f 100644 --- a/common-src/bsd-security.c +++ b/common-src/bsd-security.c @@ -44,22 +44,17 @@ #undef DUMPER_SOCKET_BUFFERING #endif -#ifdef BSD_SECURITY /* { */ - -/* - * Change the following from #undef to #define to cause detailed logging - * of the security steps, e.g. into /tmp/amanda/amandad*debug. - */ -#undef SHOW_SECURITY_DETAIL - /* * Interface functions */ static void bsd_connect(const char *, char *(*)(char *, void *), void (*)(void *, security_handle_t *, security_status_t), void *, void *); -static void bsd_accept(const struct security_driver *, int, int, - void (*)(security_handle_t *, pkt_t *)); +static void bsd_accept(const struct security_driver *, + char *(*)(char *, void *), + int, int, + void (*)(security_handle_t *, pkt_t *), + void *); static void bsd_close(void *); static void * bsd_stream_server(void *); static int bsd_stream_accept(void *); @@ -131,12 +126,12 @@ bsd_connect( struct servent *se; in_port_t port = 0; struct timeval sequence_time; - amanda_timezone dontcare; int sequence; char *handle; int result; - struct addrinfo hints; - struct addrinfo *res = NULL; + struct addrinfo *res, *res_addr; + char *canonname; + int result_bind; assert(hostname != NULL); @@ -147,117 +142,142 @@ bsd_connect( bh->proto_handle=NULL; security_handleinit(&bh->sech, &bsd_security_driver); - /* - * Only init the socket once - */ -#ifdef WORKING_IPV6 - hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL; - hints.ai_family = AF_INET6; -#else - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET; -#endif - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - result = getaddrinfo(hostname, NULL, &hints, &res); -#ifdef WORKING_IPV6 - if (result != 0) { - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; - result = getaddrinfo(hostname, NULL, &hints, &res); - } -#endif + result = resolve_hostname(hostname, SOCK_DGRAM, &res, &canonname); if(result != 0) { - dbprintf(("getaddrinfo(%s): %s\n", hostname, gai_strerror(result))); - security_seterror(&bh->sech, "getaddrinfo(%s): %s\n", hostname, + dbprintf(_("resolve_hostname(%s): %s\n"), hostname, gai_strerror(result)); + security_seterror(&bh->sech, _("resolve_hostname(%s): %s\n"), hostname, gai_strerror(result)); (*fn)(arg, &bh->sech, S_ERROR); return; } - if (res->ai_canonname == NULL) { - dbprintf(("getaddrinfo(%s) did not return a canonical name\n", hostname)); + if (canonname == NULL) { + dbprintf(_("resolve_hostname(%s) did not return a canonical name\n"), hostname); security_seterror(&bh->sech, - _("getaddrinfo(%s) did not return a canonical name\n"), hostname); + _("resolve_hostname(%s) did not return a canonical name\n"), hostname); (*fn)(arg, &bh->sech, S_ERROR); return; } + if (res == NULL) { + dbprintf(_("resolve_hostname(%s): no results\n"), hostname); + security_seterror(&bh->sech, + _("resolve_hostname(%s): no results\n"), hostname); + (*fn)(arg, &bh->sech, S_ERROR); + amfree(canonname); + return; + } + for (res_addr = res; res_addr != NULL; res_addr = res_addr->ai_next) { #ifdef WORKING_IPV6 - if (res->ai_addr->sa_family == AF_INET6 && not_init6 == 1) { - uid_t euid; - dgram_zero(&netfd6.dgram); - - euid = geteuid(); - seteuid((uid_t)0); - dgram_bind(&netfd6.dgram, res->ai_addr->sa_family, &port); - seteuid(euid); - netfd6.handle = NULL; - netfd6.pkt.body = NULL; - netfd6.recv_security_ok = &bsd_recv_security_ok; - netfd6.prefix_packet = &bsd_prefix_packet; + /* IPv6 socket already bound */ + if (res_addr->ai_addr->sa_family == AF_INET6 && not_init6 == 0) { + break; + } /* - * We must have a reserved port. Bomb if we didn't get one. + * Only init the IPv6 socket once */ - if (port >= IPPORT_RESERVED) { - security_seterror(&bh->sech, - "unable to bind to a reserved port (got port %u)", - (unsigned int)port); - (*fn)(arg, &bh->sech, S_ERROR); - return; + if (res_addr->ai_addr->sa_family == AF_INET6 && not_init6 == 1) { + uid_t euid; + dgram_zero(&netfd6.dgram); + + euid = geteuid(); + set_root_privs(1); + result_bind = dgram_bind(&netfd6.dgram, + res_addr->ai_addr->sa_family, &port); + set_root_privs(0); + if (result_bind != 0) { + continue; + } + netfd6.handle = NULL; + netfd6.pkt.body = NULL; + netfd6.recv_security_ok = &bsd_recv_security_ok; + netfd6.prefix_packet = &bsd_prefix_packet; + /* + * We must have a reserved port. Bomb if we didn't get one. + */ + if (port >= IPPORT_RESERVED) { + security_seterror(&bh->sech, + _("unable to bind to a reserved port (got port %u)"), + (unsigned int)port); + (*fn)(arg, &bh->sech, S_ERROR); + freeaddrinfo(res); + amfree(canonname); + return; + } + not_init6 = 0; + bh->udp = &netfd6; + break; } - not_init6 = 0; - bh->udp = &netfd6; - } #endif - if (res->ai_addr->sa_family == AF_INET && not_init4 == 1) { - uid_t euid; - dgram_zero(&netfd4.dgram); - - euid = geteuid(); - seteuid((uid_t)0); - dgram_bind(&netfd4.dgram, res->ai_addr->sa_family, &port); - seteuid(euid); - netfd4.handle = NULL; - netfd4.pkt.body = NULL; - netfd4.recv_security_ok = &bsd_recv_security_ok; - netfd4.prefix_packet = &bsd_prefix_packet; + /* IPv4 socket already bound */ + if (res_addr->ai_addr->sa_family == AF_INET && not_init4 == 0) { + break; + } + /* - * We must have a reserved port. Bomb if we didn't get one. + * Only init the IPv4 socket once */ - if (port >= IPPORT_RESERVED) { - security_seterror(&bh->sech, - "unable to bind to a reserved port (got port %u)", - (unsigned int)port); - (*fn)(arg, &bh->sech, S_ERROR); - return; + if (res_addr->ai_addr->sa_family == AF_INET && not_init4 == 1) { + uid_t euid; + dgram_zero(&netfd4.dgram); + + euid = geteuid(); + set_root_privs(1); + result_bind = dgram_bind(&netfd4.dgram, + res_addr->ai_addr->sa_family, &port); + set_root_privs(0); + if (result_bind != 0) { + continue; + } + netfd4.handle = NULL; + netfd4.pkt.body = NULL; + netfd4.recv_security_ok = &bsd_recv_security_ok; + netfd4.prefix_packet = &bsd_prefix_packet; + /* + * We must have a reserved port. Bomb if we didn't get one. + */ + if (port >= IPPORT_RESERVED) { + security_seterror(&bh->sech, + "unable to bind to a reserved port (got port %u)", + (unsigned int)port); + (*fn)(arg, &bh->sech, S_ERROR); + freeaddrinfo(res); + amfree(canonname); + return; + } + not_init4 = 0; + bh->udp = &netfd4; + break; } - not_init4 = 0; - bh->udp = &netfd4; + } + + if (res_addr == NULL) { + dbprintf(_("Can't bind a socket to connect to %s\n"), hostname); + security_seterror(&bh->sech, + _("Can't bind a socket to connect to %s\n"), hostname); + (*fn)(arg, &bh->sech, S_ERROR); + amfree(canonname); + return; } #ifdef WORKING_IPV6 - if (res->ai_addr->sa_family == AF_INET6) + if (res_addr->ai_addr->sa_family == AF_INET6) bh->udp = &netfd6; else #endif bh->udp = &netfd4; - auth_debug(1, ("Resolved hostname=%s\n", res->ai_canonname)); + auth_debug(1, _("Resolved hostname=%s\n"), canonname); if ((se = getservbyname(AMANDA_SERVICE_NAME, "udp")) == NULL) port = AMANDA_SERVICE_DEFAULT; else port = (in_port_t)ntohs(se->s_port); - amanda_gettimeofday(&sequence_time, &dontcare); + amanda_gettimeofday(&sequence_time); sequence = (int)sequence_time.tv_sec ^ (int)sequence_time.tv_usec; handle=alloc(15); - snprintf(handle, 14, "000-%08x", (unsigned)newhandle++); - if (udp_inithandle(bh->udp, bh, res->ai_canonname, - (struct sockaddr_storage *)res->ai_addr, port, handle, sequence) < 0) { + g_snprintf(handle, 14, "000-%08x", (unsigned)newhandle++); + if (udp_inithandle(bh->udp, bh, canonname, + (struct sockaddr_storage *)res_addr->ai_addr, port, handle, sequence) < 0) { (*fn)(arg, &bh->sech, S_ERROR); amfree(bh->hostname); amfree(bh); @@ -266,6 +286,7 @@ bsd_connect( (*fn)(arg, &bh->sech, S_OK); } amfree(handle); + amfree(canonname); freeaddrinfo(res); } @@ -276,9 +297,11 @@ bsd_connect( static void bsd_accept( const struct security_driver * 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) { assert(in >= 0 && out >= 0); @@ -286,6 +309,8 @@ bsd_accept( (void)out; /* Quiet unused parameter warning */ (void)driver; /* Quiet unused parameter warning */ + (void)conf_fn; + (void)datap; /* * We assume in and out point to the same socket, and just use @@ -320,8 +345,7 @@ bsd_close( return; } - auth_debug(1, ("%s: bsd: close handle '%s'\n", - debug_prefix_time(NULL), bh->proto_handle)); + auth_debug(1, _("bsd: close handle '%s'\n"), bh->proto_handle); udp_recvpkt_cancel(bh); if(bh->next) { @@ -363,11 +387,12 @@ bsd_stream_server( bs = alloc(SIZEOF(*bs)); security_streaminit(&bs->secstr, &bsd_security_driver); - bs->socket = stream_server(&bs->port, (size_t)STREAM_BUFSIZE, - (size_t)STREAM_BUFSIZE, 0); + bs->socket = stream_server(bh->udp->peer.ss_family, &bs->port, + (size_t)STREAM_BUFSIZE, (size_t)STREAM_BUFSIZE, + 0); if (bs->socket < 0) { security_seterror(&bh->sech, - "can't create server stream: %s", strerror(errno)); + _("can't create server stream: %s"), strerror(errno)); amfree(bs); return (NULL); } @@ -393,7 +418,7 @@ bsd_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", strerror(errno)); + _("can't accept new stream connection: %s"), strerror(errno)); return (-1); } return (0); @@ -421,7 +446,7 @@ bsd_stream_client( STREAM_BUFSIZE, STREAM_BUFSIZE, &bs->port, 0); if (bs->fd < 0) { security_seterror(&bh->sech, - "can't connect stream to %s port %d: %s", bh->hostname, + _("can't connect stream to %s port %d: %s"), bh->hostname, id, strerror(errno)); amfree(bs); return (NULL); @@ -540,8 +565,7 @@ stream_read_sync_callback( assert(bs != NULL); - auth_debug(1, ("%s: bsd: stream_read_callback_sync: fd %d\n", - debug_prefix_time(NULL), bs->fd)); + auth_debug(1, _("bsd: stream_read_callback_sync: fd %d\n"), bs->fd); /* * Remove the event first, in case they reschedule it in the callback. @@ -597,5 +621,3 @@ stream_read_callback( (*bs->fn)(bs->arg, bs->databuf, n); } - -#endif /* BSD_SECURITY */ /* } */