Ejemplo n.º 1
0
void test_random_decode(void)
{
  unsigned char buf[16];
  size_t i, j;

  for(j = 0; j < 100; j++)
    {
      for (i = 0; i < sizeof(buf); i++)
	buf[i] = rand();

      ssh_decode_array(buf, sizeof(buf), SSH_DECODE_UINT32_STR(NULL, NULL),
		       SSH_FORMAT_END);
      ssh_decode_array(buf, sizeof(buf), SSH_DECODE_UINT32(NULL),
		       SSH_FORMAT_END);
      ssh_decode_array(buf, sizeof(buf), SSH_DECODE_CHAR(NULL),
		       SSH_FORMAT_END);
      ssh_decode_array(buf, sizeof(buf), SSH_DECODE_BOOLEAN(NULL),
		       SSH_FORMAT_END);
      ssh_decode_array(buf, sizeof(buf), SSH_DECODE_DATA(NULL, 0),
		       SSH_FORMAT_END);
    }
}
Ejemplo n.º 2
0
void test_empty_decode(void)
{
  if (ssh_decode_array((const unsigned char *) "", 0,
                       SSH_DECODE_UINT32_STR(NULL, NULL),
                       SSH_FORMAT_END) != 0)
    ssh_fatal("test_empty_decode failed");
  if (ssh_decode_array((const unsigned char *) "", 0,
                       SSH_DECODE_UINT32(NULL),
                       SSH_FORMAT_END) != 0)
    ssh_fatal("test_empty_decode failed");
  if (ssh_decode_array((const unsigned char *) "", 0,
                       SSH_DECODE_CHAR(NULL),
                       SSH_FORMAT_END) != 0)
    ssh_fatal("test_empty_decode failed");
  if (ssh_decode_array((const unsigned char *) "", 0,
                       SSH_DECODE_BOOLEAN(NULL),
                       SSH_FORMAT_END) != 0)
    ssh_fatal("test_empty_decode failed");
  if (ssh_decode_array((const unsigned char *) "", 0,
                       SSH_DECODE_DATA(NULL, 0),
                       SSH_FORMAT_END) != 0)
    ssh_fatal("test_empty_decode failed");
}
Boolean
ssh_virtual_adapter_param_decode(SshVirtualAdapterParams params,
				 const unsigned char *data, size_t len)
{
  unsigned char *dns;
  size_t dns_len;
  unsigned char *wins;
  size_t wins_len;
  unsigned char *win_domain;
  size_t win_domain_len;
  SshUInt32 netbios_node_type;
  SshUInt32 i;
  size_t decode_len;

  SSH_ASSERT(params != NULL);
  SSH_ASSERT(data != NULL);
  SSH_ASSERT(len > 0);

  memset(params, 0, sizeof(*params));
  
  if (ssh_decode_array(data, len,
		       SSH_DECODE_UINT32(&params->mtu),
		       SSH_DECODE_UINT32(&params->dns_ip_count),
		       SSH_DECODE_UINT32_STR_NOCOPY(&dns, &dns_len),
		       SSH_DECODE_UINT32(&params->wins_ip_count),
		       SSH_DECODE_UINT32_STR_NOCOPY(&wins, &wins_len),
		       SSH_DECODE_UINT32_STR_NOCOPY(
		       &win_domain, &win_domain_len),
		       SSH_DECODE_UINT32(&netbios_node_type),
		       SSH_FORMAT_END) != len)
    return FALSE;

  /* DNS. */
  if (params->dns_ip_count)
    {
      params->dns_ip = ssh_calloc(params->dns_ip_count, 
				  sizeof(*params->dns_ip));
      if (params->dns_ip == NULL)
	goto error;
      
      for (i = 0; i < params->dns_ip_count; i++)
	{
	  decode_len = ssh_decode_ipaddr_array(dns, dns_len, 
					       &params->dns_ip[i]);
	  if (decode_len == 0)
	    goto error;	  
	  dns += decode_len;
	  dns_len -= decode_len;
	}
    }
  
      /* WINS. */
  if (params->wins_ip_count)
    {
      params->wins_ip = ssh_calloc(params->wins_ip_count, 
				   sizeof(*params->wins_ip));
      if (params->wins_ip == NULL)
	goto error;
      
      for (i = 0; i < params->wins_ip_count; i++)
	{
	  decode_len = ssh_decode_ipaddr_array(wins, wins_len, 
					       &params->wins_ip[i]);
	  if (decode_len == 0)
	    goto error;	  
	  wins += decode_len;
	  wins_len -= decode_len;
	}
    }
  
  if (win_domain_len)
    {
      params->win_domain = ssh_memdup(win_domain, win_domain_len);
      if (params->win_domain == NULL)
	goto error;
    }
  
  params->netbios_node_type = (SshUInt8) netbios_node_type;

  return TRUE;

 error:
  ssh_free(params->dns_ip);
  ssh_free(params->wins_ip);
  ssh_free(params->win_domain);
  memset(params, 0, sizeof(*params));
  return FALSE;
}
Ejemplo n.º 4
0
/* Import given buffer to the IKE Server given in the argument. Returns the IKE
   SA negotiation or NULL in case of error. The data that was parsed
   successfully is consumed from the buffer in any case. If there is extra data
   after the complete packet then it is left to the buffer. */
