Example #1
0
int
ssh_cm_edb_distinguisher_render(unsigned char *buf, int buf_size,
				int precision, void *datum)
{
  int nbytes;
  SshCMDBDistinguisher *d = datum;
  unsigned char tmp[256];
  char *ldap;
  SshDNStruct dn;

  switch (d->key_type)
    {
    case SSH_CM_KEY_TYPE_DNS:
    case SSH_CM_KEY_TYPE_URI:
    case SSH_CM_KEY_TYPE_X400:
    case SSH_CM_KEY_TYPE_RFC822:
    case SSH_CM_KEY_TYPE_UNIQUE_ID:
      ssh_snprintf(tmp, sizeof(tmp), "%s", d->key);
      break;

    case SSH_CM_KEY_TYPE_DIRNAME:
    case SSH_CM_KEY_TYPE_DISNAME:
      ssh_dn_init(&dn);
      if (ssh_dn_decode_der(d->key, d->key_length, &dn, NULL))
        {
          if (ssh_dn_encode_ldap(&dn, &ldap))
            {
              strncpy(ssh_sstr(tmp), ldap, sizeof(tmp));
              ssh_free(ldap);
            }
        }
      ssh_dn_clear(&dn);
      break;

    case SSH_CM_KEY_TYPE_RID:
    case SSH_CM_KEY_TYPE_OTHER:
    case SSH_CM_KEY_TYPE_SERIAL_NO:
    case SSH_CM_KEY_TYPE_BER_HASH:
    case SSH_CM_KEY_TYPE_IDNUMBER:
    case SSH_CM_KEY_TYPE_PUBLIC_KEY_ID:
    case SSH_CM_KEY_TYPE_SI_HASH:
    case SSH_CM_KEY_TYPE_X509_KEY_IDENTIFIER:
    case SSH_CM_KEY_TYPE_CERT_HASH:
      ssh_snprintf(tmp, sizeof(tmp), "%.*@",
                   d->key_length, cm_edb_key_render, d->key);
      break;
    default:
      tmp[0] = '\0';
      break;
    };

  if ((nbytes =
       ssh_snprintf(buf, buf_size, "%s by %s[%s]",
                    ssh_find_keyword_name(ssh_cm_edb_data_types, d->data_type),
                    ssh_find_keyword_name(ssh_cm_edb_key_types, d->key_type),
                    tmp)) == -1)
    return buf_size + 1;
  else
    return nbytes;
}
Example #2
0
int
ssh_cm_render_state(unsigned char *buf, int len, int precision, void *datum)
{
  SshCMSearchState state = *(unsigned int *)((void *)&datum);
  int i;
  const char *name;
  SshBufferStruct buffer;

  ssh_buffer_init(&buffer);
  ssh_buffer_append_str(&buffer, "\nsearch-state = \n{\n");
  if (state == 0)
    ssh_buffer_append_str(&buffer, "  nil\n");
  else
    {
      for (i = 0; i < 32; i++)
        {
          if (state & (1 << i))
            {
              name =
                ssh_find_keyword_name(ssh_cm_debug_state_strs, (1 << i));
              ssh_buffer_append_cstrs(&buffer, "  ", name, "\n", NULL);
            }
        }
    }
  ssh_buffer_append_str(&buffer, "}\n");
  return cm_debug_renderer_return(&buffer, buf, len);
}
const char *ssh_ikev2_transform_to_string(SshIkev2TransformType type,
					  SshIkev2TransformID value)
{
  const char *name, *unknown = NULL;

  switch (type)
    {
    case SSH_IKEV2_TRANSFORM_TYPE_ENCR:
      name = ssh_find_keyword_name(ssh_ikev2_encr_to_string_table, value);
      unknown = "unknown encryption";
      break;
    case SSH_IKEV2_TRANSFORM_TYPE_PRF:
      name = ssh_find_keyword_name(ssh_ikev2_prf_to_string_table, value);
      unknown = "unknown prf";
      break;
    case SSH_IKEV2_TRANSFORM_TYPE_INTEG:
      name = ssh_find_keyword_name(ssh_ikev2_integ_to_string_table, value);
      unknown = "unknown integrity";
      break;
    case SSH_IKEV2_TRANSFORM_TYPE_D_H:
      name = ssh_find_keyword_name(ssh_ikev2_dh_to_string_table, value);
      unknown = "unknown DH group";
      break;
    case SSH_IKEV2_TRANSFORM_TYPE_ESN:
      name = ssh_find_keyword_name(ssh_ikev2_esn_to_string_table, value);
      unknown = "unknown ESN value";
      break;
    default:
      name = "unknown type";
      break;
    }

  if (name == NULL)
    return unknown;
  return name;
}
Example #4
0
/* 
 * Inserts specified event into log file specified in context.
 * event parameter specifies the audited event. Each element after event 
 * must start with a SshAuditformat type followed by arguments of the 
 * appropriate type, and the list must end with SSH_AUDIT_ARGUMENT_END.
 */
