mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-09-26 11:29:04 +02:00
upstream: Add BindInterface ssh_config directive and -B
command-line argument to ssh(1) that directs it to bind its outgoing connection to the address of the specified network interface. BindInterface prefers to use addresses that aren't loopback or link- local, but will fall back to those if no other addresses of the required family are available on that interface. Based on patch by Mike Manning in bz#2820, ok dtucker@ OpenBSD-Commit-ID: c5064d285c2851f773dd736a2c342aa384fbf713
This commit is contained in:
parent
fcdb9d7778
commit
ac2e3026bb
11
readconf.c
11
readconf.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.c,v 1.281 2017/12/05 23:59:47 dtucker Exp $ */
|
/* $OpenBSD: readconf.c,v 1.282 2018/02/23 02:34:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -156,7 +156,7 @@ typedef enum {
|
|||||||
oPubkeyAuthentication,
|
oPubkeyAuthentication,
|
||||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||||
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
||||||
oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
|
oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
|
||||||
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
|
||||||
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
||||||
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
||||||
@ -266,6 +266,7 @@ static struct {
|
|||||||
{ "preferredauthentications", oPreferredAuthentications },
|
{ "preferredauthentications", oPreferredAuthentications },
|
||||||
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
||||||
{ "bindaddress", oBindAddress },
|
{ "bindaddress", oBindAddress },
|
||||||
|
{ "bindinterface", oBindInterface },
|
||||||
{ "clearallforwardings", oClearAllForwardings },
|
{ "clearallforwardings", oClearAllForwardings },
|
||||||
{ "enablesshkeysign", oEnableSSHKeysign },
|
{ "enablesshkeysign", oEnableSSHKeysign },
|
||||||
{ "verifyhostkeydns", oVerifyHostKeyDNS },
|
{ "verifyhostkeydns", oVerifyHostKeyDNS },
|
||||||
@ -1099,6 +1100,10 @@ parse_char_array:
|
|||||||
charptr = &options->bind_address;
|
charptr = &options->bind_address;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
|
|
||||||
|
case oBindInterface:
|
||||||
|
charptr = &options->bind_interface;
|
||||||
|
goto parse_string;
|
||||||
|
|
||||||
case oPKCS11Provider:
|
case oPKCS11Provider:
|
||||||
charptr = &options->pkcs11_provider;
|
charptr = &options->pkcs11_provider;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
@ -1800,6 +1805,7 @@ initialize_options(Options * options)
|
|||||||
options->log_level = SYSLOG_LEVEL_NOT_SET;
|
options->log_level = SYSLOG_LEVEL_NOT_SET;
|
||||||
options->preferred_authentications = NULL;
|
options->preferred_authentications = NULL;
|
||||||
options->bind_address = NULL;
|
options->bind_address = NULL;
|
||||||
|
options->bind_interface = NULL;
|
||||||
options->pkcs11_provider = NULL;
|
options->pkcs11_provider = NULL;
|
||||||
options->enable_ssh_keysign = - 1;
|
options->enable_ssh_keysign = - 1;
|
||||||
options->no_host_authentication_for_localhost = - 1;
|
options->no_host_authentication_for_localhost = - 1;
|
||||||
@ -2509,6 +2515,7 @@ dump_client_config(Options *o, const char *host)
|
|||||||
|
|
||||||
/* String options */
|
/* String options */
|
||||||
dump_cfg_string(oBindAddress, o->bind_address);
|
dump_cfg_string(oBindAddress, o->bind_address);
|
||||||
|
dump_cfg_string(oBindInterface, o->bind_interface);
|
||||||
dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
|
dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
|
||||||
dump_cfg_string(oControlPath, o->control_path);
|
dump_cfg_string(oControlPath, o->control_path);
|
||||||
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
|
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.h,v 1.124 2017/10/21 23:06:24 millert Exp $ */
|
/* $OpenBSD: readconf.h,v 1.125 2018/02/23 02:34:33 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -81,6 +81,7 @@ typedef struct {
|
|||||||
char *user_hostfiles[SSH_MAX_HOSTS_FILES];
|
char *user_hostfiles[SSH_MAX_HOSTS_FILES];
|
||||||
char *preferred_authentications;
|
char *preferred_authentications;
|
||||||
char *bind_address; /* local socket address for connection to sshd */
|
char *bind_address; /* local socket address for connection to sshd */
|
||||||
|
char *bind_interface; /* local interface for bind address */
|
||||||
char *pkcs11_provider; /* PKCS#11 provider */
|
char *pkcs11_provider; /* PKCS#11 provider */
|
||||||
int verify_host_key_dns; /* Verify host key using DNS */
|
int verify_host_key_dns; /* Verify host key using DNS */
|
||||||
|
|
||||||
|
11
ssh.1
11
ssh.1
@ -33,8 +33,8 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh.1,v 1.389 2017/11/03 02:29:17 djm Exp $
|
.\" $OpenBSD: ssh.1,v 1.390 2018/02/23 02:34:33 djm Exp $
|
||||||
.Dd $Mdocdate: November 3 2017 $
|
.Dd $Mdocdate: February 23 2018 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -43,6 +43,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ssh
|
.Nm ssh
|
||||||
.Op Fl 46AaCfGgKkMNnqsTtVvXxYy
|
.Op Fl 46AaCfGgKkMNnqsTtVvXxYy
|
||||||
|
.Op Fl B Ar bind_interface
|
||||||
.Op Fl b Ar bind_address
|
.Op Fl b Ar bind_address
|
||||||
.Op Fl c Ar cipher_spec
|
.Op Fl c Ar cipher_spec
|
||||||
.Op Fl D Oo Ar bind_address : Oc Ns Ar port
|
.Op Fl D Oo Ar bind_address : Oc Ns Ar port
|
||||||
@ -124,6 +125,12 @@ authenticate using the identities loaded into the agent.
|
|||||||
.It Fl a
|
.It Fl a
|
||||||
Disables forwarding of the authentication agent connection.
|
Disables forwarding of the authentication agent connection.
|
||||||
.Pp
|
.Pp
|
||||||
|
.It Fl B Ar interface
|
||||||
|
Bind to the address of
|
||||||
|
.Ar interface
|
||||||
|
before attempting to connect to the destination host.
|
||||||
|
This is only useful on systems with more than one address.
|
||||||
|
.Pp
|
||||||
.It Fl b Ar bind_address
|
.It Fl b Ar bind_address
|
||||||
Use
|
Use
|
||||||
.Ar bind_address
|
.Ar bind_address
|
||||||
|
21
ssh.c
21
ssh.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh.c,v 1.473 2018/02/13 03:36:56 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.474 2018/02/23 02:34:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -201,13 +201,13 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n"
|
"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]\n"
|
||||||
" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n"
|
" [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]\n"
|
||||||
" [-F configfile] [-I pkcs11] [-i identity_file]\n"
|
" [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]\n"
|
||||||
" [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]\n"
|
" [-i identity_file] [-J [user@]host[:port]] [-L address]\n"
|
||||||
" [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]\n"
|
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
|
||||||
" [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n"
|
" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n"
|
||||||
" destination [command]\n"
|
" [-w local_tun[:remote_tun]] destination [command]\n"
|
||||||
);
|
);
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
@ -663,7 +663,7 @@ main(int ac, char **av)
|
|||||||
|
|
||||||
again:
|
again:
|
||||||
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
|
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
|
||||||
"ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
|
"AB:CD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '1':
|
case '1':
|
||||||
fatal("SSH protocol v.1 is no longer supported");
|
fatal("SSH protocol v.1 is no longer supported");
|
||||||
@ -973,6 +973,9 @@ main(int ac, char **av)
|
|||||||
case 'b':
|
case 'b':
|
||||||
options.bind_address = optarg;
|
options.bind_address = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'B':
|
||||||
|
options.bind_interface = optarg;
|
||||||
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
config = optarg;
|
config = optarg;
|
||||||
break;
|
break;
|
||||||
|
11
ssh_config.5
11
ssh_config.5
@ -33,8 +33,8 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.266 2018/02/16 02:40:45 djm Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.267 2018/02/23 02:34:33 djm Exp $
|
||||||
.Dd $Mdocdate: February 16 2018 $
|
.Dd $Mdocdate: February 23 2018 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -254,6 +254,13 @@ The argument must be
|
|||||||
or
|
or
|
||||||
.Cm no
|
.Cm no
|
||||||
(the default).
|
(the default).
|
||||||
|
.It Cm BindInterface
|
||||||
|
Use the address of the specified interface on the local machine as the
|
||||||
|
source address of the connection.
|
||||||
|
Note that this option does not work if
|
||||||
|
.Cm UsePrivilegedPort
|
||||||
|
is set to
|
||||||
|
.Cm yes .
|
||||||
.It Cm BindAddress
|
.It Cm BindAddress
|
||||||
Use the specified address on the local machine as the source address of
|
Use the specified address on the local machine as the source address of
|
||||||
the connection.
|
the connection.
|
||||||
|
140
sshconnect.c
140
sshconnect.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshconnect.c,v 1.294 2018/02/10 09:25:35 djm Exp $ */
|
/* $OpenBSD: sshconnect.c,v 1.295 2018/02/23 02:34:33 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -23,6 +23,7 @@
|
|||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
@ -270,14 +272,79 @@ ssh_kill_proxy_command(void)
|
|||||||
kill(proxy_command_pid, SIGHUP);
|
kill(proxy_command_pid, SIGHUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search a interface address list (returned from getifaddrs(3)) for an
|
||||||
|
* address that matches the desired address family on the specifed interface.
|
||||||
|
* Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
|
||||||
|
struct sockaddr_storage *resultp, socklen_t *rlenp)
|
||||||
|
{
|
||||||
|
struct sockaddr_in6 *sa6;
|
||||||
|
struct sockaddr_in *sa;
|
||||||
|
struct in6_addr *v6addr;
|
||||||
|
const struct ifaddrs *ifa;
|
||||||
|
int allow_local;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prefer addresses that are not loopback or linklocal, but use them
|
||||||
|
* if nothing else matches.
|
||||||
|
*/
|
||||||
|
for (allow_local = 0; allow_local < 2; allow_local++) {
|
||||||
|
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
|
||||||
|
if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
|
||||||
|
(ifa->ifa_flags & IFF_UP) == 0 ||
|
||||||
|
ifa->ifa_addr->sa_family != af ||
|
||||||
|
strcmp(ifa->ifa_name, options.bind_interface) != 0)
|
||||||
|
continue;
|
||||||
|
switch (ifa->ifa_addr->sa_family) {
|
||||||
|
case AF_INET:
|
||||||
|
sa = (struct sockaddr_in *)ifa->ifa_addr;
|
||||||
|
if (!allow_local && sa->sin_addr.s_addr ==
|
||||||
|
htonl(INADDR_LOOPBACK))
|
||||||
|
continue;
|
||||||
|
if (*rlenp < sizeof(struct sockaddr_in)) {
|
||||||
|
error("%s: v4 addr doesn't fit",
|
||||||
|
__func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*rlenp = sizeof(struct sockaddr_in);
|
||||||
|
memcpy(resultp, sa, *rlenp);
|
||||||
|
return 0;
|
||||||
|
case AF_INET6:
|
||||||
|
sa6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||||
|
v6addr = &sa6->sin6_addr;
|
||||||
|
if (!allow_local &&
|
||||||
|
(IN6_IS_ADDR_LINKLOCAL(v6addr) ||
|
||||||
|
IN6_IS_ADDR_LOOPBACK(v6addr)))
|
||||||
|
continue;
|
||||||
|
if (*rlenp < sizeof(struct sockaddr_in6)) {
|
||||||
|
error("%s: v6 addr doesn't fit",
|
||||||
|
__func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*rlenp = sizeof(struct sockaddr_in6);
|
||||||
|
memcpy(resultp, sa6, *rlenp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates a (possibly privileged) socket for use as the ssh connection.
|
* Creates a (possibly privileged) socket for use as the ssh connection.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ssh_create_socket(int privileged, struct addrinfo *ai)
|
ssh_create_socket(int privileged, struct addrinfo *ai)
|
||||||
{
|
{
|
||||||
int sock, r, gaierr;
|
int sock, r, oerrno;
|
||||||
|
struct sockaddr_storage bindaddr;
|
||||||
|
socklen_t bindaddrlen = 0;
|
||||||
struct addrinfo hints, *res = NULL;
|
struct addrinfo hints, *res = NULL;
|
||||||
|
struct ifaddrs *ifaddrs = NULL;
|
||||||
|
char ntop[NI_MAXHOST];
|
||||||
|
|
||||||
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
@ -287,22 +354,50 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
|
|||||||
fcntl(sock, F_SETFD, FD_CLOEXEC);
|
fcntl(sock, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
/* Bind the socket to an alternative local IP address */
|
/* Bind the socket to an alternative local IP address */
|
||||||
if (options.bind_address == NULL && !privileged)
|
if (options.bind_address == NULL && options.bind_interface == NULL &&
|
||||||
|
!privileged)
|
||||||
return sock;
|
return sock;
|
||||||
|
|
||||||
if (options.bind_address) {
|
if (options.bind_address != NULL) {
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = ai->ai_family;
|
hints.ai_family = ai->ai_family;
|
||||||
hints.ai_socktype = ai->ai_socktype;
|
hints.ai_socktype = ai->ai_socktype;
|
||||||
hints.ai_protocol = ai->ai_protocol;
|
hints.ai_protocol = ai->ai_protocol;
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
|
if ((r = getaddrinfo(options.bind_address, NULL,
|
||||||
if (gaierr) {
|
&hints, &res)) != 0) {
|
||||||
error("getaddrinfo: %s: %s", options.bind_address,
|
error("getaddrinfo: %s: %s", options.bind_address,
|
||||||
ssh_gai_strerror(gaierr));
|
ssh_gai_strerror(r));
|
||||||
close(sock);
|
goto fail;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
if (res == NULL)
|
||||||
|
error("getaddrinfo: no addrs");
|
||||||
|
goto fail;
|
||||||
|
if (res->ai_addrlen > sizeof(bindaddr)) {
|
||||||
|
error("%s: addr doesn't fit", __func__);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
memcpy(&bindaddr, res->ai_addr, res->ai_addrlen);
|
||||||
|
bindaddrlen = res->ai_addrlen;
|
||||||
|
} else if (options.bind_interface != NULL) {
|
||||||
|
if ((r = getifaddrs(&ifaddrs)) != 0) {
|
||||||
|
error("getifaddrs: %s: %s", options.bind_interface,
|
||||||
|
strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
bindaddrlen = sizeof(bindaddr);
|
||||||
|
if (check_ifaddrs(options.bind_interface, ai->ai_family,
|
||||||
|
ifaddrs, &bindaddr, &bindaddrlen) != 0) {
|
||||||
|
logit("getifaddrs: %s: no suitable addresses",
|
||||||
|
options.bind_interface);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen,
|
||||||
|
ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) {
|
||||||
|
error("%s: getnameinfo failed: %s", __func__,
|
||||||
|
ssh_gai_strerror(r));
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we are running as root and want to connect to a privileged
|
* If we are running as root and want to connect to a privileged
|
||||||
@ -310,25 +405,30 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
|
|||||||
*/
|
*/
|
||||||
if (privileged) {
|
if (privileged) {
|
||||||
PRIV_START;
|
PRIV_START;
|
||||||
r = bindresvport_sa(sock, res ? res->ai_addr : NULL);
|
r = bindresvport_sa(sock,
|
||||||
|
bindaddrlen == 0 ? NULL : (struct sockaddr *)&bindaddr);
|
||||||
|
oerrno = errno;
|
||||||
PRIV_END;
|
PRIV_END;
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error("bindresvport_sa: af=%d %s", ai->ai_family,
|
error("bindresvport_sa %s: %s", ntop,
|
||||||
strerror(errno));
|
strerror(oerrno));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) {
|
||||||
if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
|
error("bind %s: %s", ntop, strerror(errno));
|
||||||
error("bind: %s: %s", options.bind_address,
|
goto fail;
|
||||||
strerror(errno));
|
}
|
||||||
|
debug("%s: bound to %s", __func__, ntop);
|
||||||
|
/* success */
|
||||||
|
goto out;
|
||||||
fail:
|
fail:
|
||||||
close(sock);
|
close(sock);
|
||||||
freeaddrinfo(res);
|
sock = -1;
|
||||||
return -1;
|
out:
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
if (ifaddrs != NULL)
|
||||||
|
freeifaddrs(ifaddrs);
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user