SshIkeNegotiation ssh_ike_sa_import(SshBuffer buffer,
                                    SshIkeServerContext server)
{
  unsigned char initiator_cookie[SSH_IKE_COOKIE_LENGTH];
  unsigned char responder_cookie[SSH_IKE_COOKIE_LENGTH];
  unsigned char *auc, *buc, *cuc, *duc;
  SshUInt32 a32, b32, c32, d32;
  SshUInt64 a64, b64, c64, d64;
  SshIkePMPhaseI pm_info;
  SshIkeNegotiation neg;
  SshIkeSA sa;
  size_t len;
  long l;
  SshADTHandle h;
  SshCryptoStatus cret;
  SshTime t;
  SshUInt16 local_port;

  sa = NULL;
  pm_info = NULL;
  neg = NULL;
  auc = NULL;
  buc = NULL;
  cuc = NULL;
  duc = NULL;

  SSH_DEBUG(5, ("Start"));

  len = ssh_decode_buffer
    (buffer,
     /* Magic number */
     SSH_DECODE_UINT32(&a32),
     /* Version number */
     SSH_DECODE_UINT32(&b32),
     /* Cookies, initiator, responder */
     SSH_DECODE_DATA(initiator_cookie, SSH_IKE_COOKIE_LENGTH),
     SSH_DECODE_DATA(responder_cookie, SSH_IKE_COOKIE_LENGTH),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode magic, version, cookies"));
      goto error;
    }
  if (a32 != SSH_IKE_EXPORT_MAGIC1)
    {
      SSH_DEBUG(3, ("Invalid magic 0x%08x vs 0x%08x", (int) a32,
                    SSH_IKE_EXPORT_MAGIC1));
      goto error;
    }
  if (b32 != SSH_IKE_EXPORT_VERSION)
    {
      SSH_DEBUG(3, ("Invalid version 0x%08x vs 0x%08x", (int) b32,
                    SSH_IKE_EXPORT_VERSION));
      goto error;
    }

  h = ssh_adt_get_handle_to_equal(server->isakmp_context->
                                  isakmp_cookie_mapping, initiator_cookie);
  if (h != SSH_ADT_INVALID)
    {
      SSH_DEBUG(3, ("Duplicate initiator cookie"));
      goto error;
    }

  sa = ike_sa_allocate(server, initiator_cookie, responder_cookie);
  if (sa == NULL)
    {
      SSH_DEBUG(3, ("ike_sa_allocate_half return error"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Local ip, port. */
     SSH_DECODE_UINT32_STR(&auc, NULL),
     SSH_DECODE_UINT32_STR(&buc, NULL),
     /* Remote ip, port. */
     SSH_DECODE_UINT32_STR(&cuc, NULL),
     SSH_DECODE_UINT32_STR(&duc, NULL),
     /* IKE exchange version. */
     SSH_DECODE_UINT32(&a32),
     SSH_DECODE_UINT32(&b32),
     /* IKE exchange type. */
     SSH_DECODE_UINT32(&c32),
     /* Was this the initiator for the original exchange? */
     SSH_DECODE_UINT32(&d32),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode ip, port, version, exchage type, init"));
      goto error;
    }
  if (!ike_init_isakmp_sa(sa, auc, buc, cuc, duc, a32, b32, c32, d32, FALSE))
    {
      SSH_DEBUG(3, ("Could not init isakmp sa"));
      goto error;
    }
  ssh_free(auc);
  ssh_free(buc);
  ssh_free(cuc);
  ssh_free(duc);
  auc = NULL;
  buc = NULL;
  cuc = NULL;
  duc = NULL;

  neg = sa->isakmp_negotiation;
  pm_info = neg->ike_pm_info;

  /* Initialize */
  sa->phase_1_done = 1;
  neg->notification_state = SSH_IKE_NOTIFICATION_STATE_ALREADY_SENT;
  ike_free_negotiation_isakmp(neg);


  /* Set NAT-T status. */
  local_port = ssh_uatoi(sa->isakmp_negotiation->ike_pm_info->local_port);
  if (local_port != server->normal_local_port)
    sa->use_natt = 1;

  /* I think we should count this as SA */
  server->statistics->current_ike_sas++;
  server->statistics->total_ike_sas++;
  if (neg->ike_pm_info->this_end_is_initiator)
    {
      server->statistics->current_ike_sas_initiated++;
      server->statistics->total_ike_sas_initiated++;
    }
  else
    {
      server->statistics->current_ike_sas_responded++;
      server->statistics->total_ike_sas_responded++;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Byte count and byte limit. */
     SSH_DECODE_UINT64(&a64),
     SSH_DECODE_UINT64(&b64),
     /* Created time and laste use time */
     SSH_DECODE_UINT64(&c64),
     SSH_DECODE_UINT64(&d64),
     /* Encryption, hash, prf algorithm names. */
     SSH_DECODE_UINT32_STR(&auc, NULL),
     SSH_DECODE_UINT32_STR(&buc, NULL),
     SSH_DECODE_UINT32_STR(&cuc, NULL),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode byte count limit, times, alg names"));
      goto error;
    }
  sa->byte_count = (unsigned long) a64;
  sa->kbyte_limit = (unsigned long) b64;
  sa->created_time = (SshTime) c64;
  sa->last_use_time = (SshTime) d64;

  l = ssh_find_keyword_number(ssh_ike_encryption_algorithms, ssh_csstr(auc));
  if (l == -1)
    {
      if (ssh_usstrcmp(auc, "cast128-12-cbc") == 0)
        sa->encryption_algorithm_name = ssh_custr("cast128-12-cbc");
      else
        {
          SSH_DEBUG(3, ("Unknown cipher %s", auc));
          goto error;
        }
    }
  else
    {
      sa->encryption_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_encryption_algorithms, l));
      SSH_ASSERT(sa->encryption_algorithm_name != NULL);
    }

  l = ssh_find_keyword_number(ssh_ike_hash_algorithms, ssh_csstr(buc));
  if (l == -1)
    {
      SSH_DEBUG(3, ("Unknown hash %s", buc));
      goto error;
    }
  else
    {
      sa->hash_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_hash_algorithms, l));
      SSH_ASSERT(sa->hash_algorithm_name != NULL);
    }

  l = ssh_find_keyword_number(ssh_ike_hmac_prf_algorithms, ssh_csstr(cuc));
  if (l == -1)
    {
      SSH_DEBUG(3, ("Unknown prf %s", cuc));
      goto error;
    }
  else
    {
      sa->prf_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_hmac_prf_algorithms, l));
      SSH_ASSERT(sa->prf_algorithm_name != NULL);
    }

  ssh_free(auc);
  ssh_free(buc);
  ssh_free(cuc);
  ssh_free(duc);
  auc = NULL;
  buc = NULL;
  cuc = NULL;
  duc = NULL;

  len = ssh_decode_buffer
    (buffer,
     /* Cipher key. */
     SSH_DECODE_UINT32_STR(&sa->cipher_key, &sa->cipher_key_len),
     /* Cipher IV. */
     SSH_DECODE_UINT32_STR(&sa->cipher_iv, &sa->cipher_iv_len),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode cipher key, iv"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Keying material, Diffie-Hellman. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.dh, &sa->skeyid.dh_size),
     /* Keying material, SKEYID mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid, &sa->skeyid.skeyid_size),
     /* Keying material, SKEYID_d mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_d, &sa->skeyid.skeyid_d_size),
     /* Keying material, SKEYID_a mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_a, &sa->skeyid.skeyid_a_size),
     /* Keying material, SKEYID_e mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_e, &sa->skeyid.skeyid_e_size),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode skeyid"));
      goto error;
    }
  sa->skeyid.initialized = TRUE;

  cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name),
                          sa->skeyid.skeyid,
                          sa->skeyid.skeyid_size,
                          &sa->skeyid.skeyid_mac);
  if (cret != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s",
                    ssh_crypto_status_message(cret)));
      goto error;
    }

  cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name),
                          sa->skeyid.skeyid_a,
                          sa->skeyid.skeyid_a_size,
                          &sa->skeyid.skeyid_a_mac);
  if (cret != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s",
                    ssh_crypto_status_message(cret)));
      goto error;
    }
  cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name),
                          sa->skeyid.skeyid_e,
                          sa->skeyid.skeyid_e_size,
                          &sa->skeyid.skeyid_e_mac);
  if (cret != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s",
                    ssh_crypto_status_message(cret)));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Retry defaults. */
     SSH_DECODE_UINT32(&sa->retry_limit),
     SSH_DECODE_UINT32(&sa->retry_timer),
     SSH_DECODE_UINT32(&sa->retry_timer_usec),
     SSH_DECODE_UINT32(&sa->retry_timer_max),
     SSH_DECODE_UINT32(&sa->retry_timer_max_usec),
     SSH_DECODE_UINT32(&sa->expire_timer),
     SSH_DECODE_UINT32(&sa->expire_timer_usec),
     /* Statistics. */
     SSH_DECODE_UINT32(&sa->statistics.packets_in),
     SSH_DECODE_UINT32(&sa->statistics.packets_out),
     SSH_DECODE_UINT32(&sa->statistics.octects_in),
     SSH_DECODE_UINT32(&sa->statistics.octects_out),
     SSH_DECODE_UINT32(&sa->statistics.created_suites),
     SSH_DECODE_UINT32(&sa->statistics.deleted_suites),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode retry, expire timers and stats"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* IKE SA negotiation information. */
     SSH_DECODE_UINT32(&a32),
     SSH_DECODE_UINT32(&b32),





     SSH_DECODE_UINT32(&c32),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode ike sa info and private group cnt"));
      goto error;
    }
  neg->exchange_type = a32;
  /* The b32 used to be authe_method_type, but as it was duplicate for the
     value in pm_info, we ignore it now. */
  if (c32 != 0)
    {
      ssh_warning("Remote end sent packet including private groups. "
                  "This end does not support transferring of them. "
                  "Private groups ignored");
    }
  len = ssh_decode_buffer
    (buffer,
     /* Private groups as UINT32_STRING. */ 



     SSH_DECODE_UINT32_STR(NULL, NULL),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode private groups info"));
      goto error;
    }

  if (!ssh_ike_sa_import_id(buffer, &pm_info->local_id,
                            &pm_info->local_id_txt))
    {
      SSH_DEBUG(3, ("Could not decode local id"));
      goto error;
    }
  if (!ssh_ike_sa_import_id(buffer, &pm_info->remote_id,
                            &pm_info->remote_id_txt))
    {
      SSH_DEBUG(3, ("Could not decode remote id"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Authentication type. */
     SSH_DECODE_UINT32(&a32),
     SSH_DECODE_UINT32(&b32),
     /* Start and expire times. */
     SSH_DECODE_UINT64(&a64),
     SSH_DECODE_UINT64(&b64),
     /* None of the policy manager filled data is copied, this include
        auth_data, auth_data_len, own_auth_data, own_auth_data_len,
        public_key, number_of_certificates, number_of_allocated_certificates,
        certificates, certificate_lens, certificate_encodings,
        policy_manager_data, pm. */
     SSH_DECODE_UINT32(&c32),
     /* Magic number */
     SSH_DECODE_UINT32(&d32),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode pm info and magic2"));
      goto error;
    }
  pm_info->auth_method_type = a32;
  pm_info->auth_method = b32;
  pm_info->sa_start_time = (SshTime) a64;
  pm_info->sa_expire_time = (SshTime) b64;
  pm_info->doi = c32;
  if (d32 != SSH_IKE_EXPORT_MAGIC2)
    {
      SSH_DEBUG(3, ("Invalid magic2 0x%08x vs 0x%08x", (int) d32,
                    SSH_IKE_EXPORT_MAGIC2));
      goto error;
    }

  ssh_cancel_timeouts(SSH_ALL_CALLBACKS, neg);
  /* Insert expire timer allowing the sa to exists for a while (for
     bootstrap) */
  t = ssh_time();
  if (t < pm_info->sa_expire_time)
    t = pm_info->sa_expire_time - t;
  else
    t = 0;

  t = (t < 30) ? 30 : t;
  ssh_xregister_timeout((SshUInt32) t, 0,
                       ike_call_ike_remove_isakmp_sa,
                       neg);
  return neg;
 error:
  if (sa != NULL)
    {
      if (sa->isakmp_negotiation == NULL)
        {
          ike_sa_delete(server->isakmp_context, sa);
          ssh_free(sa);
        }
      else
        ike_delete_negotiation(sa->isakmp_negotiation);
    }
  ssh_free(auc);
  ssh_free(buc);
  ssh_free(cuc);
  ssh_free(duc);
  return NULL;
}
Ejemplo n.º 5
0
/* Import id from the buffer and store newly allocated id to the id pointer,
   freeing the old id if such was stored there. If the id_txt pointer is given
   then it is used to store the textual format of the id. If that pointer
   contained old id string it is freed before the new string stored there.
   Returns TRUE if successful and FALSE otherwise. In case of error the buffer
   is left unspecified state (i.e part of it might be consumed). */
Boolean ssh_ike_sa_import_id(SshBuffer buffer, SshIkePayloadID *id,
                             char **id_txt)
{
  SshUInt32 a32, b32, c32;
  SshIkePayloadID newp = NULL;
  char newp_txt[255];
  size_t ret = 0;

  SSH_DEBUG(5, ("Start"));

  if (ssh_decode_buffer
      (buffer,
       SSH_DECODE_UINT32(&a32),
       SSH_FORMAT_END) == 0)
    goto error;

  if (a32 == 0)
    {
      if (id)
        {
          ssh_ike_id_free(*id);
          *id = NULL;
        }
      if (id_txt)
        {
          ssh_free(*id_txt);
          *id_txt = ssh_strdup("No Id");
          if (*id == NULL)
            return FALSE;
        }
      return TRUE;
    }

  newp = ssh_malloc(sizeof(*newp));
  if (newp == NULL)
    return FALSE;

  newp->raw_id_packet = NULL;

  newp->id_type = a32;

  if (ssh_decode_buffer
      (buffer,
       SSH_DECODE_UINT32(&a32),
       SSH_DECODE_UINT32(&b32),
       SSH_DECODE_UINT32(&c32),
       SSH_FORMAT_END) == 0)
    goto error;

  newp->protocol_id = a32;
  newp->port_number = b32;
  newp->port_range_end = c32;

  switch (newp->id_type)
    {
    case IPSEC_ID_IPV4_ADDR:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv4_addr, 4),
         SSH_FORMAT_END);
      newp->identification_len = 4;
      break;
    case IPSEC_ID_FQDN:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.fqdn,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_USER_FQDN:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.user_fqdn,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV4_ADDR_SUBNET:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv4_addr_subnet, 4),
         SSH_DECODE_DATA(newp->identification.ipv4_addr_netmask, 4),
         SSH_FORMAT_END);
      newp->identification_len = 8;
      break;
    case IPSEC_ID_IPV6_ADDR:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv6_addr, 16),
         SSH_FORMAT_END);
      newp->identification_len = 16;
      break;
    case IPSEC_ID_IPV6_ADDR_SUBNET:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv6_addr_subnet, 16),
         SSH_DECODE_DATA(newp->identification.ipv6_addr_netmask, 16),
         SSH_FORMAT_END);
      newp->identification_len = 32;
      break;
    case IPSEC_ID_IPV4_ADDR_RANGE:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv4_addr_range1, 4),
         SSH_DECODE_DATA(newp->identification.ipv4_addr_range2, 4),
         SSH_FORMAT_END);
      newp->identification_len = 8;
      break;
    case IPSEC_ID_IPV6_ADDR_RANGE:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv6_addr_range1, 16),
         SSH_DECODE_DATA(newp->identification.ipv6_addr_range2, 16),
         SSH_FORMAT_END);
      newp->identification_len = 32;
      break;
    case IPSEC_ID_DER_ASN1_DN:
    case IPSEC_ID_DER_ASN1_GN:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.asn1_data,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_KEY_ID:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.key_id,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
