Blame src/bind.c

Packit 6c0a39
/*
Packit 6c0a39
 * bind.c : all ssh_bind functions
Packit 6c0a39
 *
Packit 6c0a39
 * This file is part of the SSH Library
Packit 6c0a39
 *
Packit 6c0a39
 * Copyright (c) 2004-2005 by Aris Adamantiadis
Packit 6c0a39
 *
Packit 6c0a39
 * The SSH Library is free software; you can redistribute it and/or modify
Packit 6c0a39
 * it under the terms of the GNU Lesser General Public License as published by
Packit 6c0a39
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit 6c0a39
 * option) any later version.
Packit 6c0a39
 *
Packit 6c0a39
 * The SSH Library is distributed in the hope that it will be useful, but
Packit 6c0a39
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 6c0a39
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit 6c0a39
 * License for more details.
Packit 6c0a39
 *
Packit 6c0a39
 * You should have received a copy of the GNU Lesser General Public License
Packit 6c0a39
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit 6c0a39
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit 6c0a39
 * MA 02111-1307, USA.
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
#include "config.h"
Packit 6c0a39
Packit 6c0a39
#include <errno.h>
Packit 6c0a39
#include <fcntl.h>
Packit 6c0a39
#include <stdio.h>
Packit 6c0a39
#include <string.h>
Packit 6c0a39
#include <stdlib.h>
Packit 6c0a39
Packit 6c0a39
#include "libssh/priv.h"
Packit 6c0a39
#include "libssh/bind.h"
Packit 6c0a39
#include "libssh/libssh.h"
Packit 6c0a39
#include "libssh/server.h"
Packit 6c0a39
#include "libssh/pki.h"
Packit 6c0a39
#include "libssh/buffer.h"
Packit 6c0a39
#include "libssh/socket.h"
Packit 6c0a39
#include "libssh/session.h"
Packit 6c0a39
#include "libssh/token.h"
Packit 6c0a39
Packit 6c0a39
/**
Packit 6c0a39
 * @addtogroup libssh_server
Packit 6c0a39
 *
Packit 6c0a39
 * @{
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
#ifdef _WIN32
Packit 6c0a39
#include <io.h>
Packit 6c0a39
#include <winsock2.h>
Packit 6c0a39
#include <ws2tcpip.h>
Packit 6c0a39
Packit 6c0a39
/*
Packit 6c0a39
 * <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
Packit 6c0a39
 * available on some platforms like MinGW.
Packit 6c0a39
 */
