示例#1
0
err_status_t
hmac_dealloc (auth_t *a)
{
    extern auth_type_t hmac;
    hmac_ctx_t *hmac_ctx;

    hmac_ctx = (hmac_ctx_t*)a->state;
    if (hmac_ctx->ctx_initialized) {
        EVP_MD_CTX_cleanup(&hmac_ctx->ctx);
    }
    if (hmac_ctx->init_ctx_initialized) {
        EVP_MD_CTX_cleanup(&hmac_ctx->init_ctx);
    }

    /* zeroize entire state*/
    octet_string_set_to_zero((uint8_t*)a,
                             sizeof(hmac_ctx_t) + sizeof(auth_t));

    /* free memory */
    crypto_free(a);

    /* decrement global count of all hmac uses */
    hmac.ref_count--;

    return err_status_ok;
}
示例#2
0
uint64_t
cipher_bits_per_second(cipher_t *c, int octets_in_buffer, int num_trials) {
  int i;
  v128_t nonce;
  clock_t timer;
  unsigned char *enc_buf;
  unsigned int len = octets_in_buffer;

  enc_buf = (unsigned char*) crypto_alloc(octets_in_buffer);
  if (enc_buf == NULL)
    return 0;  /* indicate bad parameters by returning null */
  
  /* time repeated trials */
  v128_set_to_zero(&nonce);
  timer = clock();
  for(i=0; i < num_trials; i++, nonce.v32[3] = i) {
    cipher_set_iv(c, &nonce);
    cipher_encrypt(c, enc_buf, &len);
  }
  timer = clock() - timer;

  crypto_free(enc_buf);

  if (timer == 0) {
    /* Too fast! */
    return 0;
  }
  
  return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
}
示例#3
0
err_status_t
crypto_kernel_shutdown() {
  err_status_t status;
  kernel_cipher_type_t *ctype, *next;

  /*
   * free dynamic memory used in crypto_kernel at present
   */

  /* walk down cipher type list, freeing memory */
  ctype = crypto_kernel.cipher_type_list;
  while (ctype != NULL) {
    next = ctype->next;
    debug_print(mod_crypto_kernel, 
		"freeing memory for cipher %s", 
		ctype->cipher_type->description);
    crypto_free(ctype);
    ctype = next;
  }

  /* de-initialize random number generator */
  status = rand_source_deinit();
  if (status)
    return status;

  /* return to insecure state */
  crypto_kernel.state = crypto_kernel_state_insecure;
  
  return err_status_ok;
}
示例#4
0
void
bitvector_dealloc(bitvector_t *v) {
  if (v->word != NULL)
    crypto_free(v->word);
  v->word = NULL;
  v->length = 0;
}
/*
 * This function deallocates a GCM session 
 */