void ssh_audit_event(SshAuditContext context, SshAuditEvent event, ...)
{
  size_t bytes;
  va_list ap;
  SshBuffer *audit_info, *formated_str;
  char *audit_time;

  if (context == NULL) return;

  if ((event < 0) || (event > SSH_AUDIT_MAX_VALUE)) return;
  /* Check if given event is allowed */
  if (!context->ssh_audit_event_allowed[(int)event]) return;

  /* Initialize a buffer for output string */
  audit_info = ssh_buffer_allocate();

  /* Start constructing string which will be inserted into audit log.*/
  /* Start with inserting the name of the event.*/
  /* then date and time */
  audit_time = ssh_time_string(ssh_time());
  ssh_buffer_append_cstrs(audit_info, 
                          ssh_find_keyword_name(ssh_audit_event_title, 
                                                (int)event),
                          ": ", audit_time, ": ", 
                          NULL); 
  ssh_xfree(audit_time);

  /* Handle the variable list*/
  va_start(ap, event);
  formated_str = ssh_format_audit_string(ap);
  va_end(ap);

  /* Insert given parameters into string*/
  ssh_buffer_append(audit_info, 
                    ssh_buffer_ptr(formated_str),
                    ssh_buffer_len(formated_str));
  ssh_buffer_append(audit_info, (unsigned char *) "\0", 1);

  /* Output the log message*/
  ssh_send_log_message(context, ssh_buffer_ptr(audit_info));

  ssh_buffer_free(formated_str);
  ssh_buffer_free(audit_info);
}
void
ssh_l2tp_session_message_handler(SshFSMThread thread, SshUInt32 exception_arg)
{
  SshL2tpSession session = ssh_fsm_get_tdata(thread);
  SshL2tpThreadException exception = (SshL2tpThreadException) exception_arg;
  SshFSMStepCB next_state;

  SSH_DEBUG(SSH_D_NICETOKNOW,
            ("Received exception `%s' (%d)",
             ssh_find_keyword_name(ssh_l2tp_thread_exceptions,
                                   exception), exception));

  /* Resolve our next state. Assigned first to shut up some compilers. */
  next_state = NULL_FNPTR;
  switch (exception)
    {
    case SSH_L2TP_THREAD_EXCEPTION_SHUTDOWN:
      next_state = ssh_l2tp_fsm_session_closed;
      break;

    case SSH_L2TP_THREAD_EXCEPTION_DESTROY:
      next_state = ssh_l2tp_fsm_session_destroyed;
      break;

    case SSH_L2TP_THREAD_EXCEPTION_CLEAN_UP:
      next_state = ssh_l2tp_fsm_session_clean_up;
      break;
    }

  ssh_fsm_set_next(thread, next_state);

  /* Cancel all pending operations. */
  if (session->operation_handle)
    {
      ssh_operation_abort(session->operation_handle);
      session->operation_handle = NULL;
    }

  /* Mark us destroyed and continue from the next state. */
  session->destroyed = 1;
  ssh_fsm_continue(thread);
}
Example #6
0
/*                                                              shade{0.9}
 * ike_isakmp_sa_reply
 * Process policy managers reply to isakmp sa query.            shade{1.0}
 */
