Beispiel #1
0
Boolean handler_output_outgoing(Handler c)
{
  int len;
#ifdef DEBUG
  ssh_debug("handler_output_outgoing");
#endif
#ifdef DUMP_PACKETS
  buffer_dump(&c->outgoing); 
#endif
 

  while (ssh_buffer_len(&c->outgoing) > 0)
    {
      len = ssh_buffer_len(&c->outgoing);
      len = ssh_stream_write(c->stream, ssh_buffer_ptr(&c->outgoing), len);
      if (len == 0)
        ssh_fatal("%s: handler_output: error writing to stream", c->side);
      if (len < 0)
        return FALSE;
      ssh_buffer_consume(&c->outgoing, len);
    }

  if (c->outgoing_eof)
    ssh_stream_output_eof(c->stream);

  return TRUE;
}
Beispiel #2
0
void server1_read(SshStream stream)
{
  int ret;
  unsigned char buf[1024];

  for (;;)
    {
      ret = ssh_stream_read(stream, buf, sizeof(buf));
      if (ret < 0)
	return;
      if (ret == 0)
	{
	  if (read_count != send_count)
	    ssh_fatal("server1_read eof received, read_count %ld send_count %ld",
		  read_count, send_count);
	  break;
	}
      if (memcmp(buf, ssh_buffer_ptr(&expect_buffer), ret) != 0)
	ssh_fatal("server1_read data does not match");
      ssh_buffer_consume(&expect_buffer, ret);
      read_count += ret;
    }
  /* All data has been received. */
  ssh_stream_destroy(stream);
  exited1 = 1;
}
Beispiel #3
0
void encode_case(const char *name, const char *expect,
                 size_t expect_len, ...)
{
  size_t len, i, bytes;
  unsigned char ch, *cp;
  va_list va;

  ssh_buffer_clear(buffer);
  len = rand() % 100;
  ch = rand();
  for (i = 0; i < len; i++)
    ssh_buffer_append(buffer, &ch, 1);

  va_start(va, expect_len);
  bytes = ssh_encode_buffer_va(buffer, va);

  if (bytes != expect_len || ssh_buffer_len(buffer) != len + expect_len)
    ssh_fatal("test_encode: %s: unexpected length %d vs. %d",
              name, bytes, len + expect_len);
  cp = ssh_buffer_ptr(buffer);
  if (memcmp(expect, cp + len, expect_len) != 0)
    ssh_fatal("test_encode: %s: mismatch", name);

  for (i = 0; i < len; i++)
    if (cp[i] != ch)
      ssh_fatal("test_encode: %s: beginning corrupted", name);
  ssh_buffer_consume(buffer, len);
}
static int
ssh_appgw_http_unmarshal_string(SshBuffer buf, unsigned char **ptr)
{
  int len;

  *ptr = NULL;

  if (ssh_appgw_http_unmarshal_int(buf, &len) == 0)
    return 0;

  if (len == 0)
    return 1;

  if (ssh_buffer_len(buf) < len)
    return 0;

  *ptr = ssh_malloc(len+1);
  if (ptr == NULL)
    return 0;

  memcpy(*ptr,ssh_buffer_ptr(buf),len);
  (*ptr)[len] = '\0';
  ssh_buffer_consume(buf,len);
  return 1;

}
static int
ssh_appgw_http_unmarshal_int(SshBuffer buf, int *result)
{
  if (ssh_buffer_len(buf) < 4)
    {
      *result = 0;
      return 0;
    }

  *result = (int)(SSH_GET_32BIT(ssh_buffer_ptr(buf)));
  ssh_buffer_consume(buf,4);
  return 1;
}
Beispiel #6
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;
}
Beispiel #7
0
void connect1_write(SshStream stream)
{
  int len;
  while (ssh_buffer_len(&send_buffer) > 0)
    {
      len = ssh_buffer_len(&send_buffer);
      len = ssh_stream_write(stream, ssh_buffer_ptr(&send_buffer), len);
      if (len < 0)
	return;
      if (len == 0)
	ssh_fatal("connect1_write failed");
      ssh_buffer_consume(&send_buffer, len);
    }
  ssh_stream_output_eof(stream);
  ssh_stream_destroy(stream);
}
Beispiel #8
0
SshBuffer *handler_input_expect_cross(Handler c, unsigned int expect_type)
{
  SshBuffer *packet;
  const unsigned char *cp;
  unsigned int packet_type;

  packet = handler_input_cross(c);
  if (!packet)
    return NULL;

  cp = ssh_buffer_ptr(packet);
  packet_type = (unsigned int) cp[4];
  if (packet_type != expect_type)
    ssh_fatal("%s: handler_input_expect_cross: got %d expected %d",
          c->side, packet_type, expect_type);
  /* Remove cross-layer header and return the payload. */
  ssh_buffer_consume(packet, 5);
  return packet;
}
static int
ssh_appgw_http_unmarshal_data(SshBuffer buf, unsigned char **ptr, int *len)
{
  *ptr = NULL;
  *len = 0;

  if (ssh_appgw_http_unmarshal_int(buf, len) == 0)
    return 0;

  if (*len == 0)
    return 1;

  if (ssh_buffer_len(buf) < *len)
    return 0;

  *ptr = ssh_malloc(*len);
  if (ptr == NULL)
    return 0;

  memcpy(*ptr,ssh_buffer_ptr(buf),*len);
  ssh_buffer_consume(buf,*len);
  return 1;
}
Beispiel #10
0
int ssh_packet_impl_read(void *context, unsigned char *buf, size_t size)
{
  SshPacketImpl up = (SshPacketImpl)context;
  size_t len;

  /* Compute the number of bytes we can transmit. */
  len = ssh_buffer_len(&up->outgoing);
  if (len > size)
    len = size;

  /* Return immediately if no data available. */
  if (len == 0)
    {
      /* If shortcircuiting, pass it to the shortcircuit stream. */
      if (up->shortcircuit_stream)
        return ssh_stream_read(up->shortcircuit_stream, buf, size);

      /* Return EOF or "no more data available yet". */
      if (up->outgoing_eof)
        return 0;
      else
        {
          up->up_read_blocked = TRUE;
          return -1;
        }
    }

  /* Move data to the caller's buffer. */
  memcpy(buf, ssh_buffer_ptr(&up->outgoing), len);
  ssh_buffer_consume(&up->outgoing, len);

  /* Wake up the sender if appropriate. */
  if (ssh_buffer_len(&up->outgoing) == 0)
    ssh_packet_impl_restart_send(up);

  return len;
}
Beispiel #11
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;
}
Beispiel #12
0
Boolean ssh_pgp_read_packet(SshFileBuffer *filebuf, SshPgpPacket *packet)
{
  unsigned char type_id;
  int packet_type;
  int i;
  size_t l;
  Boolean fr;
  Boolean partial_body;
  SshPgpPacket newpacket;
  SshBuffer partial_buf;
  Boolean partial_buf_init;

  partial_buf_init = FALSE;

  do {
    fr = ssh_file_buffer_expand(filebuf, 1);
    if (fr == FALSE)
      goto failed;
    type_id = *(ssh_buffer_ptr(&(filebuf->buf)));
    ssh_buffer_consume(&(filebuf->buf), 1);
    
    SSH_DEBUG(5, ("type_id = %d\n", type_id));

    if (type_id & 0x40) 
      {
        /* New packet header format */
        SSH_DEBUG(5, ("New packet header format\n"));
        if (partial_buf_init == FALSE)
          packet_type = type_id & 0x7f;
        fr = ssh_file_buffer_expand(filebuf, 1);
        if (fr == FALSE)
          goto failed;
        l = *(ssh_buffer_ptr(&(filebuf->buf)));
        ssh_buffer_consume(&(filebuf->buf), 1);
        if ((l >= 192) && (l <= 223))
          {
            partial_body = FALSE;
            fr = ssh_file_buffer_expand(filebuf, 1);
            if (fr == FALSE)
              goto failed;
            l = (((l - 192) << 8) + 
                 ((size_t)(*(ssh_buffer_ptr(&(filebuf->buf))))) +
                 192);
            ssh_buffer_consume(&(filebuf->buf), 1);
          }
        else if ((l >= 224) && (l <= 254))
          {
            partial_body = TRUE;
            fr = ssh_file_buffer_expand(filebuf, 1);
            if (fr == FALSE)
              goto failed;
            l = ((size_t)1) << ((*(ssh_buffer_ptr(&(filebuf->buf)))) & 0x1f);
            ssh_buffer_consume(&(filebuf->buf), 1);
            if (partial_buf_init == FALSE)
              {
                ssh_buffer_init(&partial_buf);
                partial_buf_init = TRUE;
              }
          }
        else if (l == 255)
          {
            partial_body = FALSE;
            l = 0;
            fr = ssh_file_buffer_expand(filebuf, 4);
            if (fr == FALSE)
              goto failed;
            for (i = 0; i < 4; i++)
              {
                l = (l << 8) + (*(ssh_buffer_ptr(&(filebuf->buf))));
                ssh_buffer_consume(&(filebuf->buf), 1);
              }
          }
        else
          {
            partial_body = FALSE;
          }
      }
    else
      {
        size_t ll;

        /* Old packet header format */
        SSH_DEBUG(5, ("Old packet header format\n"));
        partial_body = FALSE;
        if (partial_buf_init == FALSE)
          packet_type = (type_id & 0x7c) >> 2;
        ll = ((int)1) << (type_id & 0x03);
        fr = ssh_file_buffer_expand(filebuf, (int)ll);
        if (fr == FALSE)
          goto failed;
        l = 0;
        for (i = 0; i < ll; i++) {
          l = (l << 8) + (*(ssh_buffer_ptr(&(filebuf->buf))));
          ssh_buffer_consume(&(filebuf->buf), 1);
        }
      }

    if ((l < 1) || (l > 0x4000)) /* XXX */
      goto failed; 

    fr = ssh_file_buffer_expand(filebuf, l);
    if (fr == FALSE)
      goto failed;
    if (partial_body == FALSE)
      {
        if (packet != NULL) 
          {
            newpacket = ssh_xmalloc(sizeof (struct SshPgpPacketRec));
            newpacket->type = packet_type;
            if (partial_buf_init)
              {
                newpacket->len = l + ssh_buffer_len(&partial_buf);
                newpacket->data = ssh_xmalloc(newpacket->len);
                memcpy(newpacket->data, 
                       ssh_buffer_ptr(&partial_buf),
                       ssh_buffer_len(&partial_buf));
                memcpy(&(newpacket->data[ssh_buffer_len(&partial_buf)]), 
                       ssh_buffer_ptr(&(filebuf->buf)), 
                       l);
                ssh_buffer_uninit(&partial_buf);
                partial_buf_init = FALSE;
              }
            else
              {
                newpacket->len = l;
                newpacket->data = ssh_xmalloc(l);
                memcpy(newpacket->data, ssh_buffer_ptr(&(filebuf->buf)), l);
              }
            *packet = newpacket;
            ssh_buffer_consume(&(filebuf->buf), l);
          }
      }
    else
      {
        ssh_buffer_append(&partial_buf, ssh_buffer_ptr(&(filebuf->buf)), l);
        ssh_buffer_consume(&(filebuf->buf), l);
      }
  } while (partial_body == TRUE);

  return TRUE;

 failed:
  if (partial_buf_init == TRUE)
    ssh_buffer_uninit(&partial_buf);
  return FALSE;
}
Beispiel #13
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;
}
Beispiel #14
0
Boolean ssh_packet_wrapper_output(SshPacketWrapper down)
{
  int len;
  Boolean return_value = FALSE;

  /* Loop while we have data to output.  When all data has been sent,
     we check whether we need to send EOF. */
  while (ssh_buffer_len(&down->outgoing) > 0)
    {
      /* Write as much data as possible. */
      len = ssh_stream_write(down->stream, ssh_buffer_ptr(&down->outgoing),
                             ssh_buffer_len(&down->outgoing));
      if (len < 0)
        return return_value;  /* Cannot write more now. */
      if (len == 0)
        {
          /* EOF on output; will not be able to write any more. */
          down->outgoing_eof = TRUE;
          ssh_buffer_clear(&down->outgoing);
          return TRUE;
        }

      /* Consume written data. */
      ssh_buffer_consume(&down->outgoing, len);

      /* We've done something, so return TRUE. */
      return_value = TRUE;
    }

  /* All output has drained.  There is no more buffered data. */
  if (down->send_blocked)
    {
      down->cannot_destroy = TRUE;
      if (down->can_send)
        (*down->can_send)(down->context);
      down->cannot_destroy = FALSE;
      if (down->destroy_requested)
        {
          ssh_packet_wrapper_destroy(down);
          return FALSE;
        }
      down->send_blocked = FALSE;
    }

  /* If we should send EOF after output has drained, do it now. */
  if (down->outgoing_eof)
    ssh_stream_output_eof(down->stream);

  /* If we get here and the stream is shortcircuited, that means we had
     output data to drain before shortcircuiting. */
  if (down->shortcircuit_up_stream && !down->shortcircuited)
    {
      down->shortcircuited = TRUE;
      ssh_packet_impl_shortcircuit_now(down->shortcircuit_up_stream,
                                       down->stream);
    }

  /* If there's a destroy pending (that is, waiting for buffers to drain),
     do the destroy now. */
  if (down->destroy_pending)
    {
      /* Destroy the context now.  This also closes the stream. */
      ssh_packet_wrapper_destroy_now(down);

      /* Return FALSE to ensure that the loop in ssh_packet_wrapper_callback
         exits without looking at the context again. */
      return FALSE;
    }

  return return_value;
}
Beispiel #15
0
void t_tcpc_stream_callback(SshStreamNotification        notification,
                            void*                                 context)
{
  t_tcpc_context  pcontext = context;
  char                    buf[4096];
  int                             i;

  SSH_TRACE(SSH_D_MY, ("%s", "t_tcpc_stream_callback"));

  switch (notification)
    {
    case SSH_STREAM_INPUT_AVAILABLE:
      SSH_TRACE(SSH_D_MY, ("%s", "SSH_STREAM_INPUT_AVAILABLE"));
      while ((i = ssh_stream_read(pcontext->pstream,
                                  buf,
                                  4096)) > 0)
        {
          buf[i] = 0;
          SSH_TRACE(SSH_D_MY, ("read: %s", buf));

          if (pcontext->phost_name_or_address)
            {
              ssh_buffer_append(pcontext->pbuffer,
                                buf,
                                i);
              t_tcpc_stream_callback(SSH_STREAM_CAN_OUTPUT,
                                     pcontext);
            }
          else
            {
              SSH_TRACE(SSH_D_MY, ("output: %s", buf));
            }
        }
      break;
    case SSH_STREAM_CAN_OUTPUT:
      SSH_TRACE(SSH_D_MY, ("%s", "SSH_STREAM_CAN_OUTPUT"));
      if (ssh_buffer_len(pcontext->pbuffer) > 0)
        {
          i = ssh_stream_write(pcontext->pstream,
                               ssh_buffer_ptr(pcontext->pbuffer),
                               ssh_buffer_len(pcontext->pbuffer));

          if (i > 0)
            {
              ssh_buffer_consume(pcontext->pbuffer,
                                 i);
            }
        }
      break;
    case SSH_STREAM_DISCONNECTED:
      SSH_TRACE(SSH_D_MY, ("%s", "SSH_STREAM_DISCONNECTED"));
#if 0
      /* BUG BUG BUG */
      ssh_stream_destroy(pcontext->pstream);
#endif /* 0 */
      ssh_event_loop_abort();
      break;
    default:
      SSH_NOTREACHED;
      break;
    }
}
Beispiel #16
0
static void
filter_html(SshBuffer to, SshBuffer from, Boolean eof_seen, void *context)
{
  ProxyRequest *req = context;
  unsigned char *cp;
  size_t len;
  size_t i;

 restart:

  cp = ssh_buffer_ptr(from);
  len = ssh_buffer_len(from);

  for (i = 0; i < len; i++)
    {
      switch (req->state)
        {
        case FILTER_TEXT:
          if (cp[i] == '<')
            {
              ssh_buffer_append(to, cp, i);
              ssh_buffer_consume(from, i);

              len = ssh_buffer_len(from);
              cp = ssh_buffer_ptr(from);

              /* Is the end of the tag seen? */
              for (i = 0; i < len; i++)
                if (cp[i] == '>')
                  {
                    i++;
                    break;
                  }

              if (i >= len && !eof_seen)
                /* No, need more data. */
                return;

              /* Yes, it is seen. */

              if (i > 4 && strncasecmp(cp, "<img", 4) == 0)
                {
                  char *url = parse_img_src(cp, i);
                  ssh_buffer_append_cstrs(to,
                                          "<a href=\"http://amme.ssh.fi:8080",
                                          "/catch?url=", url, "\">*</a>",
                                          NULL);
                }

              ssh_buffer_append(to, cp, i);
              ssh_buffer_consume(from, i);

              goto restart;
            }
          else if (cp[i] == '&')
            req->state = FILTER_ENTITY;
          break;

        case FILTER_ENTITY:
          if (cp[i] == ';')
            req->state = FILTER_TEXT;
          break;
        }
    }

  ssh_buffer_append(to, ssh_buffer_ptr(from), ssh_buffer_len(from));
  ssh_buffer_clear(from);
}
Beispiel #17
0
int ssh_tls_stream_read(void *context, unsigned char *buf, size_t size)
{
  SshTlsProtocolState s = (SshTlsProtocolState)context;

  SSH_ASSERT(size > 0);
  SSH_ASSERT(s->packet_feed_len >= 0);

  SSH_DEBUG(7, ("The upper layer wants to read max. %d bytes of data.", size));

 reread_after_further_parsing:
  if (SSH_TLS_IS_FAILED_STATUS(s->status))
    {
      SSH_DEBUG(7, ("Protocol is in error condition so give EOF."));
      return 0;
    }

  if (s->packet_feed_len == 0)
    {
      SSH_DEBUG(7, ("Nothing to give (%d bytes in buffer).",
                    ssh_buffer_len(s->incoming_raw_data)));

      if (s->flags & SSH_TLS_FLAG_GOT_CLOSE_NOTIFY)
        {
          SSH_DEBUG(7, ("The protocol stream has closed, thus send EOF."));

          /* This is it. Now it is upto the application to kill us if
             it wants. Of course, data can be still sent. */
          return 0;
        }
      SSH_DEBUG(7, ("App. data packet totally consumed, trailer %d bytes.",
                    s->trailer_len));
      if (s->trailer_len >= 0)
        {
          SSH_ASSERT(ssh_buffer_len(s->incoming_raw_data) >= s->trailer_len);
          ssh_buffer_consume(s->incoming_raw_data, s->trailer_len);
          s->trailer_len = -1;

          /* Now we need to call ssh_tls_parse_incoming because it is possible
             that there are more full packets in the incoming_raw_data buffer
             waiting for parsing. */
          ssh_tls_parse_incoming(s);
          goto reread_after_further_parsing;
        }

      s->flags |= SSH_TLS_FLAG_GIVE_READ_NOTIFY;
      SSH_DEBUG(7, ("Set flags to %x.", (unsigned int) s->flags));
      return -1;
    }

  if (size > s->packet_feed_len) size = s->packet_feed_len;
  memcpy(buf, ssh_buffer_ptr(s->incoming_raw_data), size);
  SSH_ASSERT(ssh_buffer_len(s->incoming_raw_data) >= size + s->trailer_len);
  ssh_buffer_consume(s->incoming_raw_data, size);
  s->packet_feed_len -= size;

  SSH_DEBUG(7, ("%d bytes written to the buffer, %d to feed.",
                size, s->packet_feed_len));

  s->stats.app_bytes_given += size;

  trigger_rekey_if_needed(s);

  SSH_ASSERT(s->packet_feed_len >= 0);

  if (s->packet_feed_len == 0)
    {
      SSH_DEBUG(7, ("App. data packet totally consumed, trailer %d bytes.",
                    s->trailer_len));
      SSH_ASSERT(s->trailer_len >= 0);
      SSH_ASSERT(ssh_buffer_len(s->incoming_raw_data) >= s->trailer_len);
      ssh_buffer_consume(s->incoming_raw_data, s->trailer_len);
      s->trailer_len = -1;

      /* Now we need to call ssh_tls_parse_incoming because it is possible
         that there are more full packets in the incoming_raw_data buffer
         waiting for parsing. */
      ssh_tls_parse_incoming(s);
    }

  /* Now that the incoming raw data buffer has been perhaps shrunk,
     try to read more data in. */
  if ((s->flags & SSH_TLS_FLAG_READING_CEASED)
      &&
      ssh_buffer_len(s->incoming_raw_data) < s->conf.max_buffered_data)
    {
      SSH_DEBUG(7, ("Try to read in more data as reading had been "
                    "temporarily stopped and now there is more room."));
      ssh_tls_try_read_in(s);
    }

  return size;
}