err_status_t aes_gcm_openssl_dealloc (cipher_t *c)
{
    aes_gcm_ctx_t *ctx;

    ctx = (aes_gcm_ctx_t*)c->state;
    if (ctx) {
	EVP_CIPHER_CTX_cleanup(&ctx->ctx);
        /* decrement ref_count for the appropriate engine */
        switch (ctx->key_size) {
        case AES_256_KEYSIZE:
            aes_gcm_256_openssl.ref_count--;
            break;
        case AES_128_KEYSIZE:
            aes_gcm_128_openssl.ref_count--;
            break;
        default:
            return (err_status_dealloc_fail);
            break;
        }
    }

    /* zeroize entire state*/
    octet_string_set_to_zero((uint8_t*)c, sizeof(cipher_t) + sizeof(aes_gcm_ctx_t));

    /* free memory */
    crypto_free(c);

    return (err_status_ok);
}
示例#6
0
err_status_t
crypto_kernel_shutdown() {
  err_status_t status;

  /*
   * free dynamic memory used in crypto_kernel at present
   */

  /* walk down cipher type list, freeing memory */
  while (crypto_kernel.cipher_type_list != NULL) {
    kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
    crypto_kernel.cipher_type_list = ctype->next;
    debug_print(mod_crypto_kernel, 
		"freeing memory for cipher %s", 
		ctype->cipher_type->description);
    crypto_free(ctype);
  }

  /* walk down authetication module list, freeing memory */
  while (crypto_kernel.auth_type_list != NULL) {
     kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
     crypto_kernel.auth_type_list = atype->next;
     debug_print(mod_crypto_kernel, 
		"freeing memory for authentication %s",
		atype->auth_type->description);
     crypto_free(atype);
  }

  /* walk down debug module list, freeing memory */
  while (crypto_kernel.debug_module_list != NULL) {
    kernel_debug_module_t *kdm = crypto_kernel.debug_module_list;
    crypto_kernel.debug_module_list = kdm->next;
    debug_print(mod_crypto_kernel, 
		"freeing memory for debug module %s", 
		kdm->mod->name);
    crypto_free(kdm);
  }

  /* de-initialize random number generator */  status = rand_source_deinit();
  if (status)
    return status;

  /* return to insecure state */
  crypto_kernel.state = crypto_kernel_state_insecure;
  
  return err_status_ok;
}
AsymmetricKey::~AsymmetricKey()
{
   if(mKeyData)
   {
      crypto_free((crypto_key *) mKeyData);
      free(mKeyData);
   }
}
示例#8
0
err_status_t
cipher_array_alloc_init(cipher_t ***ca, int num_ciphers,
			cipher_type_t *ctype, int klen) {
  int i, j;
  err_status_t status;
  uint8_t *key;
  cipher_t **cipher_array;
  /* pad klen allocation, to handle aes_icm reading 16 bytes for the
     14-byte salt */
  int klen_pad = ((klen + 15) >> 4) << 4;

  /* allocate array of pointers to ciphers */
  cipher_array = (cipher_t **) malloc(sizeof(cipher_t *) * num_ciphers);
  if (cipher_array == NULL)
    return err_status_alloc_fail;

  /* set ca to location of cipher_array */
  *ca = cipher_array;

  /* allocate key */
  key = crypto_alloc(klen_pad);
  if (key == NULL) {
    free(cipher_array);
    return err_status_alloc_fail;
  }
  
  /* allocate and initialize an array of ciphers */
  for (i=0; i < num_ciphers; i++) {

    /* allocate cipher */
    status = cipher_type_alloc(ctype, cipher_array, klen, 16);
    if (status)
      return status;
    
    /* generate random key and initialize cipher */
    for (j=0; j < klen; j++)
      key[j] = (uint8_t) rand();
    for (; j < klen_pad; j++)
      key[j] = 0;
    status = cipher_init(*cipher_array, key);
    if (status)
      return status;

/*     printf("%dth cipher is at %p\n", i, *cipher_array); */
/*     printf("%dth cipher description: %s\n", i,  */
/* 	   (*cipher_array)->type->description); */
    
    /* advance cipher array pointer */
    cipher_array++;
  }

  crypto_free(key);

  return err_status_ok;
}
示例#9
0
文件: hmac.c 项目: dozeo/libsrtp
err_status_t
hmac_dealloc(auth_t *a) {
  extern auth_type_t hmac;
  
  /* zeroize entire state*/
  octet_string_set_to_zero((uint8_t *)a, 
			   sizeof(hmac_ctx_t) + sizeof(auth_t));

  /* free memory */
  crypto_free(a);
  
  /* decrement global count of all hmac uses */
  hmac.ref_count--;

  return err_status_ok;
}
err_status_t null_cipher_dealloc(cipher_t *c) {
    extern cipher_type_t null_cipher;

    /* zeroize entire state*/
    octet_string_set_to_zero((uint8_t *) c, sizeof(null_cipher_ctx_t)
            + sizeof(cipher_t));

    /* free memory of type null_cipher */
    crypto_free(c);

    /* decrement reference count */
    null_cipher.ref_count--;

    return err_status_ok;

}
示例#11
0
err_status_t
aes_icm_dealloc(cipher_t *c) {
    extern cipher_type_t aes_icm;

    /* zeroize entire state*/
    octet_string_set_to_zero((octet_t *)c,
                             sizeof(aes_icm_ctx_t) + sizeof(cipher_t));

    /* free memory */
    crypto_free(c);

    /* decrement ref_count */
    aes_icm.ref_count--;

    return err_status_ok;
}
示例#12
0
/*
 * This function deallocates an instance of this engine
 */
