示例#1
0
/* Decode question. */
Boolean ssh_dns_packet_decode_question(SshDNSPacket packet,
				       const unsigned char *packet_buffer,
				       size_t packet_length,
				       size_t *offset_ptr,
				       SshDNSQuestion question)
{
  SshUInt16 qtype, qclass;
  size_t len;

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

  len = ssh_decode_array(packet_buffer + *offset_ptr,
			 packet_length - *offset_ptr,
			 SSH_DECODE_UINT16(&qtype),
			 SSH_DECODE_UINT16(&qclass),
			 SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(SSH_D_NETGARB, ("Error decoding question"));
      return FALSE;
    }

  *offset_ptr += len;
  question->qtype = qtype;
  question->qclass = qclass;
  return TRUE;
}
示例#2
0
文件: sshchtcpfwd.c 项目: AnthraX1/rk
Boolean ssh_channel_tcp_forward_cancel(const char *type,
                                       const unsigned char *data,
                                       size_t len,
                                       void *context)
{
  SshCommon common = (SshCommon)context;
  char *address_to_bind;
  SshUInt32 port;
  char port_string[20];
  SshRemoteTcpForward fwd, *fwdp;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("remote TCP/IP cancel request received"));

  ct = ssh_channel_ftcp_ct(common);
  
  /* Don't allow a server to send remote forwarding requests to the client. */
  if (common->client)
    {
      ssh_warning("Remote TCP/IP forwarding cancel from server denied.");
      return FALSE;
    }
  
  /* Parse the request. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG(0, ("bad data"));
      return FALSE;
    }

  /* Convert port number to a string. */
  snprintf(port_string, sizeof(port_string), "%ld", (unsigned long) port);

  for (fwdp = &ct->remote_forwards; *fwdp; fwdp = &fwd->next)
    {
      fwd = *fwdp;
      if (strcmp(port_string, fwd->port) == 0 &&
          strcmp(address_to_bind, fwd->address_to_bind) == 0)
        {
          ssh_tcp_destroy_listener(fwd->listener);
          ssh_xfree(fwd->address_to_bind);
          ssh_xfree(fwd->port);
          *fwdp = fwd->next;
          ssh_xfree(fwd);
          ssh_xfree(address_to_bind);
          return TRUE;
        }
    }

  SSH_DEBUG(1, ("port %s address_to_bind %s not found",
                port_string, address_to_bind));
  ssh_xfree(address_to_bind);
  return FALSE;
}
示例#3
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);
    }
}
示例#4
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");
}
示例#5
0
/*
 * Parse methods array. This doesn't do anything with SOCKS4.
 */
SocksError ssh_socks_server_parse_methods(SshBuffer buffer,
                                          SocksInfo *socksinfo)
{
  size_t ret = 0L, len;
  unsigned int version, num_methods;
  unsigned char *data;

  data = ssh_buffer_ptr(buffer);
  len = ssh_buffer_len(buffer);

  if (len < 1)
    return SSH_SOCKS_TRY_AGAIN;

  version = *data;

  if (version == 4)
    goto return_success;

  if (len < 2)
    return SSH_SOCKS_TRY_AGAIN;

  ret = ssh_decode_array(data, len,
                         SSH_DECODE_CHAR(&version),
                         SSH_DECODE_CHAR(&num_methods),
                         SSH_FORMAT_END);
  if (ret == 0)
    {
      SSH_DEBUG(2, ("Decoding methods buffer failed."));
      return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
    }
  if (len < num_methods + 2)
    return SSH_SOCKS_TRY_AGAIN;

  ssh_buffer_consume(buffer, num_methods + 2);

 return_success:
  if (socksinfo)
    {
      *socksinfo = ssh_calloc(1, sizeof(**socksinfo));
      if (*socksinfo == NULL)
        {
          SSH_DEBUG(2, ("Couldn't allocate SshSocksInfo."));
          return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
        }
      (*socksinfo)->socks_version_number = version;
    }
  return SSH_SOCKS_SUCCESS;
}
示例#6
0
void decode_case_char(SshEncodingFormat fmt, unsigned char value)
{
  unsigned int ch;
  size_t bytes;

  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, SSH_FORMAT_END))
    ssh_fatal("decode_case_char: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, &ch, SSH_FORMAT_END))
    ssh_fatal("decode_case_char: bad returned len");
  if (ch != value)
    ssh_fatal("decode_case_char: bad value");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_char: data left");
}
示例#7
0
void decode_case_bool(SshEncodingFormat fmt, Boolean value)
{
  Boolean boo;
  size_t bytes;

  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, SSH_FORMAT_END))
    ssh_fatal("decode_case_bool: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, &boo, SSH_FORMAT_END))
    ssh_fatal("decode_case_bool: bad returned len");
  if (boo != value)
    ssh_fatal("decode_case_bool: bad value");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_bool: data left");
}
示例#8
0
void decode_case_data(SshEncodingFormat fmt,
                      const char *value, size_t valuelen)
{
  char buf[1024];
  size_t bytes;

  SSH_ASSERT(valuelen < sizeof(buf));
  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, valuelen, SSH_FORMAT_END))
    ssh_fatal("decode_case_data: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, buf, valuelen,
                                       SSH_FORMAT_END))
    ssh_fatal("decode_case_data: bad returned len");
  if (memcmp(buf, value, valuelen) != 0)
    ssh_fatal("decode_case_data: bad value");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_data: data left");
}
示例#9
0
void decode_case_str(SshEncodingFormat fmt, const char *value, size_t valuelen)
{
  unsigned char *cp;
  size_t len, bytes;

  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, NULL, SSH_FORMAT_END))
    ssh_fatal("decode_case_str: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, &cp, &len, SSH_FORMAT_END))
    ssh_fatal("decode_case_str: bad returned len");
  if (len != valuelen || memcmp(cp, value, len) != 0)
    ssh_fatal("decode_case_str: bad cmp");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_str: data left");
  if (cp[len] != 0)
    ssh_fatal("decode_case_str: not null terminated");
  ssh_xfree(cp);
}
void ssh_engine_from_ipm_set_debug(SshEngine engine,
                                   const unsigned char *data, size_t len)
{
    char *s;

    /* Decode the packet. */
    if (ssh_decode_array(data, len,
                         SSH_FORMAT_UINT32_STR, &s, NULL,
                         SSH_FORMAT_END) != len)
    {
        SSH_DEBUG_HEXDUMP(0, ("Bad set debug from policy manager"),
                          data, len);
        return;
    }

    /* Set debug level according to the stringl. */



    ssh_debug_set_level_string(s);
    SSH_DEBUG(1, ("Engine debug level set to %s", s));
    ssh_free(s);
}
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;
}
示例#12
0
文件: sshchtcpfwd.c 项目: AnthraX1/rk
void ssh_channel_ftcp_open_request(const char *type, int channel_id,
                                   const unsigned char *data, size_t len,
                                   SshConnOpenCompletionProc completion,
                                   void *completion_context, void *context)
{
  SshCommon common = (SshCommon)context;
  SshUInt32 port, originator_port;
  char *address_to_bind, *originator_ip;
  char port_string[20];
  SshRemoteTcpForward fwd;
  SshChannelTcpFwdConnect c;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("open request for remote forwarded TCP/IP channel"));

  ct = ssh_channel_ftcp_ct(common);

  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port, 
                       SSH_FORMAT_UINT32_STR, &originator_ip, NULL,
                       SSH_FORMAT_UINT32, &originator_port,
                       SSH_FORMAT_END) != len)
    {
      /* XXX should disconnect? */
      SSH_DEBUG(0, ("bad data"));
      (*completion)(SSH_OPEN_RESOURCE_SHORTAGE,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }

  snprintf(port_string, sizeof(port_string), "%ld", (long) port);

  ssh_debug("Received remote TCP/IP forward connect for port %s from %s:%ld",
            port_string, originator_ip, (long)originator_port);
  
  for (fwd = ct->remote_forwards; fwd; fwd = fwd->next)
    if (strcmp(fwd->address_to_bind, address_to_bind) == 0 &&
        strcmp(fwd->port, port_string) == 0)
      {
        c = ssh_xcalloc(1, sizeof(*c));
        c->fwd = fwd;
        c->channel_id = channel_id;
        c->completion = completion;
        c->completion_context = completion_context;

        ssh_tcp_connect_with_socks(fwd->connect_to_host, fwd->connect_to_port,
                           NULL, 1, ssh_channel_ftcp_open_connected,
                           (void *)c);

        ssh_xfree(address_to_bind);
        ssh_xfree(originator_ip);
        return;
      }

  ssh_warning("Received remote TCP/IP connect for non-forwarded port %s from %s:%ld",
              port_string, originator_ip, (long)originator_port);

  ssh_xfree(address_to_bind);
  ssh_xfree(originator_ip);
  
  (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                completion_context);
}
示例#13
0
/* Decode packet. This returns NULL if there is memory error or parse error,
   otherwise it will return the decoded packet. */
