예제 #1
0
STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *svrkey,
        PUBLIC_KEY *hostkey,int slen, int hlen ){
    unsigned char buffer[32];
    int i;
    STRING *data1,*data2;
    /* first, generate a session key */
    
    ssh_get_random(session->next_crypto->encryptkey,32,1);
    memcpy(buffer,session->next_crypto->encryptkey,32);
    memcpy(session->next_crypto->decryptkey,
            session->next_crypto->encryptkey,32);
#ifdef DEBUG_CRYPTO
    ssh_print_hexa("session key",buffer,32);
#endif
    /* xor session key with session_id */
    for (i=0;i<16;++i)
        buffer[i]^=session->next_crypto->session_id[i];
    data1=string_new(32);
    string_fill(data1,buffer,32);
    if(ABS(hlen-slen)<128){
        ssh_say(1,"Difference between server modulus and host modulus is only %d. It's illegal and may not work\n",
                ABS(hlen-slen));
    }
    if(modulus_smaller(svrkey,hostkey)){
        data2=ssh_encrypt_rsa1(session,data1,svrkey);
        free(data1);
        data1=ssh_encrypt_rsa1(session,data2,hostkey);
    } else {
        data2=ssh_encrypt_rsa1(session,data1,hostkey);
        free(data1);
        data1=ssh_encrypt_rsa1(session,data2,svrkey);
    }
    return data1;
}
예제 #2
0
/** @internal
 * @brief Starts [email protected] key exchange
 */
int ssh_client_curve25519_init(ssh_session_t * session){
  ssh_string_t * client_pubkey;
  int rc;

  rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT);
  if (rc < 0) {
      return SSH_ERROR;
  }

  rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
  if (rc == 0){
	  ssh_set_error(session, SSH_FATAL, "PRNG error");
	  return SSH_ERROR;
  }

  crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
		  session->next_crypto->curve25519_privkey);
  client_pubkey = ssh_string_new(CURVE25519_PUBKEY_SIZE);
  if (client_pubkey == NULL) {
      return SSH_ERROR;
  }
  ssh_string_fill(client_pubkey, session->next_crypto->curve25519_client_pubkey,
		  CURVE25519_PUBKEY_SIZE);
  rc = buffer_add_ssh_string(session->out_buffer,client_pubkey);
  ssh_string_free(client_pubkey);
  if (rc < 0) {
      return SSH_ERROR;
  }

  rc = packet_send(session);

  return rc;
}
예제 #3
0
int server_set_kex(SSH_SESSION * session) {
    KEX *server = &session->server_kex;
    SSH_OPTIONS *options = session->options;
    int i;
    char *wanted;
    memset(server,0,sizeof(KEX));
    // the program might ask for a specific cookie to be sent. useful for server
    //   debugging
    if (options->wanted_cookie)
        memcpy(server->cookie, options->wanted_cookie, 16);
    else
        ssh_get_random(server->cookie, 16,0);
    if(session->dsa_key && session->rsa_key){
        ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-dss,ssh-rsa");
    } else {
        if(session->dsa_key)
            ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-dss");
        else
            ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-rsa");
    }
    server->methods = malloc(10 * sizeof(char **));
    for (i = 0; i < 10; i++) {
        if (!(wanted = options->wanted_methods[i]))
            wanted = supported_methods[i];
        server->methods[i] = strdup(wanted);
        //printf("server->methods[%d]=%s\n",i,wanted);
    }
    return 0;
}
예제 #4
0
int set_kex(SSH_SESSION *session){
    KEX *server = &session->server_kex;
    KEX *client=&session->client_kex;
    SSH_OPTIONS *options=session->options;
    int i;
    char *wanted;
    /* the client might ask for a specific cookie to be sent. useful for server debugging */
    if(options->wanted_cookie)
        memcpy(client->cookie,options->wanted_cookie,16);
    else
        ssh_get_random(client->cookie,16,0);
    client->methods=malloc(10 * sizeof(char **));
    memset(client->methods,0,10*sizeof(char **));
    for (i=0;i<10;i++){
        if(!(wanted=options->wanted_methods[i]))
            wanted=default_methods[i];
        client->methods[i]=ssh_find_matching(server->methods[i],wanted);
        if(!client->methods[i] && i < SSH_LANG_C_S){
            ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s",
            wanted,server->methods[i],ssh_kex_nums[i]);
            return -1;
        } else {
            if(i>=SSH_LANG_C_S && !client->methods[i])
                client->methods[i]=strdup(""); // we can safely do that for languages
        }
    }
    return 0;
}
예제 #5
0
파일: kex.c 프로젝트: simonsj/libssh
/**
 * @brief sets the key exchange parameters to be sent to the server,
 *        in function of the options and available methods.
 */
