/**
 * Loads all keysym/scancode mappings declared within the given keymap and its
 * parent keymap, if any. These mappings are stored within the given
 * guac_rdp_keyboard structure for future use in translating keysyms to the
 * scancodes required by RDP key events.
 *
 * @param keyboard
 *     The guac_rdp_keyboard which should be initialized with the
 *     keysym/scancode mapping defined in the given keymap.
 *
 * @param keymap
 *     The keymap to use to populate the given client's keysym/scancode
 *     mapping.
 */
static void __guac_rdp_keyboard_load_keymap(guac_rdp_keyboard* keyboard,
        const guac_rdp_keymap* keymap) {

    /* Get mapping */
    const guac_rdp_keysym_desc* mapping = keymap->mapping;

    /* If parent exists, load parent first */
    if (keymap->parent != NULL)
        __guac_rdp_keyboard_load_keymap(keyboard, keymap->parent);

    /* Log load */
    guac_client_log(keyboard->client, GUAC_LOG_INFO,
            "Loading keymap \"%s\"", keymap->name);

    /* Load mapping into keymap */
    while (mapping->keysym != 0) {

        /* Locate corresponding key definition within keyboard */
        guac_rdp_key* key = guac_rdp_keyboard_map_key(keyboard,
                mapping->keysym);

        /* Copy mapping (if key is mappable) */
        if (key != NULL)
            key->definition = mapping;
        else
            guac_client_log(keyboard->client, GUAC_LOG_DEBUG,
                    "Ignoring unmappable keysym 0x%X", mapping->keysym);

        /* Next keysym */
        mapping++;

    }

}
예제 #2
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;

}
/**
 * Called periodically by guacd whenever the plugin should handle accumulated
 * data and render a frame.
 *
 * @param client
 *     The guac_client associated with the plugin that should render a frame.
 *
 * @return
 *     Non-zero if an error occurs, zero otherwise.
 */
