Commit message: security: fix for vulnerability CVE-2014-0017

When accepting a new connection, a forking server based on libssh forks
and the child process handles the request. The RAND_bytes() function of
openssl doesn't reset its state after the fork, but simply adds the
current process id (getpid) to the PRNG state, which is not guaranteed
to be unique.
This can cause several children to end up with same PRNG state which is
a security issue.
CVE: CVE-2014-0017
CWE: CWE-310
Vulnerability description: The RAND_bytes function in libssh before 0.6.3, when forking is enabled, does not properly reset the state of the OpenSSL pseudo-random number generator (PRNG), which causes the state to be shared between children processes and allows local users to obtain sensitive information by leveraging a pid collision.

Project: libssh

static int blowfish_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV){
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }

    if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_BLOWFISH,
        GCRY_CIPHER_MODE_CBC, 0)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setkey(cipher->key[0], key, 16)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setiv(cipher->key[0], IV, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
  }

  return 0;
}

Project: libssh

static void blowfish_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

void ssh_bind_fd_toaccept(ssh_bind sshbind) {
  sshbind->toaccept = 1;
}

Project: libssh

static void aes_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
    unsigned long len) {
  gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

static const EVP_MD *nid_to_evpmd(int nid)
{
    switch (nid) {
        case NID_X9_62_prime256v1:
            return EVP_sha256();
        case NID_secp384r1:
            return EVP_sha384();
        case NID_secp521r1:
            return EVP_sha512();
        default:
            return NULL;
    }

    return NULL;
}

Project: libssh

static void aes_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
    unsigned long len) {
  AES_cbc_encrypt(in, out, len, cipher->key, cipher->IV, AES_DECRYPT);
}

Project: libssh

static void des1_1_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

static void des3_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  DES_ede3_cbc_encrypt(in, out, len, cipher->key,
      (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
      (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
      cipher->IV, 0);
}

Project: libssh

void hmac_update(HMACCTX ctx, const void *data, unsigned long len) {
  HMAC_Update(ctx, data, len);
}

Project: libssh

static void aes_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
    unsigned long len) {
  AES_cbc_encrypt(in, out, len, cipher->key, cipher->IV, AES_ENCRYPT);
}

Project: libssh

static void des3_1_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Encrypt IV before", cipher->IV, 24);
#endif
  DES_ncbc_encrypt(in, out, len, cipher->key, cipher->IV, 1);
  DES_ncbc_encrypt(out, in, len, (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
      (void*)((uint8_t*)cipher->IV + 8), 0);
  DES_ncbc_encrypt(in, out, len, (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
      (void*)((uint8_t*)cipher->IV + 16), 1);
#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Encrypt IV after", cipher->IV, 24);
#endif
}

Project: libssh

void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) {
  sshbind->bindfd = fd;
}

Project: libssh

EVPCTX evp_init(int nid)
{
    const EVP_MD *evp_md = nid_to_evpmd(nid);

    EVPCTX ctx = malloc(sizeof(EVP_MD_CTX));
    if (ctx == NULL) {
        return NULL;
    }

    EVP_DigestInit(ctx, evp_md);

    return ctx;
}

Project: libssh

void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len) {
  gcry_md_write(ctx->ctx,data,len);
}

Project: libssh

static socket_t bind_socket(ssh_bind sshbind, const char *hostname,
    int port) {
    char port_c[6];
    struct addrinfo *ai;
    struct addrinfo hints;
    int opt = 1;
    socket_t s;
    int rc;

    ZERO_STRUCT(hints);

    hints.ai_flags = AI_PASSIVE;
    hints.ai_socktype = SOCK_STREAM;

    snprintf(port_c, 6, "%d", port);
    rc = getaddrinfo(hostname, port_c, &hints, &ai);
    if (rc != 0) {
        ssh_set_error(sshbind,
                      SSH_FATAL,
                      "Resolving %s: %s", hostname, gai_strerror(rc));
        return -1;
    }

    s = socket (ai->ai_family,
                           ai->ai_socktype,
                           ai->ai_protocol);
    if (s == SSH_INVALID_SOCKET) {
        ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno));
        freeaddrinfo (ai);
        return -1;
    }

    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                   (char *)&opt, sizeof(opt)) < 0) {
        ssh_set_error(sshbind,
                      SSH_FATAL,
                      "Setting socket options failed: %s",
                      strerror(errno));
        freeaddrinfo (ai);
        close(s);
        return -1;
    }

    if (bind(s, ai->ai_addr, ai->ai_addrlen) != 0) {
        ssh_set_error(sshbind,
                      SSH_FATAL,
                      "Binding to %s:%d: %s",
                      hostname,
                      port,
                      strerror(errno));
        freeaddrinfo (ai);
        close(s);
        return -1;
    }

    freeaddrinfo (ai);
    return s;
}

