示例#1
0
文件: sshmalloc.c 项目: AnthraX1/rk
void ssh_xfree(void *ptr)
{
#ifdef SSH_DEBUG_MALLOC
  if (ptr != NULL)
    {
      unsigned long size;

      if (SSH_GET_32BIT((unsigned char *) ptr - 4) !=
          SSH_DEBUG_MALLOC_MAGIC_IN_USE)
        {
          if (SSH_GET_32BIT((unsigned char *) ptr - 4) ==
              SSH_DEBUG_MALLOC_MAGIC_FREED)
            ssh_fatal("Freeing block that is already freed");
          ssh_fatal("Freeing block that is either not mallocated, or whose magic number before the object was overwritten");
        }

      size = SSH_GET_32BIT((unsigned char *) ptr -
                           SSH_DEBUG_MALLOC_SIZE_BEFORE);
      if (SSH_GET_32BIT((unsigned char *) ptr + size) !=
          SSH_DEBUG_MALLOC_MAGIC_AFTER)
        ssh_fatal("Freeing block whose magic number after the object was overwritten");

      /* Mark the old block freed */
      SSH_PUT_32BIT((unsigned char *) ptr - 4, SSH_DEBUG_MALLOC_MAGIC_FREED);
      SSH_PUT_32BIT((unsigned char *) ptr + size,
                    SSH_DEBUG_MALLOC_MAGIC_FREED);
      free((unsigned char *) ptr - SSH_DEBUG_MALLOC_SIZE_BEFORE);
    }
#else /* SSH_DEBUG_MALLOC */
  if (ptr != NULL)
    free(ptr);
#endif /* SSH_DEBUG_MALLOC */
}
示例#2
0
文件: sshmalloc.c 项目: AnthraX1/rk
void *ssh_xmalloc(unsigned long size)
{
  void *ptr;

  if (size > XMALLOC_MAX_SIZE)
    ssh_fatal("ssh_xmalloc: allocation too large (allocating %ld bytes)",
              size);

  if (size == 0)
    size = 1;
#ifdef SSH_DEBUG_MALLOC
  ptr = (void *)malloc((size_t) size + SSH_DEBUG_MALLOC_SIZE_BEFORE +
                       SSH_DEBUG_MALLOC_SIZE_AFTER);
  if (ptr == NULL)
    ssh_fatal("ssh_xmalloc: out of memory (allocating %ld bytes)", size);

  SSH_PUT_32BIT(ptr, size);
  SSH_PUT_32BIT((unsigned char *) ptr + 4, SSH_DEBUG_MALLOC_MAGIC_IN_USE);
  SSH_PUT_32BIT((unsigned char *) ptr + size + SSH_DEBUG_MALLOC_SIZE_BEFORE,
                SSH_DEBUG_MALLOC_MAGIC_AFTER);
  ptr = (unsigned char *) ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE;
#else /* SSH_DEBUG_MALLOC */
  ptr = (void *)malloc((size_t) size);
  if (ptr == NULL)
    ssh_fatal("ssh_xmalloc: out of memory (allocating %ld bytes)", size);
#endif /* SSH_DEBUG_MALLOC */
  return ptr;
}
示例#3
0
static SshCryptoStatus sha512_final(void *c, unsigned char *digest,
                                    int num_64bit_words )
{
    SshSHA512Context *context = c;
    int padding, i;
    unsigned char temp = 0x80;
    unsigned int in_buffer;
    SshUInt32 total_low, total_high;

    total_low = context->total_length[0];
    total_high = context->total_length[1];

    ssh_sha512_update(context, &temp, 1);

    in_buffer = context->total_length[0] % 128;
    padding = (128 - (in_buffer + 17) % 128) % 128;

    if (in_buffer > 112)
    {
        memset(&context->u.in[in_buffer], 0, 128 - in_buffer);
        padding -= (128 - in_buffer);
        sha512_transform(context, context->u.in);
        in_buffer = 0;
    }

    /* Change the byte count to bit count. */
    total_high <<= 3;
    total_high += (total_low >> 29);
    total_low <<= 3;

    SSH_PUT_32BIT(context->u.in + 120, total_high);
    SSH_PUT_32BIT(context->u.in + 124, total_low);
    /* Highest bits of length are always zero */
    SSH_PUT_32BIT(context->u.in + 116, 0);
    SSH_PUT_32BIT(context->u.in + 112, 0);

    if ((128 - in_buffer - 16) > 0)
    {
        memset(&context->u.in[in_buffer],
               0, 128 - in_buffer - 16);
    }

    sha512_transform(context, context->u.in);

    /* Copy the internal state to the digest output. */
    for (i = 0; i < num_64bit_words; i++)
    {
        SSH_XUINT64_PUT(context->H[i], digest + i*8);
    }

    memset(context, 0, sizeof(SshSHA512Context));
    return SSH_CRYPTO_OK;
}
示例#4
0
size_t ssh_packet_encode_va(SshBuffer *buffer,
                            SshPacketType type,
                            va_list ap)
{
  size_t payload_size, original_len;
  unsigned char *p;

  /* Save the original length so we can later find where the packet header
     starts. */
  original_len = ssh_buffer_len(buffer);

  /* Construct the packet header with dummy length. */
  ssh_encode_buffer(buffer,
                    SSH_FORMAT_UINT32, (SshUInt32) 0,
                    SSH_FORMAT_CHAR, (unsigned int)type,
                    SSH_FORMAT_END);

  /* Encode the packet payload. */
  payload_size = ssh_encode_va(buffer, ap);

  /* Update the packet header to contain the correct payload size. */
  p = ssh_buffer_ptr(buffer);
  p += original_len;
  SSH_PUT_32BIT(p, payload_size + 1);
  
  /* Return the total number of bytes added to the buffer. */
  return ssh_buffer_len(buffer) - original_len;
}
void
ssh_virtual_adapter_ip_ether_address(SshIpAddr ip, unsigned char *buffer)
{
  memset(buffer, 0, SSH_ETHERH_ADDRLEN);

  if (SSH_IP_IS4(ip))
    {
      buffer[1] = 2;
      SSH_IP4_ENCODE(ip, buffer + 2);
    }
#if defined (WITH_IPV6)
  else
    {
      SshUInt32 value;

      value = SSH_IP6_WORD0_TO_INT(ip);
      value ^= SSH_IP6_WORD1_TO_INT(ip);
      value ^= SSH_IP6_WORD2_TO_INT(ip);
      value ^= SSH_IP6_WORD3_TO_INT(ip);

      buffer[1] = 2;
      SSH_PUT_32BIT(buffer + 2, value);
    }
#endif /* WITH_IPV6 */
}
Boolean ssh_engine_send(SshEngine engine, Boolean locked,
                        Boolean reliable, ...)
{
    va_list ap;
    unsigned char *ucp;
    size_t len;

    if (!locked)
        ssh_kernel_mutex_lock(engine->lock);
    if (!engine->ipm_open)
    {
        if (!locked)
            ssh_kernel_mutex_unlock(engine->lock);
        return FALSE;
    }
    if (!locked)
        ssh_kernel_mutex_unlock(engine->lock);

    /* WARNING: this function is called from ssh_debug callback, which
       means that no debug functions can be called here or we'll end up
       with infinite recursion. */

    /* Construct the final packet to send to ipm. */
    va_start(ap, reliable);
    len = ssh_encode_array_alloc_va(&ucp, ap);
    va_end(ap);
    SSH_ASSERT(len >= 5); /* must have at least len+type */

    /* Update the length of the packet. */
    SSH_PUT_32BIT(ucp, len - 4);

    /* Send and/or queue the packet to the ipm.  This will free the buffer. */
    return (*engine->send)(ucp, len, reliable, engine->machine_context);
}
void
ssh_virtual_adapter_interface_ether_address(SshInterceptorIfnum adapter_ifnum,
                                            unsigned char *buffer)
{
  memset(buffer, 0, SSH_ETHERH_ADDRLEN);
  buffer[1] = 1;
  SSH_PUT_32BIT(buffer + 2, (SshUInt32) adapter_ifnum + 1);
}
示例#8
0
void ssh_channel_open_ssh1_agent_connected(SshStream stream,
                                          void *context)
{
  SshAgentConnection a = (SshAgentConnection)context;
  SshBuffer buffer;
  unsigned char *cp;

  if (stream == NULL)
    {
      SSH_DEBUG(1, ("Connecting to the real agent failed."));
      (*a->completion)(SSH_OPEN_CONNECT_FAILED,
                       NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                       a->context);
      ssh_xfree(a);
      return;
    }

  SSH_DEBUG(5, ("connection to real agent established"));

  /* Increment the number of channels. */
  ssh_common_new_channel(a->common);

  if (a->common->config->ssh_agent_compat == SSH_AGENT_COMPAT_SSH2)
    {
      /* We are required to send a FORWARDING_NOTIFY to the agent to inform it
         that the connection is actually forwarded.  Format that packet now. */
      ssh_buffer_init(&buffer);
      ssh_encode_buffer(&buffer,
                        SSH_FORMAT_DATA, "1234", (size_t)4,
                        SSH_FORMAT_CHAR,
                        (unsigned int) SSH_AGENT_FORWARDING_NOTICE,
                        SSH_FORMAT_UINT32_STR,
                        a->common->server_host_name,
                        strlen(a->common->server_host_name),
                        SSH_FORMAT_UINT32_STR,
                        a->common->remote_ip, strlen(a->common->remote_ip),
                        SSH_FORMAT_UINT32,
                        (SshUInt32) atol(a->common->remote_port),
                        SSH_FORMAT_END);
      cp = ssh_buffer_ptr(&buffer);
      SSH_PUT_32BIT(cp, ssh_buffer_len(&buffer) - 4);

      /* Write the buffer to the channel.  This is a kludge; this assumes that
         we can always write this much to the internal buffers. */
      if (ssh_stream_write(stream, ssh_buffer_ptr(&buffer),
                           ssh_buffer_len(&buffer)) !=
          ssh_buffer_len(&buffer))
        ssh_fatal("ssh_channel_open_agent_connected: kludge failed");
      ssh_buffer_uninit(&buffer);
    }

  /* Create the channel. */
  (*a->completion)(SSH_OPEN_OK, stream, TRUE, TRUE, AGENT_WINDOW_SIZE, NULL, 0,
                   NULL, ssh_channel_ssh1_agent_connection_destroy,
                   (void *)a->common, a->context);
  ssh_xfree(a);
}
示例#9
0
static SshRadiusUrlStatus
ssh_radius_url_add_avp_by_type(SshRadiusUrlAvpSet avp_set,
                               const SshRadiusAvpInfoStruct *avp_info,
                               unsigned char *value,
                               size_t value_length)
{
  long val;
  const SshKeywordStruct *keywords;
  SshUInt8 number_buf[4];

  SSH_PRECOND(avp_set != NULL);
  SSH_PRECOND(avp_info != NULL);

  /* If value == NULL, then choose default value based on value type */

  if (value == NULL)
    return SSH_RADIUS_URL_STATUS_NONE;

  if (avp_info->value_type != SSH_RADIUS_AVP_VALUE_INTEGER)
    return SSH_RADIUS_URL_STATUS_NONE;

  /* Special cases for some attributes */

  switch (avp_info->type)
    {
    case SSH_RADIUS_AVP_FRAMED_PROTOCOL:
      keywords = ssh_radius_framed_protocols;
      break;
    case SSH_RADIUS_AVP_SERVICE_TYPE:
      keywords = ssh_radius_service_types;
      break;
    case SSH_RADIUS_AVP_NAS_PORT_TYPE:
      keywords = ssh_radius_nas_port_types;
      break;
    default:
      keywords = NULL;
      break;
    }

  if (keywords == NULL)
    return SSH_RADIUS_URL_STATUS_NONE;

  val = ssh_find_partial_keyword_number_case_insensitive(keywords,
                                                         ssh_csstr(value),
                                                         NULL);

  if (val == -1)
    return SSH_RADIUS_URL_INVALID_AVP_VALUE;

  SSH_PUT_32BIT(number_buf, val);

  if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                    number_buf, 4) == FALSE)
    return SSH_RADIUS_URL_OUT_OF_MEMORY;

  return SSH_RADIUS_URL_STATUS_SUCCESS;
}
示例#10
0
static int
ssh_appgw_http_marshal_int(SshBuffer buf, int i)
{
  SshUInt32 hi;

  SSH_PUT_32BIT(&hi,i);
  if (ssh_buffer_append(buf,(unsigned char*)&hi,4) == SSH_BUFFER_ERROR)
    return 0;
  return 1;
}
示例#11
0
文件: t-tr.c 项目: AnthraX1/rk
void handler_send_cross(Handler c, unsigned int cross_type,
                        const unsigned char *payload, size_t len)
{
  unsigned char header[5];

  SSH_PUT_32BIT(header, len + 1);
  header[4] = cross_type;
  ssh_buffer_append(&c->outgoing, header, 5);
  ssh_buffer_append(&c->outgoing, payload, len);
}
示例#12
0
文件: sshmalloc.c 项目: AnthraX1/rk
void *ssh_xcalloc(unsigned long nitems, unsigned long size)
{
  void *ptr;
  
  if (nitems == 0)
    nitems = 1;
  if (size == 0)
    size = 1;

  if (size * nitems > XMALLOC_MAX_SIZE)
    ssh_fatal("ssh_xcalloc: allocation too large (allocating %ld*%ld bytes)",
          size, nitems);

#ifdef SSH_DEBUG_MALLOC
  ptr = (void *)malloc(((size_t) nitems * (size_t) size) +
                       SSH_DEBUG_MALLOC_SIZE_BEFORE +
                       SSH_DEBUG_MALLOC_SIZE_AFTER);

  if (ptr == NULL)
    ssh_fatal("ssh_xcalloc: out of memory (allocating %ld*%ld bytes)",
          nitems, size);

  memset((unsigned char *) ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE,
         0, (nitems * size));
  SSH_PUT_32BIT(ptr, (size * nitems));
  SSH_PUT_32BIT((unsigned char *) ptr + 4, SSH_DEBUG_MALLOC_MAGIC_IN_USE);
  SSH_PUT_32BIT((unsigned char *) ptr + (size * nitems) +
                SSH_DEBUG_MALLOC_SIZE_BEFORE,
                SSH_DEBUG_MALLOC_MAGIC_AFTER);
  ptr = (unsigned char *) ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE;
#else /* SSH_DEBUG_MALLOC */
  ptr = (void *)calloc((size_t) nitems, (size_t) size);
  
  if (ptr == NULL)
    ssh_fatal("ssh_xcalloc: out of memory (allocating %ld*%ld bytes)",
          nitems, size);
#endif /* SSH_DEBUG_MALLOC */
  return ptr;
}
示例#13
0
static int
ssh_appgw_http_marshal_data(SshBuffer buf, const unsigned char *str,
                            size_t len)
{
  SshUInt32 i;

  if (str == NULL)
    {
      SSH_PUT_32BIT(&i,0);
      if (ssh_buffer_append(buf, (unsigned char *)&i, 4) == SSH_BUFFER_ERROR)
        return 0;
    }
  else
    {
      SSH_PUT_32BIT(&i,len);
      if (ssh_buffer_append(buf, (unsigned char*)&i, 4) == SSH_BUFFER_ERROR)
        return 0;

      if (ssh_buffer_append(buf, (unsigned char *)str,len) == SSH_BUFFER_ERROR)
        return 0;
    }
  return 1;
}
示例#14
0
文件: sha.c 项目: AnthraX1/rk
void ssh_sha_final(void *c, unsigned char *digest)
{
  SshSHAContext *context = c;
  int padding;
  unsigned char temp = 0x80;
  unsigned int in_buffer; 
  SshUInt32 total_low, total_high;

  total_low = context->total_length[0];
  total_high = context->total_length[1];
  
  ssh_sha_update(context, &temp, 1);

  in_buffer = context->total_length[0] % 64;
  padding = (64 - (in_buffer + 9) % 64) % 64;

  if (in_buffer > 56)
    {
      memset(&context->in[in_buffer], 0, 64 - in_buffer);
      padding -= (64 - in_buffer);
      sha_transform(context, context->in);
      in_buffer = 0;
    }

  /* change the byte count to bits count */
  total_high <<= 3;
  total_high += (total_low >> 29);
  total_low <<= 3;

  SSH_PUT_32BIT(context->in + 56, total_high);
  SSH_PUT_32BIT(context->in + 60, total_low);

  if ((64 - in_buffer - 8) > 0)
    {
      memset(&context->in[in_buffer],
             0, 64 - in_buffer - 8);
    }

  sha_transform(context, context->in);

  SSH_PUT_32BIT(digest,      context->A);
  SSH_PUT_32BIT(digest + 4,  context->B);
  SSH_PUT_32BIT(digest + 8,  context->C);
  SSH_PUT_32BIT(digest + 12, context->D);
  SSH_PUT_32BIT(digest + 16, context->E);

  memset(context, 0, sizeof(SshSHAContext));
}
示例#15
0
文件: sshmpaux.c 项目: AnthraX1/rk
void mp_linearize_msb_first(unsigned char *buf, unsigned int len, 
                            SshInt *value)
{
  unsigned int i;
  SshInt aux;
  ssh_mp_init_set(&aux, value);
  for (i = len; i >= 4; i -= 4)
    {
      unsigned long limb = ssh_mp_get_ui(&aux);
      SSH_PUT_32BIT(buf + i - 4, limb);
      ssh_mp_div_2exp(&aux, &aux, 32);
    }
  for (; i > 0; i--)
    {
      buf[i - 1] = ssh_mp_get_ui(&aux);
      ssh_mp_div_2exp(&aux, &aux, 8);
    }           
  ssh_mp_clear(&aux);
}
示例#16
0
文件: sshmpaux.c 项目: AnthraX1/rk
void ssh_mp_to_buf(unsigned char *cp, size_t len, const SshInt *x)
{
  unsigned long limb;
  size_t i;
  SshInt aux;
  
  ssh_mp_init_set(&aux, x);

  for (i = len; i >= 4; i -= 4)
    {
      limb = ssh_mp_get_ui(&aux);
      SSH_PUT_32BIT(cp + i - 4, limb);
      ssh_mp_div_2exp(&aux, &aux, 32);
    }
  for (;i > 0; i--)
    {
      cp[i - 1] = (unsigned char)(ssh_mp_get_ui(&aux) & 0xff);
      ssh_mp_div_2exp(&aux, &aux, 8);
    }

  ssh_mp_clear(&aux);
}
示例#17
0
SshOperationHandle
d_spd_notify_request(SshSADHandle sad_handle,
		     SshIkev2ExchangeData ed,
		     SshIkev2SpdNotifyCB reply_callback,
		     void *reply_callback_context)
{
  SshIkev2Error status = SSH_IKEV2_ERROR_OK;
  SshIkev2ProtocolIdentifiers protocol = SSH_IKEV2_PROTOCOL_ID_IKE;
  unsigned char *spi = NULL, *notify_data = NULL;
  size_t spi_size = 0, notify_data_size = 0;
  SshIkev2NotifyMessageType notify_type = SSH_IKEV2_NOTIFY_RESERVED;

  SSH_DEBUG(SSH_D_HIGHSTART, ("Enter SA %p ED %p", ed->ike_sa, ed));

#if 1
  if (!opt_client &&
      (ed->state == SSH_IKEV2_STATE_REKEY_IKE
       || ((ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR)
	   && ed->state == SSH_IKEV2_STATE_IKE_AUTH_1ST)
#ifdef SSH_IKEV2_MULTIPLE_AUTH
       || (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR)
           && ed->ike_ed
           && !(ed->ike_ed->second_eap_auth)
	   && ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST)
       || (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR)
           && ed->ike_ed
           && ed->ike_ed->second_eap_auth
           && ed->ike_ed->first_auth_done
           && ed->ike_ed->eap_state == SSH_IKEV2_EAP_DONE
	   && ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST)
#else /* SSH_IKEV2_MULTIPLE_AUTH */
       || (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR)
	   && ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST)