void ike_isakmp_sa_reply(int proposal_index, int number_of_protocols,
                         int *transforms_indexes, void *context)
{
    SshIkeNegotiation negotiation = (SshIkeNegotiation) context;
    SshIkeSA isakmp_sa = negotiation->sa;
    SshIkePayloadSA pl;
    struct SshIkeAttributesRec attrs;

    SSH_DEBUG(5, ("Start"));

    if (ike_reply_check_deleted(negotiation))
    {
        ssh_free(transforms_indexes);
        return;
    }

    if (proposal_index == -1 || number_of_protocols != 1)
    {
        negotiation->ike_ed->selected_proposal = 0;
        negotiation->ike_ed->selected_transform = -1;
        ssh_free(transforms_indexes);

        ike_reply_done(negotiation);
        return;
    }

    pl = &(negotiation->ike_ed->sa_i->pl.sa);
    ssh_ike_clear_isakmp_attrs(&attrs);
    if (!ssh_ike_read_isakmp_attrs(negotiation,
                                   &(pl->proposals[proposal_index].
                                     protocols[0].
                                     transforms[transforms_indexes[0]]),
                                   &attrs))
    {
        SSH_IKE_DEBUG(3, negotiation,
                      ("Isakmp SA: Internal policy manager error, "
                       "policy manager selected proposal, "
                       "that contains unsupported values"));
        negotiation->ike_ed->selected_proposal = 0;
        negotiation->ike_ed->selected_transform = -1;
        ssh_free(transforms_indexes);

        ike_reply_return_error(negotiation,
                               SSH_IKE_NOTIFY_MESSAGE_ATTRIBUTES_NOT_SUPPORTED);
        return;
    }

    /* Check for group parameters */
    if (attrs.group_parameters)
    {
        struct SshIkeGrpAttributesRec grp_attrs;

        /* Make sure there isn't any pre defined group descriptor given with
           group */
        if (attrs.group_desc != NULL)
        {
            SSH_IKE_DEBUG(3, negotiation,
                          ("Isakmp SA: Internal policy manager error, "
                           "policy manager selected proposal, "
                           "that contains both group descriptor and "
                           "group parameters"));
            negotiation->ike_ed->selected_proposal = 0;
            negotiation->ike_ed->selected_transform = -1;
            ssh_free(transforms_indexes);

            ike_reply_return_error(negotiation,
                                   SSH_IKE_NOTIFY_MESSAGE_ATTRIBUTES_NOT_SUPPORTED);
            return;
        }

        ssh_ike_clear_grp_attrs(&grp_attrs);

        if (!ssh_ike_read_grp_attrs(negotiation,
                                    &(pl->proposals[proposal_index].
                                      protocols[0].
                                      transforms[transforms_indexes[0]]),
                                    &grp_attrs))
        {
            SSH_IKE_DEBUG(3, negotiation,
                          ("Isakmp SA: Internal policy manager error, "
                           "policy manager selected proposal, "
                           "that contains unsupported group values"));
            negotiation->ike_ed->selected_proposal = 0;
            negotiation->ike_ed->selected_transform = -1;
            ssh_free(transforms_indexes);

            ike_reply_return_error(negotiation,
                                   SSH_IKE_NOTIFY_MESSAGE_ATTRIBUTES_NOT_SUPPORTED);
            return;
        }
        /* Insert it as group -1 */
        ike_remove_group(negotiation, -1);
        grp_attrs.group_descriptor = -1;
        attrs.group_desc = ike_add_group(negotiation, &grp_attrs);
        ssh_ike_free_grp_attrs(&grp_attrs);
    }

    /* We know that we only have one protocol */
    negotiation->ike_ed->attributes = attrs;
    negotiation->ike_ed->group = attrs.group_desc;

    if (attrs.encryption_algorithm == SSH_IKE_VALUES_ENCR_ALG_CAST_CBC &&
            attrs.key_length != 0 &&
            attrs.key_length <= 80)
        isakmp_sa->encryption_algorithm_name = ssh_custr("cast128-12-cbc");
    else
    {
        isakmp_sa->encryption_algorithm_name =
            ssh_custr(ssh_find_keyword_name(ssh_ike_encryption_algorithms,
                                            attrs.encryption_algorithm));
        if (isakmp_sa->encryption_algorithm_name == NULL)
            isakmp_sa->encryption_algorithm_name = ssh_custr("unknown");
    }

    isakmp_sa->hash_algorithm_name =
        ssh_custr(ssh_find_keyword_name(ssh_ike_hash_algorithms,
                                        attrs.hash_algorithm));
    if (isakmp_sa->hash_algorithm_name == NULL)
        isakmp_sa->hash_algorithm_name = ssh_custr("unknown");

    if (attrs.prf_algorithm == 0)
        isakmp_sa->prf_algorithm_name =
            ssh_custr(ssh_find_keyword_name(ssh_ike_hmac_prf_algorithms,
                                            attrs.hash_algorithm));
    else
        isakmp_sa->prf_algorithm_name =
            ssh_custr(ssh_find_keyword_name(ssh_ike_prf_algorithms,
                                            attrs.prf_algorithm));
    if (isakmp_sa->prf_algorithm_name == NULL)
        isakmp_sa->prf_algorithm_name = ssh_custr("unknown");

    isakmp_sa->kbyte_limit = attrs.life_duration_kb;

    negotiation->ike_pm_info->auth_method = attrs.auth_method;
    switch (attrs.auth_method)
    {
    case SSH_IKE_VALUES_AUTH_METH_PRE_SHARED_KEY:
#ifdef SSHDIST_IKE_XAUTH
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_I_PRE_SHARED:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_R_PRE_SHARED:
#endif /* SSHDIST_IKE_XAUTH */
        negotiation->ed->auth_method_type = SSH_IKE_AUTH_METHOD_PRE_SHARED_KEY;
        break;
    case SSH_IKE_VALUES_AUTH_METH_DSS_SIGNATURES:
    case SSH_IKE_VALUES_AUTH_METH_RSA_SIGNATURES:
#ifdef SSHDIST_CRYPT_ECP
    case SSH_IKE_VALUES_AUTH_METH_ECP_DSA_256:
    case SSH_IKE_VALUES_AUTH_METH_ECP_DSA_384:
    case SSH_IKE_VALUES_AUTH_METH_ECP_DSA_521:
#endif /* SSHDIST_CRYPT_ECP */
#ifdef SSHDIST_IKE_XAUTH
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_I_DSS_SIGNATURES:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_R_DSS_SIGNATURES:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_I_RSA_SIGNATURES:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_R_RSA_SIGNATURES:
#endif /* SSHDIST_IKE_XAUTH */
#ifdef SSHDIST_IKE_CERT_AUTH
        negotiation->ed->auth_method_type = SSH_IKE_AUTH_METHOD_SIGNATURES;
#else /* SSHDIST_IKE_CERT_AUTH */
        goto not_implemented;
#endif /* SSHDIST_IKE_CERT_AUTH */
        break;

    case SSH_IKE_VALUES_AUTH_METH_RSA_ENCRYPTION:
    case SSH_IKE_VALUES_AUTH_METH_RSA_ENCRYPTION_REVISED:
#ifdef SSHDIST_IKE_XAUTH
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_I_RSA_ENCRYPTION:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_R_RSA_ENCRYPTION:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_I_RSA_ENCRYPTION_REVISED:
    case SSH_IKE_VALUES_AUTH_METH_XAUTH_R_RSA_ENCRYPTION_REVISED:
#endif /* SSHDIST_IKE_XAUTH */
#ifdef SSHDIST_IKE_CERT_AUTH
        negotiation->ed->auth_method_type =
            SSH_IKE_AUTH_METHOD_PUBLIC_KEY_ENCRYPTION;
#else /* SSHDIST_IKE_CERT_AUTH */
        goto not_implemented;
#endif /* SSHDIST_IKE_CERT_AUTH */
        break;
#ifdef REMOVED_BY_DOI_DRAFT_07
    case SSH_IKE_VALUES_AUTH_METH_GSSAPI:
        goto not_implemented;
        break;
#endif
    }
    negotiation->ike_pm_info->auth_method_type =
        negotiation->ed->auth_method_type;

    negotiation->ike_ed->selected_proposal = proposal_index;
    negotiation->ike_ed->selected_transform = transforms_indexes[0];

    ssh_free(transforms_indexes);
    ike_reply_done(negotiation);

    return;

#ifdef SSHDIST_IKE_CERT_AUTH
    /* NOTREACHED */
#else /* SSHDIST_IKE_CERT_AUTH */
not_implemented:
    SSH_IKE_DEBUG(3, negotiation,
                  ("Other end selected locally unsupported "
                   "authentication method %d",
                   attrs.auth_method));
    negotiation->ike_ed->selected_proposal = 0;
    negotiation->ike_ed->selected_transform = -1;
    ssh_free(transforms_indexes);
    ike_reply_done(negotiation);

    return;
#endif /* SSHDIST_IKE_CERT_AUTH */
}
/* 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;
}
void
ikev2_fb_phase_qm_notification(SshIkePMPhaseQm pm_info,
			       SshIkeProtocolIdentifiers proto,
			       unsigned char *spi,
			       size_t spi_size,
			       SshIkeNotifyMessageType type,
			       unsigned char *data,
			       size_t data_size)
{
  SshIkev2FbNegotiation neg;
  char buffer[64];

  neg = SSH_IKEV2_FB_QM_GET_P1_NEGOTIATION(pm_info);
  if (neg == NULL)
    return;

  SSH_DEBUG(SSH_D_LOWOK, ("QM notification call entered, IKE SA %p (neg %p)",
			  pm_info->phase_i->policy_manager_data, neg));

  switch (type)
    {
    case SSH_IKE_NOTIFY_MESSAGE_RESPONDER_LIFETIME:
      {
	int i;
	SshUInt32 *life;
	SshUInt32 kb, sec;

	life = NULL;
	kb = 0;
	sec = 0;

	i = 0;
	while (i + 4 <= data_size)
	  {
	    SshUInt16 lifetype;
	    SshUInt32 value;

	    if (!ssh_ike_decode_data_attribute_int(data + i,
						   data_size - i,
						   &lifetype, &value, 0L))
	      {
		SSH_DEBUG(3, ("ssh_ike_decode_data_attribute_int returned "
			      "error"));
		return;
	      }

	    switch (lifetype)
	      {
	      case IPSEC_CLASSES_SA_LIFE_TYPE: /* Life type selector */
		if (life != NULL)
		  {
		    SSH_DEBUG(3, ("Two life types, without duration"));
		    return;
		  }
		if (value == IPSEC_VALUES_LIFE_TYPE_SECONDS)
		  {
		    life = &sec;
		  }
		else if (value == IPSEC_VALUES_LIFE_TYPE_KILOBYTES)
		  {
		    life = &kb;
		  }
		else
		  {
		    SSH_DEBUG(3, ("Invalid life type"));
		    return;
		  }
		break;

	      case IPSEC_CLASSES_SA_LIFE_DURATION: /* Life type value */
		if (life == NULL)
		  {
		    SSH_DEBUG(3, ("Life duration without type"));
		    return;
		  }
		if (*life != 0)
		  {
		    SSH_DEBUG(3, ("Same life duration value given twice"));
		    return;
		  }
		*life = value;
		life = NULL;
	      }
	    i += ssh_ike_decode_data_attribute_size(data + i, 0L);
	  }

	if (sec != 0)
	  {
	    if (neg->ed->ipsec_ed->sa_life_seconds == 0 ||
		neg->ed->ipsec_ed->sa_life_seconds > sec)
	      neg->ed->ipsec_ed->sa_life_seconds = sec;
	  }
	if (kb != 0)
	  {
	    if (neg->ed->ipsec_ed->sa_life_kbytes == 0 ||
		neg->ed->ipsec_ed->sa_life_kbytes > kb)
	      neg->ed->ipsec_ed->sa_life_kbytes = kb;
	  }

	SSH_DEBUG(SSH_D_NICETOKNOW,
		  ("Received responder lifetime notification: "
		   "life_secs=%lu, life_kbytes=%lu",
		   (unsigned long) sec, (unsigned long) kb));
      }

    default:
      ssh_log_event(SSH_LOGFACILITY_AUTH, SSH_LOG_INFORMATIONAL,
		    "QM notification `%s' (%d) (size %d bytes) "
		    "from %s%@ for protocol %s spi[0...%d]=%s",
		    ssh_find_keyword_name(ssh_ike_status_keywords, type),
		    type,
		    data_size,
		    pm_info->remote_ip,
		    ikev2_fb_ike_port_render, pm_info->remote_port,
		    ssh_find_keyword_name(ikev2_fb_ike_protocol_identifiers,
					  proto),
		    spi_size - 1,
		    ikev2_fb_util_data_to_hex(buffer, sizeof(buffer),
					      spi, spi_size));
    }
}