err_status_t aes_icm_openssl_dealloc (cipher_t *c)
{
    aes_icm_ctx_t *ctx;

    if (c == NULL) {
        return err_status_bad_param;
    }

    /*
     * Free the EVP context
     */
    ctx = (aes_icm_ctx_t*)c->state;
    if (ctx != NULL) {
        EVP_CIPHER_CTX_cleanup(&ctx->ctx);
        /* decrement ref_count for the appropriate engine */
        switch (ctx->key_size) {
        case AES_256_KEYSIZE:
            aes_icm_256.ref_count--;
            break;
#ifndef BORINGSSL
        case AES_192_KEYSIZE:
            aes_icm_192.ref_count--;
            break;
#endif
        case AES_128_KEYSIZE:
            aes_icm.ref_count--;
            break;
        default:
            return err_status_dealloc_fail;
            break;
        }
    }

    /* zeroize entire state*/
    octet_string_set_to_zero((uint8_t*)c,
                             sizeof(cipher_t) + sizeof(aes_icm_ctx_t));

    /* free memory */
    crypto_free(c);

    return err_status_ok;
}
示例#13
0
static int dh_handshake_server(SSH_SESSION *session){
    STRING *e,*f,*pubkey,*sign;
    PUBLIC_KEY *pub;
    PRIVATE_KEY *prv;
    BUFFER *buf=buffer_new();
    if(packet_wait(session, SSH2_MSG_KEXDH_INIT)) // FIXME BLOCKING
        return -1;
    e=buffer_get_ssh_string(session->in_buffer);
    if(!e){
        ssh_set_error(session,SSH_FATAL,"No e number in client request");
        return -1;
    }
    dh_import_e(session,e);
    dh_generate_y(session);
    dh_generate_f(session);
    f=dh_get_f(session);
    switch(session->hostkeys){
        case TYPE_DSS:
            prv=session->dsa_key;
            break;
        case TYPE_RSA:
            prv=session->rsa_key;
            break;
        default:
            prv=NULL;
    }
    pub=publickey_from_privatekey(prv);
    pubkey=publickey_to_string(pub);
    publickey_free(pub);
    dh_import_pubkey(session,pubkey);
    dh_build_k(session);
    make_sessionid(session);
    sign=ssh_sign_session_id(session,prv);
    buffer_free(buf);
    /* free private keys as they should not be readable past this point */
    if(session->rsa_key){
        private_key_free(session->rsa_key);
        session->rsa_key=NULL;
    }
    if(session->dsa_key){
        private_key_free(session->dsa_key);
        session->dsa_key=NULL;
    }
    buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_REPLY);
    buffer_add_ssh_string(session->out_buffer,pubkey);
    buffer_add_ssh_string(session->out_buffer,f);
    buffer_add_ssh_string(session->out_buffer,sign);
    free(sign);
    packet_send(session);
    free(f);
    packet_clear_out(session);
    buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
    packet_send(session);
    ssh_say(2,"SSH_MSG_NEWKEYS sent\n");

    packet_wait(session,SSH2_MSG_NEWKEYS);// FIXME BLOCKING
    ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
    generate_session_keys(session);
    /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
    if(session->current_crypto)
        crypto_free(session->current_crypto);
    /* XXX later, include a function to change keys */
    session->current_crypto=session->next_crypto;
    session->next_crypto=crypto_new();
    return 0;
}
示例#14
0
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  ssh_string str = NULL;
  struct ssh_iterator *it;

  if (session == NULL) {
    return;
  }

  if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
    if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
      goto error;
    }
    if (buffer_add_u32(session->out_buffer,
          htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) {
      goto error;
    }

    str = ssh_string_from_char("Bye Bye");
    if (str == NULL) {
      goto error;
    }

    if (buffer_add_ssh_string(session->out_buffer,str) < 0) {
      ssh_string_free(str);
      goto error;
    }
    ssh_string_free(str);

    packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->alive = 0;
  if (session->socket != NULL){
    ssh_socket_reset(session->socket);
  }
  session->opts.fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;

  while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
    ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
    ssh_list_remove(session->channels, it);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if (session->in_buffer) {
    ssh_buffer_reinit(session->in_buffer);
  }
  if (session->out_buffer) {
    ssh_buffer_reinit(session->out_buffer);
  }
  if (session->in_hashbuf) {
    ssh_buffer_reinit(session->in_hashbuf);
  }
  if (session->out_hashbuf) {
    ssh_buffer_reinit(session->out_hashbuf);
  }
  session->auth_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);

  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }
}
示例#15
0
/**
 * @brief Deallocate a SSH session handle.
 *
 * @param[in] session   The SSH session to free.
 *
 * @see ssh_disconnect()
 * @see ssh_new()
 */
