int ssh_execute_message_callbacks(ssh_session session){ ssh_message msg=NULL; int ret; ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); if(!session->ssh_message_list) return SSH_OK; if(session->ssh_message_callback){ while((msg=ssh_message_pop_head(session)) != NULL) { ret=session->ssh_message_callback(session,msg, session->ssh_message_callback_data); if(ret==1){ ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) return ret; } else { ssh_message_free(msg); } } } else { while((msg=ssh_message_pop_head(session)) != NULL) { ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) return ret; } } return SSH_OK; }
void server_handle_message(ssh_session s, ssh_message m, int type, int subtype, int *state) { int handled = 0; if((*state == SERVER_CONNECTED) && (type == SSH_REQUEST_AUTH) && (subtype == SSH_AUTH_METHOD_PUBLICKEY)) { ssh_public_key key = ssh_message_auth_publickey(m); ssh_string keystr = publickey_to_string(key); char *keyhash = pubkey_hash(keystr); int has_sig = ssh_message_auth_publickey_state(m); if(has_sig == SSH_PUBLICKEY_STATE_NONE) { if(authenticate(keyhash, 1)) { //FIXME: type detection ssh_string algostr = ssh_string_from_char("ssh-rsa"); ssh_message_auth_reply_pk_ok(m, algostr, keystr); handled = 1; ssh_string_free(algostr); } } else if(has_sig == SSH_PUBLICKEY_STATE_VALID) { if(authenticate(keyhash, 0)) { session_event(s, "authenticated", keyhash); ssh_message_auth_reply_success(m, 0); handled = 1; *state = SERVER_AUTHENTICATED; } else { ssh_message_reply_default(m); handled = 1; *state = SERVER_CLOSED; } } ssh_string_free(keystr); free(keyhash); } else if((*state == SERVER_AUTHENTICATED) && (type == SSH_REQUEST_CHANNEL_OPEN) && (subtype == SSH_CHANNEL_SESSION)) { ssh_channel chan = ssh_message_channel_request_open_reply_accept(m); if(!chan) session_error(s, "open-channel"); handled = 1; session_event(s, "channel-opened", NULL); channel_to_file(chan, 1); ssh_channel_free(chan); *state = SERVER_CLOSED; } if(!handled) ssh_message_reply_default(m); }
static int authenticate(ssh_session session) { ssh_message message; do { message=ssh_message_get(session); if(!message) break; switch(ssh_message_type(message)){ case SSH_REQUEST_AUTH: switch(ssh_message_subtype(message)){ case SSH_AUTH_METHOD_PASSWORD: printf("User %s wants to auth with pass %s\n", ssh_message_auth_user(message), ssh_message_auth_password(message)); if(auth_password(ssh_message_auth_user(message), ssh_message_auth_password(message))){ ssh_message_auth_reply_success(message,0); ssh_message_free(message); return 1; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); // not authenticated, send default message ssh_message_reply_default(message); break; case SSH_AUTH_METHOD_NONE: default: printf("User %s wants to auth with unknown auth %d\n", ssh_message_auth_user(message), ssh_message_subtype(message)); ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); break; } break; default: ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); } ssh_message_free(message); } while (1); return 0; }
/** * @internal * * @brief Add a message to the current queue of messages to be parsed and/or call * the various callback functions. * * @param[in] session The SSH session to add the message. * * @param[in] message The message to add to the queue. */ void ssh_message_queue(ssh_session session, ssh_message message){ if (message != NULL) { #ifdef WITH_SERVER int ret; /* probably not the best place to execute server callbacks, but still better * than nothing. */ ret = ssh_execute_server_callbacks(session, message); if (ret == SSH_OK){ ssh_message_free(message); return; } #endif /* WITH_SERVER */ if(session->ssh_message_callback != NULL) { ssh_execute_message_callback(session, message); return; } if (session->server_callbacks != NULL){ /* if we have server callbacks, but nothing was executed, it means we are * in non-synchronous mode, and we just don't care about the message we * received. Just send a default response. Do not queue it. */ ssh_message_reply_default(message); ssh_message_free(message); return; } if(session->ssh_message_list == NULL) { session->ssh_message_list = ssh_list_new(); } if (session->ssh_message_list != NULL) { ssh_list_append(session->ssh_message_list, message); } } }
static int ssh_execute_client_request(ssh_session session, ssh_message msg) { ssh_channel channel = NULL; int rc = SSH_AGAIN; if (msg->type == SSH_REQUEST_CHANNEL_OPEN && msg->channel_request_open.type == SSH_CHANNEL_X11 && ssh_callbacks_exists(session->common.callbacks, channel_open_request_x11_function)) { channel = session->common.callbacks->channel_open_request_x11_function (session, msg->channel_request_open.originator, msg->channel_request_open.originator_port, session->common.callbacks->userdata); if (channel != NULL) { rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel); return rc; } else { ssh_message_reply_default(msg); } return SSH_OK; } return rc; }
/* Logs password auth attempts. Always replies with SSH_MESSAGE_USERAUTH_FAILURE. */ int handle_auth(ssh_session session) { struct connection con; con.session = session; /* Perform key exchange. */ if (ssh_handle_key_exchange(con.session)) { fprintf(stderr, "Error exchanging keys: `%s'.\n", ssh_get_error(con.session)); return -1; } if (DEBUG) { printf("Successful key exchange.\n"); } /* Wait for a message, which should be an authentication attempt. Send the default * reply if it isn't. Log the attempt and quit. */ while (1) { if ((con.message = ssh_message_get(con.session)) == NULL) { break; } /* Log the authentication request and disconnect. */ if (ssh_message_subtype(con.message) == SSH_AUTH_METHOD_PASSWORD) { log_attempt(&con); } else { if (DEBUG) { fprintf(stderr, "Not a password authentication attempt.\n"); } } /* Send the default message regardless of the request type. */ ssh_message_reply_default(con.message); ssh_message_free(con.message); } if (DEBUG) { printf("Exiting child.\n"); } return 0; }
CHANNEL *recv_channel(SSH_SESSION *session){ CHANNEL *chan=NULL; SSH_MESSAGE *message; int sftp=0; do { message=ssh_message_get(session); if(message){ switch(ssh_message_type(message)){ case SSH_CHANNEL_REQUEST_OPEN: if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){ chan=ssh_message_channel_request_open_reply_accept(message); break; } default: ssh_message_reply_default(message); } ssh_message_free(message); } } while(message && !chan); if(!chan) return NULL; do { message=ssh_message_get(session); if(message && ssh_message_type(message)==SSH_CHANNEL_REQUEST && ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SUBSYSTEM){ if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){ sftp=1; ssh_message_channel_request_reply_success(message); break; } } if(!sftp){ ssh_message_reply_default(message); } ssh_message_free(message); } while (message && !sftp); if(!message) return NULL; return chan; }
static int ssh_execute_message_callback(ssh_session session, ssh_message msg) { int ret; if(session->ssh_message_callback != NULL) { ret = session->ssh_message_callback(session, msg, session->ssh_message_callback_data); if(ret == 1) { ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) { return ret; } } else { ssh_message_free(msg); } } else { ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) { return ret; } } return SSH_OK; }
int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_message message; ssh_channel chan=0; char buf[2048]; int auth=0; int sftp=0; int i; int r; sshbind=ssh_bind_new(); session=ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; #endif #ifdef WITH_PCAP set_pcap(session); #endif if(ssh_bind_listen(sshbind)<0){ printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); return 1; } r=ssh_bind_accept(sshbind,session); if(r==SSH_ERROR){ printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); return 1; } if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } do { message=ssh_message_get(session); if(!message) break; switch(ssh_message_type(message)){ case SSH_REQUEST_AUTH: switch(ssh_message_subtype(message)){ case SSH_AUTH_METHOD_PASSWORD: printf("User %s wants to auth with pass %s\n", ssh_message_auth_user(message), ssh_message_auth_password(message)); if(auth_password(ssh_message_auth_user(message), ssh_message_auth_password(message))){ auth=1; ssh_message_auth_reply_success(message,0); break; } // not authenticated, send default message case SSH_AUTH_METHOD_NONE: default: ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD); ssh_message_reply_default(message); break; } break; default: ssh_message_reply_default(message); } ssh_message_free(message); } while (!auth); if(!auth){ printf("auth error: %s\n",ssh_get_error(session)); ssh_disconnect(session); return 1; } do { message=ssh_message_get(session); if(message){ switch(ssh_message_type(message)){ case SSH_REQUEST_CHANNEL_OPEN: if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){ chan=ssh_message_channel_request_open_reply_accept(message); break; } default: ssh_message_reply_default(message); } ssh_message_free(message); } } while(message && !chan); if(!chan){ printf("error : %s\n",ssh_get_error(session)); ssh_finalize(); return 1; } do { message=ssh_message_get(session); if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL && ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){ // if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){ sftp=1; ssh_message_channel_request_reply_success(message); break; // } } if(!sftp){ ssh_message_reply_default(message); } ssh_message_free(message); } while (message && !sftp); if(!sftp){ printf("error : %s\n",ssh_get_error(session)); return 1; } printf("it works !\n"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } } } while (i>0); ssh_disconnect(session); ssh_bind_free(sshbind); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; }
int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_message message; ssh_channel chan=0; char buf[2048]; int auth=0; int shell=0; int i; int r; sshbind=ssh_bind_new(); session=ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; #endif #ifdef WITH_PCAP set_pcap(session); #endif if(ssh_bind_listen(sshbind)<0){ printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); return 1; } printf("Started sample libssh sshd on port %d\n", port); printf("You can login as the user %s with the password %s\n", SSHD_USER, SSHD_PASSWORD); r = ssh_bind_accept(sshbind, session); if(r==SSH_ERROR){ printf("Error accepting a connection: %s\n", ssh_get_error(sshbind)); return 1; } if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } /* proceed to authentication */ auth = authenticate(session); if (!auth || !authenticated) { printf("Authentication error: %s\n", ssh_get_error(session)); ssh_disconnect(session); return 1; } /* wait for a channel session */ do { message = ssh_message_get(session); if(message){ if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN && ssh_message_subtype(message) == SSH_CHANNEL_SESSION) { chan = ssh_message_channel_request_open_reply_accept(message); ssh_message_free(message); break; } else { ssh_message_reply_default(message); ssh_message_free(message); } } else { break; } } while(!chan); if(!chan) { printf("Error: cleint did not ask for a channel session (%s)\n", ssh_get_error(session)); ssh_finalize(); return 1; } /* wait for a shell */ do { message = ssh_message_get(session); if(message != NULL) { if(ssh_message_type(message) == SSH_REQUEST_CHANNEL && ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) { shell = 1; ssh_message_channel_request_reply_success(message); ssh_message_free(message); break; } ssh_message_reply_default(message); ssh_message_free(message); } else { break; } } while(!shell); if(!shell) { printf("Error: No shell requested (%s)\n", ssh_get_error(session)); return 1; } printf("it works !\n"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { if(*buf == '' || *buf == '') break; if(i == 1 && *buf == '\r') ssh_channel_write(chan, "\r\n", 2); else ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } } } while (i>0); ssh_channel_close(chan); ssh_disconnect(session); ssh_bind_free(sshbind); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; }
static int authenticate(ssh_session session) { ssh_message message; name = "\n\nKeyboard-Interactive Fancy Authentication\n"; instruction = "Please enter your real name and your password"; prompts[0] = "Real name: "; prompts[1] = "Password: "******"User %s wants to auth with pass %s\n", ssh_message_auth_user(message), ssh_message_auth_password(message)); if(auth_password(ssh_message_auth_user(message), ssh_message_auth_password(message))){ ssh_message_auth_reply_success(message,0); ssh_message_free(message); return 1; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); // not authenticated, send default message ssh_message_reply_default(message); break; case SSH_AUTH_METHOD_INTERACTIVE: if(!ssh_message_auth_kbdint_is_response(message)) { printf("User %s wants to auth with kbdint\n", ssh_message_auth_user(message)); ssh_message_auth_interactive_request(message, name, instruction, 2, prompts, echo); } else { if(kbdint_check_response(session)) { ssh_message_auth_reply_success(message,0); ssh_message_free(message); return 1; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); } break; case SSH_AUTH_METHOD_NONE: default: printf("User %s wants to auth with unknown auth %d\n", ssh_message_auth_user(message), ssh_message_subtype(message)); ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); break; } break; default: ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); } ssh_message_free(message); } while (1); return 0; }
// Parse an SSH command message and do something bool SSHServer::processSSHMessage(ssh_message message) { if (!message) { return false; } switch(ssh_message_type(message)){ case SSH_REQUEST_AUTH: switch(ssh_message_subtype(message)) { // not authenticated, send default message case SSH_AUTH_METHOD_NONE: break; case SSH_AUTH_METHOD_PASSWORD: { log_debug(_("User %s wants to auth with pass %s\n"), ssh_message_auth_user(message), ssh_message_auth_password(message)); string user = ssh_message_auth_user(message); string passwd = ssh_message_auth_password(message); if (authPassword(user, passwd)){ // auth=1; ssh_message_auth_reply_success(message,0); break; } break; } case SSH_AUTH_METHOD_HOSTBASED: break; case SSH_AUTH_METHOD_PUBLICKEY: break; case SSH_AUTH_METHOD_INTERACTIVE: break; case SSH_AUTH_METHOD_UNKNOWN: break; default: ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD); ssh_message_reply_default(message); break; } case SSH_REQUEST_CHANNEL_OPEN: if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){ _channel = ssh_message_channel_request_open_reply_accept(message); break; } break; // case SSH_CHANNEL_REQUEST_EXEC: // break; case SSH_CHANNEL_REQUEST_ENV: break; case SSH_CHANNEL_REQUEST_SUBSYSTEM: break; case SSH_CHANNEL_REQUEST_WINDOW_CHANGE: break; case SSH_CHANNEL_REQUEST_UNKNOWN: break; default: ssh_message_reply_default(message); } ssh_message_free(message); return false; }
static int ssh_execute_server_request(ssh_session session, ssh_message msg) { ssh_channel channel = NULL; int rc; switch(msg->type) { case SSH_REQUEST_AUTH: if (msg->auth_request.method == SSH_AUTH_METHOD_PASSWORD && ssh_callbacks_exists(session->server_callbacks, auth_password_function)) { rc = session->server_callbacks->auth_password_function(session, msg->auth_request.username, msg->auth_request.password, session->server_callbacks->userdata); if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL) { ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL); } else { ssh_message_reply_default(msg); } return SSH_OK; } else if(msg->auth_request.method == SSH_AUTH_METHOD_PUBLICKEY && ssh_callbacks_exists(session->server_callbacks, auth_pubkey_function)) { rc = session->server_callbacks->auth_pubkey_function(session, msg->auth_request.username, msg->auth_request.pubkey, msg->auth_request.signature_state, session->server_callbacks->userdata); if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL){ ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL); } else { ssh_message_reply_default(msg); } return SSH_OK; } break; case SSH_REQUEST_CHANNEL_OPEN: if (msg->channel_request_open.type == SSH_CHANNEL_SESSION && ssh_callbacks_exists(session->server_callbacks, channel_open_request_session_function)) { channel = session->server_callbacks->channel_open_request_session_function(session, session->server_callbacks->userdata); if (channel != NULL) { rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel); return SSH_OK; } else { ssh_message_reply_default(msg); } return SSH_OK; } break; case SSH_REQUEST_CHANNEL: channel = msg->channel_request.channel; if (msg->channel_request.type == SSH_CHANNEL_REQUEST_PTY && ssh_callbacks_exists(channel->callbacks, channel_pty_request_function)) { rc = channel->callbacks->channel_pty_request_function(session, channel, msg->channel_request.TERM, msg->channel_request.width, msg->channel_request.height, msg->channel_request.pxwidth, msg->channel_request.pxheight, channel->callbacks->userdata); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_SHELL && ssh_callbacks_exists(channel->callbacks, channel_shell_request_function)) { rc = channel->callbacks->channel_shell_request_function(session, channel, channel->callbacks->userdata); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_X11 && ssh_callbacks_exists(channel->callbacks, channel_x11_req_function)) { channel->callbacks->channel_x11_req_function(session, channel, msg->channel_request.x11_single_connection, msg->channel_request.x11_auth_protocol, msg->channel_request.x11_auth_cookie, msg->channel_request.x11_screen_number, channel->callbacks->userdata); ssh_message_channel_request_reply_success(msg); return SSH_OK; } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_WINDOW_CHANGE && ssh_callbacks_exists(channel->callbacks, channel_pty_window_change_function)) { rc = channel->callbacks->channel_pty_window_change_function(session, channel, msg->channel_request.height, msg->channel_request.width, msg->channel_request.pxheight, msg->channel_request.pxwidth, channel->callbacks->userdata); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_EXEC && ssh_callbacks_exists(channel->callbacks, channel_exec_request_function)) { rc = channel->callbacks->channel_exec_request_function(session, channel, msg->channel_request.command, channel->callbacks->userdata); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_ENV && ssh_callbacks_exists(channel->callbacks, channel_env_request_function)) { rc = channel->callbacks->channel_env_request_function(session, channel, msg->channel_request.var_name, msg->channel_request.var_value, channel->callbacks->userdata); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_SUBSYSTEM && ssh_callbacks_exists(channel->callbacks, channel_subsystem_request_function)) { rc = channel->callbacks->channel_subsystem_request_function(session, channel, msg->channel_request.subsystem, channel->callbacks->userdata); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } break; case SSH_REQUEST_SERVICE: if (ssh_callbacks_exists(session->server_callbacks, service_request_function)) { rc = session->server_callbacks->service_request_function(session, msg->service_request.service, session->server_callbacks->userdata); if (rc == 0) { ssh_message_reply_default(msg); } else { ssh_disconnect(session); } return SSH_OK; } return SSH_AGAIN; case SSH_REQUEST_GLOBAL: break; } return SSH_AGAIN; }