SshDNSPacket ssh_dns_packet_decode(const unsigned char *packet_buffer,
				   size_t packet_length)
{
  SshUInt16 question_count, answer_count, authority_count, additional_count;
  SshUInt16 id, flags;
  SshDNSPacket packet;
  size_t len;
  int i;

  len = ssh_decode_array(packet_buffer, packet_length,
			 SSH_DECODE_UINT16(&id),
			 SSH_DECODE_UINT16(&flags),
			 SSH_DECODE_UINT16(&question_count),
			 SSH_DECODE_UINT16(&answer_count),
			 SSH_DECODE_UINT16(&authority_count),
			 SSH_DECODE_UINT16(&additional_count),
			 SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(SSH_D_NETGARB, ("Error decoding dns packet"));
      return NULL;
    }

  packet = ssh_dns_packet_allocate(question_count, answer_count,
				   authority_count, additional_count);
  if (packet == NULL)
    return NULL;

  packet->id = id;
  packet->flags = flags & SSH_DNS_FLAG_MASK;
  packet->op_code = (flags >> 11) & 0xf;
  packet->response_code = flags & 0xf;

  for (i = 0; i < question_count; i++)
    {
      if (!ssh_dns_packet_decode_question(packet, packet_buffer,
					  packet_length, &len,
					  &(packet->question_array[i])))
	goto error;
    }
  for (i = 0; i < answer_count; i++)
    {
      if (!ssh_dns_packet_decode_record(packet, packet_buffer,
					packet_length, &len,
					&(packet->answer_array[i])))
	goto error;
    }
  for (i = 0; i < authority_count; i++)
    {
      if (!ssh_dns_packet_decode_record(packet, packet_buffer,
					packet_length, &len,
					&(packet->authority_array[i])))
	goto error;
    }
  for (i = 0; i < additional_count; i++)
    {
      if (!ssh_dns_packet_decode_record(packet, packet_buffer,
					packet_length, &len,
					&(packet->additional_array[i])))
	goto error;
    }
  if (packet_length > len)
    {



      SSH_DEBUG(SSH_D_NETGARB, ("Dns packet contains %d bytes of extra data",
				packet_length - len));
    }
  return packet;
 error:
  ssh_dns_packet_free(packet);
  return NULL;
}
示例#14
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;
  
}
示例#15
0
static void
receive_virtual_adapter_packet_cb(SshInterceptor interceptor, 
				  const unsigned char *data, size_t len)
{
  SshUInt32 flags;
  SshUInt32 ifnum_in, ifnum_out;
  SshUInt32 protocol;
  const unsigned char *packet, *internal;
  size_t packet_len, internal_len;
  SshInterceptorVirtualAdapter va;
  SshInterceptorPacket pp;

  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32, &flags,
                       SSH_FORMAT_UINT32, &ifnum_in,
                       SSH_FORMAT_UINT32, &ifnum_out,
                       SSH_FORMAT_UINT32, &protocol,
                       SSH_FORMAT_UINT32_STR_NOCOPY, &packet, &packet_len,
                       SSH_FORMAT_UINT32_STR_NOCOPY, &internal, &internal_len,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG_HEXDUMP(SSH_D_ERROR, ("bad virtual adapter receive message"),
                        data, len);
      return;
    }

  /* Find the virtual adapter of this receive operation. */
  ssh_mutex_lock(interceptor->mutex);
  for (va = interceptor->virtual_adapters; va; va = va->next)
    if (va->adapter_ifnum == ifnum_in)
      break;
  ssh_mutex_unlock(interceptor->mutex);

  if (va == NULL)
    {
      SSH_DEBUG(SSH_D_ERROR,
                ("virtual adapter receive for unknown adapter %d",
		 (int) ifnum_in));
      return;
    }

  if (va->packet_cb == NULL_FNPTR)
    return;

  /* Assert that the interface numbers fit into SshInterceptorIfnum. */
  SSH_ASSERT(ifnum_in <= SSH_INTERCEPTOR_MAX_IFNUM);
  SSH_ASSERT(ifnum_out <= SSH_INTERCEPTOR_MAX_IFNUM);

  /* Allocate a packet object. */
  pp = ssh_interceptor_packet_alloc(interceptor, 
				    SSH_PACKET_FROMADAPTER, 
				    protocol,
                                    (SshInterceptorIfnum) ifnum_in, 
				    (SshInterceptorIfnum) ifnum_out, 
				    packet_len);

  if (pp == NULL)
    {
      SSH_DEBUG(SSH_D_ERROR,
                ("could not allocate packet for virtual adapter receive"));
      return;
    }

  if (!ssh_interceptor_packet_import_internal_data(pp, internal, internal_len))
    {
      SSH_DEBUG(SSH_D_ERROR, ("import failed"));
      return;
    }

  pp->flags = flags;

  if (!ssh_interceptor_packet_copyin(pp, 0, packet, packet_len))
    {
      SSH_DEBUG(SSH_D_ERROR, ("copyin failed, dropping packet"));
      return;
    }

  SSH_DEBUG(SSH_D_NICETOKNOW, 
	    ("received packet callback for virtual adapter %d from forwarder.",
	     (int) ifnum_in));

  /* Pass the packet to the user-supplied packet callback. */
  (*va->packet_cb)(interceptor, pp, va->adapter_context);
}
示例#16
0
static void
receive_virtual_adapter_status_cb(SshInterceptor interceptor, 
				  const unsigned char *data,
				  size_t len)
{
  SshUInt32 operation_id;
  SshUInt32 error;
  SshUInt32 adapter_ifnum;
  char *adapter_name;
  SshUInt32 adapter_state;
  SshInterceptorVirtualAdapterOp op;
  SshInterceptorVirtualAdapter va;
  void *adapter_context;
  
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32, &operation_id,
                       SSH_FORMAT_UINT32, &error,
                       SSH_FORMAT_UINT32, &adapter_ifnum,
                       SSH_FORMAT_UINT32_STR_NOCOPY, &adapter_name, NULL,
                       SSH_FORMAT_UINT32, &adapter_state,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG_HEXDUMP(SSH_D_ERROR, ("bad virtual adapter status message"),
                        data, len);
      return;
    }

  /* Lookup the pending operation. */
  op = lookup_virtual_adapter_op(interceptor, operation_id);
  if (op == NULL)
    {
      SSH_DEBUG(SSH_D_ERROR, ("unknown virtual adapter operation ID %d",
                              (int) operation_id));
      return;
    }

  /* Handle attach operations separately. */
  if (op->attach)
    {
      receive_virtual_adapter_attach_cb(interceptor, error, 
					adapter_ifnum, adapter_name, 
					adapter_state, op);
      return;
    }

  /* Is the operation aborted? */
  if (op->aborted)
    {
      /* Free the operation context. */
      free_virtual_adapter_op(interceptor, op);
      return;
    }

  /* Lookup virtual adapter. */
  ssh_mutex_lock(interceptor->mutex);
  for (va = interceptor->virtual_adapters; va; va = va->next)
    if (va->adapter_ifnum == adapter_ifnum)
      break;
  ssh_mutex_unlock(interceptor->mutex);

  /* Take adapter context from virtual adapter, if it was found. */
  if (va == NULL)
    adapter_context = op->adapter_context;
  else
    adapter_context = va->adapter_context;

  SSH_DEBUG(SSH_D_NICETOKNOW, 
	    ("received status callback for virtual adapter %d from forwarder, "
	     "error %d", (int) adapter_ifnum, (int) error));

  /* Call the completion function. */
  if (op->status_cb)
    (*op->status_cb)((SshVirtualAdapterError) error,
		     (SshInterceptorIfnum) adapter_ifnum, adapter_name,
		     (SshVirtualAdapterState) adapter_state,
		     adapter_context, op->context);

  /* Free operation context if there will be no more status callbacks
     to this operation. */
  if (error != SSH_VIRTUAL_ADAPTER_ERROR_OK_MORE)
    {
      /* Unregister operation handle and free operation context. */
      ssh_operation_unregister(op->handle);
      free_virtual_adapter_op(interceptor, op);
    }
}
示例#17
0
/*
 * Parse incoming socks connection from buffer. Consume the request
 * packet data from buffer. If everything is ok it allocates SocksInfo
 * strcture and store the request fields in it (sets
 * socks_version_number, command_code, ip, port, username). Returns
 * SSH_SOCKS_SUCCESS, SSH_SOCKS_TRY_AGAIN, or SSH_SOCKS_ERROR_*. If
 * anything other than SSH_SOCKS_SUCCESS is returned the socksinfo is
 * set to NULL.  Use ssh_socks_free to free socksinfo data.
 */
