mirror of
https://github.com/clearml/dropbear
synced 2025-04-23 15:44:35 +00:00
Progressing client support
--HG-- extra : convert_revision : 48946be1cef774d1c33b0f78689962b18720c627
This commit is contained in:
parent
052bf7df93
commit
a76b1ba068
Makefile.inauth.hcli-auth.ccli-authpasswd.ccli-kex.ccli-main.ccli-service.ccli-session.ccommon-kex.ccommon-runopts.ccommon-session.cdbmulti.cdebug.hkex.hoptions.hpacket.crunopts.hscp.cservice.hsession.hsvr-agentfwd.csvr-auth.csvr-authpasswd.csvr-authpubkey.csvr-chansession.csvr-runopts.csvr-service.csvr-session.c
13
Makefile.in
13
Makefile.in
@ -27,7 +27,7 @@ SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
|
||||
svr-chansession.o svr-runopts.o svr-agentfwd.o svr-main.o svr-x11fwd.o
|
||||
|
||||
CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
|
||||
cli-session.o cli-service.o
|
||||
cli-session.o cli-service.o cli-runopts.o
|
||||
|
||||
CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
|
||||
common-channel.o common-chansession.o termcodes.o loginrec.o \
|
||||
@ -140,11 +140,12 @@ dbclient: $(dbclientobjs)
|
||||
dropbearkey: $(dropbearkeyobjs)
|
||||
dropbearconvert: $(dropbearconvertobjs)
|
||||
|
||||
dropbear dbclient dropbearkey dropbearconvert: $(HEADERS) $(LTC) $(LTM)
|
||||
dropbear dbclient dropbearkey dropbearconvert: $(HEADERS) $(LTC) $(LTM) \
|
||||
Makefile
|
||||
$(LD) $(LDFLAGS) -o $(SPREFIX)$@$(EXEEXT) $($@objs) $(LIBS)
|
||||
|
||||
# scp doesn't use the libs so is special.
|
||||
scp: $(SCPOBJS) $(HEADERS)
|
||||
scp: $(SCPOBJS) $(HEADERS) Makefile
|
||||
$(LD) $(LDFLAGS) -o $(SPREFIX)$@$(EXEEXT) $(SCPOBJS)
|
||||
|
||||
|
||||
@ -155,16 +156,16 @@ ifeq ($(MULTI),1)
|
||||
CFLAGS+=$(addprefix -DDBMULTI_, $(PROGRAMS)) -DDROPBEAR_MULTI
|
||||
endif
|
||||
|
||||
dropbearmulti: $(HEADERS) $(MULTIOBJS) $(LTC) $(LTM)
|
||||
dropbearmulti: $(HEADERS) $(MULTIOBJS) $(LTC) $(LTM) Makefile
|
||||
$(LD) $(LDFLAGS) -o $(SPREFIX)$@$(EXEEXT) $(MULTIOBJS) $(LIBS)
|
||||
@echo
|
||||
@echo "You should now create symlinks to the programs you have included"
|
||||
@echo "ie 'ln -s dropbearmulti dropbear'"
|
||||
|
||||
$(LTC): $(HEADERS)
|
||||
$(LTC): options.h
|
||||
cd libtomcrypt && $(MAKE) clean && $(MAKE)
|
||||
|
||||
$(LTM): $(HEADERS)
|
||||
$(LTM): options.h
|
||||
cd libtommath && $(MAKE)
|
||||
|
||||
ltc-clean:
|
||||
|
30
auth.h
30
auth.h
@ -27,12 +27,28 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
void authinitialise();
|
||||
void svr_authinitialise();
|
||||
void cli_authinitialise();
|
||||
|
||||
void svr_auth_password();
|
||||
void svr_auth_pubkey();
|
||||
|
||||
int cli_auth_password();
|
||||
int cli_auth_pubkey();
|
||||
|
||||
/* Server functions */
|
||||
void recv_msg_userauth_request();
|
||||
void send_msg_userauth_failure(int partial, int incrfail);
|
||||
void send_msg_userauth_success();
|
||||
|
||||
/* Client functions */
|
||||
void recv_msg_userauth_failure();
|
||||
void recv_msg_userauth_success();
|
||||
void cli_get_user();
|
||||
void cli_auth_getmethods();
|
||||
void cli_auth_try();
|
||||
|
||||
|
||||
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */
|
||||
|
||||
#define AUTH_TYPE_PUBKEY 1 << 0
|
||||
@ -46,17 +62,23 @@ void send_msg_userauth_success();
|
||||
#define AUTH_METHOD_PASSWORD "password"
|
||||
#define AUTH_METHOD_PASSWORD_LEN 8
|
||||
|
||||
/* This structure is shared between server and client - it contains
|
||||
* relatively little extraneous bits when used for the client rather than the
|
||||
* server */
|
||||
struct AuthState {
|
||||
|
||||
char *username; /* This is the username the client presents to check. It
|
||||
is updated each run through, used for auth checking */
|
||||
char *printableuser; /* stripped of control chars, used for logs etc */
|
||||
struct passwd * pw;
|
||||
unsigned char authtypes; /* Flags indicating which auth types are still
|
||||
valid */
|
||||
unsigned int failcount; /* Number of (failed) authentication attempts.*/
|
||||
unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have */
|
||||
unsigned authdone : 1; /* 0 if we haven't authed, 1 if we have. Applies for
|
||||
client and server (though has differing [obvious]
|
||||
meanings). */
|
||||
|
||||
/* These are only used for the server */
|
||||
char *printableuser; /* stripped of control chars, used for logs etc */
|
||||
struct passwd * pw;
|
||||
|
||||
};
|
||||
|
||||
|
148
cli-auth.c
Normal file
148
cli-auth.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include "includes.h"
|
||||
#include "session.h"
|
||||
#include "auth.h"
|
||||
#include "dbutil.h"
|
||||
#include "buffer.h"
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
#include "runopts.h"
|
||||
|
||||
void cli_authinitialise() {
|
||||
|
||||
memset(&ses.authstate, 0, sizeof(ses.authstate));
|
||||
}
|
||||
|
||||
|
||||
void cli_get_user() {
|
||||
|
||||
uid_t uid;
|
||||
struct passwd *pw;
|
||||
|
||||
TRACE(("enter cli_get_user"));
|
||||
if (cli_opts.username != NULL) {
|
||||
ses.authstate.username = cli_opts.username;
|
||||
} else {
|
||||
uid = getuid();
|
||||
|
||||
pw = getpwuid(uid);
|
||||
if (pw == NULL || pw->pw_name == NULL) {
|
||||
dropbear_exit("Couldn't find username for current user");
|
||||
}
|
||||
|
||||
ses.authstate.username = m_strdup(pw->pw_name);
|
||||
}
|
||||
TRACE(("leave cli_get_user: %s", cli_ses.username));
|
||||
}
|
||||
|
||||
/* Send a "none" auth request to get available methods */
|
||||
void cli_auth_getmethods() {
|
||||
|
||||
TRACE(("enter cli_auth_getmethods"));
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
buf_putstring(ses.writepayload, ses.authstate.username,
|
||||
strlen(ses.authstate.username));
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
buf_putstring(ses.writepayload, "none", 4); /* 'none' method */
|
||||
|
||||
encrypt_packet();
|
||||
cli_ses.state = USERAUTH_METHODS_SENT;
|
||||
TRACE(("leave cli_auth_getmethods"));
|
||||
|
||||
}
|
||||
|
||||
void recv_msg_userauth_failure() {
|
||||
|
||||
unsigned char * methods = NULL;
|
||||
unsigned char * tok = NULL;
|
||||
unsigned int methlen = 0;
|
||||
unsigned int partial = 0;
|
||||
unsigned int i = 0;
|
||||
|
||||
TRACE(("<- MSG_USERAUTH_FAILURE"));
|
||||
TRACE(("enter recv_msg_userauth_failure"));
|
||||
|
||||
methods = buf_getstring(ses.payload, &methlen);
|
||||
|
||||
partial = buf_getbyte(ses.payload);
|
||||
|
||||
if (partial) {
|
||||
dropbear_log(LOG_INFO, "Authentication partially succeeded, more attempts required");
|
||||
} else {
|
||||
ses.authstate.failcount++;
|
||||
}
|
||||
|
||||
TRACE(("Methods (len %d): '%s'", methlen, methods));
|
||||
|
||||
ses.authstate.authdone=0;
|
||||
ses.authstate.authtypes=0;
|
||||
|
||||
/* Split with nulls rather than commas */
|
||||
for (i = 0; i < methlen; i++) {
|
||||
if (methods[i] == ',') {
|
||||
methods[i] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
tok = methods; /* tok stores the next method we'll compare */
|
||||
for (i = 0; i <= methlen; i++) {
|
||||
if (methods[i] == '\0') {
|
||||
TRACE(("auth method '%s'\n", tok));
|
||||
#ifdef DROPBEAR_PUBKEY_AUTH
|
||||
if (strncmp(AUTH_METHOD_PUBKEY, tok,
|
||||
AUTH_METHOD_PUBKEY_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
|
||||
}
|
||||
#endif
|
||||
#ifdef DROPBEAR_PASSWORD_AUTH
|
||||
if (strncmp(AUTH_METHOD_PASSWORD, tok,
|
||||
AUTH_METHOD_PASSWORD_LEN) == 0) {
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
|
||||
}
|
||||
#endif
|
||||
tok = &methods[i]; /* Must make sure we don't use it after
|
||||
the last loop, since it'll point
|
||||
to something undefined */
|
||||
}
|
||||
}
|
||||
|
||||
cli_ses.state = USERAUTH_FAIL_RCVD;
|
||||
|
||||
TRACE(("leave recv_msg_userauth_failure"));
|
||||
}
|
||||
|
||||
void recv_msg_userauth_success() {
|
||||
TRACE(("received msg_userauth_success"));
|
||||
ses.authstate.authdone = 1;
|
||||
}
|
||||
|
||||
void cli_auth_try() {
|
||||
|
||||
TRACE(("enter cli_auth_try"));
|
||||
int finished = 0;
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
/* XXX We hardcode that we try a pubkey first */
|
||||
#ifdef DROPBEAR_PUBKEY_AUTH
|
||||
if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
|
||||
finished = cli_auth_pubkey();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DROPBEAR_PASSWORD_AUTH
|
||||
if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
finished = cli_auth_password();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!finished) {
|
||||
dropbear_exit("No auth methods could be used.");
|
||||
}
|
||||
|
||||
cli_ses.state = USERAUTH_REQ_SENT;
|
||||
TRACE(("leave cli_auth_try"));
|
||||
}
|
36
cli-authpasswd.c
Normal file
36
cli-authpasswd.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "includes.h"
|
||||
#include "buffer.h"
|
||||
#include "dbutil.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
|
||||
int cli_auth_password() {
|
||||
|
||||
char* password = NULL;
|
||||
TRACE(("enter cli_auth_password"));
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
password = getpass("Password: ");
|
||||
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
|
||||
|
||||
buf_putstring(ses.writepayload, ses.authstate.username,
|
||||
strlen(ses.authstate.username));
|
||||
|
||||
buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
|
||||
SSH_SERVICE_CONNECTION_LEN);
|
||||
|
||||
buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD,
|
||||
AUTH_METHOD_PASSWORD_LEN);
|
||||
|
||||
buf_putbyte(ses.writepayload, 0); /* FALSE - so says the spec */
|
||||
|
||||
buf_putstring(ses.writepayload, password, strlen(password));
|
||||
|
||||
encrypt_packet();
|
||||
m_burn(password, strlen(password));
|
||||
|
||||
TRACE(("leave cli_auth_password"));
|
||||
return 1; /* Password auth can always be tried */
|
||||
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
#include "bignum.h"
|
||||
#include "random.h"
|
||||
#include "runopts.h"
|
||||
#include "signkey.h"
|
||||
|
||||
|
||||
|
||||
|
49
cli-main.c
49
cli-main.c
@ -1,6 +1,17 @@
|
||||
#include <includes.h>
|
||||
#include "includes.h"
|
||||
#include "dbutil.h"
|
||||
#include "runopts.h"
|
||||
#include "session.h"
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param);
|
||||
static void cli_dropbear_log(int priority, const char* format, va_list param);
|
||||
|
||||
#if defined(DBMULTI_dbclient) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_dbclient) && defined(DROPBEAR_MULTI)
|
||||
int cli_main(int argc, char ** argv) {
|
||||
#else
|
||||
int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
int sock;
|
||||
char* error = NULL;
|
||||
@ -12,6 +23,9 @@ int main(int argc, char ** argv) {
|
||||
|
||||
cli_getopts(argc, argv);
|
||||
|
||||
TRACE(("user='%s' host='%s' port='%s'", cli_opts.username,
|
||||
cli_opts.remotehost, cli_opts.remoteport));
|
||||
|
||||
sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||
0, &error);
|
||||
|
||||
@ -23,7 +37,7 @@ int main(int argc, char ** argv) {
|
||||
len = strlen(cli_opts.remotehost);
|
||||
len += 10; /* 16 bit port and leeway*/
|
||||
hostandport = (char*)m_malloc(len);
|
||||
snprintf(hostandport, len, "%s%d",
|
||||
snprintf(hostandport, len, "%s:%s",
|
||||
cli_opts.remotehost, cli_opts.remoteport);
|
||||
|
||||
cli_session(sock, hostandport);
|
||||
@ -31,3 +45,34 @@ int main(int argc, char ** argv) {
|
||||
/* not reached */
|
||||
return -1;
|
||||
}
|
||||
#endif /* DBMULTI stuff */
|
||||
|
||||
static void cli_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
|
||||
char fmtbuf[300];
|
||||
|
||||
if (!sessinitdone) {
|
||||
snprintf(fmtbuf, sizeof(fmtbuf), "exited: %s",
|
||||
format);
|
||||
} else {
|
||||
snprintf(fmtbuf, sizeof(fmtbuf),
|
||||
"connection to %s@%s:%s exited: %s",
|
||||
cli_opts.username, cli_opts.remotehost,
|
||||
cli_opts.remoteport, format);
|
||||
}
|
||||
|
||||
_dropbear_log(LOG_INFO, fmtbuf, param);
|
||||
|
||||
common_session_cleanup();
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static void cli_dropbear_log(int priority, const char* format, va_list param) {
|
||||
|
||||
char printbuf[1024];
|
||||
|
||||
vsnprintf(printbuf, sizeof(printbuf), format, param);
|
||||
|
||||
fprintf(stderr, "Dropbear: %s\n", printbuf);
|
||||
|
||||
}
|
||||
|
62
cli-service.c
Normal file
62
cli-service.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "includes.h"
|
||||
#include "service.h"
|
||||
#include "dbutil.h"
|
||||
#include "packet.h"
|
||||
#include "buffer.h"
|
||||
#include "session.h"
|
||||
#include "ssh.h"
|
||||
|
||||
void send_msg_service_request(char* servicename) {
|
||||
|
||||
TRACE(("enter send_msg_service_request: servicename='%s'", servicename));
|
||||
|
||||
CHECKCLEARTOWRITE();
|
||||
|
||||
buf_putbyte(ses.payload, SSH_MSG_SERVICE_REQUEST);
|
||||
buf_putstring(ses.payload, servicename, strlen(servicename));
|
||||
|
||||
encrypt_packet();
|
||||
TRACE(("leave send_msg_service_request"));
|
||||
}
|
||||
|
||||
/* This just sets up the state variables right for the main client session loop
|
||||
* to deal with */
|
||||
void recv_msg_service_accept() {
|
||||
|
||||
unsigned char* servicename;
|
||||
unsigned int len;
|
||||
|
||||
TRACE(("enter recv_msg_service_accept"));
|
||||
|
||||
servicename = buf_getstring(ses.payload, &len);
|
||||
|
||||
/* ssh-userauth */
|
||||
if (cli_ses.state = SERVICE_AUTH_REQ_SENT
|
||||
&& len == SSH_SERVICE_USERAUTH_LEN
|
||||
&& strncmp(SSH_SERVICE_USERAUTH, servicename, len) == 0) {
|
||||
|
||||
cli_ses.state = SERVICE_AUTH_ACCEPT_RCVD;
|
||||
m_free(servicename);
|
||||
TRACE(("leave recv_msg_service_accept: done ssh-userauth"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* ssh-connection */
|
||||
if (cli_ses.state = SERVICE_CONN_REQ_SENT
|
||||
&& len == SSH_SERVICE_CONNECTION_LEN
|
||||
&& strncmp(SSH_SERVICE_CONNECTION, servicename, len) == 0) {
|
||||
|
||||
if (ses.authstate.authdone != 1) {
|
||||
dropbear_exit("request for connection before auth");
|
||||
}
|
||||
|
||||
cli_ses.state = SERVICE_CONN_ACCEPT_RCVD;
|
||||
m_free(servicename);
|
||||
TRACE(("leave recv_msg_service_accept: done ssh-connection"));
|
||||
return;
|
||||
}
|
||||
|
||||
dropbear_exit("unrecognised service accept");
|
||||
/* m_free(servicename); not reached */
|
||||
|
||||
}
|
@ -8,9 +8,11 @@
|
||||
#include "tcpfwd-remote.h"
|
||||
#include "channel.h"
|
||||
#include "random.h"
|
||||
#include "service.h"
|
||||
|
||||
static void cli_remoteclosed();
|
||||
static void cli_sessionloop();
|
||||
static void cli_session_init();
|
||||
|
||||
struct clientsession cli_ses; /* GLOBAL */
|
||||
|
||||
@ -28,6 +30,8 @@ static const packettype cli_packettypes[] = {
|
||||
{SSH_MSG_CHANNEL_CLOSE, recv_msg_channel_close},
|
||||
{SSH_MSG_CHANNEL_OPEN_CONFIRMATION, recv_msg_channel_open_confirmation},
|
||||
{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
|
||||
{SSH_MSG_USERAUTH_FAILURE, recv_msg_userauth_failure},
|
||||
{SSH_MSG_USERAUTH_SUCCESS, recv_msg_userauth_success},
|
||||
{0, 0} /* End */
|
||||
};
|
||||
|
||||
@ -37,6 +41,7 @@ static const struct ChanType *cli_chantypes[] = {
|
||||
* that forwarding */
|
||||
NULL /* Null termination */
|
||||
};
|
||||
|
||||
void cli_session(int sock, char* remotehost) {
|
||||
|
||||
crypto_init();
|
||||
@ -44,11 +49,9 @@ void cli_session(int sock, char* remotehost) {
|
||||
|
||||
chaninitialise(cli_chantypes);
|
||||
|
||||
/* For printing "remote host closed" for the user */
|
||||
session_remoteclosed = cli_remoteclosed;
|
||||
|
||||
/* packet handlers */
|
||||
ses.packettypes = cli_packettypes;
|
||||
/* Set up cli_ses vars */
|
||||
cli_session_init();
|
||||
|
||||
/* Ready to go */
|
||||
sessinitdone = 1;
|
||||
@ -66,27 +69,86 @@ void cli_session(int sock, char* remotehost) {
|
||||
|
||||
/* Not reached */
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void cli_session_init() {
|
||||
|
||||
cli_ses.state = STATE_NOTHING;
|
||||
cli_ses.kex_state = KEX_NOTHING;
|
||||
|
||||
/* For printing "remote host closed" for the user */
|
||||
ses.remoteclosed = cli_remoteclosed;
|
||||
ses.buf_match_algo = cli_buf_match_algo;
|
||||
|
||||
/* packet handlers */
|
||||
ses.packettypes = cli_packettypes;
|
||||
}
|
||||
|
||||
/* This function drives the progress of the session - it initiates KEX,
|
||||
* service, userauth and channel requests */
|
||||
static void cli_sessionloop() {
|
||||
|
||||
TRACE(("enter cli_sessionloop"));
|
||||
|
||||
if (cli_ses.kex_state == KEX_NOTHING && ses.kexstate.recvkexinit) {
|
||||
cli_ses.state = KEXINIT_RCVD;
|
||||
}
|
||||
|
||||
if (cli_ses.state == KEXINIT_RCVD) {
|
||||
|
||||
/* We initiate the KEXDH. If DH wasn't the correct type, the KEXINIT
|
||||
* negotiation would have failed. */
|
||||
send_msg_kexdh_init();
|
||||
cli_ses.kex_state = KEXDH_INIT_SENT;
|
||||
TRACE(("leave cli_sessionloop: done with KEXINIT_RCVD"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* A KEX has finished, so we should go back to our KEX_NOTHING state */
|
||||
if (cli_ses.kex_state != KEX_NOTHING && ses.kexstate.recvkexinit == 0
|
||||
&& ses.kexstate.sentkexinit == 0) {
|
||||
cli_ses.kex_state = KEX_NOTHING;
|
||||
}
|
||||
|
||||
/* We shouldn't do anything else if a KEX is in progress */
|
||||
if (cli_ses.kex_state != KEX_NOTHING) {
|
||||
TRACE(("leave cli_sessionloop: kex_state != KEX_NOTHING"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We should exit if we haven't donefirstkex: we shouldn't reach here
|
||||
* in normal operation */
|
||||
if (ses.kexstate.donefirstkex == 0) {
|
||||
TRACE(("XXX XXX might be bad! leave cli_sessionloop: haven't donefirstkex"));
|
||||
}
|
||||
|
||||
switch (cli_ses.state) {
|
||||
|
||||
KEXINIT_RCVD:
|
||||
/* We initiate the KEX. If DH wasn't the correct type, the KEXINIT
|
||||
* negotiation would have failed. */
|
||||
send_msg_kexdh_init();
|
||||
cli_ses.state = KEXDH_INIT_SENT;
|
||||
break;
|
||||
case STATE_NOTHING:
|
||||
/* We've got the transport layer sorted, we now need to request
|
||||
* userauth */
|
||||
send_msg_service_request(SSH_SERVICE_USERAUTH);
|
||||
cli_ses.state = SERVICE_AUTH_REQ_SENT;
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
/* userauth code */
|
||||
case SERVICE_AUTH_ACCEPT_RCVD:
|
||||
cli_get_user();
|
||||
cli_auth_getmethods();
|
||||
cli_ses.state = USERAUTH_METHODS_SENT;
|
||||
return;
|
||||
|
||||
case USERAUTH_FAIL_RCVD:
|
||||
cli_auth_try();
|
||||
return;
|
||||
|
||||
/* XXX more here needed */
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (cli_ses.donefirstkex && !cli_ses.authdone) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -97,5 +159,5 @@ static void cli_remoteclosed() {
|
||||
* already sent/received disconnect message(s) ??? */
|
||||
close(ses.sock);
|
||||
ses.sock = -1;
|
||||
dropbear_exit("%s closed the connection", ses.remotehost);
|
||||
dropbear_exit("remote closed the connection");
|
||||
}
|
||||
|
42
common-kex.c
42
common-kex.c
@ -5,7 +5,7 @@
|
||||
* This code is copied from the larger file "kex.c"
|
||||
* some functions are verbatim, others are generalized --mihnea
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* Copyright (c) 2002-2004 Matt Johnston
|
||||
* Portions Copyright (c) 2004 by Mihnea Stoenescu
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -54,10 +54,12 @@ const unsigned char dh_p_val[] = {
|
||||
|
||||
const int DH_G_VAL = 2;
|
||||
|
||||
static void kexinitialise();
|
||||
static void gen_new_keys();
|
||||
#ifndef DISABLE_ZLIB
|
||||
static void gen_new_zstreams();
|
||||
#endif
|
||||
static void read_kex_algos();
|
||||
/* helper function for gen_new_keys */
|
||||
static void hashkeys(unsigned char *out, int outlen,
|
||||
const hash_state * hs, unsigned const char X);
|
||||
@ -145,6 +147,7 @@ void send_msg_newkeys() {
|
||||
kexinitialise(); /* we've finished with this kex */
|
||||
TRACE((" -> DATAALLOWED=1"));
|
||||
ses.dataallowed = 1; /* we can send other packets again now */
|
||||
ses.kexstate.donefirstkex = 1;
|
||||
} else {
|
||||
ses.kexstate.sentnewkeys = 1;
|
||||
TRACE(("SENTNEWKEYS=1"));
|
||||
@ -168,6 +171,7 @@ void recv_msg_newkeys() {
|
||||
kexinitialise(); /* we've finished with this kex */
|
||||
TRACE((" -> DATAALLOWED=1"));
|
||||
ses.dataallowed = 1; /* we can send other packets again now */
|
||||
ses.kexstate.donefirstkex = 1;
|
||||
} else {
|
||||
TRACE(("RECVNEWKEYS=1"));
|
||||
ses.kexstate.recvnewkeys = 1;
|
||||
@ -177,8 +181,15 @@ void recv_msg_newkeys() {
|
||||
}
|
||||
|
||||
|
||||
/* Duplicated verbatim from kex.c --mihnea */
|
||||
void kexinitialise() {
|
||||
/* Set up the kex for the first time */
|
||||
void kexfirstinitialise() {
|
||||
|
||||
ses.kexstate.donefirstkex = 0;
|
||||
kexinitialise();
|
||||
}
|
||||
|
||||
/* Reset the kex state, ready for a new negotiation */
|
||||
static void kexinitialise() {
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
@ -404,7 +415,7 @@ void recv_msg_kexinit() {
|
||||
#ifdef DROPBEAR_CLIENT
|
||||
|
||||
/* read the peer's choice of algos */
|
||||
read_kex_algos(cli_buf_match_algo);
|
||||
read_kex_algos();
|
||||
|
||||
/* V_C, the client's version string (CR and NL excluded) */
|
||||
buf_putstring(ses.kexhashbuf,
|
||||
@ -423,14 +434,13 @@ void recv_msg_kexinit() {
|
||||
buf_getptr(ses.payload, ses.payload->len),
|
||||
ses.payload->len);
|
||||
|
||||
cli_ses.state = KEXINIT_RCVD;
|
||||
#endif
|
||||
} else {
|
||||
/* SERVER */
|
||||
#ifdef DROPBEAR_SERVER
|
||||
|
||||
/* read the peer's choice of algos */
|
||||
read_kex_algos(svr_buf_match_algo);
|
||||
read_kex_algos();
|
||||
/* V_C, the client's version string (CR and NL excluded) */
|
||||
buf_putstring(ses.kexhashbuf,
|
||||
ses.remoteident, strlen((char*)ses.remoteident));
|
||||
@ -583,9 +593,7 @@ void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
||||
|
||||
/* read the other side's algo list. buf_match_algo is a callback to match
|
||||
* algos for the client or server. */
|
||||
void read_kex_algos(
|
||||
algo_type*(buf_match_algo)(buffer*buf, algo_type localalgos[],
|
||||
int *goodguess)) {
|
||||
static void read_kex_algos() {
|
||||
|
||||
algo_type * algo;
|
||||
char * erralgo = NULL;
|
||||
@ -599,7 +607,7 @@ void read_kex_algos(
|
||||
ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
|
||||
|
||||
/* kex_algorithms */
|
||||
algo = buf_match_algo(ses.payload, sshkex, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshkex, &goodguess);
|
||||
allgood &= goodguess;
|
||||
if (algo == NULL) {
|
||||
erralgo = "kex";
|
||||
@ -608,7 +616,7 @@ void read_kex_algos(
|
||||
ses.newkeys->algo_kex = algo->val;
|
||||
|
||||
/* server_host_key_algorithms */
|
||||
algo = buf_match_algo(ses.payload, sshhostkey, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshhostkey, &goodguess);
|
||||
allgood &= goodguess;
|
||||
if (algo == NULL) {
|
||||
erralgo = "hostkey";
|
||||
@ -617,7 +625,7 @@ void read_kex_algos(
|
||||
ses.newkeys->algo_hostkey = algo->val;
|
||||
|
||||
/* encryption_algorithms_client_to_server */
|
||||
algo = buf_match_algo(ses.payload, sshciphers, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
|
||||
if (algo == NULL) {
|
||||
erralgo = "enc c->s";
|
||||
goto error;
|
||||
@ -625,7 +633,7 @@ void read_kex_algos(
|
||||
ses.newkeys->recv_algo_crypt = (struct dropbear_cipher*)algo->data;
|
||||
|
||||
/* encryption_algorithms_server_to_client */
|
||||
algo = buf_match_algo(ses.payload, sshciphers, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshciphers, &goodguess);
|
||||
if (algo == NULL) {
|
||||
erralgo = "enc s->c";
|
||||
goto error;
|
||||
@ -633,7 +641,7 @@ void read_kex_algos(
|
||||
ses.newkeys->trans_algo_crypt = (struct dropbear_cipher*)algo->data;
|
||||
|
||||
/* mac_algorithms_client_to_server */
|
||||
algo = buf_match_algo(ses.payload, sshhashes, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
|
||||
if (algo == NULL) {
|
||||
erralgo = "mac c->s";
|
||||
goto error;
|
||||
@ -641,7 +649,7 @@ void read_kex_algos(
|
||||
ses.newkeys->recv_algo_mac = (struct dropbear_hash*)algo->data;
|
||||
|
||||
/* mac_algorithms_server_to_client */
|
||||
algo = buf_match_algo(ses.payload, sshhashes, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshhashes, &goodguess);
|
||||
if (algo == NULL) {
|
||||
erralgo = "mac s->c";
|
||||
goto error;
|
||||
@ -649,7 +657,7 @@ void read_kex_algos(
|
||||
ses.newkeys->trans_algo_mac = (struct dropbear_hash*)algo->data;
|
||||
|
||||
/* compression_algorithms_client_to_server */
|
||||
algo = buf_match_algo(ses.payload, sshcompress, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
|
||||
if (algo == NULL) {
|
||||
erralgo = "comp c->s";
|
||||
goto error;
|
||||
@ -657,7 +665,7 @@ void read_kex_algos(
|
||||
ses.newkeys->recv_algo_comp = algo->val;
|
||||
|
||||
/* compression_algorithms_server_to_client */
|
||||
algo = buf_match_algo(ses.payload, sshcompress, &goodguess);
|
||||
algo = ses.buf_match_algo(ses.payload, sshcompress, &goodguess);
|
||||
if (algo == NULL) {
|
||||
erralgo = "comp s->c";
|
||||
goto error;
|
||||
|
28
common-runopts.c
Normal file
28
common-runopts.c
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Dropbear - a SSH2 server
|
||||
*
|
||||
* Copyright (c) 2002,2003 Matt Johnston
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE. */
|
||||
|
||||
#include "includes.h"
|
||||
#include "runopts.h"
|
||||
|
||||
runopts opts; /* GLOBAL */
|
@ -45,8 +45,6 @@ int sessinitdone = 0; /* GLOBAL */
|
||||
/* this is set when we get SIGINT or SIGTERM, the handler is in main.c */
|
||||
int exitflag = 0; /* GLOBAL */
|
||||
|
||||
void(*session_remoteclosed)() = NULL;
|
||||
|
||||
|
||||
static void checktimeouts();
|
||||
static int ident_readln(int fd, char* buf, int count);
|
||||
@ -63,7 +61,7 @@ void common_session_init(int sock, char* remotehost) {
|
||||
|
||||
ses.connecttimeout = 0;
|
||||
|
||||
kexinitialise(); /* initialise the kex state */
|
||||
kexfirstinitialise(); /* initialise the kex state */
|
||||
chaninitialise(); /* initialise the channel state */
|
||||
|
||||
ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN);
|
||||
@ -104,8 +102,6 @@ void common_session_init(int sock, char* remotehost) {
|
||||
ses.dh_K = NULL;
|
||||
ses.remoteident = NULL;
|
||||
|
||||
ses.authdone = 0;
|
||||
|
||||
ses.chantypes = NULL;
|
||||
|
||||
ses.allowprivport = 0;
|
||||
|
@ -19,6 +19,11 @@ int main(int argc, char ** argv) {
|
||||
return dropbear_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dbclient
|
||||
if (strcmp(progname, "dbclient") == 0) {
|
||||
return cli_main(argc, argv);
|
||||
}
|
||||
#endif
|
||||
#ifdef DBMULTI_dropbearkey
|
||||
if (strcmp(progname, "dropbearkey") == 0) {
|
||||
return dropbearkey_main(argc, argv);
|
||||
@ -41,6 +46,9 @@ int main(int argc, char ** argv) {
|
||||
#ifdef DBMULTI_dropbear
|
||||
"'dropbear' - the Dropbear server\n"
|
||||
#endif
|
||||
#ifdef DBMULTI_dbclient
|
||||
"'dbclient' - the Dropbear client\n"
|
||||
#endif
|
||||
#ifdef DBMULTI_dropbearkey
|
||||
"'dropbearkey' - the key generator\n"
|
||||
#endif
|
||||
|
2
debug.h
2
debug.h
@ -36,7 +36,7 @@
|
||||
/* Define this to print trace statements - very verbose */
|
||||
/* Caution: Don't use this in an unfriendly environment (ie unfirewalled),
|
||||
* since the printing does not sanitise strings etc */
|
||||
//#define DEBUG_TRACE
|
||||
#define DEBUG_TRACE
|
||||
|
||||
/* All functions writing to the cleartext payload buffer call
|
||||
* CHECKCLEARTOWRITE() before writing. This is only really useful if you're
|
||||
|
9
kex.h
9
kex.h
@ -32,15 +32,11 @@ void send_msg_kexinit();
|
||||
void recv_msg_kexinit();
|
||||
void send_msg_newkeys();
|
||||
void recv_msg_newkeys();
|
||||
void kexinitialise();
|
||||
void kexfirstinitialise();
|
||||
void gen_kexdh_vals(mp_int *dh_pub, mp_int *dh_priv);
|
||||
void kexdh_comb_key(mp_int *dh_pub_us, mp_int *dh_priv, mp_int *dh_pub_them,
|
||||
sign_key *hostkey);
|
||||
|
||||
void read_kex_algos(
|
||||
algo_type*(buf_match_algo)(buffer*buf, algo_type localalgos[],
|
||||
int *goodguess));
|
||||
|
||||
void recv_msg_kexdh_init(); // server
|
||||
|
||||
void send_msg_kexdh_init(); // client
|
||||
@ -59,6 +55,9 @@ struct KEXState {
|
||||
unsigned sentnewkeys : 1; /* set once we've send/recv'ed MSG_NEWKEYS*/
|
||||
unsigned recvnewkeys : 1;
|
||||
|
||||
unsigned donefirstkex : 1; /* Set to 1 after the first kex has completed,
|
||||
ie the transport layer has been set up */
|
||||
|
||||
long lastkextime; /* time of the last kex */
|
||||
unsigned int datatrans; /* data transmitted since last kex */
|
||||
unsigned int datarecv; /* data received since last kex */
|
||||
|
23
options.h
23
options.h
@ -29,8 +29,6 @@
|
||||
* Define compile-time options below - the "#ifndef DROPBEAR_XXX .... #endif"
|
||||
* parts are to allow for commandline -DDROPBEAR_XXX options etc.
|
||||
******************************************************************/
|
||||
#define DROPBEAR_SERVER
|
||||
//#define DROPBEAR_CLIENT
|
||||
|
||||
#ifndef DROPBEAR_PORT
|
||||
#define DROPBEAR_PORT 22
|
||||
@ -48,7 +46,6 @@
|
||||
* perhaps 20% slower for pubkey operations (it is probably worth experimenting
|
||||
* if you want to use this) */
|
||||
/*#define NO_FAST_EXPTMOD*/
|
||||
#define DROPBEAR_SMALL_CODE
|
||||
|
||||
/* Enable X11 Forwarding */
|
||||
#define ENABLE_X11FWD
|
||||
@ -114,7 +111,7 @@
|
||||
/* Authentication types to enable, at least one required.
|
||||
RFC Draft requires pubkey auth, and recommends password */
|
||||
#define DROPBEAR_PASSWORD_AUTH
|
||||
#define DROPBEAR_PUBKEY_AUTH
|
||||
//#define DROPBEAR_PUBKEY_AUTH
|
||||
|
||||
/* Random device to use - you must specify _one only_.
|
||||
* DEV_RANDOM is recommended on hosts with a good /dev/urandom, otherwise use
|
||||
@ -162,20 +159,8 @@
|
||||
/* This is used by the scp binary when used as a client binary */
|
||||
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
|
||||
|
||||
/* Multi-purpose binary configuration - if you want to make the combined
|
||||
* binary, first define DROPBEAR_MULTI, and then define which of the three
|
||||
* components you want. You should then compile Dropbear with
|
||||
* "make clean; make dropbearmulti". You'll need to install the binary
|
||||
* manually, see MULTI for details */
|
||||
|
||||
/* #define DROPBEAR_MULTI */
|
||||
|
||||
/* The three multi binaries: dropbear, dropbearkey, dropbearconvert
|
||||
* Comment out these if you don't want some of them */
|
||||
#define DBMULTI_DROPBEAR
|
||||
#define DBMULTI_KEY
|
||||
#define DBMULTI_CONVERT
|
||||
|
||||
/* Multi-purpose binary configuration has now moved. Look at the top
|
||||
* of the Makefile for instructions, or INSTALL */
|
||||
|
||||
/*******************************************************************
|
||||
* You shouldn't edit below here unless you know you need to.
|
||||
@ -246,7 +231,7 @@
|
||||
#define DROPBEAR_COMP_ZLIB 1
|
||||
|
||||
/* Required for pubkey auth */
|
||||
#ifdef DROPBEAR_PUBKEY_AUTH
|
||||
#if defined(DROPBEAR_PUBKEY_AUTH) || defined(DROPBEAR_CLIENT)
|
||||
#define DROPBEAR_SIGNKEY_VERIFY
|
||||
#endif
|
||||
|
||||
|
6
packet.c
6
packet.c
@ -73,7 +73,7 @@ void write_packet() {
|
||||
}
|
||||
|
||||
if (written == 0) {
|
||||
session_remoteclosed();
|
||||
ses.remoteclosed();
|
||||
}
|
||||
|
||||
if (written == len) {
|
||||
@ -122,7 +122,7 @@ void read_packet() {
|
||||
len = read(ses.sock, buf_getptr(ses.readbuf, maxlen), maxlen);
|
||||
|
||||
if (len == 0) {
|
||||
session_remoteclosed();
|
||||
ses.remoteclosed();
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
@ -171,7 +171,7 @@ static void read_packet_init() {
|
||||
len = read(ses.sock, buf_getwriteptr(ses.readbuf, maxlen),
|
||||
maxlen);
|
||||
if (len == 0) {
|
||||
session_remoteclosed();
|
||||
ses.remoteclosed();
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EINTR) {
|
||||
|
@ -79,7 +79,11 @@ void svr_getopts(int argc, char ** argv);
|
||||
/* Uncompleted XXX matt */
|
||||
typedef struct cli_runopts {
|
||||
|
||||
int todo;
|
||||
char *remotehost;
|
||||
char *remoteport;
|
||||
|
||||
char *username;
|
||||
/* XXX TODO */
|
||||
|
||||
} cli_runopts;
|
||||
|
||||
|
7
scp.c
7
scp.c
@ -229,8 +229,12 @@ void tolocal(int, char *[]);
|
||||
void toremote(char *, int, char *[]);
|
||||
void usage(void);
|
||||
|
||||
int
|
||||
#if defined(DBMULTI_scp) || !defined(DROPBEAR_MULTI)
|
||||
#if defined(DBMULTI_scp) && defined(DROPBEAR_MULTI)
|
||||
int scp_main(int argc, char **argv)
|
||||
#else
|
||||
main(int argc, char **argv)
|
||||
#endif
|
||||
{
|
||||
int ch, fflag, tflag, status;
|
||||
double speed;
|
||||
@ -379,6 +383,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
exit(errs != 0);
|
||||
}
|
||||
#endif /* DBMULTI stuff */
|
||||
|
||||
void
|
||||
toremote(char *targ, int argc, char **argv)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef _SERVICE_H_
|
||||
#define _SERVICE_H_
|
||||
|
||||
void recv_msg_service_request();
|
||||
void recv_msg_service_request(); /* Server */
|
||||
void send_msg_service_request(); /* Client */
|
||||
|
||||
#endif /* _SERVICE_H_ */
|
||||
|
38
session.h
38
session.h
@ -45,7 +45,6 @@ void common_session_cleanup();
|
||||
void checktimeouts();
|
||||
void session_identification();
|
||||
|
||||
extern void(*session_remoteclosed)();
|
||||
|
||||
/* Server */
|
||||
void svr_session(int sock, int childpipe, char *remotehost);
|
||||
@ -135,13 +134,18 @@ struct sshsession {
|
||||
buffer* transkexinit; /* the kexinit packet we send should be kept so we
|
||||
can add it to the hash when generating keys */
|
||||
|
||||
algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[],
|
||||
int *goodguess); /* The function to use to choose which algorithm
|
||||
to use from the ones presented by the remote
|
||||
side. Is specific to the client/server mode,
|
||||
hence the function-pointer callback.*/
|
||||
|
||||
unsigned char authdone; /* Indicates when authentication has been
|
||||
completed. This applies to both client and
|
||||
server - in the server it gets set to 1 when
|
||||
authentication is successful, in the client it
|
||||
is set when the server has told us that auth
|
||||
succeeded */
|
||||
void(*remoteclosed)(); /* A callback to handle closure of the
|
||||
remote connection */
|
||||
|
||||
|
||||
struct AuthState authstate; /* Common amongst client and server, since most
|
||||
struct elements are common */
|
||||
|
||||
/* Channel related */
|
||||
struct Channel ** channels; /* these pointers may be null */
|
||||
@ -165,7 +169,6 @@ struct serversession {
|
||||
/* Server specific options */
|
||||
int childpipe; /* kept open until we successfully authenticate */
|
||||
/* userauth */
|
||||
struct AuthState authstate;
|
||||
|
||||
struct ChildPid * childpids; /* array of mappings childpid<->channel */
|
||||
unsigned int childpidsize;
|
||||
@ -173,17 +176,30 @@ struct serversession {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
NOTHING,
|
||||
KEX_NOTHING,
|
||||
KEXINIT_RCVD,
|
||||
KEXDH_INIT_SENT,
|
||||
KEXDH_REPLY_RCVD,
|
||||
KEXDONE,
|
||||
|
||||
} cli_kex_state;
|
||||
|
||||
typedef enum {
|
||||
STATE_NOTHING,
|
||||
SERVICE_AUTH_REQ_SENT,
|
||||
SERVICE_AUTH_ACCEPT_RCVD,
|
||||
SERVICE_CONN_REQ_SENT,
|
||||
SERVICE_CONN_ACCEPT_RCVD,
|
||||
USERAUTH_METHODS_SENT,
|
||||
USERAUTH_REQ_SENT,
|
||||
USERAUTH_FAIL_RCVD,
|
||||
|
||||
} cli_state;
|
||||
|
||||
struct clientsession {
|
||||
|
||||
mp_int *dh_e, *dh_x; /* Used during KEX */
|
||||
cli_state state; /* Used to progress the KEX/auth/channelsession etc */
|
||||
cli_kex_state kex_state; /* Used for progressing KEX */
|
||||
cli_state state; /* Used to progress auth/channelsession etc */
|
||||
int something; /* XXX */
|
||||
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
|
||||
|
||||
|
@ -152,8 +152,8 @@ void agentcleanup(struct ChanSess * chansess) {
|
||||
* for themselves */
|
||||
uid = getuid();
|
||||
gid = getgid();
|
||||
if ((setegid(svr_ses.authstate.pw->pw_gid)) < 0 ||
|
||||
(seteuid(svr_ses.authstate.pw->pw_uid)) < 0) {
|
||||
if ((setegid(ses.authstate.pw->pw_gid)) < 0 ||
|
||||
(seteuid(ses.authstate.pw->pw_uid)) < 0) {
|
||||
dropbear_exit("failed to set euid");
|
||||
}
|
||||
|
||||
@ -215,8 +215,8 @@ static int bindagent(int fd, struct ChanSess * chansess) {
|
||||
/* drop to user privs to make the dir/file */
|
||||
uid = getuid();
|
||||
gid = getgid();
|
||||
if ((setegid(svr_ses.authstate.pw->pw_gid)) < 0 ||
|
||||
(seteuid(svr_ses.authstate.pw->pw_uid)) < 0) {
|
||||
if ((setegid(ses.authstate.pw->pw_gid)) < 0 ||
|
||||
(seteuid(ses.authstate.pw->pw_uid)) < 0) {
|
||||
dropbear_exit("failed to set euid");
|
||||
}
|
||||
|
||||
|
72
svr-auth.c
72
svr-auth.c
@ -41,9 +41,9 @@ static int checkusername(unsigned char *username, unsigned int userlen);
|
||||
static void send_msg_userauth_banner();
|
||||
|
||||
/* initialise the first time for a session, resetting all parameters */
|
||||
void authinitialise() {
|
||||
void svr_authinitialise() {
|
||||
|
||||
svr_ses.authstate.failcount = 0;
|
||||
ses.authstate.failcount = 0;
|
||||
authclear();
|
||||
|
||||
}
|
||||
@ -53,17 +53,13 @@ void authinitialise() {
|
||||
* on initialisation */
|
||||
static void authclear() {
|
||||
|
||||
ses.authdone = 0;
|
||||
svr_ses.authstate.pw = NULL;
|
||||
svr_ses.authstate.username = NULL;
|
||||
svr_ses.authstate.printableuser = NULL;
|
||||
svr_ses.authstate.authtypes = 0;
|
||||
memset(&ses.authstate, 0, sizeof(ses.authstate));
|
||||
#ifdef DROPBEAR_PUBKEY_AUTH
|
||||
svr_ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PUBKEY;
|
||||
#endif
|
||||
#ifdef DROPBEAR_PASSWORD_AUTH
|
||||
if (svr_opts.noauthpass) {
|
||||
svr_ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
|
||||
ses.authstate.authtypes |= AUTH_TYPE_PASSWORD;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -103,7 +99,7 @@ void recv_msg_userauth_request() {
|
||||
TRACE(("enter recv_msg_userauth_request"));
|
||||
|
||||
/* ignore packets if auth is already done */
|
||||
if (ses.authdone == 1) {
|
||||
if (ses.authstate.authdone == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -147,12 +143,12 @@ void recv_msg_userauth_request() {
|
||||
|
||||
#ifdef DROPBEAR_PASSWORD_AUTH
|
||||
if (!svr_opts.noauthpass &&
|
||||
!(svr_opts.norootpass && svr_ses.authstate.pw->pw_uid == 0) ) {
|
||||
!(svr_opts.norootpass && ses.authstate.pw->pw_uid == 0) ) {
|
||||
/* user wants to try password auth */
|
||||
if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
|
||||
strncmp(methodname, AUTH_METHOD_PASSWORD,
|
||||
AUTH_METHOD_PASSWORD_LEN) == 0) {
|
||||
passwordauth();
|
||||
svr_auth_password();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -163,7 +159,7 @@ void recv_msg_userauth_request() {
|
||||
if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
|
||||
strncmp(methodname, AUTH_METHOD_PUBKEY,
|
||||
AUTH_METHOD_PUBKEY_LEN) == 0) {
|
||||
pubkeyauth();
|
||||
svr_auth_pubkey();
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
@ -192,21 +188,21 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
|
||||
}
|
||||
|
||||
/* new user or username has changed */
|
||||
if (svr_ses.authstate.username == NULL ||
|
||||
strcmp(username, svr_ses.authstate.username) != 0) {
|
||||
if (ses.authstate.username == NULL ||
|
||||
strcmp(username, ses.authstate.username) != 0) {
|
||||
/* the username needs resetting */
|
||||
if (svr_ses.authstate.username != NULL) {
|
||||
if (ses.authstate.username != NULL) {
|
||||
dropbear_log(LOG_WARNING, "client trying multiple usernames");
|
||||
m_free(svr_ses.authstate.username);
|
||||
m_free(ses.authstate.username);
|
||||
}
|
||||
authclear();
|
||||
svr_ses.authstate.pw = getpwnam((char*)username);
|
||||
svr_ses.authstate.username = m_strdup(username);
|
||||
m_free(svr_ses.authstate.printableuser);
|
||||
ses.authstate.pw = getpwnam((char*)username);
|
||||
ses.authstate.username = m_strdup(username);
|
||||
m_free(ses.authstate.printableuser);
|
||||
}
|
||||
|
||||
/* check that user exists */
|
||||
if (svr_ses.authstate.pw == NULL) {
|
||||
if (ses.authstate.pw == NULL) {
|
||||
TRACE(("leave checkusername: user '%s' doesn't exist", username));
|
||||
dropbear_log(LOG_WARNING,
|
||||
"login attempt for nonexistent user");
|
||||
@ -215,10 +211,10 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
|
||||
}
|
||||
|
||||
/* We can set it once we know its a real user */
|
||||
svr_ses.authstate.printableuser = m_strdup(svr_ses.authstate.pw->pw_name);
|
||||
ses.authstate.printableuser = m_strdup(ses.authstate.pw->pw_name);
|
||||
|
||||
/* check for non-root if desired */
|
||||
if (svr_opts.norootlogin && svr_ses.authstate.pw->pw_uid == 0) {
|
||||
if (svr_opts.norootlogin && ses.authstate.pw->pw_uid == 0) {
|
||||
TRACE(("leave checkusername: root login disabled"));
|
||||
dropbear_log(LOG_WARNING, "root login rejected");
|
||||
send_msg_userauth_failure(0, 1);
|
||||
@ -226,18 +222,18 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
|
||||
}
|
||||
|
||||
/* check for an empty password */
|
||||
if (svr_ses.authstate.pw->pw_passwd[0] == '\0') {
|
||||
if (ses.authstate.pw->pw_passwd[0] == '\0') {
|
||||
TRACE(("leave checkusername: empty pword"));
|
||||
dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected",
|
||||
svr_ses.authstate.printableuser);
|
||||
ses.authstate.printableuser);
|
||||
send_msg_userauth_failure(0, 1);
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
TRACE(("shell is %s", svr_ses.authstate.pw->pw_shell));
|
||||
TRACE(("shell is %s", ses.authstate.pw->pw_shell));
|
||||
|
||||
/* check that the shell is set */
|
||||
usershell = svr_ses.authstate.pw->pw_shell;
|
||||
usershell = ses.authstate.pw->pw_shell;
|
||||
if (usershell[0] == '\0') {
|
||||
/* empty shell in /etc/passwd means /bin/sh according to passwd(5) */
|
||||
usershell = "/bin/sh";
|
||||
@ -258,7 +254,7 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
|
||||
endusershell();
|
||||
TRACE(("no matching shell"));
|
||||
dropbear_log(LOG_WARNING, "user '%s' has invalid shell, rejected",
|
||||
svr_ses.authstate.printableuser);
|
||||
ses.authstate.printableuser);
|
||||
send_msg_userauth_failure(0, 1);
|
||||
return DROPBEAR_FAILURE;
|
||||
|
||||
@ -266,7 +262,7 @@ goodshell:
|
||||
endusershell();
|
||||
TRACE(("matching shell"));
|
||||
|
||||
TRACE(("uid = %d", svr_ses.authstate.pw->pw_uid));
|
||||
TRACE(("uid = %d", ses.authstate.pw->pw_uid));
|
||||
TRACE(("leave checkusername"));
|
||||
return DROPBEAR_SUCCESS;
|
||||
|
||||
@ -290,14 +286,14 @@ void send_msg_userauth_failure(int partial, int incrfail) {
|
||||
/* put a list of allowed types */
|
||||
typebuf = buf_new(30); /* long enough for PUBKEY and PASSWORD */
|
||||
|
||||
if (svr_ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
|
||||
if (ses.authstate.authtypes & AUTH_TYPE_PUBKEY) {
|
||||
buf_putbytes(typebuf, AUTH_METHOD_PUBKEY, AUTH_METHOD_PUBKEY_LEN);
|
||||
if (svr_ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
if (ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
buf_putbyte(typebuf, ',');
|
||||
}
|
||||
}
|
||||
|
||||
if (svr_ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
if (ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
|
||||
buf_putbytes(typebuf, AUTH_METHOD_PASSWORD, AUTH_METHOD_PASSWORD_LEN);
|
||||
}
|
||||
|
||||
@ -311,18 +307,18 @@ void send_msg_userauth_failure(int partial, int incrfail) {
|
||||
|
||||
if (incrfail) {
|
||||
usleep(300000); /* XXX improve this */
|
||||
svr_ses.authstate.failcount++;
|
||||
ses.authstate.failcount++;
|
||||
}
|
||||
|
||||
if (svr_ses.authstate.failcount >= MAX_AUTH_TRIES) {
|
||||
if (ses.authstate.failcount >= MAX_AUTH_TRIES) {
|
||||
char * userstr;
|
||||
/* XXX - send disconnect ? */
|
||||
TRACE(("Max auth tries reached, exiting"));
|
||||
|
||||
if (svr_ses.authstate.printableuser == NULL) {
|
||||
if (ses.authstate.printableuser == NULL) {
|
||||
userstr = "is invalid";
|
||||
} else {
|
||||
userstr = svr_ses.authstate.printableuser;
|
||||
userstr = ses.authstate.printableuser;
|
||||
}
|
||||
dropbear_exit("Max auth tries reached - user %s", userstr);
|
||||
}
|
||||
@ -340,9 +336,9 @@ void send_msg_userauth_success() {
|
||||
buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_SUCCESS);
|
||||
encrypt_packet();
|
||||
|
||||
ses.authdone = 1;
|
||||
ses.authstate.authdone = 1;
|
||||
|
||||
if (svr_ses.authstate.pw->pw_uid == 0) {
|
||||
if (ses.authstate.pw->pw_uid == 0) {
|
||||
ses.allowprivport = 1;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
/* Process a password auth request, sending success or failure messages as
|
||||
* appropriate */
|
||||
void passwordauth() {
|
||||
void svr_auth_password() {
|
||||
|
||||
#ifdef HAVE_SHADOW_H
|
||||
struct spwd *spasswd;
|
||||
@ -47,10 +47,10 @@ void passwordauth() {
|
||||
|
||||
unsigned char changepw;
|
||||
|
||||
passwdcrypt = svr_ses.authstate.pw->pw_passwd;
|
||||
passwdcrypt = ses.authstate.pw->pw_passwd;
|
||||
#ifdef HAVE_SHADOW_H
|
||||
/* get the shadow password if possible */
|
||||
spasswd = getspnam(svr_ses.authstate.pw->pw_name);
|
||||
spasswd = getspnam(ses.authstate.pw->pw_name);
|
||||
if (spasswd != NULL && spasswd->sp_pwdp != NULL) {
|
||||
passwdcrypt = spasswd->sp_pwdp;
|
||||
}
|
||||
@ -66,7 +66,7 @@ void passwordauth() {
|
||||
* in auth.c */
|
||||
if (passwdcrypt[0] == '\0') {
|
||||
dropbear_log(LOG_WARNING, "user '%s' has blank password, rejected",
|
||||
svr_ses.authstate.printableuser);
|
||||
ses.authstate.printableuser);
|
||||
send_msg_userauth_failure(0, 1);
|
||||
return;
|
||||
}
|
||||
@ -92,12 +92,12 @@ void passwordauth() {
|
||||
/* successful authentication */
|
||||
dropbear_log(LOG_NOTICE,
|
||||
"password auth succeeded for '%s'",
|
||||
svr_ses.authstate.printableuser);
|
||||
ses.authstate.printableuser);
|
||||
send_msg_userauth_success();
|
||||
} else {
|
||||
dropbear_log(LOG_WARNING,
|
||||
"bad password attempt for '%s'",
|
||||
svr_ses.authstate.printableuser);
|
||||
ses.authstate.printableuser);
|
||||
send_msg_userauth_failure(0, 1);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ static int getauthline(buffer * line, FILE * authfile);
|
||||
|
||||
/* process a pubkey auth request, sending success or failure message as
|
||||
* appropriate */
|
||||
void pubkeyauth() {
|
||||
void svr_auth_pubkey() {
|
||||
|
||||
unsigned char testkey; /* whether we're just checking if a key is usable */
|
||||
unsigned char* algo = NULL; /* pubkey algo */
|
||||
@ -113,12 +113,12 @@ void pubkeyauth() {
|
||||
signbuf->len) == DROPBEAR_SUCCESS) {
|
||||
dropbear_log(LOG_NOTICE,
|
||||
"pubkey auth succeeded for '%s' with key %s",
|
||||
svr_ses.authstate.printableuser, fp);
|
||||
ses.authstate.printableuser, fp);
|
||||
send_msg_userauth_success();
|
||||
} else {
|
||||
dropbear_log(LOG_WARNING,
|
||||
"pubkey auth bad signature for '%s' with key %s",
|
||||
svr_ses.authstate.printableuser, fp);
|
||||
ses.authstate.printableuser, fp);
|
||||
send_msg_userauth_failure(0, 1);
|
||||
}
|
||||
m_free(fp);
|
||||
@ -178,7 +178,7 @@ static int checkpubkey(unsigned char* algo, unsigned int algolen,
|
||||
if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) {
|
||||
dropbear_log(LOG_WARNING,
|
||||
"pubkey auth attempt with unknown algo for '%s'",
|
||||
svr_ses.authstate.printableuser);
|
||||
ses.authstate.printableuser);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -190,12 +190,12 @@ static int checkpubkey(unsigned char* algo, unsigned int algolen,
|
||||
|
||||
/* we don't need to check pw and pw_dir for validity, since
|
||||
* its been done in checkpubkeyperms. */
|
||||
len = strlen(svr_ses.authstate.pw->pw_dir);
|
||||
len = strlen(ses.authstate.pw->pw_dir);
|
||||
/* allocate max required pathname storage,
|
||||
* = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
|
||||
filename = m_malloc(len + 22);
|
||||
snprintf(filename, len + 22, "%s/.ssh/authorized_keys",
|
||||
svr_ses.authstate.pw->pw_dir);
|
||||
ses.authstate.pw->pw_dir);
|
||||
|
||||
/* open the file */
|
||||
authfile = fopen(filename, "r");
|
||||
@ -352,19 +352,19 @@ static int checkpubkeyperms() {
|
||||
|
||||
TRACE(("enter checkpubkeyperms"));
|
||||
|
||||
assert(svr_ses.authstate.pw);
|
||||
if (svr_ses.authstate.pw->pw_dir == NULL) {
|
||||
assert(ses.authstate.pw);
|
||||
if (ses.authstate.pw->pw_dir == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((len = strlen(svr_ses.authstate.pw->pw_dir)) == 0) {
|
||||
if ((len = strlen(ses.authstate.pw->pw_dir)) == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* allocate max required pathname storage,
|
||||
* = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */
|
||||
filename = m_malloc(len + 22);
|
||||
strncpy(filename, svr_ses.authstate.pw->pw_dir, len+1);
|
||||
strncpy(filename, ses.authstate.pw->pw_dir, len+1);
|
||||
|
||||
/* check ~ */
|
||||
if (checkfileperm(filename) != DROPBEAR_SUCCESS) {
|
||||
@ -406,7 +406,7 @@ static int checkfileperm(char * filename) {
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
/* check ownership - user or root only*/
|
||||
if (filestat.st_uid != svr_ses.authstate.pw->pw_uid
|
||||
if (filestat.st_uid != ses.authstate.pw->pw_uid
|
||||
&& filestat.st_uid != 0) {
|
||||
TRACE(("leave checkfileperm: wrong ownership"));
|
||||
return DROPBEAR_FAILURE;
|
||||
|
@ -239,7 +239,7 @@ static void closechansess(struct Channel *channel) {
|
||||
|
||||
if (chansess->tty) {
|
||||
/* write the utmp/wtmp login record */
|
||||
li = login_alloc_entry(chansess->pid, svr_ses.authstate.username,
|
||||
li = login_alloc_entry(chansess->pid, ses.authstate.username,
|
||||
ses.remotehost, chansess->tty);
|
||||
login_logout(li);
|
||||
login_free_entry(li);
|
||||
@ -425,7 +425,7 @@ static int sessionpty(struct ChanSess * chansess) {
|
||||
dropbear_exit("out of memory"); /* TODO disconnect */
|
||||
}
|
||||
|
||||
pty_setowner(svr_ses.authstate.pw, chansess->tty);
|
||||
pty_setowner(ses.authstate.pw, chansess->tty);
|
||||
pty_change_window_size(chansess->master, chansess->termr, chansess->termc,
|
||||
chansess->termw, chansess->termh);
|
||||
|
||||
@ -683,7 +683,7 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
|
||||
|
||||
/* write the utmp/wtmp login record - must be after changing the
|
||||
* terminal used for stdout with the dup2 above */
|
||||
li= login_alloc_entry(getpid(), svr_ses.authstate.username,
|
||||
li= login_alloc_entry(getpid(), ses.authstate.username,
|
||||
ses.remotehost, chansess->tty);
|
||||
login_login(li);
|
||||
login_free_entry(li);
|
||||
@ -695,10 +695,10 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) {
|
||||
/* don't show the motd if ~/.hushlogin exists */
|
||||
|
||||
/* 11 == strlen("/hushlogin\0") */
|
||||
len = strlen(svr_ses.authstate.pw->pw_dir) + 11;
|
||||
len = strlen(ses.authstate.pw->pw_dir) + 11;
|
||||
|
||||
hushpath = m_malloc(len);
|
||||
snprintf(hushpath, len, "%s/hushlogin", svr_ses.authstate.pw->pw_dir);
|
||||
snprintf(hushpath, len, "%s/hushlogin", ses.authstate.pw->pw_dir);
|
||||
|
||||
if (stat(hushpath, &sb) < 0) {
|
||||
/* more than a screenful is stupid IMHO */
|
||||
@ -808,10 +808,10 @@ static void execchild(struct ChanSess *chansess) {
|
||||
/* We can only change uid/gid as root ... */
|
||||
if (getuid() == 0) {
|
||||
|
||||
if ((setgid(svr_ses.authstate.pw->pw_gid) < 0) ||
|
||||
(initgroups(svr_ses.authstate.pw->pw_name,
|
||||
svr_ses.authstate.pw->pw_gid) < 0) ||
|
||||
(setuid(svr_ses.authstate.pw->pw_uid) < 0)) {
|
||||
if ((setgid(ses.authstate.pw->pw_gid) < 0) ||
|
||||
(initgroups(ses.authstate.pw->pw_name,
|
||||
ses.authstate.pw->pw_gid) < 0) ||
|
||||
(setuid(ses.authstate.pw->pw_uid) < 0)) {
|
||||
dropbear_exit("error changing user");
|
||||
}
|
||||
} else {
|
||||
@ -822,29 +822,29 @@ static void execchild(struct ChanSess *chansess) {
|
||||
* usernames with the same uid, but differing groups, then the
|
||||
* differing groups won't be set (as with initgroups()). The solution
|
||||
* is for the sysadmin not to give out the UID twice */
|
||||
if (getuid() != svr_ses.authstate.pw->pw_uid) {
|
||||
if (getuid() != ses.authstate.pw->pw_uid) {
|
||||
dropbear_exit("couldn't change user as non-root");
|
||||
}
|
||||
}
|
||||
|
||||
/* an empty shell should be interpreted as "/bin/sh" */
|
||||
if (svr_ses.authstate.pw->pw_shell[0] == '\0') {
|
||||
if (ses.authstate.pw->pw_shell[0] == '\0') {
|
||||
usershell = "/bin/sh";
|
||||
} else {
|
||||
usershell = svr_ses.authstate.pw->pw_shell;
|
||||
usershell = ses.authstate.pw->pw_shell;
|
||||
}
|
||||
|
||||
/* set env vars */
|
||||
addnewvar("USER", svr_ses.authstate.pw->pw_name);
|
||||
addnewvar("LOGNAME", svr_ses.authstate.pw->pw_name);
|
||||
addnewvar("HOME", svr_ses.authstate.pw->pw_dir);
|
||||
addnewvar("USER", ses.authstate.pw->pw_name);
|
||||
addnewvar("LOGNAME", ses.authstate.pw->pw_name);
|
||||
addnewvar("HOME", ses.authstate.pw->pw_dir);
|
||||
addnewvar("SHELL", usershell);
|
||||
if (chansess->term != NULL) {
|
||||
addnewvar("TERM", chansess->term);
|
||||
}
|
||||
|
||||
/* change directory */
|
||||
if (chdir(svr_ses.authstate.pw->pw_dir) < 0) {
|
||||
if (chdir(ses.authstate.pw->pw_dir) < 0) {
|
||||
dropbear_exit("error changing directory");
|
||||
}
|
||||
|
||||
|
@ -106,8 +106,8 @@ void svr_getopts(int argc, char ** argv) {
|
||||
opts.nolocaltcp = 0;
|
||||
opts.noremotetcp = 0;
|
||||
/* not yet
|
||||
svr_opts.ipv4 = 1;
|
||||
svr_opts.ipv6 = 1;
|
||||
opts.ipv4 = 1;
|
||||
opts.ipv6 = 1;
|
||||
*/
|
||||
#ifdef DO_MOTD
|
||||
svr_opts.domotd = 1;
|
||||
|
@ -56,7 +56,7 @@ void recv_msg_service_request() {
|
||||
/* ssh-connection */
|
||||
if (len == SSH_SERVICE_CONNECTION_LEN &&
|
||||
(strncmp(SSH_SERVICE_CONNECTION, name, len) == 0)) {
|
||||
if (ses.authdone != 1) {
|
||||
if (ses.authstate.authdone != 1) {
|
||||
dropbear_exit("request for connection before auth");
|
||||
}
|
||||
|
||||
@ -70,7 +70,6 @@ void recv_msg_service_request() {
|
||||
/* TODO this should be a MSG_DISCONNECT */
|
||||
dropbear_exit("unrecognised SSH_MSG_SERVICE_REQUEST");
|
||||
|
||||
TRACE(("leave recv_msg_service_request"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ void svr_session(int sock, int childpipe, char* remotehost) {
|
||||
|
||||
/* Initialise server specific parts of the session */
|
||||
svr_ses.childpipe = childpipe;
|
||||
authinitialise();
|
||||
svr_authinitialise();
|
||||
chaninitialise(svr_chantypes);
|
||||
svr_chansessinitialise();
|
||||
|
||||
@ -90,10 +90,11 @@ void svr_session(int sock, int childpipe, char* remotehost) {
|
||||
ses.connecttimeout = timeout.tv_sec + AUTH_TIMEOUT;
|
||||
|
||||
/* set up messages etc */
|
||||
session_remoteclosed = svr_remoteclosed;
|
||||
ses.remoteclosed = svr_remoteclosed;
|
||||
|
||||
/* packet handlers */
|
||||
ses.packettypes = svr_packettypes;
|
||||
ses.buf_match_algo = svr_buf_match_algo;
|
||||
|
||||
/* We're ready to go now */
|
||||
sessinitdone = 1;
|
||||
@ -123,16 +124,16 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
|
||||
/* before session init */
|
||||
snprintf(fmtbuf, sizeof(fmtbuf),
|
||||
"premature exit: %s", format);
|
||||
} else if (svr_ses.authstate.authdone) {
|
||||
} else if (ses.authstate.authdone) {
|
||||
/* user has authenticated */
|
||||
snprintf(fmtbuf, sizeof(fmtbuf),
|
||||
"exit after auth (%s): %s",
|
||||
svr_ses.authstate.printableuser, format);
|
||||
} else if (svr_ses.authstate.printableuser) {
|
||||
ses.authstate.printableuser, format);
|
||||
} else if (ses.authstate.printableuser) {
|
||||
/* we have a potential user */
|
||||
snprintf(fmtbuf, sizeof(fmtbuf),
|
||||
"exit before auth (user '%s', %d fails): %s",
|
||||
svr_ses.authstate.printableuser, svr_ses.authstate.failcount, format);
|
||||
ses.authstate.printableuser, ses.authstate.failcount, format);
|
||||
} else {
|
||||
/* before userauth */
|
||||
snprintf(fmtbuf, sizeof(fmtbuf),
|
||||
|
Loading…
Reference in New Issue
Block a user