int guac_rdp_upload_end_handler(guac_client* client, guac_stream* stream) { guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) { guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); return 0; } /* Close file */ guac_rdp_fs_close(fs, rdp_stream->upload_status.file_id); /* Acknowledge stream end */ guac_protocol_send_ack(client->socket, stream, "OK (STREAM END)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); free(rdp_stream); return 0; }
int guac_sftp_blob_handler(guac_client* client, guac_stream* stream, void* data, int length) { /* Pull file from stream */ ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* Attempt write */ if (libssh2_sftp_write(file, data, length) == length) { guac_protocol_send_ack(client->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); } /* Inform of any errors */ else { guac_client_log_error(client, "Unable to write to file: %s", libssh2_sftp_last_error(client_data->sftp_session)); guac_protocol_send_ack(client->socket, stream, "SFTP: Write failed", GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); guac_socket_flush(client->socket); } return 0; }
int guac_rdp_svc_pipe_handler(guac_client* client, guac_stream* stream, char* mimetype, char* name) { guac_rdp_stream* rdp_stream; guac_rdp_svc* svc = guac_rdp_get_svc(client, name); /* Fail if no such SVC */ if (svc == NULL) { guac_client_log(client, GUAC_LOG_ERROR, "Requested non-existent pipe: \"%s\".", name); guac_protocol_send_ack(client->socket, stream, "FAIL (NO SUCH PIPE)", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); guac_socket_flush(client->socket); return 0; } else guac_client_log(client, GUAC_LOG_ERROR, "Inbound half of channel \"%s\" connected.", name); /* Init stream data */ stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); stream->blob_handler = guac_rdp_svc_blob_handler; rdp_stream->type = GUAC_RDP_INBOUND_SVC_STREAM; rdp_stream->svc = svc; svc->input_pipe = stream; return 0; }
int guac_rdp_user_file_handler(guac_user* user, guac_stream* stream, char* mimetype, char* filename) { guac_rdp_client* rdp_client = (guac_rdp_client*) user->client->data; #ifdef ENABLE_COMMON_SSH guac_rdp_settings* settings = rdp_client->settings; /* If SFTP is enabled, it should be used for default uploads only if RDPDR * is not enabled or its upload directory has been set */ if (rdp_client->sftp_filesystem != NULL) { if (!settings->drive_enabled || settings->sftp_directory != NULL) return guac_rdp_sftp_file_handler(user, stream, mimetype, filename); } #endif /* Default to using RDPDR uploads (if enabled) */ if (rdp_client->filesystem != NULL) return guac_rdp_upload_file_handler(user, stream, mimetype, filename); /* File transfer not enabled */ guac_protocol_send_ack(user->socket, stream, "File transfer disabled", GUAC_PROTOCOL_STATUS_UNSUPPORTED); guac_socket_flush(user->socket); return 0; }
int guac_rdp_upload_blob_handler(guac_client* client, guac_stream* stream, void* data, int length) { int bytes_written; guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Get filesystem, return error if no filesystem 0*/ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) { guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); return 0; } /* Write entire block */ while (length > 0) { /* Attempt write */ bytes_written = guac_rdp_fs_write(fs, rdp_stream->upload_status.file_id, rdp_stream->upload_status.offset, data, length); /* On error, abort */ if (bytes_written < 0) { guac_protocol_send_ack(client->socket, stream, "FAIL (BAD WRITE)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(client->socket); return 0; } /* Update counters */ rdp_stream->upload_status.offset += bytes_written; data += bytes_written; length -= bytes_written; } guac_protocol_send_ack(client->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); return 0; }
int guac_rdp_download_ack_handler(guac_client* client, guac_stream* stream, char* message, guac_protocol_status status) { guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) { guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); return 0; } /* If successful, read data */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { /* Attempt read into buffer */ char buffer[4096]; int bytes_read = guac_rdp_fs_read(fs, rdp_stream->download_status.file_id, rdp_stream->download_status.offset, buffer, sizeof(buffer)); /* If bytes read, send as blob */ if (bytes_read > 0) { rdp_stream->download_status.offset += bytes_read; guac_protocol_send_blob(client->socket, stream, buffer, bytes_read); } /* If EOF, send end */ else if (bytes_read == 0) { guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); free(rdp_stream); } /* Otherwise, fail stream */ else { guac_client_log(client, GUAC_LOG_ERROR, "Error reading file for download"); guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); free(rdp_stream); } guac_socket_flush(client->socket); } /* Otherwise, return stream to client */ else guac_client_free_stream(client, stream); return 0; }
int guac_rdp_upload_file_handler(guac_client* client, guac_stream* stream, char* mimetype, char* filename) { int file_id; guac_rdp_stream* rdp_stream; char file_path[GUAC_RDP_FS_MAX_PATH]; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) { guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); return 0; } /* Translate name */ __generate_upload_path(filename, file_path); /* Open file */ file_id = guac_rdp_fs_open(fs, file_path, ACCESS_GENERIC_WRITE, 0, DISP_FILE_OVERWRITE_IF, 0); if (file_id < 0) { guac_protocol_send_ack(client->socket, stream, "FAIL (CANNOT OPEN)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(client->socket); return 0; } /* Init upload status */ rdp_stream = malloc(sizeof(guac_rdp_stream)); rdp_stream->type = GUAC_RDP_UPLOAD_STREAM; rdp_stream->upload_status.offset = 0; rdp_stream->upload_status.file_id = file_id; stream->data = rdp_stream; stream->blob_handler = guac_rdp_upload_blob_handler; stream->end_handler = guac_rdp_upload_end_handler; guac_protocol_send_ack(client->socket, stream, "OK (STREAM BEGIN)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); return 0; }
int guac_sftp_end_handler(guac_client* client, guac_stream* stream) { /* Pull file from stream */ LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* Attempt to close file */ if (libssh2_sftp_close(file) == 0) { guac_protocol_send_ack(client->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); } else { guac_client_log_error(client, "Unable to close file"); guac_protocol_send_ack(client->socket, stream, "SFTP: Close failed", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); } return 0; }
int guac_rdp_upload_put_handler(guac_client* client, guac_object* object, guac_stream* stream, char* mimetype, char* name) { /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) { guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); return 0; } /* Open file */ int file_id = guac_rdp_fs_open(fs, name, ACCESS_GENERIC_WRITE, 0, DISP_FILE_OVERWRITE_IF, 0); /* Abort on failure */ if (file_id < 0) { guac_protocol_send_ack(client->socket, stream, "FAIL (CANNOT OPEN)", GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); guac_socket_flush(client->socket); return 0; } /* Init upload stream data */ guac_rdp_stream* rdp_stream = malloc(sizeof(guac_rdp_stream)); rdp_stream->type = GUAC_RDP_UPLOAD_STREAM; rdp_stream->upload_status.offset = 0; rdp_stream->upload_status.file_id = file_id; /* Allocate stream, init for file upload */ stream->data = rdp_stream; stream->blob_handler = guac_rdp_upload_blob_handler; stream->end_handler = guac_rdp_upload_end_handler; /* Acknowledge stream creation */ guac_protocol_send_ack(client->socket, stream, "OK (STREAM BEGIN)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); return 0; }
int guac_rdp_svc_blob_handler(guac_client* client, guac_stream* stream, void* data, int length) { guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Write blob data to SVC directly */ guac_rdp_svc_write(rdp_stream->svc, data, length); guac_protocol_send_ack(client->socket, stream, "OK (DATA RECEIVED)", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); return 0; }
int guac_sftp_file_handler(guac_client* client, guac_stream* stream, char* mimetype, char* filename) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; char fullpath[GUAC_SFTP_MAX_PATH]; LIBSSH2_SFTP_HANDLE* file; int i; /* Ensure filename is a valid filename and not a path */ if (!__ssh_guac_valid_filename(filename)) { guac_protocol_send_ack(client->socket, stream, "SFTP: Illegal filename", GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST); guac_socket_flush(client->socket); return 0; } /* Copy upload path, append trailing slash */ for (i=0; i<GUAC_SFTP_MAX_PATH; i++) { char c = client_data->sftp_upload_path[i]; if (c == '\0') { fullpath[i++] = '/'; break; } fullpath[i] = c; } /* Append filename */ for (; i<GUAC_SFTP_MAX_PATH; i++) { char c = *(filename++); if (c == '\0') break; fullpath[i] = c; } /* If path + filename exceeds max length, abort */ if (i == GUAC_SFTP_MAX_PATH) { guac_protocol_send_ack(client->socket, stream, "SFTP: Name too long", GUAC_PROTOCOL_STATUS_CLIENT_OVERRUN); guac_socket_flush(client->socket); return 0; } /* Terminate path string */ fullpath[i] = '\0'; /* Open file via SFTP */ file = libssh2_sftp_open(client_data->sftp_session, fullpath, LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC, S_IRUSR | S_IWUSR); /* Inform of status */ if (file != NULL) { guac_protocol_send_ack(client->socket, stream, "SFTP: File opened", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(client->socket); } else { guac_client_log_error(client, "Unable to open file \"%s\": %s", fullpath, libssh2_sftp_last_error(client_data->sftp_session)); guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed", GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND); guac_socket_flush(client->socket); } /* Set handlers for file stream */ stream->blob_handler = guac_sftp_blob_handler; stream->end_handler = guac_sftp_end_handler; /* Store file within stream */ stream->data = file; return 0; }