SocksError ssh_socks_server_parse_open(SshBuffer buffer, SocksInfo *socksinfo)
{
  unsigned char *data, *ip;
  unsigned long i, port;
  unsigned int version, cmd, ip_addr_len, atyp;
  unsigned char *username = NULL;
  size_t ret, len, bytes = 0;

  *socksinfo = NULL;
  len = ssh_buffer_len(buffer);
  data = ssh_buffer_ptr(buffer);

  if (len < 1)
    return SSH_SOCKS_TRY_AGAIN;

  version = data[0];
  bytes++;

  if (version != 4 && version != 5)
    {
      SSH_DEBUG(2, ("Server gave us version %d.", version));
      return SSH_SOCKS_ERROR_UNSUPPORTED_SOCKS_VERSION;
    }

  if (version == 4)
    {
      /* Check if enough data for header and name */
      if (len < SOCKS4_COMMAND_SIZE + 1)
        {
          return SSH_SOCKS_TRY_AGAIN;
        }


      /* Find the end of username */
      for (i = SOCKS4_COMMAND_SIZE; i < len; i++)
        {
          if (data[i] == '\0')
            break;
        }

      /* End of username not found, return either error or try_again */
      if (i == len || data[i] != '\0')
        {
          if (len > SOCKS4_COMMAND_SIZE + SOCKS4_MAX_NAME_LEN)
            {
              return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
            }
          return SSH_SOCKS_TRY_AGAIN;
        }

      cmd = data[1];

      port = SSH_GET_16BIT(&data[2]);

      ip_addr_len = 4;
      ip = ssh_memdup(&data[4], ip_addr_len);
      atyp = SSH_SOCKS5_ATYP_IPV4;

      if (ip == NULL)
        {
          SSH_DEBUG(2, ("Failed to allocate IP-address buffer."));
          return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
        }

      username = ssh_strdup((char *)(data + SOCKS4_COMMAND_SIZE));
      bytes = SOCKS4_COMMAND_SIZE +
        strlen((char *) data + SOCKS4_COMMAND_SIZE) + 1;
    }
  else
    {
      unsigned char port_buf[2];

      if (len - bytes < 3)
        return SSH_SOCKS_TRY_AGAIN;

      ret = ssh_decode_array(data + bytes, len - bytes,
                             SSH_DECODE_CHAR(&cmd),
                             SSH_DECODE_CHAR(NULL), /* RSV */
                             SSH_DECODE_CHAR(&atyp),
                             SSH_FORMAT_END);
      if (ret <= 0)
        {
          SSH_DEBUG(2, ("Failed to decode command packet."));
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      bytes += ret;
      if (atyp == SSH_SOCKS5_ATYP_IPV4)
        {
          SSH_DEBUG(4, ("SOCKS5 received address type IPV4."));
          ip_addr_len = 4;
        }
      else if (atyp == SSH_SOCKS5_ATYP_IPV6)
        {
          SSH_DEBUG(4, ("SOCKS5 received address type IPV6."));
          ip_addr_len = 16;
        }
      else if (atyp == SSH_SOCKS5_ATYP_FQDN)
        {
          if (len - bytes < 1)
            return SSH_SOCKS_TRY_AGAIN;

          ip_addr_len = *(data + bytes);
          if (ip_addr_len <= 0 || ip_addr_len >= 255)
            {
              SSH_DEBUG(2, ("Invalid FQDN address len %d.", ip_addr_len));
              return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
            }
          SSH_DEBUG(4, ("SOCKS5 received address type FQDN, len %d.",
                        ip_addr_len));
          bytes++;
        }
      else
        {
          SSH_DEBUG(2, ("Invalid address type %d.", atyp));
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      /* ip addr len + port */
      if (len - bytes < ip_addr_len + 2)
        return SSH_SOCKS_TRY_AGAIN;

      ip = ssh_calloc(ip_addr_len + 1, sizeof(unsigned char));
      if (ip == NULL)
        {
          SSH_DEBUG(2, ("Failed to allocate IP-address buffer."));
          return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
        }
      ret = ssh_decode_array(data + bytes, len - bytes,
                             SSH_DECODE_DATA(ip, ip_addr_len),
                             SSH_DECODE_DATA(port_buf, 2),
                             SSH_FORMAT_END);
      if (ret <= 0)
        {
          SSH_DEBUG(2, ("Failed to decode command packet."));
          ssh_free(ip);
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      port = SSH_GET_16BIT(port_buf);
      bytes += ret;
    }

  if ((*socksinfo = ssh_calloc(1, sizeof(struct SocksInfoRec))) == NULL)
    {
      SSH_DEBUG(2, ("Failed to allocate SocksInfo."));
      ssh_free(ip);
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }

  if (atyp == SSH_SOCKS5_ATYP_FQDN)
    {
      (*socksinfo)->ip = ip;
    }
  else
    {
      SshIpAddrStruct ip_addr;
      unsigned char buf[SSH_IP_ADDR_STRING_SIZE];

      SSH_IP_DECODE(&ip_addr, ip, ip_addr_len);

      ssh_ipaddr_print(&ip_addr, buf, sizeof(buf));
      (*socksinfo)->ip = ssh_memdup(buf, ssh_ustrlen(buf));
      ssh_free(ip);
      if ((*socksinfo)->ip == NULL)
        {
          SSH_DEBUG(2, ("Failed to allocate final IP-addr buf."));
          return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
        }
    }

  (*socksinfo)->socks_version_number = version;
  (*socksinfo)->command_code = cmd;
  ssh_dsprintf(&(*socksinfo)->port, "%lu", port);
  (*socksinfo)->username = username;
  ssh_buffer_consume(buffer, bytes);
  SSH_DEBUG(5, ("Decoded %zd bytes.", bytes));
  return SSH_SOCKS_SUCCESS;
}
示例#18
0
/*
 * Parse socks reply packet. Consume the reply packet data from buffer.
 * If the request was not granted (returns SSH_SOCKS_FAILED_*) the socket can
 * be immediately closed down (there will not be any additional data from the
 * socks server.
 * If the request is granted allocate socksinfo structure and store information
 * from request packet to there (sets socks_version_number, command_code, ip,
 * and port fields).
 * Use ssh_socks_free to free socksinfo data.
 */
SocksError ssh_socks_client_parse_reply(SshBuffer buffer,
                                        SocksInfo *socksinfo)
{
  unsigned char *data, *ip_ptr, *port_ptr;
  unsigned char *username =NULL;
  unsigned long len, port, version;
  size_t bytes = 0;
  unsigned int cmd, atyp, ip_addr_len;

  if (socksinfo)
    *socksinfo = NULL;
  len = ssh_buffer_len(buffer);
  data = ssh_buffer_ptr(buffer);

  /* Check if enough data for version. */
  if (len < 1)
    return SSH_SOCKS_TRY_AGAIN;

  version = data[0];
  /* SOCKS4 replys have version number '0'. Go figure. */
  if (version == 0)
    version = 4;
  bytes++;

  if (version != 4 && version != 5)
    {
      SSH_DEBUG(2, ("Server gave us version %ld.", version));
      return SSH_SOCKS_ERROR_UNSUPPORTED_SOCKS_VERSION;
    }

  if (version == 4)
    {
      /* A SOCKS4 command reply is exactly 8 bytes long. */
      if (len < 8)
        return SSH_SOCKS_TRY_AGAIN;
      SSH_DEBUG(2, ("Doing SOCKS4."));
      bytes = 8;

      if (data[1] != SSH_SOCKS4_REPLY_GRANTED)
        {
          SocksError error = SSH_SOCKS_ERROR_PROTOCOL_ERROR;
          switch (data[1])
            {
            case SSH_SOCKS4_REPLY_FAILED_REQUEST:
              error = SSH_SOCKS_FAILED_REQUEST;
              break;
            case SSH_SOCKS4_REPLY_FAILED_IDENTD:
              error = SSH_SOCKS_FAILED_IDENTD;
              break;
            case SSH_SOCKS4_REPLY_FAILED_USERNAME:
              error = SSH_SOCKS_FAILED_USERNAME;
              break;
            default:
              error = SSH_SOCKS_ERROR_PROTOCOL_ERROR;
              break;
            }
          ssh_buffer_consume(buffer, bytes);
          return error;
        }

      cmd = data[1];
      port_ptr = &data[2];
      ip_ptr = &data[4];
      ip_addr_len = 4;
      atyp = SSH_SOCKS5_ATYP_IPV4;
      username = (unsigned char *)&data[8];
    }
  else
    {
      size_t ret = 0L;

      /* SOCKS5. */
      if (len - bytes < 3)
        return SSH_SOCKS_TRY_AGAIN;

      ret = ssh_decode_array(data + bytes, len - bytes,
                             SSH_DECODE_CHAR(&cmd),
                             SSH_DECODE_CHAR(NULL), /* RSV */
                             SSH_DECODE_CHAR(&atyp),
                             SSH_FORMAT_END);
      if (ret == 0)
        {
          SSH_DEBUG(2, ("Decoding reply packet failed."));
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      bytes += ret;
      if (atyp == SSH_SOCKS5_ATYP_IPV4)
        {
          ip_addr_len = 4;
        }
      else if (atyp == SSH_SOCKS5_ATYP_IPV6)
        {
          ip_addr_len = 16;
        }
      else if (atyp == SSH_SOCKS5_ATYP_FQDN)
        {
          if (len - bytes < 1)
            return SSH_SOCKS_TRY_AGAIN;
          ret = ssh_decode_array(data + bytes, len - bytes,
                                 SSH_DECODE_CHAR(&ip_addr_len),
                                 SSH_FORMAT_END);
          if (ret == 0)
            {
              SSH_DEBUG(2, ("Decoding FQDN hostname len failed."));
              return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
            }
          bytes += ret;
        }
      else
        {
          SSH_DEBUG(2, ("Invalid address type %d.", atyp));
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      /* ip addr len + port (2 bytes) */
      if (len - bytes < ip_addr_len + 2)
        return SSH_SOCKS_TRY_AGAIN;

      ip_ptr = data + bytes;
      if (ret == 0)
        {
          SSH_DEBUG(2, ("Decoding reply packet failed."));
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      bytes += ip_addr_len;

      port_ptr = data + bytes;
      bytes += 2;
      SSH_DEBUG(2, ("Doing SOCKS5."));

      if (cmd != SSH_SOCKS5_REPLY_SUCCESS)
        {
          SSH_DEBUG(2, ("Got reply %d from server.", cmd));
          if (cmd < SSH_SOCKS5_REPLY_SUCCESS ||
              cmd > SSH_SOCKS5_REPLY_ATYP_NOT_SUPPORTED)
            return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
          return SSH_SOCKS_FAILED_REQUEST;
        }
    }

  if (socksinfo)
    {
      SshIpAddrStruct ip_addr;

      if ((*socksinfo = ssh_calloc(1, sizeof(SocksInfoStruct))) == NULL)
        {
          SSH_DEBUG(2, ("Couldn't allocate SocksInfo."));
          return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
        }

      memset(&ip_addr, 0, sizeof(ip_addr));
      (*socksinfo)->socks_version_number = version;
      (*socksinfo)->command_code = cmd;

      port = SSH_GET_16BIT(port_ptr);
      ssh_dsprintf(&(*socksinfo)->port, "%lu", port);
      if (username)
        (*socksinfo)->username = ssh_strdup(username);
      else
        (*socksinfo)->username = NULL;

      if (atyp == SSH_SOCKS5_ATYP_FQDN)
        {
          (*socksinfo)->ip = ssh_calloc(ip_addr_len + 1, sizeof(char));
          if ((*socksinfo)->ip)
            memmove((*socksinfo)->ip, ip_ptr, ip_addr_len);
        }
      else
        {
          unsigned char buf[SSH_IP_ADDR_STRING_SIZE];

          SSH_IP_DECODE(&ip_addr, ip_ptr, ip_addr_len);
          ssh_ipaddr_print(&ip_addr, buf, sizeof(buf) - 1);
          (*socksinfo)->ip = ssh_strdup(buf);
        }
    }

  SSH_DEBUG(2, ("Decoded %zd bytes.", bytes));
  ssh_buffer_consume(buffer, bytes);
  return SSH_SOCKS_SUCCESS;
}
示例#19
0
文件: sshchtcpfwd.c 项目: AnthraX1/rk
void ssh_channel_dtcp_open_request(const char *type, int channel_id,
                                   const unsigned char *data, size_t len,
                                   SshConnOpenCompletionProc completion,
                                   void *completion_context, void *context)
{
  SshCommon common = (SshCommon)context;
  char *connect_to_host, connect_to_port[20], *originator_ip;
  SshUInt32 port, originator_port;
  SshDirectTcp tcp;

  SSH_DEBUG(5, ("direct TCP/IP channel open request"));
  
  /* Parse packet data. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &connect_to_host, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_UINT32_STR, &originator_ip, NULL,
                       SSH_FORMAT_UINT32, &originator_port,
                       SSH_FORMAT_END) != len)
    {
      /* XXX disconnect? */
      SSH_DEBUG(0, ("bad data"));
      (*completion)(SSH_OPEN_RESOURCE_SHORTAGE,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }

  /* We do not currently allow direct connections from server to client. */
  if (common->client)
    {
      ssh_warning("Direct TCP/IP connection request from server "
                  "to %s:%ld denied.",
                  connect_to_host, (long)port);
      /* Free dynamically allocated data. */
      ssh_xfree(originator_ip);
      ssh_xfree(connect_to_host);
      (*completion)(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
                    NULL, FALSE, FALSE, 0, NULL, 0, NULL, NULL, NULL,
                    completion_context);
      return;
    }


  /* Convert port number to string. */
  snprintf(connect_to_port, sizeof(connect_to_port), "%ld", (long) port);

  ssh_debug("Direct TCP/IP connect to %s:%s from %s:%ld",
            connect_to_host, connect_to_port, originator_ip,
            (long)originator_port);
  
  /* Save data for callback. */
  tcp = ssh_xcalloc(1, sizeof(*tcp));
  tcp->common = common;
  tcp->channel_id = channel_id;
  tcp->completion = completion;
  tcp->completion_context = completion_context;

  /* Connect to the given host/port. */
  ssh_tcp_connect_with_socks(connect_to_host, connect_to_port, 
                             NULL, 1, ssh_channel_dtcp_connected, 
                             (void *)tcp);

  /* Free dynamically allocated data. */
  ssh_xfree(originator_ip);
  ssh_xfree(connect_to_host);
}
示例#20
0
文件: sshchtcpfwd.c 项目: AnthraX1/rk
Boolean ssh_channel_remote_tcp_forward_request(const char *type,
                                               const unsigned char *data,
                                               size_t len,
                                               void *context)
{
  SshCommon common = (SshCommon)context;
  char *address_to_bind;
  SshUInt32 port;
  char port_string[20];
  SshRemoteTcpForward fwd;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("remote TCP/IP forwarding request received"));
  ssh_log_event(common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Remote TCP/IP forwarding request received from host \"%s\", "\
                "by authenticated user \"%s\".",
                common->remote_host,
                ssh_user_name(common->user_data));
  
  ct = ssh_channel_ftcp_ct(common);
  
  /* Don't allow a server to send remote forwarding requests to the client. */
  if (common->client)
    {
      ssh_warning("Remote TCP/IP forwarding request from server denied.");
      return FALSE;
    }
  
  /* Parse the request. */
  if (ssh_decode_array(data, len,
                       SSH_FORMAT_UINT32_STR, &address_to_bind, NULL,
                       SSH_FORMAT_UINT32, &port,
                       SSH_FORMAT_END) != len)
    {
      SSH_DEBUG(0, ("bad data"));
      return FALSE;
    }

  /* Convert port number to a string. */
  snprintf(port_string, sizeof(port_string), "%ld", (unsigned long) port);

  /* If user is not logged in as a privileged user, don't allow
     forwarding of privileged ports. */
  if (port < 1024)
    {
      if (ssh_user_uid(common->user_data))
        {
          SSH_TRACE(2, ("User \"%s\" not root, tried to forward " \
                        "privileged port %ld.",
                        ssh_user_name(common->user_data),
                        (unsigned long) port));
          ssh_log_event(common->config->log_facility,
                        SSH_LOG_WARNING,
                        "User \"%s\" not root, tried to forward " \
                        "privileged port %ld.",
                        ssh_user_name(common->user_data),
                        (unsigned long) port);
          return FALSE;
        }
      else
        {
          ssh_log_event(common->config->log_facility,
                        SSH_LOG_NOTICE,
                        "Privileged user \"%s\" forwarding a privileged port.",
                        ssh_user_name(common->user_data));
        }
    }

  if (port >= 65536)
    {
      SSH_TRACE(2, ("User \"%s\" tried to forward " \
                    "port above 65535 (%ld).",
                    ssh_user_name(common->user_data), (unsigned long) port));
      ssh_log_event(common->config->log_facility,
                    SSH_LOG_WARNING,
                    "User \"%s\" tried to forward " \
                    "port above 65535 (%ld).",
                    ssh_user_name(common->user_data), (unsigned long) port);
      return FALSE;
    }
  
      
  /* Create a socket listener. */
  fwd = ssh_xcalloc(1, sizeof(*fwd));
  fwd->listener = ssh_tcp_make_listener(address_to_bind, port_string,
                                        ssh_channel_ftcp_incoming_connection,
                                        (void *)fwd);
  if (fwd->listener == NULL)
    {
      ssh_debug("Creating remote listener for %s:%s failed.",
                address_to_bind, port_string);
      ssh_log_event(common->config->log_facility,
                    SSH_LOG_NOTICE,
                    "Creating remote listener for %s:%s failed.",
                    address_to_bind, port_string);
      
      ssh_xfree(address_to_bind);
      ssh_xfree(fwd);
      return FALSE;
    }

  /* Fill the remaining fields. */
  fwd->common = common;
  fwd->address_to_bind = address_to_bind;
  fwd->port = ssh_xstrdup(port_string);
  fwd->connect_to_host = NULL;
  fwd->connect_to_port = NULL;

  /* Add to list of forwardings. */
  fwd->next = ct->remote_forwards;
  ct->remote_forwards = fwd;

  ssh_log_event(common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Port %ld set up for remote forwarding.",
                (unsigned long) port);
  
  return TRUE;
}  
示例#21
0
void ssh_acc_device_modexp_op_done(SshCryptoStatus status,
                                   const unsigned char *data,
                                   size_t data_len,
                                   void *context)
{

  SshAccDeviceModExpContext ctx = context;
  
  ctx->sub_op = NULL;
  
  if (status == SSH_CRYPTO_OK)
    {
      /* No array decoding is needed. */
      (*ctx->callback)(SSH_CRYPTO_OK, data, data_len, ctx->context);
      ssh_acc_device_modexp_op_free(ctx);
      return;
    }
  else 
    {
      unsigned char *b, *e, *m, *ret;
      size_t b_len, e_len, mod_len, ret_len;

      /* The accelerated operation has failed, instead perform the operation 
	 in software. */
      SSH_DEBUG(SSH_D_FAIL, ("Accelerated modexp operation has failed, "
			     "now performing the operation in software"));
      
      /* Decode the data buffer to extract the original parameters */
      if (ssh_decode_array(ctx->data, ctx->data_len,
			   SSH_DECODE_UINT32_STR_NOCOPY(&b, &b_len),
			   SSH_DECODE_UINT32_STR_NOCOPY(&e, &e_len),
			   SSH_DECODE_UINT32_STR_NOCOPY(&m, &mod_len),
			   SSH_FORMAT_END) != ctx->data_len)
        {
          (*ctx->callback)(SSH_CRYPTO_NO_MEMORY, NULL, 0, ctx->context);
	  ssh_acc_device_modexp_op_free(ctx);
          return;
        }
      
      ret_len = mod_len;
      if ((ret = ssh_calloc(1, ret_len)) == NULL)
        {
          (*ctx->callback)(SSH_CRYPTO_NO_MEMORY, NULL, 0, ctx->context);
	  ssh_acc_device_modexp_op_free(ctx);
          return;
        }
      
      if (modexp_op_buf(ret, ret_len, b, b_len, 
                        e, e_len, m, mod_len))
        {
          (*ctx->callback)(SSH_CRYPTO_OK, ret, ret_len, ctx->context);
        }
      else
        {
          (*ctx->callback)(SSH_CRYPTO_OPERATION_FAILED, NULL, 0, ctx->context);
        }

      ssh_acc_device_modexp_op_free(ctx);
      ssh_free(ret);
      return;
    } 

}
示例#22
0
文件: ssh-signer2.c 项目: hnuxgp/rk
void signer_received_packet(SshPacketType type,
                            const unsigned char *data, size_t len,
                            void *context)
{
    /* Received. */
    unsigned int msg_byte; /* This is unsigned int because
                            SSH_FORMAT_CHAR expects uint; caused a
                            rather nasty bug during development (I
                            used SshUInt8, which wasn't long
                            enough => ssh_decode_array blew the
                            stack).*/
    char *userauth_str, *hostbased_str, *recv_pubkey_alg, *recv_hostname;
    char *recv_username;
    unsigned char *recv_pubkeyblob;
    size_t recv_pubkeyblob_len;
    /* Dug up by us. */
    char *pubkey_alg, *hostname, *username;
    unsigned char *pubkeyblob;
    size_t pubkeyblob_len;
    size_t hostname_len;

    /* Internal stuff*/
    SshSigner signer = (SshSigner) context;
    char hostkeyfile[512];
    char *comment;
    SshPrivateKey privkey;
    size_t sig_len, length_return;
    unsigned char *signature_buffer;
    SshCryptoStatus result;
    SshUser real_user;

    SSH_TRACE(2, ("Packet received."));

    switch(type)
    {
    case SSH_AUTH_HOSTBASED_PACKET:
        /* Check packet out, and if it's ok, sign it and send
           signature to ssh2. */

#ifdef HEXDUMPS
        SSH_DEBUG_HEXDUMP(3, ("packet:"), \
                          data, len);
#endif /* HEXDUMPS */

        if (ssh_decode_array(data, len,
                             /* session id */
                             SSH_FORMAT_UINT32_STR, NULL, NULL,
                             /* SSH_MSG_USERAUTH_REQUEST (must be checked)*/
                             SSH_FORMAT_CHAR, &msg_byte,
                             /* user name */
                             SSH_FORMAT_UINT32_STR, NULL, NULL,
                             /* service "ssh-userauth" (must be checked)*/
                             SSH_FORMAT_UINT32_STR, &userauth_str, NULL,
                             /* "hostbased" (must be checked)*/
                             SSH_FORMAT_UINT32_STR, &hostbased_str, NULL,
                             /* public key algorithm for hostkey (must
                                be checked)*/
                             SSH_FORMAT_UINT32_STR, &recv_pubkey_alg, NULL,
                             /* public hostkey and certificates (must be
                                checked)*/
                             SSH_FORMAT_UINT32_STR, &recv_pubkeyblob,
                             &recv_pubkeyblob_len,
                             /* client host name (must be checked)*/
                             SSH_FORMAT_UINT32_STR, &recv_hostname, NULL,
                             /* user name on client host (must be checked) */
                             SSH_FORMAT_UINT32_STR, &recv_username, NULL,
                             SSH_FORMAT_END) != len || len == 0)
        {
            /* There was an error. */
            SSH_TRACE(0, ("Invalid packet."));
            goto error;
        }

        /* Get pubkeyblob, pubkeyblob_len, pubkey_alg, hostname and
           username. */

        /* Dig up hosts publickey. */
        if(signer->config->public_host_key_file[0] != '/')
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR,
                     signer->config->public_host_key_file);
        }
        else
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s",
                     signer->config->public_host_key_file);
        }

        SSH_TRACE(2, ("place to look for public key: %s", hostkeyfile));

        /* This pubkey*-stuff is for the client _host's_ public
           hostkey. */
        /* Getting pubkeyblob, pubkeyblob_len */
        SSH_DEBUG(4, ("Reading pubkey-blob from %s...", hostkeyfile));
        if (ssh2_key_blob_read(signer->effective_user_data, hostkeyfile, NULL,
                               &pubkeyblob,
                               &pubkeyblob_len, NULL)
                != SSH_KEY_MAGIC_PUBLIC)
        {
            SSH_TRACE(1, ("Reading public key failed."));
            goto error;
        }

        SSH_DEBUG(4, ("done."));

        if ((pubkey_alg =
                    ssh_pubkeyblob_type(pubkeyblob, pubkeyblob_len))
                == NULL)
        {
            SSH_TRACE(1, ("Couldn't figure out public key algorithm."));
            goto error;
        }

        /* Getting hostname. */
        hostname = ssh_xmalloc(MAXHOSTNAMELEN + 1);
        ssh_tcp_get_host_name(hostname, MAXHOSTNAMELEN + 1);
        hostname_len = strlen(hostname);
        /* Sanity check */
        SSH_ASSERT(hostname_len + 2 < MAXHOSTNAMELEN);
        /* We want FQDN. */
        hostname[hostname_len] = '.';
        hostname[hostname_len + 1] = '\0';

        /* Getting username. */
        real_user = ssh_user_initialize(NULL, FALSE);
        username = ssh_xstrdup(ssh_user_name(real_user));
        ssh_user_free(real_user, FALSE);

        /* Check all parameters. */
        if (msg_byte != SSH_MSG_USERAUTH_REQUEST)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("msg_byte != SSH_MSG_USERAUTH_REQUEST " \
                          "(msg_byte = %d)", msg_byte));
            goto error;
        }
        if (strcmp(userauth_str, SSH_USERAUTH_SERVICE) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("userauth_str != \"ssh-userauth\" (it was '%s')", \
                          userauth_str));
            goto error;
        }
        if (strcmp(hostbased_str, SSH_AUTH_HOSTBASED) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("hostbased_str != \"hostbased\" (it was '%s')", \
                          hostbased_str));
            goto error;
        }
        /* XXX has to be change when adding support for multiple hostkeys */
        if (strcmp(recv_pubkey_alg, pubkey_alg) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Client gave us invalid pubkey-algorithms for our " \
                          "hostkey."));
            goto error;
        }

        if (recv_pubkeyblob_len == pubkeyblob_len)
        {
            if (memcmp(recv_pubkeyblob, pubkeyblob, pubkeyblob_len) != 0)
            {
                SSH_TRACE(1, ("Invalid packet."));
                SSH_DEBUG(1, ("client gave us wrong (or corrupted) " \
                              "public key."));
#ifdef HEXDUMPS
                SSH_DEBUG_HEXDUMP(3, ("client gave us:"), \
                                  recv_pubkeyblob, pubkeyblob_len);
                SSH_DEBUG_HEXDUMP(3, ("our pubkey:"), \
                                  recv_pubkeyblob, pubkeyblob_len);
#endif /* HEXDUMPS */
                goto error;
            }
        }
        else
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Client gave us wrong (or corrupted) public key. " \
                          "Lengths differ (received: %d ; ours: %d)", \
                          recv_pubkeyblob_len, pubkeyblob_len));
            goto error;
        }

        if (strcmp(recv_hostname, hostname) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Wethinks the client gave us the wrong hostname. " \
                          "(client's opinion: '%s' ours: '%s'", \
                          recv_hostname, hostname));
            goto error;
        }
        if (strcmp(recv_username, username) != 0)
        {
            SSH_TRACE(1, ("Invalid packet."));
            SSH_DEBUG(1, ("Client definitely gave us the wrong user name. " \
                          "(it says: '%s' we know: '%s')", recv_username, \
                          username));
            goto error;
        }

        /* Sign the packet and send it to client. */

        /* If we've gotten this far, the packet is ok, and it can be
           signed. */

        SSH_TRACE(0, ("Received packet ok."));
        if(signer->config->public_host_key_file[0] != '/')
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s/%s", SSH_SERVER_DIR,
                     signer->config->host_key_file);
        }
        else
        {
            snprintf(hostkeyfile, sizeof(hostkeyfile), "%s",
                     signer->config->host_key_file);
        }

        SSH_TRACE(2, ("place to look for private key: %s", hostkeyfile));

        if ((privkey = ssh_privkey_read(signer->effective_user_data, hostkeyfile, "",
                                        &comment, NULL)) == NULL)
            ssh_fatal("ssh_privkey_read from %s failed.", hostkeyfile);

        /* Check how big a chunk our private key can sign (this is
           purely a sanity check, as both of our signature schemas do
           their own hashing) */
        sig_len = ssh_private_key_max_signature_input_len(privkey);

        SSH_TRACE(2, ("max input length for signing: %d", sig_len));

        if (sig_len == 0)
        {
            SSH_TRACE(0, ("private key not capable of signing! " \
                          "(definitely an error)"));
            goto error;
        }
        else if (sig_len != -1 && sig_len < len)
        {
            SSH_TRACE(0, ("private key can't sign our data. (too much " \
                          "data (data_len %d, max input len for signing " \
                          "%d))", len, sig_len));
            goto error;
        }

        /* Now check how much we much buffer we must allocate for the
           signature. */
        sig_len = ssh_private_key_max_signature_output_len(privkey);

        SSH_TRACE(2, ("max output length for signature: %d", sig_len));

        signature_buffer = ssh_xcalloc(sig_len, sizeof(unsigned char));

        /* Do the actual signing. */