int ssh_set_client_kex(ssh_session session)
{
    struct ssh_kex_struct *client= &session->next_crypto->client_kex;
    const char *wanted;
    char *kex = NULL;
    char *kex_tmp = NULL;
    int ok;
    int i;
    size_t kex_len, len;

    ok = ssh_get_random(client->cookie, 16, 0);
    if (!ok) {
        ssh_set_error(session, SSH_FATAL, "PRNG error");
        return SSH_ERROR;
    }

    memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
    /* first check if we have specific host key methods */
    if (session->opts.wanted_methods[SSH_HOSTKEYS] == NULL) {
    	/* Only if no override */
    	session->opts.wanted_methods[SSH_HOSTKEYS] =
            ssh_client_select_hostkeys(session);
    }

    for (i = 0; i < KEX_METHODS_SIZE; i++) {
        wanted = session->opts.wanted_methods[i];
        if (wanted == NULL)
            wanted = default_methods[i];
        client->methods[i] = strdup(wanted);
        if (client->methods[i] == NULL) {
            ssh_set_error_oom(session);
            return SSH_ERROR;
        }
    }

    /* For rekeying, skip the extension negotiation */
    if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) {
        return SSH_OK;
    }

    /* Here we append  ext-info-c  to the list of kex algorithms */
    kex = client->methods[SSH_KEX];
    len = strlen(kex);
    if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) {
        /* Overflow */
        return SSH_ERROR;
    }
    kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */
    kex_tmp = realloc(kex, kex_len);
    if (kex_tmp == NULL) {
        free(kex);
        ssh_set_error_oom(session);
        return SSH_ERROR;
    }
    snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT);
    client->methods[SSH_KEX] = kex_tmp;

    return SSH_OK;
}
예제 #6
0
파일: server.c 프로젝트: alejom200/tmate
static int server_set_kex(ssh_session session) {
  struct ssh_kex_struct *server = &session->next_crypto->server_kex;
  int i, j, rc;
  const char *wanted;
  char hostkeys[64] = {0};
  enum ssh_keytypes_e keytype;
  size_t len;

  ZERO_STRUCTP(server);
  ssh_get_random(server->cookie, 16, 0);

#ifdef HAVE_ECC
  if (session->srv.ecdsa_key != NULL) {
      snprintf(hostkeys, sizeof(hostkeys),
               "%s", session->srv.ecdsa_key->type_c);
  }
#endif
  if (session->srv.dsa_key != NULL) {
      len = strlen(hostkeys);
      keytype = ssh_key_type(session->srv.dsa_key);

      snprintf(hostkeys + len, sizeof(hostkeys) - len,
               ",%s", ssh_key_type_to_char(keytype));
  }
  if (session->srv.rsa_key != NULL) {
      len = strlen(hostkeys);
      keytype = ssh_key_type(session->srv.rsa_key);

      snprintf(hostkeys + len, sizeof(hostkeys) - len,
               ",%s", ssh_key_type_to_char(keytype));
  }

  if (strlen(hostkeys) == 0) {
      return -1;
  }

  rc = ssh_options_set_algo(session,
                            SSH_HOSTKEYS,
                            hostkeys[0] == ',' ? hostkeys + 1 : hostkeys);
  if (rc < 0) {
      return -1;
  }

  for (i = 0; i < 10; i++) {
    if ((wanted = session->opts.wanted_methods[i]) == NULL) {
      wanted = ssh_kex_get_supported_method(i);
    }
    server->methods[i] = strdup(wanted);
    if (server->methods[i] == NULL) {
      for (j = 0; j < i; j++) {
        SAFE_FREE(server->methods[j]);
      }
      return -1;
    }
  }

  return 0;
}
예제 #7
0
static int server_set_kex(SSH_SESSION * session) {
  KEX *server = &session->server_kex;
  SSH_OPTIONS *options = session->options;
  int i, j;
  char *wanted;

  ZERO_STRUCTP(server);
  /*
   * The program might ask for a specific cookie to be sent. Useful for server
   * debugging
   */
  if (options->wanted_cookie) {
    memcpy(server->cookie, options->wanted_cookie, 16);
  } else {
    ssh_get_random(server->cookie, 16, 0);
  }

  if (session->dsa_key != NULL && session->rsa_key != NULL) {
    if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS,
          "ssh-dss,ssh-rsa") < 0) {
      return -1;
    }
  } else if (session->dsa_key != NULL) {
    if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-dss") < 0) {
      return -1;
    }
  } else {
    if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-rsa") < 0) {
      return -1;
    }
  }

  server->methods = malloc(10 * sizeof(char **));
  if (server->methods == NULL) {
    return -1;
  }

  for (i = 0; i < 10; i++) {
    if ((wanted = options->wanted_methods[i]) == NULL) {
      wanted = supported_methods[i];
    }
    server->methods[i] = strdup(wanted);
    if (server->methods[i] == NULL) {
      for (j = i - 1; j <= 0; j--) {
        SAFE_FREE(server->methods[j]);
      }
      SAFE_FREE(server->methods);
      return -1;
    }
  }

  return 0;
}
예제 #8
0
파일: kex.c 프로젝트: MarvinZhuang/tmate
/**
 * @brief sets the key exchange parameters to be sent to the server,
 *        in function of the options and available methods.
 */
int set_client_kex(ssh_session session){
    struct ssh_kex_struct *client= &session->next_crypto->client_kex;
    const char *wanted;
    int i;

    ssh_get_random(client->cookie, 16, 0);

    memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
    for (i = 0; i < KEX_METHODS_SIZE; i++) {
        wanted = session->opts.wanted_methods[i];
        if (wanted == NULL)
            wanted = default_methods[i];
        client->methods[i] = strdup(wanted);
    }

    return SSH_OK;
}
예제 #9
0
파일: server.c 프로젝트: imeckler/Watch
static int server_set_kex(ssh_session session) {
  KEX *server = &session->server_kex;
  int i, j;
  char *wanted;

  ZERO_STRUCTP(server);
  ssh_get_random(server->cookie, 16, 0);
  if (session->dsa_key != NULL && session->rsa_key != NULL) {
    if (ssh_options_set_algo(session, SSH_HOSTKEYS,
          "ssh-dss,ssh-rsa") < 0) {
      return -1;
    }
  } else if (session->dsa_key != NULL) {
    if (ssh_options_set_algo(session, SSH_HOSTKEYS, "ssh-dss") < 0) {
      return -1;
    }
  } else {
    if (ssh_options_set_algo(session, SSH_HOSTKEYS, "ssh-rsa") < 0) {
      return -1;
    }
  }

  server->methods = (char **) malloc(10 * sizeof(char **));
  if (server->methods == NULL) {
    return -1;
  }

  for (i = 0; i < 10; i++) {
    if ((wanted = session->wanted_methods[i]) == NULL) {
      wanted = supported_methods[i];
    }
    server->methods[i] = strdup(wanted);
    if (server->methods[i] == NULL) {
      for (j = i - 1; j <= 0; j--) {
        SAFE_FREE(server->methods[j]);
      }
      SAFE_FREE(server->methods);
      return -1;
    }
  }

  return 0;
}
예제 #10
0
파일: kex.c 프로젝트: caidongyun/libssh
/**
 * @brief sets the key exchange parameters to be sent to the server,
 *        in function of the options and available methods.
 */