void ssh_free(ssh_session session) {
  int i;
  struct ssh_iterator *it;

  if (session == NULL) {
    return;
  }

  /*
   * Delete all channels
   *
   * This needs the first thing we clean up cause if there is still an open
   * channel we call ssh_channel_close() first. So we need a working socket
   * and poll context for it.
   */
  for (it = ssh_list_get_iterator(session->channels);
       it != NULL;
       it = ssh_list_get_iterator(session->channels)) {
      ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
      ssh_list_remove(session->channels, it);
  }
  ssh_list_free(session->channels);
  session->channels = NULL;

#ifdef WITH_PCAP
  if (session->pcap_ctx) {
      ssh_pcap_context_free(session->pcap_ctx);
      session->pcap_ctx = NULL;
  }
#endif

  ssh_socket_free(session->socket);
  session->socket = NULL;

  if (session->default_poll_ctx) {
      ssh_poll_ctx_free(session->default_poll_ctx);
  }

  ssh_buffer_free(session->in_buffer);
  ssh_buffer_free(session->out_buffer);
  session->in_buffer = session->out_buffer = NULL;

  if (session->in_hashbuf != NULL) {
      ssh_buffer_free(session->in_hashbuf);
  }
  if (session->out_hashbuf != NULL) {
      ssh_buffer_free(session->out_hashbuf);
  }

  crypto_free(session->current_crypto);
  crypto_free(session->next_crypto);

#ifndef _WIN32
  agent_free(session->agent);
#endif /* _WIN32 */

  ssh_key_free(session->srv.dsa_key);
  ssh_key_free(session->srv.rsa_key);

  if (session->ssh_message_list) {
      ssh_message msg;

      for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
           msg != NULL;
           msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) {
          ssh_message_free(msg);
      }
      ssh_list_free(session->ssh_message_list);
  }

  if (session->packet_callbacks) {
    ssh_list_free(session->packet_callbacks);
  }

  /* options */
  if (session->opts.identity) {
      char *id;

      for (id = ssh_list_pop_head(char *, session->opts.identity);
           id != NULL;
           id = ssh_list_pop_head(char *, session->opts.identity)) {
          SAFE_FREE(id);
      }
      ssh_list_free(session->opts.identity);
  }
示例#16
0
文件: server.c 项目: alejom200/tmate
/**
 * @internal
 *
 * @brief A function to be called each time a step has been done in the
 * connection.
 */
