Exemple #1
0
void create_server_keys(SshPrivateKey *host, SshPrivateKey *server,
                        unsigned char **blob, unsigned int *len)
{
  SshPublicKey public_host_key;

#ifdef DEBUG
  ssh_debug("generating host key");
#endif
  if (ssh_private_key_generate(random_state, host,
                               SSH_CRYPTO_RSA, SSH_PKF_SIZE, 768, 
                               SSH_PKF_END) != SSH_CRYPTO_OK)
    ssh_fatal("Generating host key failed");
#ifdef DEBUG
  ssh_debug("generating server key");
#endif

  if (ssh_private_key_generate(random_state, server,
                               SSH_CRYPTO_RSA, SSH_PKF_SIZE, 512, 
                               SSH_PKF_END) != SSH_CRYPTO_OK)
    ssh_fatal("Generating server key failed");

#ifdef DEBUG  
  ssh_debug("deriving public host key blob");
#endif
  public_host_key = ssh_private_key_derive_public_key(*host);
  if (ssh_public_key_export(public_host_key, blob, len) != SSH_CRYPTO_OK)
    ssh_fatal("deriving public key blob failed");
  ssh_public_key_free(public_host_key);
}
Exemple #2
0
int main(int argc, char **argv)
{
  srand(ssh_time());

  utf8_basic_tests();
  ssh_debug("basic tests passed.");
  utf8_advanced_tests();
  ssh_debug("advanced tests passed.");

  return 0;
}
Exemple #3
0
void ssh_packet_wrapper_send_encode_va(SshPacketWrapper down,
                                       SshPacketType type,
                                       va_list va)
{
  /* Format the packet in a separate buffer. */
  ssh_buffer_clear(&down->outgoing_packet);
  ssh_packet_encode_va(&down->outgoing_packet, type, va);

  /* Check that we don't overflow maximum buffer size.  Drop the packet
     if we would. */
  if (ssh_buffer_len(&down->outgoing) +
      ssh_buffer_len(&down->outgoing_packet) >= BUFFER_MAX_SIZE)
    {
      ssh_debug("ssh_packet_wrapper_send_encode_va: flow control problems; "
                "outgoing packet dropped.");
      return;
    }

  /* Append the packet to the outgoing buffer. */
  ssh_buffer_append(&down->outgoing, ssh_buffer_ptr(&down->outgoing_packet),
                    ssh_buffer_len(&down->outgoing_packet));

  /* Reset the callback to ensure that our callback gets called. */
  ssh_stream_set_callback(down->stream, ssh_packet_wrapper_callback,
                          (void *)down);
}
Exemple #4
0
int ssh_pipe_stream_read(void *context, unsigned char *buf, size_t size)
{
    SshPipeStream pipes = (SshPipeStream)context;
    int len;

    len = ssh_stream_read(pipes->stdio_stream, buf, size);

    /* Convert the return status to EOF if the child has already
       exited.  Note that we'll want to keep reading as long as
       there is data available before returning the EOF, as the
       SIGCHLD handler might be called before all data is read. */
    if (len < 0 && pipes->status_returned)
    {
        ssh_debug("ssh_pipe_stream_read: faking eof after sigchld");
        len = 0;
    }
    else if (len == 0 && !pipes->status_returned)
    {
        /* We got real EOF, but the SIGCHLD handler hasn't been called yet.
           Do not return EOF quite yet; we fake it to no data available.
           When SIGCHLD is delivered, the callback will be called
           and it will call this again; at that time we'll return EOF.
           This is to ensure that a valid exit status is available after
           we return EOF. */
        len = -1;
    }
    return len;
}
Exemple #5
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;
}
Exemple #6
0
void connect_callback(SshIpError status, SshStream stream, void *context)
{
  Handler c;
  TestCase *testcase = context;
  SshTransportParams params;
  
  if (status != SSH_IP_OK)
    ssh_fatal("connect_callback: status %d", status);

#ifdef DEBUG
  ssh_debug("connect successful");
#endif  

  params = ssh_transport_create_params();
  update_algs(params, testcase->c_to_s_algs);
  
  c = ssh_xcalloc(sizeof(*c), 1);
  c->stream = ssh_transport_client_wrap(stream, random_state, SSH_VERSION,
                                        testcase->service, params,
                                        SERVER_NAME, NULL, NULL, NULL, NULL);
  c->script = testcase->client_script;
  c->side = "client";
  c->name = testcase->name;
  ssh_stream_set_callback(c->stream, handler_callback, (void *)c);
  client_handler = c;
}
Exemple #7
0
void ssh_pipe_sigchld_do_callback(void *context)
{
    SshPipeStream pipes = (SshPipeStream)context;

    ssh_debug("ssh_pipe_sigchld_do_callback");
    if (pipes->callback)
        (*pipes->callback)(SSH_STREAM_INPUT_AVAILABLE, pipes->callback_context);
}
Exemple #8
0
int main()
{
  int pass;

  srandom(ssh_time());

  ssh_event_loop_initialize();
  
  random_state = ssh_random_allocate();
  create_server_keys(&hostkey, &serverkey, &hostkey_blob, &hostkey_blob_len);

  pingpong_success = FALSE;
  for (pass = 0; pass < 10; pass++)
    {
#ifdef DEBUG
      ssh_debug("========== iteration %d ==========", pass);
#endif
      disconnect_test();
      simple_password_test(NULL);
    }
  if (!pingpong_success)
    ssh_fatal("main: no successful pingpong");

  pingpong_success = FALSE;
  
  for (pass = 0; pass < 100; pass++)
    {
#ifdef DEBUG
      ssh_debug("========== iteration dual-%d ==========", pass);
#endif
      disconnect_test();
      simple_password_test(dual_policy);
    }

  if (!pingpong_success)
    ssh_fatal("main: no successful pingpong");
  
  ssh_private_key_free(hostkey);
  ssh_private_key_free(serverkey);
  ssh_xfree(hostkey_blob);
  ssh_random_free(random_state);

  ssh_event_loop_uninitialize();
  return 0;
}
void ssh_packet_impl_send_encode_va(SshStream up_stream,
                                    SshPacketType type,
                                    va_list va)
{
  SshPacketImpl up;

  /* Verify that it is a SshPacketImpl stream. */
  if (ssh_stream_get_methods(up_stream) != &ssh_packet_impl_methods)
    ssh_fatal("ssh_packet_impl_can_receive: not a SshPacketImpl stream");
  /* Get the internal context. */
  up = (SshPacketImpl)ssh_stream_get_context(up_stream);

  /* Format the packet in a separate buffer. */
  ssh_buffer_clear(&up->outgoing_packet);
  ssh_packet_encode_va(&up->outgoing_packet, type, va);

  /* Check that we don't overflow maximum buffer size.  Drop the
     packet if we would. */
  if (ssh_buffer_len(&up->outgoing) + ssh_buffer_len(&up->outgoing_packet) >=
      BUFFER_MAX_SIZE)
    {
      ssh_debug("ssh_packet_impl_send_encode_va: "
                "flow control problems; outgoing packet dropped.");
      return;
    }

  /* Append the packet to the outgoing buffer. */
  if (ssh_buffer_append(&up->outgoing,
                        ssh_buffer_ptr(&up->outgoing_packet),
                        ssh_buffer_len(&up->outgoing_packet)) != SSH_BUFFER_OK)
    {
      return;
    }

  /* Restart reads by upper level. */
  ssh_packet_impl_restart_input(up);

  /* Sanity check that we didn't exceed max buffer size. */
  if (ssh_buffer_len(&up->outgoing) > BUFFER_MAX_SIZE)
    ssh_debug("ssh_packet_impl_send: buffer max size exceeded: size %ld",
              (long)ssh_buffer_len(&up->outgoing));
}
Exemple #10
0
void client_received_packet(SshCrossPacketType type,
                            const unsigned char *data, size_t len,
                            void *context)
{
#ifdef DEBUG
  switch (type)
    {
    case SSH_CROSS_PACKET:
      ssh_debug("client_received_packet: PACKET");
      break;
    case SSH_CROSS_DISCONNECT:
      ssh_debug("client_received_packet: DISCONNECT");
      simple_password_failed = TRUE;
      break;
    case SSH_CROSS_DEBUG:
      ssh_debug("client_received_packet: DEBUG");
      break;
    case SSH_CROSS_STARTUP:
      ssh_debug("client_received_packet: STARTUP");
      break;
    case SSH_CROSS_ALGORITHMS:
      ssh_debug("client_received_packet: ALGORITHMS");
      break;
    case SSH_CROSS_AUTHENTICATED:
      ssh_debug("client_received_packet: AUTHENTICATED");
      simple_password_authenticated = TRUE;
      break;
    default:
      ssh_fatal("client_received_packet: type %d", (int)type);
    }
#endif
}
Exemple #11
0
void update_algs(SshTransportParams params, const char *algs)
{
  char *copy;
  char *cp, **dest;
  int i;

  if (algs == NULL)
    return;
  
  copy = ssh_xstrdup(algs);
  for (i = 0, cp = strtok(copy, ":"); cp; i++, cp = strtok(NULL, ":"))
    {
      switch (i)
        {
        case 0: /* c_to_s_cipher */
          dest = &params->ciphers_c_to_s;
          break;
        case 1: /* s_to_c_cipher */
          dest = &params->ciphers_s_to_c;
          break;
        case 2: /* c_to_s_mac */
          dest = &params->macs_c_to_s;
          break;
        case 3: /* s_to_c_mac */
          dest = &params->macs_s_to_c;
          break;
        case 4: /* c_to_s_compression */
          dest = &params->compressions_c_to_s;
          break;
        case 5: /* s_to_c_compression */
          dest = &params->compressions_s_to_c;
          break;
        default:
          dest = NULL; /* to avoid compiler warning... */
          ssh_fatal("too many algorithms: %s", cp);
        }
#ifdef DEBUG
      ssh_debug("alg: %s\n", cp);
#endif
      if (*dest)
        ssh_xfree(*dest);
      *dest = ssh_xstrdup(cp);
    }
  ssh_xfree(copy);
}
Exemple #12
0
void ssh_pipe_stream_destroy(void *context)
{
    SshPipeStream pipes = (SshPipeStream)context;

    ssh_debug("ssh_pipe_stream_destroy");

    /* Cancel any pending input notification callbacks for this pipe. */
    ssh_cancel_timeouts(ssh_pipe_sigchld_do_callback, (void *)pipes);

    /* Unregister the sigchld handler for the stream. */
    ssh_sigchld_unregister(pipes->pid);

    /* Destroy the stream going to the master side. */
    ssh_stream_destroy(pipes->stdio_stream);

    /* Free our own data structures. */
    memset(pipes, 'F', sizeof(*pipes));
    ssh_xfree(pipes);
}
Exemple #13
0
void ssh_pipe_sigchld_handler(pid_t pid, int status, void *context)
{
    SshPipeStream pipes = (SshPipeStream)context;

    ssh_debug("ssh_pipe_sigchld_handler: pid %d status %d", (int)pid, status);

    /* Sanity checks... */
    if (pipes->status_returned)
        ssh_fatal("ssh_pipe_sigchld_handler: status already returned");

    /* Record the exit status. */
    pipes->status_returned = TRUE;
    pipes->exit_status = status;

    /* Schedule a callback from the bottom of the event loop.  Note that if
       the stream is destroyed, before the event is delivered, we'll cancel
       the timeout before destroying the context. */
    ssh_register_timeout(0L, 0L, ssh_pipe_sigchld_do_callback, (void *)pipes);
}
Exemple #14
0
char *dual_policy(const char *user, const char *service, const char *client_ip,
                  const char *client_port,
                  const char *completed_authentications, void *context)
{
#ifdef DEBUG
  ssh_debug("dual_policy: user '%s' service '%s' client_ip '%s' "
            "client_port '%s' completed '%s'",
            user, service, client_ip, client_port, completed_authentications);
#endif

  if (strcmp(completed_authentications, "") == 0)
    return ssh_xstrdup("password1");
  if (strcmp(completed_authentications, "password1") == 0)
    return ssh_xstrdup("password2");
  if (strcmp(completed_authentications, "password2") == 0)
    return ssh_xstrdup("password1");
  if (strcmp(completed_authentications, "password1,password2") == 0 ||
      strcmp(completed_authentications, "password2,password1") == 0)
    return NULL;
  return "";
}
Exemple #15
0
void listener_callback(SshIpError status, SshStream stream, void *context)
{
  SshPrivateKey private_host_key, private_server_key;
  unsigned char *blob;
  unsigned int blob_len = 0;
  Handler c;
  TestCase *testcase = context;
  SshTransportParams params;
  
  if (status != SSH_IP_NEW_CONNECTION)
    ssh_fatal("listener_callback: status %d", status);

#ifdef DEBUG
  ssh_debug("listener: new connection");
#endif
  
  create_server_keys(&private_host_key, &private_server_key, &blob, &blob_len);
  
  params = ssh_transport_create_params();
  update_algs(params, testcase->s_to_c_algs);

  c = ssh_xcalloc(sizeof(*c), 1);

  c->stream = ssh_transport_server_wrap(stream, random_state, SSH_VERSION,
                                        params,
                                        private_host_key, private_server_key,
                                        blob, blob_len, NULL, NULL);

  ssh_private_key_free(private_host_key);
  ssh_private_key_free(private_server_key);
  ssh_xfree(blob);
  c->script = testcase->server_script;
  c->side = "server";
  c->name = testcase->name;

  ssh_stream_set_callback(c->stream, handler_callback, (void *)c);
  server_handler = c;
  ssh_tcp_destroy_listener(listener);
}
Exemple #16
0
void ssh_packet_wrapper_callback(SshStreamNotification op, void *context)
{
  SshPacketWrapper down = (SshPacketWrapper)context;
  Boolean ret;

  ret = FALSE;

  /* Process the notification.  We loop between input and output
     operations until one returns FALSE (they return TRUE if the other
     operation should be performed). */
  do
    {
      switch (op)
        {
        case SSH_STREAM_CAN_OUTPUT:
          ret = ssh_packet_wrapper_output(down);
          op = SSH_STREAM_INPUT_AVAILABLE;
          break;

        case SSH_STREAM_INPUT_AVAILABLE:
          ret = ssh_packet_wrapper_input(down);
          op = SSH_STREAM_CAN_OUTPUT;
          break;

        case SSH_STREAM_DISCONNECTED:
          ssh_debug("ssh_packet_wrapper_callback: disconnected");
          ret = FALSE;
          break;

        default:
          ssh_fatal("ssh_packet_wrapper_callback: unknown op %d", (int)op);
        }
      /* Note: `down' might have been destroyed by now.  In that case
         `ret' is FALSE. */
    }
  while (ret == TRUE);
}
Exemple #17
0
void ssh_local_listen_callback(unsigned int events, void *context)
{
    SshLocalListener listener = (SshLocalListener)context;
    int sock, addrlen;
    struct sockaddr_un sunaddr;

    if (events & SSH_IO_READ)
    {
        addrlen = sizeof(sunaddr);
        sock = accept(listener->sock, (struct sockaddr *)&sunaddr, &addrlen);
        if (sock < 0)
        {
            ssh_debug("ssh_local_listen_callback: accept failed");
            return;
        }

        /* Re-enable requests on the listener. */
        ssh_io_set_fd_request(listener->sock, SSH_IO_READ);

        /* Inform user callback of the new socket.  Note that this might
           destroy the listener. */
        (*listener->callback)(ssh_stream_fd_wrap(sock, TRUE), listener->context);
    }
}
Exemple #18
0
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);
}
Exemple #19
0
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);
    }
}
Exemple #20
0
Boolean handler_input(Handler c)
{
  SshBuffer *packet;
  char *cp, *cp2;
  int len;
  unsigned char byte;
  Boolean wake_up_output = FALSE;

  for (;; c->script++)
    {
#ifdef DEBUG
      ssh_debug("%s: handler_input: %s", c->side, opnames[c->script->op]);
#endif
      switch (c->script->op)
        {
        case OP_EXPECT_SERVICE_REQUEST:
          packet = handler_input_expect_cross(c,
                                              SSH_CROSS_SERVICE_REQUEST);
          if (!packet)
            return FALSE;
          cp = buffer_get_uint32_string(packet, NULL);
          if (strcmp(cp, c->script->arg) != 0)
            ssh_fatal("%s: handler_input: service request mismatch: %s vs %s",
                  c->side, c->script->arg, cp);
          ssh_xfree(cp);
          ssh_buffer_free(packet);
          break;

        case OP_EXPECT_DISCONNECT:
          packet = handler_input_expect_cross(c, SSH_CROSS_DISCONNECT);
          if (!packet)
            return FALSE;
          (void)buffer_get_boolean(packet);
          (void)buffer_get_int(packet);
          cp = buffer_get_uint32_string(packet, NULL);
          ssh_xfree(buffer_get_uint32_string(packet, NULL)); /* lang. tag */
          if (strcmp(cp, c->script->arg) != 0)
            ssh_fatal("%s: handler_input: disconnect mismatch: %s vs %s",
                  c->side, c->script->arg, cp);
          ssh_xfree(cp);
          ssh_buffer_free(packet);
          break;
          
        case OP_EXPECT_EOF:
          len = ssh_stream_read(c->stream, &byte, 1);
          if (len < 0)
            return FALSE;
          if (len != 0)
            ssh_fatal("%s: handler_input: EOF expected, received 0x%0x",
                  c->side, byte);
          break;
          
        case OP_EXPECT_STARTUP:
          packet = handler_input_expect_cross(c, SSH_CROSS_STARTUP);
          if (!packet)
            return FALSE;
          ssh_buffer_free(packet);
          break;
          
        case OP_EXPECT_ALGORITHMS:
          packet = handler_input_expect_cross(c, SSH_CROSS_ALGORITHMS);
          if (!packet)
            return FALSE;
          ssh_buffer_free(packet);
          break;

        case OP_EXPECT_PACKET:
          packet = handler_input_expect_packet(c, atoi(c->script->arg));
          if (!packet)
            return FALSE;
          ssh_buffer_free(packet);
          break;
          
        case OP_EXPECT_TEST_STREAM:
          while (c->stream_offset < ssh_buffer_len(&testdata))
            {
              packet = handler_input_expect_packet(c, atoi(c->script->arg));
              if (!packet)
                return FALSE;
              cp = ssh_buffer_ptr(packet);
              cp2 = ssh_buffer_ptr(&testdata);
              if (memcmp(cp, cp2 + c->stream_offset, ssh_buffer_len(packet)) != 0)
                ssh_fatal("%s: handler_input: TEST_STREAM compare fail offset %d",
                      c->side, c->stream_offset);
              c->stream_offset += ssh_buffer_len(packet);
              ssh_buffer_free(packet);
            }
          c->stream_offset = 0;
          break;
          
        case OP_SEND_SERVICE_ACCEPT:
        case OP_SEND_REKEY_REQUEST:
        case OP_SEND_PACKET:
        case OP_SEND_TEST_STREAM:
        case OP_SEND_DISCONNECT:
        case OP_SEND_EOF:
          wake_up_output = TRUE;
          goto out;

        case OP_END:
          return FALSE;

        default:
          ssh_fatal("%s: handler_input: unknown op %d",
                c->side, (int)c->script->op);
        }
    }
out:
  c->input_blocked = TRUE;
  return wake_up_output;
}
Exemple #21
0
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;
}
Exemple #22
0
void handler_callback(SshStreamNotification notification, void *context)
{
  Handler c = context;
  SshTransportStatistics stats;
  Boolean cont = FALSE;
  
#ifdef DEBUG
  ssh_debug("\n** %s: handler_callback %s **\n", c->side,
            opnames[c->script->op]);
#endif

  do
    {
      switch (notification)
        {
        case SSH_STREAM_INPUT_AVAILABLE:
          cont = handler_input(c);
          if (cont)
            notification = SSH_STREAM_CAN_OUTPUT;
          break;
        case SSH_STREAM_CAN_OUTPUT:
          cont = handler_output(c);
          if (cont)
            notification = SSH_STREAM_INPUT_AVAILABLE;
          break;
        case SSH_STREAM_DISCONNECTED:
          ssh_fatal("%s: handler_callback: DISCONNECT", c->side);
          
        default:
          ssh_fatal("%s: handler_callback: unexpected %d",
                    c->side, (int)notification);
        }

      if (c->script->op == OP_END)
        {
          /* End of script reached.  Destroy handler. */
#ifdef DEBUG
          ssh_debug("%s: End of script reached", c->side);
#endif
          cont = FALSE;
          ssh_transport_get_statistics(c->stream, &stats);
#ifdef DEBUG

          ssh_debug("%s: %lu/%lu bytes in, %lu/%lu out, %lu packets in, "
                    "%lu out\n",
                    c->side,
                    stats.compressed_incoming_bytes,
                    stats.uncompressed_incoming_bytes,
                    stats.compressed_outgoing_bytes,
                    stats.uncompressed_outgoing_bytes,
                    stats.incoming_packets, stats.outgoing_packets);
#endif

          ssh_stream_destroy(c->stream);
          memset(c, 'F', sizeof(*c));
          ssh_xfree(c);
          end_of_script_count++;
        }
    }
  while (cont);
}
Exemple #23
0
Boolean ssh_pty_internal_make_ctty(int *ttyfd, const char *ttyname)
{
  int fd;

  /* First disconnect from the old controlling tty. */
#ifdef TIOCNOTTY
  fd = open("/dev/tty", O_RDWR|O_NOCTTY);
  if (fd >= 0)
    {
      (void)ioctl(fd, TIOCNOTTY, NULL);
      close(fd);
    }
#endif /* TIOCNOTTY */
  
  /* Verify that we are successfully disconnected from the controlling tty. */
  fd = open("/dev/tty", O_RDWR|O_NOCTTY);
  if (fd >= 0)
    {
      ssh_warning("Failed to disconnect from controlling tty.");
      close(fd);
    }

  /* Make it our controlling tty. */
#ifdef TIOCSCTTY
  ssh_debug("Setting controlling tty using TIOCSCTTY.");
  /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
     EINVAL with these arguments, and there is absolutely no documentation. */
  ioctl(*ttyfd, TIOCSCTTY, NULL);
#endif /* TIOCSCTTY */

#ifdef HAVE_SETPGID
  /* This appears to be necessary on some machines...  */
  setpgid(0, 0);
#endif

  fd = open(ttyname, O_RDWR);
  if (fd < 0)
    ssh_warning("%.100s: %.100s", ttyname, strerror(errno));
  else
    close(fd);

  /* Verify that we now have a controlling tty. */
  fd = open("/dev/tty", O_WRONLY);
  if (fd < 0)
    {
      ssh_warning("open /dev/tty failed; could not set controlling tty: %",
		  strerror(errno));
      return FALSE;
    }
  close(fd);
#if defined(HAVE_VHANGUP) && !defined(HAVE_REVOKE)
  signal(SIGHUP, SIG_IGN);
  vhangup();
  signal(SIGHUP, SIG_DFL);
  fd = open(ttyname, O_RDWR);
  if (fd == -1)
    ssh_warning("pty_make_controlling_tty: reopening controlling tty after vhangup failed for %.100s",
		ttyname);
  close(*ttyfd);
  *ttyfd = fd;
#endif /* HAVE_VHANGUP && !HAVE_REVOKE */
  return TRUE;
}
Exemple #24
0
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);
}
Exemple #25
0
SshServer ssh_server_wrap(SshStream stream, SshConfig config,
                          SshRandomState random_state,
                          SshPrivateKey private_server_key,
                          SshServerDisconnectProc disconnect,
                          SshServerDebugProc debug,
                          SshVersionCallback version_check,
                          SshAuthPolicyProc auth_policy_proc,
                          SshCommonAuthenticatedNotify authenticated_notify,
                          void *context)
{
  SshServer server;
  SshStream trans, auth;
  SshTransportParams params;

  /* Create parameters. */
  params = ssh_transport_create_params();
  if (!ssh_server_update_transport_params(config, params))
    {
      ssh_stream_destroy(stream);
      ssh_transport_destroy_params(params);
      return NULL;
    }

  /* Check the host key. */

  if (config->private_host_key == NULL || 
      config->public_host_key_blob == NULL)
    ssh_fatal("ssh_server_wrap: no host key !");

  /* Create the server object. */
  server = ssh_xcalloc(1, sizeof(*server));
  server->config = config;
  
  /* Create a transport layer protocol object. */
  ssh_debug("ssh_server_wrap: creating transport protocol");
  trans = ssh_transport_server_wrap(stream, random_state, 
                                    SSH2_PROTOCOL_VERSION_STRING,
                                    params, config->private_host_key,
                                    private_server_key,
                                    config->public_host_key_blob,
                                    config->public_host_key_blob_len,
                                    version_check,
                                    (void *)context);

  
  ssh_transport_get_compatibility_flags(trans, &server->compat_flags);
  
  /* Create the authentication methods array for the server. */
  server->methods = ssh_server_authentication_initialize();
  /* XXX config data */
  
  /* Create an authentication protocol object. */
  ssh_debug("ssh_server_wrap: creating userauth protocol");
  /* XXX policy_proc */
  auth = ssh_auth_server_wrap(trans, auth_policy_proc, (void *)server,
                              server->methods, (void *)server);

  /* Create the common part of client/server objects. */
  server->common = ssh_common_wrap(stream, auth, FALSE, config, random_state,
                                   NULL,
                                   disconnect, debug, authenticated_notify,
                                   context);

  if (server->common == NULL)
    {
      ssh_server_authentication_uninitialize(server->methods);
      ssh_xfree(server);
      return NULL;
    }
  
  return server;
}
Exemple #26
0
void simple_password_client(SshAuthClientOperation op,
                            const char *user,
                            unsigned int packet_type,
                            SshBuffer *packet_in,
                            const unsigned char *session_id,
                            size_t session_id_len,
                            void **state_placeholder,
                            SshAuthClientCompletionProc completion_proc,
                            void *completion_context,
                            void *method_context)
{
  char *pass;
  SshBuffer *b;
  ClientPingPongData *pd;
  SshUInt32 value;

#ifdef DEBUG
  ssh_debug("simple_password_client: op %d", (int)op);
#endif  

  switch (op)
    {
    case SSH_AUTH_CLIENT_OP_START:

      simple_user_accept = random() % 2;
      simple_password_accept = random() % 2;
      
      if (simple_password_may_fail && pingpong_success &&
          random() % 5 == 0)
        {
#ifdef DEBUG
          ssh_debug("simple_password_client: cancelling");
#endif
          simple_password_failed = TRUE;
          (*completion_proc)(SSH_AUTH_CLIENT_CANCEL, user, NULL,
                             completion_context);
          return;
        }
      
      if (simple_user_accept)
        user = CORRECT_USER;
      else
        user = WRONG_USER;
      if (simple_password_accept)
        pass = CORRECT_PASS;
      else
        pass = WRONG_PASS;

      b = ssh_buffer_allocate();

      if (pingpong_count > 0)
        {
          /* Send pingpong reply */
          assert(*state_placeholder == NULL);
          pd = ssh_xmalloc(sizeof(*pd));
          *state_placeholder = pd;
          pd->count = 0;
#ifdef DEBUG
          ssh_debug("simple_password_client: sending pongpong %ld", pd->count);
#endif
          ssh_encode_buffer(b,
                            SSH_FORMAT_BOOLEAN, TRUE,
                            SSH_FORMAT_UINT32, pd->count,
                            SSH_FORMAT_END);
          if (pd->count < pingpong_count)
            (*completion_proc)(SSH_AUTH_CLIENT_SEND_AND_CONTINUE, user, b,
                               completion_context);
          else
            {
              ssh_xfree(*state_placeholder);
              *state_placeholder = NULL;
              (*completion_proc)(SSH_AUTH_CLIENT_SEND, user, b,
                                 completion_context);
            }
        }
      else
        {
          /* Send normal reply */
#ifdef DEBUG
          ssh_debug("simple_password_client: sending req");
#endif
          ssh_encode_buffer(b,
                            SSH_FORMAT_BOOLEAN, FALSE,
                            SSH_FORMAT_UINT32_STR, pass, strlen(pass),
                            SSH_FORMAT_END);
          (*completion_proc)(SSH_AUTH_CLIENT_SEND, user, b,
                             completion_context);
        }
      ssh_buffer_free(b);
      break;
      
    case SSH_AUTH_CLIENT_OP_START_NONINTERACTIVE:
#ifdef DEBUG
      ssh_debug("simple_password_client: noninteractive failing");
#endif
      (*completion_proc)(SSH_AUTH_CLIENT_FAIL, user, NULL, completion_context);
      break;
      
    case SSH_AUTH_CLIENT_OP_CONTINUE:
#ifdef DEBUG
      ssh_debug("simple_password_client: OP_CONTINUE");
#endif
      pd = *state_placeholder;
      if (pd == NULL || pd->count < 0 || pd->count >= pingpong_count)
        ssh_fatal("simple_password_client: strange pd");
      if (ssh_decode_buffer(packet_in,
                            SSH_FORMAT_UINT32, &value,
                            SSH_FORMAT_END) == 0)
        ssh_fatal("simple_password_client: bad packet_in");
      if ((value ^ 0x12345678) != pd->count)
        ssh_fatal("simple_password_client: bad value");
      pd->count++;
#ifdef DEBUG
      ssh_debug("simple_password_client: sending pongpong %ld", pd->count);
#endif
      b = ssh_buffer_allocate();
      ssh_encode_buffer(b,
                        SSH_FORMAT_BOOLEAN, TRUE,
                        SSH_FORMAT_UINT32, pd->count,
                        SSH_FORMAT_END);
      if (pd->count < pingpong_count)
        (*completion_proc)(SSH_AUTH_CLIENT_SEND_AND_CONTINUE, user, b,
                           completion_context);
      else
        {
          ssh_xfree(*state_placeholder);
          *state_placeholder = NULL;
          (*completion_proc)(SSH_AUTH_CLIENT_SEND, user, b,
                             completion_context);
        }
      ssh_buffer_free(b);
      break;
      
    case SSH_AUTH_CLIENT_OP_ABORT:
      if (*state_placeholder)
        {
          ssh_xfree(*state_placeholder);
          *state_placeholder = NULL;
        }
      break;
      
    default:
      ssh_fatal("simple_password_client: unknown op %d", (int)op);
    }
}
Exemple #27
0
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;
}
Exemple #28
0
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;
}  
Exemple #29
0
SshAuthServerResult simple_password_server(SshAuthServerOperation op,
                                           const char *user,
                                           SshBuffer *packet,
                                           const unsigned char *session_id,
                                           size_t session_id_len,
                                           void **state_placeholder,
                                           void **longtime_placeholder,
                                           void *method_context)
{
  char *password;
  Boolean is_pingpong;
  SshUInt32 value;

#ifdef DEBUG
  ssh_debug("simple_password_server: op %d", (int)op);
#endif
  
  switch (op)
    {
    case SSH_AUTH_SERVER_OP_START:
      if (ssh_decode_buffer(packet,
                            SSH_FORMAT_BOOLEAN, &is_pingpong,
                            SSH_FORMAT_END) == 0)
        {
#ifdef DEBUG
          ssh_debug("simple_password_server: bad is_pingpong");
#endif
          return SSH_AUTH_SERVER_REJECTED;
        }
      if (!is_pingpong)
        {
          /* Normal password auth */
          if (pingpong_count != 0)
            ssh_fatal("simple_password_server: passwd when pingpong");
          if (ssh_decode_buffer(packet,
                                SSH_FORMAT_UINT32_STR, &password, NULL,
                                SSH_FORMAT_END) == 0)
            ssh_debug("simple_password_server: bad passwd request");
          
          if (strcmp(user, CORRECT_USER) == 0)
            {
              if (!simple_user_accept)
                ssh_fatal("simple_password_server: correct user, !accept");
            }
          else
            if (strcmp(user, WRONG_USER) == 0)
              {
                if (simple_user_accept)
                  ssh_fatal("simple_password_server: wrong user, accept");
              }
            else
              ssh_fatal("simple_password_server: bad user");
          
          if (strcmp(password, CORRECT_PASS) == 0)
            {
              if (!simple_password_accept)
                ssh_fatal("simple_password_server: correct pass, !accept");
            }
          else
            if (strcmp(password, WRONG_PASS) == 0)
              {
                if (simple_password_accept)
                  ssh_fatal("simple_password_server: wrong pass, accept");
              }
            else
              ssh_fatal("simple_password_server: bad pass");
          
          if (strcmp(user, CORRECT_USER) == 0 &&
              strcmp(password, CORRECT_PASS) == 0)
            {
              ssh_xfree(password);
#ifdef DEBUG
              ssh_debug("simple_password_server: accepted");
#endif
              return SSH_AUTH_SERVER_ACCEPTED;
            }
          
          ssh_xfree(password);
#ifdef DEBUG
          ssh_debug("simple_password_server: rejected");
#endif
          return SSH_AUTH_SERVER_REJECTED;
        }
      else
        {
          /* Pingpong request. */
          if (pingpong_count == 0)
            ssh_fatal("simple_password_server: pingpong when count 0");
          if (ssh_decode_buffer(packet,
                                SSH_FORMAT_UINT32, &value,
                                SSH_FORMAT_END) == 0)
            ssh_fatal("simple_password_server: bad pingpong");
          if (value == pingpong_count)
            {
#ifdef DEBUG
              ssh_debug("simple_password_server: pingpong count reached");
#endif
              return SSH_AUTH_SERVER_ACCEPTED;
            }
          *state_placeholder = (void *)value;
          value ^= 0x12345678;
          ssh_buffer_clear(packet);
          ssh_encode_buffer(packet,
                            SSH_FORMAT_CHAR, (unsigned int) PINGPONG_PACKET,
                            SSH_FORMAT_UINT32, value,
                            SSH_FORMAT_END);
          return SSH_AUTH_SERVER_CONTINUE_WITH_PACKET_BACK;
        }
      /*NOTREACHED*/
      abort();

    case SSH_AUTH_SERVER_OP_ABORT:
#ifdef DEBUG
      ssh_debug("simple_password_server: SERVER_OP_ABORT");
#endif
      *state_placeholder = NULL;
      return SSH_AUTH_SERVER_REJECTED;

    case SSH_AUTH_SERVER_OP_CONTINUE:
#ifdef DEBUG
      ssh_debug("simple_password_server: SERVER_OP_CONTINUE");
#endif
      if (ssh_decode_buffer(packet,
                            SSH_FORMAT_BOOLEAN, &is_pingpong,
                            SSH_FORMAT_UINT32, &value,
                            SSH_FORMAT_END) == 0)
        ssh_fatal("simple_password_server: bad pingpong continue");
      if (!is_pingpong)
        ssh_fatal("simple_password_server: !pingpong");
      if (((SshUInt32)*state_placeholder) + 1 != value)
        ssh_fatal("simple_password_server: pingpong did not +1");
      if (value == pingpong_count)
        {
#ifdef DEBUG
          ssh_debug("simple_password_server: pingpong count reached");
#endif
          *state_placeholder = NULL;
          pingpong_success = TRUE;
          return SSH_AUTH_SERVER_ACCEPTED;
        }
      *state_placeholder = (void *)value;
      value ^= 0x12345678;
      ssh_buffer_clear(packet);
      ssh_encode_buffer(packet,
                        SSH_FORMAT_CHAR, (unsigned int) PINGPONG_PACKET,
                        SSH_FORMAT_UINT32, value,
                        SSH_FORMAT_END);
      return SSH_AUTH_SERVER_CONTINUE_WITH_PACKET_BACK;

    case SSH_AUTH_SERVER_OP_UNDO_LONGTIME:
#ifdef DEBUG
      ssh_debug("simple_password_server: SERVER_OP_UNDO_LONGTIME");
#endif
      return SSH_AUTH_SERVER_REJECTED;

    case SSH_AUTH_SERVER_OP_CLEAR_LONGTIME:
#ifdef DEBUG
      ssh_debug("simple_password_server: SERVER_OP_CLEAR_LONGTIME");
#endif
      return SSH_AUTH_SERVER_REJECTED;

    default:
      ssh_fatal("simple_password_server: unknown op %d", (int)op);
    }
  /*NOTREACHED*/
  return SSH_AUTH_SERVER_REJECTED;
}