int ssh_set_client_kex(ssh_session session){
    struct ssh_kex_struct *client= &session->next_crypto->client_kex;
    const char *wanted;
    int i;

    ssh_get_random(client->cookie, 16, 0);

    memset(client->methods, 0, KEX_METHODS_SIZE * sizeof(char **));
    /* first check if we have specific host key methods */
    if(session->opts.wanted_methods[SSH_HOSTKEYS] == NULL){
    	/* Only if no override */
    	session->opts.wanted_methods[SSH_HOSTKEYS] =
    			ssh_client_select_hostkeys(session);
    }

    for (i = 0; i < KEX_METHODS_SIZE; i++) {
        wanted = session->opts.wanted_methods[i];
        if (wanted == NULL)
            wanted = default_methods[i];
        client->methods[i] = strdup(wanted);
    }

    return SSH_OK;
}
예제 #11
0
파일: kex.c 프로젝트: caidongyun/nullfxp
int set_kex(ssh_session session){
    KEX *server = &session->server_kex;
    KEX *client=&session->client_kex;
    int i;
    const char *wanted;
    enter_function();
    ssh_get_random(client->cookie,16,0);
    client->methods=malloc(10 * sizeof(char **));
    if (client->methods == NULL) {
      ssh_set_error(session, SSH_FATAL, "No space left");
      leave_function();
      return -1;
    }
    memset(client->methods,0,10*sizeof(char **));
    for (i=0;i<10;i++){
        if(!(wanted=session->wanted_methods[i]))
            wanted=default_methods[i];
        client->methods[i]=ssh_find_matching(server->methods[i],wanted);
        if(!client->methods[i] && i < SSH_LANG_C_S){
            ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s",
            wanted,server->methods[i],ssh_kex_nums[i]);
            leave_function();
            return -1;
        } else {
          if ((i >= SSH_LANG_C_S) && (client->methods[i] == NULL)) {
            /* we can safely do that for languages */
            client->methods[i] = strdup("");
            if (client->methods[i] == NULL) {
              return -1;
            }
          }
        }
    }
    leave_function();
    return 0;
}
예제 #12
0
파일: packet.c 프로젝트: Paxxi/libssh
static int packet_send2(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  unsigned int lenfield_blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->lenfield_blocksize : 0);
  enum ssh_hmac_e hmac_type = (session->current_crypto ?
      session->current_crypto->out_hmac : session->next_crypto->out_hmac);
  uint32_t currentlen = ssh_buffer_get_len(session->out_buffer);
  unsigned char *hmac = NULL;
  char padstring[32] = { 0 };
  int rc = SSH_ERROR;
  uint32_t finallen,payloadsize,compsize;
  uint8_t padding;
  ssh_buffer header_buffer = ssh_buffer_new();

  payloadsize = currentlen;
#ifdef WITH_ZLIB
  if (session->current_crypto
      && session->current_crypto->do_compress_out
      && ssh_buffer_get_len(session->out_buffer)) {
    if (compress_buffer(session,session->out_buffer) < 0) {
      goto error;
    }
    currentlen = ssh_buffer_get_len(session->out_buffer);
  }
#endif /* WITH_ZLIB */
  compsize = currentlen;
  /* compressed payload + packet len (4) + padding len (1) */
  /* totallen - lenfield_blocksize must be equal to 0 (mod blocksize) */
  padding = (blocksize - ((blocksize - lenfield_blocksize + currentlen + 5) % blocksize));
  if(padding < 4) {
    padding += blocksize;
  }

  if (session->current_crypto != NULL) {
      int ok;

      ok = ssh_get_random(padstring, padding, 0);
      if (!ok) {
          ssh_set_error(session, SSH_FATAL, "PRNG error");
          goto error;
      }
  }

  if (header_buffer == NULL){
    ssh_set_error_oom(session);
    goto error;
  }
  finallen = currentlen + padding + 1;
  rc = ssh_buffer_pack(header_buffer, "db", finallen, padding);
  if (rc == SSH_ERROR){
    goto error;
  }

  rc = ssh_buffer_prepend_data(session->out_buffer,
                               ssh_buffer_get(header_buffer),
                               ssh_buffer_get_len(header_buffer));
  if (rc < 0) {
    goto error;
  }
  rc = ssh_buffer_add_data(session->out_buffer, padstring, padding);
  if (rc < 0) {
    goto error;
  }
#ifdef WITH_PCAP
  if (session->pcap_ctx) {
      ssh_pcap_context_write(session->pcap_ctx,
                             SSH_PCAP_DIR_OUT,
                             ssh_buffer_get(session->out_buffer),
                             ssh_buffer_get_len(session->out_buffer),
                             ssh_buffer_get_len(session->out_buffer));
  }
