예제 #1
0
void copy_data_test(SshStream s1, SshStream s2)
{
  ts1 = s1;
  ts2 = s2;

  create_testdata();
  if (received_data)
    ssh_buffer_clear(received_data);
  else
    received_data = ssh_buffer_allocate();
  test_data_index = 0;
  destroy_count = 0;
  reader_sent_eof = FALSE;

  ssh_stream_set_callback(s1, copy_writer, NULL);
  ssh_stream_set_callback(s2, copy_reader, NULL);

  ssh_event_loop_run();
  if (destroy_count != 2 || ts1 != NULL || ts2 != NULL)
    ssh_fatal("copy_data_test: one stream not destroyed");
  if (ssh_buffer_len(received_data) > ssh_buffer_len(testdata))
    ssh_fatal("copy_data_test: received more data than sent");
  if (break_test)
    ssh_buffer_consume_end(testdata,
                           ssh_buffer_len(testdata)
                           - ssh_buffer_len(received_data));
  if (ssh_buffer_len(testdata) != ssh_buffer_len(received_data))
    ssh_fatal("copy_data_test: data lens differ");
  if (memcmp(ssh_buffer_ptr(testdata), ssh_buffer_ptr(received_data),
             ssh_buffer_len(testdata)) != 0)
    ssh_fatal("copy_data_test: received data differs");
}
예제 #2
0
/* Read attached file so that buffer size exceeds argument bytes. */
Boolean ssh_file_buffer_expand(SshFileBuffer buf, size_t bytes)
{
  size_t len, need_bytes;
  unsigned char *newdata;

  SSH_ASSERT(buf != NULL);
  len = ssh_buffer_len(&(buf->buf));
  if (len >= bytes)
    return TRUE;
  if (!ssh_file_buffer_attached(buf))
    return FALSE;
  need_bytes = bytes - len;
  bytes = ((need_bytes > SSH_FILE_BUFFER_MINIMUM_READ) ?
           need_bytes :
           SSH_FILE_BUFFER_MINIMUM_READ);
  ssh_buffer_append_space(&(buf->buf), &newdata, bytes);
  SSH_ASSERT(newdata != NULL);
  if (buf->read_callback == NULL_FNPTR)
    {
      SSH_DEBUG(5, ("attempting to read %d bytes with fread", (int)bytes));
      len = fread(newdata, 1, bytes, buf->f);
    }
  else
    {
      SSH_DEBUG(5, ("attempting to read %d bytes with callback", (int)bytes));
      len = buf->read_callback(newdata, bytes, buf->read_context);
    }
  SSH_ASSERT(len <= bytes);
  if (len < need_bytes)
    {
      ssh_buffer_consume_end(&(buf->buf), bytes - len);
      ssh_file_buffer_detach(buf);
      return FALSE;
    }
  else if (len < bytes)
    {
      ssh_buffer_consume_end(&(buf->buf), bytes - len);
    }
  return TRUE;
}
예제 #3
0
Boolean ssh_packet_wrapper_input(SshPacketWrapper down)
{
  size_t data_to_read, data_read;
  int ret;
  unsigned char *ptr;
  SshPacketType type;
  Boolean return_value = FALSE;

  for (;;)
    {
      /* If we cannot receive, return immediately. */
      if (!down->can_receive || down->incoming_eof || down->destroy_pending ||
          down->shortcircuit_up_stream != NULL)
        return return_value;

      /* Get length of data read so far. */
      data_read = ssh_buffer_len(&down->incoming);

      /* Add enough space to buffer for reading either header or
         entire packet.  This also sets `ptr' to point to the place
         where data should be read, and `data_to_read' to the number
         of bytes that should be there after reading (should read
         data_to_read - data_read bytes). */
      if (data_read < 4)
        {
          /* Packet header not yet in buffer.  Read only header. */
          data_to_read = 4;
          ssh_buffer_append_space(&down->incoming, &ptr, 4 - data_read);
        }
      else
        {
          /* Packet header already in buffer. */
          ptr = ssh_buffer_ptr(&down->incoming);
          data_to_read = 4 + SSH_GET_32BIT(ptr);
          if (data_to_read > 100000000L)
            ssh_fatal("ssh_packet_wrapper_input: "
                      "invalid packet received: len %ld",
                      (long)data_to_read);
          SSH_ASSERT(data_to_read > data_read);
          ssh_buffer_append_space(&down->incoming, &ptr,
                                  data_to_read - data_read);
        }

      /* Keep reading until entire packet read, or no more data available. */
      while (data_read < data_to_read)
        {
          /* Try to read the remaining bytes. */
          ptr = (unsigned char *)ssh_buffer_ptr(&down->incoming) + data_read;
          ret = ssh_stream_read(down->stream, ptr, data_to_read - data_read);
          if (ret < 0)
            {
              /* No more data available at this time.  Remove
                 allocated but unread space from end of buffer. */
              ssh_buffer_consume_end(&down->incoming,
                                     data_to_read - data_read);
              return return_value;
            }

          if (ret == 0)
            {
              /* EOF received. */
              ssh_buffer_consume_end(&down->incoming,
                                     data_to_read - data_read);
              down->incoming_eof = TRUE;

              /* Pass the EOF to the application callback. */
              down->cannot_destroy = TRUE;
              if (down->received_eof)
                (*down->received_eof)(down->context);
              down->cannot_destroy = FALSE;
              if (down->destroy_requested)
                {
                  ssh_packet_wrapper_destroy(down);
                  return FALSE;
                }
              return TRUE;
            }

          if (data_read < 4 && data_read + ret >= 4)
            {
              /* Header has now been fully received.  Prepare to receive rest
                 of packet. */
              data_read += ret;
              ptr = ssh_buffer_ptr(&down->incoming);
              data_to_read = 4 + SSH_GET_32BIT(ptr);
              if (data_to_read > 100000000L)
                ssh_fatal("ssh_packet_wrapper_input: "
                          "invalid packet received: len %ld",
                          (long)data_to_read);
              if (data_to_read > data_read)
                ssh_buffer_append_space(&down->incoming, &ptr,
                                    data_to_read - data_read);
            }
          else
            data_read += ret;
        }

      /* An entire packet has been received. */
      SSH_ASSERT(ssh_buffer_len(&down->incoming) == data_to_read);

      /* Get packet type. */
      ptr = ssh_buffer_ptr(&down->incoming);
      type = (SshPacketType)ptr[4];

      /* Call the application callback if set. */
      down->cannot_destroy = TRUE;
      if (down->received_packet)
        (*down->received_packet)(type, ptr + 5, data_to_read - 5,
                                 down->context);
      down->cannot_destroy = FALSE;
      if (down->destroy_requested)
        {
          ssh_packet_wrapper_destroy(down);
          return FALSE;
        }
      ssh_buffer_clear(&down->incoming);

      return_value = TRUE;
    }
  /*NOTREACHED*/
}
예제 #4
0
/* For SOCKS5. */
SocksError ssh_socks5_client_generate_open(SshBuffer buffer,
                                           SocksInfo socksinfo)
{
  unsigned char *data;
  unsigned long port;
  size_t bytes = 0L, bytes_needed = 0;
  SshIpAddrStruct ip_addr;
  unsigned int address_type;

  port = ssh_inet_get_port_by_service(socksinfo->port, ssh_custr("tcp"));
  if (port >= 65536 || port <= 0)
    return SSH_SOCKS_ERROR_INVALID_ARGUMENT;

  if (ssh_ipaddr_parse(&ip_addr, socksinfo->ip))
    {
      if (SSH_IP_IS4(&ip_addr))
        address_type = SSH_SOCKS5_ATYP_IPV4;
      else
        address_type = SSH_SOCKS5_ATYP_IPV6;
    }
  else
    {
      SSH_DEBUG(2, ("IP `%s' could not be parsed, assuming it is a hostname.",
                    socksinfo->ip));
      address_type = SSH_SOCKS5_ATYP_FQDN;
    }

  bytes = ssh_encode_buffer(buffer,
                            SSH_ENCODE_CHAR(socksinfo->socks_version_number),
                            SSH_ENCODE_CHAR(socksinfo->command_code),
                            /* RSV. */
                            SSH_ENCODE_CHAR(0),
                            SSH_ENCODE_CHAR(address_type),
                            SSH_FORMAT_END);
  if (bytes == 0)
    {
      SSH_DEBUG(2, ("Encoding command buffer failed."));
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  if (address_type == SSH_SOCKS5_ATYP_IPV4)
    bytes_needed = 4;
  else if (address_type == SSH_SOCKS5_ATYP_IPV6)
    bytes_needed = 16;
  else if (address_type == SSH_SOCKS5_ATYP_FQDN)
    /* length field + address length */
    bytes_needed = 1 + ssh_ustrlen(socksinfo->ip);

  /* port */
  bytes_needed += 2;

  /* Allocate space for the IP-address*/
  if (ssh_buffer_append_space(buffer, &data, bytes_needed) != SSH_BUFFER_OK)
    {
      SSH_DEBUG(2, ("Allocating space for the IP-address failed."));
      ssh_buffer_consume_end(buffer, bytes);
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  if (address_type == SSH_SOCKS5_ATYP_IPV4)
    {
      SSH_IP4_ENCODE(&ip_addr, data);
    }
  else if (address_type == SSH_SOCKS5_ATYP_IPV6)
    {
      SSH_IP6_ENCODE(&ip_addr, data);
    }
  else if (address_type == SSH_SOCKS5_ATYP_FQDN)
    {
      *data = ssh_ustrlen(socksinfo->ip);
      ssh_ustrcpy(data + 1, socksinfo->ip);
    }
  bytes += bytes_needed - 2;
  data += bytes_needed - 2;
  SSH_PUT_16BIT(data, port);
  SSH_DEBUG(4, ("Command buffer size %zd.", bytes + bytes_needed));
  return SSH_SOCKS_SUCCESS;
}
예제 #5
0
/* For SOCKS4. */
SocksError ssh_socks4_client_generate_open(SshBuffer buffer,
                                           SocksInfo socksinfo)
{
  unsigned char *data;
  const unsigned char *username;
  unsigned long port;
  size_t bytes = 0L, ret = 0;
  SshIpAddrStruct ip_addr;

  port = ssh_inet_get_port_by_service(socksinfo->port, ssh_custr("tcp"));
  if (port >= 65536 || port <= 0)
    return SSH_SOCKS_ERROR_INVALID_ARGUMENT;

  if (socksinfo->username == NULL)
    username = ssh_custr("");
  else
    username = socksinfo->username;

  if (ssh_ustrlen(username) > SOCKS4_MAX_NAME_LEN)
    return SSH_SOCKS_ERROR_INVALID_ARGUMENT;

  if (!ssh_ipaddr_parse(&ip_addr, socksinfo->ip))
    {
      SSH_DEBUG(2, ("IP `%s' could not be parsed.", socksinfo->ip));
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  /* nowadays the ip-addresses returned by ssh functions is more and more
     often in ipv6 format (ipv4 addresses are in ipv6 mapped ipv4 format). */
  ssh_inet_convert_ip6_mapped_ip4_to_ip4(&ip_addr);

  if (!SSH_IP_IS4(&ip_addr))
    {
      SSH_DEBUG(2, ("IP `%s' is not a valid IPv4 address.", socksinfo->ip));
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  bytes = ssh_encode_buffer(buffer,
                            SSH_ENCODE_CHAR(socksinfo->socks_version_number),
                            SSH_ENCODE_CHAR(socksinfo->command_code),
                            SSH_ENCODE_CHAR((port & 0xff00U) >> 8),
                            SSH_ENCODE_CHAR(port & 0xffU),
                            SSH_FORMAT_END);
  if (bytes == 0)
    {
      SSH_DEBUG(2, ("Encoding command buffer failed."));
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  /* Allocate space for the IP-address*/
  if (ssh_buffer_append_space(buffer, &data, 4) != SSH_BUFFER_OK)
    {
      SSH_DEBUG(2, ("Allocating space for the IP-address failed."));
      ssh_buffer_consume_end(buffer, bytes);
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  SSH_IP4_ENCODE(&ip_addr, data);
  data += 4;
  bytes += 4;

  ret = ssh_encode_buffer(buffer,
                          SSH_ENCODE_DATA(username,
					  ssh_ustrlen(username)),
                          SSH_ENCODE_DATA(ssh_custr("\0"), 1),
                          SSH_FORMAT_END);
  if (ret == 0)
    {
      SSH_DEBUG(2, ("Encoding username to the command buffer failed."));
      ssh_buffer_consume_end(buffer, bytes);
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  SSH_DEBUG(4, ("Command buffer size %zd.", bytes + ret));
  return SSH_SOCKS_SUCCESS;
}
예제 #6
0
/* Export given IKE SA pointed by negotiation to buffer. Buffer is NOT cleared
   before the export. Returns size of packet added to the buffer, or 0 in case
   of error. In case of error the data added to the buffer is removed. */
size_t ssh_ike_sa_export(SshBuffer buffer, SshIkeNegotiation negotiation)
{
  SshIkeNegotiation ike_negotiation;
  SshIkePMPhaseI pm_info;
  SshIkeSA sa;
  size_t orig_len;
  size_t item_len;
  size_t len;

  SSH_DEBUG(5, ("Start"));

  orig_len = ssh_buffer_len(buffer);
  len = 0;

  sa = negotiation->sa;
  if (sa == NULL)
    {
      SSH_DEBUG(3, ("Trying to export SA that is deleted"));
      goto error;
    }
  if (sa->lock_flags != 0)
    {
      SSH_DEBUG(3, ("Trying to export SA whose lock_flags is not 0"));
      goto error;
    }
  if (!sa->phase_1_done)
    {
      SSH_DEBUG(3, ("Trying to export IKE SA which is not ready yet"));
      goto error;
    }

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

  if (ike_negotiation->notification_state !=
      SSH_IKE_NOTIFICATION_STATE_ALREADY_SENT)
    {
      SSH_DEBUG(3, ("Trying to export IKE SA which hasn't call callback yet"));
      goto error;
    }
  if ((ike_negotiation->lock_flags & ~SSH_IKE_NEG_LOCK_FLAG_WAITING_FOR_DONE)
      != 0)
    {
      SSH_DEBUG(3, ("Trying to export IKE SA whose neg lock_flags are not 0"));
      goto error;
    }

  item_len = ssh_encode_buffer
    (buffer,
     /* Magic number */
     SSH_ENCODE_UINT32((SshUInt32) SSH_IKE_EXPORT_MAGIC1),
     /* Version number */
     SSH_ENCODE_UINT32((SshUInt32) SSH_IKE_EXPORT_VERSION),
     /* Cookies, initiator, responder */
     SSH_ENCODE_DATA(sa->cookies.initiator_cookie, SSH_IKE_COOKIE_LENGTH),
     SSH_ENCODE_DATA(sa->cookies.responder_cookie, SSH_IKE_COOKIE_LENGTH),
     /* Local ip, port. */
     SSH_ENCODE_UINT32_STR(
       pm_info->local_ip, ssh_ustrlen(pm_info->local_ip)),
     SSH_ENCODE_UINT32_STR(
       pm_info->local_port, ssh_ustrlen(pm_info->local_port)),
     /* Remote ip, port. */
     SSH_ENCODE_UINT32_STR(
       pm_info->remote_ip, ssh_ustrlen(pm_info->remote_ip)),
     SSH_ENCODE_UINT32_STR(
       pm_info->remote_port, ssh_ustrlen(pm_info->remote_port)),
     /* IKE exchange version. */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->major_version),
     SSH_ENCODE_UINT32((SshUInt32) pm_info->minor_version),
     /* IKE exchange type. */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->exchange_type),
     /* Was this the initiator for the original exchange? */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->this_end_is_initiator),
     /* Byte count and byte limit. */
     SSH_ENCODE_UINT64((SshUInt64) sa->byte_count),
     SSH_ENCODE_UINT64((SshUInt64) sa->kbyte_limit),
     /* Created time and laste use time */
     SSH_ENCODE_UINT64((SshUInt64) sa->created_time),
     SSH_ENCODE_UINT64((SshUInt64) sa->last_use_time),
     /* Encryption, hash, prf algorithm names. */
     SSH_ENCODE_UINT32_STR(sa->encryption_algorithm_name,
     ssh_ustrlen(sa->encryption_algorithm_name)),
     SSH_ENCODE_UINT32_STR(sa->hash_algorithm_name,
     ssh_ustrlen(sa->hash_algorithm_name)),
     SSH_ENCODE_UINT32_STR(sa->prf_algorithm_name,
     ssh_ustrlen(sa->prf_algorithm_name)),
     /* Cipher key. */
     SSH_ENCODE_UINT32_STR(sa->cipher_key, sa->cipher_key_len),
     /* Cipher IV. */
     SSH_ENCODE_UINT32_STR(sa->cipher_iv, sa->cipher_iv_len),
     /* Keying material, Diffie-Hellman. */
     SSH_ENCODE_UINT32_STR(sa->skeyid.dh, sa->skeyid.dh_size),
     /* Keying material, SKEYID mac. */
     SSH_ENCODE_UINT32_STR(sa->skeyid.skeyid, sa->skeyid.skeyid_size),
     /* Keying material, SKEYID_d mac. */
     SSH_ENCODE_UINT32_STR(sa->skeyid.skeyid_d, sa->skeyid.skeyid_d_size),
     /* Keying material, SKEYID_a mac. */
     SSH_ENCODE_UINT32_STR(sa->skeyid.skeyid_a, sa->skeyid.skeyid_a_size),
     /* Keying material, SKEYID_e mac. */
     SSH_ENCODE_UINT32_STR(sa->skeyid.skeyid_e, sa->skeyid.skeyid_e_size),
     /* Retry defaults. */
     SSH_ENCODE_UINT32(sa->retry_limit),
     SSH_ENCODE_UINT32(sa->retry_timer),
     SSH_ENCODE_UINT32(sa->retry_timer_usec),
     SSH_ENCODE_UINT32(sa->retry_timer_max),
     SSH_ENCODE_UINT32(sa->retry_timer_max_usec),
     SSH_ENCODE_UINT32(sa->expire_timer),
     SSH_ENCODE_UINT32(sa->expire_timer_usec),
     /* Statistics. */
     SSH_ENCODE_UINT32(sa->statistics.packets_in),
     SSH_ENCODE_UINT32(sa->statistics.packets_out),
     SSH_ENCODE_UINT32(sa->statistics.octects_in),
     SSH_ENCODE_UINT32(sa->statistics.octects_out),
     SSH_ENCODE_UINT32(sa->statistics.created_suites),
     SSH_ENCODE_UINT32(sa->statistics.deleted_suites),
     /* IKE SA negotiation information. */
     SSH_ENCODE_UINT32((SshUInt32) ike_negotiation->exchange_type),
     /* This field used to be in negotation structure, now it is in
        ExchangeData strcuture which is already freed. Put the copy of the
        value from pm_info here to be compatible with old versions. */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->auth_method_type),





     SSH_ENCODE_UINT32((SshUInt32) 0),
     /* Private groups as UINT32_STRING. */ 



     SSH_ENCODE_UINT32_STR(ssh_ustr(""), 0),
     SSH_FORMAT_END);
  if (item_len == 0)
    goto error;
  len += item_len;

  /* Local id. */
  item_len = ssh_ike_sa_export_id(buffer, pm_info->local_id);
  if (item_len == 0)
    goto error;
  len += item_len;

  /* Remote id. */
  item_len = ssh_ike_sa_export_id(buffer, pm_info->remote_id);
  if (item_len == 0)
    goto error;
  len += item_len;

  item_len = ssh_encode_buffer
    (buffer,
     /* Authentication type. */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->auth_method_type),
     SSH_ENCODE_UINT32((SshUInt32) pm_info->auth_method),
     /* Start and expire times. */
     SSH_ENCODE_UINT64((SshUInt64) pm_info->sa_start_time),
     SSH_ENCODE_UINT64((SshUInt64) pm_info->sa_expire_time),
     /* 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_ENCODE_UINT32((SshUInt32) pm_info->doi),
     /* Magic number */
     SSH_ENCODE_UINT32((SshUInt32) SSH_IKE_EXPORT_MAGIC2),
     SSH_FORMAT_END);
  if (item_len == 0)
    goto error;
  len += item_len;
  return len;
 error:
  orig_len -= ssh_buffer_len(buffer);
  if (orig_len != 0)
    ssh_buffer_consume_end(buffer, orig_len);
  return 0;
}
예제 #7
0
/* Expore identity payload to buffer. Buffer is NOT cleared, before the
   export. Returns size of the data added to the buffer, or 0 in case of error.
   In case of error the data added to the buffer is removed. */
size_t ssh_ike_sa_export_id(SshBuffer buffer, SshIkePayloadID id)
{
  size_t orig_len;
  size_t item_len;
  size_t len;

  SSH_DEBUG(5, ("Start"));

  orig_len = ssh_buffer_len(buffer);
  len = 0;
  if (id == NULL)
    {
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_UINT32((SshUInt32) 0),
         SSH_FORMAT_END);
      if (item_len == 0)
        goto error;
      len += item_len;
      return len;
    }
  item_len = ssh_encode_buffer
    (buffer,
     SSH_ENCODE_UINT32((SshUInt32) id->id_type),
     SSH_ENCODE_UINT32((SshUInt32) id->protocol_id),
     SSH_ENCODE_UINT32((SshUInt32) id->port_number),
     SSH_ENCODE_UINT32((SshUInt32) id->port_range_end),
     SSH_FORMAT_END);
  if (item_len == 0)
    goto error;
  len += item_len;
  switch (id->id_type)
    {
    case IPSEC_ID_IPV4_ADDR:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_DATA(id->identification.ipv4_addr, 4),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_FQDN:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_UINT32_STR(id->identification.fqdn,
         id->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_USER_FQDN:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_UINT32_STR(id->identification.user_fqdn,
         id->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV4_ADDR_SUBNET:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_DATA(id->identification.ipv4_addr_subnet, 4),
         SSH_ENCODE_DATA(id->identification.ipv4_addr_netmask, 4),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV6_ADDR:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_DATA(id->identification.ipv6_addr, 16),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV6_ADDR_SUBNET:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_DATA(id->identification.ipv6_addr_subnet, 16),
         SSH_ENCODE_DATA(id->identification.ipv6_addr_netmask, 16),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV4_ADDR_RANGE:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_DATA(id->identification.ipv4_addr_range1, 4),
         SSH_ENCODE_DATA(id->identification.ipv4_addr_range2, 4),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV6_ADDR_RANGE:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_DATA(id->identification.ipv6_addr_range1, 16),
         SSH_ENCODE_DATA(id->identification.ipv6_addr_range2, 16),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_DER_ASN1_DN:
    case IPSEC_ID_DER_ASN1_GN:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_UINT32_STR(id->identification.asn1_data,
         id->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_KEY_ID:
      item_len = ssh_encode_buffer
        (buffer,
         SSH_ENCODE_UINT32_STR(id->identification.key_id,
         id->identification_len),
         SSH_FORMAT_END);
      break;
#ifdef SSHDIST_IKE_ID_LIST
    case IPSEC_ID_LIST:
      {
        int cnt;

        item_len = ssh_encode_buffer(buffer,
                                     SSH_ENCODE_UINT32(
                                     (SshUInt32) id->identification.
                                     id_list_number_of_items),
                                     SSH_FORMAT_END);
        if (item_len == 0)
          goto error;
        len += item_len;
        for (cnt = 0;
             cnt < id->identification.id_list_number_of_items;
             cnt++)
          {
            item_len =
              ssh_ike_sa_export_id(buffer,
                                   &(id->identification.id_list_items[cnt]));
            if (item_len == 0)
              goto error;
            len += item_len;
          }
        break;
      }
#endif /* SSHDIST_IKE_ID_LIST */
    }
  if (item_len == 0)
    goto error;
  len += item_len;
  return len;
 error:
  orig_len -= ssh_buffer_len(buffer);
  if (orig_len != 0)
    ssh_buffer_consume_end(buffer, orig_len);
  return 0;
}