Project: libssh

static void blowfish_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  BF_cbc_encrypt(in, out, len, cipher->key, cipher->IV, BF_DECRYPT);
}

Project: libssh

MD5CTX md5_init(void) {
  MD5CTX c = NULL;
  gcry_md_open(&c, GCRY_MD_MD5, 0);

  return c;
}

Project: libssh

static void blowfish_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

static int des3_1_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_DES,
          GCRY_CIPHER_MODE_CBC, 0)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setkey(cipher->key[0], key, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setiv(cipher->key[0], IV, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }

    if (gcry_cipher_open(&cipher->key[1], GCRY_CIPHER_DES,
          GCRY_CIPHER_MODE_CBC, 0)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setkey(cipher->key[1], (unsigned char *)key + 8, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setiv(cipher->key[1], (unsigned char *)IV + 8, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }

    if (gcry_cipher_open(&cipher->key[2], GCRY_CIPHER_DES,
          GCRY_CIPHER_MODE_CBC, 0)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setkey(cipher->key[2], (unsigned char *)key + 16, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setiv(cipher->key[2], (unsigned char *)IV + 16, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
  }

  return 0;
}

Project: libssh

void md5_final(unsigned char *md, MD5CTX c) {
  MD5_Final(md,c);
  SAFE_FREE(c);
}

Project: libssh

ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
  ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
  ctx->mac_type=type;
  switch(type){
    case SSH_MAC_SHA1:
      gcry_md_open(&ctx->ctx, GCRY_MD_SHA1, 0);
      break;
    case SSH_MAC_SHA256:
      gcry_md_open(&ctx->ctx, GCRY_MD_SHA256, 0);
      break;
    case SSH_MAC_SHA384:
      gcry_md_open(&ctx->ctx, GCRY_MD_SHA384, 0);
      break;
    case SSH_MAC_SHA512:
      gcry_md_open(&ctx->ctx, GCRY_MD_SHA512, 0);
      break;
    default:
      SAFE_FREE(ctx);
      return NULL;
  }
  return ctx;
}

Project: libssh

static void aes_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
    unsigned long len) {
  gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

static void des3_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  DES_ede3_cbc_encrypt(in, out, len, cipher->key,
      (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
      (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
      cipher->IV, 1);
}

Project: libssh

static void blowfish_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  BF_cbc_encrypt(in, out, len, cipher->key, cipher->IV, BF_ENCRYPT);
}

Project: libssh

static void des1_1_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
                           unsigned long len){

  DES_ncbc_encrypt(in, out, len, cipher->key, cipher->IV, 1);
}

Project: libssh

static int ssh_bind_import_keys(ssh_bind sshbind) {
  int rc;

  if (sshbind->ecdsakey == NULL &&
      sshbind->dsakey == NULL &&
      sshbind->rsakey == NULL) {
      ssh_set_error(sshbind, SSH_FATAL,
                    "ECDSA, DSA, or RSA host key file must be set");
      return SSH_ERROR;
  }

#ifdef HAVE_ECC
  if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) {
      rc = ssh_pki_import_privkey_file(sshbind->ecdsakey,
                                       NULL,
                                       NULL,
                                       NULL,
                                       &sshbind->ecdsa);
      if (rc == SSH_ERROR || rc == SSH_EOF) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "Failed to import private ECDSA host key");
          return SSH_ERROR;
      }

      if (ssh_key_type(sshbind->ecdsa) != SSH_KEYTYPE_ECDSA) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "The ECDSA host key has the wrong type");
          ssh_key_free(sshbind->ecdsa);
          sshbind->ecdsa = NULL;
          return SSH_ERROR;
      }
  }