#ifdef SSHDIST_IKE_ID_LIST
    case IPSEC_ID_LIST:
      {
        int cnt;
        SshIkePayloadID itemp = NULL;

        newp->identification_len = 0;
        ret = ssh_decode_buffer
          (buffer,
           SSH_DECODE_UINT32((SshUInt32 *)&newp->identification.
			     id_list_number_of_items),
           SSH_FORMAT_END);
        if (ret == 0)
          goto error;
        newp->identification.id_list_items =
          ssh_calloc(newp->identification.id_list_number_of_items,
                     sizeof(newp->identification.id_list_items[0]));
        if (newp->identification.id_list_items == NULL)
          goto error;

        for (cnt = 0;
             cnt < newp->identification.id_list_number_of_items;
             cnt++)
          {
            if (!ssh_ike_sa_import_id(buffer, &itemp, NULL))
              goto error;

            newp->identification.id_list_items[cnt] = *itemp;
            ssh_free(itemp);
            itemp = NULL;
          }
        break;
      }
#endif /* SSHDIST_IKE_ID_LIST */
    }
  if (ret == 0)
    goto error;
  if (id_txt)
    {
      ssh_free(*id_txt);
      ssh_ike_id_to_string(newp_txt, sizeof(newp_txt), newp);
      *id_txt = ssh_strdup(newp_txt);
      if (*id_txt == NULL)
        goto error;
    }
  if (id)
    {
      ssh_ike_id_free(*id);
      *id = newp;
    }
  else
    {
      ssh_ike_id_free(newp);
    }
  return TRUE;
 error:
  if (newp != NULL)
    ssh_ike_id_free(newp);
  return FALSE;
}
Ejemplo n.º 6
0
/* Decode record. */
Boolean ssh_dns_packet_decode_record(SshDNSPacket packet,
				     const unsigned char *packet_buffer,
				     size_t packet_length,
				     size_t *offset_ptr,
				     SshDNSRecord record)
{
  SshUInt16 type, dns_class, rdlength;
  size_t len, len2, new_rdlength, offset, offset2;

  if (!ssh_dns_packet_decode_name(packet, packet_buffer, packet_length,
				  offset_ptr, &record->name))
    return FALSE;

  len = ssh_decode_array(packet_buffer + *offset_ptr,
			 packet_length - *offset_ptr,
			 SSH_DECODE_UINT16(&type),
			 SSH_DECODE_UINT16(&dns_class),
			 SSH_DECODE_UINT32(&record->ttl),
			 SSH_DECODE_UINT16(&rdlength),
			 SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(SSH_D_NETGARB, ("Error decoding record"));
      return FALSE;
    }

  if (*offset_ptr + len + rdlength > packet_length)
    {
      SSH_DEBUG(SSH_D_NETGARB, ("Data length in record exceeds packet size"));
      return FALSE;
    }

  record->type = type;
  record->dns_class = dns_class;
  *offset_ptr += len;

  switch (record->type)
    {
      /* One compressed name. Copy rest. */
    case SSH_DNS_RESOURCE_NS:
    case SSH_DNS_RESOURCE_MD:
    case SSH_DNS_RESOURCE_MF:
    case SSH_DNS_RESOURCE_CNAME:
    case SSH_DNS_RESOURCE_MB:
    case SSH_DNS_RESOURCE_MG:
    case SSH_DNS_RESOURCE_MR:
    case SSH_DNS_RESOURCE_PTR:
    case SSH_DNS_RESOURCE_NSAP_PTR:
    case SSH_DNS_RESOURCE_NXT:
    case SSH_DNS_RESOURCE_DNAME: /* Do not compress, but do decompress. */
    case SSH_DNS_RESOURCE_NSEC: /* Do not compress, but do decompress. */
      offset = *offset_ptr;
      len = ssh_dns_packet_decode_name_len(packet_buffer, packet_length,
					   offset_ptr);
      if (len == 0)
	return FALSE;
      new_rdlength = len + rdlength - (*offset_ptr - offset);
      record->rdata = ssh_obstack_alloc(packet->obstack, new_rdlength);
      ssh_dns_packet_decode_name_copy(packet_buffer, packet_length,
				      offset, record->rdata);
      memcpy(record->rdata + len, packet_buffer + *offset_ptr,
	     new_rdlength - len);
      *offset_ptr += new_rdlength - len;
      break;

      /* Two domain name addresses, copy rest. */
    case SSH_DNS_RESOURCE_SOA:
    case SSH_DNS_RESOURCE_MINFO:
    case SSH_DNS_RESOURCE_RP:
      offset = *offset_ptr;
      len = ssh_dns_packet_decode_name_len(packet_buffer, packet_length,
					   offset_ptr);
      if (len == 0)
	return FALSE;
      offset2 = *offset_ptr;
      len2 = ssh_dns_packet_decode_name_len(packet_buffer, packet_length,
					    offset_ptr);
      if (len2 == 0)
	return FALSE;
      
      new_rdlength = len + len2 + rdlength - (*offset_ptr - offset);
      record->rdata = ssh_obstack_alloc(packet->obstack, new_rdlength);
      ssh_dns_packet_decode_name_copy(packet_buffer, packet_length,
				      offset, record->rdata);
      ssh_dns_packet_decode_name_copy(packet_buffer, packet_length,
				      offset2, record->rdata + len);
      memcpy(record->rdata + len + len2, packet_buffer + *offset_ptr,
	     new_rdlength - len - len2);
      *offset_ptr += new_rdlength - len - len2;
      break;

      /* 16-bit number and dns name. */
    case SSH_DNS_RESOURCE_MX:
    case SSH_DNS_RESOURCE_AFSDB:
    case SSH_DNS_RESOURCE_RT:
    case SSH_DNS_RESOURCE_KX: /* Do not compress, but do decompress. */
      len2 = 2;
    copy_name_copy:
      offset = *offset_ptr;
      *offset_ptr += len2;
      len = ssh_dns_packet_decode_name_len(packet_buffer, packet_length,
					   offset_ptr);
      if (len == 0)
	return FALSE;
      new_rdlength = len2 + len + rdlength - (*offset_ptr - offset);
      record->rdata = ssh_obstack_alloc(packet->obstack, new_rdlength);
      memcpy(record->rdata, packet_buffer + offset, len2);
      ssh_dns_packet_decode_name_copy(packet_buffer, packet_length,
				      offset + len2, record->rdata + len2);
      memcpy(record->rdata + len2 + len, packet_buffer + *offset_ptr,
	     new_rdlength - len2 - len);
      *offset_ptr += new_rdlength - len2 - len;
      break;

      /* Copy 9 bytes, then decompress signers name, and then copy rest. */
    case SSH_DNS_RESOURCE_SIG:
    case SSH_DNS_RESOURCE_RRSIG: /* Docompress, must not compress */
      len2 = 9;
      goto copy_name_copy;

      /* 16-bit number and 2 dns names. */
    case SSH_DNS_RESOURCE_PX:
      offset = *offset_ptr;
      *offset_ptr += 2;
      len = ssh_dns_packet_decode_name_len(packet_buffer, packet_length,
					   offset_ptr);
      if (len == 0)
	return FALSE;
      offset2 = *offset_ptr;
      len2 = ssh_dns_packet_decode_name_len(packet_buffer, packet_length,
					    offset_ptr);
      if (len2 == 0)
	return FALSE;
      
      new_rdlength = len + len2 + rdlength - (*offset_ptr - offset);
      record->rdata = ssh_obstack_alloc(packet->obstack, new_rdlength);
      memcpy(record->rdata, packet_buffer + offset, 2);
      ssh_dns_packet_decode_name_copy(packet_buffer, packet_length,
				      offset + 2, record->rdata + 2);
      ssh_dns_packet_decode_name_copy(packet_buffer, packet_length,
				      offset2, record->rdata + len + 2);
      memcpy(record->rdata + 2 + len + len2, packet_buffer + *offset_ptr,
	     new_rdlength - 2 - len - len2);
      *offset_ptr += new_rdlength - 2 - len - len2;
      break;

      /* 3 16-bit numbers and dns name. */
    case SSH_DNS_RESOURCE_SRV:	/* Do not compress, but do decompress */
      len2 = 6;
      goto copy_name_copy;

      /* Special handling. */
    case SSH_DNS_RESOURCE_OPT:
      /* The special OPT handling is to parse the data and then copy it.
	 i.e. we will fall through to the next case. */
      packet->response_code |= ((record->ttl & 0xff000000) >> 24) << 4;
      /* We leave rest of the special stuff (i.e. senders UDP payload size
	 version, extra flags, etc in the class, ttl etc fields, and there
	 might be some attribute value pairs also). */

      /* Just copy data. */
    case SSH_DNS_RESOURCE_A:
    case SSH_DNS_RESOURCE_NULL:
    case SSH_DNS_RESOURCE_WKS:
    case SSH_DNS_RESOURCE_HINFO:
    case SSH_DNS_RESOURCE_TXT:
    case SSH_DNS_RESOURCE_X25:
    case SSH_DNS_RESOURCE_ISDN:
    case SSH_DNS_RESOURCE_NSAP:
    case SSH_DNS_RESOURCE_KEY:
    case SSH_DNS_RESOURCE_GPOS:
    case SSH_DNS_RESOURCE_AAAA:
    case SSH_DNS_RESOURCE_LOC:
    case SSH_DNS_RESOURCE_NAPTR: /* Contains name, and rfc2168 says it is
				    compressed, but rfc2915 says that will not
				    be compressed. */
    case SSH_DNS_RESOURCE_CERT:
    case SSH_DNS_RESOURCE_A6:	/* Contains name, but MUST NOT be compr. */
    case SSH_DNS_RESOURCE_APL:
    case SSH_DNS_RESOURCE_DS:
    case SSH_DNS_RESOURCE_SSHFP:
    case SSH_DNS_RESOURCE_DNSKEY:
    case SSH_DNS_QUERY_TKEY:
    case SSH_DNS_QUERY_TSIG:
      /* Unknown, just copy. */
    case SSH_DNS_RESOURCE_EID:
    case SSH_DNS_RESOURCE_NIMLOC:
    case SSH_DNS_RESOURCE_ATMA:
    case SSH_DNS_RESOURCE_SINK:
    case SSH_DNS_RESOURCE_UINFO:
    case SSH_DNS_RESOURCE_UID:
    case SSH_DNS_RESOURCE_GID:
    case SSH_DNS_RESOURCE_UNSPEC:
      /* Query typedef values which do not appear in resource records, copy */
    case SSH_DNS_QUERY_IXFR:
    case SSH_DNS_QUERY_AXFR:
    case SSH_DNS_QUERY_MAILB:
    case SSH_DNS_QUERY_MAILA:
    case SSH_DNS_QUERY_ANY:
    default:
      record->rdata = ssh_obstack_memdup(packet->obstack,
					 packet_buffer + *offset_ptr,
					 rdlength);
      *offset_ptr += rdlength;
      new_rdlength = rdlength;
      break;
    }
  record->rdlength = new_rdlength;

  return TRUE;
  
}