#endif /* SSH_IKEV2_MULTIPLE_AUTH */
       )
      )
    {
      unsigned char buffer[4];

      SSH_PUT_32BIT(buffer, 2);
      (*reply_callback)(SSH_IKEV2_ERROR_OK,
			0, NULL, 0,
			SSH_IKEV2_NOTIFY_SET_WINDOW_SIZE,
			buffer, sizeof(buffer),
			reply_callback_context);
    }
#endif
  
#ifdef SSHDIST_IKE_MOBIKE
  /* Responder indicates MOBIKE supported in the IKE_AUTH exchange if MOBIKE 
     is locally supported and a MOBIKE supported notify was received from 
     the initiator. */
  if (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) &&
      (ed->state == SSH_IKEV2_STATE_IKE_AUTH_LAST) && 
      mobike_supported && peer_supports_mobike)
    {
      SSH_DEBUG(SSH_D_MIDOK, ("Indicating support for MOBIKE"));
      (*reply_callback)(SSH_IKEV2_ERROR_OK,
			0, NULL, 0,
			SSH_IKEV2_NOTIFY_MOBIKE_SUPPORTED,
			NULL, 0,
			reply_callback_context);
    }
#endif /* SSHDIST_IKE_MOBIKE */

#ifdef SSH_IKEV2_MULTIPLE_AUTH
  if (!(ed->ike_sa->flags & SSH_IKEV2_IKE_SA_FLAGS_INITIATOR) &&
      (ed->state == SSH_IKEV2_STATE_IKE_INIT_SA) && 
      use_multiple_auth)
    {
      SSH_DEBUG(SSH_D_MIDOK, ("Indicating support for multiple "
                              "authentications"));
      (*reply_callback)(SSH_IKEV2_ERROR_OK,
			0, NULL, 0,
			SSH_IKEV2_NOTIFY_MULTIPLE_AUTH_SUPPORTED,
			NULL, 0,
			reply_callback_context);
    }