#endif

  if (sshbind->dsa == NULL && sshbind->dsakey != NULL) {
      rc = ssh_pki_import_privkey_file(sshbind->dsakey,
                                       NULL,
                                       NULL,
                                       NULL,
                                       &sshbind->dsa);
      if (rc == SSH_ERROR || rc == SSH_EOF) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "Failed to import private DSA host key");
          return SSH_ERROR;
      }

      if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "The DSA host key has the wrong type: %d",
                  ssh_key_type(sshbind->dsa));
          ssh_key_free(sshbind->dsa);
          sshbind->dsa = NULL;
          return SSH_ERROR;
      }
  }

  if (sshbind->rsa == NULL && sshbind->rsakey != NULL) {
      rc = ssh_pki_import_privkey_file(sshbind->rsakey,
                                       NULL,
                                       NULL,
                                       NULL,
                                       &sshbind->rsa);
      if (rc == SSH_ERROR || rc == SSH_EOF) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "Failed to import private RSA host key");
          return SSH_ERROR;
      }

      if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA &&
          ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA1) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "The RSA host key has the wrong type");
          ssh_key_free(sshbind->rsa);
          sshbind->rsa = NULL;
          return SSH_ERROR;
      }
  }

  return SSH_OK;
}

Project: libssh

static void des1_1_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks,
    void *userdata){
  if (sshbind == NULL) {
    return SSH_ERROR;
  }
  if (callbacks == NULL) {
    ssh_set_error_invalid(sshbind);
    return SSH_ERROR;
  }
  if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){
    ssh_set_error(sshbind,SSH_FATAL,
        "Invalid callback passed in (badly initialized)");
    return SSH_ERROR;
  }
  sshbind->bind_callbacks = callbacks;
  sshbind->bind_callbacks_userdata=userdata;
  return 0;
}

Project: libssh

int ssh_bind_listen(ssh_bind sshbind) {
  const char *host;
  socket_t fd;
  int rc;

  if (ssh_init() < 0) {
    ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed");
    return -1;
  }

  rc = ssh_bind_import_keys(sshbind);
  if (rc != SSH_OK) {
    return SSH_ERROR;
  }

  if (sshbind->bindfd == SSH_INVALID_SOCKET) {
      host = sshbind->bindaddr;
      if (host == NULL) {
          host = "0.0.0.0";
      }

      fd = bind_socket(sshbind, host, sshbind->bindport);
      if (fd == SSH_INVALID_SOCKET) {
          ssh_key_free(sshbind->dsa);
          sshbind->dsa = NULL;
          ssh_key_free(sshbind->rsa);
          sshbind->rsa = NULL;
          return -1;
      }
      sshbind->bindfd = fd;

      if (listen(fd, 10) < 0) {
          ssh_set_error(sshbind, SSH_FATAL,
                  "Listening to socket %d: %s",
                  fd, strerror(errno));
          close(fd);
          ssh_key_free(sshbind->dsa);
          sshbind->dsa = NULL;
          ssh_key_free(sshbind->rsa);
          sshbind->rsa = NULL;
          return -1;
      }
  } else {
      SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket");
  }
  return 0;
}

Project: libssh

struct ssh_cipher_struct *ssh_get_ciphertab(void)
{
  return ssh_ciphertab;
}

Project: libssh

MD5CTX md5_init(void) {
  MD5CTX c = malloc(sizeof(*c));
  if (c == NULL) {
    return NULL;
  }

  MD5_Init(c);

  return c;
}

Project: libssh

static void des3_1_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
  gcry_cipher_decrypt(cipher->key[1], in, len, out, len);
  gcry_cipher_encrypt(cipher->key[2], out, len, in, len);
}

Project: libssh

void sha256(unsigned char *digest, int len, unsigned char *hash){
  gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len);
}

Project: libssh

SHA256CTX sha256_init(void){
  SHA256CTX c = malloc(sizeof(*c));
  if (c == NULL) {
    return NULL;
  }
  SHA256_Init(c);

  return c;
}

Project: libssh

static void des3_1_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_decrypt(cipher->key[2], out, len, in, len);
  gcry_cipher_encrypt(cipher->key[1], in, len, out, len);
  gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

socket_t ssh_bind_get_fd(ssh_bind sshbind) {
  return sshbind->bindfd;
}

Project: libssh

void md5_final(unsigned char *md, MD5CTX c) {
  gcry_md_final(c);
  memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN);
  gcry_md_close(c);
}

Project: libssh

ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind){
  if(sshbind->poll)
    return sshbind->poll;
  sshbind->poll=ssh_poll_new(sshbind->bindfd,POLLIN,
      ssh_bind_poll_callback,sshbind);
  return sshbind->poll;
}

