|
From: Alex M. S. <arc...@us...> - 2010-09-21 17:46:22
|
Update of /cvsroot/nettle/nettle/c In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv20419/c Modified Files: keyboard nettle wimp Log Message: Largely commit James Bursa's changes for SSH support - some slight tweaks to the code in c/wimp which was preventing it building with Norcroft, and I've removed the \!Run wimpslot changes for the time being (I guess I'd like to do something clever based on whether it's Norcroft-built or gcc-built). Doesn't quite seem to work for me as-is (claims to be missing ciphers), but I don't think that's directly caused by anything in this patch. Index: keyboard =================================================================== RCS file: /cvsroot/nettle/nettle/c/keyboard,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** keyboard 1 Dec 2002 17:22:56 -0000 1.12 --- keyboard 21 Sep 2010 17:46:13 -0000 1.13 *************** *** 79,82 **** --- 79,86 ---- SETBLOCK (1, "\r"); } + else if (session->connection_type == NETTLE_SSH) + { + SETBLOCK (1, "\n"); + } else if (session->other_session_flags & NETTLE_OTHER_LINEFEED_MODE) { Index: nettle =================================================================== RCS file: /cvsroot/nettle/nettle/c/nettle,v retrieving revision 1.122 retrieving revision 1.123 diff -C2 -d -r1.122 -r1.123 *** nettle 13 Apr 2004 20:30:56 -0000 1.122 --- nettle 21 Sep 2010 17:46:13 -0000 1.123 *************** *** 165,170 **** } } - else - *port = 23; /* if the port is <1, then it's either invalid or was too big and got wrapped */ --- 165,168 ---- *************** *** 195,198 **** --- 193,199 ---- return false; + port = 23; + if (params->connection_type == NETTLE_SSH) + port = 22; if (get_host_port (host, &port) == false) return false; *************** *** 323,326 **** --- 324,330 ---- return false; + port = 23; + if (connection_type == NETTLE_SSH) + port = 22; if (get_host_port(string, &port) == false) return false; *************** *** 567,570 **** --- 571,580 ---- session->want_blink = false; session->socket_state = NETTLE_SESSION_NONE; + #ifdef WITH_SSH + session->ssh_session = NULL; + session->ssh_channel = NULL; + session->ssh_negotiate_state = 0; + session->ssh_more_read = false; + #endif session->dns = NULL; /* Should be null for non telnet/ssh sessions */ *************** *** 574,590 **** case NETTLE_TELNET: case NETTLE_SSH: ! /* host, port already parsed */ ! session->socket_handle=-1; ! session->socket_state=NETTLE_SESSION_RESOLVE; session->socket_port = params->port; ! strcpy (session->socket_host, params->host); ! session->dns = dns_gethostbyname(session->socket_host); ! assert(session->dns != NULL); ! ! if (params->connection_type==NETTLE_SSH) { session->local_echo=false; } - break; --- 584,595 ---- case NETTLE_TELNET: case NETTLE_SSH: ! session->socket_handle = -1; ! session->socket_state = NETTLE_SESSION_START; session->socket_port = params->port; ! strcpy(session->socket_host, params->host); ! if (params->connection_type == NETTLE_SSH) { session->local_echo=false; } break; *************** *** 767,774 **** case NETTLE_SSH: set_title_bar(session->window_handle, lookup_static ("title_conn")); - write_out_strings (session, - lookup_static_var ("lookup", 1, - session->socket_host), - "\r\n", 0); main_requirenull = true; break; --- 772,775 ---- *************** *** 798,801 **** --- 799,919 ---- } + + #ifdef WITH_SSH + /** + * Start SSH on a connected socket. + * + * Returns true on success, false on failure. + */ + bool connect_session_ssh(struct session_struct *session) + { + LIBSSH2_SESSION *ssh = session->ssh_session; + LIBSSH2_CHANNEL *channel = session->ssh_channel; + const char *fingerprint; + unsigned int i; + int code = 0; + char *errmsg; + + assert(session->connection_type == NETTLE_SSH); + assert(session->socket_state == NETTLE_SESSION_NEGOTIATE); + + if (ssh == NULL) + { + write_out_strings(session, "Nettle: Creating SSH session", 0); + + ssh = libssh2_session_init(); + if (!ssh) + return false; + + libssh2_session_set_blocking(ssh, 0); + + session->ssh_session = ssh; + } + + switch (session->ssh_negotiate_state) + { + case 0: + code = libssh2_session_startup(ssh, session->socket_handle); + if (code == 0) + { + fingerprint = libssh2_hostkey_hash(ssh, LIBSSH2_HOSTKEY_HASH_MD5); + write_out_strings(session, "\r\n", "Nettle: Fingerprint: ", 0); + for (i = 0; i < 16; i++) { + char hex[10]; + snprintf(hex, sizeof hex, "%02x ", (unsigned char) fingerprint[i]); + write_out_strings(session, hex, 0); + } + write_out_strings(session, "\r\n", 0); + } + break; + + case 1: + code = libssh2_userauth_password(ssh, session->login_user, + session->login_pass); + break; + + case 2: + channel = libssh2_channel_open_session(ssh); + if (channel) + session->ssh_channel = channel; + else + code = libssh2_session_last_errno(ssh); + break; + + case 3: + code = libssh2_channel_request_pty_ex(channel, + terminal_name[session->terminal_type], + strlen(terminal_name[session->terminal_type]), + NULL, 0, + session->terminal_size.x, + session->terminal_size.y, + 0, 0); + break; + + case 4: + code = libssh2_channel_shell(channel); + if (code == 0) + session->socket_state = NETTLE_SESSION_CONNECTED; + break; + } + + if (code == 0) + { + char state[10]; + session->ssh_negotiate_state++; + snprintf(state, sizeof state, "%i", session->ssh_negotiate_state); + write_out_strings(session, state, 0); + } + else if (code == LIBSSH2_ERROR_EAGAIN) + { + write_out_strings(session, ".", 0); + main_requirenull = true; + } + else + { + char message[20]; + snprintf(message, sizeof message, "%i", + session->ssh_negotiate_state); + libssh2_session_last_error(ssh, &errmsg, 0, 0); + write_out_strings(session, "\r\n", + "Nettle: SSH connection failed in step ", + message, ": ", errmsg, "\r\n", 0); + if (channel) + libssh2_channel_free(channel); + libssh2_session_disconnect(ssh, ""); + libssh2_session_free(ssh); + return false; + } + + if (session->socket_state == NETTLE_SESSION_CONNECTED) + { + write_out_strings(session, "\r\n", "Nettle: SSH connected", "\r\n", 0); + } + + return true; + } + #endif + + void write_out_string(struct session_struct *session, const char *string) { *************** *** 1008,1011 **** --- 1126,1132 ---- break; case NETTLE_SSH: + #ifdef WITH_SSH + return libssh2_channel_write(session->ssh_channel, data, length); + #endif break; case NETTLE_TASKWINDOW: *************** *** 1565,1568 **** --- 1686,1697 ---- break; + + case NETTLE_SSH: + #ifdef WITH_SSH + libssh2_channel_request_pty_size(session->ssh_channel, + session->terminal_size.x, + session->terminal_size.y); + #endif + break; } } Index: wimp =================================================================== RCS file: /cvsroot/nettle/nettle/c/wimp,v retrieving revision 1.198 retrieving revision 1.199 diff -C2 -d -r1.198 -r1.199 *** wimp 29 Aug 2010 19:45:29 -0000 1.198 --- wimp 21 Sep 2010 17:46:13 -0000 1.199 *************** *** 190,199 **** set_title_bar(session->window_handle,string); ! session->socket_state = NETTLE_SESSION_CONNECTED; ! write_out_strings(session, ! lookup_static_var("connected", 1, ! socket_ip_string(session->socket_ip)), ! "\r\n", ! 0); main_requirenull = true; /* read any data waiting on the socket */ --- 190,206 ---- set_title_bar(session->window_handle,string); ! if (session->connection_type == NETTLE_SSH) ! { ! session->socket_state = NETTLE_SESSION_NEGOTIATE; ! } ! else ! { ! session->socket_state = NETTLE_SESSION_CONNECTED; ! write_out_strings(session, ! lookup_static_var("connected", 1, ! socket_ip_string(session->socket_ip)), ! "\r\n", ! 0); ! } main_requirenull = true; /* read any data waiting on the socket */ *************** *** 226,229 **** --- 233,247 ---- + static void wimp_pollnegotiate(struct session_struct *session) + { + #ifdef WITH_SSH + if (!connect_session_ssh(session)) { + socket_close(session->socket_handle); + session->socket_handle = -1; + session->socket_state = NETTLE_SESSION_NONE; + } + #endif + } + static void wimp_pollsocket(struct session_struct *session) *************** *** 231,234 **** --- 249,254 ---- int packet_length=-1; char receive_block[RECEIVE_BLOCK_LENGTH]; + bool eof = false; + const char *error = NULL; switch (session->connection_type) *************** *** 237,258 **** packet_length = recv(session->socket_handle, receive_block, RECEIVE_BLOCK_LENGTH, 0); break; case NETTLE_SSH: break; } ! if (packet_length == -1 && errno == EWOULDBLOCK) ! /* we've read all the available data */ ! return; ! ! if (packet_length == 0 || packet_length == -1) { /* EOF or error condition */ set_title_bar(session->window_handle, lookup_static("title_disconnect")); reset_terminal(session); ! if (packet_length == 0) { - /* EOF received */ write_out_strings(session, "\r\n", lookup_static("closed"), "\r\n", 0); } --- 257,293 ---- packet_length = recv(session->socket_handle, receive_block, RECEIVE_BLOCK_LENGTH, 0); + if (packet_length == -1 && errno == EWOULDBLOCK) + /* we've read all the available data */ + return; + else if (packet_length == -1) + error = socket_strerror(errno); + else if (packet_length == 0) + /* EOF received */ + eof = true; break; case NETTLE_SSH: + #ifdef WITH_SSH + packet_length = libssh2_channel_read(session->ssh_channel, receive_block, + RECEIVE_BLOCK_LENGTH); + if (packet_length == 0 || packet_length == LIBSSH2_ERROR_EAGAIN) + /* we've read all the available data */ + return; + else if (packet_length < 0) + libssh2_session_last_error(session->ssh_session, &error, 0, 0); + else + /* there may be more data to read next time */ + session->ssh_more_read = true; + #endif break; } ! if (eof || error) { /* EOF or error condition */ set_title_bar(session->window_handle, lookup_static("title_disconnect")); reset_terminal(session); ! if (eof) { write_out_strings(session, "\r\n", lookup_static("closed"), "\r\n", 0); } *************** *** 261,265 **** write_out_strings(session, "\r\n", lookup_static_var("socketerror", 1, ! socket_strerror(errno)), "\r\n", 0); } --- 296,300 ---- write_out_strings(session, "\r\n", lookup_static_var("socketerror", 1, ! error), "\r\n", 0); } *************** *** 304,307 **** --- 339,370 ---- switch (session->socket_state) { + case NETTLE_SESSION_START: + if (session->connection_type == NETTLE_SSH && + session->login_user == NULL) { + write_out_strings(session, "SSH user: ", 0); + session->line_editor_buffer[0] = 0; + session->socket_state = NETTLE_SESSION_PROMPT_USER; + } else if (session->connection_type == NETTLE_SSH && + session->login_pass == NULL) { + write_out_strings(session, "SSH password: ", 0); + session->line_editor_buffer[0] = 0; + session->socket_state = NETTLE_SESSION_PROMPT_PASS; + } else { + write_out_strings (session, + lookup_static_var ("lookup", 1, + session->socket_host), + "\r\n", 0); + session->dns = dns_gethostbyname(session->socket_host); + assert(session->dns != NULL); + session->socket_state = NETTLE_SESSION_RESOLVE; + main_requirenull = true; + } + break; + + case NETTLE_SESSION_PROMPT_USER: + case NETTLE_SESSION_PROMPT_PASS: + /* awaiting entry - see key_pressed() */ + break; + case NETTLE_SESSION_RESOLVE: wimp_pollresolve(session); *************** *** 312,316 **** --- 375,388 ---- break; + case NETTLE_SESSION_NEGOTIATE: + wimp_pollnegotiate(session); + break; + case NETTLE_SESSION_CONNECTED: + #ifdef WITH_SSH + if (session->ssh_more_read) + wimp_pollsocket(session); + #endif + if (session->connection_type != NETTLE_TASKWINDOW) { *************** *** 1768,1771 **** --- 1840,1901 ---- } } + else if (session->socket_state == NETTLE_SESSION_PROMPT_USER) + { + if ((' ' <= key && key <= '~') || + (128 <= key && key <= 255)) + { + char s[2]; + + s[0] = key; + s[1] = '\0'; + + if (strlen(session->line_editor_buffer) < + MAX_LINEEDITOR_LENGTH - 2) + { + strcat(session->line_editor_buffer, s); + write_out_strings(session, s, 0); + } + key_status = true; + } + else if (key == 13) + { + session->login_user = strdup(session->line_editor_buffer); + write_out_strings(session, "\r\n", "SSH password: ", 0); + session->line_editor_buffer[0] = 0; + session->socket_state = NETTLE_SESSION_PROMPT_PASS; + key_status = true; + } + } + else if (session->socket_state == NETTLE_SESSION_PROMPT_PASS) + { + if ((' ' <= key && key <= '~') || + (128 <= key && key <= 255)) + { + char s[2]; + + s[0] = key; + s[1] = '\0'; + + if (strlen(session->line_editor_buffer) < + MAX_LINEEDITOR_LENGTH - 2) + { + strcat(session->line_editor_buffer, s); + write_out_strings(session, "*", 0); + } + key_status = true; + } + else if (key == 13) + { + session->login_pass = strdup(session->line_editor_buffer); + write_out_strings (session, "\r\n", + lookup_static_var ("lookup", 1, + session->socket_host), + "\r\n", 0); + session->dns = dns_gethostbyname(session->socket_host); + assert(session->dns != NULL); + session->socket_state = NETTLE_SESSION_RESOLVE; + key_status = true; + } + } } } *************** *** 3170,3174 **** --- 3300,3308 ---- char *menu_title =get_menu_item("Connection"); char *menu_telnet =get_menu_item("Telnet"); + #ifdef WITH_SSH + char *menu_ssh =get_menu_item("SSH"); + #else char *menu_ssh =get_grey_menu_item("SSH"); + #endif char *menu_taskwindow=get_last_menu_item("Taskwindow"); |