| 112 |
TYPE_SHELL, TYPE_PORTFWD, |
TYPE_SHELL, TYPE_PORTFWD, |
| 113 |
}; |
}; |
| 114 |
|
|
| 115 |
|
typedef struct bufchain { |
| 116 |
|
buffer_t *msg; |
| 117 |
|
struct bufchain *next; |
| 118 |
|
} bufchain_t; |
| 119 |
|
|
| 120 |
typedef struct channel { |
typedef struct channel { |
| 121 |
int used; |
int used; |
| 122 |
int self_id; |
int self_id; |
| 129 |
unsigned int remote_maxpacket; |
unsigned int remote_maxpacket; |
| 130 |
enum channel_type type; |
enum channel_type type; |
| 131 |
int local_num; |
int local_num; |
| 132 |
|
bufchain_t *bufchain; |
| 133 |
|
int chain_count; |
| 134 |
} Channel_t; |
} Channel_t; |
| 135 |
|
|
| 136 |
static Channel_t channels[CHANNEL_MAX]; |
static Channel_t channels[CHANNEL_MAX]; |
| 157 |
|
|
| 158 |
// setup |
// setup |
| 159 |
c = &channels[found]; |
c = &channels[found]; |
| 160 |
|
memset(c, 0, sizeof(Channel_t)); |
| 161 |
c->used = 1; |
c->used = 1; |
| 162 |
c->self_id = i; |
c->self_id = i; |
| 163 |
c->remote_id = -1; |
c->remote_id = -1; |
| 169 |
c->remote_maxpacket = 0; |
c->remote_maxpacket = 0; |
| 170 |
c->type = type; |
c->type = type; |
| 171 |
c->local_num = local_num; // alloc_channel()の返値を保存しておく |
c->local_num = local_num; // alloc_channel()の返値を保存しておく |
| 172 |
|
c->bufchain = NULL; |
| 173 |
|
|
| 174 |
return (c); |
return (c); |
| 175 |
} |
} |
| 176 |
|
|
| 177 |
|
|
| 178 |
|
static void ssh2_channel_add_bufchain(Channel_t *c, unsigned char *buf, unsigned int buflen) |
| 179 |
|
{ |
| 180 |
|
bufchain_t *ch; |
| 181 |
|
|
| 182 |
|
ch = malloc(sizeof(bufchain_t)); |
| 183 |
|
if (ch == NULL) |
| 184 |
|
return; |
| 185 |
|
ch->msg = buffer_init(); |
| 186 |
|
if (ch == NULL) { |
| 187 |
|
free(ch); |
| 188 |
|
return; |
| 189 |
|
} |
| 190 |
|
buffer_put_string(ch->msg, buf, buflen); |
| 191 |
|
|
| 192 |
|
ch->next = c->bufchain; |
| 193 |
|
c->bufchain = ch; |
| 194 |
|
c->chain_count++; |
| 195 |
|
} |
| 196 |
|
|
| 197 |
|
|
| 198 |
|
static void ssh2_channel_retry_send_bufchain(PTInstVar pvar, Channel_t *c) |
| 199 |
|
{ |
| 200 |
|
bufchain_t *ch, *ptr, *prev_ptr; |
| 201 |
|
unsigned int size; |
| 202 |
|
|
| 203 |
|
while (c->bufchain) { |
| 204 |
|
// 末尾から先に送る |
| 205 |
|
prev_ptr = NULL; |
| 206 |
|
ptr = c->bufchain; |
| 207 |
|
while (ptr->next) { |
| 208 |
|
prev_ptr = ptr; |
| 209 |
|
ptr = ptr->next; |
| 210 |
|
} |
| 211 |
|
ch = ptr; |
| 212 |
|
size = buffer_len(ch->msg); |
| 213 |
|
if (size >= c->remote_window) |
| 214 |
|
break; |
| 215 |
|
|
| 216 |
|
SSH_channel_send(pvar, c->local_num, 0, buffer_ptr(ch->msg), size); |
| 217 |
|
c->chain_count--; |
| 218 |
|
|
| 219 |
|
buffer_free(ch->msg); |
| 220 |
|
free(ch); |
| 221 |
|
if (prev_ptr) |
| 222 |
|
prev_ptr->next = NULL; |
| 223 |
|
else |
| 224 |
|
c->bufchain = NULL; |
| 225 |
|
} |
| 226 |
|
} |
| 227 |
|
|
| 228 |
|
|
| 229 |
|
|
| 230 |
// channel close時にチャネル構造体をリストへ返却する |
// channel close時にチャネル構造体をリストへ返却する |
| 231 |
// (2007.4.26 yutaka) |
// (2007.4.26 yutaka) |
| 232 |
static void ssh2_channel_delete(Channel_t *c) |
static void ssh2_channel_delete(Channel_t *c) |
| 233 |
{ |
{ |
| 234 |
|
bufchain_t *ch, *ptr; |
| 235 |
|
|
| 236 |
|
ch = c->bufchain; |
| 237 |
|
while (ch) { |
| 238 |
|
if (ch->msg) |
| 239 |
|
buffer_free(ch->msg); |
| 240 |
|
ptr = ch; |
| 241 |
|
ch = ch->next; |
| 242 |
|
free(ptr); |
| 243 |
|
} |
| 244 |
|
|
| 245 |
memset(c, 0, sizeof(Channel_t)); |
memset(c, 0, sizeof(Channel_t)); |
| 246 |
c->used = 0; |
c->used = 0; |
| 247 |
} |
} |
| 255 |
|
|
| 256 |
for (i = 0 ; i < CHANNEL_MAX ; i++) { |
for (i = 0 ; i < CHANNEL_MAX ; i++) { |
| 257 |
c = &channels[i]; |
c = &channels[i]; |
| 258 |
memset(c, 0, sizeof(Channel_t)); |
ssh2_channel_delete(c); |
| 259 |
} |
} |
| 260 |
|
|
| 261 |
} |
} |
| 971 |
if (block_size < 8) { |
if (block_size < 8) { |
| 972 |
block_size = 8; |
block_size = 8; |
| 973 |
} |
} |
| 974 |
|
#if 0 |
| 975 |
encryption_size = ((len + 8) / block_size + 1) * block_size; |
encryption_size = ((len + 8) / block_size + 1) * block_size; |
| 976 |
data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar); |
data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar); |
| 977 |
|
|
| 978 |
set_uint32(data, encryption_size - 4); |
set_uint32(data, encryption_size - 4); |
| 979 |
padding = encryption_size - len - 5; |
padding = encryption_size - len - 5; |
| 980 |
data[4] = (unsigned char) padding; |
data[4] = (unsigned char) padding; |
| 981 |
|
#else |
| 982 |
|
// でかいパケットを送ろうとすると、サーバ側で"Bad packet length"になってしまう問題への対処。 |
| 983 |
|
// (2007.10.29 yutaka) |
| 984 |
|
encryption_size = 4 + 1 + len; |
| 985 |
|
padding = block_size - (encryption_size % block_size); |
| 986 |
|
if (padding < 4) |
| 987 |
|
padding += block_size; |
| 988 |
|
encryption_size += padding; |
| 989 |
|
set_uint32(data, encryption_size - 4); |
| 990 |
|
data[4] = (unsigned char) padding; |
| 991 |
|
data_length = encryption_size + CRYPT_get_sender_MAC_size(pvar); |
| 992 |
|
#endif |
| 993 |
CRYPT_set_random_data(pvar, data + 5 + len, padding); |
CRYPT_set_random_data(pvar, data + 5 + len, padding); |
| 994 |
ret = CRYPT_build_sender_MAC(pvar, |
ret = CRYPT_build_sender_MAC(pvar, |
| 995 |
pvar->ssh_state.sender_sequence_number, |
pvar->ssh_state.sender_sequence_number, |
| 2911 |
if (c == NULL) |
if (c == NULL) |
| 2912 |
return; |
return; |
| 2913 |
|
|
| 2914 |
msg = buffer_init(); |
#if 0 |
| 2915 |
if (msg == NULL) { |
if (c->bufchain) { // chainに残っている場合はそのままつなぐ |
| 2916 |
// TODO: error check |
ssh2_channel_add_bufchain(c, buf, buflen); |
| 2917 |
return; |
return; |
| 2918 |
} |
} |
| 2919 |
buffer_put_int(msg, c->remote_id); |
#endif |
|
buffer_put_string(msg, (char *)buf, buflen); |
|
| 2920 |
|
|
| 2921 |
len = buffer_len(msg); |
if ((unsigned int)buflen > c->remote_window) { |
| 2922 |
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len); |
unsigned int offset = c->remote_window; |
| 2923 |
memcpy(outmsg, buffer_ptr(msg), len); |
#ifdef TBD |
| 2924 |
finish_send_packet(pvar); |
// 送れないデータはいったん保存しておく |
| 2925 |
buffer_free(msg); |
ssh2_channel_add_bufchain(c, buf + offset, buflen - offset); |
| 2926 |
|
#endif |
| 2927 |
|
buflen = offset; |
| 2928 |
|
} |
| 2929 |
|
if (buflen > 0) { |
| 2930 |
|
msg = buffer_init(); |
| 2931 |
|
if (msg == NULL) { |
| 2932 |
|
// TODO: error check |
| 2933 |
|
return; |
| 2934 |
|
} |
| 2935 |
|
buffer_put_int(msg, c->remote_id); |
| 2936 |
|
buffer_put_string(msg, (char *)buf, buflen); |
| 2937 |
|
|
| 2938 |
// remote window sizeの調整 |
len = buffer_len(msg); |
| 2939 |
if (len <= c->remote_window) { |
outmsg = begin_send_packet(pvar, SSH2_MSG_CHANNEL_DATA, len); |
| 2940 |
c->remote_window -= buflen; |
memcpy(outmsg, buffer_ptr(msg), len); |
| 2941 |
} |
finish_send_packet(pvar); |
| 2942 |
else { |
buffer_free(msg); |
| 2943 |
c->remote_window = 0; |
|
| 2944 |
|
// remote window sizeの調整 |
| 2945 |
|
if (len <= c->remote_window) { |
| 2946 |
|
c->remote_window -= buflen; |
| 2947 |
|
} |
| 2948 |
|
else { |
| 2949 |
|
c->remote_window = 0; |
| 2950 |
|
} |
| 2951 |
} |
} |
| 2952 |
} |
} |
| 2953 |
|
|
| 7303 |
// window sizeの調整 |
// window sizeの調整 |
| 7304 |
c->remote_window += adjust; |
c->remote_window += adjust; |
| 7305 |
|
|
| 7306 |
|
#ifdef TBD |
| 7307 |
|
// 送り残し |
| 7308 |
|
ssh2_channel_retry_send_bufchain(pvar, c); |
| 7309 |
|
#endif |
| 7310 |
|
|
| 7311 |
return TRUE; |
return TRUE; |
| 7312 |
} |
} |