mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-25 01:02:24 +00:00
Move some ssh.c declarations into header files.
ssh.c has been an unmanageably huge monolith of a source file for too long, and it's finally time I started breaking it up into smaller pieces. The first step is to move some declarations - basic types like packets and packet queues, standard constants, enums, and the coroutine system - into headers where other files can see them.
This commit is contained in:
parent
8b98fea4ae
commit
ba7571291a
180
ssh.c
180
ssh.c
@ -15,6 +15,7 @@
|
|||||||
#include "storage.h"
|
#include "storage.h"
|
||||||
#include "marshal.h"
|
#include "marshal.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
#include "sshcr.h"
|
||||||
#ifndef NO_GSSAPI
|
#ifndef NO_GSSAPI
|
||||||
#include "sshgssc.h"
|
#include "sshgssc.h"
|
||||||
#include "sshgss.h"
|
#include "sshgss.h"
|
||||||
@ -25,26 +26,6 @@
|
|||||||
#define GSS_CTXT_MAYFAIL (1<<3) /* Context may expire during handshake */
|
#define GSS_CTXT_MAYFAIL (1<<3) /* Context may expire during handshake */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Packet type contexts, so that ssh2_pkt_type can correctly decode
|
|
||||||
* the ambiguous type numbers back into the correct type strings.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
SSH2_PKTCTX_NOKEX,
|
|
||||||
SSH2_PKTCTX_DHGROUP,
|
|
||||||
SSH2_PKTCTX_DHGEX,
|
|
||||||
SSH2_PKTCTX_ECDHKEX,
|
|
||||||
SSH2_PKTCTX_GSSKEX,
|
|
||||||
SSH2_PKTCTX_RSAKEX
|
|
||||||
} Pkt_KCtx;
|
|
||||||
typedef enum {
|
|
||||||
SSH2_PKTCTX_NOAUTH,
|
|
||||||
SSH2_PKTCTX_PUBLICKEY,
|
|
||||||
SSH2_PKTCTX_PASSWORD,
|
|
||||||
SSH2_PKTCTX_GSSAPI,
|
|
||||||
SSH2_PKTCTX_KBDINTER
|
|
||||||
} Pkt_ACtx;
|
|
||||||
|
|
||||||
static const char *const ssh2_disconnect_reasons[] = {
|
static const char *const ssh2_disconnect_reasons[] = {
|
||||||
NULL,
|
NULL,
|
||||||
"host not allowed to connect",
|
"host not allowed to connect",
|
||||||
@ -200,7 +181,7 @@ static unsigned long rekey_mins(int rekey_time, unsigned long def)
|
|||||||
#define translate(x) if (type == x) return #x
|
#define translate(x) if (type == x) return #x
|
||||||
#define translatek(x,ctx) if (type == x && (pkt_kctx == ctx)) return #x
|
#define translatek(x,ctx) if (type == x && (pkt_kctx == ctx)) return #x
|
||||||
#define translatea(x,ctx) if (type == x && (pkt_actx == ctx)) return #x
|
#define translatea(x,ctx) if (type == x && (pkt_actx == ctx)) return #x
|
||||||
static const char *ssh1_pkt_type(int type)
|
const char *ssh1_pkt_type(int type)
|
||||||
{
|
{
|
||||||
translate(SSH1_MSG_DISCONNECT);
|
translate(SSH1_MSG_DISCONNECT);
|
||||||
translate(SSH1_SMSG_PUBLIC_KEY);
|
translate(SSH1_SMSG_PUBLIC_KEY);
|
||||||
@ -245,8 +226,7 @@ static const char *ssh1_pkt_type(int type)
|
|||||||
translate(SSH1_CMSG_AUTH_CCARD_RESPONSE);
|
translate(SSH1_CMSG_AUTH_CCARD_RESPONSE);
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
static const char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx,
|
const char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type)
|
||||||
int type)
|
|
||||||
{
|
{
|
||||||
translatea(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,SSH2_PKTCTX_GSSAPI);
|
translatea(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,SSH2_PKTCTX_GSSAPI);
|
||||||
translatea(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,SSH2_PKTCTX_GSSAPI);
|
translatea(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,SSH2_PKTCTX_GSSAPI);
|
||||||
@ -313,57 +293,6 @@ enum {
|
|||||||
PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM,
|
PKT_END, PKT_INT, PKT_CHAR, PKT_DATA, PKT_STR, PKT_BIGNUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Coroutine mechanics for the sillier bits of the code. If these
|
|
||||||
* macros look impenetrable to you, you might find it helpful to
|
|
||||||
* read
|
|
||||||
*
|
|
||||||
* https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
|
|
||||||
*
|
|
||||||
* which explains the theory behind these macros.
|
|
||||||
*
|
|
||||||
* In particular, if you are getting `case expression not constant'
|
|
||||||
* errors when building with MS Visual Studio, this is because MS's
|
|
||||||
* Edit and Continue debugging feature causes their compiler to
|
|
||||||
* violate ANSI C. To disable Edit and Continue debugging:
|
|
||||||
*
|
|
||||||
* - right-click ssh.c in the FileView
|
|
||||||
* - click Settings
|
|
||||||
* - select the C/C++ tab and the General category
|
|
||||||
* - under `Debug info:', select anything _other_ than `Program
|
|
||||||
* Database for Edit and Continue'.
|
|
||||||
*/
|
|
||||||
#define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
|
|
||||||
#define crBeginState crBegin(s->crLine)
|
|
||||||
#define crStateP(t, v) \
|
|
||||||
struct t *s; \
|
|
||||||
if (!(v)) { s = (v) = snew(struct t); s->crLine = 0; } \
|
|
||||||
s = (v);
|
|
||||||
#define crState(t) crStateP(t, ssh->t)
|
|
||||||
#define crFinish(z) } *crLine = 0; return (z); }
|
|
||||||
#define crFinishV } *crLine = 0; return; }
|
|
||||||
#define crFinishFree(z) } sfree(s); return (z); }
|
|
||||||
#define crFinishFreeV } sfree(s); return; }
|
|
||||||
#define crReturn(z) \
|
|
||||||
do {\
|
|
||||||
*crLine =__LINE__; return (z); case __LINE__:;\
|
|
||||||
} while (0)
|
|
||||||
#define crReturnV \
|
|
||||||
do {\
|
|
||||||
*crLine=__LINE__; return; case __LINE__:;\
|
|
||||||
} while (0)
|
|
||||||
#define crStop(z) do{ *crLine = 0; return (z); }while(0)
|
|
||||||
#define crStopV do{ *crLine = 0; return; }while(0)
|
|
||||||
#define crWaitUntil(c) do { crReturn(0); } while (!(c))
|
|
||||||
#define crWaitUntilV(c) do { crReturnV; } while (!(c))
|
|
||||||
#define crMaybeWaitUntil(c) do { while (!(c)) crReturn(0); } while (0)
|
|
||||||
#define crMaybeWaitUntilV(c) do { while (!(c)) crReturnV; } while (0)
|
|
||||||
|
|
||||||
typedef struct PktIn PktIn;
|
|
||||||
typedef struct PktOut PktOut;
|
|
||||||
|
|
||||||
static struct PktOut *ssh1_pkt_init(int pkt_type);
|
|
||||||
static struct PktOut *ssh2_pkt_init(int pkt_type);
|
|
||||||
static void ssh_pkt_ensure(struct PktOut *, int length);
|
static void ssh_pkt_ensure(struct PktOut *, int length);
|
||||||
static void ssh_pkt_adddata(struct PktOut *, const void *data, int len);
|
static void ssh_pkt_adddata(struct PktOut *, const void *data, int len);
|
||||||
static ptrlen ssh2_pkt_construct(Ssh, struct PktOut *);
|
static ptrlen ssh2_pkt_construct(Ssh, struct PktOut *);
|
||||||
@ -386,47 +315,6 @@ static void ssh1_login_input(Ssh ssh);
|
|||||||
static void ssh2_userauth_input(Ssh ssh);
|
static void ssh2_userauth_input(Ssh ssh);
|
||||||
static void ssh2_connection_input(Ssh ssh);
|
static void ssh2_connection_input(Ssh ssh);
|
||||||
|
|
||||||
/*
|
|
||||||
* Buffer management constants. There are several of these for
|
|
||||||
* various different purposes:
|
|
||||||
*
|
|
||||||
* - SSH1_BUFFER_LIMIT is the amount of backlog that must build up
|
|
||||||
* on a local data stream before we throttle the whole SSH
|
|
||||||
* connection (in SSH-1 only). Throttling the whole connection is
|
|
||||||
* pretty drastic so we set this high in the hope it won't
|
|
||||||
* happen very often.
|
|
||||||
*
|
|
||||||
* - SSH_MAX_BACKLOG is the amount of backlog that must build up
|
|
||||||
* on the SSH connection itself before we defensively throttle
|
|
||||||
* _all_ local data streams. This is pretty drastic too (though
|
|
||||||
* thankfully unlikely in SSH-2 since the window mechanism should
|
|
||||||
* ensure that the server never has any need to throttle its end
|
|
||||||
* of the connection), so we set this high as well.
|
|
||||||
*
|
|
||||||
* - OUR_V2_WINSIZE is the default window size we present on SSH-2
|
|
||||||
* channels.
|
|
||||||
*
|
|
||||||
* - OUR_V2_BIGWIN is the window size we advertise for the only
|
|
||||||
* channel in a simple connection. It must be <= INT_MAX.
|
|
||||||
*
|
|
||||||
* - OUR_V2_MAXPKT is the official "maximum packet size" we send
|
|
||||||
* to the remote side. This actually has nothing to do with the
|
|
||||||
* size of the _packet_, but is instead a limit on the amount
|
|
||||||
* of data we're willing to receive in a single SSH2 channel
|
|
||||||
* data message.
|
|
||||||
*
|
|
||||||
* - OUR_V2_PACKETLIMIT is actually the maximum size of SSH
|
|
||||||
* _packet_ we're prepared to cope with. It must be a multiple
|
|
||||||
* of the cipher block size, and must be at least 35000.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SSH1_BUFFER_LIMIT 32768
|
|
||||||
#define SSH_MAX_BACKLOG 32768
|
|
||||||
#define OUR_V2_WINSIZE 16384
|
|
||||||
#define OUR_V2_BIGWIN 0x7fffffff
|
|
||||||
#define OUR_V2_MAXPKT 0x4000UL
|
|
||||||
#define OUR_V2_PACKETLIMIT 0x9000UL
|
|
||||||
|
|
||||||
struct ssh_signkey_with_user_pref_id {
|
struct ssh_signkey_with_user_pref_id {
|
||||||
const ssh_keyalg *alg;
|
const ssh_keyalg *alg;
|
||||||
int id;
|
int id;
|
||||||
@ -670,40 +558,6 @@ struct ssh_portfwd {
|
|||||||
((pf) ? (sfree((pf)->saddr), sfree((pf)->daddr), \
|
((pf) ? (sfree((pf)->saddr), sfree((pf)->daddr), \
|
||||||
sfree((pf)->sserv), sfree((pf)->dserv)) : (void)0 ), sfree(pf) )
|
sfree((pf)->sserv), sfree((pf)->dserv)) : (void)0 ), sfree(pf) )
|
||||||
|
|
||||||
typedef struct PacketQueueNode PacketQueueNode;
|
|
||||||
struct PacketQueueNode {
|
|
||||||
PacketQueueNode *next, *prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PktIn {
|
|
||||||
int refcount;
|
|
||||||
int type;
|
|
||||||
unsigned long sequence; /* SSH-2 incoming sequence number */
|
|
||||||
long encrypted_len; /* for SSH-2 total-size counting */
|
|
||||||
PacketQueueNode qnode; /* for linking this packet on to a queue */
|
|
||||||
BinarySource_IMPLEMENTATION;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PktOut {
|
|
||||||
long prefix; /* bytes up to and including type field */
|
|
||||||
long length; /* total bytes, including prefix */
|
|
||||||
int type;
|
|
||||||
long forcepad; /* SSH-2: force padding to at least this length */
|
|
||||||
unsigned char *data; /* allocated storage */
|
|
||||||
long maxlen; /* amount of storage allocated for `data' */
|
|
||||||
long encrypted_len; /* for SSH-2 total-size counting */
|
|
||||||
|
|
||||||
/* Extra metadata used in SSH packet logging mode, allowing us to
|
|
||||||
* log in the packet header line that the packet came from a
|
|
||||||
* connection-sharing downstream and what if anything unusual was
|
|
||||||
* done to it. The additional_log_text field is expected to be a
|
|
||||||
* static string - it will not be freed. */
|
|
||||||
unsigned downstream_id;
|
|
||||||
const char *additional_log_text;
|
|
||||||
|
|
||||||
BinarySink_IMPLEMENTATION;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ssh1_protocol_setup(Ssh ssh);
|
static void ssh1_protocol_setup(Ssh ssh);
|
||||||
static void ssh2_protocol_setup(Ssh ssh);
|
static void ssh2_protocol_setup(Ssh ssh);
|
||||||
static void ssh2_bare_connection_protocol_setup(Ssh ssh);
|
static void ssh2_bare_connection_protocol_setup(Ssh ssh);
|
||||||
@ -724,18 +578,13 @@ static PktOut *ssh2_gss_authpacket(Ssh ssh, Ssh_gss_ctx gss_ctx,
|
|||||||
const char *authtype);
|
const char *authtype);
|
||||||
#endif
|
#endif
|
||||||
static void ssh2_msg_unexpected(Ssh ssh, PktIn *pktin);
|
static void ssh2_msg_unexpected(Ssh ssh, PktIn *pktin);
|
||||||
static void ssh_unref_packet(PktIn *pkt);
|
|
||||||
|
|
||||||
struct PacketQueue {
|
void pq_init(struct PacketQueue *pq)
|
||||||
PacketQueueNode end;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pq_init(struct PacketQueue *pq)
|
|
||||||
{
|
{
|
||||||
pq->end.next = pq->end.prev = &pq->end;
|
pq->end.next = pq->end.prev = &pq->end;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pq_push(struct PacketQueue *pq, PktIn *pkt)
|
void pq_push(struct PacketQueue *pq, PktIn *pkt)
|
||||||
{
|
{
|
||||||
PacketQueueNode *node = &pkt->qnode;
|
PacketQueueNode *node = &pkt->qnode;
|
||||||
assert(!node->next);
|
assert(!node->next);
|
||||||
@ -746,7 +595,7 @@ static void pq_push(struct PacketQueue *pq, PktIn *pkt)
|
|||||||
node->prev->next = node;
|
node->prev->next = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pq_push_front(struct PacketQueue *pq, PktIn *pkt)
|
void pq_push_front(struct PacketQueue *pq, PktIn *pkt)
|
||||||
{
|
{
|
||||||
PacketQueueNode *node = &pkt->qnode;
|
PacketQueueNode *node = &pkt->qnode;
|
||||||
assert(!node->next);
|
assert(!node->next);
|
||||||
@ -757,14 +606,14 @@ static void pq_push_front(struct PacketQueue *pq, PktIn *pkt)
|
|||||||
node->prev->next = node;
|
node->prev->next = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PktIn *pq_peek(struct PacketQueue *pq)
|
PktIn *pq_peek(struct PacketQueue *pq)
|
||||||
{
|
{
|
||||||
if (pq->end.next == &pq->end)
|
if (pq->end.next == &pq->end)
|
||||||
return NULL;
|
return NULL;
|
||||||
return FROMFIELD(pq->end.next, PktIn, qnode);
|
return FROMFIELD(pq->end.next, PktIn, qnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PktIn *pq_pop(struct PacketQueue *pq)
|
PktIn *pq_pop(struct PacketQueue *pq)
|
||||||
{
|
{
|
||||||
PacketQueueNode *node = pq->end.next;
|
PacketQueueNode *node = pq->end.next;
|
||||||
if (node == &pq->end)
|
if (node == &pq->end)
|
||||||
@ -777,15 +626,14 @@ static PktIn *pq_pop(struct PacketQueue *pq)
|
|||||||
return FROMFIELD(node, PktIn, qnode);
|
return FROMFIELD(node, PktIn, qnode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pq_clear(struct PacketQueue *pq)
|
void pq_clear(struct PacketQueue *pq)
|
||||||
{
|
{
|
||||||
PktIn *pkt;
|
PktIn *pkt;
|
||||||
while ((pkt = pq_pop(pq)) != NULL)
|
while ((pkt = pq_pop(pq)) != NULL)
|
||||||
ssh_unref_packet(pkt);
|
ssh_unref_packet(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pq_empty_on_to_front_of(struct PacketQueue *src,
|
int pq_empty_on_to_front_of(struct PacketQueue *src, struct PacketQueue *dest)
|
||||||
struct PacketQueue *dest)
|
|
||||||
{
|
{
|
||||||
struct PacketQueueNode *srcfirst, *srclast;
|
struct PacketQueueNode *srcfirst, *srclast;
|
||||||
|
|
||||||
@ -1373,13 +1221,13 @@ static void c_write_str(Ssh ssh, const char *buf)
|
|||||||
c_write(ssh, buf, strlen(buf));
|
c_write(ssh, buf, strlen(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ssh_unref_packet(PktIn *pkt)
|
void ssh_unref_packet(PktIn *pkt)
|
||||||
{
|
{
|
||||||
if (--pkt->refcount <= 0)
|
if (--pkt->refcount <= 0)
|
||||||
sfree(pkt);
|
sfree(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ssh_free_pktout(PktOut *pkt)
|
void ssh_free_pktout(PktOut *pkt)
|
||||||
{
|
{
|
||||||
sfree(pkt->data);
|
sfree(pkt->data);
|
||||||
sfree(pkt);
|
sfree(pkt);
|
||||||
@ -2347,7 +2195,7 @@ static void ssh_pkt_BinarySink_write(BinarySink *bs,
|
|||||||
ssh_pkt_adddata(pkt, data, len);
|
ssh_pkt_adddata(pkt, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PktOut *ssh1_pkt_init(int pkt_type)
|
PktOut *ssh1_pkt_init(int pkt_type)
|
||||||
{
|
{
|
||||||
PktOut *pkt = ssh_new_packet();
|
PktOut *pkt = ssh_new_packet();
|
||||||
pkt->length = 4 + 8; /* space for length + max padding */
|
pkt->length = 4 + 8; /* space for length + max padding */
|
||||||
@ -2359,7 +2207,7 @@ static PktOut *ssh1_pkt_init(int pkt_type)
|
|||||||
return pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PktOut *ssh2_pkt_init(int pkt_type)
|
PktOut *ssh2_pkt_init(int pkt_type)
|
||||||
{
|
{
|
||||||
PktOut *pkt = ssh_new_packet();
|
PktOut *pkt = ssh_new_packet();
|
||||||
pkt->length = 5; /* space for packet length + padding length */
|
pkt->length = 5; /* space for packet length + padding length */
|
||||||
|
115
ssh.h
115
ssh.h
@ -22,6 +22,118 @@ void sshfwd_x11_sharing_handover(struct ssh_channel *c,
|
|||||||
const void *initial_data, int initial_len);
|
const void *initial_data, int initial_len);
|
||||||
void sshfwd_x11_is_local(struct ssh_channel *c);
|
void sshfwd_x11_is_local(struct ssh_channel *c);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buffer management constants. There are several of these for
|
||||||
|
* various different purposes:
|
||||||
|
*
|
||||||
|
* - SSH1_BUFFER_LIMIT is the amount of backlog that must build up
|
||||||
|
* on a local data stream before we throttle the whole SSH
|
||||||
|
* connection (in SSH-1 only). Throttling the whole connection is
|
||||||
|
* pretty drastic so we set this high in the hope it won't
|
||||||
|
* happen very often.
|
||||||
|
*
|
||||||
|
* - SSH_MAX_BACKLOG is the amount of backlog that must build up
|
||||||
|
* on the SSH connection itself before we defensively throttle
|
||||||
|
* _all_ local data streams. This is pretty drastic too (though
|
||||||
|
* thankfully unlikely in SSH-2 since the window mechanism should
|
||||||
|
* ensure that the server never has any need to throttle its end
|
||||||
|
* of the connection), so we set this high as well.
|
||||||
|
*
|
||||||
|
* - OUR_V2_WINSIZE is the default window size we present on SSH-2
|
||||||
|
* channels.
|
||||||
|
*
|
||||||
|
* - OUR_V2_BIGWIN is the window size we advertise for the only
|
||||||
|
* channel in a simple connection. It must be <= INT_MAX.
|
||||||
|
*
|
||||||
|
* - OUR_V2_MAXPKT is the official "maximum packet size" we send
|
||||||
|
* to the remote side. This actually has nothing to do with the
|
||||||
|
* size of the _packet_, but is instead a limit on the amount
|
||||||
|
* of data we're willing to receive in a single SSH2 channel
|
||||||
|
* data message.
|
||||||
|
*
|
||||||
|
* - OUR_V2_PACKETLIMIT is actually the maximum size of SSH
|
||||||
|
* _packet_ we're prepared to cope with. It must be a multiple
|
||||||
|
* of the cipher block size, and must be at least 35000.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SSH1_BUFFER_LIMIT 32768
|
||||||
|
#define SSH_MAX_BACKLOG 32768
|
||||||
|
#define OUR_V2_WINSIZE 16384
|
||||||
|
#define OUR_V2_BIGWIN 0x7fffffff
|
||||||
|
#define OUR_V2_MAXPKT 0x4000UL
|
||||||
|
#define OUR_V2_PACKETLIMIT 0x9000UL
|
||||||
|
|
||||||
|
typedef struct PacketQueueNode PacketQueueNode;
|
||||||
|
struct PacketQueueNode {
|
||||||
|
PacketQueueNode *next, *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct PktIn {
|
||||||
|
int refcount;
|
||||||
|
int type;
|
||||||
|
unsigned long sequence; /* SSH-2 incoming sequence number */
|
||||||
|
long encrypted_len; /* for SSH-2 total-size counting */
|
||||||
|
PacketQueueNode qnode; /* for linking this packet on to a queue */
|
||||||
|
BinarySource_IMPLEMENTATION;
|
||||||
|
} PktIn;
|
||||||
|
|
||||||
|
typedef struct PktOut {
|
||||||
|
long prefix; /* bytes up to and including type field */
|
||||||
|
long length; /* total bytes, including prefix */
|
||||||
|
int type;
|
||||||
|
long forcepad; /* SSH-2: force padding to at least this length */
|
||||||
|
unsigned char *data; /* allocated storage */
|
||||||
|
long maxlen; /* amount of storage allocated for `data' */
|
||||||
|
long encrypted_len; /* for SSH-2 total-size counting */
|
||||||
|
|
||||||
|
/* Extra metadata used in SSH packet logging mode, allowing us to
|
||||||
|
* log in the packet header line that the packet came from a
|
||||||
|
* connection-sharing downstream and what if anything unusual was
|
||||||
|
* done to it. The additional_log_text field is expected to be a
|
||||||
|
* static string - it will not be freed. */
|
||||||
|
unsigned downstream_id;
|
||||||
|
const char *additional_log_text;
|
||||||
|
|
||||||
|
BinarySink_IMPLEMENTATION;
|
||||||
|
} PktOut;
|
||||||
|
|
||||||
|
typedef struct PacketQueue {
|
||||||
|
PacketQueueNode end;
|
||||||
|
} PacketQueue;
|
||||||
|
|
||||||
|
void pq_init(struct PacketQueue *pq);
|
||||||
|
void pq_push(struct PacketQueue *pq, PktIn *pkt);
|
||||||
|
void pq_push_front(struct PacketQueue *pq, PktIn *pkt);
|
||||||
|
PktIn *pq_peek(struct PacketQueue *pq);
|
||||||
|
PktIn *pq_pop(struct PacketQueue *pq);
|
||||||
|
void pq_clear(struct PacketQueue *pq);
|
||||||
|
int pq_empty_on_to_front_of(struct PacketQueue *src, struct PacketQueue *dest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Packet type contexts, so that ssh2_pkt_type can correctly decode
|
||||||
|
* the ambiguous type numbers back into the correct type strings.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SSH2_PKTCTX_NOKEX,
|
||||||
|
SSH2_PKTCTX_DHGROUP,
|
||||||
|
SSH2_PKTCTX_DHGEX,
|
||||||
|
SSH2_PKTCTX_ECDHKEX,
|
||||||
|
SSH2_PKTCTX_GSSKEX,
|
||||||
|
SSH2_PKTCTX_RSAKEX
|
||||||
|
} Pkt_KCtx;
|
||||||
|
typedef enum {
|
||||||
|
SSH2_PKTCTX_NOAUTH,
|
||||||
|
SSH2_PKTCTX_PUBLICKEY,
|
||||||
|
SSH2_PKTCTX_PASSWORD,
|
||||||
|
SSH2_PKTCTX_GSSAPI,
|
||||||
|
SSH2_PKTCTX_KBDINTER
|
||||||
|
} Pkt_ACtx;
|
||||||
|
|
||||||
|
PktOut *ssh1_pkt_init(int pkt_type);
|
||||||
|
PktOut *ssh2_pkt_init(int pkt_type);
|
||||||
|
void ssh_unref_packet(PktIn *pkt);
|
||||||
|
void ssh_free_pktout(PktOut *pkt);
|
||||||
|
|
||||||
extern Socket ssh_connection_sharing_init(
|
extern Socket ssh_connection_sharing_init(
|
||||||
const char *host, int port, Conf *conf, Ssh ssh, Plug sshplug,
|
const char *host, int port, Conf *conf, Ssh ssh, Plug sshplug,
|
||||||
void **state);
|
void **state);
|
||||||
@ -1048,6 +1160,9 @@ void platform_ssh_share_cleanup(const char *name);
|
|||||||
|
|
||||||
#define SSH2_EXTENDED_DATA_STDERR 1 /* 0x1 */
|
#define SSH2_EXTENDED_DATA_STDERR 1 /* 0x1 */
|
||||||
|
|
||||||
|
const char *ssh1_pkt_type(int type);
|
||||||
|
const char *ssh2_pkt_type(Pkt_KCtx pkt_kctx, Pkt_ACtx pkt_actx, int type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Need this to warn about support for the original SSH-2 keyfile
|
* Need this to warn about support for the original SSH-2 keyfile
|
||||||
* format.
|
* format.
|
||||||
|
54
sshcr.h
Normal file
54
sshcr.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Coroutine mechanics used in PuTTY's SSH code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PUTTY_SSHCR_H
|
||||||
|
#define PUTTY_SSHCR_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If these macros look impenetrable to you, you might find it helpful
|
||||||
|
* to read
|
||||||
|
*
|
||||||
|
* https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
|
||||||
|
*
|
||||||
|
* which explains the theory behind these macros.
|
||||||
|
*
|
||||||
|
* In particular, if you are getting `case expression not constant'
|
||||||
|
* errors when building with MS Visual Studio, this is because MS's
|
||||||
|
* Edit and Continue debugging feature causes their compiler to
|
||||||
|
* violate ANSI C. To disable Edit and Continue debugging:
|
||||||
|
*
|
||||||
|
* - right-click ssh.c in the FileView
|
||||||
|
* - click Settings
|
||||||
|
* - select the C/C++ tab and the General category
|
||||||
|
* - under `Debug info:', select anything _other_ than `Program
|
||||||
|
* Database for Edit and Continue'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
|
||||||
|
#define crBeginState crBegin(s->crLine)
|
||||||
|
#define crStateP(t, v) \
|
||||||
|
struct t *s; \
|
||||||
|
if (!(v)) { s = (v) = snew(struct t); s->crLine = 0; } \
|
||||||
|
s = (v);
|
||||||
|
#define crState(t) crStateP(t, ssh->t)
|
||||||
|
#define crFinish(z) } *crLine = 0; return (z); }
|
||||||
|
#define crFinishV } *crLine = 0; return; }
|
||||||
|
#define crFinishFree(z) } sfree(s); return (z); }
|
||||||
|
#define crFinishFreeV } sfree(s); return; }
|
||||||
|
#define crReturn(z) \
|
||||||
|
do {\
|
||||||
|
*crLine =__LINE__; return (z); case __LINE__:;\
|
||||||
|
} while (0)
|
||||||
|
#define crReturnV \
|
||||||
|
do {\
|
||||||
|
*crLine=__LINE__; return; case __LINE__:;\
|
||||||
|
} while (0)
|
||||||
|
#define crStop(z) do{ *crLine = 0; return (z); }while(0)
|
||||||
|
#define crStopV do{ *crLine = 0; return; }while(0)
|
||||||
|
#define crWaitUntil(c) do { crReturn(0); } while (!(c))
|
||||||
|
#define crWaitUntilV(c) do { crReturnV; } while (!(c))
|
||||||
|
#define crMaybeWaitUntil(c) do { while (!(c)) crReturn(0); } while (0)
|
||||||
|
#define crMaybeWaitUntilV(c) do { while (!(c)) crReturnV; } while (0)
|
||||||
|
|
||||||
|
#endif /* PUTTY_SSHCR_H */
|
Loading…
Reference in New Issue
Block a user