#endif
  hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
  if (hmac) {
    rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type));
    if (rc < 0) {
      goto error;
    }
  }

  rc = ssh_packet_write(session);
  session->send_seq++;
  if (session->raw_counter != NULL) {
      session->raw_counter->out_bytes += payloadsize;
      session->raw_counter->out_packets++;
  }

  SSH_LOG(SSH_LOG_PACKET,
          "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]",
          finallen, padding, compsize, payloadsize);
  if (ssh_buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:
  if (header_buffer != NULL) {
      ssh_buffer_free(header_buffer);
  }
  return rc; /* SSH_OK, AGAIN or ERROR */
}
예제 #13
0
파일: packet1.c 프로젝트: caidongyun/libssh
int ssh_packet_send1(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  uint32_t currentlen = ssh_buffer_get_len(session->out_buffer) + sizeof(uint32_t);
  char padstring[32] = {0};
  int rc = SSH_ERROR;
  uint32_t finallen;
  uint32_t crc;
  uint8_t padding;

  SSH_LOG(SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen);

/* TODO FIXME
#ifdef WITH_ZLIB
  if (session->current_crypto && session->current_crypto->do_compress_out) {
    if (compress_buffer(session, session->out_buffer) < 0) {
      goto error;
    }
    currentlen = ssh_buffer_get_len(session->out_buffer);
  }
#endif
*/
  padding = blocksize - (currentlen % blocksize);
  if (session->current_crypto) {
    ssh_get_random(padstring, padding, 0);
  } else {
    memset(padstring, 0, padding);
  }

  finallen = htonl(currentlen);
  SSH_LOG(SSH_LOG_PACKET,
      "%d bytes after comp + %d padding bytes = %d bytes packet",
      currentlen, padding, ntohl(finallen));

  if (ssh_buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) {
    goto error;
  }
  if (ssh_buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
    goto error;
  }

  crc = ssh_crc32((char *)ssh_buffer_get(session->out_buffer) + sizeof(uint32_t),
      ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t));

  if (ssh_buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) {
    goto error;
  }

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Clear packet", ssh_buffer_get(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
#endif

  /* session->out_buffer should have more than sizeof(uint32_t) bytes
     in it as required for ssh_packet_encrypt */
  ssh_packet_encrypt(session, (unsigned char *)ssh_buffer_get(session->out_buffer) + sizeof(uint32_t),
      ssh_buffer_get_len(session->out_buffer) - sizeof(uint32_t));

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("encrypted packet",ssh_buffer_get(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
#endif
  rc=ssh_socket_write(session->socket, ssh_buffer_get(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
  if(rc== SSH_ERROR) {
    goto error;
  }

  session->send_seq++;

  if (ssh_buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:

  return rc;     /* SSH_OK, AGAIN or ERROR */
}
예제 #14
0
파일: kex1.c 프로젝트: caidongyun/libssh
static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey,
    ssh_public_key hostkey, int slen, int hlen) {
  unsigned char buffer[32] = {0};
  int i;
  ssh_string data1 = NULL;
  ssh_string data2 = NULL;
  if(session->next_crypto->encryptkey != NULL)
      SAFE_FREE(session->next_crypto->encryptkey);
  if(session->next_crypto->decryptkey != NULL)
        SAFE_FREE(session->next_crypto->decryptkey);
  if(session->next_crypto->encryptIV != NULL)
          SAFE_FREE(session->next_crypto->encryptIV);
  if(session->next_crypto->decryptIV != NULL)
          SAFE_FREE(session->next_crypto->decryptIV);
  session->next_crypto->encryptkey = malloc(32);
  session->next_crypto->decryptkey = malloc(32);
  session->next_crypto->encryptIV = malloc(32);
  session->next_crypto->decryptIV = malloc(32);
  if(session->next_crypto->encryptkey == NULL ||
          session->next_crypto->decryptkey == NULL ||
          session->next_crypto->encryptIV == NULL ||
          session->next_crypto->decryptIV == NULL){
      ssh_set_error_oom(session);
      return NULL;
  }
  /* first, generate a session key */
  ssh_get_random(session->next_crypto->encryptkey, 32, 1);
  memcpy(buffer, session->next_crypto->encryptkey, 32);
  memcpy(session->next_crypto->decryptkey, session->next_crypto->encryptkey, 32);
  memset(session->next_crypto->encryptIV, 0, 32);
  memset(session->next_crypto->decryptIV, 0, 32);

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("session key",buffer,32);
#endif

  /* xor session key with session_id */
  for (i = 0; i < 16; i++) {
    buffer[i] ^= session->next_crypto->session_id[i];
  }
  data1 = ssh_string_new(32);
  if (data1 == NULL) {
    return NULL;
  }
  ssh_string_fill(data1, buffer, 32);
  if (ABS(hlen - slen) < 128){
    SSH_LOG(SSH_LOG_FUNCTIONS,
        "Difference between server modulus and host modulus is only %d. "
        "It's illegal and may not work",
        ABS(hlen - slen));
  }

  if (modulus_smaller(srvkey, hostkey)) {
    data2 = ssh_encrypt_rsa1(session, data1, srvkey);
    ssh_string_free(data1);
    data1 = NULL;
    if (data2 == NULL) {
      return NULL;
    }
    data1 = ssh_encrypt_rsa1(session, data2, hostkey);
    ssh_string_free(data2);
    if (data1 == NULL) {
      return NULL;
    }
  } else {
    data2 = ssh_encrypt_rsa1(session, data1, hostkey);
    ssh_string_free(data1);
    data1 = NULL;
    if (data2 == NULL) {
      return NULL;
    }
    data1 = ssh_encrypt_rsa1(session, data2, srvkey);
    ssh_string_free(data2);
    if (data1 == NULL) {
      return NULL;
    }
  }

  return data1;
}
예제 #15
0
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
 * SSH_MSG_KEXDH_REPLY
 */
int ssh_server_curve25519_init(ssh_session_t * session, ssh_buffer_t * packet){
    /* ECDH keys */
    ssh_string_t * q_c_string;
    ssh_string_t * q_s_string;

    /* SSH host keys (rsa,dsa,ecdsa) */
    ssh_key_t * privkey;
    ssh_string_t * sig_blob = NULL;
    int rc;

    /* Extract the client pubkey from the init packet */
    q_c_string = buffer_get_ssh_string(packet);
    if (q_c_string == NULL) {
        ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
        return SSH_ERROR;
    }
    if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
    	ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
    			(int)ssh_string_len(q_c_string));
    	ssh_string_free(q_c_string);
    	return SSH_ERROR;
    }

    memcpy(session->next_crypto->curve25519_client_pubkey,
    		ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
    ssh_string_free(q_c_string);
    /* Build server's keypair */

    rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1);
    if (rc == 0){
        ssh_set_error(session, SSH_FATAL, "PRNG error");
        return SSH_ERROR;
    }

    crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
  		  session->next_crypto->curve25519_privkey);

    rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    /* build k and session_id */
    rc = ssh_curve25519_build_k(session);
    if (rc < 0) {
        ssh_set_error(session, SSH_FATAL, "Cannot build k number");
        goto error;
    }

    /* privkey is not allocated */
    rc = ssh_get_key_params(session, &privkey);
    if (rc == SSH_ERROR) {
        goto error;
    }

    rc = make_sessionid(session);
    if (rc != SSH_OK) {
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
        goto error;
    }

    /* add host's public key */
    rc = buffer_add_ssh_string(session->out_buffer,
                               session->next_crypto->server_pubkey);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    /* add ecdh public key */
    q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE);
    if (q_s_string == NULL) {
        goto error;
    }

    ssh_string_fill(q_s_string,
                    session->next_crypto->curve25519_server_pubkey,
                    CURVE25519_PUBKEY_SIZE);

    rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
    ssh_string_free(q_s_string);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }
    /* add signature blob */
    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
    if (sig_blob == NULL) {
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
        goto error;
    }

    rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
    ssh_string_free(sig_blob);
    if (rc < 0) {
        ssh_set_error_oom(session);
        goto error;
    }

    SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent");
    rc = packet_send(session);
    if (rc == SSH_ERROR) {
        return SSH_ERROR;
    }

    /* Send the MSG_NEWKEYS */
    rc = buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
    if (rc < 0) {
        goto error;
    }

    session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
    rc = packet_send(session);
    SSH_INFO(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");

    return rc;
error:
    buffer_reinit(session->out_buffer);
    return SSH_ERROR;
}
예제 #16
0
파일: auth1.c 프로젝트: imeckler/Watch
int ssh_userauth1_password(ssh_session session, const char *username,
    const char *password) {
  ssh_string pwd = NULL;
  int rc;
  enter_function();
  rc = send_username(session, username);
  if (rc != SSH_AUTH_DENIED) {
    leave_function();
    return rc;
  }

  /* we trick a bit here. A known flaw in SSH1 protocol is that it's
   * easy to guess password sizes.
   * not that sure ...
   */

  /* XXX fix me here ! */
  /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */
  if(1 || strlen(password) >= 128) {
    /* not risky to disclose the size of such a big password .. */
    pwd = ssh_string_from_char(password);
    if (pwd == NULL) {
      leave_function();
      return SSH_AUTH_ERROR;
    }
  } else {
    /* fill the password string from random things. the strcpy
     * ensure there is at least a nul byte after the password.
     * most implementation won't see the garbage at end.
     * why garbage ? because nul bytes will be compressed by
     * gzip and disclose password len.
     */
    pwd = ssh_string_new(128);
    if (pwd == NULL) {
      leave_function();
      return SSH_AUTH_ERROR;
    }
    ssh_get_random( pwd->string, 128, 0);
    strcpy((char *) pwd->string, password);
  }

  if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) {
    ssh_string_burn(pwd);
    ssh_string_free(pwd);
    leave_function();
    return SSH_AUTH_ERROR;
  }
  if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) {
    ssh_string_burn(pwd);
    ssh_string_free(pwd);
    leave_function();
    return SSH_AUTH_ERROR;
  }

  ssh_string_burn(pwd);
  ssh_string_free(pwd);
  session->auth_state=SSH_AUTH_STATE_NONE;
  if (packet_send(session) == SSH_ERROR) {
    leave_function();
    return SSH_AUTH_ERROR;
  }
  rc = wait_auth1_status(session);
  leave_function();
  return rc;
}
예제 #17
0
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
                                          const char *passphrase,
                                          ssh_auth_callback auth_fn,
                                          void *auth_data)
{
    ssh_buffer buffer;
    ssh_string str = NULL;
    ssh_string pubkey_s=NULL;
    ssh_buffer privkey_buffer = NULL;
    uint32_t rnd;
    uint32_t rounds = 16;
    ssh_string salt=NULL;
    ssh_string kdf_options=NULL;
    int to_encrypt=0;
    unsigned char *b64;
    uint32_t str_len, len;
    int rc;

    if (privkey == NULL) {
        return NULL;
    }
    if (privkey->type != SSH_KEYTYPE_ED25519){
        ssh_pki_log("Unsupported key type %s", privkey->type_c);
        return NULL;
    }
    if (passphrase != NULL || auth_fn != NULL){
        ssh_pki_log("Enabling encryption for private key export");
        to_encrypt = 1;
    }
    buffer = ssh_buffer_new();
    pubkey_s = pki_publickey_to_blob(privkey);
    if(buffer == NULL || pubkey_s == NULL){
        goto error;
    }
    ssh_get_random(&rnd, sizeof(rnd), 0);

    privkey_buffer = ssh_buffer_new();
    if (privkey_buffer == NULL) {
        goto error;
    }

    /* checkint1 & 2 */
    rc = ssh_buffer_pack(privkey_buffer,
                         "dd",
                         rnd,
                         rnd);
    if (rc == SSH_ERROR){
        goto error;
    }

    rc = pki_openssh_export_privkey_blob(privkey, privkey_buffer);
    if (rc == SSH_ERROR){
        goto error;
    }

    /* comment */
    rc = ssh_buffer_pack(privkey_buffer, "s", "" /* comment */);
    if (rc == SSH_ERROR){
        goto error;
    }

    if (to_encrypt){
        ssh_buffer kdf_buf;

        kdf_buf = ssh_buffer_new();
        if (kdf_buf == NULL) {
            goto error;
        }

        salt = ssh_string_new(16);
        if (salt == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        ssh_get_random(ssh_string_data(salt),16, 0);
        ssh_buffer_pack(kdf_buf, "Sd", salt, rounds);
        kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf));
        if (kdf_options == NULL){
            ssh_buffer_free(kdf_buf);
            goto error;
        }
        memcpy(ssh_string_data(kdf_options),
               ssh_buffer_get_begin(kdf_buf),
               ssh_buffer_get_len(kdf_buf));
        ssh_buffer_free(kdf_buf);
        rc = pki_private_key_encrypt(privkey_buffer,
                                     passphrase,
                                     "aes128-cbc",
                                     "bcrypt",
                                     auth_fn,
                                     auth_data,
                                     rounds,
                                     salt);
        if (rc != SSH_OK){
            goto error;
        }
    } else {
        kdf_options = ssh_string_new(0);
    }

    rc = ssh_buffer_pack(buffer,
                         "PssSdSdP",
                         (size_t)strlen(OPENSSH_AUTH_MAGIC) + 1, OPENSSH_AUTH_MAGIC,
                         to_encrypt ? "aes128-cbc" : "none", /* ciphername */
                         to_encrypt ? "bcrypt" : "none", /* kdfname */
                         kdf_options, /* kdfoptions */
                         (uint32_t) 1, /* nkeys */
                         pubkey_s,
                         (uint32_t)ssh_buffer_get_len(privkey_buffer),
                         /* rest of buffer is a string */
                         (size_t)ssh_buffer_get_len(privkey_buffer), ssh_buffer_get_begin(privkey_buffer));
    if (rc != SSH_OK) {
        goto error;
    }

    b64 = bin_to_base64(ssh_buffer_get_begin(buffer),
                        ssh_buffer_get_len(buffer));
    if (b64 == NULL){
        goto error;
    }

    /* we can reuse the buffer */
    ssh_buffer_reinit(buffer);
    rc = ssh_buffer_pack(buffer,
                         "tttttt",
                         OPENSSH_HEADER_BEGIN,
                         "\n",
                         b64,
                         "\n",
                         OPENSSH_HEADER_END,
                         "\n");
    BURN_BUFFER(b64, strlen((char *)b64));
    SAFE_FREE(b64);

    if (rc != SSH_OK){
        goto error;
    }

    str = ssh_string_new(ssh_buffer_get_len(buffer));
    if (str == NULL){
        goto error;
    }

    str_len = ssh_buffer_get_len(buffer);
    len = buffer_get_data(buffer, ssh_string_data(str), str_len);
    if (str_len != len) {
        ssh_string_free(str);
        str = NULL;
    }