Project: libssh

void sha1(unsigned char *digest, int len, unsigned char *hash) {
  SHA1(digest, len, hash);
}

Project: libssh

void hmac_update(HMACCTX c, const void *data, unsigned long len) {
  gcry_md_write(c, data, len);
}

Project: libssh

static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
  int mode=GCRY_CIPHER_MODE_CBC;
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if(strstr(cipher->name,"-ctr"))
      mode=GCRY_CIPHER_MODE_CTR;
    switch (cipher->keysize) {
      case 128:
        if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128,
              mode, 0)) {
          SAFE_FREE(cipher->key);
          return -1;
        }
        break;
      case 192:
        if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192,
              mode, 0)) {
          SAFE_FREE(cipher->key);
          return -1;
        }
        break;
      case 256:
        if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256,
              mode, 0)) {
          SAFE_FREE(cipher->key);
          return -1;
        }
        break;
    }
    if (gcry_cipher_setkey(cipher->key[0], key, cipher->keysize / 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if(mode == GCRY_CIPHER_MODE_CBC){
      if (gcry_cipher_setiv(cipher->key[0], IV, 16)) {

        SAFE_FREE(cipher->key);
        return -1;
      }
    } else {
      if(gcry_cipher_setctr(cipher->key[0],IV,16)){
        SAFE_FREE(cipher->key);
        return -1;
      }
    }
  }

  return 0;
}

Project: libssh

void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
{
    EVP_DigestFinal(ctx, md, mdlen);
}

Project: libssh

void sha256_update(SHA256CTX c, const void *data, unsigned long len){
  SHA256_Update(c,data,len);
}

Project: libssh

static int des3_set_key(struct ssh_cipher_struct *cipher, void *key,void *IV) {
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }

    DES_set_odd_parity(key);
    DES_set_odd_parity((void*)((uint8_t*)key + 8));
    DES_set_odd_parity((void*)((uint8_t*)key + 16));
    DES_set_key_unchecked(key, cipher->key);
    DES_set_key_unchecked((void*)((uint8_t*)key + 8), (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)));
    DES_set_key_unchecked((void*)((uint8_t*)key + 16), (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)));
  }
  cipher->IV=IV;
  return 0;
}

Project: libssh

void evp_update(EVPCTX ctx, const void *data, unsigned long len)
{
    EVP_DigestUpdate(ctx, data, len);
}

Project: libssh

static int des1_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV){
  if(!cipher->key){
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_DES,
          GCRY_CIPHER_MODE_CBC, 0)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setkey(cipher->key[0], key, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setiv(cipher->key[0], IV, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
  }
  return 0;
}

Project: libssh

void md5_update(MD5CTX c, const void *data, unsigned long len) {
  MD5_Update(c, data, len);
}

Project: libssh

ssh_bind ssh_bind_new(void) {
  ssh_bind ptr;

  ptr = malloc(sizeof(struct ssh_bind_struct));
  if (ptr == NULL) {
    return NULL;
  }
  ZERO_STRUCTP(ptr);
  ptr->bindfd = SSH_INVALID_SOCKET;
  ptr->bindport= 22;
  ptr->common.log_verbosity = 0;

  return ptr;
}

Project: libssh

void sha256(unsigned char *digest, int len, unsigned char *hash) {
  SHA256(digest, len, hash);
}

Project: libssh

static void aes_ctr128_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
    unsigned long len) {
  unsigned char tmp_buffer[128/8];
  unsigned int num=0;
  /* Some things are special with ctr128 :
   * In this case, tmp_buffer is not being used, because it is used to store temporary data
   * when an encryption is made on lengths that are not multiple of blocksize.
   * Same for num, which is being used to store the current offset in blocksize in CTR
   * function.
   */
  AES_ctr128_encrypt(in, out, len, cipher->key, cipher->IV, tmp_buffer, &num);
}

Project: libssh

void ssh_reseed(void){
    struct timeval tv;
    gettimeofday(&tv, NULL);
    RAND_add(&tv, sizeof(tv), 0.0);
}

Project: libssh

void ssh_reseed(void){
	}

Project: libssh

int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){
    int i, rc;

    if (session == NULL){
        ssh_set_error(sshbind, SSH_FATAL,"session is null");
        return SSH_ERROR;
    }

    session->server = 1;
    session->version = 2;

    /* copy options */
    for (i = 0; i < 10; ++i) {
      if (sshbind->wanted_methods[i]) {
        session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]);
        if (session->opts.wanted_methods[i] == NULL) {
          return SSH_ERROR;
        }
      }
    }

    if (sshbind->bindaddr == NULL)
      session->opts.bindaddr = NULL;
    else {
      SAFE_FREE(session->opts.bindaddr);
      session->opts.bindaddr = strdup(sshbind->bindaddr);
      if (session->opts.bindaddr == NULL) {
        return SSH_ERROR;
      }
    }

    session->common.log_verbosity = sshbind->common.log_verbosity;
    if(sshbind->banner != NULL)
    	session->opts.custombanner = strdup(sshbind->banner);
    ssh_socket_free(session->socket);
    session->socket = ssh_socket_new(session);
    if (session->socket == NULL) {
      /* perhaps it may be better to copy the error from session to sshbind */
      ssh_set_error_oom(sshbind);
      return SSH_ERROR;
    }
    ssh_socket_set_fd(session->socket, fd);
    ssh_socket_get_poll_handle_out(session->socket);

    /* We must try to import any keys that could be imported in case
     * we are not using ssh_bind_listen (which is the other place
     * where keys can be imported) on this ssh_bind and are instead
     * only using ssh_bind_accept_fd to manage sockets ourselves.
     */
    rc = ssh_bind_import_keys(sshbind);
    if (rc != SSH_OK) {
      return SSH_ERROR;
    }

#ifdef HAVE_ECC
    if (sshbind->ecdsa) {
        session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa);
        if (session->srv.ecdsa_key == NULL) {
          ssh_set_error_oom(sshbind);
          return SSH_ERROR;
        }
    }
#endif
    if (sshbind->dsa) {
        session->srv.dsa_key = ssh_key_dup(sshbind->dsa);
        if (session->srv.dsa_key == NULL) {
          ssh_set_error_oom(sshbind);
          return SSH_ERROR;
        }
    }
    if (sshbind->rsa) {
        session->srv.rsa_key = ssh_key_dup(sshbind->rsa);
        if (session->srv.rsa_key == NULL) {
          ssh_set_error_oom(sshbind);
          return SSH_ERROR;
        }
    }
    /* force PRNG to change state in case we fork after ssh_bind_accept */
    ssh_reseed();
    return SSH_OK;
}

Project: libssh

HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
  HMACCTX c = NULL;

  switch(type) {
    case SSH_HMAC_SHA1:
      gcry_md_open(&c, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
      break;
    case SSH_HMAC_MD5:
      gcry_md_open(&c, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
      break;
    default:
      c = NULL;
  }

  gcry_md_setkey(c, key, len);

  return c;
}

Project: libssh

int ssh_bind_accept(ssh_bind sshbind, ssh_session session) {
  socket_t fd = SSH_INVALID_SOCKET;
  int rc;
  if (sshbind->bindfd == SSH_INVALID_SOCKET) {
    ssh_set_error(sshbind, SSH_FATAL,
        "Can't accept new clients on a not bound socket.");
    return SSH_ERROR;
  }

  if (session == NULL){
      ssh_set_error(sshbind, SSH_FATAL,"session is null");
      return SSH_ERROR;
  }

  fd = accept(sshbind->bindfd, NULL, NULL);
  if (fd == SSH_INVALID_SOCKET) {
    ssh_set_error(sshbind, SSH_FATAL,
        "Accepting a new connection: %s",
        strerror(errno));
    return SSH_ERROR;
  }
  rc = ssh_bind_accept_fd(sshbind, session, fd);

  if(rc == SSH_ERROR){
#ifdef _WIN32
      closesocket(fd);
#else
      close(fd);
#endif
      ssh_socket_free(session->socket);
  }
  return rc;
}

Project: libssh

static int des3_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) {
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_3DES,
          GCRY_CIPHER_MODE_CBC, 0)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setkey(cipher->key[0], key, 24)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
    if (gcry_cipher_setiv(cipher->key[0], IV, 8)) {
      SAFE_FREE(cipher->key);
      return -1;
    }
  }

  return 0;
}

Project: libssh

void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
  size_t len;
  switch(ctx->mac_type){
    case SSH_MAC_SHA1:
      len=SHA_DIGEST_LEN;
      break;
    case SSH_MAC_SHA256:
      len=SHA256_DIGEST_LENGTH;
      break;
    case SSH_MAC_SHA384:
      len=SHA384_DIGEST_LENGTH;
      break;
    case SSH_MAC_SHA512:
      len=SHA512_DIGEST_LENGTH;
      break;
  }
  gcry_md_final(ctx->ctx);
  memcpy(md, gcry_md_read(ctx->ctx, 0), len);
  gcry_md_close(ctx->ctx);
  SAFE_FREE(ctx);
}

Project: libssh

static void des1_1_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
                           unsigned long len){

  DES_ncbc_encrypt(in,out,len, cipher->key, cipher->IV, 0);
}

Project: libssh

void sha1_final(unsigned char *md, SHACTX c) {
  gcry_md_final(c);
  memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN);
  gcry_md_close(c);
}

Project: libssh

static int des1_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV){
  if(!cipher->key){
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    DES_set_odd_parity(key);
    DES_set_key_unchecked(key,cipher->key);
  }
  cipher->IV=IV;
  return 0;
}

Project: libssh

static void des3_1_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Decrypt IV before", cipher->IV, 24);
#endif

  DES_ncbc_encrypt(in, out, len, (void*)((uint8_t*)cipher->key + 2 * sizeof(DES_key_schedule)),
      cipher->IV, 0);
  DES_ncbc_encrypt(out, in, len, (void*)((uint8_t*)cipher->key + sizeof(DES_key_schedule)),
      (void*)((uint8_t*)cipher->IV + 8), 1);
  DES_ncbc_encrypt(in, out, len, cipher->key, (void*)((uint8_t*)cipher->IV + 16), 0);

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Decrypt IV after", cipher->IV, 24);
#endif
}

Project: libssh

void sha256_final(unsigned char *md, SHA256CTX c) {
  SHA256_Final(md, c);
  SAFE_FREE(c);
}

Project: libssh

ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
  ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
  ctx->mac_type=type;
  switch(type){
    case SSH_MAC_SHA1:
      ctx->ctx.sha1_ctx = sha1_init();
      return ctx;
    case SSH_MAC_SHA256:
      ctx->ctx.sha256_ctx = sha256_init();
      return ctx;
    case SSH_MAC_SHA384:
    case SSH_MAC_SHA512:
    default:
      SAFE_FREE(ctx);
      return NULL;
  }
}

Project: libssh

static int blowfish_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV){
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    BF_set_key(cipher->key, 16, key);
  }
  cipher->IV = IV;
  return 0;
}

Project: libssh

void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) {
  HMAC_Final(ctx,hashmacbuf,len);

#ifndef OLD_CRYPTO
  HMAC_CTX_cleanup(ctx);
#else
  HMAC_cleanup(ctx);
#endif

  SAFE_FREE(ctx);
}

Project: libssh

SHACTX sha1_init(void) {
  SHACTX ctx = NULL;
  gcry_md_open(&ctx, GCRY_MD_SHA1, 0);

  return ctx;
}

Project: libssh

void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) {
  sshbind->blocking = blocking ? 1 : 0;
}

Project: libssh

void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen)
{
    const EVP_MD *evp_md = nid_to_evpmd(nid);
    EVP_MD_CTX md;

    EVP_DigestInit(&md, evp_md);
    EVP_DigestUpdate(&md, digest, len);
    EVP_DigestFinal(&md, hash, hlen);
}

Project: libssh

void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
  switch(ctx->mac_type){
    case SSH_MAC_SHA1:
      sha1_final(md,ctx->ctx.sha1_ctx);
      break;
    case SSH_MAC_SHA256:
      sha256_final(md,ctx->ctx.sha256_ctx);
      break;
    case SSH_MAC_SHA384:
    case SSH_MAC_SHA512:
    default:
      break;
  }
  SAFE_FREE(ctx);
}

Project: libssh

void sha1_update(SHACTX c, const void *data, unsigned long len) {
  gcry_md_write(c, data, len);
}

Project: libssh

void sha1_update(SHACTX c, const void *data, unsigned long len) {
  SHA1_Update(c,data,len);
}

Project: libssh

void md5_update(MD5CTX c, const void *data, unsigned long len) {
    gcry_md_write(c,data,len);
}

Project: libssh

void sha1(unsigned char *digest, int len, unsigned char *hash) {
  gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len);
}

Project: libssh

static void des3_decrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_decrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

