Example #1
0
int main(int ac, char **av)
{
  int i, j;
  int pass;
  unsigned char buf[1024];

  snprintf(lpath1, sizeof (lpath1), "/tmp/lstr1.%x", (unsigned)random());
  snprintf(lpath2, sizeof (lpath2), "/tmp/lstr2.%x", (unsigned)random());
  
  printf("Doing %d iterations of localstream test:", PASSES);

  for (pass = 0; pass < PASSES; pass++)
    {
      printf(" %d", pass);
      fflush(stdout);

      ssh_buffer_init(&send_buffer);
      ssh_buffer_init(&expect_buffer);
      
      for (i = 0; i < 100; i++)
	{
	  for (j = 0; j < sizeof(buf); j++)
	    buf[j] = random();
	  ssh_buffer_append(&send_buffer, buf, sizeof(buf));
	  ssh_buffer_append(&expect_buffer, buf, sizeof(buf));
	  send_count += sizeof(buf);
	}

      ssh_event_loop_initialize();

      remove(lpath1);
      listener1 = ssh_local_make_listener(lpath1, 
					  listener1_callback,
					  (void *)4);
      if (!listener1) {
	  ssh_fatal("cannot create listener1");
      }

      ssh_local_connect(lpath1, connect1_done, (void *)3);

      ssh_event_loop_run();

      ssh_event_loop_uninitialize();

      ssh_buffer_uninit(&send_buffer);
      ssh_buffer_uninit(&expect_buffer);
      
    }
  printf("\n");
  
  return 0;
}
Example #2
0
void ssh_packet_wrapper_destroy_now(SshPacketWrapper down)
{
  /* Close the downward stream. */
  ssh_stream_destroy(down->stream);

  /* Uninitialize buffers. */
  ssh_buffer_uninit(&down->incoming);
  ssh_buffer_uninit(&down->outgoing);
  ssh_buffer_uninit(&down->outgoing_packet);

  /* Fill the context with 'F' to ease debugging, and free it. */
  memset(down, 'F', sizeof(*down));
  ssh_xfree(down);
}
Example #3
0
/* Uninitialize a file buffer initialized by ssh_file_buffer_init */
void ssh_file_buffer_uninit(SshFileBuffer buf)
{
  SSH_ASSERT(buf != NULL);
  ssh_file_buffer_detach(buf);
  ssh_buffer_uninit(&(buf->buf));
  return;
}
Example #4
0
void ssh_buffer_free(SshBuffer *buffer)
{
  SSH_ASSERT(buffer);
  if (!buffer->dynamic)
    ssh_fatal("ssh_buffer_free given a buffer which was not dynamically allocated.");
  ssh_buffer_uninit(buffer);
  ssh_xfree(buffer);
}
Example #5
0
Boolean
ssh2_key_blob_encode(unsigned long magic,
                     const char *subject, const char *comment,
                     const unsigned char *key, size_t keylen,
                     unsigned char **encoded, size_t *encoded_len)
{
  SshBufferStruct buffer;
  char *base64;
  unsigned int key_index;

  /* Translate to index. */
  switch (magic)
    {
    case SSH_KEY_MAGIC_PUBLIC:            key_index = 0; break;
    case SSH_KEY_MAGIC_PRIVATE:           key_index = 1; break;
    case SSH_KEY_MAGIC_PRIVATE_ENCRYPTED: key_index = 2; break;
    default:                                             return FALSE;
    }

  ssh_buffer_init(&buffer);

  /* Add the head for the key. */
  ssh_key_blob_dump_line_str(&buffer,
                             ssh2_pk_format_name_list[key_index].head);
  ssh_key_blob_dump_lf(&buffer);

  /* Handle key words. */
  if (subject)
    {
      ssh_key_blob_dump_line_str(&buffer, "Subject: ");
      ssh_key_blob_dump_line_str(&buffer, subject);
      ssh_key_blob_dump_lf(&buffer);
    }

  if (comment)
    {
      ssh_key_blob_dump_line_str(&buffer, "Comment: ");
      ssh_key_blob_dump_quoted_str(&buffer, 9, comment);
      ssh_key_blob_dump_lf(&buffer);
    }

  /* Now add the base64 formatted stuff. */
  base64 = (char *)ssh_buf_to_base64(key, keylen);
  ssh_key_blob_dump_str(&buffer, base64);
  ssh_key_blob_dump_lf(&buffer);
  ssh_xfree(base64);

  /* Add the tail for the key. */
  ssh_key_blob_dump_line_str(&buffer,
                             ssh2_pk_format_name_list[key_index].tail);
  ssh_key_blob_dump_lf(&buffer);

  *encoded_len = ssh_buffer_len(&buffer);
  *encoded = ssh_xmemdup(ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
  ssh_buffer_uninit(&buffer);
  return TRUE;
}
Example #6
0
static int
cm_debug_renderer_return(SshBuffer buffer, unsigned char *buf, int len)
{
  int l = ssh_buffer_len(buffer);

  if (l > len)
    {
      ssh_ustrncpy(buf, ssh_buffer_ptr(buffer), len - 1);
      ssh_buffer_uninit(buffer);
      return len + 1;
    }
  else
    {
      ssh_ustrncpy(buf, ssh_buffer_ptr(buffer), l);
      ssh_buffer_uninit(buffer);
      return l;
    }
}
Example #7
0
void ssh_channel_open_ssh1_agent_connected(SshStream stream,
                                          void *context)
{
  SshAgentConnection a = (SshAgentConnection)context;
  SshBuffer buffer;
  unsigned char *cp;

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

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

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

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

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

  /* Create the channel. */
  (*a->completion)(SSH_OPEN_OK, stream, TRUE, TRUE, AGENT_WINDOW_SIZE, NULL, 0,
                   NULL, ssh_channel_ssh1_agent_connection_destroy,
                   (void *)a->common, a->context);
  ssh_xfree(a);
}
void
ssh_audit_syslog_destroy(SshAuditSyslogContext context)
{
  if (context == NULL)
    return;

  ssh_buffer_uninit(&context->buffer);

  ssh_free(context);
}
Example #9
0
void ssh_packet_impl_destroy(void *context)
{
  SshPacketImpl up = (SshPacketImpl)context;

  /* Call the destroy callback. */
  if (up->destroy)
    (*up->destroy)(up->context);

  /* Cancel pending callbacks. */
  ssh_cancel_timeouts(ssh_packet_impl_signal_output_proc, (void *)up);
  ssh_cancel_timeouts(ssh_packet_impl_signal_input_proc, (void *)up);
  ssh_cancel_timeouts(ssh_packet_impl_signal_send_proc, (void *)up);

  /* Uninitialize the buffers. */
  ssh_buffer_uninit(&up->outgoing);
  ssh_buffer_uninit(&up->outgoing_packet);
  ssh_buffer_uninit(&up->incoming);

  /* Fill the context with garbage so that accesses after freeing are more
     reliably trapped.  This eases debugging. */
  memset(up, 'F', sizeof(*up));
  ssh_xfree(up);
}
Example #10
0
/* Free a file buffer */
void ssh_file_buffer_free(SshFileBuffer buf)
{
  SSH_ASSERT(buf != NULL);
  if (ssh_file_buffer_attached(buf))
    {
      if (!(buf->attached_as_fileptr))
        fclose(buf->f);
      buf->attached_as_fileptr = FALSE;
      buf->f = NULL;
    }
  ssh_buffer_uninit(&(buf->buf));
  ssh_xfree(buf);
  return;
}
Example #11
0
/* Handle the parsing of the single line string. */
static size_t
ssh_key_blob_get_line(const unsigned char *buf, size_t len,
                      char **string)
{
  size_t i, step, keep;
  SshBufferStruct buffer;

  ssh_buffer_init(&buffer);
  for (i = 0, step = 0, keep = 0; i < len; i++)
    {
      switch (buf[i])
        {
        case '\n':
          /* End. */
          step = i;
          goto end;
        case ' ':
        case '\t':
        case '\r':
          if (ssh_buffer_len(&buffer) == 0)
            {
              keep = 0;
              break;
            }
          keep = 1;
          break;
        default:
          if (keep)
            {
              ssh_xbuffer_append(&buffer, (const unsigned char *)" ", 1);
              keep = 0;
            }
          ssh_xbuffer_append(&buffer, &buf[i], 1);
          break;
        }
    }

end:

  /* Make a string. */
  *string = ssh_xmalloc(ssh_buffer_len(&buffer) + 1);
  memcpy(*string, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
  (*string)[ssh_buffer_len(&buffer)] = '\0';

  ssh_buffer_uninit(&buffer);

  return step;
}
Example #12
0
void ssh_channel_start_remote_tcp_forward(SshCommon common,
                                          const char *address_to_bind,
                                          const char *port,
                                          const char *connect_to_host,
                                          const char *connect_to_port,
                                          void (*completion)(Boolean ok,
                                                             void *context),
                                          void *context)
{
  SshRemoteTcpForward fwd;
  SshBuffer buffer;
  SshChannelTypeTcpForward ct;

  SSH_DEBUG(5, ("requesting remote forwarding for port %s", port));

  ct = ssh_channel_ftcp_ct(common);
  
  /* Create a context for the forwarding. */
  fwd = ssh_xcalloc(1, sizeof(*fwd));
  fwd->common = common;
  fwd->address_to_bind = ssh_xstrdup(address_to_bind);
  fwd->port = ssh_xstrdup(port);
  fwd->connect_to_host = ssh_xstrdup(connect_to_host);
  fwd->connect_to_port = ssh_xstrdup(connect_to_port);

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

  /* Send a forwarding request to the remote side. */
  ssh_buffer_init(&buffer);
  ssh_encode_buffer(&buffer,
                    SSH_FORMAT_UINT32_STR,
                      address_to_bind, strlen(address_to_bind),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(port),
                    SSH_FORMAT_END);
  ssh_conn_send_global_request(common->conn, "tcpip-forward",
                               ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer),
                               completion, context);
  ssh_buffer_uninit(&buffer);
}
Example #13
0
void ssh_channel_dtcp_open_to_remote(SshCommon common, SshStream stream,
                                     const char *connect_to_host,
                                     const char *connect_to_port,
                                     const char *originator_ip,
                                     const char *originator_port)
{
  SshBuffer buffer;

  SSH_DEBUG(5, ("opening direct TCP/IP connection to %s:%s originator %s:%s",
                connect_to_host, connect_to_port,
                originator_ip, originator_port));

  /* Register that we have a new channel. */
  ssh_common_new_channel(common);

  /* Format the channel open request in a buffer. */
  ssh_buffer_init(&buffer);
  ssh_encode_buffer(&buffer,
                    SSH_FORMAT_UINT32_STR,
                      connect_to_host, strlen(connect_to_host),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(connect_to_port),
                    SSH_FORMAT_UINT32_STR,
                      originator_ip, strlen(originator_ip),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(originator_port),
                    SSH_FORMAT_END);
  
  /* Send the channel open request. */
  ssh_conn_send_channel_open(common->conn, "direct-tcpip",
                             stream, TRUE, FALSE, SSH_TCPIP_WINDOW,
                             SSH_TCPIP_PACKET_SIZE,
                             ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer),
                             NULL, 
                             ssh_channel_tcp_connection_destroy,
                             (void *)common, NULL, NULL);

  ssh_buffer_uninit(&buffer);
}
Example #14
0
File: t-tr.c Project: AnthraX1/rk
Boolean handler_output(Handler c)
{
  SshBuffer buffer;
  unsigned int len;
  const unsigned char *cp;
  Boolean wake_up_input = FALSE;
  
  for (;; c->script++)
    {
#ifdef DEBUG
      ssh_debug("%s: handler_output: %s", c->side, opnames[c->script->op]);
#endif
      switch (c->script->op)
        {
        case OP_EXPECT_SERVICE_REQUEST:
        case OP_EXPECT_DISCONNECT:
        case OP_EXPECT_EOF:
        case OP_EXPECT_STARTUP:
        case OP_EXPECT_ALGORITHMS:
        case OP_EXPECT_PACKET:
        case OP_EXPECT_TEST_STREAM:
          wake_up_input = TRUE;
          goto out;
          
        case OP_SEND_SERVICE_ACCEPT:
          handler_send_cross(c, SSH_CROSS_SERVICE_ACCEPT, NULL, 0);
          break;
          
        case OP_SEND_REKEY_REQUEST:
          ssh_buffer_init(&buffer);
          store_delimited_strings(&buffer, c->script->arg);
          handler_send_cross(c, SSH_CROSS_REKEY_REQUEST,
                             ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
          ssh_buffer_uninit(&buffer);
          break;
          
        case OP_SEND_PACKET:
          ssh_buffer_init(&buffer);
          buffer_put_char(&buffer, atoi(c->script->arg));
          handler_send_cross(c, SSH_CROSS_PACKET,
                             ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
          ssh_buffer_uninit(&buffer);
          break;

        case OP_SEND_TEST_STREAM:
          while (c->stream_offset < ssh_buffer_len(&testdata))
            {
              if (ssh_buffer_len(&c->outgoing) >
                  XMALLOC_MAX_SIZE - SSH_MAX_PAYLOAD_LENGTH - 5000 ||
                  ssh_buffer_len(&c->outgoing) > 50000 - SSH_MAX_PAYLOAD_LENGTH)
                if (!handler_output_outgoing(c))
                  goto out;
              len = random() % (SSH_MAX_PAYLOAD_LENGTH - 3);
              if (len > ssh_buffer_len(&testdata) - c->stream_offset)
                len = ssh_buffer_len(&testdata) - c->stream_offset;
              ssh_buffer_init(&buffer);
              buffer_put_char(&buffer, atoi(c->script->arg));
              cp = ssh_buffer_ptr(&testdata);
              ssh_buffer_append(&buffer, cp + c->stream_offset, len);
              c->stream_offset += len;
              handler_send_cross(c, SSH_CROSS_PACKET,
                                 ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
              ssh_buffer_uninit(&buffer);
            }
          c->stream_offset = 0;
          break;

        case OP_SEND_DISCONNECT:
          ssh_buffer_init(&buffer);
          buffer_put_boolean(&buffer, TRUE);
          buffer_put_int(&buffer, SSH_DISCONNECT_BY_APPLICATION);
          buffer_put_uint32_string(&buffer, c->script->arg,
                                    strlen(c->script->arg));
          buffer_put_uint32_string(&buffer, "", 0);
          handler_send_cross(c, SSH_CROSS_DISCONNECT,
                             ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
          ssh_buffer_uninit(&buffer);
          break;

        case OP_SEND_EOF:
          c->outgoing_eof = TRUE;
          break;
          
        case OP_END:
          goto out;

        default:
          ssh_fatal("%s: handler_output: unknown op %d",
                c->side, (int)c->script->op);
        }
    }

out:
  c->output_blocked = handler_output_outgoing(c);
  return wake_up_input;
}
Example #15
0
/* Handle the quoted string parsing. */
size_t
ssh_key_blob_get_string(const unsigned char *buf, size_t len,
                        char **string)
{
  unsigned int quoting, ret_quoting;
  SshBufferStruct buffer;
  size_t step, i, j;

  ssh_buffer_init(&buffer);
  for (i = 0, step = 0, quoting = 0, ret_quoting = 0; i < len; i++)
    {
      switch (quoting)
        {
        case 0:
          switch (buf[i])
            {
            case ' ':
            case '\n':
            case '\r':
            case '\t':
              /* Skip! */
              break;
            case '\"': /* " */
              quoting = 2;
              ret_quoting = 0;
              break;
            default:
              /* End! */
              step = i;
              goto end;
            }
          break;
        case 1:
          if (buf[i] == '\n')
            {
              for (j = 0; isspace(buf[i + j]) && i + j < len;
                   j++)
                ;
              i = i + j - 1;
            }
          quoting = ret_quoting;
          ret_quoting = 0;
          break;
        case 2:
          switch (buf[i])
            {
            case '\\':
              quoting = 1;
              ret_quoting = 2;
              break;
            case '\"': /* " */
              quoting = 0;
              ret_quoting = 0;
              break;
            default:
              ssh_xbuffer_append(&buffer, &buf[i], 1);
              break;
            }
        }
    }

end:

  /* Make a string. */
  *string = ssh_xmalloc(ssh_buffer_len(&buffer) + 1);
  memcpy(*string, ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer));
  (*string)[ssh_buffer_len(&buffer)] = '\0';

  ssh_buffer_uninit(&buffer);

  return step;
}
Example #16
0
void
ssh_virtual_adapter_configure(SshInterceptor interceptor,
			      SshInterceptorIfnum adapter_ifnum,
			      SshVirtualAdapterState adapter_state,
			      SshUInt32 num_addresses,
			      SshIpAddr addresses,
			      SshVirtualAdapterParams params,
			      SshVirtualAdapterStatusCB callback,
			      void *context)
{
  SshInterceptorVirtualAdapter va;
  SshInterceptorVirtualAdapterOp op;
  SshBufferStruct ip_buffer;
  unsigned char *param_ptr;
  size_t param_len;
  SshUInt32 i;
  SshVirtualAdapterError error = SSH_VIRTUAL_ADAPTER_ERROR_UNKNOWN_ERROR;
  SshIpAddrStruct undefined_ip;

  ssh_buffer_init(&ip_buffer);

  /* Assert that this virtual adapter exists. */
  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);
  SSH_ASSERT(va != NULL);

  /* Encode "clear all addresses" as one undefined address. */
  if (num_addresses == 0 && addresses != NULL)
    {
      SSH_IP_UNDEFINE(&undefined_ip);
      addresses = &undefined_ip;      
      num_addresses = 1;
    }
  
  /* Encode IP addresses. */
  for (i = 0; i < num_addresses; i++)
    {
      if (!ssh_encode_ipaddr_buffer(&ip_buffer, &addresses[i]))
	{
	  error = SSH_VIRTUAL_ADAPTER_ERROR_ADDRESS_FAILURE;
	  goto error;
	}
    }

  /* Encode params. */
  param_ptr = NULL;
  param_len = 0;
  if (params)
    {      
      if (!ssh_virtual_adapter_param_encode(params, &param_ptr, &param_len))
	{
	  error = SSH_VIRTUAL_ADAPTER_ERROR_ADDRESS_FAILURE;
	  goto error;
	}
    }

  /* Initialize an operation handle. */
  op = alloc_virtual_adapter_op(interceptor);
  op->status_cb = callback;
  op->context = context;

  SSH_DEBUG(SSH_D_NICETOKNOW, 
	    ("sending configure request for virtual adapter %d to forwarder.",
	     (int) adapter_ifnum));

  /* Send a message to the kernel forwarder module. */
  ssh_usermode_interceptor_send_encode(
                  interceptor,
                  SSH_ENGINE_IPM_FORWARDER_VIRTUAL_ADAPTER_CONFIGURE,
                  SSH_FORMAT_UINT32, op->id,
		  SSH_FORMAT_UINT32, adapter_ifnum,
		  SSH_FORMAT_UINT32, adapter_state,
		  SSH_FORMAT_UINT32, num_addresses,
                  SSH_FORMAT_UINT32_STR, 
		  ssh_buffer_ptr(&ip_buffer), ssh_buffer_len(&ip_buffer),
                  SSH_FORMAT_UINT32_STR, param_ptr, param_len,
                  SSH_FORMAT_END);

  op->handle = ssh_operation_register(virtual_adapter_operation_abort, op);
  ssh_buffer_uninit(&ip_buffer);
  ssh_free(param_ptr);
  return;

 error:
  ssh_buffer_uninit(&ip_buffer);
  ssh_free(param_ptr);

  (*callback)(error, adapter_ifnum, NULL, SSH_VIRTUAL_ADAPTER_STATE_UNDEFINED,
	      NULL, context);
}
Example #17
0
int main(int ac, char **av)
{
  unsigned int pass, i;
  SshBuffer buffer, buffer2;
  SocksInfo socksinfo, socksreturn;
  SocksError ret;

  ssh_buffer_init(&buffer);
  ssh_buffer_init(&buffer2);
  for(pass = 0; pass < 20000; pass++)
    {
      ssh_buffer_clear(&buffer);
      socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec));
      socksinfo->socks_version_number = 4;
      socksinfo->command_code = (pass & 1) + 1;
      socksinfo->ip =
	ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) /
				   sizeof(ip_numbers[0]))]);
      socksinfo->port =
	ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) /
				     sizeof(port_numbers[0]))]);
      socksinfo->username =
	ssh_xstrdup(usernames[pass % (sizeof(usernames) /
				  sizeof(usernames[0]))]);
      if (ssh_socks_client_generate_open(&buffer, socksinfo) !=
	  SSH_SOCKS_SUCCESS)
	ssh_fatal("ssh_socks_client_generate_open fails");
      if (pass & 1)
	{
	  unsigned char *p;
	  unsigned int len;
	  
	  ssh_buffer_clear(&buffer2);
	  p = ssh_buffer_ptr(&buffer);
	  len = ssh_buffer_len(&buffer);
	  /* Give partial buffer */
	  for(i = 0; i + 1 < len; i++)
	    {
	      ssh_buffer_append(&buffer2, p + i, 1);
	      if (ssh_socks_server_parse_open(&buffer2, &socksreturn) !=
		  SSH_SOCKS_TRY_AGAIN)
		ssh_fatal("ssh_socks_server_parse_open fails in partial data (should return try_again)");
	    }
	  ssh_buffer_append(&buffer2, p + i, 1);
	  if (ssh_socks_server_parse_open(&buffer2, &socksreturn) !=
	      SSH_SOCKS_SUCCESS)
	    ssh_fatal("ssh_socks_server_parse_open fails for partial data (should return success)");
          if (ssh_buffer_len(&buffer2) != 0)
	    ssh_fatal("Junk left to buffer after server_parse_open");
	}
      else
	{
	  if (ssh_socks_server_parse_open(&buffer, &socksreturn) !=
	      SSH_SOCKS_SUCCESS)
	    ssh_fatal("ssh_socks_server_parse_open fails for partial data (should return success)");
          if (ssh_buffer_len(&buffer) != 0)
	    ssh_fatal("Junk left to buffer after server_parse_open");
	}
      if (socksinfo->socks_version_number != socksreturn->socks_version_number)
	ssh_fatal("socks_version_numbers differ request");
      if (socksinfo->command_code != socksreturn->command_code)
	ssh_fatal("command_codes differ request");
      if (strcmp(socksinfo->ip, socksreturn->ip) != 0)
	ssh_fatal("ip numbers differ request");
      if (strcmp(socksinfo->port, socksreturn->port) != 0)
	ssh_fatal("port numbers differ request");
      if (strcmp(socksinfo->username, socksreturn->username) != 0)
	ssh_fatal("usernames differ request");
      ssh_socks_free(&socksreturn);
      ssh_socks_free(&socksinfo);
      
      ssh_buffer_clear(&buffer);
      socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec));
      socksinfo->socks_version_number = 0;
      socksinfo->command_code = (pass % 4) + 90;
      socksinfo->ip =
	ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) /
				   sizeof(ip_numbers[0]))]);
      socksinfo->port =
	ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) /
				     sizeof(port_numbers[0]))]);
      socksinfo->username =
	ssh_xstrdup(usernames[pass % (sizeof(usernames) /
				  sizeof(usernames[0]))]);
      if (ssh_socks_server_generate_reply(&buffer, socksinfo) !=
	  SSH_SOCKS_SUCCESS)
	ssh_fatal("ssh_socks_server_generate_reply fails");
      if (pass & 1)
	{
	  unsigned char *p;
	  unsigned int len;
	  
	  ssh_buffer_clear(&buffer2);
	  p = ssh_buffer_ptr(&buffer);
	  len = ssh_buffer_len(&buffer);
	  /* Give partial buffer */
	  for(i = 0; i + 1 < len; i++)
	    {
	      ssh_buffer_append(&buffer2, p + i, 1);
	      if (ssh_socks_client_parse_reply(&buffer2, &socksreturn) !=
		  SSH_SOCKS_TRY_AGAIN)
		ssh_fatal("ssh_socks_server_parse_open fails in partial data (should return try_again)");
	    }
	  ssh_buffer_append(&buffer2, p + i, 1);
	  ret = ssh_socks_client_parse_reply(&buffer2, &socksreturn);
	  if (((pass % 4) == 0 && ret != SSH_SOCKS_SUCCESS) ||
	      ((pass % 4) == 1 && ret != SSH_SOCKS_FAILED_REQUEST) ||
	      ((pass % 4) == 2 && ret != SSH_SOCKS_FAILED_IDENTD) ||
	      ((pass % 4) == 3 && ret != SSH_SOCKS_FAILED_USERNAME))
	    ssh_fatal("ssh_socks_client_parse_reply fails for partial data");
          if (ret == SSH_SOCKS_SUCCESS && ssh_buffer_len(&buffer2) != 0)
	    ssh_fatal("Junk left to buffer after server_parse_open");
	}
      else
	{
	  ret = ssh_socks_client_parse_reply(&buffer, &socksreturn);
	  if (((pass % 4) == 0 && ret != SSH_SOCKS_SUCCESS) ||
	      ((pass % 4) == 1 && ret != SSH_SOCKS_FAILED_REQUEST) ||
	      ((pass % 4) == 2 && ret != SSH_SOCKS_FAILED_IDENTD) ||
	      ((pass % 4) == 3 && ret != SSH_SOCKS_FAILED_USERNAME))
	    ssh_fatal("ssh_socks_client_parse_reply fails");
          if (ret == SSH_SOCKS_SUCCESS && ssh_buffer_len(&buffer) != 0)
	    ssh_fatal("Junk left to buffer after server_parse_open");
	}
      if (ret == SSH_SOCKS_SUCCESS)
	{
	  if (socksinfo->socks_version_number !=
	      socksreturn->socks_version_number)
	    ssh_fatal("socks_version_numbers differ reply");
	  if (socksinfo->command_code != socksreturn->command_code)
	    ssh_fatal("command_codes differ reply");
	  if (strcmp(socksinfo->ip, socksreturn->ip) != 0)
	    ssh_fatal("ip numbers differ reply");
	  if (strcmp(socksinfo->port, socksreturn->port) != 0)
	    ssh_fatal("port numbers differ reply");
	  ssh_socks_free(&socksreturn);
	}
      ssh_socks_free(&socksinfo);
    }
  
  ssh_buffer_clear(&buffer);
  
  for(pass = 0;
      pass < (sizeof(ip_invalid_numbers) / sizeof(ip_invalid_numbers[0]));
      pass++)
    {
      socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec));
      socksinfo->socks_version_number = 4;
      socksinfo->command_code = (pass & 1) + 1;
      socksinfo->ip =
	ssh_xstrdup(ip_invalid_numbers[pass % (sizeof(ip_invalid_numbers) /
					   sizeof(ip_invalid_numbers[0]))]);
      socksinfo->port =
	ssh_xstrdup(port_numbers[pass % (sizeof(port_numbers) /
				     sizeof(port_numbers[0]))]);
      socksinfo->username =
	ssh_xstrdup(usernames[pass % (sizeof(usernames) /
				  sizeof(usernames[0]))]);
      if (ssh_socks_client_generate_open(&buffer, socksinfo) ==
	  SSH_SOCKS_SUCCESS)
	ssh_fatal("ssh_socks_client_generate_open success (should fail, ip)");
      socksinfo->socks_version_number = 0;
      socksinfo->command_code = (pass % 4) + 90;
      if (ssh_socks_server_generate_reply(&buffer, socksinfo) ==
	  SSH_SOCKS_SUCCESS)
	ssh_fatal("ssh_socks_server_generate_reply success (should fail, ip)");
      ssh_socks_free(&socksinfo);
    }
  for(pass = 0;
      pass < (sizeof(port_invalid_numbers) / sizeof(port_invalid_numbers[0]));
      pass++)
    {
      socksinfo = ssh_xmalloc(sizeof(struct SocksInfoRec));
      socksinfo->socks_version_number = 4;
      socksinfo->command_code = (pass & 1) + 1;
      socksinfo->ip =
	ssh_xstrdup(ip_numbers[pass % (sizeof(ip_numbers) /
				   sizeof(ip_numbers[0]))]);
      socksinfo->port =
	ssh_xstrdup(port_invalid_numbers[pass % (sizeof(port_invalid_numbers) /
					     sizeof(port_invalid_numbers[0]))]);
      socksinfo->username =
	ssh_xstrdup(usernames[pass % (sizeof(usernames) /
				  sizeof(usernames[0]))]);
      if (ssh_socks_client_generate_open(&buffer, socksinfo) ==
	  SSH_SOCKS_SUCCESS)
	ssh_fatal("ssh_socks_client_generate_open success (should fail, port)");
      socksinfo->command_code = (pass % 4) + 90;
      socksinfo->socks_version_number = 0;
      if (ssh_socks_server_generate_reply(&buffer, socksinfo) ==
	  SSH_SOCKS_SUCCESS)
	ssh_fatal("ssh_socks_server_generate_reply success (should fail, port)");
      ssh_socks_free(&socksinfo);
    }
  if (ssh_buffer_len(&buffer) != 0)
    ssh_fatal("some of the failed ssh_socks_*_generate_* function wrote something to buffer, size != 0");
  ssh_buffer_uninit(&buffer);
  ssh_buffer_uninit(&buffer2);
  return 0;
}
Example #18
0
int
ssh_cm_render_certificate(unsigned char *buf, int len,
			  int precision, void *datum)
{

  SshX509Certificate cert = datum;
  char *name;
  unsigned char *t;
  SshX509Name names;
  SshMPIntegerStruct mp;
  SshBerTimeStruct not_before, not_after;
  SshBufferStruct buffer;
  SshX509OidList oid_list;
  const SshOidStruct *oids;
  Boolean critical;
  SshStr str;
  size_t l, kid_len;
  SshPublicKey pub;
  unsigned char *kid;

  if (cert)
    {
      ssh_buffer_init(&buffer);
      ssh_buffer_append_str(&buffer, "\ncertificate = { \n");

      /* Add the serial number. */
      ssh_mprz_init(&mp);
      if (ssh_x509_cert_get_serial_number(cert, &mp) == FALSE)
        {
          ssh_buffer_append_str(&buffer, "  missing-serial-number\n");
        }
      else
        {
	  if ((t = (unsigned char *) ssh_mprz_get_str(&mp, 10)) != NULL)
	    {
	      ssh_buffer_append_cstrs(&buffer,
				      "  serial-number = ", t, "\n", NULL);
	      ssh_mprz_clear(&mp);
	      ssh_free(t);
	    }
	  else
	    {
	      ssh_mprz_clear(&mp);
	      ssh_buffer_uninit(&buffer);
	      return -1;
	    }
	}

      /* Add suitable names. */
      ssh_x509_name_reset(cert->subject_name);
      if (!ssh_x509_cert_get_subject_name_str(cert, &str))
        {
          ssh_buffer_append_str(&buffer, "  missing-subject-name\n");
        }
      else
        {
          SshStr latin1 = ssh_str_charset_convert(str,
						  SSH_CHARSET_ISO_8859_1);

          name = (char *)ssh_str_get(latin1, &l);
          ssh_buffer_append_cstrs(&buffer,
                                  "  subject-name = <", name, ">\n", NULL);
          ssh_str_free(latin1);
          ssh_free(name);
          ssh_str_free(str);
        }
      ssh_x509_name_reset(cert->issuer_name);
      if (!ssh_x509_cert_get_issuer_name(cert, &name))
        {
          ssh_buffer_append_str(&buffer, "  missing-issuer-name\n");
        }
      else
        {
          ssh_buffer_append_cstrs(&buffer,
                                  "  issuer-name = <", name, ">\n", NULL);
          ssh_free(name);
        }

      /* Validity period. */
      if (!ssh_x509_cert_get_validity(cert, &not_before, &not_after))
        {
          ssh_buffer_append_str(&buffer, "  missing-validity-period\n");
        }
      else
        {
	  if ((t = ssh_malloc(64)) != NULL)
	    {
	      if (ssh_ber_time_available(&not_before))
		{
		  ssh_snprintf(t, 64,
			       "%@", ssh_ber_time_render, &not_before);
		  ssh_buffer_append_cstrs(&buffer,
					  "  not-before = ", t, "\n", NULL);
		}
	      if (ssh_ber_time_available(&not_after))
		{
		  ssh_snprintf(t, 64,
			       "%@", ssh_ber_time_render, &not_after);
		  ssh_buffer_append_cstrs(&buffer,
					  "  not-after = ", t, "\n", NULL);
		}
	      ssh_free(t);
	    }
        }

      if (ssh_x509_cert_get_subject_key_id(cert, &kid, &kid_len, &critical))
        {
          unsigned char *fingerprint;

          if ((fingerprint = (unsigned char *)
               ssh_fingerprint(kid, kid_len,  SSH_FINGERPRINT_HEX_UPPER))
              != NULL)
            ssh_buffer_append_cstrs(&buffer,
                                    "  subject-kid = ",
                                    fingerprint, "\n", NULL);
          ssh_free(fingerprint);
        }
      if (ssh_x509_cert_get_public_key(cert, &pub))
        {
          unsigned char *key_digest;
          size_t digest_len;

          if (ssh_cm_key_kid_create(pub, FALSE, &key_digest, &digest_len))
            {
              unsigned char *fingerprint;

              fingerprint =
		(unsigned char *)ssh_fingerprint(key_digest,
						 digest_len,
						 SSH_FINGERPRINT_HEX_UPPER);
              if (fingerprint)
                {
                  ssh_buffer_append_cstrs(&buffer,
                                          "  pubkey-hash = ",
                                          ssh_sstr(fingerprint), "\n", NULL);

                }
              ssh_free(fingerprint);
              ssh_free(key_digest);
            }
          ssh_public_key_free(pub);
        }

      /* Some alternate names. */
      if (ssh_x509_cert_get_subject_alternative_names(cert, &names, &critical))
        {
          ssh_x509_name_reset(names);
          ssh_buffer_append_str(&buffer, "  subject-alt-names = { \n");
          ssh_cm_names_dump(&buffer, names);
          ssh_buffer_append_str(&buffer, "  }\n");
        }

      if (ssh_x509_cert_get_issuer_alternative_names(cert, &names, &critical))
        {
          ssh_x509_name_reset(names);
          ssh_buffer_append_str(&buffer, "  issuer-alt-names = { \n");
          ssh_cm_names_dump(&buffer, names);
          ssh_buffer_append_str(&buffer, "  }\n");
        }

      if (ssh_x509_cert_get_ext_key_usage(cert, &oid_list, &critical))
        {
          ssh_buffer_append_str(&buffer, "  extended-key-usage = { \n");
          while (oid_list != NULL)
            {
              oids = ssh_oid_find_by_oid_of_type(ssh_custr(oid_list->oid),
                                                 SSH_OID_EXT_KEY_USAGE);
              if (oids == NULL)
                ssh_buffer_append_cstrs(&buffer,
                                        "    (", oid_list->oid, ")\n",
                                        NULL);
              else
                ssh_buffer_append_cstrs(&buffer,
                                        "    ", oids->std_name,
                                        " (", oid_list->oid, ")\n",
                                        NULL);
              oid_list = oid_list->next;
            }
          ssh_buffer_append_str(&buffer, "  }\n");
        }
      ssh_buffer_append_str(&buffer, "}\n");

      return cm_debug_renderer_return(&buffer, buf, len);
    }
  return 0;
}
Example #19
0
void ssh_channel_ftcp_incoming_connection(SshIpError error, SshStream stream,
                                          void *context)
{
  SshRemoteTcpForward fwd = (SshRemoteTcpForward)context;
  char ip[20], port[20];
  SshBuffer buffer;

  SSH_DEBUG(5, ("connection to forwarded TCP/IP port"));
  
  /* We should only receive new connection notifications. */
  if (error != SSH_IP_NEW_CONNECTION)
    ssh_fatal("ssh_channel_ftcp_incoming_connection: error %d", (int)error);

  /* Get remote ip address and port. */
  if (!ssh_tcp_get_remote_address(stream, ip, sizeof(ip)))
    strcpy(ip, "UNKNOWN");
  if (!ssh_tcp_get_remote_port(stream, port, sizeof(port)))
    strcpy(port, "UNKNOWN");

  SSH_TRACE(0, ("Connection to forwarded port %s from %s:%s",
                fwd->port, ip, port));
  ssh_log_event(fwd->common->config->log_facility,
                SSH_LOG_INFORMATIONAL,
                "Connection to forwarded port %s from %s:%s",
                fwd->port, fwd->common->remote_host, port);

  /* XXXXXXXX */
#ifdef HAVE_LIBWRAP
  {
    struct request_info req;
    struct servent *serv;
    char fwdportname[32];
    void *old_handler;
    
    old_handler = signal(SIGCHLD, SIG_DFL);

    /* try to find port's name in /etc/services */
    serv = getservbyport(atoi(fwd->port), "tcp");
    if (serv == NULL)
      {
        /* not found (or faulty getservbyport) -
           use the number as a name */
        snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%s", fwd->port);
      }
    else
      {
        snprintf(fwdportname, sizeof(fwdportname), "sshdfwd-%.20s",
                 serv->s_name);
      }
    /* fill req struct with port name and fd number */
    request_init(&req, RQ_DAEMON, fwdportname,
                 RQ_FILE, ssh_stream_fd_get_readfd(stream), NULL);
    fromhost(&req);
    if (!hosts_access(&req))
      {
        ssh_conn_send_debug(fwd->common->conn, TRUE,
                            "Fwd connection from %.500s to local port " \
                            "%s refused by tcp_wrappers.",
                            eval_client(&req), fwdportname);
        ssh_stream_destroy(stream);
        signal(SIGCHLD, old_handler);
    
        return;
      }
    signal(SIGCHLD, old_handler);
        
    ssh_log_event(fwd->common->config->log_facility, SSH_LOG_INFORMATIONAL,
                  "Remote fwd connect from %.500s to local port %s",
                  eval_client(&req), fwdportname);
  }
#endif /* HAVE_LIBWRAP */

  /* Register that we have an open channel. */
  ssh_common_new_channel(fwd->common);
  
  /* Send a request to open a channel and connect it to the given port. */
  ssh_buffer_init(&buffer);
  ssh_encode_buffer(&buffer,
                    SSH_FORMAT_UINT32_STR,
                    fwd->address_to_bind, strlen(fwd->address_to_bind),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(fwd->port),
                    SSH_FORMAT_UINT32_STR, ip, strlen(ip),
                    SSH_FORMAT_UINT32, (SshUInt32) atol(port),
                    SSH_FORMAT_END);
  ssh_conn_send_channel_open(fwd->common->conn, "forwarded-tcpip",
                             stream, TRUE, FALSE, SSH_TCPIP_WINDOW,
                             SSH_TCPIP_PACKET_SIZE,
                             ssh_buffer_ptr(&buffer), ssh_buffer_len(&buffer),
                             NULL,
                             ssh_channel_tcp_connection_destroy,
                             (void *)fwd->common, NULL, NULL);
  ssh_buffer_uninit(&buffer);
}  
Example #20
0
File: t-tr.c Project: AnthraX1/rk
int main(int ac, char **av)
{
  char port[100];
  int i;
  TestCase *testcase;
  int pass;
  SshTime time_now;

  time_now = ssh_time();
  srandom(time_now);

  for (pass = 0; pass < PASSES; pass++)
    {
#ifdef DEBUG
      ssh_debug("pass %d", pass);
#endif
      random_state = ssh_random_allocate();

      /* randomize it a bit */
      ssh_random_add_noise(random_state, &time_now, sizeof(time_now));

      ssh_buffer_init(&testdata);
      for (i = 0; i < 100000; i++)
        buffer_put_char(&testdata, ssh_random_get_byte(random_state));

      ssh_event_loop_initialize();

      for (i = 0; tests[i].name; i++)
        {
          testcase = &tests[i];
          end_of_script_count = 0;

#ifdef DEBUG      
          ssh_debug("Running test %s", testcase->name);
#endif
          
          snprintf(port, sizeof(port), "%d", (int)(35000 + random() % 1000));
#ifdef DEBUG
          ssh_debug("Making listener, port %s...", port);
#endif
          listener = ssh_tcp_make_listener("127.0.0.1", port,
                                              listener_callback,
                                              (void *)testcase);
          if (!listener)
            ssh_fatal("making listener failed");
#ifdef DEBUG      
          ssh_debug("Making connect...");
#endif
          ssh_tcp_connect_with_socks("127.0.0.1", port, NULL, 2,
                             connect_callback, (void *)testcase);

#ifdef DEBUG      
          ssh_debug("Event loop running...");
#endif 
          ssh_event_loop_run();
#ifdef DEBUG
          ssh_debug("Event loop exited...");
#endif
          if (end_of_script_count != 2)
            ssh_fatal("end_of_script_count %d, script end not reached.",
                  end_of_script_count);
          /* Listener was destroyed in callback. */
        }
  
      ssh_event_loop_uninitialize();
      ssh_buffer_uninit(&testdata);
      ssh_random_free(random_state);
    }
#ifdef DEBUG
  ssh_debug("Exiting...");
#endif
  return 0;
}
Example #21
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;
}
Example #22
0
/* Encodes terminal modes for the terminal referenced by fd in a
   portable manner, and appends the modes to a buffer being
   constructed. Stores constructed buffers len to buf_len. This call
   always succeeds, but if an error happens during encoding, buf will
   be empty and buf_len will be 0 */
