X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fbsdtcp-security.c;h=25a32ac5c1165644b7004276017df2abbd3fb43a;hb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;hp=9ddf90cf602089ebfd9664b0062cfd34c61dcdac;hpb=12179dea039515c06168c0037d048566a3f623de;p=debian%2Famanda diff --git a/common-src/bsdtcp-security.c b/common-src/bsdtcp-security.c index 9ddf90c..25a32ac 100644 --- a/common-src/bsdtcp-security.c +++ b/common-src/bsdtcp-security.c @@ -37,22 +37,10 @@ #include "util.h" #include "event.h" #include "packet.h" -#include "queue.h" #include "security.h" #include "security-util.h" +#include "sockaddr-util.h" #include "stream.h" -#include "version.h" - -#ifdef BSDTCP_SECURITY - -/*#define BSDTCP_DEBUG*/ - -#ifdef BSDTCP_DEBUG -#define bsdtcpprintf(x) dbprintf(x) -#else -#define bsdtcpprintf(x) -#endif - /* * Number of seconds bsdtcp has to start up @@ -62,8 +50,11 @@ /* * Interface functions */ -static void bsdtcp_accept(const struct security_driver *, int, int, - void (*)(security_handle_t *, pkt_t *)); +static void bsdtcp_accept(const struct security_driver *, + char *(*)(char *, void *), + int, int, + void (*)(security_handle_t *, pkt_t *), + void *); static void bsdtcp_connect(const char *, char *(*)(char *, void *), void (*)(void *, security_handle_t *, security_status_t), void *, void *); @@ -75,6 +66,7 @@ const security_driver_t bsdtcp_security_driver = { "BSDTCP", bsdtcp_connect, bsdtcp_accept, + sec_get_authenticated_peer_name_hostname, sec_close, stream_sendpkt, stream_recvpkt, @@ -90,6 +82,8 @@ const security_driver_t bsdtcp_security_driver = { tcpm_stream_read_sync, tcpm_stream_read_cancel, tcpm_close_connection, + NULL, + NULL }; static int newhandle = 1; @@ -97,7 +91,7 @@ static int newhandle = 1; /* * Local functions */ -static int runbsdtcp(struct sec_handle *); +static int runbsdtcp(struct sec_handle *, in_port_t port); /* @@ -113,30 +107,43 @@ bsdtcp_connect( void * datap) { struct sec_handle *rh; - struct hostent *he; + int result; + char *canonname; + char *service; + in_port_t port; assert(fn != NULL); assert(hostname != NULL); (void)conf_fn; /* Quiet unused parameter warning */ (void)datap; /* Quiet unused parameter warning */ - bsdtcpprintf(("%s: bsdtcp: bsdtcp_connect: %s\n", debug_prefix_time(NULL), - hostname)); + auth_debug(1, _("bsdtcp: bsdtcp_connect: %s\n"), hostname); - rh = alloc(sizeof(*rh)); + rh = g_new0(struct sec_handle, 1); security_handleinit(&rh->sech, &bsdtcp_security_driver); rh->hostname = NULL; rh->rs = NULL; rh->ev_timeout = NULL; rh->rc = NULL; - if ((he = gethostbyname(hostname)) == NULL) { - security_seterror(&rh->sech, - "%s: could not resolve hostname", hostname); + result = resolve_hostname(hostname, 0, NULL, &canonname); + if(result != 0) { + dbprintf(_("resolve_hostname(%s): %s\n"), hostname, gai_strerror(result)); + security_seterror(&rh->sech, _("resolve_hostname(%s): %s\n"), hostname, + gai_strerror(result)); (*fn)(arg, &rh->sech, S_ERROR); return; } - rh->hostname = stralloc(he->h_name); /* will be replaced */ + if (canonname == NULL) { + dbprintf(_("resolve_hostname(%s) did not return a canonical name\n"), hostname); + security_seterror(&rh->sech, + _("resolve_hostname(%s) did not return a canonical name\n"), hostname); + (*fn)(arg, &rh->sech, S_ERROR); + return; + } + + rh->hostname = canonname; /* will be replaced */ + canonname = NULL; /* steal reference */ rh->rs = tcpma_stream_client(rh, newhandle++); rh->rc->recv_security_ok = &bsd_recv_security_ok; rh->rc->prefix_packet = &bsd_prefix_packet; @@ -147,13 +154,26 @@ bsdtcp_connect( amfree(rh->hostname); rh->hostname = stralloc(rh->rs->rc->hostname); + if (conf_fn) { + service = conf_fn("client_port", datap); + if (!service || strlen(service) <= 1) + service = "amanda"; + } else { + service = "amanda"; + } + port = find_port_for_service(service, "tcp"); + if (port == 0) { + security_seterror(&rh->sech, _("%s/tcp unknown protocol"), service); + goto error; + } + /* * We need to open a new connection. * * XXX need to eventually limit number of outgoing connections here. */ if(rh->rc->read == -1) { - if (runbsdtcp(rh) < 0) + if (runbsdtcp(rh, port) < 0) goto error; rh->rc->refcnt++; } @@ -185,31 +205,46 @@ error: static void bsdtcp_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) { - struct sockaddr_in sin; - socklen_t len; + sockaddr_union sin; + socklen_t_equiv len; struct tcp_conn *rc; - struct hostent *he; + char hostname[NI_MAXHOST]; + int result; + char *errmsg = NULL; len = sizeof(sin); - if (getpeername(in, (struct sockaddr *)&sin, &len) < 0) + if (getpeername(in, (struct sockaddr *)&sin, &len) < 0) { + dbprintf(_("getpeername returned: %s\n"), strerror(errno)); + return; + } + if ((result = getnameinfo((struct sockaddr *)&sin, len, + hostname, NI_MAXHOST, NULL, 0, 0) != 0)) { + dbprintf(_("getnameinfo failed: %s\n"), + gai_strerror(result)); return; - he = gethostbyaddr((void *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET); - if (he == NULL) + } + if (check_name_give_sockaddr(hostname, + (struct sockaddr *)&sin, &errmsg) < 0) { + amfree(errmsg); return; + } - rc = sec_tcp_conn_get(he->h_name, 0); + rc = sec_tcp_conn_get(hostname, 0); rc->recv_security_ok = &bsd_recv_security_ok; rc->prefix_packet = &bsd_prefix_packet; - memcpy(&rc->peer.sin_addr, he->h_addr, sizeof(rc->peer.sin_addr)); - rc->peer.sin_port = sin.sin_port; + copy_sockaddr(&rc->peer, &sin); rc->read = in; rc->write = out; rc->accept_fn = fn; rc->driver = driver; + rc->conf_fn = conf_fn; + rc->datap = datap; sec_tcp_conn_read(rc); } @@ -219,27 +254,22 @@ bsdtcp_accept( */ static int runbsdtcp( - struct sec_handle * rh) + struct sec_handle * rh, + in_port_t port) { - struct servent * sp; int server_socket; in_port_t my_port; - uid_t euid; struct tcp_conn * rc = rh->rc; - if ((sp = getservbyname("amanda", "tcp")) == NULL) { - error("%s/tcp unknown protocol", "amanda"); - } - - euid = geteuid(); - seteuid(0); + set_root_privs(1); server_socket = stream_client_privileged(rc->hostname, - (in_port_t)(ntohs((in_port_t)sp->s_port)), + port, STREAM_BUFSIZE, STREAM_BUFSIZE, &my_port, 0); + set_root_privs(0); if(server_socket < 0) { security_seterror(&rh->sech, @@ -247,15 +277,12 @@ runbsdtcp( return -1; } - seteuid(euid); if(my_port >= IPPORT_RESERVED) { security_seterror(&rh->sech, - "did not get a reserved port: %d", my_port); + _("did not get a reserved port: %d"), my_port); } rc->read = rc->write = server_socket; return 0; } - -#endif /* BSDTCP_SECURITY */