#ifdef HEXDUMPS
        SSH_DEBUG_HEXDUMP(5, ("Signing following data"),
                          data + 4, len - 4);
#endif /* HEXDUMPS */

        if ((result = ssh_private_key_sign(privkey,
                                           data,
                                           len,
                                           signature_buffer,
                                           sig_len,
                                           &length_return,
                                           signer->random_state))
                != SSH_CRYPTO_OK)
        {
            SSH_TRACE(0, ("ssh_private_key_sign() returned %d.", result));
            goto error;
        }

#ifdef HEXDUMPS
        SSH_DEBUG_HEXDUMP(5, ("Signature"), signature_buffer, length_return);
#endif /* HEXDUMPS */
        /* Send it to client. */
        signer->packet_payload = signature_buffer;
        signer->packet_payload_len = length_return;
        signer->packet_waiting = TRUE;

        if (ssh_packet_wrapper_can_send(signer->wrapper))
            signer_can_send(signer);

        /* XXX free dynamically allocated data. */
        ssh_xfree(username);

        break;
    case SSH_AUTH_HOSTBASED_SIGNATURE:
        /* We shouldn't get this type of packet. This is an error.*/
        SSH_TRACE(0, ("client sent us SSH_AUTH_HOSTBASED_SIGNATURE. This " \
                      "is an error."));
        goto error;
        break;
    case SSH_AUTH_HOSTBASED_ERROR:
        /* We shouldn't be getting this either. This is an error. */
        SSH_TRACE(0, ("client sent us SSH_AUTH_HOSTBASED_SIGNATURE_ERROR. " \
                      "This is an error. (This message can be sent by " \
                      "ssh-signer2 only)"));
        goto error;
        break;
    }
    return;

    /* We come here after errors. */
