static void parse_username_password(struct vsf_session* p_sess) { while (1) { /* Kitsune: update point */ kitsune_update("prelogin.c"); /**DSU updatepoint */ /* Kitsune */ vsf_sysutil_kitsune_set_update_point("prelogin.c"); vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str, &p_sess->ftp_arg_str, 1); if (str_equal_text(&p_sess->ftp_cmd_str, "USER")) { handle_user_command(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS")) { handle_pass_command(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT")) { vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye."); vsf_sysutil_exit(0); } else { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Please login with USER and PASS."); } } }
static void handle_user_command(struct vsf_session* p_sess) { /* SECURITY: If we're in anonymous only-mode, immediately reject * non-anonymous usernames in the hope we save passwords going plaintext * over the network */ int is_anon = 1; str_copy(&p_sess->user_str, &p_sess->ftp_arg_str); str_upper(&p_sess->ftp_arg_str); if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") && !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS")) { is_anon = 0; } if (!tunable_local_enable && !is_anon) { vsf_cmdio_write( p_sess, FTP_LOGINERR, "This FTP server is anonymous only."); str_empty(&p_sess->user_str); return; } if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl) { vsf_cmdio_write( p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption."); str_empty(&p_sess->user_str); return; } if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl && tunable_force_local_logins_ssl) { vsf_cmdio_write( p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption."); str_empty(&p_sess->user_str); return; } if (!str_isempty(&p_sess->userlist_str)) { int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str); if ((located && tunable_userlist_deny) || (!located && !tunable_userlist_deny)) { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied."); str_empty(&p_sess->user_str); return; } } if (is_anon && tunable_no_anon_password) { /* Fake a password */ str_alloc_text(&p_sess->ftp_arg_str, "<no password>"); handle_pass_command(p_sess); } else { vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password."); } }
static void handle_get(struct vsf_session* p_sess) { p_sess->is_http = 1; str_copy(&p_sess->http_get_arg, &p_sess->ftp_arg_str); str_alloc_text(&p_sess->user_str, "FTP"); str_alloc_text(&p_sess->ftp_arg_str, "<http>"); handle_pass_command(p_sess); }
static void parse_username_password(struct vsf_session* p_sess) { while (1) { vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str, &p_sess->ftp_arg_str, 1); if (str_equal_text(&p_sess->ftp_cmd_str, "USER")) { handle_user_command(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS")) { handle_pass_command(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT")) { vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye."); vsf_sysutil_exit(0); } else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT")) { handle_feat(p_sess); } else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "AUTH")) { handle_auth(p_sess); } else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PBSZ")) { handle_pbsz(p_sess); } else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PROT")) { handle_prot(p_sess); } else { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Please login with USER and PASS."); } } }
static void parse_username_password(struct vsf_session* p_sess) { while (1) { vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str, &p_sess->ftp_arg_str, 1); if (tunable_ftp_enable) { if (str_equal_text(&p_sess->ftp_cmd_str, "USER")) { handle_user_command(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS")) { handle_pass_command(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT")) { vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye."); } else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT")) { handle_feat(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS")) { handle_opts(p_sess); } else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "AUTH") && !p_sess->control_use_ssl) { handle_auth(p_sess); } else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PBSZ")) { handle_pbsz(p_sess); } else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PROT")) { handle_prot(p_sess); } else if (str_isempty(&p_sess->ftp_cmd_str) && str_isempty(&p_sess->ftp_arg_str)) { /* Deliberately ignore to avoid NAT device bugs, as per ProFTPd. */ } else { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Please login with USER and PASS."); } } else if (tunable_http_enable) { if (str_equal_text(&p_sess->ftp_cmd_str, "GET")) { handle_get(p_sess); } else { vsf_cmdio_write(p_sess, FTP_LOGINERR, "Bad HTTP verb."); } vsf_sysutil_exit(0); } } }
void *client_handler(void *void_args) { user_session_t *session = (user_session_t *) void_args; status_t error; //Finish session initialization session->directory = realpath(".", NULL); if (session->directory == NULL) { error = REALPATH_ERROR; goto exit0; } session->data_sock = -1; //End session initialization error = send_response(session->command_sock, SERVICE_READY, "Ready. Please send USER.", session->server->log, 0); if (error) { goto exit1; } string_t command; string_initialize(&command); uint8_t done = 0; do { char_vector_clear(&command); error = read_single_line(session->command_sock, &command); if (!error) { error = write_received_message_to_log(session->server->log, &command); if (!error) { //Remove the CRLF from the command char_vector_pop_back(&command); char_vector_pop_back(&command); //Split the string up by spaces size_t len; string_t *split = string_split_skip_consecutive(&command, ' ', &len, 1); char *c_str = string_c_str(split + 0); //Determine which command has been sent if (bool_strcmp(c_str, "USER")) { error = handle_user_command(session, split, len); } else if (bool_strcmp(c_str, "PASS")) { error = handle_pass_command(session, split, len); } else if (bool_strcmp(c_str, "CWD")) { error = handle_cwd_command(session, split, len); } else if (bool_strcmp(c_str, "CDUP")) { error = handle_cdup_command(session, split, len); } else if (bool_strcmp(c_str, "QUIT")) { done = 1; error = handle_quit_command(session, split, len); } else if (bool_strcmp(c_str, "PASV")) { error = handle_pasv_command(session, split, len); } else if (bool_strcmp(c_str, "EPSV")) { error = handle_epsv_command(session, split, len); } else if (bool_strcmp(c_str, "PORT")) { error = handle_port_command(session, split, len); } else if (bool_strcmp(c_str, "EPRT")) { error = handle_eprt_command(session, split, len); } else if (bool_strcmp(c_str, "RETR")) { error = handle_retr_command(session, split, len); } else if (bool_strcmp(c_str, "PWD")) { error = handle_pwd_command(session, split, len); } else if (bool_strcmp(c_str, "LIST")) { error = handle_list_command(session, split, len); } else if (bool_strcmp(c_str, "HELP")) { error = handle_help_command(session, split, len); } else { error = handle_unrecognized_command(session, split, len); } size_t i; for (i = 0; i < len; i++) { string_uninitialize(split + i); } free(split); } } if (error) { char message[] = "Error encountered while processing: "; string_t error_message; string_initialize(&error_message); char *error_string = get_error_message(error); string_assign_from_char_array(&error_message, error_string); prepend_and_write_to_log(session->server->log, &error_message, message, sizeof message); string_uninitialize(&error_message); } } while (!error && !done); char quitting_message[] = "Client quitting.\n"; exit2: string_uninitialize(&command); exit1: free(session->directory); exit0: write_log(session->server->log, quitting_message, sizeof quitting_message); printf("%s", quitting_message); free(session); pthread_exit(NULL); }