static void ssh_server_connection_callback(ssh_session session){
	int ssh1,ssh2;

	switch(session->session_state){
		case SSH_SESSION_STATE_NONE:
		case SSH_SESSION_STATE_CONNECTING:
		case SSH_SESSION_STATE_SOCKET_CONNECTED:
			break;
		case SSH_SESSION_STATE_BANNER_RECEIVED:
		  if (session->clientbanner == NULL) {
		    goto error;
		  }
		  set_status(session, 0.4f);
		  SSH_LOG(SSH_LOG_RARE,
		      "SSH client banner: %s", session->clientbanner);

		  /* Here we analyze the different protocols the server allows. */
		  if (ssh_analyze_banner(session, 1, &ssh1, &ssh2) < 0) {
		    goto error;
		  }
		  /* Here we decide which version of the protocol to use. */
		  if (ssh2 && session->opts.ssh2) {
		    session->version = 2;
		  } else if (ssh1 && session->opts.ssh1) {
		    session->version = 1;
		  } else if (ssh1 && !session->opts.ssh1) {
#ifdef WITH_SSH1
		    ssh_set_error(session, SSH_FATAL,
		        "SSH-1 protocol not available (configure session to allow SSH-1)");
		    goto error;
#else
		    ssh_set_error(session, SSH_FATAL,
		        "SSH-1 protocol not available (libssh compiled without SSH-1 support)");
		    goto error;
#endif
		  } else {
		    ssh_set_error(session, SSH_FATAL,
		        "No version of SSH protocol usable (banner: %s)",
		        session->clientbanner);
		    goto error;
		  }
		  /* from now, the packet layer is handling incoming packets */
		  if(session->version==2)
		    session->socket_callbacks.data=ssh_packet_socket_callback;
#ifdef WITH_SSH1
		  else
		    session->socket_callbacks.data=ssh_packet_socket_callback1;
#endif
		  ssh_packet_set_default_callbacks(session);
		  set_status(session, 0.5f);
		  session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
          if (ssh_send_kex(session, 1) < 0) {
			goto error;
		  }
		  break;
		case SSH_SESSION_STATE_INITIAL_KEX:
		/* TODO: This state should disappear in favor of get_key handle */
#ifdef WITH_SSH1
			if(session->version==1){
				if (ssh_get_kex1(session) < 0)
					goto error;
				set_status(session,0.6f);
				session->connected = 1;
				break;
			}
#endif
			break;
		case SSH_SESSION_STATE_KEXINIT_RECEIVED:
			set_status(session,0.6f);
			if(session->next_crypto->server_kex.methods[0]==NULL){
			      if(server_set_kex(session) == SSH_ERROR)
				goto error;
			      /* We are in a rekeying, so we need to send the server kex */
			      if(ssh_send_kex(session, 1) < 0)
				goto error;
			}
			ssh_list_kex(&session->next_crypto->client_kex); // log client kex
			if (ssh_kex_select_methods(session) < 0) {
				goto error;
			}
            if (crypt_set_algorithms_server(session) == SSH_ERROR)
                goto error;
			set_status(session,0.8f);
			session->session_state=SSH_SESSION_STATE_DH;
            break;
		case SSH_SESSION_STATE_DH:
			if(session->dh_handshake_state==DH_STATE_FINISHED){
                if (generate_session_keys(session) < 0) {
                  goto error;
                }

                /*
                 * Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
                 * current_crypto
                 */
                if (session->current_crypto) {
                  crypto_free(session->current_crypto);
                }

                /* FIXME TODO later, include a function to change keys */
                session->current_crypto = session->next_crypto;
                session->next_crypto = crypto_new();
                if (session->next_crypto == NULL) {
                  goto error;
                }
			session->next_crypto->session_id = malloc(session->current_crypto->digest_len);
			if (session->next_crypto->session_id == NULL) {
			  ssh_set_error_oom(session);
			  goto error;
			}
			memcpy(session->next_crypto->session_id, session->current_crypto->session_id,
			    session->current_crypto->digest_len);

			    set_status(session,1.0f);
			    session->connected = 1;
			    session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
			    if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
				    session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
		}
			break;
		case SSH_SESSION_STATE_AUTHENTICATING:
			break;
		case SSH_SESSION_STATE_ERROR:
			goto error;
		default:
			ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
	}

	return;
error:
	ssh_socket_close(session->socket);
	session->alive = 0;
	session->session_state=SSH_SESSION_STATE_ERROR;
}
示例#17
0
文件: client.c 项目: Ludoovik5/libssh
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  ssh_string str = NULL;
  int i;

  if (session == NULL) {
    return;
  }

  enter_function();

  if (ssh_socket_is_open(session->socket)) {
    if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
      goto error;
    }
    if (buffer_add_u32(session->out_buffer,
          htonl(SSH2_DISCONNECT_BY_APPLICATION)) < 0) {
      goto error;
    }

    str = ssh_string_from_char("Bye Bye");
    if (str == NULL) {
      goto error;
    }

    if (buffer_add_ssh_string(session->out_buffer,str) < 0) {
      ssh_string_free(str);
      goto error;
    }
    ssh_string_free(str);

    packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->alive = 0;
  if(session->socket){
    ssh_socket_reset(session->socket);
  }
  session->fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;
  while (session->channels) {
    ssh_channel_free(session->channels);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if(session->in_buffer)
    buffer_reinit(session->in_buffer);
  if(session->out_buffer)
    buffer_reinit(session->out_buffer);
  if(session->in_hashbuf)
    buffer_reinit(session->in_hashbuf);
  if(session->out_hashbuf)
    buffer_reinit(session->out_hashbuf);
  session->auth_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);
  if (session->client_kex.methods) {
    for (i = 0; i < 10; i++) {
      SAFE_FREE(session->client_kex.methods[i]);
    }
  }

  if (session->server_kex.methods) {
    for (i = 0; i < 10; i++) {
      SAFE_FREE(session->server_kex.methods[i]);
    }
  }
  SAFE_FREE(session->client_kex.methods);
  SAFE_FREE(session->server_kex.methods);
  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }

  leave_function();
}
示例#18
0
文件: server.c 项目: Paxxi/libssh
/**
 * @internal
 *
 * @brief A function to be called each time a step has been done in the
 * connection.
 */