#endif /* SSH_IKEV2_MULTIPLE_AUTH */


  (*reply_callback)(status,
		    protocol, spi, spi_size,
		    notify_type, notify_data, notify_data_size,
		    reply_callback_context);

  return NULL;
}
void
ikev2_fb_spd_select_qm_sa_cb(SshIkev2Error error_code,
			     int ikev2_proposal_index,
			     SshIkev2PayloadTransform
			     selected_transforms[SSH_IKEV2_TRANSFORM_TYPE_MAX],
			     void *context)
{
  SshIkev2FbNegotiation neg = context;
  SshIkeIpsecSelectedSAIndexes selected = NULL;
  SshIkePayloadSA sa;
  int ikev1_proposal_index, ikev1_ipsec_transform_index;
  int ikev1_ipcomp_transform_index, i, iproto;

  SSH_IKEV2_FB_V2_COMPLETE_CALL(neg);

  sa = &neg->sa_table_in[0]->pl.sa;

  if (error_code != SSH_IKEV2_ERROR_OK)
    {
      SSH_DEBUG(SSH_D_FAIL, ("IKEv2 SA select failed with error %s",
			     ssh_ikev2_error_to_string(error_code)));
      goto error;
    }







  /* Check if ISAKMP library has freed the qm negotiation. */
  if (neg->qm_info == NULL)
    {
      SSH_DEBUG(SSH_D_FAIL, ("QM negotiation has disappeared"));
      neg->ike_error = SSH_IKEV2_ERROR_INVALID_ARGUMENT;
      goto error;
    }

  if (selected_transforms == NULL)
    {
      SSH_DEBUG(SSH_D_FAIL, ("No IPSec SA transforms selected"));
      goto error;
    }

  /* Store information on the selected SA to the IPSec exchange data. */
  for (i = 0; i < SSH_IKEV2_TRANSFORM_TYPE_MAX; i++)
    {
      neg->ed->ipsec_ed->ipsec_sa_transforms[i] = selected_transforms[i];
    }

  neg->ed->ipsec_ed->ipsec_sa_protocol =
    neg->sav2->protocol_id[ikev2_proposal_index];

  /* Set the inbound SPI to the IPSec exchange data */
  neg->ed->ipsec_ed->spi_inbound = neg->inbound_spi;

  SSH_DEBUG(SSH_D_LOWOK, ("Inbound SPI %lx",
			  (unsigned long) neg->inbound_spi));

  SSH_ASSERT(neg->number_of_sas_in == 1);
  selected = ssh_calloc(neg->number_of_sas_in, sizeof(*selected));
  if (selected == NULL)
    goto error;

  /* Check to see which proposal and ESP/AH/IPComp transform index 
     was selected. */
  if (!ikev2_fb_select_ipsec_transform_index(selected_transforms,
					     neg->qm_info->negotiation,
					     sa,
					     neg->ipcomp_proposals,
					     neg->ipcomp_algs[0],
					     &ikev1_proposal_index,
					     &ikev1_ipsec_transform_index,
					     &ikev1_ipcomp_transform_index))
    {
    error:
      SSH_DEBUG(SSH_D_FAIL,
		("SA selection failed, no matching proposal (neg %p)", neg));
      ikev2_fb_free_sa_indexes(selected, neg->number_of_sas_in);
      neg->selected = NULL;
      SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread);
      return;
    }
  selected[0].proposal_index = ikev1_proposal_index;

  SSH_DEBUG(SSH_D_LOWOK, 
	    ("Selected proposal indices are v2=%d, v1=%d num protocols is %d",
	     ikev2_proposal_index, ikev1_proposal_index,  
	     sa->proposals[ikev1_proposal_index].number_of_protocols));
  
  selected[0].number_of_protocols
    = sa->proposals[ikev1_proposal_index].number_of_protocols;
  selected[0].transform_indexes
    = ssh_calloc(selected[0].number_of_protocols, sizeof(int));
  selected[0].spi_sizes
    = ssh_calloc(selected[0].number_of_protocols, sizeof(size_t));
  selected[0].spis
    = ssh_calloc(selected[0].number_of_protocols,
		 sizeof(unsigned char *));

  if (selected[0].transform_indexes == NULL ||
      selected[0].spi_sizes == NULL ||
      selected[0].spis == NULL)
    goto error;

  for (iproto = 0; iproto < selected[0].number_of_protocols; iproto++)
    {
      SshIkePayloadPProtocol proto = 
	&sa->proposals[ikev1_proposal_index].protocols[iproto];
      
      if ((selected->spis[iproto] = ssh_malloc(4)) == NULL)
	goto error;

      switch (proto->protocol_id)
	{
	case SSH_IKE_PROTOCOL_IPCOMP:
	  selected->spi_sizes[iproto] = 2;
	  SSH_PUT_16BIT(selected->spis[iproto], neg->ipcomp_cpi_in);

	  selected[0].transform_indexes[iproto] = ikev1_ipcomp_transform_index;
	  break;
	default:
	  selected->spi_sizes[iproto] = 4;
	  SSH_PUT_32BIT(selected->spis[iproto], neg->inbound_spi);

	  /* Check the proposed lifetimes against that of our policy to see
	     whether we should send a responder lifetime notification */
	  if (ikev2_fb_check_ipsec_responder_lifetimes(neg->ed,
						       neg->sa_life_seconds,
						       neg->sa_life_kbytes))
	    {
	      /* Let's send a responder lifetime notify. */
	      SSH_DEBUG(SSH_D_NICETOKNOW,
			("Sending a responder lifetime notification: "
			 "life_sec=%lu, life_kb=%lu",
			 neg->ed->ipsec_ed->sa_life_seconds,
			 neg->ed->ipsec_ed->sa_life_kbytes));
	      selected[0].expire_secs = neg->ed->ipsec_ed->sa_life_seconds;
	      selected[0].expire_kb = neg->ed->ipsec_ed->sa_life_kbytes;
	    }
	  selected[0].transform_indexes[iproto] = ikev1_ipsec_transform_index;
	}
    }

  neg->selected = selected;

  SSH_FSM_CONTINUE_AFTER_CALLBACK(neg->sub_thread);
  return;
}
示例#19
0
文件: sshmalloc.c 项目: AnthraX1/rk
void *ssh_xrealloc(void *ptr, unsigned long new_size)
{
  void *new_ptr;

  if (ptr == NULL)
    return ssh_xmalloc(new_size);

  if (new_size > XMALLOC_MAX_SIZE)
    ssh_fatal("ssh_xrealloc: allocation too large (allocating %ld bytes)",
              (long)new_size);
  
  if (new_size == 0)
    new_size = 1;
#ifdef SSH_DEBUG_MALLOC
  if (SSH_GET_32BIT((unsigned char *) ptr - 4) !=
      SSH_DEBUG_MALLOC_MAGIC_IN_USE)
    {
      if (SSH_GET_32BIT((unsigned char *) ptr - 4) ==
          SSH_DEBUG_MALLOC_MAGIC_FREED)
        ssh_fatal("Reallocating block that is already freed");
      ssh_fatal("Reallocating block that is either not mallocated, or whose magic number before the object was overwritten");
    }
  else
    {
      unsigned long old_size;

      old_size = SSH_GET_32BIT((unsigned char *) ptr -
                               SSH_DEBUG_MALLOC_SIZE_BEFORE);
      if (SSH_GET_32BIT((unsigned char *) ptr + old_size) !=
          SSH_DEBUG_MALLOC_MAGIC_AFTER)
        ssh_fatal("Reallocating block whose magic number after the object was overwritten");

      /* Mark the old block freed */
      SSH_PUT_32BIT((unsigned char *) ptr - 4, SSH_DEBUG_MALLOC_MAGIC_FREED);
      SSH_PUT_32BIT((unsigned char *) ptr + old_size,
                    SSH_DEBUG_MALLOC_MAGIC_FREED);

      new_ptr = (void *)realloc((unsigned char *) ptr -
                                SSH_DEBUG_MALLOC_SIZE_BEFORE,
                                (size_t) new_size +
                                SSH_DEBUG_MALLOC_SIZE_BEFORE +
                                SSH_DEBUG_MALLOC_SIZE_AFTER);
      if (new_ptr == NULL)
        ssh_fatal("ssh_xrealloc: out of memory (new_size %ld bytes)",
                  (long)new_size);

      SSH_PUT_32BIT(new_ptr, new_size);
      SSH_PUT_32BIT((unsigned char *) new_ptr + 4,
                    SSH_DEBUG_MALLOC_MAGIC_IN_USE);
      SSH_PUT_32BIT((unsigned char *) new_ptr + new_size +
                    SSH_DEBUG_MALLOC_SIZE_BEFORE,
                    SSH_DEBUG_MALLOC_MAGIC_AFTER);
      new_ptr = (unsigned char *) new_ptr + SSH_DEBUG_MALLOC_SIZE_BEFORE;
    }
#else /* SSH_DEBUG_MALLOC */
  new_ptr = (void *)realloc(ptr, (size_t) new_size);
  if (new_ptr == NULL)
    ssh_fatal("ssh_xrealloc: out of memory (new_size %ld bytes)",
              (long)new_size);
#endif /* SSH_DEBUG_MALLOC */
  return new_ptr;
}
示例#20
0
static SshRadiusUrlStatus
ssh_radius_url_add_avp(SshRadiusUrlAvpSet avp_set,
                       const SshRadiusAvpInfoStruct *avp_info,
                       unsigned char *value,
                       size_t value_len)
{
  unsigned long val;
  SshRadiusUrlStatus url_status;

  SSH_PRECOND(avp_set != NULL);
  SSH_PRECOND(avp_info != NULL);

  /* Try to allow for "magic keyword" substituion for selected
     parameter values. */

  if (avp_info->value_type == SSH_RADIUS_AVP_VALUE_INTEGER)
    {
      url_status =
        ssh_radius_url_add_avp_by_type(avp_set, avp_info, value, value_len);

      if (url_status != SSH_RADIUS_URL_STATUS_NONE)
        return url_status;
    }

  /* Perform setting based on type */

  switch (avp_info->value_type)
    {
    case SSH_RADIUS_AVP_VALUE_TEXT:
      if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                        (SshUInt8 *) value,
                                        (SshUInt8)value_len)
          == FALSE)
        return SSH_RADIUS_URL_OUT_OF_MEMORY;
      break;

    case SSH_RADIUS_AVP_VALUE_TAG_INTEGER:
    case SSH_RADIUS_AVP_VALUE_TAG_STRING:
    case SSH_RADIUS_AVP_VALUE_IPV6_ADDRESS:
      SSH_DEBUG(SSH_D_FAIL,("TAG and IPV6 attributes not yet supported"));
      return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE;
      break;

    case SSH_RADIUS_AVP_VALUE_TIME:
    case SSH_RADIUS_AVP_VALUE_INTEGER:
      {
        SshUInt8 number_buf[4];
        val = (value != NULL ? ssh_ustrtol(value, NULL, 0) : 0);
        SSH_PUT_32BIT(number_buf, val);

        if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                          number_buf, 4) == FALSE)
          return SSH_RADIUS_URL_OUT_OF_MEMORY;
      }
      break;

      /* Convert IPv4 address to 32-bit integer */
    case SSH_RADIUS_AVP_VALUE_ADDRESS:
      {
        SshIpAddrStruct ip_addr;
        SshUInt8 number_buf[4];

        if (value == NULL)
          return SSH_RADIUS_URL_INVALID_AVP_VALUE;

        if (ssh_ipaddr_parse(&ip_addr, value) == FALSE)
          return SSH_RADIUS_URL_INVALID_AVP_VALUE;

        if (SSH_IP_IS4(&ip_addr) == FALSE)
          return SSH_RADIUS_URL_INVALID_AVP_VALUE;

        SSH_PUT_32BIT(number_buf, SSH_IP4_TO_INT(&ip_addr));

        if (ssh_radius_url_set_avpset_avp(avp_set, avp_info->type,
                                          number_buf, 4) == FALSE)
          return SSH_RADIUS_URL_OUT_OF_MEMORY;
      }
      break;

    default:
      SSH_DEBUG(SSH_D_FAIL,
                ("Unknown RADIUS attribute value type %d!",
                 avp_info->value_type));
      return SSH_RADIUS_URL_UNKNOWN_AVP_TYPE;
    }

  return SSH_RADIUS_URL_STATUS_SUCCESS;
}
示例#21
0
void test_variant(const char *postfix)
{
  SshCipher cipher;
  SshCryptoStatus status;
  unsigned char *iv, *key, *src, *plain;
  unsigned char *aad, *ciph, *auth_tag, digest_len;
  size_t key_len, iv_len, aad_len, src_len, src_len_block, ciph_len, 
    auth_tag_len, orig_len;
  unsigned char *orig;
  unsigned char iv_buf[16], *digest;
  unsigned char *ciph_name;
  size_t blocklen;
  int i;

  for (i = 0; combined_test_vectors[i].key != NULL; i++)
    {
      hex_string_to_buf(combined_test_vectors[i].key, &key, &key_len);
      hex_string_to_buf(combined_test_vectors[i].iv, &iv, &iv_len);
      hex_string_to_buf(combined_test_vectors[i].aad, &aad, &aad_len);
      hex_string_to_buf(combined_test_vectors[i].plaintext, &plain, &src_len);
      hex_string_to_buf(combined_test_vectors[i].plaintext, &src, &src_len);
      orig = ssh_xmemdup(src, src_len);
      orig_len = src_len;
      hex_string_to_buf(combined_test_vectors[i].ciphertext, &ciph, &ciph_len);
      hex_string_to_buf(combined_test_vectors[i].auth_tag, &auth_tag, 
			&auth_tag_len);
      digest = NULL;

      ciph_name = ssh_string_concat_2(combined_test_vectors[i].name, postfix);
      SSH_ASSERT(ciph_name);
      status = ssh_cipher_allocate(ciph_name,
				   key, key_len, TRUE, &cipher);
      if (status != SSH_CRYPTO_OK)
	{ 
	  fprintf(stderr, "Cannot allocate cipher \"%s\" (status is %s)\n", 
		  ciph_name, ssh_crypto_status_message(status));
	  exit(1);
	}




      if (iv_len != 12)
	{
	  SSH_DEBUG(1, ("Skipping test %d with IV not equal to 12 bytes", i));
	  goto dealloc_and_continue;
	}

      if (!ssh_cipher_is_auth_cipher(combined_test_vectors[i].name))
	{
	  SSH_DEBUG(1, ("Skipping test %d with non-auth cipher", i));
	  goto dealloc_and_continue;
	}

      digest_len = 
	ssh_cipher_auth_digest_length(combined_test_vectors[i].name);
      digest = ssh_xmalloc(digest_len);

      ssh_cipher_auth_reset(cipher);
      
      if (aad != NULL)
	ssh_cipher_auth_update(cipher, aad, aad_len);
      



      SSH_ASSERT(iv_len == 12);
      memcpy(iv_buf, iv, 12);
      SSH_PUT_32BIT(iv_buf + 12, 1);
      
      status = ssh_cipher_set_iv(cipher, iv_buf);
      SSH_VERIFY(status == SSH_CRYPTO_OK);

      blocklen = ssh_cipher_get_block_length(combined_test_vectors[i].name);

      src_len_block = src_len - (src_len % blocklen);
      status = ssh_cipher_transform(cipher, src, src, src_len_block);
	
      /* Process remaining bytes if test was not multiple of block size. */
      if (status == SSH_CRYPTO_OK && (src_len > src_len_block))
	{
	  status = ssh_cipher_transform_remaining(cipher, 
						  src + src_len_block,
						  src + src_len_block,
						  src_len - src_len_block);
	}

      SSH_VERIFY(status == SSH_CRYPTO_OK);
      
      SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK);
      
      if (src_len != ciph_len || memcmp(src, ciph, src_len))
	{
	  fprintf(stderr, 
		  "Test vectors ciphertext (ciph=%s) do not agree test=%d\n", 
		  ciph_name, i);
	  SSH_DEBUG_HEXDUMP(1, ("cipher computed"), src, src_len);
	  SSH_DEBUG_HEXDUMP(1, ("cipher expected"), ciph, ciph_len);
	  exit(1);
	}

      if (digest_len != auth_tag_len ||
	  memcmp(digest, auth_tag, digest_len)) 
	{
	  fprintf(stderr, 
		  "Test vectors digest (ciph=%s) do not agree test=%d\n", 
		  ciph_name, i);
	  SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len);
	  SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len);
	  exit(1);
	}
      
      /* Redo operation, now decryption */
      ssh_cipher_free(cipher);

      status = ssh_cipher_allocate(ciph_name,
				   key, key_len, FALSE, &cipher);
      if (status != SSH_CRYPTO_OK)
	{ 
	  fprintf(stderr, "Cannot allocate cipher \"%s\" (status is %s)\n", 
		  ciph_name, ssh_crypto_status_message(status));
	  exit(1);
	}

      SSH_ASSERT(digest_len == 
		 ssh_cipher_auth_digest_length(combined_test_vectors[i].name));

      ssh_cipher_auth_reset(cipher);
      
      if (aad != NULL)
	ssh_cipher_auth_update(cipher, aad, aad_len);
      



      SSH_ASSERT(iv_len == 12);
      memcpy(iv_buf, iv, 12);
      SSH_PUT_32BIT(iv_buf + 12, 1);
      
      status = ssh_cipher_set_iv(cipher, iv_buf);
      SSH_VERIFY(status == SSH_CRYPTO_OK);

      src_len_block = src_len - (src_len % blocklen);
      status = ssh_cipher_transform(cipher, orig, src, src_len_block);
	
      /* Process remaining bytes if test was not multiple of block size. */
      if (status == SSH_CRYPTO_OK && (src_len > src_len_block))
	{
	  status = ssh_cipher_transform_remaining(cipher, 
						  orig + src_len_block,
						  src + src_len_block,
						  src_len - src_len_block);
	}

      SSH_VERIFY(status == SSH_CRYPTO_OK);
      
      SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK);
      
      if (orig_len != ciph_len || memcmp(orig, plain, src_len))
	{
	  fprintf(stderr, 
		  "Test vectors plaintext (ciph=%s) do not agree test=%d\n", 
		  ciph_name, i);
	  SSH_DEBUG_HEXDUMP(1, ("plain computed"), orig, orig_len);
	  SSH_DEBUG_HEXDUMP(1, ("plain expected"), plain, ciph_len);
	  exit(1);
	}

      if (digest_len != auth_tag_len ||
	  memcmp(digest, auth_tag, digest_len)) 
	{
	  fprintf(stderr, 
		  "Test vectors digest (ciph=%s) do not agree test=%d\n", 
		  ciph_name, i);
	  SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len);
	  SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len);
	  exit(1);
	}
      
      /* Reset cipher and redo decryption */
      ssh_cipher_auth_reset(cipher);

      if (aad != NULL)
	ssh_cipher_auth_update(cipher, aad, aad_len);
      
      status = ssh_cipher_set_iv(cipher, iv_buf);
      SSH_VERIFY(status == SSH_CRYPTO_OK);

      status = ssh_cipher_transform(cipher, orig, src, src_len_block);
	
      /* Process remaining bytes if test was not multiple of block size. */
      if (status == SSH_CRYPTO_OK && (src_len > src_len_block))
	{
	  status = ssh_cipher_transform_remaining(cipher, 
						  orig + src_len_block,
						  src + src_len_block,
						  src_len - src_len_block);
	}

      SSH_VERIFY(status == SSH_CRYPTO_OK);
      
      SSH_VERIFY(ssh_cipher_auth_final(cipher, digest) == SSH_CRYPTO_OK);
      
      if (orig_len != ciph_len || memcmp(orig, plain, src_len))
	{
	  fprintf(stderr, 
		  "Test vectors plaintext (ciph=%s) do not agree test=%d\n", 
		  ciph_name, i);
	  SSH_DEBUG_HEXDUMP(1, ("plain computed"), orig, orig_len);
	  SSH_DEBUG_HEXDUMP(1, ("plain expected"), plain, ciph_len);
	  exit(1);
	}

      if (digest_len != auth_tag_len ||
	  memcmp(digest, auth_tag, digest_len)) 
	{
	  fprintf(stderr, 
		  "Test vectors digest (ciph=%s) do not agree test=%d\n", 
		  ciph_name, i);
	  SSH_DEBUG_HEXDUMP(1, ("digest computed"), digest, digest_len);
	  SSH_DEBUG_HEXDUMP(1, ("digest expected"), auth_tag, auth_tag_len);
	  exit(1);
	}
      
      SSH_DEBUG(2, ("Test %d (cipher=`%s') successful", i, 
		    combined_test_vectors[i].name));

    dealloc_and_continue:
      if (cipher) 
	ssh_cipher_free(cipher);

      ssh_xfree(digest);
      ssh_xfree(key); 
      ssh_xfree(iv);  
      ssh_xfree(aad);
      ssh_xfree(src); 
      ssh_xfree(orig); 
      ssh_xfree(plain); 
      ssh_xfree(ciph); 
      ssh_xfree(auth_tag);
      ssh_xfree(ciph_name);
    }

}
示例#22
0
/* Generate stateless cookie based on the secret, nonce,
   spi_i and ip-address. */