static int streamtest_client_message_handler(guac_client* client) {

    /* Get stream state from client */
    streamtest_state* state = (streamtest_state*) client->data;

    int frame_start;
    int frame_duration;

    /* Record start of frame */
    frame_start = streamtest_utime();

    /* Read from stream and write as blob(s) */
    if (!state->paused) {

        /* Attempt to fill the available buffer space */
        int length = streamtest_fill_buffer(state->fd,
                state->frame_buffer, state->frame_bytes);

        /* Abort connection if we cannot read */
        if (length == -1) {
            guac_client_log(client, GUAC_LOG_ERROR,
                    "Unable to read from specified file: %s",
                    strerror(errno));
            return 1;
        }

        /* Write all data read as blobs */
        if (length > 0)
            streamtest_write_blobs(client->socket, state->stream,
                    state->frame_buffer, length);

        /* Disconnect on EOF */
        else {
            guac_client_log(client, GUAC_LOG_INFO, "Media streaming complete");
            guac_client_stop(client);
        }

    }

    /* Update progress bar */
    streamtest_render_progress(client);
    guac_socket_flush(client->socket);

    /* Sleep for remainder of frame */
    frame_duration = streamtest_utime() - frame_start;
    if (frame_duration < state->frame_duration)
        streamtest_usleep(state->frame_duration - frame_duration);

    /* Warn (at debug level) if frame takes too long */
    else
        guac_client_log(client, GUAC_LOG_DEBUG,
                "Frame took longer than requested duration: %i microseconds",
                frame_duration);

    /* Success */
    return 0;

}
예제 #4
0
int guac_telnet_user_key_handler(guac_user* user, int keysym, int pressed) {

    guac_client* client = user->client;
    guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
    guac_telnet_settings* settings = telnet_client->settings;
    guac_terminal* term = telnet_client->term;

    /* Skip if terminal not yet ready */
    if (term == NULL)
        return 0;

    /* Stop searching for password */
    if (settings->password_regex != NULL) {

        guac_client_log(client, GUAC_LOG_DEBUG,
                "Stopping password prompt search due to user input.");

        regfree(settings->password_regex);
        free(settings->password_regex);
        settings->password_regex = NULL;

    }

    /* Stop searching for username */
    if (settings->username_regex != NULL) {

        guac_client_log(client, GUAC_LOG_DEBUG,
                "Stopping username prompt search due to user input.");

        regfree(settings->username_regex);
        free(settings->username_regex);
        settings->username_regex = NULL;

    }

    /* Intercept and handle Pause / Break / Ctrl+0 as "IAC BRK" */
    if (pressed && (
                keysym == 0xFF13                  /* Pause */
             || keysym == 0xFF6B                  /* Break */
             || (term->mod_ctrl && keysym == '0') /* Ctrl + 0 */
       )) {

        /* Send IAC BRK */
        telnet_iac(telnet_client->telnet, TELNET_BREAK);

        return 0;
    }

    /* Send key */
    guac_terminal_send_key(term, keysym, pressed);

    return 0;

}
예제 #5
0
int guac_common_ssh_init(guac_client* client) {

#ifdef LIBSSH2_USES_GCRYPT
    /* Init threadsafety in libgcrypt */
    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
    if (!gcry_check_version(GCRYPT_VERSION)) {
        guac_client_log(client, GUAC_LOG_ERROR, "libgcrypt version mismatch.");
        return 1;
    }
#endif

    /* Init threadsafety in OpenSSL */
    guac_common_ssh_openssl_init_locks(CRYPTO_num_locks());
    CRYPTO_set_id_callback(guac_common_ssh_openssl_id_callback);
    CRYPTO_set_locking_callback(guac_common_ssh_openssl_locking_callback);

    /* Init OpenSSL */
    SSL_library_init();
    ERR_load_crypto_strings();

    /* Init libssh2 */
    libssh2_init(0);

    /* Success */
    return 0;

}
예제 #6
0
void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) {

    guac_client* client = ((rdp_freerdp_context*) context)->client;
    rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;

    if (primary)
        client_data->current_surface = client_data->default_surface;

    else {

        /* Make sure that the recieved bitmap is not NULL before processing */
        if (bitmap == NULL) {
            guac_client_log(client, GUAC_LOG_INFO, "NULL bitmap found in bitmap_setsurface instruction.");
            return;
        }

        /* If not available as a surface, make available. */
        if (((guac_rdp_bitmap*) bitmap)->surface == NULL)
            guac_rdp_cache_bitmap(context, bitmap);

        client_data->current_surface = ((guac_rdp_bitmap*) bitmap)->surface;

    }

}
예제 #7
0
void guac_rdpdr_process_connect(rdpSvcPlugin* plugin) {

    /* Get RDPDR plugin */
    guac_rdpdrPlugin* rdpdr = (guac_rdpdrPlugin*) plugin;

    /* Get client from plugin parameters */
    guac_client* client = (guac_client*)
        plugin->channel_entry_points.pExtendedData;

    /* NULL out pExtendedData so we don't lose our guac_client due to an
     * automatic free() within libfreerdp */
    plugin->channel_entry_points.pExtendedData = NULL;

    /* Get data from client */
    rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data;

    /* Init plugin */
    rdpdr->client = client;
    rdpdr->devices_registered = 0;

    /* Register printer if enabled */
    if (client_data->settings.printing_enabled)
        guac_rdpdr_register_printer(rdpdr);

    /* Register drive if enabled */
    if (client_data->settings.drive_enabled)
        guac_rdpdr_register_fs(rdpdr);

    /* Log that printing, etc. has been loaded */
    guac_client_log(client, GUAC_LOG_INFO, "guacdr connected.");

}
예제 #8
0
void guac_pa_start_stream(guac_client* client) {

    vnc_guac_client_data* client_data = (vnc_guac_client_data*) client->data;
    pa_context* context;

    guac_client_log(client, GUAC_LOG_INFO, "Starting audio stream");
    guac_audio_stream_begin(client_data->audio,
                GUAC_VNC_AUDIO_RATE,
                GUAC_VNC_AUDIO_CHANNELS,
                GUAC_VNC_AUDIO_BPS);

    /* Init main loop */
    client_data->pa_mainloop = pa_threaded_mainloop_new();

    /* Create context */
    context = pa_context_new(
            pa_threaded_mainloop_get_api(client_data->pa_mainloop),
            "Guacamole Audio");

    /* Set up context */
    pa_context_set_state_callback(context, __context_state_callback, client);
    pa_context_connect(context, client_data->pa_servername,
            PA_CONTEXT_NOAUTOSPAWN, NULL);

    /* Start loop */
    pa_threaded_mainloop_start(client_data->pa_mainloop);

}
예제 #9
0
int guac_client_init(guac_client* client) {

    /* Set client args */
    client->args = GUAC_TELNET_CLIENT_ARGS;

    /* Allocate client instance data */
    guac_telnet_client* telnet_client = calloc(1, sizeof(guac_telnet_client));
    client->data = telnet_client;

    /* Init telnet client */
    telnet_client->socket_fd = -1;
    telnet_client->naws_enabled = 0;
    telnet_client->echo_enabled = 1;

    /* Set handlers */
    client->join_handler = guac_telnet_user_join_handler;
    client->free_handler = guac_telnet_client_free_handler;

    /* Set locale and warn if not UTF-8 */
    setlocale(LC_CTYPE, "");
    if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) {
        guac_client_log(client, GUAC_LOG_INFO,
                "Current locale does not use UTF-8. Some characters may "
                "not render correctly.");
    }

    /* Success */
    return 0;

}
예제 #10
0
void __guac_rdp_client_load_keymap(guac_client* client,
        const guac_rdp_keymap* keymap) {

    rdp_guac_client_data* guac_client_data =
        (rdp_guac_client_data*) client->data;

    /* Get mapping */
    const guac_rdp_keysym_desc* mapping = keymap->mapping;

    /* If parent exists, load parent first */
    if (keymap->parent != NULL)
        __guac_rdp_client_load_keymap(client, keymap->parent);

    /* Log load */
    guac_client_log(client, GUAC_LOG_INFO, "Loading keymap \"%s\"", keymap->name);

    /* Load mapping into keymap */
    while (mapping->keysym != 0) {

        /* Copy mapping */
        GUAC_RDP_KEYSYM_LOOKUP(guac_client_data->keymap, mapping->keysym) =
            *mapping;

        /* Next keysym */
        mapping++;

    }

}
예제 #11
0
void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device,
        wStream* input_stream, int completion_id) {

    guac_rdpdr_printer_data* printer_data =
        (guac_rdpdr_printer_data*) device->data;

    wStream* output_stream = guac_rdpdr_new_io_completion(device,
            completion_id, STATUS_SUCCESS, 1);

    Stream_Write_UINT32(output_stream, 0); /* padding*/

    /* Close input and wait for output thread to finish */
    close(printer_data->printer_input);
    pthread_join(printer_data->printer_output_thread, NULL);

    /* Close file descriptors */
    close(printer_data->printer_output);

    /* Close file */
    guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, "Print job closed");
    guac_protocol_send_end(device->rdpdr->client->socket, printer_data->stream);

    svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream);

}
예제 #12
0
static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* device,
        wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) {

    switch (major_func) {

        /* Print job create */
        case IRP_MJ_CREATE:
            guac_rdpdr_process_print_job_create(device, input_stream, completion_id);
            break;

        /* Printer job write */
        case IRP_MJ_WRITE:
            guac_rdpdr_process_print_job_write(device, input_stream, completion_id);
            break;

        /* Printer job close */
        case IRP_MJ_CLOSE:
            guac_rdpdr_process_print_job_close(device, input_stream, completion_id);
            break;

        /* Log unknown */
        default:
            guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR,
                    "Unknown printer I/O request function: 0x%x/0x%x",
                    major_func, minor_func);

    }

}
void guac_common_set_pointer_cursor(guac_user* user) {

    guac_client* client = user->client;
    guac_socket* socket = user->socket;

    /* Draw to buffer */
    guac_layer* cursor = guac_client_alloc_buffer(client);

    cairo_surface_t* graphic = cairo_image_surface_create_for_data(
            guac_common_pointer_cursor,
            guac_common_pointer_cursor_format,
            guac_common_pointer_cursor_width,
            guac_common_pointer_cursor_height,
            guac_common_pointer_cursor_stride);

    guac_user_stream_png(user, socket, GUAC_COMP_SRC, cursor,
            0, 0, graphic);
    cairo_surface_destroy(graphic);

    /* Set cursor */
    guac_protocol_send_cursor(socket, 0, 0, cursor,
            0, 0,
            guac_common_pointer_cursor_width,
            guac_common_pointer_cursor_height);

    /* Free buffer */
    guac_client_free_buffer(client, cursor);

    guac_client_log(client, GUAC_LOG_DEBUG,
            "Client cursor image set to generic built-in pointer.");

}
예제 #14
0
/**
 * Callback for the keyboard-interactive authentication method. Currently
 * supports just one prompt for the password. This callback is invoked as
 * needed to fullfill a call to libssh2_userauth_keyboard_interactive().
 *
 * @param name
 *     An arbitrary name which should be printed to the terminal for the
 *     benefit of the user. This is currently ignored.
 *
 * @param name_len
 *     The length of the name string, in bytes.
 *
 * @param instruction
 *     Arbitrary instructions which should be printed to the terminal for the
 *     benefit of the user. This is currently ignored.
 *
 * @param instruction_len
 *     The length of the instruction string, in bytes.
 *
 * @param num_prompts
 *     The number of keyboard-interactive prompts for which responses are
 *     requested. This callback currently only supports one prompt, and assumes
 *     that this prompt is requesting the password.
 *
 * @param prompts
 *     An array of all keyboard-interactive prompts for which responses are
 *     requested.
 *
 * @param responses
 *     A parallel array into which all prompt responses should be stored. Each
 *     entry within this array corresponds to the entry in the prompts array
 *     with the same index.
 *
 * @param abstract
 *     The value of the abstract parameter provided when the SSH session was
 *     created with libssh2_session_init_ex().
 */