static void ssh_server_connection_callback(ssh_session session){
    int rc;

    switch(session->session_state){
        case SSH_SESSION_STATE_NONE:
        case SSH_SESSION_STATE_CONNECTING:
        case SSH_SESSION_STATE_SOCKET_CONNECTED:
            break;
        case SSH_SESSION_STATE_BANNER_RECEIVED:
            if (session->clientbanner == NULL) {
                goto error;
            }
            set_status(session, 0.4f);
            SSH_LOG(SSH_LOG_RARE,
                    "SSH client banner: %s", session->clientbanner);

            /* Here we analyze the different protocols the server allows. */
            rc = ssh_analyze_banner(session, 1);
            if (rc < 0) {
                ssh_set_error(session, SSH_FATAL,
                        "No version of SSH protocol usable (banner: %s)",
                        session->clientbanner);
                goto error;
            }

            /* from now, the packet layer is handling incoming packets */
            session->socket_callbacks.data=ssh_packet_socket_callback;

            ssh_packet_set_default_callbacks(session);
            set_status(session, 0.5f);
            session->session_state=SSH_SESSION_STATE_INITIAL_KEX;
            if (ssh_send_kex(session, 1) < 0) {
                goto error;
            }
            break;
        case SSH_SESSION_STATE_INITIAL_KEX:
            /* TODO: This state should disappear in favor of get_key handle */
            break;
        case SSH_SESSION_STATE_KEXINIT_RECEIVED:
            set_status(session,0.6f);
            if(session->next_crypto->server_kex.methods[0]==NULL){
                if(server_set_kex(session) == SSH_ERROR)
                    goto error;
                /* We are in a rekeying, so we need to send the server kex */
                if(ssh_send_kex(session, 1) < 0)
                    goto error;
            }
            ssh_list_kex(&session->next_crypto->client_kex); // log client kex
            if (ssh_kex_select_methods(session) < 0) {
                goto error;
            }
            if (crypt_set_algorithms_server(session) == SSH_ERROR)
                goto error;
            set_status(session,0.8f);
            session->session_state=SSH_SESSION_STATE_DH;
            break;
        case SSH_SESSION_STATE_DH:
            if(session->dh_handshake_state==DH_STATE_FINISHED){
                if (ssh_generate_session_keys(session) < 0) {
                    goto error;
                }

                /*
                 * Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
                 * current_crypto
                 */
                if (session->current_crypto) {
                    crypto_free(session->current_crypto);
                }

                /* FIXME TODO later, include a function to change keys */
                session->current_crypto = session->next_crypto;
                session->next_crypto = crypto_new();
                if (session->next_crypto == NULL) {
                    goto error;
                }
                session->next_crypto->session_id = malloc(session->current_crypto->digest_len);
                if (session->next_crypto->session_id == NULL) {
                    ssh_set_error_oom(session);
                    goto error;
                }
                memcpy(session->next_crypto->session_id, session->current_crypto->session_id,
                        session->current_crypto->digest_len);
                if (session->current_crypto->in_cipher->set_decrypt_key(session->current_crypto->in_cipher, session->current_crypto->decryptkey,
                            session->current_crypto->decryptIV) < 0) {
                    goto error;
                }
                if (session->current_crypto->out_cipher->set_encrypt_key(session->current_crypto->out_cipher, session->current_crypto->encryptkey,
                            session->current_crypto->encryptIV) < 0) {
                    goto error;
                }

                set_status(session,1.0f);
                session->connected = 1;
                session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
                if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED)
                    session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
            }
            break;
        case SSH_SESSION_STATE_AUTHENTICATING:
            break;
        case SSH_SESSION_STATE_ERROR:
            goto error;
        default:
            ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state);
    }

    return;
error:
    ssh_socket_close(session->socket);
    session->alive = 0;
    session->session_state=SSH_SESSION_STATE_ERROR;
}
示例#19
0
文件: client.c 项目: cedral/libssh
/**
 * @brief Disconnect from a session (client or server).
 * The session can then be reused to open a new session.
 *
 * @param[in]  session  The SSH session to use.
 */
void ssh_disconnect(ssh_session session) {
  struct ssh_iterator *it;
  int rc;

  if (session == NULL) {
    return;
  }

  if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
    rc = ssh_buffer_pack(session->out_buffer,
                         "bdss",
                         SSH2_MSG_DISCONNECT,
                         SSH2_DISCONNECT_BY_APPLICATION,
                         "Bye Bye",
                         ""); /* language tag */
    if (rc != SSH_OK){
      ssh_set_error_oom(session);
      goto error;
    }

    ssh_packet_send(session);
    ssh_socket_close(session->socket);
  }