void ssh_encode_tty_flags(int fd, unsigned char **buf, size_t *buf_len)
     /*void tty_make_modes(int fd)*/
{
  SshBuffer buffer;  
#ifdef USING_TERMIOS
  struct termios tio;
#endif
#ifdef USING_SGTTY
  struct sgttyb tio;
  struct tchars tiotc;
  struct ltchars tioltc;
  int tiolm;
#ifdef TIOCGSTAT
  struct tstatus tiots;
#endif /* TIOCGSTAT */
#endif /* USING_SGTTY */
  int baud;

  if (!isatty(fd))
    {
      SSH_TRACE(2, ("Not a tty. (fd = %d)", fd));
      *buf = ssh_xstrdup("");
      *buf_len = 0;
      return;
    }
  
  ssh_buffer_init(&buffer);

  /* Get the modes. */
#ifdef USING_TERMIOS
  if (tcgetattr(fd, &tio) < 0)
    {
      PUT_CHAR(TTY_OP_END);
      ssh_warning("tcgetattr: %.100s", strerror(errno));
      goto error;
    }
#endif /* USING_TERMIOS */
#ifdef USING_SGTTY
  if (ioctl(fd, TIOCGETP, &tio) < 0)
    {
      PUT_CHAR(TTY_OP_END);
      ssh_warning("ioctl(fd, TIOCGETP, ...): %.100s", strerror(errno));
      goto error;
    }
  if (ioctl(fd, TIOCGETC, &tiotc) < 0)
    {
      PUT_CHAR(TTY_OP_END);
      ssh_warning("ioctl(fd, TIOCGETC, ...): %.100s", strerror(errno));
      goto error;
    }
  if (ioctl(fd, TIOCLGET, &tiolm) < 0)
    {
      PUT_CHAR(TTY_OP_END);
      ssh_warning("ioctl(fd, TIOCLGET, ...): %.100s", strerror(errno));
      goto error;
    }
  if (ioctl(fd, TIOCGLTC, &tioltc) < 0)
    {
      PUT_CHAR(TTY_OP_END);
      ssh_warning("ioctl(fd, TIOCGLTC, ...): %.100s", strerror(errno));
      goto error;
    }
#ifdef TIOCGSTAT
  if (ioctl(fd, TIOCGSTAT, &tiots) < 0) 
    {
      PUT_CHAR(TTY_OP_END);
      ssh_warning("ioctl(fd, TIOCGSTAT, ...): %.100s", strerror(errno));
      goto error;
    }
#endif /* TIOCGSTAT */
  /* termio's ECHOE is really both LCRTBS and LCRTERA - so wire them
     together */
  if (tiolm & LCRTBS)
    tiolm |= LCRTERA;
#endif /* USING_SGTTY */

  /* Store input and output baud rates. */
  baud = speed_to_baud(cfgetospeed(&tio));
  PUT_CHAR(TTY_OP_OSPEED);
  PUT_UINT32(baud);
  baud = speed_to_baud(cfgetispeed(&tio));
  PUT_CHAR(TTY_OP_ISPEED);
  PUT_UINT32(baud);

  /* Store values of mode flags. */
#ifdef USING_TERMIOS
#define TTYCHAR(NAME, OP) \
  PUT_CHAR(OP); PUT_UINT32(tio.c_cc[NAME]);
#define TTYMODE(NAME, FIELD, OP) \
  PUT_CHAR(OP); PUT_UINT32((tio.FIELD & NAME) != 0);
#define SGTTYCHAR(NAME, OP)
#define SGTTYMODE(NAME, FIELD, OP)
#define SGTTYMODEN(NAME, FIELD, OP)
#endif /* USING_TERMIOS */

#ifdef USING_SGTTY
#define TTYCHAR(NAME, OP)
#define TTYMODE(NAME, FIELD, OP)
#define SGTTYCHAR(NAME, OP) \
  PUT_CHAR(OP); PUT_UINT32(NAME);
#define SGTTYMODE(NAME, FIELD, OP) \
  PUT_CHAR(OP); PUT_UINT32((FIELD & NAME) != 0);
#define SGTTYMODEN(NAME, FIELD, OP) \
  PUT_CHAR(OP); PUT_UINT32((FIELD & NAME) == 0);
#endif /* USING_SGTTY */

#include "sshttyflagsi.h"

#undef TTYCHAR
#undef TTYMODE
#undef SGTTYCHAR
#undef SGTTYMODE
#undef SGTTYMODEN

  /* Mark end of mode data. */
  PUT_CHAR(TTY_OP_END);

  *buf_len = ssh_buffer_len(&buffer);
  *buf = ssh_xmemdup(ssh_buffer_ptr(&buffer), *buf_len);
  ssh_buffer_uninit(&buffer);

  SSH_DEBUG_HEXDUMP(5, ("encoded tty-flags buffer"), *buf, *buf_len);
  
  return;

 error:
  ssh_buffer_uninit(&buffer);
  *buf = ssh_xstrdup("");
  *buf_len = 0;
}