error:
    if (privkey_buffer != NULL) {
        void *bufptr = ssh_buffer_get_begin(privkey_buffer);
        BURN_BUFFER(bufptr, ssh_buffer_get_len(privkey_buffer));
        ssh_buffer_free(privkey_buffer);
    }
    SAFE_FREE(pubkey_s);
    SAFE_FREE(kdf_options);
    SAFE_FREE(salt);
    if (buffer != NULL) {
        ssh_buffer_free(buffer);
    }

    return str;
}
예제 #18
0
파일: packet.c 프로젝트: caidongyun/nullfxp
static int packet_send2(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  uint32_t currentlen = buffer_get_rest_len(session->out_buffer);
  unsigned char *hmac = NULL;
  char padstring[32] = {0};
  int rc = SSH_ERROR;
  uint32_t finallen;
  uint8_t padding;

  enter_function();

  ssh_log(session, SSH_LOG_PACKET,
      "Writing on the wire a packet having %u bytes before", currentlen);

#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
  if (session->current_crypto
      && session->current_crypto->do_compress_out
      && buffer_get_rest_len(session->out_buffer)) {
    ssh_log(session, SSH_LOG_PACKET, "Compressing out_buffer ...");
    if (compress_buffer(session,session->out_buffer) < 0) {
      goto error;
    }
    currentlen = buffer_get_rest_len(session->out_buffer);
  }
#endif
  padding = (blocksize - ((currentlen +5) % blocksize));
  if(padding < 4) {
    padding += blocksize;
  }

  if (session->current_crypto) {
    ssh_get_random(padstring, padding, 0);
  } else {
    memset(padstring,0,padding);
  }

  finallen = htonl(currentlen + padding + 1);
  ssh_log(session, SSH_LOG_PACKET,
      "%d bytes after comp + %d padding bytes = %lu bytes packet",
      currentlen, padding, (long unsigned int) ntohl(finallen));

  if (buffer_prepend_data(session->out_buffer, &padding, sizeof(uint8_t)) < 0) {
    goto error;
  }
  if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
    goto error;
  }
  if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
    goto error;
  }