static void des3_encrypt(struct ssh_cipher_struct *cipher, void *in,
    void *out, unsigned long len) {
  gcry_cipher_encrypt(cipher->key[0], out, len, in, len);
}

Project: libssh

void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len) {
  switch(ctx->mac_type){
    case SSH_MAC_SHA1:
      sha1_update(ctx->ctx.sha1_ctx, data, len);
      break;
    case SSH_MAC_SHA256:
      sha256_update(ctx->ctx.sha256_ctx, data, len);
      break;
    case SSH_MAC_SHA384:
    case SSH_MAC_SHA512:
    default:
      break;
  }
}

Project: libssh

HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
  HMACCTX ctx = NULL;

  ctx = malloc(sizeof(*ctx));
  if (ctx == NULL) {
    return NULL;
  }

#ifndef OLD_CRYPTO
  HMAC_CTX_init(ctx); // openssl 0.9.7 requires it.
#endif

  switch(type) {
    case SSH_HMAC_SHA1:
      HMAC_Init(ctx, key, len, EVP_sha1());
      break;
    case SSH_HMAC_MD5:
      HMAC_Init(ctx, key, len, EVP_md5());
      break;
    default:
      SAFE_FREE(ctx);
      ctx = NULL;
  }

  return ctx;
}

Project: libssh

static int aes_set_decrypt_key(struct ssh_cipher_struct *cipher, void *key,
    void *IV) {
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if (AES_set_decrypt_key(key,cipher->keysize,cipher->key) < 0) {
      SAFE_FREE(cipher->key);
      return -1;
    }
  }
  cipher->IV=IV;
  return 0;
}

Project: libssh

SHACTX sha1_init(void) {
  SHACTX c = malloc(sizeof(*c));
  if (c == NULL) {
    return NULL;
  }
  SHA1_Init(c);

  return c;
}

Project: libssh

static int alloc_key(struct ssh_cipher_struct *cipher) {
    cipher->key = malloc(cipher->keylen);
    if (cipher->key == NULL) {
      return -1;
    }

    return 0;
}

Project: libssh

static int aes_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key,
    void *IV) {
  if (cipher->key == NULL) {
    if (alloc_key(cipher) < 0) {
      return -1;
    }
    if (AES_set_encrypt_key(key,cipher->keysize,cipher->key) < 0) {
      SAFE_FREE(cipher->key);
      return -1;
    }
  }
  cipher->IV=IV;
  return 0;
}

Project: libssh

static int ssh_bind_poll_callback(ssh_poll_handle sshpoll,
    socket_t fd, int revents, void *user){
  ssh_bind sshbind=(ssh_bind)user;
  (void)sshpoll;
  (void)fd;

  if(revents & POLLIN){
    /* new incoming connection */
    if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){
      sshbind->bind_callbacks->incoming_connection(sshbind,
          sshbind->bind_callbacks_userdata);
    }
  }
  return 0;
}

Project: libssh

void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) {
  *len = gcry_md_get_algo_dlen(gcry_md_get_algo(c));
  memcpy(hashmacbuf, gcry_md_read(c, 0), *len);
  gcry_md_close(c);
}

Project: libssh

void sha1_final(unsigned char *md, SHACTX c) {
  SHA1_Final(md, c);
  SAFE_FREE(c);
}

Project: libssh

void ssh_bind_free(ssh_bind sshbind){
  int i;

  if (sshbind == NULL) {
    return;
  }

  if (sshbind->bindfd >= 0) {
#ifdef _WIN32
    closesocket(sshbind->bindfd);
#else
    close(sshbind->bindfd);
#endif
  }
  sshbind->bindfd = SSH_INVALID_SOCKET;

  /* options */
  SAFE_FREE(sshbind->banner);
  SAFE_FREE(sshbind->bindaddr);

  SAFE_FREE(sshbind->dsakey);
  SAFE_FREE(sshbind->rsakey);
  SAFE_FREE(sshbind->ecdsakey);

  ssh_key_free(sshbind->dsa);
  sshbind->dsa = NULL;
  ssh_key_free(sshbind->rsa);
  sshbind->rsa = NULL;
  ssh_key_free(sshbind->ecdsa);
  sshbind->ecdsa = NULL;

  for (i = 0; i < 10; i++) {
    if (sshbind->wanted_methods[i]) {
      SAFE_FREE(sshbind->wanted_methods[i]);
    }
  }

  SAFE_FREE(sshbind);
}