| ︙ | | | ︙ | |
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
|
unsigned sport, dport;
char dhost[256];
};
struct Packet {
long length;
int type;
unsigned char *data;
unsigned char *body;
long savedpos;
long maxlen;
/*
* State associated with packet logging
*/
int logmode;
int nblanks;
struct logblank_t *blanks;
};
static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin);
static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin);
static void ssh_size(void *handle, int width, int height);
static void ssh_special(void *handle, Telnet_Special);
static int ssh2_try_send(struct ssh_channel *c);
static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);
static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
static void ssh2_set_window(struct ssh_channel *c, unsigned newwin);
static int ssh_sendbuffer(void *handle);
|
>
>
>
|
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
|
unsigned sport, dport;
char dhost[256];
};
struct Packet {
long length;
int type;
unsigned long sequence;
unsigned char *data;
unsigned char *body;
long savedpos;
long maxlen;
/*
* State associated with packet logging
*/
int logmode;
int nblanks;
struct logblank_t *blanks;
};
static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin);
static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin);
static void ssh1_protocol_setup(Ssh ssh);
static void ssh2_protocol_setup(Ssh ssh);
static void ssh_size(void *handle, int width, int height);
static void ssh_special(void *handle, Telnet_Special);
static int ssh2_try_send(struct ssh_channel *c);
static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);
static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);
static void ssh2_set_window(struct ssh_channel *c, unsigned newwin);
static int ssh_sendbuffer(void *handle);
|
| ︙ | | | ︙ | |
553
554
555
556
557
558
559
560
561
562
563
564
565
566
|
struct rdpkt2_state_tag {
long len, pad, payload, packetlen, maclen;
int i;
int cipherblk;
unsigned long incoming_sequence;
struct Packet *pktin;
};
struct ssh_tag {
const struct plug_function_table *fn;
/* the above field _must_ be first in the structure */
SHA_State exhash, exhashbase;
|
>
>
|
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
|
struct rdpkt2_state_tag {
long len, pad, payload, packetlen, maclen;
int i;
int cipherblk;
unsigned long incoming_sequence;
struct Packet *pktin;
};
typedef void (*handler_fn_t)(Ssh ssh, struct Packet *pktin);
struct ssh_tag {
const struct plug_function_table *fn;
/* the above field _must_ be first in the structure */
SHA_State exhash, exhashbase;
|
| ︙ | | | ︙ | |
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
|
int v1_stdout_throttling;
int v2_outgoing_sequence;
int ssh1_rdpkt_crstate;
int ssh2_rdpkt_crstate;
int do_ssh_init_crstate;
int ssh_gotdata_crstate;
int ssh1_protocol_crstate;
int do_ssh1_login_crstate;
int do_ssh2_transport_crstate;
int do_ssh2_authconn_crstate;
void *do_ssh_init_state;
void *do_ssh1_login_state;
void *do_ssh2_transport_state;
void *do_ssh2_authconn_state;
struct rdpkt1_state_tag rdpkt1_state;
struct rdpkt2_state_tag rdpkt2_state;
void (*protocol) (Ssh ssh, unsigned char *in, int inlen,
struct Packet *pkt);
struct Packet *(*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
/*
* We maintain a full _copy_ of a Config structure here, not
* merely a pointer to it. That way, when we're passed a new
* one for reconfiguration, we can check the differences and
* potentially reconfigure port forwardings etc in mid-session.
*/
Config cfg;
/*
* Used to transfer data back from async agent callbacks.
*/
void *agent_response;
int agent_response_len;
};
#define logevent(s) logevent(ssh->frontend, s)
/* logevent, only printf-formatted. */
static void logeventf(Ssh ssh, const char *fmt, ...)
{
|
<
>
>
>
>
>
>
>
>
>
>
|
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
|
int v1_stdout_throttling;
int v2_outgoing_sequence;
int ssh1_rdpkt_crstate;
int ssh2_rdpkt_crstate;
int do_ssh_init_crstate;
int ssh_gotdata_crstate;
int do_ssh1_login_crstate;
int do_ssh1_connection_crstate;
int do_ssh2_transport_crstate;
int do_ssh2_authconn_crstate;
void *do_ssh_init_state;
void *do_ssh1_login_state;
void *do_ssh2_transport_state;
void *do_ssh2_authconn_state;
struct rdpkt1_state_tag rdpkt1_state;
struct rdpkt2_state_tag rdpkt2_state;
/* ssh1 and ssh2 use this for different things, but both use it */
int protocol_initial_phase_done;
void (*protocol) (Ssh ssh, unsigned char *in, int inlen,
struct Packet *pkt);
struct Packet *(*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
/*
* We maintain a full _copy_ of a Config structure here, not
* merely a pointer to it. That way, when we're passed a new
* one for reconfiguration, we can check the differences and
* potentially reconfigure port forwardings etc in mid-session.
*/
Config cfg;
/*
* Used to transfer data back from async agent callbacks.
*/
void *agent_response;
int agent_response_len;
/*
* Dispatch table for packet types that we may have to deal
* with at any time.
*/
handler_fn_t packet_dispatch[256];
};
#define logevent(s) logevent(ssh->frontend, s)
/* logevent, only printf-formatted. */
static void logeventf(Ssh ssh, const char *fmt, ...)
{
|
| ︙ | | | ︙ | |
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
|
*/
static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
{
struct rdpkt1_state_tag *st = &ssh->rdpkt1_state;
crBegin(ssh->ssh1_rdpkt_crstate);
next_packet:
st->pktin = ssh_new_packet();
st->pktin->type = 0;
st->pktin->length = 0;
for (st->i = st->len = 0; st->i < 4; st->i++) {
while ((*datalen) == 0)
|
<
<
|
883
884
885
886
887
888
889
890
891
892
893
894
895
896
|
*/
static struct Packet *ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
{
struct rdpkt1_state_tag *st = &ssh->rdpkt1_state;
crBegin(ssh->ssh1_rdpkt_crstate);
st->pktin = ssh_new_packet();
st->pktin->type = 0;
st->pktin->length = 0;
for (st->i = st->len = 0; st->i < 4; st->i++) {
while ((*datalen) == 0)
|
| ︙ | | | ︙ | |
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
|
log_packet(ssh->logctx,
PKT_INCOMING, st->pktin->type,
ssh1_pkt_type(st->pktin->type),
st->pktin->body, st->pktin->length,
nblanks, &blank);
}
if (st->pktin->type == SSH1_SMSG_STDOUT_DATA ||
st->pktin->type == SSH1_SMSG_STDERR_DATA ||
st->pktin->type == SSH1_MSG_DEBUG ||
st->pktin->type == SSH1_SMSG_AUTH_TIS_CHALLENGE ||
st->pktin->type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
long stringlen = GET_32BIT(st->pktin->body);
if (stringlen + 4 != st->pktin->length) {
bombout(("Received data packet with bogus string length"));
ssh_free_packet(st->pktin);
crStop(NULL);
}
}
if (st->pktin->type == SSH1_MSG_DEBUG) {
char *buf, *msg;
int msglen;
ssh_pkt_getstring(st->pktin, &msg, &msglen);
buf = dupprintf("Remote debug message: %.*s", msglen, msg);
logevent(buf);
sfree(buf);
ssh_free_packet(st->pktin);
goto next_packet;
} else if (st->pktin->type == SSH1_MSG_IGNORE) {
/* do nothing */
ssh_free_packet(st->pktin);
goto next_packet;
}
if (st->pktin->type == SSH1_MSG_DISCONNECT) {
/* log reason code in disconnect message */
char *msg;
int msglen;
ssh_pkt_getstring(st->pktin, &msg, &msglen);
bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg));
ssh_free_packet(st->pktin);
crStop(NULL);
}
crFinish(st->pktin);
}
static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
{
struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;
crBegin(ssh->ssh2_rdpkt_crstate);
next_packet:
st->pktin = ssh_new_packet();
st->pktin->type = 0;
st->pktin->length = 0;
if (ssh->sccipher)
st->cipherblk = ssh->sccipher->blksize;
else
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
|
log_packet(ssh->logctx,
PKT_INCOMING, st->pktin->type,
ssh1_pkt_type(st->pktin->type),
st->pktin->body, st->pktin->length,
nblanks, &blank);
}
crFinish(st->pktin);
}
static struct Packet *ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
{
struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;
crBegin(ssh->ssh2_rdpkt_crstate);
st->pktin = ssh_new_packet();
st->pktin->type = 0;
st->pktin->length = 0;
if (ssh->sccipher)
st->cipherblk = ssh->sccipher->blksize;
else
|
| ︙ | | | ︙ | |
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
|
if (ssh->scmac
&& !ssh->scmac->verify(ssh->sc_mac_ctx, st->pktin->data, st->len + 4,
st->incoming_sequence)) {
bombout(("Incorrect MAC received on packet"));
ssh_free_packet(st->pktin);
crStop(NULL);
}
st->incoming_sequence++; /* whether or not we MACed */
/*
* Decompress packet payload.
*/
{
unsigned char *newpayload;
int newlen;
|
|
>
|
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
|
if (ssh->scmac
&& !ssh->scmac->verify(ssh->sc_mac_ctx, st->pktin->data, st->len + 4,
st->incoming_sequence)) {
bombout(("Incorrect MAC received on packet"));
ssh_free_packet(st->pktin);
crStop(NULL);
}
st->pktin->sequence = st->incoming_sequence++;
/*
* Decompress packet payload.
*/
{
unsigned char *newpayload;
int newlen;
|
| ︙ | | | ︙ | |
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
|
}
log_packet(ssh->logctx, PKT_INCOMING, st->pktin->type,
ssh2_pkt_type(ssh->pkt_ctx, st->pktin->type),
st->pktin->data+6, st->pktin->length-6,
nblanks, &blank);
}
switch (st->pktin->type) {
/*
* These packets we must handle instantly.
*/
case SSH2_MSG_DISCONNECT:
{
/* log reason code in disconnect message */
char *buf, *msg;
int nowlen, reason, msglen;
reason = ssh_pkt_getuint32(st->pktin);
ssh_pkt_getstring(st->pktin, &msg, &msglen);
if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
buf = dupprintf("Received disconnect message (%s)",
ssh2_disconnect_reasons[reason]);
} else {
buf = dupprintf("Received disconnect message (unknown"
" type %d)", reason);
}
logevent(buf);
sfree(buf);
buf = dupprintf("Disconnection message text: %n%.*s",
&nowlen, msglen, msg);
logevent(buf);
bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"",
reason,
(reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
ssh2_disconnect_reasons[reason] : "unknown",
buf+nowlen));
sfree(buf);
ssh_free_packet(st->pktin);
crStop(NULL);
}
break;
case SSH2_MSG_IGNORE:
ssh_free_packet(st->pktin);
goto next_packet;
case SSH2_MSG_DEBUG:
{
/* log the debug message */
char *buf, *msg;
int msglen;
int always_display;
/* XXX maybe we should actually take notice of this */
always_display = ssh2_pkt_getbool(st->pktin);
ssh_pkt_getstring(st->pktin, &msg, &msglen);
buf = dupprintf("Remote debug message: %.*s", msglen, msg);
logevent(buf);
sfree(buf);
}
ssh_free_packet(st->pktin);
goto next_packet;
/*
* These packets we need do nothing about here.
*/
case SSH2_MSG_UNIMPLEMENTED:
case SSH2_MSG_SERVICE_REQUEST:
case SSH2_MSG_SERVICE_ACCEPT:
case SSH2_MSG_KEXINIT:
case SSH2_MSG_NEWKEYS:
case SSH2_MSG_KEXDH_INIT:
case SSH2_MSG_KEXDH_REPLY:
/* case SSH2_MSG_KEX_DH_GEX_REQUEST: duplicate case value */
/* case SSH2_MSG_KEX_DH_GEX_GROUP: duplicate case value */
case SSH2_MSG_KEX_DH_GEX_INIT:
case SSH2_MSG_KEX_DH_GEX_REPLY:
case SSH2_MSG_USERAUTH_REQUEST:
case SSH2_MSG_USERAUTH_FAILURE:
case SSH2_MSG_USERAUTH_SUCCESS:
case SSH2_MSG_USERAUTH_BANNER:
case SSH2_MSG_USERAUTH_PK_OK:
/* case SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: duplicate case value */
/* case SSH2_MSG_USERAUTH_INFO_REQUEST: duplicate case value */
case SSH2_MSG_USERAUTH_INFO_RESPONSE:
case SSH2_MSG_GLOBAL_REQUEST:
case SSH2_MSG_REQUEST_SUCCESS:
case SSH2_MSG_REQUEST_FAILURE:
case SSH2_MSG_CHANNEL_OPEN:
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
case SSH2_MSG_CHANNEL_OPEN_FAILURE:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_CLOSE:
case SSH2_MSG_CHANNEL_REQUEST:
case SSH2_MSG_CHANNEL_SUCCESS:
case SSH2_MSG_CHANNEL_FAILURE:
break;
/*
* For anything else we send SSH2_MSG_UNIMPLEMENTED.
*/
default:
{
struct Packet *pktout;
pktout = ssh2_pkt_init(SSH2_MSG_UNIMPLEMENTED);
ssh2_pkt_adduint32(pktout, st->incoming_sequence - 1);
/* UNIMPLEMENTED messages MUST appear in the same order as
* the messages they respond to. Hence, never queue them. */
ssh2_pkt_send_noqueue(ssh, pktout);
}
break;
}
crFinish(st->pktin);
}
static void ssh1_pktout_size(struct Packet *pkt, int len)
{
int pad, biglen;
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
|
}
log_packet(ssh->logctx, PKT_INCOMING, st->pktin->type,
ssh2_pkt_type(ssh->pkt_ctx, st->pktin->type),
st->pktin->data+6, st->pktin->length-6,
nblanks, &blank);
}
crFinish(st->pktin);
}
static void ssh1_pktout_size(struct Packet *pkt, int len)
{
int pad, biglen;
|
| ︙ | | | ︙ | |
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
|
sha_string(&ssh->exhashbase, s->vstring, strcspn(s->vstring, "\r\n"));
sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
strcat(verstring, "\012");
logevent("Using SSH protocol version 2");
sk_write(ssh->s, verstring, strlen(verstring));
ssh->protocol = ssh2_protocol;
ssh->version = 2;
ssh->s_rdpkt = ssh2_rdpkt;
} else {
/*
* Use v1 protocol.
*/
char verstring[80], vlog[100];
sprintf(verstring, "SSH-%s-%s",
(ssh_versioncmp(s->version, "1.5") <= 0 ? s->version : "1.5"),
sshver);
sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
strcat(verstring, "\012");
logevent("Using SSH protocol version 1");
sk_write(ssh->s, verstring, strlen(verstring));
ssh->protocol = ssh1_protocol;
ssh->version = 1;
ssh->s_rdpkt = ssh1_rdpkt;
}
update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE;
sfree(s->vstring);
|
>
>
|
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
|
sha_string(&ssh->exhashbase, s->vstring, strcspn(s->vstring, "\r\n"));
sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
strcat(verstring, "\012");
logevent("Using SSH protocol version 2");
sk_write(ssh->s, verstring, strlen(verstring));
ssh->protocol = ssh2_protocol;
ssh2_protocol_setup(ssh);
ssh->version = 2;
ssh->s_rdpkt = ssh2_rdpkt;
} else {
/*
* Use v1 protocol.
*/
char verstring[80], vlog[100];
sprintf(verstring, "SSH-%s-%s",
(ssh_versioncmp(s->version, "1.5") <= 0 ? s->version : "1.5"),
sshver);
sprintf(vlog, "We claim version: %s", verstring);
logevent(vlog);
strcat(verstring, "\012");
logevent("Using SSH protocol version 1");
sk_write(ssh->s, verstring, strlen(verstring));
ssh->protocol = ssh1_protocol;
ssh1_protocol_setup(ssh);
ssh->version = 1;
ssh->s_rdpkt = ssh1_rdpkt;
}
update_specials_menu(ssh->frontend);
ssh->state = SSH_STATE_BEFORE_SIZE;
sfree(s->vstring);
|
| ︙ | | | ︙ | |
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
|
Bignum challenge;
char *commentp;
int commentlen;
};
crState(do_ssh1_login_state);
crBegin(ssh->do_ssh1_login_crstate);
if (!pktin)
crWaitUntil(pktin);
if (pktin->type != SSH1_SMSG_PUBLIC_KEY) {
bombout(("Public key packet not received"));
crStop(0);
|
>
>
|
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
|
Bignum challenge;
char *commentp;
int commentlen;
};
crState(do_ssh1_login_state);
crBegin(ssh->do_ssh1_login_crstate);
random_init();
if (!pktin)
crWaitUntil(pktin);
if (pktin->type != SSH1_SMSG_PUBLIC_KEY) {
bombout(("Public key packet not received"));
crStop(0);
|
| ︙ | | | ︙ | |
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
|
ssh1_throttle(ssh, -1);
}
} else {
ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
}
}
static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
crBegin(ssh->ssh1_protocol_crstate);
random_init();
while (!do_ssh1_login(ssh, in, inlen, pktin)) {
crReturnV;
}
if (ssh->state == SSH_STATE_CLOSED)
crReturnV;
if (ssh->cfg.agentfwd && agent_exists()) {
logevent("Requesting agent forwarding");
send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
do {
crReturnV;
} while (!pktin);
|
|
|
|
<
<
<
<
<
<
<
<
|
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
|
ssh1_throttle(ssh, -1);
}
} else {
ssh2_set_window(c, OUR_V2_WINSIZE - bufsize);
}
}
static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
crBegin(ssh->do_ssh1_connection_crstate);
if (ssh->cfg.agentfwd && agent_exists()) {
logevent("Requesting agent forwarding");
send_packet(ssh, SSH1_CMSG_AGENT_REQUEST_FORWARDING, PKT_END);
do {
crReturnV;
} while (!pktin);
|
| ︙ | | | ︙ | |
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
|
inlen -= len;
}
}
}
crFinishV;
}
/*
* Utility routine for decoding comma-separated strings in KEXINIT.
*/
static int in_commasep_string(char *needle, char *haystack, int haylen)
{
int needlen;
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
|
inlen -= len;
}
}
}
crFinishV;
}
/*
* Handle the top-level SSH2 protocol.
*/
static void ssh1_msg_debug(Ssh ssh, struct Packet *pktin)
{
char *buf, *msg;
int msglen;
ssh_pkt_getstring(pktin, &msg, &msglen);
buf = dupprintf("Remote debug message: %.*s", msglen, msg);
logevent(buf);
sfree(buf);
}
static void ssh1_msg_disconnect(Ssh ssh, struct Packet *pktin)
{
/* log reason code in disconnect message */
char *msg;
int msglen;
ssh_pkt_getstring(pktin, &msg, &msglen);
bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg));
}
void ssh_msg_ignore(Ssh ssh, struct Packet *pktin)
{
/* Do nothing, because we're ignoring it! Duhh. */
}
static void ssh1_protocol_setup(Ssh ssh)
{
int i;
/*
* Most messages are handled by the coroutines.
*/
for (i = 0; i < 256; i++)
ssh->packet_dispatch[i] = NULL;
/*
* These special message types we install handlers for.
*/
ssh->packet_dispatch[SSH1_MSG_DISCONNECT] = ssh1_msg_disconnect;
ssh->packet_dispatch[SSH1_MSG_IGNORE] = ssh_msg_ignore;
ssh->packet_dispatch[SSH1_MSG_DEBUG] = ssh1_msg_debug;
}
static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
if (ssh->state == SSH_STATE_CLOSED)
return;
if (pktin && ssh->packet_dispatch[pktin->type]) {
ssh->packet_dispatch[pktin->type](ssh, pktin);
return;
}
if (!ssh->protocol_initial_phase_done) {
if (do_ssh1_login(ssh, in, inlen, pktin))
ssh->protocol_initial_phase_done = TRUE;
else
return;
}
do_ssh1_connection(ssh, in, inlen, pktin);
}
/*
* Utility routine for decoding comma-separated strings in KEXINIT.
*/
static int in_commasep_string(char *needle, char *haystack, int haylen)
{
int needlen;
|
| ︙ | | | ︙ | |
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
|
* SSH2_MSG_NEWKEYS packet to the next layer, not because it
* wants to see it but because it will need time to initialise
* itself before it sees an actual packet. In subsequent key
* exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because
* it would only confuse the layer above.
*/
if (!s->first_kex) {
crReturn(0);
}
s->first_kex = 0;
/*
* Now we're encrypting. Begin returning 1 to the protocol main
* function so that other things can run on top of the
* transport. If we ever see a KEXINIT, we must go back to the
|
|
|
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
|
* SSH2_MSG_NEWKEYS packet to the next layer, not because it
* wants to see it but because it will need time to initialise
* itself before it sees an actual packet. In subsequent key
* exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because
* it would only confuse the layer above.
*/
if (!s->first_kex) {
crReturn(1);
}
s->first_kex = 0;
/*
* Now we're encrypting. Begin returning 1 to the protocol main
* function so that other things can run on top of the
* transport. If we ever see a KEXINIT, we must go back to the
|
| ︙ | | | ︙ | |
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
|
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
ssh2_pkt_adduint32(pktout, c->remoteid);
ssh2_pkt_adduint32(pktout, newwin - c->v.v2.locwindow);
ssh2_pkt_send(ssh, pktout);
c->v.v2.locwindow = newwin;
}
}
/*
* Handle the SSH2 userauth and connection layers.
*/
static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
|
>
>
>
>
>
>
>
>
>
|
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
|
pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
ssh2_pkt_adduint32(pktout, c->remoteid);
ssh2_pkt_adduint32(pktout, newwin - c->v.v2.locwindow);
ssh2_pkt_send(ssh, pktout);
c->v.v2.locwindow = newwin;
}
}
void ssh2_msg_channel_window_adjust(Ssh ssh, struct Packet *pktin)
{
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (c && !c->closes)
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
/*
* Handle the SSH2 userauth and connection layers.
*/
static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
|
| ︙ | | | ︙ | |
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
|
* Now we're authenticated for the connection protocol. The
* connection protocol will automatically have started at this
* point; there's no need to send SERVICE_REQUEST.
*/
ssh->channels = newtree234(ssh_channelcmp);
/*
* Create the main session channel.
*/
if (!ssh->cfg.ssh_no_shell) {
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
ssh->mainchan->localid = alloc_channel_id(ssh);
|
>
>
>
>
>
>
>
|
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
|
* Now we're authenticated for the connection protocol. The
* connection protocol will automatically have started at this
* point; there's no need to send SERVICE_REQUEST.
*/
ssh->channels = newtree234(ssh_channelcmp);
/*
* Set up handlers for some connection protocol messages, so we
* don't have to handle them repeatedly in this coroutine.
*/
ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] =
ssh2_msg_channel_window_adjust;
/*
* Create the main session channel.
*/
if (!ssh->cfg.ssh_no_shell) {
ssh->mainchan = snew(struct ssh_channel);
ssh->mainchan->ssh = ssh;
ssh->mainchan->localid = alloc_channel_id(ssh);
|
| ︙ | | | ︙ | |
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
|
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_addbool(s->pktout, 0); /* many connections */
ssh2_pkt_addstring(s->pktout, proto);
ssh2_pkt_addstring(s->pktout, data);
ssh2_pkt_adduint32(s->pktout, x11_get_screen_number(ssh->cfg.x11_display));
ssh2_pkt_send(ssh, s->pktout);
do {
crWaitUntilV(pktin);
if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
} while (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to X11 forwarding request:"
" packet type %d", pktin->type));
crStopV;
}
|
<
|
<
<
<
<
<
<
<
<
<
|
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
|
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_addbool(s->pktout, 0); /* many connections */
ssh2_pkt_addstring(s->pktout, proto);
ssh2_pkt_addstring(s->pktout, data);
ssh2_pkt_adduint32(s->pktout, x11_get_screen_number(ssh->cfg.x11_display));
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to X11 forwarding request:"
" packet type %d", pktin->type));
crStopV;
}
|
| ︙ | | | ︙ | |
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
|
ssh2_pkt_addstring(s->pktout, "0.0.0.0");
} else {
ssh2_pkt_addstring(s->pktout, "127.0.0.1");
}
ssh2_pkt_adduint32(s->pktout, sport);
ssh2_pkt_send(ssh, s->pktout);
do {
crWaitUntilV(pktin);
if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue;/* nonexistent channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
} while (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin->type != SSH2_MSG_REQUEST_SUCCESS) {
if (pktin->type != SSH2_MSG_REQUEST_FAILURE) {
bombout(("Unexpected response to port "
"forwarding request: packet type %d",
pktin->type));
crStopV;
|
<
|
<
<
<
<
<
<
<
<
<
|
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
|
ssh2_pkt_addstring(s->pktout, "0.0.0.0");
} else {
ssh2_pkt_addstring(s->pktout, "127.0.0.1");
}
ssh2_pkt_adduint32(s->pktout, sport);
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_REQUEST_SUCCESS) {
if (pktin->type != SSH2_MSG_REQUEST_FAILURE) {
bombout(("Unexpected response to port "
"forwarding request: packet type %d",
pktin->type));
crStopV;
|
| ︙ | | | ︙ | |
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
|
logevent("Requesting OpenSSH-style agent forwarding");
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
ssh2_pkt_addstring(s->pktout, "auth-agent-req@openssh.com");
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_send(ssh, s->pktout);
do {
crWaitUntilV(pktin);
if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
} while (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to agent forwarding request:"
" packet type %d", pktin->type));
crStopV;
}
|
<
|
<
<
<
<
<
<
<
<
<
|
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
|
logevent("Requesting OpenSSH-style agent forwarding");
s->pktout = ssh2_pkt_init(SSH2_MSG_CHANNEL_REQUEST);
ssh2_pkt_adduint32(s->pktout, ssh->mainchan->remoteid);
ssh2_pkt_addstring(s->pktout, "auth-agent-req@openssh.com");
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to agent forwarding request:"
" packet type %d", pktin->type));
crStopV;
}
|
| ︙ | | | ︙ | |
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
|
ssh2_pkt_adduint32(s->pktout, ssh->ispeed);
ssh2_pkt_addbyte(s->pktout, 129); /* TTY_OP_OSPEED */
ssh2_pkt_adduint32(s->pktout, ssh->ospeed);
ssh2_pkt_addstring_data(s->pktout, "\0", 1); /* TTY_OP_END */
ssh2_pkt_send(ssh, s->pktout);
ssh->state = SSH_STATE_INTERMED;
do {
crWaitUntilV(pktin);
if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
} while (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to pty request:"
" packet type %d", pktin->type));
crStopV;
}
|
<
|
<
<
<
<
<
<
<
<
<
|
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
|
ssh2_pkt_adduint32(s->pktout, ssh->ispeed);
ssh2_pkt_addbyte(s->pktout, 129); /* TTY_OP_OSPEED */
ssh2_pkt_adduint32(s->pktout, ssh->ospeed);
ssh2_pkt_addstring_data(s->pktout, "\0", 1); /* TTY_OP_END */
ssh2_pkt_send(ssh, s->pktout);
ssh->state = SSH_STATE_INTERMED;
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to pty request:"
" packet type %d", pktin->type));
crStopV;
}
|
| ︙ | | | ︙ | |
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
|
logeventf(ssh, "Sent %d environment variables", s->num_env);
s->env_ok = 0;
s->env_left = s->num_env;
while (s->env_left > 0) {
do {
crWaitUntilV(pktin);
if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
} while (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to environment request:"
" packet type %d", pktin->type));
crStopV;
}
|
<
|
<
<
<
<
<
<
<
<
<
|
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
|
logeventf(ssh, "Sent %d environment variables", s->num_env);
s->env_ok = 0;
s->env_left = s->num_env;
while (s->env_left > 0) {
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to environment request:"
" packet type %d", pktin->type));
crStopV;
}
|
| ︙ | | | ︙ | |
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
|
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_addstring(s->pktout, cmd);
} else {
ssh2_pkt_addstring(s->pktout, "shell");
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
}
ssh2_pkt_send(ssh, s->pktout);
do {
crWaitUntilV(pktin);
if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
}
} while (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to shell/command request:"
" packet type %d", pktin->type));
crStopV;
}
/*
|
|
|
<
<
<
<
<
<
<
|
<
|
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
|
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_addstring(s->pktout, cmd);
} else {
ssh2_pkt_addstring(s->pktout, "shell");
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
}
ssh2_pkt_send(ssh, s->pktout);
crWaitUntilV(pktin);
if (pktin->type != SSH2_MSG_CHANNEL_SUCCESS) {
if (pktin->type != SSH2_MSG_CHANNEL_FAILURE) {
bombout(("Unexpected response to shell/command request:"
" packet type %d", pktin->type));
crStopV;
}
/*
|
| ︙ | | | ︙ | |
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
|
ssh2_pkt_addstring(s->pktout, "en"); /* language tag */
ssh2_pkt_send_noqueue(ssh, s->pktout);
#endif
ssh_closing((Plug)ssh, NULL, 0, 0);
crStopV;
}
continue; /* remote sends close; ignore (FIXME) */
} else if (pktin->type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c || c->closes)
continue; /* nonexistent or closing channel */
c->v.v2.remwindow += ssh_pkt_getuint32(pktin);
s->try_send = TRUE;
} else if (pktin->type == SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
if (c->type != CHAN_SOCKDATA_DORMANT)
|
<
<
<
<
<
<
<
<
|
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
|
ssh2_pkt_addstring(s->pktout, "en"); /* language tag */
ssh2_pkt_send_noqueue(ssh, s->pktout);
#endif
ssh_closing((Plug)ssh, NULL, 0, 0);
crStopV;
}
continue; /* remote sends close; ignore (FIXME) */
} else if (pktin->type == SSH2_MSG_CHANNEL_OPEN_CONFIRMATION) {
unsigned i = ssh_pkt_getuint32(pktin);
struct ssh_channel *c;
c = find234(ssh->channels, &i, ssh_channelfind);
if (!c)
continue; /* nonexistent channel */
if (c->type != CHAN_SOCKDATA_DORMANT)
|
| ︙ | | | ︙ | |
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
|
}
}
}
}
crFinishV;
}
/*
* Handle the top-level SSH2 protocol.
*/
static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
if (do_ssh2_transport(ssh, in, inlen, pktin) == 0)
return;
do_ssh2_authconn(ssh, in, inlen, pktin);
}
/*
* Called to set up the connection.
*
* Returns an error message, or NULL on success.
*/
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
|
}
}
}
}
crFinishV;
}
/*
* Handlers for SSH2 messages that might arrive at any moment.
*/
void ssh2_msg_disconnect(Ssh ssh, struct Packet *pktin)
{
/* log reason code in disconnect message */
char *buf, *msg;
int nowlen, reason, msglen;
reason = ssh_pkt_getuint32(pktin);
ssh_pkt_getstring(pktin, &msg, &msglen);
if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
buf = dupprintf("Received disconnect message (%s)",
ssh2_disconnect_reasons[reason]);
} else {
buf = dupprintf("Received disconnect message (unknown"
" type %d)", reason);
}
logevent(buf);
sfree(buf);
buf = dupprintf("Disconnection message text: %n%.*s",
&nowlen, msglen, msg);
logevent(buf);
bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"",
reason,
(reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
ssh2_disconnect_reasons[reason] : "unknown",
buf+nowlen));
sfree(buf);
}
void ssh2_msg_debug(Ssh ssh, struct Packet *pktin)
{
/* log the debug message */
char *buf, *msg;
int msglen;
int always_display;
/* XXX maybe we should actually take notice of this */
always_display = ssh2_pkt_getbool(pktin);
ssh_pkt_getstring(pktin, &msg, &msglen);
buf = dupprintf("Remote debug message: %.*s", msglen, msg);
logevent(buf);
sfree(buf);
}
void ssh2_msg_something_unimplemented(Ssh ssh, struct Packet *pktin)
{
struct Packet *pktout;
pktout = ssh2_pkt_init(SSH2_MSG_UNIMPLEMENTED);
ssh2_pkt_adduint32(pktout, pktin->sequence);
/*
* UNIMPLEMENTED messages MUST appear in the same order as the
* messages they respond to. Hence, never queue them.
*/
ssh2_pkt_send_noqueue(ssh, pktout);
}
/*
* Handle the top-level SSH2 protocol.
*/
static void ssh2_protocol_setup(Ssh ssh)
{
int i;
/*
* Most messages cause SSH2_MSG_UNIMPLEMENTED.
*/
for (i = 0; i < 256; i++)
ssh->packet_dispatch[i] = ssh2_msg_something_unimplemented;
/*
* Any message we actually understand, we set to NULL so that
* the coroutines will get it.
*/
ssh->packet_dispatch[SSH2_MSG_UNIMPLEMENTED] = NULL;
ssh->packet_dispatch[SSH2_MSG_SERVICE_REQUEST] = NULL;
ssh->packet_dispatch[SSH2_MSG_SERVICE_ACCEPT] = NULL;
ssh->packet_dispatch[SSH2_MSG_KEXINIT] = NULL;
ssh->packet_dispatch[SSH2_MSG_NEWKEYS] = NULL;
ssh->packet_dispatch[SSH2_MSG_KEXDH_INIT] = NULL;
ssh->packet_dispatch[SSH2_MSG_KEXDH_REPLY] = NULL;
/* ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_REQUEST] = NULL; duplicate case value */
/* ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_GROUP] = NULL; duplicate case value */
ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_INIT] = NULL;
ssh->packet_dispatch[SSH2_MSG_KEX_DH_GEX_REPLY] = NULL;
ssh->packet_dispatch[SSH2_MSG_USERAUTH_REQUEST] = NULL;
ssh->packet_dispatch[SSH2_MSG_USERAUTH_FAILURE] = NULL;
ssh->packet_dispatch[SSH2_MSG_USERAUTH_SUCCESS] = NULL;
ssh->packet_dispatch[SSH2_MSG_USERAUTH_BANNER] = NULL;
ssh->packet_dispatch[SSH2_MSG_USERAUTH_PK_OK] = NULL;
/* ssh->packet_dispatch[SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ] = NULL; duplicate case value */
/* ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_REQUEST] = NULL; duplicate case value */
ssh->packet_dispatch[SSH2_MSG_USERAUTH_INFO_RESPONSE] = NULL;
ssh->packet_dispatch[SSH2_MSG_GLOBAL_REQUEST] = NULL;
ssh->packet_dispatch[SSH2_MSG_REQUEST_SUCCESS] = NULL;
ssh->packet_dispatch[SSH2_MSG_REQUEST_FAILURE] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_CONFIRMATION] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_OPEN_FAILURE] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_WINDOW_ADJUST] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_DATA] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_EXTENDED_DATA] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_EOF] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_CLOSE] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_REQUEST] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_SUCCESS] = NULL;
ssh->packet_dispatch[SSH2_MSG_CHANNEL_FAILURE] = NULL;
/*
* These special message types we install handlers for.
*/
ssh->packet_dispatch[SSH2_MSG_DISCONNECT] = ssh2_msg_disconnect;
ssh->packet_dispatch[SSH2_MSG_IGNORE] = ssh_msg_ignore; /* shared with ssh1 */
ssh->packet_dispatch[SSH2_MSG_DEBUG] = ssh2_msg_debug;
}
static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
if (ssh->state == SSH_STATE_CLOSED)
return;
if (pktin && ssh->packet_dispatch[pktin->type]) {
ssh->packet_dispatch[pktin->type](ssh, pktin);
return;
}
if (!ssh->protocol_initial_phase_done ||
(pktin && pktin->type >= 20 && pktin->type < 50)) {
if (do_ssh2_transport(ssh, in, inlen, pktin) &&
!ssh->protocol_initial_phase_done) {
ssh->protocol_initial_phase_done = TRUE;
/*
* Allow authconn to initialise itself.
*/
do_ssh2_authconn(ssh, NULL, 0, NULL);
}
} else {
do_ssh2_authconn(ssh, in, inlen, pktin);
}
}
/*
* Called to set up the connection.
*
* Returns an error message, or NULL on success.
*/
|
| ︙ | | | ︙ | |
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
|
ssh->x11auth = NULL;
ssh->v1_compressing = FALSE;
ssh->v2_outgoing_sequence = 0;
ssh->ssh1_rdpkt_crstate = 0;
ssh->ssh2_rdpkt_crstate = 0;
ssh->do_ssh_init_crstate = 0;
ssh->ssh_gotdata_crstate = 0;
ssh->ssh1_protocol_crstate = 0;
ssh->do_ssh1_login_crstate = 0;
ssh->do_ssh2_transport_crstate = 0;
ssh->do_ssh2_authconn_crstate = 0;
ssh->do_ssh_init_state = NULL;
ssh->do_ssh1_login_state = NULL;
ssh->do_ssh2_transport_state = NULL;
ssh->do_ssh2_authconn_state = NULL;
|
|
|
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
|
ssh->x11auth = NULL;
ssh->v1_compressing = FALSE;
ssh->v2_outgoing_sequence = 0;
ssh->ssh1_rdpkt_crstate = 0;
ssh->ssh2_rdpkt_crstate = 0;
ssh->do_ssh_init_crstate = 0;
ssh->ssh_gotdata_crstate = 0;
ssh->do_ssh1_connection_crstate = 0;
ssh->do_ssh1_login_crstate = 0;
ssh->do_ssh2_transport_crstate = 0;
ssh->do_ssh2_authconn_crstate = 0;
ssh->do_ssh_init_state = NULL;
ssh->do_ssh1_login_state = NULL;
ssh->do_ssh2_transport_state = NULL;
ssh->do_ssh2_authconn_state = NULL;
|
| ︙ | | | ︙ | |
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
|
ssh->editing = 0;
ssh->echoing = 0;
ssh->v1_throttle_count = 0;
ssh->overall_bufsize = 0;
ssh->fallback_cmd = 0;
ssh->protocol = NULL;
p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
if (p != NULL)
return p;
return NULL;
}
|
>
>
|
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
|
ssh->editing = 0;
ssh->echoing = 0;
ssh->v1_throttle_count = 0;
ssh->overall_bufsize = 0;
ssh->fallback_cmd = 0;
ssh->protocol = NULL;
ssh->protocol_initial_phase_done = FALSE;
p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
if (p != NULL)
return p;
return NULL;
}
|
| ︙ | | | ︙ | |