Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
LSH
lsh
Commits
bb0cd1b3
Commit
bb0cd1b3
authored
Nov 29, 1999
by
Balázs Scheidler
Committed by
Niels Möller
Nov 29, 1999
Browse files
* src/lsh_proxy.c: New program (Bazsi).
Rev: src/lsh_proxy.c:1.1
parent
b7d0ab48
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/lsh_proxy.c
0 → 100644
View file @
bb0cd1b3
/* lsh_proxy.c
*
* main proxy program.
*
* $Id$ */
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998, 1999 Niels Mller, Balzs Scheidler
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "algorithms.h"
#include "alist.h"
#include "atoms.h"
#include "channel.h"
#include "channel_commands.h"
#include "charset.h"
#include "compress.h"
#include "connection_commands.h"
#include "crypto.h"
#include "daemon.h"
#include "format.h"
#include "io.h"
#include "io_commands.h"
#include "lookup_verifier.h"
#include "randomness.h"
#include "spki.h"
#include "ssh.h"
#include "werror.h"
#include "xalloc.h"
#include "reaper.h"
#include "server.h"
#include "server_authorization.h"
#include "server_keyexchange.h"
#include "client_keyexchange.h"
#include "server_userauth.h"
#include "server_session.h"
#include "proxy.h"
#include "proxy_userauth.h"
#include "proxy_session.h"
#include "sexp.h"
#include "sexp_commands.h"
#include "lsh_argp.h"
#include "lsh_proxy.c.x"
#include <assert.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
/* Block size for stdout and stderr buffers */
#define BLOCK_SIZE 32768
/* Option parsing */
#define OPT_NO 0x400
#define OPT_SSH1_FALLBACK 0x200
#define OPT_INTERFACE 0x201
#define OPT_TCPIP_FORWARD 0x202
#define OPT_NO_TCPIP_FORWARD (OPT_TCPIP_FORWARD | OPT_NO)
#define OPT_DAEMONIC 0x203
#define OPT_NO_DAEMONIC (OPT_DAEMONIC | OPT_NO)
#define OPT_PIDFILE 0x204
#define OPT_NO_PIDFILE (OPT_PIDFILE | OPT_NO)
#define OPT_CORE 0x207
/* GABA:
(class
(name lsh_proxy_options)
(super algorithms_options)
(vars
(style . sexp_argp_state)
(interface . "char *")
(port . "char *")
(hostkey . "char *")
(local object address_info)
(with_tcpip_forward . int)
(sshd1 object ssh1_fallback)
(daemonic . int)
(corefile . int)
(pid_file . "const char *")
; -1 means use pid file iff we're in daemonic mode
(use_pid_file . int)))
*/
static
struct
lsh_proxy_options
*
make_lsh_proxy_options
(
struct
alist
*
algorithms
)
{
NEW
(
lsh_proxy_options
,
self
);
init_algorithms_options
(
&
self
->
super
,
algorithms
);
self
->
style
=
SEXP_TRANSPORT
;
self
->
interface
=
NULL
;
self
->
port
=
"ssh"
;
/* FIXME: this should perhaps use sysconfdir */
self
->
hostkey
=
"/etc/lsh_host_key"
;
self
->
local
=
NULL
;
self
->
with_tcpip_forward
=
1
;
self
->
sshd1
=
NULL
;
self
->
daemonic
=
0
;
/* FIXME: Make the default a configure time option? */
self
->
pid_file
=
"/var/run/lsh_proxy.pid"
;
self
->
use_pid_file
=
-
1
;
self
->
corefile
=
0
;
return
self
;
}
static
const
struct
argp_option
main_options
[]
=
{
/* Name, key, arg-name, flags, doc, group */
{
"interface"
,
OPT_INTERFACE
,
"interface"
,
0
,
"Listen on this network interface"
,
0
},
{
"port"
,
'p'
,
"Port"
,
0
,
"Listen on this port."
,
0
},
{
"host-key"
,
'h'
,
"Key file"
,
0
,
"Location of the server's private key."
,
0
},
{
"destination"
,
'D'
,
"destination:port"
,
0
,
"Destination ssh server address (transparent if not given)"
,
0
},
#if WITH_SSH1_FALLBACK
{
"ssh1-fallback"
,
OPT_SSH1_FALLBACK
,
"File name"
,
OPTION_ARG_OPTIONAL
,
"Location of the sshd1 program, for falling back to version 1 of the Secure Shell protocol."
,
0
},
#endif
/* WITH_SSH1_FALLBACK */
#if WITH_TCP_FORWARD
{
"tcp-forward"
,
OPT_TCPIP_FORWARD
,
NULL
,
0
,
"Enable tcpip forwarding (default)."
,
0
},
{
"no-tcp-forward"
,
OPT_NO_TCPIP_FORWARD
,
NULL
,
0
,
"Disable tcpip forwarding."
,
0
},
#endif
/* WITH_TCP_FORWARD */
{
NULL
,
0
,
NULL
,
0
,
"Daemonic behaviour"
,
0
},
{
"daemonic"
,
OPT_DAEMONIC
,
NULL
,
0
,
"Run in the background, redirect stdio to /dev/null, and chdir to /."
,
0
},
{
"no-daemonic"
,
OPT_NO_DAEMONIC
,
NULL
,
0
,
"Run in the foreground, with messages to stderr (default)."
,
0
},
{
"pid-file"
,
OPT_PIDFILE
,
"file name"
,
0
,
"Create a pid file. When running in daemonic mode, "
"the default is /var/run/lsh_proxy.pid."
,
0
},
{
"no-pid-file"
,
OPT_NO_PIDFILE
,
NULL
,
0
,
"Don't use any pid file. Default in non-daemonic mode."
,
0
},
{
"enable-core"
,
OPT_CORE
,
NULL
,
0
,
"Dump core on fatal errors (disabled by default)."
,
0
},
{
NULL
,
0
,
NULL
,
0
,
NULL
,
0
}
};
static
const
struct
argp_child
main_argp_children
[]
=
{
{
&
sexp_input_argp
,
0
,
""
,
0
},
{
&
algorithms_argp
,
0
,
""
,
0
},
{
&
werror_argp
,
0
,
""
,
0
},
{
NULL
,
0
,
NULL
,
0
}
};
static
error_t
main_argp_parser
(
int
key
,
char
*
arg
,
struct
argp_state
*
state
)
{
CAST
(
lsh_proxy_options
,
self
,
state
->
input
);
switch
(
key
)
{
default:
return
ARGP_ERR_UNKNOWN
;
case
ARGP_KEY_INIT
:
state
->
child_inputs
[
0
]
=
&
self
->
style
;
state
->
child_inputs
[
1
]
=
&
self
->
super
;
state
->
child_inputs
[
2
]
=
NULL
;
break
;
case
ARGP_KEY_ARG
:
argp_error
(
state
,
"Spurious arguments."
);
break
;
case
ARGP_KEY_END
:
self
->
local
=
make_address_info_c
(
self
->
interface
,
self
->
port
);
if
(
!
self
->
local
)
argp_error
(
state
,
"Invalid interface, port or service, %s:%s'."
,
self
->
interface
?
self
->
interface
:
"ANY"
,
self
->
port
);
if
(
self
->
use_pid_file
<
0
)
self
->
use_pid_file
=
self
->
daemonic
;
break
;
case
'p'
:
self
->
port
=
arg
;
break
;
case
'h'
:
self
->
hostkey
=
arg
;
break
;
case
OPT_INTERFACE
:
self
->
interface
=
arg
;
break
;
#if WITH_SSH1_FALLBACK
case
OPT_SSH1_FALLBACK
:
self
->
sshd1
=
make_ssh1_fallback
(
arg
?
arg
:
SSHD1
);
break
;
#endif
case
OPT_TCPIP_FORWARD
:
self
->
with_tcpip_forward
=
1
;
break
;
case
OPT_NO_TCPIP_FORWARD
:
self
->
with_tcpip_forward
=
0
;
break
;
case
OPT_DAEMONIC
:
self
->
daemonic
=
1
;
break
;
case
OPT_NO_DAEMONIC
:
self
->
daemonic
=
0
;
break
;
case
OPT_PIDFILE
:
self
->
pid_file
=
arg
;
self
->
use_pid_file
=
1
;
break
;
case
OPT_NO_PIDFILE
:
self
->
use_pid_file
=
0
;
break
;
case
OPT_CORE
:
self
->
corefile
=
1
;
break
;
}
return
0
;
}
static
const
struct
argp
main_argp
=
{
main_options
,
main_argp_parser
,
NULL
,
"Server for the ssh-2 protocol."
,
main_argp_children
,
NULL
,
NULL
};
/* GABA:
(class
(name fake_host_db)
(super lookup_verifier)
(vars
;; (algorithm object signature_algorithm)
))
*/
static
struct
verifier
*
do_host_lookup
(
struct
lookup_verifier
*
c
UNUSED
,
int
method
UNUSED
,
struct
lsh_string
*
keyholder
UNUSED
,
struct
lsh_string
*
key
)
{
assert
(
method
==
ATOM_SSH_DSS
);
return
&
make_ssh_dss_verifier
(
key
->
length
,
key
->
data
)
->
super
;
}
static
struct
lookup_verifier
*
make_fake_host_db
(
void
)
{
NEW
(
fake_host_db
,
res
);
res
->
super
.
lookup
=
do_host_lookup
;
return
&
res
->
super
;
}
/* GABA:
(expr
(name lsh_proxy_listen)
(globals
(log "&io_log_peer_command.super.super"))
(params
(listen object command)
(handshake object command)
(services object command)
(connect_server object command)
(chain_connections object command))
(expr
(lambda (port)
(services
(let ((peer (listen port)))
(chain_connections
connect_server
peer
(handshake (log peer))))))))
*/
/* GABA:
(expr
(name lsh_proxy_connect_server)
(params
(connect object command)
(handshake object command))
(expr
(lambda (port)
(handshake (connect port)))))
*/
/* Invoked when the client requests the userauth service. */
/* GABA:
(expr
(name lsh_proxy_services)
(params
(userauth object command))
(expr
(lambda (connection)
((userauth connection) connection))))
*/
/* Invoked when starting the ssh-connection service */
/* GABA:
(expr
(name lsh_proxy_connection_service)
(globals
(progn "&progn_command.super.super")
(init "&connection_service.super"))
(params
(login object command)
(hooks object object_list))
(expr
(lambda (user connection)
((progn hooks) (login user
; We have to initialize the connection
; before logging in.
(init connection))))))
*/
int
main
(
int
argc
,
char
**
argv
)
{
struct
lsh_proxy_options
*
options
;
struct
alist
*
keys
;
struct
reap
*
reaper
;
struct
randomness
*
r
;
struct
alist
*
algorithms_server
,
*
algorithms_client
;
struct
alist
*
lookup_keys
;
struct
make_kexinit
*
make_kexinit
;
struct
keypair
*
hostkey
;
/* FIXME: Why not allocate backend statically? */
NEW
(
io_backend
,
backend
);
init_backend
(
backend
);
/* For filtering messages. Could perhaps also be used when converting
* strings to and from UTF8. */
setlocale
(
LC_CTYPE
,
""
);
/* FIXME: Choose character set depending on the locale */
set_local_charset
(
CHARSET_LATIN1
);
r
=
make_reasonably_random
();
algorithms_server
=
many_algorithms
(
1
,
ATOM_SSH_DSS
,
make_dsa_algorithm
(
r
),
-
1
);
/* FIXME: copy algorithms_server */
algorithms_client
=
many_algorithms
(
1
,
ATOM_SSH_DSS
,
make_dsa_algorithm
(
r
),
-
1
);
options
=
make_lsh_proxy_options
(
algorithms_server
);
argp_parse
(
&
main_argp
,
argc
,
argv
,
0
,
NULL
,
options
);
if
(
!
options
->
corefile
&&
!
daemon_disable_core
())
{
werror
(
"Disabling of core dumps failed.
\n
"
);
return
EXIT_FAILURE
;
}
if
(
options
->
daemonic
)
{
#if HAVE_SYSLOG
set_error_syslog
(
"lsh_proxy"
);
#else
/* !HAVE_SYSLOG */
werror
(
"lsh_proxy: No syslog. Further messages will be directed to /dev/null.
\n
"
);
#endif
/* !HAVE_SYSLOG */
}
if
(
options
->
daemonic
)
switch
(
daemon_init
())
{
case
0
:
werror
(
"lsh_proxy: Spawning into background failed.
\n
"
);
return
EXIT_FAILURE
;
case
DAEMON_INETD
:
werror
(
"lsh_proxy: spawning from inetd not yet supported.
\n
"
);
return
EXIT_FAILURE
;
case
DAEMON_INIT
:
case
DAEMON_NORMAL
:
break
;
default:
fatal
(
"Internal error
\n
"
);
}
if
(
options
->
use_pid_file
&&
!
daemon_pidfile
(
options
->
pid_file
))
{
werror
(
"lsh_proxy seems to be running already.
\n
"
);
return
EXIT_FAILURE
;
}
/* Read the hostkey */
keys
=
make_alist
(
0
,
-
1
);
if
(
!
(
hostkey
=
read_spki_key_file
(
options
->
hostkey
,
make_alist
(
1
,
ATOM_DSA
,
make_dsa_algorithm
(
r
),
-
1
),
&
ignore_exception_handler
)))
{
werror
(
"lsh_proxy: Could not read hostkey.
\n
"
);
return
EXIT_FAILURE
;
}
ALIST_SET
(
keys
,
hostkey
->
type
,
hostkey
);
/* FIXME: We should check that we have at least one host key.
* We should also extract the host-key algorithms for which we have keys,
* instead of hardcoding ssh-dss below. */
reaper
=
make_reaper
();
lookup_keys
=
make_alist
(
1
,
ATOM_SSH_DSS
,
make_fake_host_db
(),
-
1
);
ALIST_SET
(
algorithms_server
,
ATOM_DIFFIE_HELLMAN_GROUP1_SHA1
,
make_dh_server
(
make_dh1
(
r
),
keys
));
ALIST_SET
(
algorithms_client
,
ATOM_DIFFIE_HELLMAN_GROUP1_SHA1
,
make_dh_client
(
make_dh1
(
r
),
lookup_keys
));
make_kexinit
=
make_simple_kexinit
(
r
,
make_int_list
(
1
,
ATOM_DIFFIE_HELLMAN_GROUP1_SHA1
,
-
1
),
make_int_list
(
1
,
ATOM_SSH_DSS
,
-
1
),
options
->
super
.
crypto_algorithms
,
options
->
super
.
mac_algorithms
,
options
->
super
.
compression_algorithms
,
make_int_list
(
0
,
-
1
));
{
/* Commands to be invoked on the connection */
struct
object_list
*
connection_hooks
;
connection_hooks
=
make_object_list
(
0
,
-
1
);
{
struct
lsh_object
*
o
=
lsh_proxy_listen
(
make_simple_listen
(
backend
,
NULL
),
make_handshake_command
(
CONNECTION_SERVER
,
"lsh_proxy_server - a free ssh"
,
SSH_MAX_PACKET
,
r
,
algorithms_server
,
make_kexinit
,
NULL
),
make_offer_service
(
make_alist
(
1
,
ATOM_SSH_USERAUTH
,
lsh_proxy_services
(
make_userauth_proxy
(
make_int_list
(
1
,
ATOM_PASSWORD
,
-
1
),
make_alist
(
1
,
ATOM_PASSWORD
,
&
proxy_password_auth
,
-
1
),
make_alist
(
1
,
ATOM_SSH_CONNECTION
,
lsh_proxy_connection_service
(
make_proxy_connection_service
(
make_alist
(
0
,
-
1
)),
connection_hooks
),
-
1
))),
-
1
)),
/* callback to call when client<->proxy handshake finished */
(
struct
command
*
)
lsh_proxy_connect_server
(
make_simple_connect
(
backend
,
NULL
),
make_handshake_command
(
CONNECTION_CLIENT
,
"lsh_proxy_client - a free ssh"
,
SSH_MAX_PACKET
,
r
,
algorithms_client
,
make_kexinit
,
NULL
)
),
&
chain_connections
.
super
.
super
);
CAST_SUBTYPE
(
command
,
server_listen
,
o
);
COMMAND_CALL
(
server_listen
,
options
->
local
,
&
discard_continuation
,
make_report_exception_handler
(
EXC_IO
,
EXC_IO
,
"lsh_proxy: "
,
&
default_exception_handler
,
HANDLER_CONTEXT
));
}
}
reaper_run
(
reaper
,
backend
);
return
0
;
}
Write
Preview
Supports
Markdown
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