mirror of
https://github.com/clearml/dropbear
synced 2025-04-18 13:14:47 +00:00
parent
3d61b6eab6
commit
917722257d
53
netio.c
53
netio.c
@ -348,6 +348,37 @@ void set_sock_priority(int sock, enum dropbear_prio prio) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* from openssh/canohost.c avoid premature-optimization */
|
||||||
|
int get_sock_port(int sock) {
|
||||||
|
struct sockaddr_storage from;
|
||||||
|
socklen_t fromlen;
|
||||||
|
char strport[NI_MAXSERV];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Get IP address of client. */
|
||||||
|
fromlen = sizeof(from);
|
||||||
|
memset(&from, 0, sizeof(from));
|
||||||
|
if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
|
||||||
|
TRACE(("getsockname failed: %d", errno))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Work around Linux IPv6 weirdness */
|
||||||
|
if (from.ss_family == AF_INET6)
|
||||||
|
fromlen = sizeof(struct sockaddr_in6);
|
||||||
|
|
||||||
|
/* Non-inet sockets don't have a port number. */
|
||||||
|
if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Return port number. */
|
||||||
|
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
|
||||||
|
strport, sizeof(strport), NI_NUMERICSERV)) != 0) {
|
||||||
|
TRACE(("netio.c/get_sock_port/getnameinfo NI_NUMERICSERV failed: %d", r))
|
||||||
|
}
|
||||||
|
return atoi(strport);
|
||||||
|
}
|
||||||
|
|
||||||
/* Listen on address:port.
|
/* Listen on address:port.
|
||||||
* Special cases are address of "" listening on everything,
|
* Special cases are address of "" listening on everything,
|
||||||
* and address of NULL listening on localhost only.
|
* and address of NULL listening on localhost only.
|
||||||
@ -400,11 +431,29 @@ int dropbear_listen(const char* address, const char* port,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* when listening on server-assigned-port 0
|
||||||
|
* the assigned ports may differ for address families (v4/v6)
|
||||||
|
* causing problems for tcpip-forward
|
||||||
|
* caller can do a get_socket_address to discover assigned-port
|
||||||
|
* hence, use same port for all address families
|
||||||
|
*/
|
||||||
|
u_int16_t *allocated_lport_p = 0;
|
||||||
|
int allocated_lport = 0;
|
||||||
|
|
||||||
nsock = 0;
|
nsock = 0;
|
||||||
for (res = res0; res != NULL && nsock < sockcount;
|
for (res = res0; res != NULL && nsock < sockcount;
|
||||||
res = res->ai_next) {
|
res = res->ai_next) {
|
||||||
|
|
||||||
|
if (allocated_lport > 0) {
|
||||||
|
if (AF_INET == res->ai_family) {
|
||||||
|
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
|
||||||
|
} else if (AF_INET6 == res->ai_family) {
|
||||||
|
allocated_lport_p = &((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
|
||||||
|
}
|
||||||
|
*allocated_lport_p = htons(allocated_lport);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a socket */
|
/* Get a socket */
|
||||||
socks[nsock] = socket(res->ai_family, res->ai_socktype,
|
socks[nsock] = socket(res->ai_family, res->ai_socktype,
|
||||||
res->ai_protocol);
|
res->ai_protocol);
|
||||||
@ -451,6 +500,10 @@ int dropbear_listen(const char* address, const char* port,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 == allocated_lport) {
|
||||||
|
allocated_lport = get_sock_port(sock);
|
||||||
|
}
|
||||||
|
|
||||||
*maxfd = MAX(*maxfd, sock);
|
*maxfd = MAX(*maxfd, sock);
|
||||||
|
|
||||||
nsock++;
|
nsock++;
|
||||||
|
1
netio.h
1
netio.h
@ -14,6 +14,7 @@ enum dropbear_prio {
|
|||||||
void set_sock_nodelay(int sock);
|
void set_sock_nodelay(int sock);
|
||||||
void set_sock_priority(int sock, enum dropbear_prio prio);
|
void set_sock_priority(int sock, enum dropbear_prio prio);
|
||||||
|
|
||||||
|
int get_sock_port(int sock);
|
||||||
void get_socket_address(int fd, char **local_host, char **local_port,
|
void get_socket_address(int fd, char **local_host, char **local_port,
|
||||||
char **remote_host, char **remote_port, int host_lookup);
|
char **remote_host, char **remote_port, int host_lookup);
|
||||||
void getaddrstring(struct sockaddr_storage* addr,
|
void getaddrstring(struct sockaddr_storage* addr,
|
||||||
|
45
svr-tcpfwd.c
45
svr-tcpfwd.c
@ -47,7 +47,7 @@ void recv_msg_global_request_remotetcp() {
|
|||||||
#endif /* !DROPBEAR_SVR_REMOTETCPFWD */
|
#endif /* !DROPBEAR_SVR_REMOTETCPFWD */
|
||||||
|
|
||||||
static int svr_cancelremotetcp(void);
|
static int svr_cancelremotetcp(void);
|
||||||
static int svr_remotetcpreq(void);
|
static int svr_remotetcpreq(int *allocated_listen_port);
|
||||||
static int newtcpdirect(struct Channel * channel);
|
static int newtcpdirect(struct Channel * channel);
|
||||||
|
|
||||||
#if DROPBEAR_SVR_REMOTETCPFWD
|
#if DROPBEAR_SVR_REMOTETCPFWD
|
||||||
@ -86,7 +86,16 @@ void recv_msg_global_request_remotetcp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp("tcpip-forward", reqname) == 0) {
|
if (strcmp("tcpip-forward", reqname) == 0) {
|
||||||
ret = svr_remotetcpreq();
|
int allocated_listen_port;
|
||||||
|
ret = svr_remotetcpreq(&allocated_listen_port);
|
||||||
|
/* client expects-port-number-to-make-use-of-server-allocated-ports */
|
||||||
|
if (DROPBEAR_SUCCESS == ret) {
|
||||||
|
CHECKCLEARTOWRITE();
|
||||||
|
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_SUCCESS);
|
||||||
|
buf_putint(ses.writepayload, allocated_listen_port);
|
||||||
|
encrypt_packet();
|
||||||
|
wantreply = 0; //so out does not do so
|
||||||
|
}
|
||||||
} else if (strcmp("cancel-tcpip-forward", reqname) == 0) {
|
} else if (strcmp("cancel-tcpip-forward", reqname) == 0) {
|
||||||
ret = svr_cancelremotetcp();
|
ret = svr_cancelremotetcp();
|
||||||
} else {
|
} else {
|
||||||
@ -152,7 +161,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int svr_remotetcpreq() {
|
static int svr_remotetcpreq(int *allocated_listen_port) {
|
||||||
|
|
||||||
int ret = DROPBEAR_FAILURE;
|
int ret = DROPBEAR_FAILURE;
|
||||||
char * request_addr = NULL;
|
char * request_addr = NULL;
|
||||||
@ -170,19 +179,16 @@ static int svr_remotetcpreq() {
|
|||||||
|
|
||||||
port = buf_getint(ses.payload);
|
port = buf_getint(ses.payload);
|
||||||
|
|
||||||
if (port == 0) {
|
if (port != 0) {
|
||||||
dropbear_log(LOG_INFO, "Server chosen tcpfwd ports are unsupported");
|
if (port < 1 || port > 65535) {
|
||||||
goto out;
|
TRACE(("invalid port: %d", port))
|
||||||
}
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (port < 1 || port > 65535) {
|
if (!ses.allowprivport && port < IPPORT_RESERVED) {
|
||||||
TRACE(("invalid port: %d", port))
|
TRACE(("can't assign port < 1024 for non-root"))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ses.allowprivport && port < IPPORT_RESERVED) {
|
|
||||||
TRACE(("can't assign port < 1024 for non-root"))
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
|
tcpinfo = (struct TCPListener*)m_malloc(sizeof(struct TCPListener));
|
||||||
@ -203,6 +209,13 @@ static int svr_remotetcpreq() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = listen_tcpfwd(tcpinfo);
|
ret = listen_tcpfwd(tcpinfo);
|
||||||
|
if (DROPBEAR_SUCCESS == ret) {
|
||||||
|
tcpinfo->listenport = get_sock_port(ses.listeners[0]->socks[0]);
|
||||||
|
*allocated_listen_port = tcpinfo->listenport;
|
||||||
|
dropbear_log(LOG_INFO, "tcpip-forward %s:%d '%s'",
|
||||||
|
((NULL == tcpinfo->listenaddr)?"localhost":tcpinfo->listenaddr),
|
||||||
|
tcpinfo->listenport, ses.authstate.pw_name);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (ret == DROPBEAR_FAILURE) {
|
if (ret == DROPBEAR_FAILURE) {
|
||||||
@ -211,7 +224,9 @@ out:
|
|||||||
m_free(request_addr);
|
m_free(request_addr);
|
||||||
m_free(tcpinfo);
|
m_free(tcpinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("leave remotetcpreq"))
|
TRACE(("leave remotetcpreq"))
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user