Packit 6c0a39
#ifdef HAVE_WSPIAPI_H
Packit 6c0a39
# include <wspiapi.h>
Packit 6c0a39
#endif
Packit 6c0a39
Packit 6c0a39
#define SOCKOPT_TYPE_ARG4 char
Packit 6c0a39
Packit 6c0a39
#else /* _WIN32 */
Packit 6c0a39
Packit 6c0a39
#include <sys/socket.h>
Packit 6c0a39
#include <netinet/in.h>
Packit 6c0a39
#include <netdb.h>
Packit 6c0a39
#define SOCKOPT_TYPE_ARG4 int
Packit 6c0a39
Packit 6c0a39
#endif /* _WIN32 */
Packit 6c0a39
Packit 6c0a39
static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
Packit 6c0a39
    int port) {
Packit 6c0a39
    char port_c[6];
Packit 6c0a39
    struct addrinfo *ai;
Packit 6c0a39
    struct addrinfo hints;
Packit 6c0a39
    int opt = 1;
Packit 6c0a39
    socket_t s;
Packit 6c0a39
    int rc;
Packit 6c0a39
Packit 6c0a39
    ZERO_STRUCT(hints);
Packit 6c0a39
Packit 6c0a39
    hints.ai_flags = AI_PASSIVE;
Packit 6c0a39
    hints.ai_socktype = SOCK_STREAM;
Packit 6c0a39
Packit 6c0a39
    snprintf(port_c, 6, "%d", port);
Packit 6c0a39
    rc = getaddrinfo(hostname, port_c, &hints, &ai;;
Packit 6c0a39
    if (rc != 0) {
Packit 6c0a39
        ssh_set_error(sshbind,
Packit 6c0a39
                      SSH_FATAL,
Packit 6c0a39
                      "Resolving %s: %s", hostname, gai_strerror(rc));
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    s = socket (ai->ai_family,
Packit 6c0a39
                           ai->ai_socktype,
Packit 6c0a39
                           ai->ai_protocol);
Packit 6c0a39
    if (s == SSH_INVALID_SOCKET) {
Packit 6c0a39
        ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
Packit 6c0a39
        freeaddrinfo (ai);
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
Packit 6c0a39
                   (char *)&opt, sizeof(opt)) < 0) {
Packit 6c0a39
        ssh_set_error(sshbind,
Packit 6c0a39
                      SSH_FATAL,
Packit 6c0a39
                      "Setting socket options failed: %s",
Packit 6c0a39
                      strerror(errno));
Packit 6c0a39
        freeaddrinfo (ai);
Packit 6c0a39
        CLOSE_SOCKET(s);
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (bind(s, ai->ai_addr, ai->ai_addrlen) != 0) {
Packit 6c0a39
        ssh_set_error(sshbind,
Packit 6c0a39
                      SSH_FATAL,
Packit 6c0a39
                      "Binding to %s:%d: %s",
Packit 6c0a39
                      hostname,
Packit 6c0a39
                      port,
Packit 6c0a39
                      strerror(errno));
Packit 6c0a39
        freeaddrinfo (ai);
Packit 6c0a39
        CLOSE_SOCKET(s);
Packit 6c0a39
        return -1;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    freeaddrinfo (ai);
Packit 6c0a39
    return s;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
ssh_bind ssh_bind_new(void) {
Packit 6c0a39
    ssh_bind ptr;
Packit 6c0a39
Packit 6c0a39
    ptr = calloc(1, sizeof(struct ssh_bind_struct));
Packit 6c0a39
    if (ptr == NULL) {
Packit 6c0a39
        return NULL;
Packit 6c0a39
    }
Packit 6c0a39
    ptr->bindfd = SSH_INVALID_SOCKET;
Packit 6c0a39
    ptr->bindport = 22;
Packit 6c0a39
    ptr->common.log_verbosity = 0;
Packit 6c0a39
Packit 6c0a39
    return ptr;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
static int ssh_bind_import_keys(ssh_bind sshbind) {
Packit 6c0a39
  int rc;
Packit 6c0a39
Packit 6c0a39
  if (sshbind->ecdsakey == NULL &&
Packit 6c0a39
      sshbind->dsakey == NULL &&
Packit 6c0a39
      sshbind->rsakey == NULL &&
Packit 6c0a39
      sshbind->ed25519key == NULL) {
Packit 6c0a39
      ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                    "ECDSA, ED25519, DSA, or RSA host key file must be set");
Packit 6c0a39
      return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
#ifdef HAVE_ECC
Packit 6c0a39
  if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) {
Packit 6c0a39
      rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       &sshbind->ecdsa);
Packit 6c0a39
      if (rc == SSH_ERROR || rc == SSH_EOF) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "Failed to import private ECDSA host key");
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      if (!is_ecdsa_key_type(ssh_key_type(sshbind->ecdsa))) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "The ECDSA host key has the wrong type");
Packit 6c0a39
          ssh_key_free(sshbind->ecdsa);
Packit 6c0a39
          sshbind->ecdsa = NULL;
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
  }
Packit 6c0a39
#endif
Packit 6c0a39
Packit 6c0a39
#ifdef HAVE_DSA
Packit 6c0a39
  if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
Packit 6c0a39
      rc = ssh_pki_import_privkey_file(sshbind->dsakey,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       &sshbind->dsa);
Packit 6c0a39
      if (rc == SSH_ERROR || rc == SSH_EOF) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "Failed to import private DSA host key");
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "The DSA host key has the wrong type: %d",
Packit 6c0a39
                  ssh_key_type(sshbind->dsa));