error:
  session->recv_seq = 0;
  session->send_seq = 0;
  session->alive = 0;
  if (session->socket != NULL){
    ssh_socket_reset(session->socket);
  }
  session->opts.fd = SSH_INVALID_SOCKET;
  session->session_state=SSH_SESSION_STATE_DISCONNECTED;

  while ((it=ssh_list_get_iterator(session->channels)) != NULL) {
    ssh_channel_do_free(ssh_iterator_value(ssh_channel,it));
    ssh_list_remove(session->channels, it);
  }
  if(session->current_crypto){
    crypto_free(session->current_crypto);
    session->current_crypto=NULL;
  }
  if (session->next_crypto) {
    crypto_free(session->next_crypto);
    session->next_crypto = crypto_new();
    if (session->next_crypto == NULL) {
      ssh_set_error_oom(session);
    }
  }
  if (session->in_buffer) {
    ssh_buffer_reinit(session->in_buffer);
  }
  if (session->out_buffer) {
    ssh_buffer_reinit(session->out_buffer);
  }
  if (session->in_hashbuf) {
    ssh_buffer_reinit(session->in_hashbuf);
  }
  if (session->out_hashbuf) {
    ssh_buffer_reinit(session->out_hashbuf);
  }
  session->auth.supported_methods = 0;
  SAFE_FREE(session->serverbanner);
  SAFE_FREE(session->clientbanner);

  if(session->ssh_message_list){
    ssh_message msg;
    while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
        != NULL){
      ssh_message_free(msg);
    }
    ssh_list_free(session->ssh_message_list);
    session->ssh_message_list=NULL;
  }

  if (session->packet_callbacks){
    ssh_list_free(session->packet_callbacks);
    session->packet_callbacks=NULL;
  }
}
示例#20
0
static int dh_handshake_server(SSH_SESSION *session) {
  STRING *e;
  STRING *f;
  STRING *pubkey;
  STRING *sign;
  PUBLIC_KEY *pub;
  PRIVATE_KEY *prv;

  if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) {
    return -1;
  }

  e = buffer_get_ssh_string(session->in_buffer);
  if (e == NULL) {
    ssh_set_error(session, SSH_FATAL, "No e number in client request");
    return -1;
  }
  if (dh_import_e(session, e) < 0) {
    ssh_set_error(session, SSH_FATAL, "Cannot import e number");
    string_free(e);
    return -1;
  }
  string_free(e);

  if (dh_generate_y(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create y number");
    return -1;
  }
  if (dh_generate_f(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not create f number");
    return -1;
  }

  f = dh_get_f(session);
  if (f == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not get the f number");
    return -1;
  }

  switch(session->hostkeys){
    case TYPE_DSS:
      prv = session->dsa_key;
      break;
    case TYPE_RSA:
      prv = session->rsa_key;
      break;
    default:
      prv = NULL;
  }

  pub = publickey_from_privatekey(prv);
  if (pub == NULL) {
    ssh_set_error(session, SSH_FATAL,
        "Could not get the public key from the private key");
    string_free(f);
    return -1;
  }
  pubkey = publickey_to_string(pub);
  publickey_free(pub);
  if (pubkey == NULL) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    string_free(f);
    return -1;
  }

  dh_import_pubkey(session, pubkey);
  if (dh_build_k(session) < 0) {
    ssh_set_error(session, SSH_FATAL, "Could not import the public key");
    string_free(f);
    return -1;
  }

  if (make_sessionid(session) != SSH_OK) {
    ssh_set_error(session, SSH_FATAL, "Could not create a session id");
    string_free(f);
    return -1;
  }

  sign = ssh_sign_session_id(session, prv);
  if (sign == NULL) {
    ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
    string_free(f);
    return -1;
  }

  /* Free private keys as they should not be readable after this point */
  if (session->rsa_key) {
    privatekey_free(session->rsa_key);
    session->rsa_key = NULL;
  }
  if (session->dsa_key) {
    privatekey_free(session->dsa_key);
    session->dsa_key = NULL;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 ||
      buffer_add_ssh_string(session->out_buffer, pubkey) < 0 ||
      buffer_add_ssh_string(session->out_buffer, f) < 0 ||
      buffer_add_ssh_string(session->out_buffer, sign) < 0) {
    ssh_set_error(session, SSH_FATAL, "Not enough space");
    buffer_free(session->out_buffer);
    string_free(f);
    string_free(sign);
    return -1;
  }
  string_free(f);
  string_free(sign);

  if (packet_send(session) != SSH_OK) {
    return -1;
  }

  if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
    buffer_free(session->out_buffer);
    return -1;
  }

  if (packet_send(session) != SSH_OK) {
    return -1;
  }
  ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");

  if (packet_wait(session, SSH2_MSG_NEWKEYS, 1) != SSH_OK) {
    return -1;
  }
  ssh_log(session, SSH_LOG_PACKET, "Got SSH_MSG_NEWKEYS");

  if (generate_session_keys(session) < 0) {
    return -1;
  }

  /*
   * Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and
   * current_crypto
   */
  if (session->current_crypto) {
    crypto_free(session->current_crypto);
  }

  /* FIXME TODO later, include a function to change keys */
  session->current_crypto = session->next_crypto;
  session->next_crypto = crypto_new();
  if (session->next_crypto == NULL) {
    return -1;
  }

  return 0;
}
示例#21
0
static int dh_handshake(SSH_SESSION *session){
    STRING *e,*f,*pubkey,*signature;
    int ret;
    switch(session->dh_handshake_state){
        case DH_STATE_INIT:
            packet_clear_out(session);
            buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_INIT);
            dh_generate_x(session);
            dh_generate_e(session);
            e=dh_get_e(session);
            buffer_add_ssh_string(session->out_buffer,e);
            ret=packet_send(session);
            free(e);
            session->dh_handshake_state=DH_STATE_INIT_TO_SEND;
            if(ret==SSH_ERROR)
                return ret;
        case DH_STATE_INIT_TO_SEND:
            ret=packet_flush(session,0);
            if(ret!=SSH_OK)
                return ret; // SSH_ERROR or SSH_AGAIN
            session->dh_handshake_state=DH_STATE_INIT_SENT;
        case DH_STATE_INIT_SENT:
            ret=packet_wait(session,SSH2_MSG_KEXDH_REPLY,1);
            if(ret != SSH_OK)
                return ret;
            pubkey=buffer_get_ssh_string(session->in_buffer);
            if(!pubkey){
                ssh_set_error(session,SSH_FATAL,"No public key in packet");
                return SSH_ERROR;
            }
            dh_import_pubkey(session,pubkey);
            f=buffer_get_ssh_string(session->in_buffer);
            if(!f){
                ssh_set_error(session,SSH_FATAL,"No F number in packet");
                return SSH_ERROR;
            }
            dh_import_f(session,f);
            free(f);
            if(!(signature=buffer_get_ssh_string(session->in_buffer))){
                ssh_set_error(session,SSH_FATAL,"No signature in packet");
                return SSH_ERROR;
            }
            session->dh_server_signature=signature;
            dh_build_k(session);
            // send the MSG_NEWKEYS
            packet_clear_out(session);
            buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
            packet_send(session);
            session->dh_handshake_state=DH_STATE_NEWKEYS_TO_SEND;
        case DH_STATE_NEWKEYS_TO_SEND:
            ret=packet_flush(session,0);
            if(ret != SSH_OK)
                return ret;
            ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
            session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
        case DH_STATE_NEWKEYS_SENT:
            ret=packet_wait(session,SSH2_MSG_NEWKEYS,1);
            if(ret != SSH_OK)
                return ret;
            ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
            make_sessionid(session);
            /* set the cryptographic functions for the next crypto */
            /* (it is needed for generate_session_keys for key lenghts) */
            if(crypt_set_algorithms(session))
                return SSH_ERROR;
            generate_session_keys(session);
            /* verify the host's signature. XXX do it sooner */
            signature=session->dh_server_signature;
            session->dh_server_signature=NULL;
            if(signature_verify(session,signature)){
                free(signature);
                return SSH_ERROR;
            }
            free(signature);	/* forget it for now ... */
            /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
            if(session->current_crypto)
                crypto_free(session->current_crypto);
                /* XXX later, include a function to change keys */
            session->current_crypto=session->next_crypto;
            session->next_crypto=crypto_new();
            session->dh_handshake_state=DH_STATE_FINISHED;
            return SSH_OK;
        default:
            ssh_set_error(session,SSH_FATAL,"Invalid state in dh_handshake():%d",session->dh_handshake_state);
            return SSH_ERROR;
    }
    /* not reached */
    return SSH_ERROR;
}