error:
    /* Send error message to ssh2, and wait for ssh2 to send
       EOF. */
    ssh_packet_wrapper_send_encode(signer->wrapper, SSH_AUTH_HOSTBASED_ERROR,
                                   SSH_FORMAT_END);

    /* Init a 5 second timeout. If ssh2 hasn't disconnected at
       that time, close stream.*/
    ssh_register_timeout(5L, 0L, signer_destroy_timeout, signer);

    return;
}
示例#23
0
文件: t-userauth.c 项目: AnthraX1/rk
void server_received_packet(SshCrossPacketType type,
                            const unsigned char *data, size_t len,
                            void *context)
{
  char *service;

  switch (type)
    {
    case SSH_CROSS_PACKET:
#ifdef DEBUG
      ssh_debug("server_received_packet: PACKET");
#endif
      break;
    case SSH_CROSS_DISCONNECT:
#ifdef DEBUG
      ssh_debug("server_received_packet: DISCONNECT");
#endif
      /* XXX destroy? */
      break;
    case SSH_CROSS_DEBUG:
#ifdef DEBUG
      ssh_debug("server_received_packet: DEBUG");
#endif
      break;
    case SSH_CROSS_STARTUP:
#ifdef DEBUG
      ssh_debug("server_received_packet: STARTUP");
#endif
      break;
    case SSH_CROSS_ALGORITHMS:
#ifdef DEBUG
      ssh_debug("server_received_packet: ALGORITHMS");
#endif
      break;
    case SSH_CROSS_AUTHENTICATED:
#ifdef DEBUG
      ssh_debug("server_received_packet: AUTHENTICATED");
#endif
      break;

    case SSH_CROSS_SERVICE_REQUEST:
#ifdef DEBUG
      ssh_debug("server_received_packet: SERVICE_REQUEST");
#endif
      if (ssh_decode_array(data, len,
                           SSH_FORMAT_UINT32_STR, &service, NULL,
                           SSH_FORMAT_END) == 0)
        ssh_fatal("server_received_packet: bad service request");
      if (strcmp(service, "TEST") == 0)
        ssh_cross_down_send(server_down, SSH_CROSS_SERVICE_ACCEPT, NULL, 0);
      else
        ssh_cross_down_send_disconnect(server_down, TRUE,
                                       SSH_DISCONNECT_SERVICE_NOT_AVAILABLE,
                                       "Service not available");
      ssh_xfree(service);
      break;
                                 
    default:
      ssh_fatal("server_received_packet: type %d", (int)type);
    }
}