Packit 6c0a39
          ssh_key_free(sshbind->dsa);
Packit 6c0a39
          sshbind->dsa = NULL;
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
  }
Packit 6c0a39
#endif
Packit 6c0a39
Packit 6c0a39
  if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
Packit 6c0a39
      rc = ssh_pki_import_privkey_file(sshbind->rsakey,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       &sshbind->rsa);
Packit 6c0a39
      if (rc == SSH_ERROR || rc == SSH_EOF) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "Failed to import private RSA host key");
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "The RSA host key has the wrong type");
Packit 6c0a39
          ssh_key_free(sshbind->rsa);
Packit 6c0a39
          sshbind->rsa = NULL;
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  if (sshbind->ed25519 == NULL && sshbind->ed25519key != NULL) {
Packit 6c0a39
      rc = ssh_pki_import_privkey_file(sshbind->ed25519key,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       NULL,
Packit 6c0a39
                                       &sshbind->ed25519);
Packit 6c0a39
      if (rc == SSH_ERROR || rc == SSH_EOF) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "Failed to import private ED25519 host key");
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      if (ssh_key_type(sshbind->ed25519) != SSH_KEYTYPE_ED25519) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "The ED25519 host key has the wrong type");
Packit 6c0a39
          ssh_key_free(sshbind->ed25519);