SshIkev2Error ikev2_generate_cookie(SshIkev2Packet packet,
				    SshIkev2Sa ike_sa,
				    unsigned char *notify_data,
				    size_t notify_len)
{
  SshCryptoStatus status;
  unsigned char buffer[16];
  SshMac mac;
  size_t len;

  SSH_DEBUG(SSH_D_LOWOK, ("Starting cookie generation for SA %p", ike_sa));
  packet->ed->ike_ed->cookie_len = 4 +
    ssh_mac_length(IKEV2_COOKIE_MAC_ALGORITHM);
  packet->ed->ike_ed->cookie =
    ssh_obstack_alloc(packet->ed->obstack,
		      packet->ed->ike_ed->cookie_len);
  if (packet->ed->ike_ed->cookie == NULL)
    {
      SSH_DEBUG(SSH_D_ERROR, ("Error: Out of memory allocating cookie"));
      return SSH_IKEV2_ERROR_OUT_OF_MEMORY;
    }

  if (notify_len > 4 && notify_data != NULL &&
      SSH_GET_32BIT(notify_data) ==
      ike_sa->server->context->cookie_version_number - 1)
    {
      ike_sa->server->context->cookie_secret_use_counter_prev++;
      SSH_PUT_32BIT(packet->ed->ike_ed->cookie,
		    ike_sa->server->context->cookie_version_number - 1);
      status = ssh_mac_allocate(IKEV2_COOKIE_MAC_ALGORITHM,
				ike_sa->server->context->cookie_secret_prev,
				IKEV2_COOKIE_SECRET_LEN, &mac);
    }
  else
    {
      ike_sa->server->context->cookie_secret_use_counter++;
      SSH_PUT_32BIT(packet->ed->ike_ed->cookie,
		    ike_sa->server->context->cookie_version_number);
      status = ssh_mac_allocate(IKEV2_COOKIE_MAC_ALGORITHM,
				ike_sa->server->context->cookie_secret,
				IKEV2_COOKIE_SECRET_LEN, &mac);
    }
  if (status != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(SSH_D_ERROR, ("Error: ssh_mac_allocate(%s) failed: %s",
			      IKEV2_COOKIE_MAC_ALGORITHM,
			      ssh_crypto_status_message(status)));
      return SSH_IKEV2_ERROR_OUT_OF_MEMORY;
    }

  ssh_mac_reset(mac);
  ssh_mac_update(mac, packet->ed->nonce->nonce_data,
		 packet->ed->nonce->nonce_size);
  SSH_IP_ENCODE(packet->remote_ip, buffer, len);
  ssh_mac_update(mac, buffer, len);
  ssh_mac_update(mac, packet->ike_spi_i, 8);
  status = ssh_mac_final(mac, packet->ed->ike_ed->cookie + 4);
  ssh_mac_free(mac);
  if (status != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(SSH_D_ERROR, ("Error: ssh_mac_final(%s) failed: %s",
			      IKEV2_COOKIE_MAC_ALGORITHM,
			      ssh_crypto_status_message(status)));
      return SSH_IKEV2_ERROR_CRYPTO_FAIL;
    }
#ifdef SSH_IKEV2_CRYPTO_KEY_DEBUG
  SSH_DEBUG_HEXDUMP(SSH_D_DATADUMP,
		    ("Cookie generated"),
		    packet->ed->ike_ed->cookie,
		    packet->ed->ike_ed->cookie_len);
#endif /* SSH_IKEV2_CRYPTO_KEY_DEBUG */
  return SSH_IKEV2_ERROR_OK;
}
SshTlsTransStatus ssh_tls_trans_write_client_hello(SshTlsProtocolState s)
{
  SshTlsCipherSuite tab[SSH_TLS_NUM_CIPHERSUITES];
  SshTlsCipherSuite *suites_to_send;
  SshTlsCipherSuiteDetailsStruct details;
  int number_suites;
  int contents_len;
  unsigned char tempbuf[2];
  int i;

  s->kex.flags |= SSH_TLS_KEX_NEW_SESSION; /* Initially. */

  if (s->conf.preferred_suites != NULL)
    {

      /* If a preference list has been given, check that the
         preferences are sound w.r.t. the protocol flags given in the
         configuration. */

      SshTlsCipherSuite *tmp;

      SSH_DEBUG(6, ("Got a preference list."));

      number_suites = 0;
      tmp = s->conf.preferred_suites;
      while (*tmp != SSH_TLS_NO_CIPHERSUITE)
        {
          ssh_tls_get_ciphersuite_details(*tmp, &details);
          if (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS)))
            {
	      return SSH_TLS_TRANS_FAILED;
            }
          if (details.cipher == SSH_TLS_CIPH_NULL &&
              (!(s->conf.flags & SSH_TLS_NULLCIPHER)))
            {
	      return SSH_TLS_TRANS_FAILED;
            }
          tmp++; number_suites++;
        }
      suites_to_send = s->conf.preferred_suites;
    }
  else
    {
      /* Otherwise construct a list containing all those ciphersuites
         that are supported by our implementation and that can be used
         according to the protocol configuration flags. */

      number_suites = 0;

      for (i = SSH_TLS_RSA_WITH_NULL_MD5; i < SSH_TLS_MAX_CIPHERSUITE; i++)
        {
          ssh_tls_get_ciphersuite_details(i, &details);

          SSH_DEBUG(7, ("Check if suite %d can be supported.", i));

	  if ((details.kex_method == SSH_TLS_UNKNOWN_SUITE)
	       || !(ssh_tls_supported_suite(s->conf.flags, 
					    (SshTlsCipherSuite) i)))
	     continue;

          SSH_DEBUG(7, ("Null? %d  Crippled? %d  RC2? %d  RSA? %d  "
                        "Nosign? %d",
                        (details.cipher == SSH_TLS_CIPH_NULL),
                        (details.crippled),
                        (details.cipher == SSH_TLS_CIPH_RC2),
                        (details.kex_method == SSH_TLS_KEX_RSA),
                        (details.signature_method == SSH_TLS_SIGN_NONE)));

          if ((details.cipher == SSH_TLS_CIPH_NULL &&
               (!(s->conf.flags & SSH_TLS_NULLCIPHER)))
              || (details.crippled && (!(s->conf.flags & SSH_TLS_WEAKCIPHERS)))
              || (details.cipher == SSH_TLS_CIPH_RC2)
              || (details.kex_method != SSH_TLS_KEX_RSA)
              || (details.signature_method != SSH_TLS_SIGN_NONE))
            continue;

          SSH_DEBUG(7, ("Adding the cipher suite %d.", i));

          tab[number_suites++] = i;
        }
      suites_to_send = tab;
    }

  /* Now we can calculate the length of the packet. */

  /* Protocol version 2 bytes, random value 32 bytes,
     session ID 1 + N bytes, ciphersuites list 2 bytes (length)
     plus number_suites * 2 bytes, and 2 bytes for the single
     compression method (no compression) we support. */

  contents_len = 2 + 32 + 1 + s->kex.id_len + 2 + number_suites * 2 + 2;

  /* Initialize the handshake history buffer now. */
  SSH_ASSERT(s->kex.handshake_history == NULL);
  s->kex.handshake_history = ssh_buffer_allocate();

  if (s->kex.handshake_history == NULL)
    return SSH_TLS_TRANS_FAILED;

  ssh_tls_make_hs_header(s, SSH_TLS_HS_CLIENT_HELLO, contents_len);

  /* Write the highest protocol version or that of a hopefully-resumed
     session. */

  tempbuf[0] = s->kex.client_version.major;
  tempbuf[1] = s->kex.client_version.minor;

  ssh_tls_add_to_kex_packet(s, tempbuf, 2);

  /* Write unix time. */
  SSH_PUT_32BIT(s->kex.client_random, (SshUInt32)ssh_time());

  /* Write 28 random bytes. */
  for (i = 4; i < 32; i++)
    {
      s->kex.client_random[i]
        = ssh_random_get_byte();
    }
  ssh_tls_add_to_kex_packet(s, s->kex.client_random, 32);

  /* Write the requested session identifier. */
  tempbuf[0] = s->kex.id_len;
  ssh_tls_add_to_kex_packet(s, &tempbuf[0], 1);
  if (s->kex.id_len > 0)
    {
      ssh_tls_add_to_kex_packet(s, s->kex.session_id, s->kex.id_len);
    }

  /* Write the cipher suites. */
  SSH_PUT_16BIT(tempbuf, number_suites * 2);
  ssh_tls_add_to_kex_packet(s, tempbuf, 2);

  for (i = 0; i < number_suites; i++)
    {
      SSH_PUT_16BIT(tempbuf, suites_to_send[i]);
      ssh_tls_add_to_kex_packet(s, tempbuf, 2);
    }

  /* And the compression method. */
  tempbuf[0] = 1;
  tempbuf[1] = 0; /* the null compression */
  ssh_tls_add_to_kex_packet(s, tempbuf, 2);

  s->kex.state = SSH_TLS_KEX_WAIT_S_HELLO;

  return SSH_TLS_TRANS_OK;
}
SshOperationHandle
ssh_pm_cfgmode_client_store_register(SshPm pm,
				     SshPmTunnel tunnel,
                                     SshPmActiveCfgModeClient client,
                                     SshIpAddr address,
				     void *address_context,
                                     SshPmRemoteAccessAttrsFreeCB free_cb,
                                     void *free_cb_context,
				     SshPmStatusCB status_cb,
				     void *status_cb_context)
{
  SSH_DEBUG(SSH_D_LOWOK,
	    ("Registering address `%@'", ssh_ipaddr_render, address));

  SSH_ASSERT(client->status_cb == NULL_FNPTR);

  if (client->flags & SSH_PM_CFGMODE_CLIENT_ADDING_ARP)
    goto error;

  if (!SSH_IP_DEFINED(address))
    goto error;
  
  if (SSH_IP_IS4(address))
    {
      SSH_ASSERT(client->ip4 == NULL);
      client->ip4 = ssh_memdup(address, sizeof(*address));
      if (client->ip4 == NULL)
	goto error;
      client->ip4_address_context = address_context;
    }
  else
    {
      SSH_ASSERT(client->ip6 == NULL);
      client->ip6 = ssh_memdup(address, sizeof(*address));
      if (client->ip6 == NULL)
	goto error;
      client->ip6_address_context = address_context;
    }

  client->free_cb = free_cb;
  client->free_cb_context = free_cb_context;
  
  /* Check if we should add a proxy ARP entry for the remote access client. */
  if (tunnel->flags & SSH_PM_TR_PROXY_ARP)
    {
      unsigned char media_addr[SSH_ETHERH_ADDRLEN];
      SshUInt32 flags;
      
      /* Create a fake ethernet address. */
      memset(media_addr, 0, sizeof(media_addr));
      if (SSH_IP_IS4(address))
	{
	  media_addr[1] = 2;
	  SSH_IP4_ENCODE(address, media_addr + 2);

	  client->flags |= SSH_PM_CFGMODE_CLIENT_IPV4_PROXY_ARP;
	}
      else
	{
	  SshUInt32 value;
	  
	  value = SSH_IP6_WORD0_TO_INT(address);
	  value ^= SSH_IP6_WORD1_TO_INT(address);
	  value ^= SSH_IP6_WORD2_TO_INT(address);
	  value ^= SSH_IP6_WORD3_TO_INT(address);
	  
	  media_addr[1] = 2;
	  SSH_PUT_32BIT(media_addr + 2, value);

	  client->flags |= SSH_PM_CFGMODE_CLIENT_IPV6_PROXY_ARP;
	}
      
      /* Flags for ARP entry. */
      flags = SSH_PME_ARP_PERMANENT | SSH_PME_ARP_GLOBAL | SSH_PME_ARP_PROXY;

      /* Store status_cb. */
      client->status_cb = status_cb;
      client->status_cb_context = status_cb_context;
      if (SSH_IP_IS4(address))
	client->flags |= SSH_PM_CFGMODE_CLIENT_IPV4_REGISTERING;
      else
	client->flags |= SSH_PM_CFGMODE_CLIENT_IPV6_REGISTERING;

      /* Register an abort callback for the engine operation. */
      ssh_operation_register_no_alloc(&client->operation,
				      pm_cfgmode_client_store_arp_abort,
				      client);

      /* Take a reference to the client and mark ARP ongoing. */
      ssh_pm_cfgmode_client_store_take_reference(pm, client);
      client->flags |= SSH_PM_CFGMODE_CLIENT_ADDING_ARP;

      /* Add ARP entry. */
      SSH_DEBUG(SSH_D_LOWSTART, ("Adding ARP entry"));
      ssh_pme_arp_add(pm->engine, address, 0,
		      media_addr, sizeof(media_addr),
		      flags, pm_cfgmode_client_store_arp_cb, client);

      return &client->operation;
    }

  if (status_cb) 
    (*status_cb)(pm, TRUE, status_cb_context);
  
  return NULL;

 error:
  if (status_cb) 
    (*status_cb)(pm, FALSE, status_cb_context);

  return NULL;
}
示例#25
0
/* HTTP/TCP transport independent send ***************************************/
static Boolean
pkix_client_srv_send(SshPkiThreadData tdata,
                     SshPkiTcpProtoVersion v, SshUInt32 flags,
                     SshPkiTcpProtoMessage type,
                     const unsigned char *data, size_t len)
{
  SshFSMThread thread = (SshFSMThread)tdata->thread;
  SshFSM fsm = ssh_fsm_get_fsm(thread);
  SshPkiGlobalData gdata = ssh_fsm_get_gdata(thread);
  size_t out_len;
  unsigned char *out;

  /* Start input processor now. */
  if (!gdata->input_thread)
    gdata->input_thread = ssh_fsm_thread_create(fsm,
                                                pkix_process_input,
                                                NULL_FNPTR, NULL_FNPTR,
                                                NULL);

  /* If it is a TCP or HTTP... */
  if (!tdata->http)
    {
      if (tdata->wrapper)
        {
          switch (v)
            {
            case SSH_PKI_VERSION_1:
              out_len = len + 2;
              out = ssh_malloc(out_len);
              if (out)
                {
                  out[0] = (unsigned char) flags;
                  out[1] = (unsigned char) type;
                  memmove(out + 2, data, len);
                  ssh_packet_wrapper_send(tdata->wrapper, v, out, out_len);
                  ssh_free(out);
                }
              break;
            case SSH_PKI_VERSION_0:
              ssh_packet_wrapper_send(tdata->wrapper, type, data, len);
            default:
              return FALSE;
            }
        }
      else
        {
          /* Trying to send to closed; reopen. */
          ssh_fsm_set_next(thread, pkix_connect);
          return TRUE;
        }
    }
  else
    {
      switch (v)
        {
        case SSH_PKI_VERSION_1:
          out_len = len + 7;
          out = ssh_malloc(out_len);
          if (out)
            {
              SSH_PUT_32BIT(out, out_len - 4);
              out[4] = v;
              out[5] = (unsigned char)flags;
              out[6] = (unsigned char)type;
              memmove(out + 7, data, len);
            }
          break;
        case SSH_PKI_VERSION_0:
          out_len = len + 5;
          out = ssh_malloc(out_len);
          if (out)
            {
              SSH_PUT_32BIT(out, out_len - 4);
              out[4] = (unsigned char)type;
              memmove(out + 5, data, len);
            }
          break;
        default:
          return FALSE;
        }
      if (out)
        {
          tdata->transport_op =
            ssh_http_post(tdata->http,
                          gdata->session->access, out, out_len,
                          pkix_http_receive_data, (void *)tdata->thread,
                          SSH_HTTP_HDR_END);
          ssh_free(out);
        }
    }
  return TRUE;
}