#ifdef WITH_PCAP
  if(session->pcap_ctx){
  	ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
  			buffer_get_rest(session->out_buffer),buffer_get_rest_len(session->out_buffer)
  			,buffer_get_rest_len(session->out_buffer));
  }
#endif
  hmac = packet_encrypt(session, buffer_get_rest(session->out_buffer),
      buffer_get_rest_len(session->out_buffer));
  if (hmac) {
    if (buffer_add_data(session->out_buffer, hmac, 20) < 0) {
      goto error;
    }
  }

  rc = ssh_packet_write(session);
  session->send_seq++;

  if (buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:
  leave_function();
  return rc; /* SSH_OK, AGAIN or ERROR */
}
예제 #19
0
파일: packet.c 프로젝트: kedazo/libssh
static int packet_send2(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  enum ssh_hmac_e hmac_type = (session->current_crypto ?
      session->current_crypto->out_hmac : session->next_crypto->out_hmac);
  uint32_t currentlen = ssh_buffer_get_len(session->out_buffer);
  unsigned char *hmac = NULL;
  char padstring[32] = { 0 };
  int rc = SSH_ERROR;
  uint32_t finallen,payloadsize,compsize;
  uint8_t padding;

  uint8_t header[sizeof(padding) + sizeof(finallen)] = { 0 };

  payloadsize = currentlen;
#ifdef WITH_ZLIB
  if (session->current_crypto
      && session->current_crypto->do_compress_out
      && ssh_buffer_get_len(session->out_buffer)) {
    if (compress_buffer(session,session->out_buffer) < 0) {
      goto error;
    }
    currentlen = ssh_buffer_get_len(session->out_buffer);
  }
#endif /* WITH_ZLIB */
  compsize = currentlen;
  padding = (blocksize - ((currentlen +5) % blocksize));
  if(padding < 4) {
    padding += blocksize;
  }

  if (session->current_crypto) {
    ssh_get_random(padstring, padding, 0);
  }

  finallen = htonl(currentlen + padding + 1);

  memcpy(&header[0], &finallen, sizeof(finallen));
  header[sizeof(finallen)] = padding;
  rc = ssh_buffer_prepend_data(session->out_buffer, &header, sizeof(header));
  if (rc < 0) {
    goto error;
  }
  rc = ssh_buffer_add_data(session->out_buffer, padstring, padding);
  if (rc < 0) {
    goto error;
  }
#ifdef WITH_PCAP
  if(session->pcap_ctx){
  	ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
  			ssh_buffer_get(session->out_buffer),ssh_buffer_get_len(session->out_buffer)
  			,ssh_buffer_get_len(session->out_buffer));
  }