static void guac_common_ssh_kbd_callback(const char *name, int name_len,
        const char *instruction, int instruction_len, int num_prompts,
        const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
        LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
        void **abstract) {

    guac_common_ssh_session* common_session =
        (guac_common_ssh_session*) *abstract;

    guac_client* client = common_session->client;

    /* Send password if only one prompt */
    if (num_prompts == 1) {
        char* password = common_session->user->password;
        responses[0].text = strdup(password);
        responses[0].length = strlen(password);
    }

    /* If more than one prompt, a single password is not enough */
    else
        guac_client_log(client, GUAC_LOG_WARNING,
                "Unsupported number of keyboard-interactive prompts: %i",
                num_prompts);

}
예제 #15
0
void guac_rdpdr_fs_process_file_info(guac_rdpdr_device* device, wStream* input_stream,
        int file_id, int completion_id) {

    int fs_information_class;

    Stream_Read_UINT32(input_stream, fs_information_class);

    /* Dispatch to appropriate class-specific handler */
    switch (fs_information_class) {

        case FileBasicInformation:
            guac_rdpdr_fs_process_query_basic_info(device, input_stream,
                    file_id, completion_id);
            break;

        case FileStandardInformation:
            guac_rdpdr_fs_process_query_standard_info(device, input_stream,
                    file_id, completion_id);
            break;

        case FileAttributeTagInformation:
            guac_rdpdr_fs_process_query_attribute_tag_info(device, input_stream,
                    file_id, completion_id);
            break;

        default:
            guac_client_log(device->rdpdr->client, GUAC_LOG_INFO,
                    "Unknown file information class: 0x%x", fs_information_class);
    }

}
예제 #16
0
void guac_rdpdr_fs_process_close(guac_rdpdr_device* device,
        wStream* input_stream, int file_id, int completion_id) {

    wStream* output_stream;
    guac_rdp_fs_file* file;

    guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
            "%s: [file_id=%i]",
            __func__, file_id);

    /* Get file */
    file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
    if (file == NULL)
        return;

    /* If file was written to, and it's in the \Download folder, start stream */
    if (file->bytes_written > 0 &&
            strncmp(file->absolute_path, "\\Download\\", 10) == 0) {
        guac_rdpdr_start_download(device, file->absolute_path);
        guac_rdp_fs_delete((guac_rdp_fs*) device->data, file_id);
    }

    /* Close file */
    guac_rdp_fs_close((guac_rdp_fs*) device->data, file_id);

    output_stream = guac_rdpdr_new_io_completion(device, completion_id,
            STATUS_SUCCESS, 4);
    Stream_Write(output_stream, "\0\0\0\0", 4); /* Padding */

    svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream);

}
예제 #17
0
void guac_rdpdr_fs_process_notify_change_directory(guac_rdpdr_device* device,
        wStream* input_stream, int file_id, int completion_id) {

    guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
            "%s: [file_id=%i] Not implemented",
            __func__, file_id);

}
예제 #18
0
guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client,
        int rop3) {

    /* Translate supported ROP3 opcodes into composite modes */
    switch (rop3) {

        /* "DSon" !(src | dest) */
        case 0x11: return GUAC_TRANSFER_BINARY_NOR;

        /* "DSna" !src & dest */
        case 0x22: return GUAC_TRANSFER_BINARY_NSRC_AND;

        /* "Sn" !src */
        case 0x33: return GUAC_TRANSFER_BINARY_NSRC;

        /* "SDna" (src & !dest) */
        case 0x44: return GUAC_TRANSFER_BINARY_NDEST_AND;

        /* "Dn" !dest */
        case 0x55: return GUAC_TRANSFER_BINARY_NDEST;

        /* "SRCINVERT" (src ^ dest) */
        case 0x66: return GUAC_TRANSFER_BINARY_XOR;

        /* "DSan" !(src & dest) */
        case 0x77: return GUAC_TRANSFER_BINARY_NAND;

        /* "SRCAND" (src & dest) */
        case 0x88: return GUAC_TRANSFER_BINARY_AND;

        /* "DSxn" !(src ^ dest) */
        case 0x99: return GUAC_TRANSFER_BINARY_XNOR;

        /* "MERGEPAINT" (!src | dest)*/
        case 0xBB: return GUAC_TRANSFER_BINARY_NSRC_OR;

        /* "SDno" (src | !dest) */
        case 0xDD: return GUAC_TRANSFER_BINARY_NDEST_OR;

        /* "SRCPAINT" (src | dest) */
        case 0xEE: return GUAC_TRANSFER_BINARY_OR;

        /* 0x00 = "BLACKNESS" (0) */
        /* 0xAA = "NOP" (dest) */
        /* 0xCC = "SRCCOPY" (src) */
        /* 0xFF = "WHITENESS" (1) */

    }

    /* Log warning if ROP3 opcode not supported */
    guac_client_log(client, GUAC_LOG_INFO, "guac_rdp_rop3_transfer_function: "
            "UNSUPPORTED opcode = 0x%02X", rop3);

    /* Default to BINARY_SRC */
    return GUAC_TRANSFER_BINARY_SRC;

}
예제 #19
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;

}
예제 #20
0
파일: rdp.c 프로젝트: tamx/guacamole-server
/**
 * Callback invoked by FreeRDP when the SSL/TLS certificate of the RDP server
 * needs to be verified. If this ever happens, this function implementation
 * will always fail unless the connection has been configured to ignore
 * certificate validity.
 *
 * @param instance
 *     The FreeRDP instance associated with the RDP session whose SSL/TLS
 *     certificate needs to be verified.
 *
 * @param subject
 *     The subject to whom the certificate was issued.
 *
 * @param issuer
 *     The authority that issued the certificate,
 *
 * @param fingerprint
 *     The cryptographic fingerprint of the certificate.
 *
 * @return
 *     TRUE if the certificate passes verification, FALSE otherwise.
 */
static BOOL rdp_freerdp_verify_certificate(freerdp* instance, char* subject,
        char* issuer, char* fingerprint) {

    rdpContext* context = instance->context;
    guac_client* client = ((rdp_freerdp_context*) context)->client;
    guac_rdp_client* rdp_client =
        (guac_rdp_client*) client->data;

    /* Bypass validation if ignore_certificate given */
    if (rdp_client->settings->ignore_certificate) {
        guac_client_log(client, GUAC_LOG_INFO, "Certificate validation bypassed");
        return TRUE;
    }

    guac_client_log(client, GUAC_LOG_INFO, "Certificate validation failed");
    return FALSE;

}
예제 #21
0
void* __guacd_client_input_thread(void* data) {

    guac_client* client = (guac_client*) data;
    guac_socket* socket = client->socket;

    /* Guacamole client input loop */
    while (client->state == GUAC_CLIENT_RUNNING) {

        /* Read instruction */
        guac_instruction* instruction =
            guac_instruction_read(socket, GUACD_USEC_TIMEOUT);

        /* Stop on error */
        if (instruction == NULL) {

            if (guac_error == GUAC_STATUS_INPUT_TIMEOUT)
                guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_TIMEOUT, "Client is not responding.");

            else {
                guacd_client_log_guac_error(client, "Error reading instruction");
                guac_client_stop(client);
            }

            return NULL;
        }

        /* Reset guac_error and guac_error_message (client handlers are not
         * guaranteed to set these) */
        guac_error = GUAC_STATUS_SUCCESS;
        guac_error_message = NULL;

        /* Call handler, stop on error */
        if (guac_client_handle_instruction(client, instruction) < 0) {

            /* Log error */
            guacd_client_log_guac_error(client,
                    "Client instruction handler error");

            /* Log handler details */
            guac_client_log(client, GUAC_LOG_INFO,
                    "Failing instruction handler in client was \"%s\"",
                    instruction->opcode);

            guac_instruction_free(instruction);
            guac_client_stop(client);
            return NULL;
        }

        /* Free allocated instruction */
        guac_instruction_free(instruction);

    }

    return NULL;

}
예제 #22
0
void guac_pa_stop_stream(guac_client* client) {

    vnc_guac_client_data* client_data = (vnc_guac_client_data*) client->data;

    /* Stop loop */
    pa_threaded_mainloop_stop(client_data->pa_mainloop);

    guac_client_log(client, GUAC_LOG_INFO, "Audio stream finished");

}
예제 #23
0
static void __context_get_server_info_callback(pa_context* context,
        const pa_server_info* info, void* data) {

    guac_client* client = (guac_client*) data;

    /* If no default sink, cannot continue */
    if (info->default_sink_name == NULL) {
        guac_client_log(client, GUAC_LOG_ERROR, "No default sink. Cannot stream audio.");
        return;
    }

    guac_client_log(client, GUAC_LOG_INFO, "Will use default sink: \"%s\"",
            info->default_sink_name);

    /* Wait for default sink information */
    pa_operation_unref(
            pa_context_get_sink_info_by_name(context,
                info->default_sink_name, __context_get_sink_info_callback,
                client));

}
예제 #24
0
파일: rdp.c 프로젝트: tamx/guacamole-server
/**
 * Callback invoked by FreeRDP when authentication is required but a username
 * and password has not already been given. In the case of Guacamole, this
 * function always succeeds but does not populate the usename or password. The
 * username/password must be given within the connection parameters.
 *
 * @param instance
 *     The FreeRDP instance associated with the RDP session requesting
 *     credentials.
 *
 * @param username
 *     Pointer to a string which will receive the user's username.
 *
 * @param password
 *     Pointer to a string which will receive the user's password.
 *
 * @param domain
 *     Pointer to a string which will receive the domain associated with the
 *     user's account.
 *
 * @return
 *     Always TRUE.
 */
static BOOL rdp_freerdp_authenticate(freerdp* instance, char** username,
        char** password, char** domain) {

    rdpContext* context = instance->context;
    guac_client* client = ((rdp_freerdp_context*) context)->client;

    /* Warn if connection is likely to fail due to lack of credentials */
    guac_client_log(client, GUAC_LOG_INFO,
            "Authentication requested but username or password not given");
    return TRUE;

}
예제 #25
0
static void __stream_state_callback(pa_stream* stream, void* data) {

    guac_client* client = (guac_client*) data;

    switch (pa_stream_get_state(stream)) {

        case PA_STREAM_UNCONNECTED:
            guac_client_log(client, GUAC_LOG_INFO,
                    "PulseAudio stream currently unconnected");
            break;

        case PA_STREAM_CREATING:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream being created...");
            break;

        case PA_STREAM_READY:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream now ready");
            break;

        case PA_STREAM_FAILED:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream connection failed");
            break;

        case PA_STREAM_TERMINATED:
            guac_client_log(client, GUAC_LOG_INFO, "PulseAudio stream terminated");
            break;

        default:
            guac_client_log(client, GUAC_LOG_INFO,
                    "Unknown PulseAudio stream state: 0x%x",
                    pa_stream_get_state(stream));

    }

}
예제 #26
0
void guac_rdpdr_fs_process_set_volume_info(guac_rdpdr_device* device,
        wStream* input_stream, int file_id, int completion_id) {

    wStream* output_stream = guac_rdpdr_new_io_completion(device,
            completion_id, STATUS_NOT_SUPPORTED, 0);

    guac_client_log(device->rdpdr->client, GUAC_LOG_DEBUG,
            "%s: [file_id=%i] Set volume info not supported",
            __func__, file_id);

    svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream);

}
예제 #27
0
파일: rdp.c 프로젝트: tamx/guacamole-server
static int __guac_receive_channel_data(freerdp* rdp_inst, UINT16 channelId,
        BYTE* data, int size, int flags, int total_size) {
#else
static int __guac_receive_channel_data(freerdp* rdp_inst, int channelId,
        UINT8* data, int size, int flags, int total_size) {
#endif
    return freerdp_channels_data(rdp_inst, channelId,
            data, size, flags, total_size);
}

#ifdef HAVE_FREERDP_EVENT_PUBSUB
/**
 * Called whenever a channel connects via the PubSub event system within
 * FreeRDP.
 *
 * @param context
 *     The rdpContext associated with the active RDP session.
 *
 * @param e
 *     Event-specific arguments, mainly the name of the channel, and a
 *     reference to the associated plugin loaded for that channel by FreeRDP.
 */
static void guac_rdp_channel_connected(rdpContext* context,
        ChannelConnectedEventArgs* e) {

    guac_client* client = ((rdp_freerdp_context*) context)->client;
    guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
    guac_rdp_settings* settings = rdp_client->settings;

    if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) {
#ifdef HAVE_RDPSETTINGS_SUPPORTDISPLAYCONTROL
        /* Store reference to the display update plugin once it's connected */
        if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) {

            DispClientContext* disp = (DispClientContext*) e->pInterface;

            /* Init module with current display size */
            guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings,
                    context->instance, guac_rdp_get_width(context->instance),
                    guac_rdp_get_height(context->instance));

            /* Store connected channel */
            guac_rdp_disp_connect(rdp_client->disp, disp);
            guac_client_log(client, GUAC_LOG_DEBUG,
                    "Display update channel connected.");

        }
#endif
    }

}
void guac_svc_process_terminate(rdpSvcPlugin* plugin) {

    /* Get corresponding guac_rdp_svc */
    guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin;
    guac_rdp_svc* svc = svc_plugin->svc;

    /* Remove and free SVC */
    guac_client_log(svc->client, GUAC_LOG_INFO, "Closing channel \"%s\"...", svc->name);
    guac_rdp_remove_svc(svc->client, svc->name);
    free(svc);

    free(plugin);

}
예제 #29
0
void guac_rdpdr_process_terminate(rdpSvcPlugin* plugin) {

    guac_rdpdrPlugin* rdpdr = (guac_rdpdrPlugin*) plugin;
    int i;

    for (i=0; i<rdpdr->devices_registered; i++) {
        guac_rdpdr_device* device = &(rdpdr->devices[i]);
        guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Unloading device %i (%s)",
                device->device_id, device->device_name);
        device->free_handler(device);
    }

    free(plugin);
}
예제 #30
0
void guac_rdpdr_start_download(guac_rdpdr_device* device, const char* path) {

    /* Get client and stream */
    guac_client* client = device->rdpdr->client;

    int file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, path,
            ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0);

    /* If file opened successfully, start stream */
    if (file_id >= 0) {

        guac_rdp_stream* rdp_stream;
        const char* basename;

        int i;
        char c;

        /* Associate stream with transfer status */
        guac_stream* stream = guac_client_alloc_stream(client);
        stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream));
        stream->ack_handler = guac_rdp_download_ack_handler;
        rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM;
        rdp_stream->download_status.file_id = file_id;
        rdp_stream->download_status.offset = 0;

        /* Get basename from absolute path */
        i=0;
        basename = path;
        do {

            c = path[i];
            if (c == '/' || c == '\\')
                basename = &(path[i+1]);

            i++;

        } while (c != '\0');

        GUAC_RDP_DEBUG(2, "Initiating download of \"%s\"", path);

        /* Begin stream */
        guac_protocol_send_file(client->socket, stream,
                "application/octet-stream", basename);
        guac_socket_flush(client->socket);

    }
    else
        guac_client_log(client, GUAC_LOG_ERROR, "Unable to download \"%s\"", path);

}