Packit 6c0a39
          sshbind->ed25519 = NULL;
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int ssh_bind_listen(ssh_bind sshbind) {
Packit 6c0a39
  const char *host;
Packit 6c0a39
  socket_t fd;
Packit 6c0a39
  int rc;
Packit 6c0a39
Packit 6c0a39
  if (sshbind->rsa == NULL &&
Packit 6c0a39
      sshbind->dsa == NULL &&
Packit 6c0a39
      sshbind->ecdsa == NULL &&
Packit 6c0a39
      sshbind->ed25519 == NULL) {
Packit 6c0a39
      rc = ssh_bind_import_keys(sshbind);
Packit 6c0a39
      if (rc != SSH_OK) {
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  if (sshbind->bindfd == SSH_INVALID_SOCKET) {
Packit 6c0a39
      host = sshbind->bindaddr;
Packit 6c0a39
      if (host == NULL) {
Packit 6c0a39
          host = "0.0.0.0";
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      fd = bind_socket(sshbind, host, sshbind->bindport);
Packit 6c0a39
      if (fd == SSH_INVALID_SOCKET) {
Packit 6c0a39
          ssh_key_free(sshbind->dsa);
Packit 6c0a39
          sshbind->dsa = NULL;
Packit 6c0a39
          ssh_key_free(sshbind->rsa);
Packit 6c0a39
          sshbind->rsa = NULL;
Packit 6c0a39
          /* XXX should this clear also other structures that were allocated */
Packit 6c0a39
          return -1;
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      if (listen(fd, 10) < 0) {
Packit 6c0a39
          ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
                  "Listening to socket %d: %s",
Packit 6c0a39
                  fd, strerror(errno));
Packit 6c0a39
          CLOSE_SOCKET(fd);
Packit 6c0a39
          ssh_key_free(sshbind->dsa);
Packit 6c0a39
          sshbind->dsa = NULL;
Packit 6c0a39
          ssh_key_free(sshbind->rsa);
Packit 6c0a39
          sshbind->rsa = NULL;
Packit 6c0a39
          /* XXX should this clear also other structures that were allocated */
Packit 6c0a39
          return -1;
Packit 6c0a39
      }
Packit 6c0a39
Packit 6c0a39
      sshbind->bindfd = fd;
Packit 6c0a39
  } else {
Packit 6c0a39
      SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
Packit 6c0a39
  }
Packit 6c0a39
  return 0;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
Packit 6c0a39
    void *userdata){
Packit 6c0a39
  if (sshbind == NULL) {
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
  if (callbacks == NULL) {
Packit 6c0a39
    ssh_set_error_invalid(sshbind);
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
  if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
Packit 6c0a39
    ssh_set_error(sshbind,SSH_FATAL,
Packit 6c0a39
        "Invalid callback passed in (badly initialized)");
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
  sshbind->bind_callbacks = callbacks;
Packit 6c0a39
  sshbind->bind_callbacks_userdata=userdata;
Packit 6c0a39
  return 0;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief callback being called by poll when an event happens
Packit 6c0a39
 *
Packit 6c0a39
 */
Packit 6c0a39
static int ssh_bind_poll_callback(ssh_poll_handle sshpoll,
Packit 6c0a39
    socket_t fd, int revents, void *user){
Packit 6c0a39
  ssh_bind sshbind=(ssh_bind)user;
Packit 6c0a39
  (void)sshpoll;
Packit 6c0a39
  (void)fd;
Packit 6c0a39
Packit 6c0a39
  if(revents & POLLIN){
Packit 6c0a39
    /* new incoming connection */
Packit 6c0a39
    if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){
Packit 6c0a39
      sshbind->bind_callbacks->incoming_connection(sshbind,
Packit 6c0a39
          sshbind->bind_callbacks_userdata);
Packit 6c0a39
    }
Packit 6c0a39
  }
Packit 6c0a39
  return 0;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief returns the current poll handle, or create it
Packit 6c0a39
 * @param sshbind the ssh_bind object
Packit 6c0a39
 * @returns a ssh_poll handle suitable for operation
Packit 6c0a39
 */
Packit 6c0a39
ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind)
Packit 6c0a39
{
Packit 6c0a39
    short events = POLLIN;
Packit 6c0a39
Packit 6c0a39
    if (sshbind->poll) {
Packit 6c0a39
        return sshbind->poll;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
#ifdef POLLRDHUP
Packit 6c0a39
    events |= POLLRDHUP;
Packit 6c0a39
#endif /* POLLRDHUP */
Packit 6c0a39
Packit 6c0a39
    sshbind->poll = ssh_poll_new(sshbind->bindfd,
Packit 6c0a39
                                 events,
Packit 6c0a39
                                 ssh_bind_poll_callback,
Packit 6c0a39
                                 sshbind);
Packit 6c0a39
Packit 6c0a39
    return sshbind->poll;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
Packit 6c0a39
  sshbind->blocking = blocking ? 1 : 0;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
socket_t ssh_bind_get_fd(ssh_bind sshbind) {
Packit 6c0a39
  return sshbind->bindfd;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
Packit 6c0a39
  sshbind->bindfd = fd;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_bind_fd_toaccept(ssh_bind sshbind) {
Packit 6c0a39
  sshbind->toaccept = 1;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_bind_free(ssh_bind sshbind){
Packit 6c0a39
  int i;
Packit 6c0a39
Packit 6c0a39
  if (sshbind == NULL) {
Packit 6c0a39
    return;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  if (sshbind->bindfd >= 0) {
Packit 6c0a39
      CLOSE_SOCKET(sshbind->bindfd);
Packit 6c0a39
  }
Packit 6c0a39
  sshbind->bindfd = SSH_INVALID_SOCKET;
Packit 6c0a39
Packit 6c0a39
  /* options */
Packit 6c0a39
  SAFE_FREE(sshbind->banner);
Packit 6c0a39
  SAFE_FREE(sshbind->bindaddr);
Packit 6c0a39
  SAFE_FREE(sshbind->config_dir);
Packit 6c0a39
  SAFE_FREE(sshbind->pubkey_accepted_key_types);
Packit 6c0a39
Packit 6c0a39
  SAFE_FREE(sshbind->dsakey);
Packit 6c0a39
  SAFE_FREE(sshbind->rsakey);
Packit 6c0a39
  SAFE_FREE(sshbind->ecdsakey);
Packit 6c0a39
  SAFE_FREE(sshbind->ed25519key);
Packit 6c0a39
Packit 6c0a39
  ssh_key_free(sshbind->dsa);
Packit 6c0a39
  sshbind->dsa = NULL;
Packit 6c0a39
  ssh_key_free(sshbind->rsa);
Packit 6c0a39
  sshbind->rsa = NULL;
Packit 6c0a39
  ssh_key_free(sshbind->ecdsa);
Packit 6c0a39
  sshbind->ecdsa = NULL;
Packit 6c0a39
  ssh_key_free(sshbind->ed25519);
Packit 6c0a39
  sshbind->ed25519 = NULL;
Packit 6c0a39
Packit Service fcc0d2
  for (i = 0; i < SSH_KEX_METHODS; i++) {
Packit 6c0a39
    if (sshbind->wanted_methods[i]) {
Packit 6c0a39
      SAFE_FREE(sshbind->wanted_methods[i]);
Packit 6c0a39
    }
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  SAFE_FREE(sshbind);
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
Packit 6c0a39
    int i, rc;
Packit 6c0a39
Packit 6c0a39
    if (sshbind == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (session == NULL){
Packit 6c0a39
        ssh_set_error(sshbind, SSH_FATAL,"session is null");
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    /* Apply global bind configurations, if it hasn't been applied before */
Packit 6c0a39
    rc = ssh_bind_options_parse_config(sshbind, NULL);
Packit 6c0a39
    if (rc != 0) {
Packit 6c0a39
        ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config");
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    session->server = 1;
Packit 6c0a39
Packit 6c0a39
    /* Copy options from bind to session */
Packit Service fcc0d2
    for (i = 0; i < SSH_KEX_METHODS; i++) {
Packit 6c0a39
      if (sshbind->wanted_methods[i]) {
Packit 6c0a39
        session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
Packit 6c0a39
        if (session->opts.wanted_methods[i] == NULL) {
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
      }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (sshbind->bindaddr == NULL)
Packit 6c0a39
      session->opts.bindaddr = NULL;
Packit 6c0a39
    else {
Packit 6c0a39
      SAFE_FREE(session->opts.bindaddr);
Packit 6c0a39
      session->opts.bindaddr = strdup(sshbind->bindaddr);
Packit 6c0a39
      if (session->opts.bindaddr == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
      }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (sshbind->pubkey_accepted_key_types != NULL) {
Packit 6c0a39
        if (session->opts.pubkey_accepted_types == NULL) {
Packit 6c0a39
            session->opts.pubkey_accepted_types = strdup(sshbind->pubkey_accepted_key_types);
Packit 6c0a39
            if (session->opts.pubkey_accepted_types == NULL) {
Packit 6c0a39
                ssh_set_error_oom(sshbind);
Packit 6c0a39
                return SSH_ERROR;
Packit 6c0a39
            }
Packit 6c0a39
        } else {
Packit 6c0a39
            char *p;
Packit 6c0a39
            /* If something was set to the session prior to calling this
Packit 6c0a39
             * function, keep only what is allowed by the options set in
Packit 6c0a39
             * sshbind */
Packit 6c0a39
            p = ssh_find_all_matching(sshbind->pubkey_accepted_key_types,
Packit 6c0a39
                                      session->opts.pubkey_accepted_types);
Packit 6c0a39
            if (p == NULL) {
Packit 6c0a39
                return SSH_ERROR;
Packit 6c0a39
            }
Packit 6c0a39
Packit 6c0a39
            SAFE_FREE(session->opts.pubkey_accepted_types);
Packit 6c0a39
            session->opts.pubkey_accepted_types = p;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    session->common.log_verbosity = sshbind->common.log_verbosity;
Packit 6c0a39
    if(sshbind->banner != NULL)
Packit 6c0a39
    	session->opts.custombanner = strdup(sshbind->banner);
Packit 6c0a39
    ssh_socket_free(session->socket);
Packit 6c0a39
    session->socket = ssh_socket_new(session);
Packit 6c0a39
    if (session->socket == NULL) {
Packit 6c0a39
      /* perhaps it may be better to copy the error from session to sshbind */
Packit 6c0a39
      ssh_set_error_oom(sshbind);
Packit 6c0a39
      return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
    ssh_socket_set_fd(session->socket, fd);
Packit 6c0a39
    ssh_socket_get_poll_handle(session->socket);
Packit 6c0a39
Packit 6c0a39
    /* We must try to import any keys that could be imported in case
Packit 6c0a39
     * we are not using ssh_bind_listen (which is the other place
Packit 6c0a39
     * where keys can be imported) on this ssh_bind and are instead
Packit 6c0a39
     * only using ssh_bind_accept_fd to manage sockets ourselves.
Packit 6c0a39
     */
Packit 6c0a39
    if (sshbind->rsa == NULL &&
Packit 6c0a39
        sshbind->dsa == NULL &&
Packit 6c0a39
        sshbind->ecdsa == NULL &&
Packit 6c0a39
        sshbind->ed25519 == NULL) {
Packit 6c0a39
        rc = ssh_bind_import_keys(sshbind);
Packit 6c0a39
        if (rc != SSH_OK) {
Packit 6c0a39
            return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
#ifdef HAVE_ECC
Packit 6c0a39
    if (sshbind->ecdsa) {
Packit 6c0a39
        session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa);
Packit 6c0a39
        if (session->srv.ecdsa_key == NULL) {
Packit 6c0a39
          ssh_set_error_oom(sshbind);
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
#endif
Packit 6c0a39
#ifdef HAVE_DSA
Packit 6c0a39
    if (sshbind->dsa) {
Packit 6c0a39
        session->srv.dsa_key = ssh_key_dup(sshbind->dsa);
Packit 6c0a39
        if (session->srv.dsa_key == NULL) {
Packit 6c0a39
          ssh_set_error_oom(sshbind);
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
#endif
Packit 6c0a39
    if (sshbind->rsa) {
Packit 6c0a39
        session->srv.rsa_key = ssh_key_dup(sshbind->rsa);
Packit 6c0a39
        if (session->srv.rsa_key == NULL) {
Packit 6c0a39
          ssh_set_error_oom(sshbind);
Packit 6c0a39
          return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
    if (sshbind->ed25519 != NULL) {
Packit 6c0a39
        session->srv.ed25519_key = ssh_key_dup(sshbind->ed25519);
Packit 6c0a39
        if (session->srv.ed25519_key == NULL){
Packit 6c0a39
            ssh_set_error_oom(sshbind);
Packit 6c0a39
            return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    /* force PRNG to change state in case we fork after ssh_bind_accept */
Packit 6c0a39
    ssh_reseed();
Packit 6c0a39
    return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
Packit 6c0a39
  socket_t fd = SSH_INVALID_SOCKET;
Packit 6c0a39
  int rc;
Packit 6c0a39
  if (sshbind->bindfd == SSH_INVALID_SOCKET) {
Packit 6c0a39
    ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
        "Can't accept new clients on a not bound socket.");
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  if (session == NULL){
Packit 6c0a39
      ssh_set_error(sshbind, SSH_FATAL,"session is null");
Packit 6c0a39
      return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
Packit 6c0a39
  fd = accept(sshbind->bindfd, NULL, NULL);
Packit 6c0a39
  if (fd == SSH_INVALID_SOCKET) {
Packit 6c0a39
    ssh_set_error(sshbind, SSH_FATAL,
Packit 6c0a39
        "Accepting a new connection: %s",
Packit 6c0a39
        strerror(errno));
Packit 6c0a39
    return SSH_ERROR;
Packit 6c0a39
  }
Packit 6c0a39
  rc = ssh_bind_accept_fd(sshbind, session, fd);
Packit 6c0a39
Packit 6c0a39
  if(rc == SSH_ERROR){
Packit 6c0a39
      CLOSE_SOCKET(fd);
Packit 6c0a39
      ssh_socket_free(session->socket);
Packit 6c0a39
  }
Packit 6c0a39
  return rc;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
/**
Packit 6c0a39
 * @}
Packit 6c0a39
 */