Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nxssh
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Алексей Аляев
nxssh
Commits
9553287a
Commit
9553287a
authored
Nov 08, 2016
by
Stas Korobeynikov
Committed by
Pavel Vainerman
Oct 04, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add ssh webproxy connect function
parent
1445232a
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
319 additions
and
1 deletion
+319
-1
sshconnect.c
sshconnect.c
+315
-1
sshconnect.h
sshconnect.h
+4
-0
No files found.
sshconnect.c
View file @
9553287a
...
...
@@ -91,6 +91,17 @@ extern uid_t original_effective_uid;
static
int
show_other_keys
(
struct
hostkeys
*
,
Key
*
);
static
void
warn_changed_key
(
Key
*
);
static
const
char
*
sockaddr_ntop
(
struct
sockaddr
*
sa
,
socklen_t
salen
)
{
static
char
addrbuf
[
NI_MAXHOST
];
if
(
getnameinfo
(
sa
,
salen
,
addrbuf
,
sizeof
(
addrbuf
),
NULL
,
0
,
NI_NUMERICHOST
)
!=
0
)
fatal
(
"sockaddr_ntop: getnameinfo NI_NUMERICHOST failed"
);
return
addrbuf
;
}
/* Expand a proxy command */
static
char
*
expand_proxy_command
(
const
char
*
proxy_command
,
const
char
*
user
,
...
...
@@ -420,6 +431,309 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
return
(
result
);
}
int
ssh_webproxy_connect
(
const
char
*
proxy_host
,
u_short
proxy_port
,
const
char
*
proxy_username
,
const
char
*
proxy_passwd
,
const
char
*
host
,
struct
sockaddr_storage
*
hostaddr
,
u_short
port
,
int
family
,
int
connection_attempts
,
int
needpriv
)
{
int
gaierr
;
int
on
=
1
;
int
sock
=
-
1
,
attempt
;
char
ntop
[
NI_MAXHOST
],
strport
[
NI_MAXSERV
];
struct
addrinfo
hints
,
*
ai
,
*
aitop
;
struct
servent
*
sp
;
char
readbuf
[
1024
];
char
writebuf
[
1024
];
fd_set
fds
;
struct
timeval
tv
;
int
sel_ret
;
int
i
,
r
;
/*
* Did we get only other errors than "Connection refused" (which
* should block fallback to rsh and similar), or did we get at least
* one "Connection refused"?
*/
int
full_failure
=
1
;
debug2
(
"ssh_webproxy_connect: needpriv %d"
,
needpriv
);
/* Get default port if port has not been set. */
if
(
proxy_port
==
0
)
{
proxy_port
=
3128
;
}
if
(
port
==
0
)
{
sp
=
getservbyname
(
SSH_SERVICE_NAME
,
"tcp"
);
if
(
sp
)
{
port
=
ntohs
(
sp
->
s_port
);
}
else
{
port
=
SSH_DEFAULT_PORT
;
}
}
memset
(
&
hints
,
0
,
sizeof
(
hints
));
hints
.
ai_family
=
family
;
hints
.
ai_socktype
=
SOCK_STREAM
;
snprintf
(
strport
,
sizeof
strport
,
"%u"
,
proxy_port
);
if
((
gaierr
=
getaddrinfo
(
proxy_host
,
strport
,
&
hints
,
&
aitop
))
!=
0
)
{
if
(
NxAdminModeEnabled
)
{
fprintf
(
stdout
,
"NX> 207 %s: %.100s: %s
\n
"
,
__progname
,
proxy_host
,
gai_strerror
(
gaierr
));
fatal
(
"%s: %.100s: %s"
,
__progname
,
proxy_host
,
gai_strerror
(
gaierr
));
}
else
if
(
NxAuthOnlyModeEnabled
)
{
fatal
(
"NX> 207 %s: %.100s: %s"
,
__progname
,
proxy_host
,
gai_strerror
(
gaierr
));
}
else
{
fatal
(
"%s: %.100s: %s"
,
__progname
,
proxy_host
,
gai_strerror
(
gaierr
));
}
}
/*
* Try to connect several times. On some machines, the first time
* will sometimes fail. In general socket code appears to behave
* quite magically on many machines.
*/
for
(
attempt
=
0
;
;)
{
if
(
attempt
>
0
)
{
debug
(
"Trying again..."
);
}
/* Loop through addresses for this host, and try each one in
sequence until the connection succeeds. */
for
(
ai
=
aitop
;
ai
;
ai
=
ai
->
ai_next
)
{
if
(
ai
->
ai_family
!=
AF_INET
&&
ai
->
ai_family
!=
AF_INET6
)
{
continue
;
}
if
(
getnameinfo
(
ai
->
ai_addr
,
ai
->
ai_addrlen
,
ntop
,
sizeof
(
ntop
),
strport
,
sizeof
(
strport
),
NI_NUMERICHOST
|
NI_NUMERICSERV
)
!=
0
)
{
error
(
"ssh_connect: getnameinfo failed"
);
continue
;
}
debug
(
"Connecting to web proxy %.200s [%.100s] port %s."
,
proxy_host
,
ntop
,
strport
);
/* Create a socket for connecting. */
sock
=
ssh_create_socket
(
needpriv
,
ai
);
if
(
sock
<
0
)
{
/* Any error is already output */
continue
;
}
if
(
timeout_connect
(
sock
,
ai
->
ai_addr
,
ai
->
ai_addrlen
,
options
.
connection_timeout
)
>=
0
)
{
/* Successful connection. */
memcpy
(
hostaddr
,
ai
->
ai_addr
,
ai
->
ai_addrlen
);
break
;
}
else
{
if
(
errno
==
ECONNREFUSED
)
{
full_failure
=
0
;
}
if
(
NxAdminModeEnabled
)
{
fprintf
(
stdout
,
"NX> 207 nxssh: connect to address %s port %s: %s
\n
"
,
sockaddr_ntop
(
ai
->
ai_addr
,
ai
->
ai_addrlen
),
strport
,
strerror
(
errno
));
}
else
if
(
NxAuthOnlyModeEnabled
)
{
fprintf
(
stdout
,
"NX> 207 nxssh: connect to address %s port %s: %s"
,
sockaddr_ntop
(
ai
->
ai_addr
,
ai
->
ai_addrlen
),
strport
,
strerror
(
errno
));
}
else
{
debug
(
"connect to address %s port %s: %s"
,
ntop
,
strport
,
strerror
(
errno
));
}
/*
* Close the failed socket; there appear to
* be some problems when reusing a socket for
* which connect() has already returned an
* error.
*/
close
(
sock
);
}
}
if
(
ai
)
{
if
(
NxModeEnabled
)
{
logit
(
"NX> 200 Connected to web proxy at address: %.200s on port: %.200s"
,
ntop
,
strport
);
}
break
;
/* Successful connection. */
}
attempt
++
;
if
(
attempt
>=
connection_attempts
)
{
break
;
}
/* Sleep a moment before retrying. */
sleep
(
1
);
}
freeaddrinfo
(
aitop
);
/* Return failure if we didn't get a successful connection. */
if
(
attempt
>=
connection_attempts
)
{
logit
(
"ssh: connect to host %s port %s: %s"
,
proxy_host
,
strport
,
strerror
(
errno
));
return
full_failure
?
ECONNABORTED
:
ECONNREFUSED
;
}
debug
(
"Connection to web proxy established."
);
#ifdef TEST
logit
(
"NX> 280 SSH connection established with fd: %d"
,
sock
);
#endif
/* Set SO_KEEPALIVE if requested. */
if
(
options
.
tcp_keep_alive
&&
setsockopt
(
sock
,
SOL_SOCKET
,
SO_KEEPALIVE
,
(
void
*
)
&
on
,
sizeof
(
on
))
<
0
)
{
error
(
"setsockopt SO_KEEPALIVE: %.100s"
,
strerror
(
errno
));
}
if
(
strcspn
(
host
,
"
\r\n\t
[]:"
)
!=
strlen
(
host
))
{
fatal
(
"ssh_webproxy_connect: invalid hostname %.100s"
,
host
);
}
if
(
strchr
(
host
,
':'
)
!=
NULL
)
{
r
=
snprintf
(
writebuf
,
sizeof
(
writebuf
),
"CONNECT [%s]:%u HTTP/1.0
\r\n
"
,
host
,
port
);
}
else
{
r
=
snprintf
(
writebuf
,
sizeof
(
writebuf
),
"CONNECT %s:%u HTTP/1.0
\r\n
"
,
host
,
port
);
}
if
(
r
==
-
1
||
(
size_t
)
r
>=
sizeof
(
writebuf
))
{
fatal
(
"ssh_webproxy_connect: hostname too long %.100s"
,
host
);
}
debug
(
"ssh_webproxy_connect: write %.100s"
,
writebuf
);
write
(
sock
,
writebuf
,
strlen
(
writebuf
));
if
(
strlen
(
proxy_username
)
&&
strlen
(
proxy_passwd
))
{
char
encodedUsrNamePasswd
[
1024
]
=
""
;
char
usrNamePasswd
[
1024
];
snprintf
(
usrNamePasswd
,
sizeof
(
usrNamePasswd
),
"%s:%s"
,
proxy_username
,
proxy_passwd
);
uuencode
(
usrNamePasswd
,
strlen
(
usrNamePasswd
),
encodedUsrNamePasswd
,
1024
);
r
=
snprintf
(
writebuf
,
sizeof
(
writebuf
),
"Proxy-Authorization: Basic %s
\r\n\r\n
"
,
encodedUsrNamePasswd
);
}
else
{
r
=
snprintf
(
writebuf
,
sizeof
(
writebuf
),
"
\r\n
"
);
}
if
(
r
==
-
1
||
(
size_t
)
r
>=
sizeof
(
writebuf
))
{
fatal
(
"ssh_webproxy_connect: username and password too long %.100s"
,
proxy_username
);
}
debug
(
"ssh_webproxy_connect: write %.100s"
,
writebuf
);
write
(
sock
,
writebuf
,
strlen
(
writebuf
));
FD_ZERO
(
&
fds
);
FD_SET
(
sock
,
&
fds
);
tv
.
tv_sec
=
30
;
tv
.
tv_usec
=
0
;
/* Read proxy repsonse. */
for
(
r
=
0
;
r
<
HTTP_MAXHDRS
;
r
++
)
{
sel_ret
=
select
(
sock
+
1
,
&
fds
,
NULL
,
NULL
,
&
tv
);
if
(
sel_ret
==
0
)
{
exit
(
1
);
}
for
(
i
=
0
;
i
<
sizeof
(
readbuf
)
-
1
;
i
++
)
{
int
len
=
read
(
sock
,
&
readbuf
[
i
],
1
);
if
(
len
<
0
)
{
fatal
(
"web proxy handshaking: read: %.100s"
,
strerror
(
errno
));
}
if
(
len
!=
1
)
{
fatal
(
"web proxy handshaking: Connection closed by remote host"
);
}
if
(
readbuf
[
i
]
==
'\r'
)
{
continue
;
/**XXX wait for \n */
}
if
(
readbuf
[
i
]
==
'\n'
)
{
readbuf
[
i
]
=
0
;
break
;
}
}
debug
(
"ssh_webproxy_connect: read %.100s"
,
readbuf
);
if
(
r
==
0
&&
strncmp
(
readbuf
,
"HTTP/1.0 200 "
,
13
)
!=
0
&&
strncmp
(
readbuf
,
"HTTP/1.1 200 "
,
13
)
!=
0
)
{
fatal
(
"web proxy handshaking: proxy error: %.100s"
,
readbuf
);
}
if
(
*
readbuf
==
'\0'
||
*
readbuf
==
'\r'
)
{
break
;
}
}
/* Set the connection. */
packet_set_connection
(
sock
,
sock
);
return
0
;
}
/*
* Opens a TCP/IP connection to the remote server on the given host.
* The address of the remote host will be returned in hostaddr.
...
...
@@ -783,7 +1097,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
* using a proxy command
*/
if
(
hostfile_ipaddr
!=
NULL
)
{
if
(
options
.
proxy_command
==
NULL
)
{
if
(
options
.
proxy_command
==
NULL
&&
webproxy_flag
==
0
)
{
if
(
getnameinfo
(
hostaddr
,
addrlen
,
ntop
,
sizeof
(
ntop
),
NULL
,
0
,
NI_NUMERICHOST
)
!=
0
)
fatal
(
"%s: getnameinfo failed"
,
__func__
);
...
...
sshconnect.h
View file @
9553287a
...
...
@@ -34,6 +34,10 @@ struct Sensitive {
struct
addrinfo
;
int
ssh_connect
(
const
char
*
,
struct
addrinfo
*
,
struct
sockaddr_storage
*
,
u_short
,
int
,
int
,
int
*
,
int
,
int
);
int
ssh_webproxy_connect
(
const
char
*
,
u_short
,
const
char
*
,
const
char
*
,
const
char
*
,
struct
sockaddr_storage
*
,
u_short
,
int
,
int
,
int
);
void
ssh_kill_proxy_command
(
void
);
void
ssh_login
(
Sensitive
*
,
const
char
*
,
struct
sockaddr
*
,
u_short
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment