Blame src/messages.c

Packit Service 31306d
/*
Packit Service 31306d
 * messages.c - message parsing for client and server
Packit Service 31306d
 *
Packit Service 31306d
 * This file is part of the SSH Library
Packit Service 31306d
 *
Packit Service 31306d
 * Copyright (c) 2003-2013 by Aris Adamantiadis
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is free software; you can redistribute it and/or modify
Packit Service 31306d
 * it under the terms of the GNU Lesser General Public License as published by
Packit Service 31306d
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit Service 31306d
 * option) any later version.
Packit Service 31306d
 *
Packit Service 31306d
 * The SSH Library is distributed in the hope that it will be useful, but
Packit Service 31306d
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit Service 31306d
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit Service 31306d
 * License for more details.
Packit Service 31306d
 *
Packit Service 31306d
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 31306d
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit Service 31306d
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit Service 31306d
 * MA 02111-1307, USA.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
Packit Service 31306d
#include <string.h>
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
Packit Service 31306d
#ifndef _WIN32
Packit Service 31306d
#include <netinet/in.h>
Packit Service 31306d
#include <arpa/inet.h>
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#include "libssh/libssh.h"
Packit Service 31306d
#include "libssh/priv.h"
Packit Service 31306d
#include "libssh/ssh2.h"
Packit Service 31306d
#include "libssh/buffer.h"
Packit Service 31306d
#include "libssh/packet.h"
Packit Service 31306d
#include "libssh/channels.h"
Packit Service 31306d
#include "libssh/session.h"
Packit Service 31306d
#include "libssh/misc.h"
Packit Service 31306d
#include "libssh/pki.h"
Packit Service 31306d
#include "libssh/dh.h"
Packit Service 31306d
#include "libssh/messages.h"
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
#include "libssh/server.h"
Packit Service 31306d
#include "libssh/gssapi.h"
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @defgroup libssh_messages The SSH message functions
Packit Service 31306d
 * @ingroup libssh
Packit Service 31306d
 *
Packit Service 31306d
 * This file contains the message parsing utilities for client and server
Packit Service 31306d
 * programs using libssh.
Packit Service 31306d
 *
Packit Service 31306d
 * On the server the the main loop of the program will call
Packit Service 31306d
 * ssh_message_get(session) to get messages as they come. They are not 1-1 with
Packit Service 31306d
 * the protocol messages. Then, the user will know what kind of a message it is
Packit Service 31306d
 * and use the appropriate functions to handle it (or use the default handlers
Packit Service 31306d
 * if you don't know what to do).
Packit Service 31306d
 *
Packit Service 31306d
 * @{
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
static ssh_message ssh_message_new(ssh_session session)
Packit Service 31306d
{
Packit Service 31306d
    ssh_message msg = calloc(1, sizeof(struct ssh_message_struct));
Packit Service 31306d
    if (msg == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    msg->session = session;
Packit Service 31306d
Packit Service 31306d
    /* Set states explicitly */
Packit Service 31306d
    msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
Packit Service 31306d
Packit Service 31306d
    return msg;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifndef WITH_SERVER
Packit Service 31306d
Packit Service 31306d
/* Reduced version of the reply default that only reply with
Packit Service 31306d
 * SSH_MSG_UNIMPLEMENTED
Packit Service 31306d
 */
Packit Service 31306d
static int ssh_message_reply_default(ssh_message msg) {
Packit Service 31306d
  SSH_LOG(SSH_LOG_FUNCTIONS, "Reporting unknown packet");
Packit Service 31306d
Packit Service 31306d
  if (ssh_buffer_add_u8(msg->session->out_buffer, SSH2_MSG_UNIMPLEMENTED) < 0)
Packit Service 31306d
    goto error;
Packit Service 31306d
  if (ssh_buffer_add_u32(msg->session->out_buffer,
Packit Service 31306d
      htonl(msg->session->recv_seq-1)) < 0)
Packit Service 31306d
    goto error;
Packit Service 31306d
  return ssh_packet_send(msg->session);
Packit Service 31306d
  error:
Packit Service 31306d
  return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
Packit Service 31306d
static int ssh_execute_server_request(ssh_session session, ssh_message msg)
Packit Service 31306d
{
Packit Service 31306d
    ssh_channel channel = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    switch(msg->type) {
Packit Service 31306d
        case SSH_REQUEST_AUTH:
Packit Service 31306d
            if (msg->auth_request.method == SSH_AUTH_METHOD_PASSWORD &&
Packit Service 31306d
                ssh_callbacks_exists(session->server_callbacks, auth_password_function)) {
Packit Service 31306d
                rc = session->server_callbacks->auth_password_function(session,
Packit Service 31306d
                        msg->auth_request.username, msg->auth_request.password,
Packit Service 31306d
                        session->server_callbacks->userdata);
Packit Service 31306d
                if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL) {
Packit Service 31306d
                    ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL);
Packit Service 31306d
                } else {
Packit Service 31306d
                    ssh_message_reply_default(msg);
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                return SSH_OK;
Packit Service 31306d
            } else if(msg->auth_request.method == SSH_AUTH_METHOD_PUBLICKEY &&
Packit Service 31306d
                      ssh_callbacks_exists(session->server_callbacks, auth_pubkey_function)) {
Packit Service 31306d
               rc = session->server_callbacks->auth_pubkey_function(session,
Packit Service 31306d
                       msg->auth_request.username, msg->auth_request.pubkey,
Packit Service 31306d
                       msg->auth_request.signature_state,
Packit Service 31306d
                       session->server_callbacks->userdata);
Packit Service 31306d
               if (msg->auth_request.signature_state != SSH_PUBLICKEY_STATE_NONE) {
Packit Service 31306d
                 if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL) {
Packit Service 31306d
                   ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL);
Packit Service 31306d
                 } else {
Packit Service 31306d
                   ssh_message_reply_default(msg);
Packit Service 31306d
                 }
Packit Service 31306d
               } else {
Packit Service 31306d
                 if (rc == SSH_AUTH_SUCCESS) {
Packit Service 31306d
                   ssh_message_auth_reply_pk_ok_simple(msg);
Packit Service 31306d
                 } else {
Packit Service 31306d
                   ssh_message_reply_default(msg);
Packit Service 31306d
                 }
Packit Service 31306d
               }
Packit Service 31306d
Packit Service 31306d
               return SSH_OK;
Packit Service 31306d
            } else if (msg->auth_request.method == SSH_AUTH_METHOD_NONE &&
Packit Service 31306d
                       ssh_callbacks_exists(session->server_callbacks, auth_none_function)) {
Packit Service 31306d
                rc = session->server_callbacks->auth_none_function(session,
Packit Service 31306d
                    msg->auth_request.username, session->server_callbacks->userdata);
Packit Service 31306d
                if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL){
Packit Service 31306d
                    ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL);
Packit Service 31306d
                } else {
Packit Service 31306d
                    ssh_message_reply_default(msg);
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                return SSH_OK;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_REQUEST_CHANNEL_OPEN:
Packit Service 31306d
            if (msg->channel_request_open.type == SSH_CHANNEL_SESSION &&
Packit Service 31306d
                ssh_callbacks_exists(session->server_callbacks, channel_open_request_session_function)) {
Packit Service 31306d
                channel = session->server_callbacks->channel_open_request_session_function(session,
Packit Service 31306d
                        session->server_callbacks->userdata);
Packit Service 31306d
                if (channel != NULL) {
Packit Service 31306d
                    rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
Packit Service 31306d
                    if (rc != SSH_OK) {
Packit Service 31306d
                        SSH_LOG(SSH_LOG_WARNING,
Packit Service 31306d
                                "Failed to send reply for accepting a channel "
Packit Service 31306d
                                "open");
Packit Service 31306d
                    }
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                } else {
Packit Service 31306d
                    ssh_message_reply_default(msg);
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                return SSH_OK;
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_REQUEST_CHANNEL:
Packit Service 31306d
            channel = msg->channel_request.channel;
Packit Service 31306d
Packit Service 31306d
            if (msg->channel_request.type == SSH_CHANNEL_REQUEST_PTY){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_pty_request_function) {
Packit Service 31306d
                    rc = ssh_callbacks_iterate_exec(channel_pty_request_function,
Packit Service 31306d
                                                    session,
Packit Service 31306d
                                                    channel,
Packit Service 31306d
                                                    msg->channel_request.TERM,
Packit Service 31306d
                                                    msg->channel_request.width,
Packit Service 31306d
                                                    msg->channel_request.height,
Packit Service 31306d
                                                    msg->channel_request.pxwidth,
Packit Service 31306d
                                                    msg->channel_request.pxheight);
Packit Service 31306d
                    if (rc == 0) {
Packit Service 31306d
                        ssh_message_channel_request_reply_success(msg);
Packit Service 31306d
                    } else {
Packit Service 31306d
                        ssh_message_reply_default(msg);
Packit Service 31306d
                    }
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_SHELL){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_shell_request_function) {
Packit Service 31306d
                    rc = ssh_callbacks_iterate_exec(channel_shell_request_function,
Packit Service 31306d
                                                    session,
Packit Service 31306d
                                                    channel);
Packit Service 31306d
                    if (rc == 0) {
Packit Service 31306d
                        ssh_message_channel_request_reply_success(msg);
Packit Service 31306d
                    } else {
Packit Service 31306d
                        ssh_message_reply_default(msg);
Packit Service 31306d
                    }
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_X11){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_x11_req_function) {
Packit Service 31306d
                    ssh_callbacks_iterate_exec(channel_x11_req_function,
Packit Service 31306d
                                               session,
Packit Service 31306d
                                               channel,
Packit Service 31306d
                                               msg->channel_request.x11_single_connection,
Packit Service 31306d
                                               msg->channel_request.x11_auth_protocol,
Packit Service 31306d
                                               msg->channel_request.x11_auth_cookie,
Packit Service 31306d
                                               msg->channel_request.x11_screen_number);
Packit Service 31306d
                    ssh_message_channel_request_reply_success(msg);
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_WINDOW_CHANGE){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_pty_window_change_function) {
Packit Service 31306d
                    rc = ssh_callbacks_iterate_exec(channel_pty_window_change_function,
Packit Service 31306d
                                                    session,
Packit Service 31306d
                                                    channel,
Packit Service 31306d
                                                    msg->channel_request.width,
Packit Service 31306d
                                                    msg->channel_request.height,
Packit Service 31306d
                                                    msg->channel_request.pxwidth,
Packit Service 31306d
                                                    msg->channel_request.pxheight);
Packit Service 31306d
                    if (rc != SSH_OK) {
Packit Service 31306d
                        SSH_LOG(SSH_LOG_WARNING,
Packit Service 31306d
                                "Failed to iterate callbacks for window change");
Packit Service 31306d
                    }
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_EXEC){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_exec_request_function) {
Packit Service 31306d
                    rc = ssh_callbacks_iterate_exec(channel_exec_request_function,
Packit Service 31306d
                                                    session,
Packit Service 31306d
                                                    channel,
Packit Service 31306d
                                                    msg->channel_request.command);
Packit Service 31306d
                    if (rc == 0) {
Packit Service 31306d
                        ssh_message_channel_request_reply_success(msg);
Packit Service 31306d
                    } else {
Packit Service 31306d
                        ssh_message_reply_default(msg);
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_ENV){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_env_request_function) {
Packit Service 31306d
                    rc = ssh_callbacks_iterate_exec(channel_env_request_function,
Packit Service 31306d
                                                    session,
Packit Service 31306d
                                                    channel,
Packit Service 31306d
                                                    msg->channel_request.var_name,
Packit Service 31306d
                                                    msg->channel_request.var_value);
Packit Service 31306d
                    if (rc == 0) {
Packit Service 31306d
                        ssh_message_channel_request_reply_success(msg);
Packit Service 31306d
                    } else {
Packit Service 31306d
                        ssh_message_reply_default(msg);
Packit Service 31306d
                    }
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_SUBSYSTEM){
Packit Service 31306d
                ssh_callbacks_iterate(channel->callbacks,
Packit Service 31306d
                                      ssh_channel_callbacks,
Packit Service 31306d
                                      channel_subsystem_request_function) {
Packit Service 31306d
                    rc = ssh_callbacks_iterate_exec(channel_subsystem_request_function,
Packit Service 31306d
                                                    session,
Packit Service 31306d
                                                    channel,
Packit Service 31306d
                                                    msg->channel_request.subsystem);
Packit Service 31306d
                    if (rc == 0) {
Packit Service 31306d
                        ssh_message_channel_request_reply_success(msg);
Packit Service 31306d
                    } else {
Packit Service 31306d
                        ssh_message_reply_default(msg);
Packit Service 31306d
                    }
Packit Service 31306d
Packit Service 31306d
                    return SSH_OK;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_callbacks_iterate_end();
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        case SSH_REQUEST_SERVICE:
Packit Service 31306d
            if (ssh_callbacks_exists(session->server_callbacks, service_request_function)) {
Packit Service 31306d
                rc = session->server_callbacks->service_request_function(session,
Packit Service 31306d
                        msg->service_request.service, session->server_callbacks->userdata);
Packit Service 31306d
                if (rc == 0) {
Packit Service 31306d
                    ssh_message_reply_default(msg);
Packit Service 31306d
                } else {
Packit Service 31306d
                    ssh_disconnect(session);
Packit Service 31306d
                }
Packit Service 31306d
Packit Service 31306d
                return SSH_OK;
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            return SSH_AGAIN;
Packit Service 31306d
        case SSH_REQUEST_GLOBAL:
Packit Service 31306d
            break;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return SSH_AGAIN;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int ssh_execute_client_request(ssh_session session, ssh_message msg)
Packit Service 31306d
{
Packit Service 31306d
    ssh_channel channel = NULL;
Packit Service 31306d
    int rc = SSH_AGAIN;
Packit Service 31306d
Packit Service 31306d
    if (msg->type == SSH_REQUEST_CHANNEL_OPEN
Packit Service 31306d
        && msg->channel_request_open.type == SSH_CHANNEL_X11
Packit Service 31306d
        && ssh_callbacks_exists(session->common.callbacks, channel_open_request_x11_function)) {
Packit Service 31306d
        channel = session->common.callbacks->channel_open_request_x11_function (session,
Packit Service 31306d
                msg->channel_request_open.originator,
Packit Service 31306d
                msg->channel_request_open.originator_port,
Packit Service 31306d
                session->common.callbacks->userdata);
Packit Service 31306d
        if (channel != NULL) {
Packit Service 31306d
            rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
Packit Service 31306d
Packit Service 31306d
            return rc;
Packit Service 31306d
        } else {
Packit Service 31306d
            ssh_message_reply_default(msg);
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        return SSH_OK;
Packit Service 31306d
    } else if (msg->type == SSH_REQUEST_CHANNEL_OPEN
Packit Service 31306d
               && msg->channel_request_open.type == SSH_CHANNEL_AUTH_AGENT
Packit Service 31306d
               && ssh_callbacks_exists(session->common.callbacks, channel_open_request_auth_agent_function)) {
Packit Service 31306d
        channel = session->common.callbacks->channel_open_request_auth_agent_function (session,
Packit Service 31306d
                session->common.callbacks->userdata);
Packit Service 31306d
Packit Service 31306d
        if (channel != NULL) {
Packit Service 31306d
            rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
Packit Service 31306d
Packit Service 31306d
            return rc;
Packit Service 31306d
        } else {
Packit Service 31306d
            ssh_message_reply_default(msg);
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        return SSH_OK;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/** @internal
Packit Service 31306d
 * Executes the callbacks defined in session->server_callbacks, out of an ssh_message
Packit Service 31306d
 * I don't like ssh_message interface but it works.
Packit Service 31306d
 * @returns SSH_OK if the message has been handled, or SSH_AGAIN otherwise.
Packit Service 31306d
 */
Packit Service 31306d
static int ssh_execute_server_callbacks(ssh_session session, ssh_message msg){
Packit Service 31306d
    int rc = SSH_AGAIN;
Packit Service 31306d
Packit Service 31306d
    if (session->server_callbacks != NULL){
Packit Service 31306d
        rc = ssh_execute_server_request(session, msg);
Packit Service 31306d
    } else if (session->common.callbacks != NULL) {
Packit Service 31306d
        /* This one is in fact a client callback... */
Packit Service 31306d
        rc = ssh_execute_client_request(session, msg);
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif /* WITH_SERVER */
Packit Service 31306d
Packit Service 31306d
static int ssh_execute_message_callback(ssh_session session, ssh_message msg) {
Packit Service 31306d
	int ret;
Packit Service 31306d
    if(session->ssh_message_callback != NULL) {
Packit Service 31306d
        ret = session->ssh_message_callback(session, msg,
Packit Service 31306d
                session->ssh_message_callback_data);
Packit Service 31306d
        if(ret == 1) {
Packit Service 31306d
            ret = ssh_message_reply_default(msg);
Packit Service 31306d
            SSH_MESSAGE_FREE(msg);
Packit Service 31306d
            if(ret != SSH_OK) {
Packit Service 31306d
                return ret;
Packit Service 31306d
            }
Packit Service 31306d
        } else {
Packit Service 31306d
            SSH_MESSAGE_FREE(msg);
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        ret = ssh_message_reply_default(msg);
Packit Service 31306d
        SSH_MESSAGE_FREE(msg);
Packit Service 31306d
        if(ret != SSH_OK) {
Packit Service 31306d
            return ret;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
    return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief Add a message to the current queue of messages to be parsed and/or call
Packit Service 31306d
 * the various callback functions.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  session  The SSH session to add the message.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  message  The message to add to the queue.
Packit Service 31306d
 */
Packit Service 31306d
static void ssh_message_queue(ssh_session session, ssh_message message)
Packit Service 31306d
{
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
    int ret;
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    if (message == NULL) {
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
    /* probably not the best place to execute server callbacks, but still better
Packit Service 31306d
     * than nothing.
Packit Service 31306d
     */
Packit Service 31306d
    ret = ssh_execute_server_callbacks(session, message);
Packit Service 31306d
    if (ret == SSH_OK) {
Packit Service 31306d
        SSH_MESSAGE_FREE(message);
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
#endif /* WITH_SERVER */
Packit Service 31306d
Packit Service 31306d
    if (session->ssh_message_callback != NULL) {
Packit Service 31306d
        /* This will transfer the message, do not free. */
Packit Service 31306d
        ssh_execute_message_callback(session, message);
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->server_callbacks != NULL) {
Packit Service 31306d
        /* if we have server callbacks, but nothing was executed, it means we are
Packit Service 31306d
         * in non-synchronous mode, and we just don't care about the message we
Packit Service 31306d
         * received. Just send a default response. Do not queue it.
Packit Service 31306d
         */
Packit Service 31306d
        ssh_message_reply_default(message);
Packit Service 31306d
        SSH_MESSAGE_FREE(message);
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    if (session->ssh_message_list == NULL) {
Packit Service 31306d
        session->ssh_message_list = ssh_list_new();
Packit Service 31306d
        if (session->ssh_message_list == NULL) {
Packit Service 31306d
            /*
Packit Service 31306d
             * If the message list couldn't be allocated, the message can't be
Packit Service 31306d
             * enqueued
Packit Service 31306d
             */
Packit Service 31306d
            ssh_message_reply_default(message);
Packit Service 31306d
            ssh_set_error_oom(session);
Packit Service 31306d
            SSH_MESSAGE_FREE(message);
Packit Service 31306d
            return;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* This will transfer the message, do not free. */
Packit Service 31306d
    ssh_list_append(session->ssh_message_list, message);
Packit Service 31306d
    return;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief Pop a message from the message list and dequeue it.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  session  The SSH session to pop the message.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             The head message or NULL if it doesn't exist.
Packit Service 31306d
 */
Packit Service 31306d
ssh_message ssh_message_pop_head(ssh_session session){
Packit Service 31306d
  ssh_message msg=NULL;
Packit Service 31306d
  struct ssh_iterator *i;
Packit Service 31306d
  if(session->ssh_message_list == NULL)
Packit Service 31306d
    return NULL;
Packit Service 31306d
  i=ssh_list_get_iterator(session->ssh_message_list);
Packit Service 31306d
  if(i != NULL){
Packit Service 31306d
    msg=ssh_iterator_value(ssh_message,i);
Packit Service 31306d
    ssh_list_remove(session->ssh_message_list,i);
Packit Service 31306d
  }
Packit Service 31306d
  return msg;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/* Returns 1 if there is a message available */
Packit Service 31306d
static int ssh_message_termination(void *s){
Packit Service 31306d
  ssh_session session = s;
Packit Service 31306d
  struct ssh_iterator *it;
Packit Service 31306d
  if(session->session_state == SSH_SESSION_STATE_ERROR)
Packit Service 31306d
    return 1;
Packit Service 31306d
  it = ssh_list_get_iterator(session->ssh_message_list);
Packit Service 31306d
  if(!it)
Packit Service 31306d
    return 0;
Packit Service 31306d
  else
Packit Service 31306d
    return 1;
Packit Service 31306d
}
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Retrieve a SSH message from a SSH session.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  session  The SSH session to get the message.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             The SSH message received, NULL in case of error, or timeout
Packit Service 31306d
 *                      elapsed.
Packit Service 31306d
 *
Packit Service 31306d
 * @warning This function blocks until a message has been received. Betterset up
Packit Service 31306d
 *          a callback if this behavior is unwanted.
Packit Service 31306d
 */
Packit Service 31306d
ssh_message ssh_message_get(ssh_session session) {
Packit Service 31306d
  ssh_message msg = NULL;
Packit Service 31306d
  int rc;
Packit Service 31306d
Packit Service 31306d
  msg=ssh_message_pop_head(session);
Packit Service 31306d
  if(msg) {
Packit Service 31306d
      return msg;
Packit Service 31306d
  }
Packit Service 31306d
  if(session->ssh_message_list == NULL) {
Packit Service 31306d
      session->ssh_message_list = ssh_list_new();
Packit Service 31306d
  }
Packit Service 31306d
  rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
Packit Service 31306d
      ssh_message_termination, session);
Packit Service 31306d
  if(rc || session->session_state == SSH_SESSION_STATE_ERROR)
Packit Service 31306d
    return NULL;
Packit Service 31306d
  msg=ssh_list_pop_head(ssh_message, session->ssh_message_list);
Packit Service 31306d
Packit Service 31306d
  return msg;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Get the type of the message.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in] msg       The message to get the type from.
Packit Service 31306d
 *
Packit Service 31306d
 * @return              The message type or -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_message_type(ssh_message msg) {
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  return msg->type;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Get the subtype of the message.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in] msg       The message to get the subtype from.
Packit Service 31306d
 *
Packit Service 31306d
 * @return              The message type or -1 on error.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_message_subtype(ssh_message msg) {
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    return -1;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  switch(msg->type) {
Packit Service 31306d
    case SSH_REQUEST_AUTH:
Packit Service 31306d
      return msg->auth_request.method;
Packit Service 31306d
    case SSH_REQUEST_CHANNEL_OPEN:
Packit Service 31306d
      return msg->channel_request_open.type;
Packit Service 31306d
    case SSH_REQUEST_CHANNEL:
Packit Service 31306d
      return msg->channel_request.type;
Packit Service 31306d
    case SSH_REQUEST_GLOBAL:
Packit Service 31306d
      return msg->global_request.type;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  return -1;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @brief Free a SSH message.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in] msg       The message to release the memory.
Packit Service 31306d
 */
Packit Service 31306d
void ssh_message_free(ssh_message msg){
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    return;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  switch(msg->type) {
Packit Service 31306d
    case SSH_REQUEST_AUTH:
Packit Service 31306d
      SAFE_FREE(msg->auth_request.username);
Packit Service 31306d
      if (msg->auth_request.password) {
Packit Service 31306d
        explicit_bzero(msg->auth_request.password,
Packit Service 31306d
                       strlen(msg->auth_request.password));
Packit Service 31306d
        SAFE_FREE(msg->auth_request.password);
Packit Service 31306d
      }
Packit Service 31306d
      ssh_key_free(msg->auth_request.pubkey);
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_REQUEST_CHANNEL_OPEN:
Packit Service 31306d
      SAFE_FREE(msg->channel_request_open.originator);
Packit Service 31306d
      SAFE_FREE(msg->channel_request_open.destination);
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_REQUEST_CHANNEL:
Packit Service 31306d
      SAFE_FREE(msg->channel_request.TERM);
Packit Service 31306d
      SAFE_FREE(msg->channel_request.modes);
Packit Service 31306d
      SAFE_FREE(msg->channel_request.var_name);
Packit Service 31306d
      SAFE_FREE(msg->channel_request.var_value);
Packit Service 31306d
      SAFE_FREE(msg->channel_request.command);
Packit Service 31306d
      SAFE_FREE(msg->channel_request.subsystem);
Packit Service 31306d
      switch (msg->channel_request.type) {
Packit Service 31306d
      case SSH_CHANNEL_REQUEST_EXEC:
Packit Service 31306d
          SAFE_FREE(msg->channel_request.command);
Packit Service 31306d
          break;
Packit Service 31306d
      case SSH_CHANNEL_REQUEST_ENV:
Packit Service 31306d
          SAFE_FREE(msg->channel_request.var_name);
Packit Service 31306d
          SAFE_FREE(msg->channel_request.var_value);
Packit Service 31306d
          break;
Packit Service 31306d
      case SSH_CHANNEL_REQUEST_PTY:
Packit Service 31306d
          SAFE_FREE(msg->channel_request.TERM);
Packit Service 31306d
          break;
Packit Service 31306d
      case SSH_CHANNEL_REQUEST_SUBSYSTEM:
Packit Service 31306d
          SAFE_FREE(msg->channel_request.subsystem);
Packit Service 31306d
          break;
Packit Service 31306d
      case SSH_CHANNEL_REQUEST_X11:
Packit Service 31306d
          SAFE_FREE(msg->channel_request.x11_auth_protocol);
Packit Service 31306d
          SAFE_FREE(msg->channel_request.x11_auth_cookie);
Packit Service 31306d
          break;
Packit Service 31306d
      }
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_REQUEST_SERVICE:
Packit Service 31306d
      SAFE_FREE(msg->service_request.service);
Packit Service 31306d
      break;
Packit Service 31306d
    case SSH_REQUEST_GLOBAL:
Packit Service 31306d
      SAFE_FREE(msg->global_request.bind_address);
Packit Service 31306d
      break;
Packit Service 31306d
  }
Packit Service 31306d
  ZERO_STRUCTP(msg);
Packit Service 31306d
  SAFE_FREE(msg);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
Packit Service 31306d
SSH_PACKET_CALLBACK(ssh_packet_service_request)
Packit Service 31306d
{
Packit Service 31306d
    char *service_c = NULL;
Packit Service 31306d
    ssh_message msg = NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    (void)type;
Packit Service 31306d
    (void)user;
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_unpack(packet,
Packit Service 31306d
                           "s",
Packit Service 31306d
                           &service_c);
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
        ssh_set_error(session,
Packit Service 31306d
                      SSH_FATAL,
Packit Service 31306d
                      "Invalid SSH_MSG_SERVICE_REQUEST packet");
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
            "Received a SERVICE_REQUEST for service %s",
Packit Service 31306d
            service_c);
Packit Service 31306d
Packit Service 31306d
    msg = ssh_message_new(session);
Packit Service 31306d
    if (msg == NULL) {
Packit Service 31306d
        SAFE_FREE(service_c);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    msg->type = SSH_REQUEST_SERVICE;
Packit Service 31306d
    msg->service_request.service = service_c;
Packit Service 31306d
Packit Service 31306d
    ssh_message_queue(session, msg);
Packit Service 31306d
error:
Packit Service 31306d
Packit Service 31306d
    return SSH_PACKET_USED;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
Packit Service 31306d
/*
Packit Service 31306d
 * This function concats in a buffer the values needed to do a signature
Packit Service 31306d
 * verification.
Packit Service 31306d
 */
Packit Service 31306d
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
Packit Service 31306d
                                                ssh_message msg,
Packit Service 31306d
                                                const char *service,
Packit Service 31306d
                                                ssh_string algo)
Packit Service 31306d
{
Packit Service 31306d
    struct ssh_crypto_struct *crypto = NULL;
Packit Service 31306d
    ssh_buffer buffer;
Packit Service 31306d
    ssh_string str=NULL;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
Packit Service 31306d
    if (crypto == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    buffer = ssh_buffer_new();
Packit Service 31306d
    if (buffer == NULL) {
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
    rc = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &str);
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        SSH_BUFFER_FREE(buffer);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_pack(buffer,
Packit Service 31306d
                         "dPbsssbsS",
Packit Service 31306d
                         crypto->digest_len, /* session ID string */
Packit Service 31306d
                         (size_t)crypto->digest_len, crypto->session_id,
Packit Service 31306d
                         SSH2_MSG_USERAUTH_REQUEST, /* type */
Packit Service 31306d
                         msg->auth_request.username,
Packit Service 31306d
                         service,
Packit Service 31306d
                         "publickey", /* method */
Packit Service 31306d
                         1, /* has to be signed (true) */
Packit Service 31306d
                         ssh_string_get_char(algo), /* pubkey algorithm */
Packit Service 31306d
                         str); /* public key as a blob */
Packit Service 31306d
Packit Service 31306d
    SSH_STRING_FREE(str);
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        SSH_BUFFER_FREE(buffer);
Packit Service 31306d
        return NULL;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return buffer;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief Handle a SSH_MSG_MSG_USERAUTH_REQUEST packet and queue a
Packit Service 31306d
 * SSH Message
Packit Service 31306d
 */
Packit Service 31306d
SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
Packit Service 31306d
  ssh_message msg = NULL;
Packit Service 31306d
  ssh_signature sig = NULL;
Packit Service 31306d
  char *service = NULL;
Packit Service 31306d
  char *method = NULL;
Packit Service 31306d
  int cmp;
Packit Service 31306d
  int rc;
Packit Service 31306d
Packit Service 31306d
  (void)user;
Packit Service 31306d
  (void)type;
Packit Service 31306d
Packit Service 31306d
  msg = ssh_message_new(session);
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    ssh_set_error_oom(session);
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
  msg->type = SSH_REQUEST_AUTH;
Packit Service 31306d
  rc = ssh_buffer_unpack(packet,
Packit Service 31306d
                         "sss",
Packit Service 31306d
                         &msg->auth_request.username,
Packit Service 31306d
                         &service,
Packit Service 31306d
                         &method);
Packit Service 31306d
Packit Service 31306d
  if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
      "Auth request for service %s, method %s for user '%s'",
Packit Service 31306d
      service, method,
Packit Service 31306d
      msg->auth_request.username);
Packit Service 31306d
Packit Service 31306d
  cmp = strcmp(service, "ssh-connection");
Packit Service 31306d
  if (cmp != 0) {
Packit Service 31306d
      SSH_LOG(SSH_LOG_WARNING,
Packit Service 31306d
              "Invalid service request: %s",
Packit Service 31306d
              service);
Packit Service 31306d
      goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(method, "none") == 0) {
Packit Service 31306d
    msg->auth_request.method = SSH_AUTH_METHOD_NONE;
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(method, "password") == 0) {
Packit Service 31306d
    uint8_t tmp;
Packit Service 31306d
Packit Service 31306d
    msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "bs", &tmp, &msg->auth_request.password);
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(method, "keyboard-interactive") == 0) {
Packit Service 31306d
    ssh_string lang = NULL;
Packit Service 31306d
    ssh_string submethods = NULL;
Packit Service 31306d
Packit Service 31306d
    msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
Packit Service 31306d
    lang = ssh_buffer_get_ssh_string(packet);
Packit Service 31306d
    if (lang == NULL) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    /* from the RFC 4256
Packit Service 31306d
     * 3.1.  Initial Exchange
Packit Service 31306d
     * "The language tag is deprecated and SHOULD be the empty string."
Packit Service 31306d
     */
Packit Service 31306d
    SSH_STRING_FREE(lang);
Packit Service 31306d
Packit Service 31306d
    submethods = ssh_buffer_get_ssh_string(packet);
Packit Service 31306d
    if (submethods == NULL) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    /* from the RFC 4256
Packit Service 31306d
     * 3.1.  Initial Exchange
Packit Service 31306d
     * "One possible implementation strategy of the submethods field on the
Packit Service 31306d
     *  server is that, unless the user may use multiple different
Packit Service 31306d
     *  submethods, the server ignores this field."
Packit Service 31306d
     */
Packit Service 31306d
    SSH_STRING_FREE(submethods);
Packit Service 31306d
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(method, "publickey") == 0) {
Packit Service 31306d
    ssh_string algo = NULL;
Packit Service 31306d
    ssh_string pubkey_blob = NULL;
Packit Service 31306d
    uint8_t has_sign;
Packit Service 31306d
Packit Service 31306d
    msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
Packit Service 31306d
    SAFE_FREE(method);
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "bSS",
Packit Service 31306d
            &has_sign,
Packit Service 31306d
            &algo,
Packit Service 31306d
            &pubkey_blob
Packit Service 31306d
            );
Packit Service 31306d
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
Packit Service 31306d
    SSH_STRING_FREE(pubkey_blob);
Packit Service 31306d
    pubkey_blob = NULL;
Packit Service 31306d
    if (rc < 0) {
Packit Service 31306d
        SSH_STRING_FREE(algo);
Packit Service 31306d
        algo = NULL;
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
Packit Service 31306d
    // has a valid signature ?
Packit Service 31306d
    if(has_sign) {
Packit Service 31306d
        ssh_string sig_blob = NULL;
Packit Service 31306d
        ssh_buffer digest = NULL;
Packit Service 31306d
Packit Service 31306d
        sig_blob = ssh_buffer_get_ssh_string(packet);
Packit Service 31306d
        if(sig_blob == NULL) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
Packit Service 31306d
            msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
Packit Service 31306d
            SSH_STRING_FREE(algo);
Packit Service 31306d
            algo = NULL;
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        digest = ssh_msg_userauth_build_digest(session, msg, service, algo);
Packit Service 31306d
        SSH_STRING_FREE(algo);
Packit Service 31306d
        algo = NULL;
Packit Service 31306d
        if (digest == NULL) {
Packit Service 31306d
            SSH_STRING_FREE(sig_blob);
Packit Service 31306d
            SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
Packit Service 31306d
            msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        rc = ssh_pki_import_signature_blob(sig_blob,
Packit Service 31306d
                                           msg->auth_request.pubkey,
Packit Service 31306d
                                           &sig);
Packit Service 31306d
        if (rc == SSH_OK) {
Packit Service 31306d
            /* Check if the signature from client matches server preferences */
Packit Service 31306d
            if (session->opts.pubkey_accepted_types) {
Packit Service 31306d
                if (!ssh_match_group(session->opts.pubkey_accepted_types,
Packit Service 31306d
                            sig->type_c))
Packit Service 31306d
                {
Packit Service 31306d
                    ssh_set_error(session,
Packit Service 31306d
                            SSH_FATAL,
Packit Service 31306d
                            "Public key from client (%s) doesn't match server "
Packit Service 31306d
                            "preference (%s)",
Packit Service 31306d
                            sig->type_c,
Packit Service 31306d
                            session->opts.pubkey_accepted_types);
Packit Service 31306d
                    rc = SSH_ERROR;
Packit Service 31306d
                }
Packit Service 31306d
            }
Packit Service 31306d
Packit Service 31306d
            if (rc == SSH_OK) {
Packit Service 31306d
                rc = ssh_pki_signature_verify(session,
Packit Service 31306d
                                              sig,
Packit Service 31306d
                                              msg->auth_request.pubkey,
Packit Service 31306d
                                              ssh_buffer_get(digest),
Packit Service 31306d
                                              ssh_buffer_get_len(digest));
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
        SSH_STRING_FREE(sig_blob);
Packit Service 31306d
        SSH_BUFFER_FREE(digest);
Packit Service 31306d
        ssh_signature_free(sig);
Packit Service 31306d
        if (rc < 0) {
Packit Service 31306d
            SSH_LOG(
Packit Service 31306d
                    SSH_LOG_PACKET,
Packit Service 31306d
                    "Received an invalid signature from peer");
Packit Service 31306d
            msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        SSH_LOG(SSH_LOG_PACKET, "Valid signature received");
Packit Service 31306d
Packit Service 31306d
        msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
Packit Service 31306d
    }
Packit Service 31306d
    SSH_STRING_FREE(algo);
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
#ifdef WITH_GSSAPI
Packit Service 31306d
  if (strcmp(method, "gssapi-with-mic") == 0) {
Packit Service 31306d
     uint32_t n_oid;
Packit Service 31306d
     ssh_string *oids;
Packit Service 31306d
     ssh_string oid;
Packit Service 31306d
     char *hexa;
Packit Service 31306d
     int i;
Packit Service 31306d
     ssh_buffer_get_u32(packet, &n_oid);
Packit Service 31306d
     n_oid=ntohl(n_oid);
Packit Service 31306d
     if(n_oid > 100){
Packit Service 31306d
    	 ssh_set_error(session, SSH_FATAL, "USERAUTH_REQUEST: gssapi-with-mic OID count too big (%d)",n_oid);
Packit Service 31306d
    	 goto error;
Packit Service 31306d
     }
Packit Service 31306d
     SSH_LOG(SSH_LOG_PACKET, "gssapi: %d OIDs", n_oid);
Packit Service 31306d
     oids = calloc(n_oid, sizeof(ssh_string));
Packit Service 31306d
     if (oids == NULL){
Packit Service 31306d
    	 ssh_set_error_oom(session);
Packit Service 31306d
    	 goto error;
Packit Service 31306d
     }
Packit Service 31306d
     for (i=0;i<(int) n_oid;++i){
Packit Service 31306d
    	 oid=ssh_buffer_get_ssh_string(packet);
Packit Service 31306d
    	 if(oid == NULL){
Packit Service 31306d
    		 for(i=i-1;i>=0;--i){
Packit Service 31306d
    			 SAFE_FREE(oids[i]);
Packit Service 31306d
    		 }
Packit Service 31306d
    		 SAFE_FREE(oids);
Packit Service 31306d
    		 ssh_set_error(session, SSH_LOG_PACKET, "USERAUTH_REQUEST: gssapi-with-mic missing OID");
Packit Service 31306d
    		 goto error;
Packit Service 31306d
    	 }
Packit Service 31306d
    	 oids[i] = oid;
Packit Service 31306d
    	 if(session->common.log_verbosity >= SSH_LOG_PACKET){
Packit Service 31306d
    		 hexa = ssh_get_hexa(ssh_string_data(oid), ssh_string_len(oid));
Packit Service 31306d
    		 SSH_LOG(SSH_LOG_PACKET,"gssapi: OID %d: %s",i, hexa);
Packit Service 31306d
    		 SAFE_FREE(hexa);
Packit Service 31306d
    	 }
Packit Service 31306d
     }
Packit Service 31306d
     ssh_gssapi_handle_userauth(session, msg->auth_request.username, n_oid, oids);
Packit Service 31306d
Packit Service 31306d
     for(i=0;i<(int)n_oid;++i){
Packit Service 31306d
    	 SAFE_FREE(oids[i]);
Packit Service 31306d
     }
Packit Service 31306d
     SAFE_FREE(oids);
Packit Service 31306d
     /* bypass the message queue thing */
Packit Service 31306d
     SAFE_FREE(service);
Packit Service 31306d
     SAFE_FREE(method);
Packit Service 31306d
     SSH_MESSAGE_FREE(msg);
Packit Service 31306d
Packit Service 31306d
     return SSH_PACKET_USED;
Packit Service 31306d
  }
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
  msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
Packit Service 31306d
  SAFE_FREE(method);
Packit Service 31306d
  goto end;
Packit Service 31306d
error:
Packit Service 31306d
  SAFE_FREE(service);
Packit Service 31306d
  SAFE_FREE(method);
Packit Service 31306d
Packit Service 31306d
  SSH_MESSAGE_FREE(msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_PACKET_USED;
Packit Service 31306d
end:
Packit Service 31306d
  SAFE_FREE(service);
Packit Service 31306d
  SAFE_FREE(method);
Packit Service 31306d
Packit Service 31306d
  ssh_message_queue(session,msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_PACKET_USED;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif /* WITH_SERVER */
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief Handle a SSH_MSG_MSG_USERAUTH_INFO_RESPONSE packet and queue a
Packit Service 31306d
 * SSH Message
Packit Service 31306d
 */
Packit Service 31306d
#ifndef WITH_SERVER
Packit Service 31306d
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
Packit Service 31306d
    (void)session;
Packit Service 31306d
    (void)type;
Packit Service 31306d
    (void)packet;
Packit Service 31306d
    (void)user;
Packit Service 31306d
    return SSH_PACKET_USED;
Packit Service 31306d
}
Packit Service 31306d
#else /* WITH_SERVER */
Packit Service 31306d
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
Packit Service 31306d
  uint32_t nanswers;
Packit Service 31306d
  uint32_t i;
Packit Service 31306d
  ssh_string tmp;
Packit Service 31306d
  int rc;
Packit Service 31306d
Packit Service 31306d
  ssh_message msg = NULL;
Packit Service 31306d
Packit Service 31306d
  /* GSSAPI_TOKEN has same packed number. XXX fix this */
Packit Service 31306d
#ifdef WITH_GSSAPI
Packit Service 31306d
  if (session->gssapi != NULL) {
Packit Service 31306d
      return ssh_packet_userauth_gssapi_token(session, type, packet, user);
Packit Service 31306d
  }
Packit Service 31306d
#endif
Packit Service 31306d
  (void)user;
Packit Service 31306d
  (void)type;
Packit Service 31306d
Packit Service 31306d
  msg = ssh_message_new(session);
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    ssh_set_error_oom(session);
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  /* HACK: we forge a message to be able to handle it in the
Packit Service 31306d
   * same switch() as other auth methods */
Packit Service 31306d
  msg->type = SSH_REQUEST_AUTH;
Packit Service 31306d
  msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
Packit Service 31306d
  msg->auth_request.kbdint_response = 1;
Packit Service 31306d
#if 0 // should we wipe the username ?
Packit Service 31306d
  msg->auth_request.username = NULL;
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
  rc = ssh_buffer_unpack(packet, "d", &nanswers);
Packit Service 31306d
  if (rc != SSH_OK) {
Packit Service 31306d
      ssh_set_error_invalid(session);
Packit Service 31306d
      goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (session->kbdint == NULL) {
Packit Service 31306d
    SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a keyboard-interactive "
Packit Service 31306d
                        "response but it seems we didn't send the request.");
Packit Service 31306d
Packit Service 31306d
    session->kbdint = ssh_kbdint_new();
Packit Service 31306d
    if (session->kbdint == NULL) {
Packit Service 31306d
      ssh_set_error_oom(session);
Packit Service 31306d
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
  } else if (session->kbdint->answers != NULL) {
Packit Service 31306d
      uint32_t n;
Packit Service 31306d
Packit Service 31306d
      for (n = 0; n < session->kbdint->nanswers; n++) {
Packit Service 31306d
            explicit_bzero(session->kbdint->answers[n],
Packit Service 31306d
                           strlen(session->kbdint->answers[n]));
Packit Service 31306d
            SAFE_FREE(session->kbdint->answers[n]);
Packit Service 31306d
      }
Packit Service 31306d
      SAFE_FREE(session->kbdint->answers);
Packit Service 31306d
      session->kbdint->nanswers = 0;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  SSH_LOG(SSH_LOG_PACKET,"kbdint: %d answers",nanswers);
Packit Service 31306d
  if (nanswers > KBDINT_MAX_PROMPT) {
Packit Service 31306d
    ssh_set_error(session, SSH_FATAL,
Packit Service 31306d
        "Too much answers received from client: %u (0x%.4x)",
Packit Service 31306d
        nanswers, nanswers);
Packit Service 31306d
    ssh_kbdint_free(session->kbdint);
Packit Service 31306d
    session->kbdint = NULL;
Packit Service 31306d
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if(nanswers != session->kbdint->nprompts) {
Packit Service 31306d
    /* warn but let the application handle this case */
Packit Service 31306d
    SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Number of prompts and answers"
Packit Service 31306d
                " mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers);
Packit Service 31306d
  }
Packit Service 31306d
  session->kbdint->nanswers = nanswers;
Packit Service 31306d
Packit Service 31306d
  session->kbdint->answers = calloc(nanswers, sizeof(char *));
Packit Service 31306d
  if (session->kbdint->answers == NULL) {
Packit Service 31306d
    session->kbdint->nanswers = 0;
Packit Service 31306d
    ssh_set_error_oom(session);
Packit Service 31306d
    ssh_kbdint_free(session->kbdint);
Packit Service 31306d
    session->kbdint = NULL;
Packit Service 31306d
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  for (i = 0; i < nanswers; i++) {
Packit Service 31306d
    tmp = ssh_buffer_get_ssh_string(packet);
Packit Service 31306d
    if (tmp == NULL) {
Packit Service 31306d
      ssh_set_error(session, SSH_FATAL, "Short INFO_RESPONSE packet");
Packit Service 31306d
      session->kbdint->nanswers = i;
Packit Service 31306d
      ssh_kbdint_free(session->kbdint);
Packit Service 31306d
      session->kbdint = NULL;
Packit Service 31306d
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    session->kbdint->answers[i] = ssh_string_to_char(tmp);
Packit Service 31306d
    SSH_STRING_FREE(tmp);
Packit Service 31306d
    if (session->kbdint->answers[i] == NULL) {
Packit Service 31306d
      ssh_set_error_oom(session);
Packit Service 31306d
      session->kbdint->nanswers = i;
Packit Service 31306d
      ssh_kbdint_free(session->kbdint);
Packit Service 31306d
      session->kbdint = NULL;
Packit Service 31306d
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  ssh_message_queue(session,msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_PACKET_USED;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
  SSH_MESSAGE_FREE(msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_PACKET_USED;
Packit Service 31306d
}
Packit Service 31306d
#endif /* WITH_SERVER */
Packit Service 31306d
Packit Service 31306d
SSH_PACKET_CALLBACK(ssh_packet_channel_open){
Packit Service 31306d
  ssh_message msg = NULL;
Packit Service 31306d
  char *type_c = NULL;
Packit Service 31306d
  uint32_t originator_port, destination_port;
Packit Service 31306d
  int rc;
Packit Service 31306d
Packit Service 31306d
  (void)type;
Packit Service 31306d
  (void)user;
Packit Service 31306d
  msg = ssh_message_new(session);
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    ssh_set_error_oom(session);
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  msg->type = SSH_REQUEST_CHANNEL_OPEN;
Packit Service 31306d
  rc = ssh_buffer_unpack(packet, "s", &type_c);
Packit Service 31306d
  if (rc != SSH_OK){
Packit Service 31306d
      goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
      "Clients wants to open a %s channel", type_c);
Packit Service 31306d
Packit Service 31306d
  ssh_buffer_unpack(packet,"ddd",
Packit Service 31306d
          &msg->channel_request_open.sender,
Packit Service 31306d
          &msg->channel_request_open.window,
Packit Service 31306d
          &msg->channel_request_open.packet_size);
Packit Service 31306d
Packit Service 31306d
  if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED){
Packit Service 31306d
    ssh_set_error(session,SSH_FATAL, "Invalid state when receiving channel open request (must be authenticated)");
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
  
Packit Service 31306d
  if (strcmp(type_c,"session") == 0) {
Packit Service 31306d
    msg->channel_request_open.type = SSH_CHANNEL_SESSION;
Packit Service 31306d
    SAFE_FREE(type_c);
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(type_c,"direct-tcpip") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet,
Packit Service 31306d
                           "sdsd",
Packit Service 31306d
                           &msg->channel_request_open.destination,
Packit Service 31306d
                           &destination_port,
Packit Service 31306d
                           &msg->channel_request_open.originator,
Packit Service 31306d
                           &originator_port);
Packit Service 31306d
	if (rc != SSH_OK) {
Packit Service 31306d
		goto error;
Packit Service 31306d
	}
Packit Service 31306d
Packit Service 31306d
    msg->channel_request_open.destination_port = (uint16_t) destination_port;
Packit Service 31306d
    msg->channel_request_open.originator_port = (uint16_t) originator_port;
Packit Service 31306d
    msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP;
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(type_c,"forwarded-tcpip") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "sdsd",
Packit Service 31306d
            &msg->channel_request_open.destination,
Packit Service 31306d
            &destination_port,
Packit Service 31306d
            &msg->channel_request_open.originator,
Packit Service 31306d
            &originator_port
Packit Service 31306d
        );
Packit Service 31306d
    if (rc != SSH_OK){
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    msg->channel_request_open.destination_port = (uint16_t) destination_port;
Packit Service 31306d
    msg->channel_request_open.originator_port = (uint16_t) originator_port;
Packit Service 31306d
    msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP;
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(type_c,"x11") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "sd",
Packit Service 31306d
            &msg->channel_request_open.originator,
Packit Service 31306d
            &originator_port);
Packit Service 31306d
    if (rc != SSH_OK){
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    msg->channel_request_open.originator_port = (uint16_t) originator_port;
Packit Service 31306d
    msg->channel_request_open.type = SSH_CHANNEL_X11;
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(type_c,"auth-agent@openssh.com") == 0) {
Packit Service 31306d
    msg->channel_request_open.type = SSH_CHANNEL_AUTH_AGENT;
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN;
Packit Service 31306d
  goto end;
Packit Service 31306d
Packit Service 31306d
error:
Packit Service 31306d
  SSH_MESSAGE_FREE(msg);
Packit Service 31306d
end:
Packit Service 31306d
  SAFE_FREE(type_c);
Packit Service 31306d
  if(msg != NULL)
Packit Service 31306d
    ssh_message_queue(session,msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_PACKET_USED;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief This function accepts a channel open request for the specified channel.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  msg      The message.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  chan     The channel the request is made on.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             SSH_OK on success, SSH_ERROR if an error occured.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan) {
Packit Service 31306d
    ssh_session session;
Packit Service 31306d
    int rc;
Packit Service 31306d
Packit Service 31306d
    if (msg == NULL) {
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    session = msg->session;
Packit Service 31306d
Packit Service 31306d
    chan->local_channel = ssh_channel_new_id(session);
Packit Service 31306d
    chan->local_maxpacket = 35000;
Packit Service 31306d
    chan->local_window = 32000;
Packit Service 31306d
    chan->remote_channel = msg->channel_request_open.sender;
Packit Service 31306d
    chan->remote_maxpacket = msg->channel_request_open.packet_size;
Packit Service 31306d
    chan->remote_window = msg->channel_request_open.window;
Packit Service 31306d
    chan->state = SSH_CHANNEL_STATE_OPEN;
Packit Service 31306d
    chan->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND;
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_pack(session->out_buffer,
Packit Service 31306d
                         "bdddd",
Packit Service 31306d
                         SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
Packit Service 31306d
                         chan->remote_channel,
Packit Service 31306d
                         chan->local_channel,
Packit Service 31306d
                         chan->local_window,
Packit Service 31306d
                         chan->local_maxpacket);
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
            "Accepting a channel request_open for chan %d",
Packit Service 31306d
            chan->remote_channel);
Packit Service 31306d
Packit Service 31306d
    rc = ssh_packet_send(session);
Packit Service 31306d
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief This function accepts a channel open request.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  msg      The message.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns a valid ssh_channel handle if the request is to be allowed
Packit Service 31306d
 *
Packit Service 31306d
 * @returns NULL in case of error
Packit Service 31306d
 */
Packit Service 31306d
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) {
Packit Service 31306d
	ssh_channel chan;
Packit Service 31306d
	int rc;
Packit Service 31306d
Packit Service 31306d
	if (msg == NULL) {
Packit Service 31306d
	    return NULL;
Packit Service 31306d
	}
Packit Service 31306d
Packit Service 31306d
	chan = ssh_channel_new(msg->session);
Packit Service 31306d
	if (chan == NULL) {
Packit Service 31306d
		return NULL;
Packit Service 31306d
	}
Packit Service 31306d
	rc = ssh_message_channel_request_open_reply_accept_channel(msg, chan);
Packit Service 31306d
	if (rc < 0) {
Packit Service 31306d
		ssh_channel_free(chan);
Packit Service 31306d
		chan = NULL;
Packit Service 31306d
	}
Packit Service 31306d
	return chan;
Packit Service 31306d
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/**
Packit Service 31306d
 * @internal
Packit Service 31306d
 *
Packit Service 31306d
 * @brief This function parses the last end of a channel request packet.
Packit Service 31306d
 *
Packit Service 31306d
 * This is normally converted to a SSH message and placed in the queue.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  session  The SSH session.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  channel  The channel the request is made on.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  packet   The rest of the packet to be parsed.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  request  The type of request.
Packit Service 31306d
 *
Packit Service 31306d
 * @param[in]  want_reply The want_reply field from the request.
Packit Service 31306d
 *
Packit Service 31306d
 * @returns             SSH_OK on success, SSH_ERROR if an error occured.
Packit Service 31306d
 */
Packit Service 31306d
int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet,
Packit Service 31306d
    const char *request, uint8_t want_reply) {
Packit Service 31306d
  ssh_message msg = NULL;
Packit Service 31306d
  int rc;
Packit Service 31306d
Packit Service 31306d
  msg = ssh_message_new(session);
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    ssh_set_error_oom(session);
Packit Service 31306d
    goto error;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
      "Received a %s channel_request for channel (%d:%d) (want_reply=%hhd)",
Packit Service 31306d
      request, channel->local_channel, channel->remote_channel, want_reply);
Packit Service 31306d
Packit Service 31306d
  msg->type = SSH_REQUEST_CHANNEL;
Packit Service 31306d
  msg->channel_request.channel = channel;
Packit Service 31306d
  msg->channel_request.want_reply = want_reply;
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "pty-req") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "sddddS",
Packit Service 31306d
            &msg->channel_request.TERM,
Packit Service 31306d
            &msg->channel_request.width,
Packit Service 31306d
            &msg->channel_request.height,
Packit Service 31306d
            &msg->channel_request.pxwidth,
Packit Service 31306d
            &msg->channel_request.pxheight,
Packit Service 31306d
            &msg->channel_request.modes
Packit Service 31306d
            );
Packit Service 31306d
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY;
Packit Service 31306d
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "window-change") == 0) {
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE;
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "dddd",
Packit Service 31306d
            &msg->channel_request.width,
Packit Service 31306d
            &msg->channel_request.height,
Packit Service 31306d
            &msg->channel_request.pxwidth,
Packit Service 31306d
            &msg->channel_request.pxheight);
Packit Service 31306d
    if (rc != SSH_OK){
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "subsystem") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "s",
Packit Service 31306d
            &msg->channel_request.subsystem);
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM;
Packit Service 31306d
    if (rc != SSH_OK){
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "shell") == 0) {
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL;
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "exec") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "s",
Packit Service 31306d
            &msg->channel_request.command);
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC;
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "env") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "ss",
Packit Service 31306d
            &msg->channel_request.var_name,
Packit Service 31306d
            &msg->channel_request.var_value);
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV;
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (strcmp(request, "x11-req") == 0) {
Packit Service 31306d
    rc = ssh_buffer_unpack(packet, "bssd",
Packit Service 31306d
            &msg->channel_request.x11_single_connection,
Packit Service 31306d
            &msg->channel_request.x11_auth_protocol,
Packit Service 31306d
            &msg->channel_request.x11_auth_cookie,
Packit Service 31306d
            &msg->channel_request.x11_screen_number);
Packit Service 31306d
Packit Service 31306d
    msg->channel_request.type = SSH_CHANNEL_REQUEST_X11;
Packit Service 31306d
    if (rc != SSH_OK) {
Packit Service 31306d
      goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    goto end;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  msg->channel_request.type = SSH_CHANNEL_REQUEST_UNKNOWN;
Packit Service 31306d
end:
Packit Service 31306d
  ssh_message_queue(session,msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_OK;
Packit Service 31306d
error:
Packit Service 31306d
  SSH_MESSAGE_FREE(msg);
Packit Service 31306d
Packit Service 31306d
  return SSH_ERROR;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
int ssh_message_channel_request_reply_success(ssh_message msg) {
Packit Service 31306d
  uint32_t channel;
Packit Service 31306d
  int rc;
Packit Service 31306d
Packit Service 31306d
  if (msg == NULL) {
Packit Service 31306d
    return SSH_ERROR;
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  if (msg->channel_request.want_reply) {
Packit Service 31306d
    channel = msg->channel_request.channel->remote_channel;
Packit Service 31306d
Packit Service 31306d
    SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
        "Sending a channel_request success to channel %d", channel);
Packit Service 31306d
Packit Service 31306d
    rc = ssh_buffer_pack(msg->session->out_buffer,
Packit Service 31306d
                         "bd",
Packit Service 31306d
                         SSH2_MSG_CHANNEL_SUCCESS,
Packit Service 31306d
                         channel);
Packit Service 31306d
    if (rc != SSH_OK){
Packit Service 31306d
      ssh_set_error_oom(msg->session);
Packit Service 31306d
      return SSH_ERROR;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return ssh_packet_send(msg->session);
Packit Service 31306d
  }
Packit Service 31306d
Packit Service 31306d
  SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
      "The client doesn't want to know the request succeeded");
Packit Service 31306d
Packit Service 31306d
  return SSH_OK;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_SERVER
Packit Service 31306d
SSH_PACKET_CALLBACK(ssh_packet_global_request){
Packit Service 31306d
    ssh_message msg = NULL;
Packit Service 31306d
    char *request=NULL;
Packit Service 31306d
    uint8_t want_reply;
Packit Service 31306d
    int rc = SSH_PACKET_USED;
Packit Service 31306d
    int r;
Packit Service 31306d
    (void)user;
Packit Service 31306d
    (void)type;
Packit Service 31306d
    (void)packet;
Packit Service 31306d
Packit Service 31306d
    SSH_LOG(SSH_LOG_PROTOCOL,"Received SSH_MSG_GLOBAL_REQUEST packet");
Packit Service 31306d
    r = ssh_buffer_unpack(packet, "sb",
Packit Service 31306d
            &request,
Packit Service 31306d
            &want_reply);
Packit Service 31306d
    if (r != SSH_OK){
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    msg = ssh_message_new(session);
Packit Service 31306d
    if (msg == NULL) {
Packit Service 31306d
        ssh_set_error_oom(session);
Packit Service 31306d
        goto error;
Packit Service 31306d
    }
Packit Service 31306d
    msg->type = SSH_REQUEST_GLOBAL;
Packit Service 31306d
Packit Service 31306d
    if (strcmp(request, "tcpip-forward") == 0) {
Packit Service 31306d
Packit Service 31306d
        /* According to RFC4254, the client SHOULD reject this message */
Packit Service 31306d
        if (session->client) {
Packit Service 31306d
            goto reply_with_failure;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        r = ssh_buffer_unpack(packet, "sd",
Packit Service 31306d
                &msg->global_request.bind_address,
Packit Service 31306d
                &msg->global_request.bind_port
Packit Service 31306d
                );
Packit Service 31306d
        if (r != SSH_OK){
Packit Service 31306d
            goto reply_with_failure;
Packit Service 31306d
        }
Packit Service 31306d
        msg->global_request.type = SSH_GLOBAL_REQUEST_TCPIP_FORWARD;
Packit Service 31306d
        msg->global_request.want_reply = want_reply;
Packit Service 31306d
Packit Service 31306d
        SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply,
Packit Service 31306d
                msg->global_request.bind_address,
Packit Service 31306d
                msg->global_request.bind_port);
Packit Service 31306d
Packit Service 31306d
        if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
Packit Service 31306d
            SSH_LOG(SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request,
Packit Service 31306d
                    want_reply, msg->global_request.bind_address,
Packit Service 31306d
                    msg->global_request.bind_port);
Packit Service 31306d
            session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
Packit Service 31306d
        } else {
Packit Service 31306d
            SAFE_FREE(request);
Packit Service 31306d
            ssh_message_queue(session, msg);
Packit Service 31306d
            return rc;
Packit Service 31306d
        }
Packit Service 31306d
    } else if (strcmp(request, "cancel-tcpip-forward") == 0) {
Packit Service 31306d
Packit Service 31306d
        /* According to RFC4254, the client SHOULD reject this message */
Packit Service 31306d
        if (session->client) {
Packit Service 31306d
            goto reply_with_failure;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        r = ssh_buffer_unpack(packet, "sd",
Packit Service 31306d
                &msg->global_request.bind_address,
Packit Service 31306d
                &msg->global_request.bind_port);
Packit Service 31306d
        if (r != SSH_OK){
Packit Service 31306d
            goto reply_with_failure;
Packit Service 31306d
        }
Packit Service 31306d
        msg->global_request.type = SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD;
Packit Service 31306d
        msg->global_request.want_reply = want_reply;
Packit Service 31306d
Packit Service 31306d
        SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply,
Packit Service 31306d
                msg->global_request.bind_address,
Packit Service 31306d
                msg->global_request.bind_port);
Packit Service 31306d
Packit Service 31306d
        if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
Packit Service 31306d
            session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
Packit Service 31306d
        } else {
Packit Service 31306d
            SAFE_FREE(request);
Packit Service 31306d
            ssh_message_queue(session, msg);
Packit Service 31306d
            return rc;
Packit Service 31306d
        }
Packit Service 31306d
    } else if(strcmp(request, "keepalive@openssh.com") == 0) {
Packit Service 31306d
        msg->global_request.type = SSH_GLOBAL_REQUEST_KEEPALIVE;
Packit Service 31306d
        msg->global_request.want_reply = want_reply;
Packit Service 31306d
        SSH_LOG(SSH_LOG_PROTOCOL, "Received keepalive@openssh.com %d", want_reply);
Packit Service 31306d
        if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
Packit Service 31306d
            session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
Packit Service 31306d
        } else {
Packit Service 31306d
            ssh_message_global_request_reply_success(msg, 0);
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, "
Packit Service 31306d
                "want_reply = %d", request, want_reply);
Packit Service 31306d
        goto reply_with_failure;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    SAFE_FREE(msg);
Packit Service 31306d
    SAFE_FREE(request);
Packit Service 31306d
    return rc;
Packit Service 31306d
Packit Service 31306d
reply_with_failure:
Packit Service 31306d
    /* Only report the failure if requested */
Packit Service 31306d
    if (want_reply) {
Packit Service 31306d
        r = ssh_buffer_add_u8(session->out_buffer,
Packit Service 31306d
                SSH2_MSG_REQUEST_FAILURE);
Packit Service 31306d
        if (r < 0) {
Packit Service 31306d
            ssh_set_error_oom(session);
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        r = ssh_packet_send(session);
Packit Service 31306d
        if (r != SSH_OK) {
Packit Service 31306d
            goto error;
Packit Service 31306d
        }
Packit Service 31306d
    } else {
Packit Service 31306d
        SSH_LOG(SSH_LOG_PACKET,
Packit Service 31306d
                "The requester doesn't want to know the request failed!");
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    /* Consume the message to avoid sending UNIMPLEMENTED later */
Packit Service 31306d
    rc = SSH_PACKET_USED;
Packit Service 31306d
error:
Packit Service 31306d
    SAFE_FREE(msg);
Packit Service 31306d
    SAFE_FREE(request);
Packit Service 31306d
    SSH_LOG(SSH_LOG_WARNING, "Invalid SSH_MSG_GLOBAL_REQUEST packet");
Packit Service 31306d
    return rc;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#endif /* WITH_SERVER */
Packit Service 31306d
Packit Service 31306d
/** @} */