mirror of
http://galexander.org/git/simplesshd.git
synced 2024-11-15 19:48:56 +00:00
313 lines
9.4 KiB
C
313 lines
9.4 KiB
C
|
/*
|
||
|
* 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. */
|
||
|
|
||
|
#ifndef _SESSION_H_
|
||
|
#define _SESSION_H_
|
||
|
|
||
|
#include "includes.h"
|
||
|
#include "options.h"
|
||
|
#include "buffer.h"
|
||
|
#include "signkey.h"
|
||
|
#include "kex.h"
|
||
|
#include "auth.h"
|
||
|
#include "channel.h"
|
||
|
#include "queue.h"
|
||
|
#include "listener.h"
|
||
|
#include "packet.h"
|
||
|
#include "tcpfwd.h"
|
||
|
#include "chansession.h"
|
||
|
#include "dbutil.h"
|
||
|
|
||
|
extern int sessinitdone; /* Is set to 0 somewhere */
|
||
|
extern int exitflag;
|
||
|
|
||
|
void common_session_init(int sock_in, int sock_out);
|
||
|
void session_loop(void(*loophandler)());
|
||
|
void session_cleanup();
|
||
|
void send_session_identification();
|
||
|
void send_msg_ignore();
|
||
|
void ignore_recv_response();
|
||
|
|
||
|
void update_channel_prio();
|
||
|
|
||
|
const char* get_user_shell();
|
||
|
void fill_passwd(const char* username);
|
||
|
|
||
|
/* Server */
|
||
|
void svr_session(int sock, int childpipe);
|
||
|
void svr_dropbear_exit(int exitcode, const char* format, va_list param) ATTRIB_NORETURN;
|
||
|
void svr_dropbear_log(int priority, const char* format, va_list param);
|
||
|
|
||
|
/* Client */
|
||
|
void cli_session(int sock_in, int sock_out);
|
||
|
void cleantext(unsigned char* dirtytext);
|
||
|
|
||
|
/* crypto parameters that are stored individually for transmit and receive */
|
||
|
struct key_context_directional {
|
||
|
const struct dropbear_cipher *algo_crypt;
|
||
|
const struct dropbear_cipher_mode *crypt_mode;
|
||
|
const struct dropbear_hash *algo_mac;
|
||
|
int hash_index; /* lookup for libtomcrypt */
|
||
|
int algo_comp; /* compression */
|
||
|
#ifndef DISABLE_ZLIB
|
||
|
z_streamp zstream;
|
||
|
#endif
|
||
|
/* actual keys */
|
||
|
union {
|
||
|
symmetric_CBC cbc;
|
||
|
#ifdef DROPBEAR_ENABLE_CTR_MODE
|
||
|
symmetric_CTR ctr;
|
||
|
#endif
|
||
|
} cipher_state;
|
||
|
unsigned char mackey[MAX_MAC_LEN];
|
||
|
int valid;
|
||
|
};
|
||
|
|
||
|
struct key_context {
|
||
|
|
||
|
struct key_context_directional recv;
|
||
|
struct key_context_directional trans;
|
||
|
|
||
|
const struct dropbear_kex *algo_kex;
|
||
|
int algo_hostkey;
|
||
|
|
||
|
int allow_compress; /* whether compression has started (useful in
|
||
|
zlib@openssh.com delayed compression case) */
|
||
|
};
|
||
|
|
||
|
struct packetlist;
|
||
|
struct packetlist {
|
||
|
struct packetlist *next;
|
||
|
buffer * payload;
|
||
|
};
|
||
|
|
||
|
struct sshsession {
|
||
|
|
||
|
/* Is it a client or server? */
|
||
|
unsigned char isserver;
|
||
|
|
||
|
int sock_in;
|
||
|
int sock_out;
|
||
|
|
||
|
/* remotehost will be initially NULL as we delay
|
||
|
* reading the remote version string. it will be set
|
||
|
* by the time any recv_() packet methods are called */
|
||
|
unsigned char *remoteident;
|
||
|
|
||
|
int maxfd; /* the maximum file descriptor to check with select() */
|
||
|
|
||
|
|
||
|
/* Packet buffers/values etc */
|
||
|
buffer *writepayload; /* Unencrypted payload to write - this is used
|
||
|
throughout the code, as handlers fill out this
|
||
|
buffer with the packet to send. */
|
||
|
struct Queue writequeue; /* A queue of encrypted packets to send */
|
||
|
buffer *readbuf; /* From the wire, decrypted in-place */
|
||
|
buffer *payload; /* Post-decompression, the actual SSH packet */
|
||
|
unsigned int transseq, recvseq; /* Sequence IDs */
|
||
|
|
||
|
/* Packet-handling flags */
|
||
|
const packettype * packettypes; /* Packet handler mappings for this
|
||
|
session, see process-packet.c */
|
||
|
|
||
|
unsigned dataallowed : 1; /* whether we can send data packets or we are in
|
||
|
the middle of a KEX or something */
|
||
|
|
||
|
unsigned char requirenext; /* byte indicating what packets we require next,
|
||
|
or 0x00 for any. */
|
||
|
|
||
|
unsigned char ignorenext; /* whether to ignore the next packet,
|
||
|
used for kex_follows stuff */
|
||
|
|
||
|
unsigned char lastpacket; /* What the last received packet type was */
|
||
|
|
||
|
int signal_pipe[2]; /* stores endpoints of a self-pipe used for
|
||
|
race-free signal handling */
|
||
|
|
||
|
/* time of the last packet send/receive, for keepalive. Not real-world clock */
|
||
|
time_t last_packet_time_keepalive_sent;
|
||
|
time_t last_packet_time_keepalive_recv;
|
||
|
time_t last_packet_time_any_sent;
|
||
|
|
||
|
time_t last_packet_time_idle; /* time of the last packet transmission or receive, for
|
||
|
idle timeout purposes so ignores SSH_MSG_IGNORE
|
||
|
or responses to keepalives. Not real-world clock */
|
||
|
|
||
|
|
||
|
/* KEX/encryption related */
|
||
|
struct KEXState kexstate;
|
||
|
struct key_context *keys;
|
||
|
struct key_context *newkeys;
|
||
|
buffer *session_id; /* this is the hash from the first kex */
|
||
|
/* The below are used temporarily during kex, are freed after use */
|
||
|
mp_int * dh_K; /* SSH_MSG_KEXDH_REPLY and sending SSH_MSH_NEWKEYS */
|
||
|
buffer *hash; /* the session hash */
|
||
|
buffer* kexhashbuf; /* session hash buffer calculated from various packets*/
|
||
|
buffer* transkexinit; /* the kexinit packet we send should be kept so we
|
||
|
can add it to the hash when generating keys */
|
||
|
|
||
|
/* Enables/disables compression */
|
||
|
algo_type *compress_algos;
|
||
|
|
||
|
/* a list of queued replies that should be sent after a KEX has
|
||
|
concluded (ie, while dataallowed was unset)*/
|
||
|
struct packetlist *reply_queue_head, *reply_queue_tail;
|
||
|
|
||
|
void(*remoteclosed)(); /* A callback to handle closure of the
|
||
|
remote connection */
|
||
|
|
||
|
void(*extra_session_cleanup)(); /* client or server specific cleanup */
|
||
|
void(*send_kex_first_guess)();
|
||
|
|
||
|
struct AuthState authstate; /* Common amongst client and server, since most
|
||
|
struct elements are common */
|
||
|
|
||
|
/* Channel related */
|
||
|
struct Channel ** channels; /* these pointers may be null */
|
||
|
unsigned int chansize; /* the number of Channel*s allocated for channels */
|
||
|
unsigned int chancount; /* the number of Channel*s in use */
|
||
|
const struct ChanType **chantypes; /* The valid channel types */
|
||
|
int channel_signal_pending; /* Flag set by sigchld handler */
|
||
|
|
||
|
/* TCP priority level for the main "port 22" tcp socket */
|
||
|
enum dropbear_prio socket_prio;
|
||
|
|
||
|
/* TCP forwarding - where manage listeners */
|
||
|
struct Listener ** listeners;
|
||
|
unsigned int listensize;
|
||
|
|
||
|
/* Whether to allow binding to privileged ports (<1024). This doesn't
|
||
|
* really belong here, but nowhere else fits nicely */
|
||
|
int allowprivport;
|
||
|
|
||
|
};
|
||
|
|
||
|
struct serversession {
|
||
|
|
||
|
/* Server specific options */
|
||
|
int childpipe; /* kept open until we successfully authenticate */
|
||
|
/* userauth */
|
||
|
|
||
|
struct ChildPid * childpids; /* array of mappings childpid<->channel */
|
||
|
unsigned int childpidsize;
|
||
|
|
||
|
/* Used to avoid a race in the exit returncode handling - see
|
||
|
* svr-chansession.c for details */
|
||
|
struct exitinfo lastexit;
|
||
|
|
||
|
/* The numeric address they connected from, used for logging */
|
||
|
char * addrstring;
|
||
|
|
||
|
/* The resolved remote address, used for lastlog etc */
|
||
|
char *remotehost;
|
||
|
|
||
|
time_t connect_time; /* time the connection was established
|
||
|
(cleared after auth once we're not
|
||
|
respecting AUTH_TIMEOUT any more).
|
||
|
A monotonic time, not realworld */
|
||
|
|
||
|
#ifdef USE_VFORK
|
||
|
pid_t server_pid;
|
||
|
#endif
|
||
|
|
||
|
};
|
||
|
|
||
|
typedef enum {
|
||
|
KEX_NOTHING,
|
||
|
KEXINIT_RCVD,
|
||
|
KEXDH_INIT_SENT,
|
||
|
KEXDONE
|
||
|
} cli_kex_state;
|
||
|
|
||
|
typedef enum {
|
||
|
STATE_NOTHING,
|
||
|
USERAUTH_WAIT,
|
||
|
USERAUTH_REQ_SENT,
|
||
|
USERAUTH_FAIL_RCVD,
|
||
|
USERAUTH_SUCCESS_RCVD,
|
||
|
SESSION_RUNNING
|
||
|
} cli_state;
|
||
|
|
||
|
struct clientsession {
|
||
|
|
||
|
/* XXX - move these to kexstate? */
|
||
|
struct kex_dh_param *dh_param;
|
||
|
struct kex_ecdh_param *ecdh_param;
|
||
|
struct kex_curve25519_param *curve25519_param;
|
||
|
const struct dropbear_kex *param_kex_algo; /* KEX algorithm corresponding to current dh_e and dh_x */
|
||
|
|
||
|
cli_kex_state kex_state; /* Used for progressing KEX */
|
||
|
cli_state state; /* Used to progress auth/channelsession etc */
|
||
|
unsigned donefirstkex : 1; /* Set when we set sentnewkeys, never reset */
|
||
|
|
||
|
int tty_raw_mode; /* Whether we're in raw mode (and have to clean up) */
|
||
|
struct termios saved_tio;
|
||
|
int stdincopy;
|
||
|
int stdinflags;
|
||
|
int stdoutcopy;
|
||
|
int stdoutflags;
|
||
|
int stderrcopy;
|
||
|
int stderrflags;
|
||
|
|
||
|
/* for escape char handling */
|
||
|
int last_char;
|
||
|
|
||
|
int winchange; /* Set to 1 when a windowchange signal happens */
|
||
|
|
||
|
int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
|
||
|
for the last type of auth we tried */
|
||
|
int ignore_next_auth_response;
|
||
|
#ifdef ENABLE_CLI_INTERACT_AUTH
|
||
|
int auth_interact_failed; /* flag whether interactive auth can still
|
||
|
be used */
|
||
|
int interact_request_received; /* flag whether we've received an
|
||
|
info request from the server for
|
||
|
interactive auth.*/
|
||
|
|
||
|
int cipher_none_after_auth; /* Set to 1 if the user requested "none"
|
||
|
auth */
|
||
|
#endif
|
||
|
sign_key *lastprivkey;
|
||
|
|
||
|
int retval; /* What the command exit status was - we emulate it */
|
||
|
#if 0
|
||
|
TODO
|
||
|
struct AgentkeyList *agentkeys; /* Keys to use for public-key auth */
|
||
|
#endif
|
||
|
|
||
|
};
|
||
|
|
||
|
/* Global structs storing the state */
|
||
|
extern struct sshsession ses;
|
||
|
|
||
|
#ifdef DROPBEAR_SERVER
|
||
|
extern struct serversession svr_ses;
|
||
|
#endif /* DROPBEAR_SERVER */
|
||
|
|
||
|
#ifdef DROPBEAR_CLIENT
|
||
|
extern struct clientsession cli_ses;
|
||
|
#endif /* DROPBEAR_CLIENT */
|
||
|
|
||
|
#endif /* _SESSION_H_ */
|