#endif
  hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer),
      ssh_buffer_get_len(session->out_buffer));
  if (hmac) {
    rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type));
    if (rc < 0) {
      goto error;
    }
  }

  rc = ssh_packet_write(session);
  session->send_seq++;
  if (session->raw_counter != NULL) {
      session->raw_counter->out_bytes += payloadsize;
      session->raw_counter->out_packets++;
  }

  SSH_LOG(SSH_LOG_PACKET,
          "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]",
          ntohl(finallen), padding, compsize, payloadsize);
  if (ssh_buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:

  return rc; /* SSH_OK, AGAIN or ERROR */
}
예제 #20
0
파일: server.c 프로젝트: simonsj/libssh
int server_set_kex(ssh_session session)
{
  struct ssh_kex_struct *server = &session->next_crypto->server_kex;
  int i, j, rc;
  const char *wanted;
  char hostkeys[128] = {0};
  enum ssh_keytypes_e keytype;
  size_t len;
  int ok;

  ZERO_STRUCTP(server);

  ok = ssh_get_random(server->cookie, 16, 0);
  if (!ok) {
      ssh_set_error(session, SSH_FATAL, "PRNG error");
      return -1;
  }

  if (session->srv.ed25519_key != NULL) {
      snprintf(hostkeys,
               sizeof(hostkeys),
               "%s",
               ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key)));
  }
#ifdef HAVE_ECC
  if (session->srv.ecdsa_key != NULL) {
	  len = strlen(hostkeys);
      snprintf(hostkeys + len, sizeof(hostkeys) - len,
               ",%s", session->srv.ecdsa_key->type_c);
  }
#endif
#ifdef HAVE_DSA
  if (session->srv.dsa_key != NULL) {
      len = strlen(hostkeys);
      keytype = ssh_key_type(session->srv.dsa_key);

      snprintf(hostkeys + len, sizeof(hostkeys) - len,
               ",%s", ssh_key_type_to_char(keytype));
  }
#endif
  if (session->srv.rsa_key != NULL) {
      /* We support also the SHA2 variants */
      len = strlen(hostkeys);
      snprintf(hostkeys + len, sizeof(hostkeys) - len,
               ",rsa-sha2-512,rsa-sha2-256");

      len = strlen(hostkeys);
      keytype = ssh_key_type(session->srv.rsa_key);

      snprintf(hostkeys + len, sizeof(hostkeys) - len,
               ",%s", ssh_key_type_to_char(keytype));
  }

  if (strlen(hostkeys) == 0) {
      return -1;
  }

  rc = ssh_options_set_algo(session,
                            SSH_HOSTKEYS,
                            hostkeys[0] == ',' ? hostkeys + 1 : hostkeys);
  if (rc < 0) {
      return -1;
  }

  for (i = 0; i < 10; i++) {
    if ((wanted = session->opts.wanted_methods[i]) == NULL) {
      wanted = ssh_kex_get_supported_method(i);
    }
    server->methods[i] = strdup(wanted);
    if (server->methods[i] == NULL) {
      for (j = 0; j < i; j++) {
        SAFE_FREE(server->methods[j]);
      }
      return -1;
    }
  }

  return 0;
}
예제 #21
0
파일: packet.c 프로젝트: alexislitool/tmate
static int packet_send2(ssh_session session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  uint32_t currentlen = buffer_get_rest_len(session->out_buffer);
  unsigned char *hmac = NULL;
  char padstring[32] = {0};
  int rc = SSH_ERROR;
  uint32_t finallen,payloadsize,compsize;
  uint8_t padding;

  payloadsize = currentlen;
#ifdef WITH_ZLIB
  if (session->current_crypto
      && session->current_crypto->do_compress_out
      && buffer_get_rest_len(session->out_buffer)) {
    if (compress_buffer(session,session->out_buffer) < 0) {
      goto error;
    }
    currentlen = buffer_get_rest_len(session->out_buffer);
  }
#endif /* WITH_ZLIB */
  compsize = currentlen;
  padding = (blocksize - ((currentlen +5) % blocksize));
  if(padding < 4) {
    padding += blocksize;
  }

  if (session->current_crypto) {
    ssh_get_random(padstring, padding, 0);
  } else {
    memset(padstring,0,padding);
  }

  finallen = htonl(currentlen + padding + 1);

  if (buffer_prepend_data(session->out_buffer, &padding, sizeof(uint8_t)) < 0) {
    goto error;
  }
  if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(uint32_t)) < 0) {
    goto error;
  }
  if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
    goto error;
  }
#ifdef WITH_PCAP
  if(session->pcap_ctx){
  	ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
  			buffer_get_rest(session->out_buffer),buffer_get_rest_len(session->out_buffer)
  			,buffer_get_rest_len(session->out_buffer));
  }
#endif
  hmac = packet_encrypt(session, buffer_get_rest(session->out_buffer),
      buffer_get_rest_len(session->out_buffer));
  if (hmac) {
    if (buffer_add_data(session->out_buffer, hmac, 20) < 0) {
      goto error;
    }
  }

  rc = ssh_packet_write(session);
  session->send_seq++;

  SSH_LOG(SSH_LOG_PACKET,
          "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]",
          ntohl(finallen), padding, compsize, payloadsize);
  if (buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:

  return rc; /* SSH_OK, AGAIN or ERROR */
}
예제 #22
0
static int packet_send1(SSH_SESSION *session) {
  unsigned int blocksize = (session->current_crypto ?
      session->current_crypto->out_cipher->blocksize : 8);
  u32 currentlen = buffer_get_len(session->out_buffer) + sizeof(u32);
  char padstring[32] = {0};
  int rc = SSH_ERROR;
  u32 finallen;
  u32 crc;
  u8 padding;

  enter_function();
  ssh_log(session,SSH_LOG_PACKET,"Sending a %d bytes long packet",currentlen);

/* TODO FIXME
#if defined(HAVE_LIBZ) && defined(WITH_LIBZ)
  if (session->current_crypto && session->current_crypto->do_compress_out) {
    if (compress_buffer(session, session->out_buffer) < 0) {
      goto error;
    }
    currentlen = buffer_get_len(session->out_buffer);
  }
#endif
*/
  padding = blocksize - (currentlen % blocksize);
  if (session->current_crypto) {
    ssh_get_random(padstring, padding, 0);
  } else {
    memset(padstring, 0, padding);
  }

  finallen = htonl(currentlen);
  ssh_log(session, SSH_LOG_PACKET,
      "%d bytes after comp + %d padding bytes = %d bytes packet",
      currentlen, padding, ntohl(finallen));

  if (buffer_prepend_data(session->out_buffer, &padstring, padding) < 0) {
    goto error;
  }
  if (buffer_prepend_data(session->out_buffer, &finallen, sizeof(u32)) < 0) {
    goto error;
  }

  crc = ssh_crc32(buffer_get(session->out_buffer) + sizeof(u32),
      buffer_get_len(session->out_buffer) - sizeof(u32));

  if (buffer_add_u32(session->out_buffer, ntohl(crc)) < 0) {
    goto error;
  }

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("Clear packet", buffer_get(session->out_buffer),
      buffer_get_len(session->out_buffer));
#endif

  packet_encrypt(session, buffer_get(session->out_buffer) + sizeof(u32),
      buffer_get_len(session->out_buffer) - sizeof(u32));

#ifdef DEBUG_CRYPTO
  ssh_print_hexa("encrypted packet",buffer_get(session->out_buffer),
      buffer_get_len(session->out_buffer));
#endif
  if (ssh_socket_write(session->socket, buffer_get(session->out_buffer),
      buffer_get_len(session->out_buffer)) == SSH_ERROR) {
    goto error;
  }

  rc = packet_flush(session, 0);
  session->send_seq++;

  if (buffer_reinit(session->out_buffer) < 0) {
    rc = SSH_ERROR;
  }
error:
  leave_function();
  return rc;     /* SSH_OK, AGAIN or ERROR */
}