int main(int ac, char **av) { unsigned int pass, i; SshBuffer buffer, buffer2; SocksInfo socksinfo, socksreturn; SocksError ret; ssh_buffer_init(&buffer); ssh_buffer_init(&buffer2); for(pass = 0; pass < 20000; pass++) { ssh_buffer_clear(&buffer); socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 4; socksinfo->command_code = (pass & 1) + 1; socksinfo->ip = ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) / sizeof(ip_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) / sizeof(port_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_client_generate_open(&buffer, socksinfo) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_client_generate_open fails"); if (pass & 1) { unsigned char *p; unsigned int len; ssh_buffer_clear(&buffer2); p = ssh_buffer_ptr(&buffer); len = ssh_buffer_len(&buffer); /* Give partial buffer */ for(i = 0; i + 1 < len; i++) { ssh_buffer_append(&buffer2, p + i, 1); if (ssh_socks_server_parse_open(&buffer2, &socksreturn) != SSH_SOCKS_TRY_AGAIN) ssh_fatal("ssh_socks_server_parse_open fails in partial data (should return try_again)"); } ssh_buffer_append(&buffer2, p + i, 1); if (ssh_socks_server_parse_open(&buffer2, &socksreturn) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_parse_open fails for partial data (should return success)"); if (ssh_buffer_len(&buffer2) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } else { if (ssh_socks_server_parse_open(&buffer, &socksreturn) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_parse_open fails for partial data (should return success)"); if (ssh_buffer_len(&buffer) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } if (socksinfo->socks_version_number != socksreturn->socks_version_number) ssh_fatal("socks_version_numbers differ request"); if (socksinfo->command_code != socksreturn->command_code) ssh_fatal("command_codes differ request"); if (strcmp(socksinfo->ip, socksreturn->ip) != 0) ssh_fatal("ip numbers differ request"); if (strcmp(socksinfo->port, socksreturn->port) != 0) ssh_fatal("port numbers differ request"); if (strcmp(socksinfo->username, socksreturn->username) != 0) ssh_fatal("usernames differ request"); ssh_socks_free(&socksreturn); ssh_socks_free(&socksinfo); ssh_buffer_clear(&buffer); socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 0; socksinfo->command_code = (pass % 4) + 90; socksinfo->ip = ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) / sizeof(ip_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) / sizeof(port_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_server_generate_reply(&buffer, socksinfo) != SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_generate_reply fails"); if (pass & 1) { unsigned char *p; unsigned int len; ssh_buffer_clear(&buffer2); p = ssh_buffer_ptr(&buffer); len = ssh_buffer_len(&buffer); /* Give partial buffer */ for(i = 0; i + 1 < len; i++) { ssh_buffer_append(&buffer2, p + i, 1); if (ssh_socks_client_parse_reply(&buffer2, &socksreturn) != SSH_SOCKS_TRY_AGAIN) ssh_fatal("ssh_socks_server_parse_open fails in partial data (should return try_again)"); } ssh_buffer_append(&buffer2, p + i, 1); ret = ssh_socks_client_parse_reply(&buffer2, &socksreturn); if (((pass % 4) == 0 && ret != SSH_SOCKS_SUCCESS) || ((pass % 4) == 1 && ret != SSH_SOCKS_FAILED_REQUEST) || ((pass % 4) == 2 && ret != SSH_SOCKS_FAILED_IDENTD) || ((pass % 4) == 3 && ret != SSH_SOCKS_FAILED_USERNAME)) ssh_fatal("ssh_socks_client_parse_reply fails for partial data"); if (ret == SSH_SOCKS_SUCCESS && ssh_buffer_len(&buffer2) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } else { ret = ssh_socks_client_parse_reply(&buffer, &socksreturn); if (((pass % 4) == 0 && ret != SSH_SOCKS_SUCCESS) || ((pass % 4) == 1 && ret != SSH_SOCKS_FAILED_REQUEST) || ((pass % 4) == 2 && ret != SSH_SOCKS_FAILED_IDENTD) || ((pass % 4) == 3 && ret != SSH_SOCKS_FAILED_USERNAME)) ssh_fatal("ssh_socks_client_parse_reply fails"); if (ret == SSH_SOCKS_SUCCESS && ssh_buffer_len(&buffer) != 0) ssh_fatal("Junk left to buffer after server_parse_open"); } if (ret == SSH_SOCKS_SUCCESS) { if (socksinfo->socks_version_number != socksreturn->socks_version_number) ssh_fatal("socks_version_numbers differ reply"); if (socksinfo->command_code != socksreturn->command_code) ssh_fatal("command_codes differ reply"); if (strcmp(socksinfo->ip, socksreturn->ip) != 0) ssh_fatal("ip numbers differ reply"); if (strcmp(socksinfo->port, socksreturn->port) != 0) ssh_fatal("port numbers differ reply"); ssh_socks_free(&socksreturn); } ssh_socks_free(&socksinfo); } ssh_buffer_clear(&buffer); for(pass = 0; pass < (sizeof(ip_invalid_numbers) / sizeof(ip_invalid_numbers[0])); pass++) { socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 4; socksinfo->command_code = (pass & 1) + 1; socksinfo->ip = ssh_xstrdup(ip_invalid_numbers[pass % (sizeof(ip_invalid_numbers) / sizeof(ip_invalid_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) / sizeof(port_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_client_generate_open(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_client_generate_open success (should fail, ip)"); socksinfo->socks_version_number = 0; socksinfo->command_code = (pass % 4) + 90; if (ssh_socks_server_generate_reply(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_generate_reply success (should fail, ip)"); ssh_socks_free(&socksinfo); } for(pass = 0; pass < (sizeof(port_invalid_numbers) / sizeof(port_invalid_numbers[0])); pass++) { socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec)); socksinfo->socks_version_number = 4; socksinfo->command_code = (pass & 1) + 1; socksinfo->ip = ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) / sizeof(ip_numbers[0]))]); socksinfo->port = ssh_xstrdup(port_invalid_numbers[pass % (sizeof(port_invalid_numbers) / sizeof(port_invalid_numbers[0]))]); socksinfo->username = ssh_xstrdup(usernames[pass % (sizeof(usernames) / sizeof(usernames[0]))]); if (ssh_socks_client_generate_open(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_client_generate_open success (should fail, port)"); socksinfo->command_code = (pass % 4) + 90; socksinfo->socks_version_number = 0; if (ssh_socks_server_generate_reply(&buffer, socksinfo) == SSH_SOCKS_SUCCESS) ssh_fatal("ssh_socks_server_generate_reply success (should fail, port)"); ssh_socks_free(&socksinfo); } if (ssh_buffer_len(&buffer) != 0) ssh_fatal("some of the failed ssh_socks_*_generate_* function wrote something to buffer, size != 0"); ssh_buffer_uninit(&buffer); ssh_buffer_uninit(&buffer2); return 0; }
void tcp_connect_socks_connect_done_cb(SshTcpError error, SshStream stream, void *context) { SshFSMThread thread = (SshFSMThread) context; ConnectContext c = (ConnectContext) ssh_fsm_get_gdata(thread); struct SocksInfoRec socksinfo; SocksError ret; unsigned char host_port[64], *next = NULL; c->handle = NULL; if (error != SSH_TCP_OK) { /* Get next address. */ if (ssh_ustrchr(c->socks_next_address, ',')) { c->socks_next_address = ssh_ustrchr(c->socks_next_address, ',') + 1; } else { /* At end of list; consider it as a failure. */ if (tcp_connect_register_failure(thread, error)) { SSH_FSM_CONTINUE_AFTER_CALLBACK(thread); return; } c->socks_next_address = c->socks_addresses; } /* Try connecting again. */ SSH_FSM_SET_NEXT(tcp_connect_socks_connect); SSH_FSM_CONTINUE_AFTER_CALLBACK(thread); return; } /* Save the stream. */ c->stream = stream; /* Set the callback so that we'll get any required read/write notifications. */ ssh_stream_set_callback(stream, tcp_connect_socks_notify, thread); if (c->next_address && (next = ssh_ustrchr(c->next_address, ',')) != NULL) { *next = '\0'; next++; } if (c->socks_type == SSH_TCP_SOCKS5) { socksinfo.socks_version_number = 5; socksinfo.command_code = SSH_SOCKS5_COMMAND_CODE_CONNECT; if (c->next_address) socksinfo.ip = (unsigned char *) c->next_address; else socksinfo.ip = c->host_name; } else { socksinfo.socks_version_number = 4; socksinfo.command_code = SSH_SOCKS4_COMMAND_CODE_CONNECT; socksinfo.ip = (unsigned char *) c->next_address; } ssh_snprintf(host_port, sizeof(host_port), "%d", c->host_port); socksinfo.port = host_port; socksinfo.username = c->user_name; ssh_buffer_clear(c->socks_buf); SSH_FSM_SET_NEXT(tcp_connect_socks_send); ret = ssh_socks_client_generate_methods(c->socks_buf, &socksinfo); if (ret == SSH_SOCKS_SUCCESS) ret = ssh_socks_client_generate_open(c->socks_buf, &socksinfo); if (ret != SSH_SOCKS_SUCCESS) { if (next != NULL) { c->stream = NULL; ssh_stream_destroy(stream); c->next_address = next; SSH_FSM_SET_NEXT(tcp_connect_socks_lookup); } else { if (ret == SSH_SOCKS_ERROR_INVALID_ARGUMENT) c->error = SSH_TCP_NO_ADDRESS; else c->error = SSH_TCP_FAILURE; SSH_FSM_SET_NEXT(tcp_connect_finish); } } SSH_FSM_CONTINUE_AFTER_CALLBACK(thread); }