Diff for /embedaddon/strongswan/src/libcharon/sa/ike_sa.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2020/06/03 09:46:45 version 1.1.1.2, 2021/03/17 00:20:09
Line 1 Line 1
 /*  /*
 * Copyright (C) 2006-2019 Tobias Brunner * Copyright (C) 2006-2020 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger   * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2009 Martin Willi   * Copyright (C) 2005-2009 Martin Willi
  * Copyright (C) 2005 Jan Hutter   * Copyright (C) 2005 Jan Hutter
Line 237  struct private_ike_sa_t { Line 237  struct private_ike_sa_t {
         uint32_t keepalive_interval;          uint32_t keepalive_interval;
   
         /**          /**
            * Time the NAT keep alive interval may be exceeded before triggering a DPD
            * instead of a NAT keep alive
            */
           uint32_t keepalive_dpd_margin;
   
           /**
          * The scheduled keep alive job, if any           * The scheduled keep alive job, if any
          */           */
         send_keepalive_job_t *keepalive_job;          send_keepalive_job_t *keepalive_job;
Line 655  METHOD(ike_sa_t, send_keepalive, void, Line 661  METHOD(ike_sa_t, send_keepalive, void,
   
         diff = now - last_out;          diff = now - last_out;
   
        if (diff >= this->keepalive_interval)        if (this->keepalive_dpd_margin &&
                 diff > (this->keepalive_interval + this->keepalive_dpd_margin))
         {          {
                   if (!this->task_manager->busy(this->task_manager))
                   {
                           DBG1(DBG_IKE, "sending DPD instead of keep alive %ds after last "
                                    "outbound message", diff);
                           this->task_manager->queue_dpd(this->task_manager);
                           this->task_manager->initiate(this->task_manager);
                   }
                   diff = 0;
           }
           else if (diff >= this->keepalive_interval)
           {
                 packet_t *packet;                  packet_t *packet;
                 chunk_t data;                  chunk_t data;
   
Line 669  METHOD(ike_sa_t, send_keepalive, void, Line 687  METHOD(ike_sa_t, send_keepalive, void,
                 packet->set_data(packet, data);                  packet->set_data(packet, data);
                 DBG1(DBG_IKE, "sending keep alive to %#H", this->other_host);                  DBG1(DBG_IKE, "sending keep alive to %#H", this->other_host);
                 charon->sender->send_no_marker(charon->sender, packet);                  charon->sender->send_no_marker(charon->sender, packet);
                   this->stats[STAT_OUTBOUND] = now;
                 diff = 0;                  diff = 0;
         }          }
         if (!this->keepalive_job)          if (!this->keepalive_job)
Line 934  METHOD(ike_sa_t, reset, void, Line 953  METHOD(ike_sa_t, reset, void,
         {          {
                 charon->ike_sa_manager->new_initiator_spi(charon->ike_sa_manager,                  charon->ike_sa_manager->new_initiator_spi(charon->ike_sa_manager,
                                                                                                   &this->public);                                                                                                    &this->public);
   
                   /* when starting from scratch, connect to the original peer again e.g.
                    * if we got redirected but weren't able to connect successfully */
                   if (this->redirected_from)
                   {
                           this->redirected_from->destroy(this->redirected_from);
                           this->redirected_from = NULL;
                           /* we can't restore the original value, if there was any */
                           DESTROY_IF(this->remote_host);
                           this->remote_host = NULL;
                   }
         }          }
         /* the responder ID is reset, as peer may choose another one */          /* the responder ID is reset, as peer may choose another one */
         if (this->ike_sa_id->is_initiator(this->ike_sa_id))          if (this->ike_sa_id->is_initiator(this->ike_sa_id))
Line 1084  METHOD(ike_sa_t, float_ports, void, Line 1114  METHOD(ike_sa_t, float_ports, void,
 }  }
   
 METHOD(ike_sa_t, update_hosts, void,  METHOD(ike_sa_t, update_hosts, void,
        private_ike_sa_t *this, host_t *me, host_t *other, bool force)        private_ike_sa_t *this, host_t *me, host_t *other, update_hosts_flag_t flags)
 {  {
        bool update = FALSE;        host_t *new_me = NULL, *new_other = NULL;
         bool silent = FALSE;
   
         if (me == NULL)          if (me == NULL)
         {          {
Line 1101  METHOD(ike_sa_t, update_hosts, void, Line 1132  METHOD(ike_sa_t, update_hosts, void,
         if (this->my_host->is_anyaddr(this->my_host) ||          if (this->my_host->is_anyaddr(this->my_host) ||
                 this->other_host->is_anyaddr(this->other_host))                  this->other_host->is_anyaddr(this->other_host))
         {          {
                set_my_host(this, me->clone(me));                new_me = me;
                set_other_host(this, other->clone(other));                new_other = other;
                update = TRUE;                silent = TRUE;
         }          }
         else          else
         {          {
                /* update our address in any case */                /* update our address only if forced */
                if (force && !me->equals(me, this->my_host))                if ((flags & UPDATE_HOSTS_FORCE_LOCAL) && !me->equals(me, this->my_host))
                 {                  {
                        charon->bus->ike_update(charon->bus, &this->public, TRUE, me);                        new_me = me;
                        set_my_host(this, me->clone(me)); 
                        update = TRUE; 
                 }                  }
   
                 if (!other->equals(other, this->other_host) &&                  if (!other->equals(other, this->other_host) &&
                        (force || has_condition(this, COND_NAT_THERE)))                        ((flags & UPDATE_HOSTS_FORCE_REMOTE) || has_condition(this, COND_NAT_THERE)))
                 {                  {
                         /* only update other's address if we are behind a static NAT,                          /* only update other's address if we are behind a static NAT,
                          * which we assume is the case if we are not initiator */                           * which we assume is the case if we are not initiator */
                        if (force ||                        if ((flags & UPDATE_HOSTS_FORCE_REMOTE) ||
                                 (!has_condition(this, COND_NAT_HERE) ||                                  (!has_condition(this, COND_NAT_HERE) ||
                                  !has_condition(this, COND_ORIGINAL_INITIATOR)))                                   !has_condition(this, COND_ORIGINAL_INITIATOR)))
                         {                          {
                                charon->bus->ike_update(charon->bus, &this->public, FALSE, other);                                new_other = other;
                                set_other_host(this, other->clone(other)); 
                                update = TRUE; 
                         }                          }
                 }                  }
         }          }
   
        /* update all associated CHILD_SAs, if required */        if (new_me || new_other || (flags & UPDATE_HOSTS_FORCE_CHILDREN))
        if (update) 
         {          {
                 enumerator_t *enumerator;                  enumerator_t *enumerator;
                 child_sa_t *child_sa;                  child_sa_t *child_sa;
                 linked_list_t *vips;                  linked_list_t *vips;
   
                   if ((new_me || new_other) && !silent)
                   {
                           charon->bus->ike_update(charon->bus, &this->public,
                                                                           new_me ?: this->my_host,
                                                                           new_other ?: this->other_host);
                   }
                   if (new_me)
                   {
                           set_my_host(this, new_me->clone(new_me));
                   }
                   if (new_other)
                   {
                           set_other_host(this, new_other->clone(new_other));
                   }
   
                 vips = linked_list_create_from_enumerator(                  vips = linked_list_create_from_enumerator(
                                                                         array_create_enumerator(this->my_vips));                                                                          array_create_enumerator(this->my_vips));
   
Line 2145  METHOD(ike_sa_t, reestablish, status_t, Line 2186  METHOD(ike_sa_t, reestablish, status_t,
                 return FAILED;                  return FAILED;
         }          }
   
        new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,        new = charon->ike_sa_manager->create_new(charon->ike_sa_manager,
                                                                                           this->version, TRUE);                                                                                         this->version, TRUE);
         if (!new)          if (!new)
         {          {
                 return FAILED;                  return FAILED;
Line 2229  static bool redirect_established(private_ike_sa_t *thi Line 2270  static bool redirect_established(private_ike_sa_t *thi
         host_t *other;          host_t *other;
         time_t redirect;          time_t redirect;
   
        new = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,        new = charon->ike_sa_manager->create_new(charon->ike_sa_manager,
                                                                                           this->version, TRUE);                                                                                         this->version, TRUE);
         if (!new)          if (!new)
         {          {
                 return FALSE;                  return FALSE;
Line 2287  static bool redirect_connecting(private_ike_sa_t *this Line 2328  static bool redirect_connecting(private_ike_sa_t *this
         reset(this, TRUE);          reset(this, TRUE);
         DESTROY_IF(this->redirected_from);          DESTROY_IF(this->redirected_from);
         this->redirected_from = this->other_host->clone(this->other_host);          this->redirected_from = this->other_host->clone(this->other_host);
         DESTROY_IF(this->remote_host);  
         /* this allows us to force the remote address while we still properly          /* this allows us to force the remote address while we still properly
          * resolve the local address */           * resolve the local address */
           DESTROY_IF(this->remote_host);
         this->remote_host = other;          this->remote_host = other;
         resolve_hosts(this);          resolve_hosts(this);
         return TRUE;          return TRUE;
Line 2396  METHOD(ike_sa_t, retransmit, status_t, Line 2437  METHOD(ike_sa_t, retransmit, status_t,
         {          {
                 return INVALID_STATE;                  return INVALID_STATE;
         }          }
        this->stats[STAT_OUTBOUND] = time_monotonic(NULL);        switch (this->task_manager->retransmit(this->task_manager, message_id))
        if (this->task_manager->retransmit(this->task_manager, message_id) != SUCCESS) 
         {          {
                /* send a proper signal to brief interested bus listeners */                case SUCCESS:
                switch (this->state)                        this->stats[STAT_OUTBOUND] = time_monotonic(NULL);
                         return SUCCESS;
                 case INVALID_STATE:
                         return INVALID_STATE;
                 default:
                         break;
         }
         /* send a proper signal to brief interested bus listeners */
         switch (this->state)
         {
                 case IKE_CONNECTING:
                 {                  {
                        case IKE_CONNECTING:                        /* retry IKE_SA_INIT/Main Mode if we have multiple keyingtries */
                         uint32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);
                         charon->bus->alert(charon->bus, ALERT_PEER_INIT_UNREACHABLE,
                                                            this->keyingtry);
                         this->keyingtry++;
                         if (tries == 0 || tries > this->keyingtry)
                         {                          {
                                /* retry IKE_SA_INIT/Main Mode if we have multiple keyingtries */                                DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)",
                                uint32_t tries = this->peer_cfg->get_keyingtries(this->peer_cfg);                                         this->keyingtry + 1, tries);
                                charon->bus->alert(charon->bus, ALERT_PEER_INIT_UNREACHABLE,                                reset(this, TRUE);
                                                                   this->keyingtry);                                resolve_hosts(this);
                                this->keyingtry++;                                return this->task_manager->initiate(this->task_manager);
                                if (tries == 0 || tries > this->keyingtry)                        }
                                {                        DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding");
                                        DBG1(DBG_IKE, "peer not responding, trying again (%d/%d)", 
                                                 this->keyingtry + 1, tries); 
                                        reset(this, TRUE); 
                                        resolve_hosts(this); 
                                        return this->task_manager->initiate(this->task_manager); 
                                } 
                                DBG1(DBG_IKE, "establishing IKE_SA failed, peer not responding"); 
   
                                if (this->version == IKEV1 && array_count(this->child_sas))                        if (this->version == IKEV1 && array_count(this->child_sas))
                                {                        {
                                        enumerator_t *enumerator;                                enumerator_t *enumerator;
                                        child_sa_t *child_sa;                                child_sa_t *child_sa;
   
                                        /* if reauthenticating an IKEv1 SA failed (assumed for an SA                                /* if reauthenticating an IKEv1 SA failed (assumed for an SA
                                         * in this state with CHILD_SAs), try again from scratch */                                 * in this state with CHILD_SAs), try again from scratch */
                                        DBG1(DBG_IKE, "reauthentication failed, trying to "                                DBG1(DBG_IKE, "reauthentication failed, trying to "
                                                 "reestablish IKE_SA");                                         "reestablish IKE_SA");
                                        reestablish(this);                                reestablish(this);
                                        /* trigger down events for the CHILD_SAs, as no down event                                /* trigger down events for the CHILD_SAs, as no down event
                                         * is triggered below for IKE SAs in this state */                                 * is triggered below for IKE SAs in this state */
                                        enumerator = array_create_enumerator(this->child_sas);                                enumerator = array_create_enumerator(this->child_sas);
                                        while (enumerator->enumerate(enumerator, &child_sa))                                while (enumerator->enumerate(enumerator, &child_sa))
                                 {
                                         if (child_sa->get_state(child_sa) != CHILD_REKEYED &&
                                                 child_sa->get_state(child_sa) != CHILD_DELETED)
                                         {                                          {
                                                if (child_sa->get_state(child_sa) != CHILD_REKEYED &&                                                charon->bus->child_updown(charon->bus, child_sa,
                                                        child_sa->get_state(child_sa) != CHILD_DELETED)                                                                                                  FALSE);
                                                { 
                                                        charon->bus->child_updown(charon->bus, child_sa, 
                                                                                                          FALSE); 
                                                } 
                                         }                                          }
                                         enumerator->destroy(enumerator);  
                                 }                                  }
                                break;                                enumerator->destroy(enumerator);
                         }                          }
                        case IKE_DELETING:                        break;
                                DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding"); 
                                if (has_condition(this, COND_REAUTHENTICATING) && 
                                        !lib->settings->get_bool(lib->settings, 
                                                                                "%s.make_before_break", FALSE, lib->ns)) 
                                { 
                                        DBG1(DBG_IKE, "delete during reauthentication failed, " 
                                                 "trying to reestablish IKE_SA anyway"); 
                                        reestablish(this); 
                                } 
                                break; 
                        case IKE_REKEYING: 
                                DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding"); 
                                /* FALL */ 
                        default: 
                                reestablish(this); 
                                break; 
                 }                  }
                if (this->state != IKE_CONNECTING &&                case IKE_DELETING:
                        this->state != IKE_REKEYED)                        DBG1(DBG_IKE, "proper IKE_SA delete failed, peer not responding");
                {                        if (has_condition(this, COND_REAUTHENTICATING) &&
                        charon->bus->ike_updown(charon->bus, &this->public, FALSE);                                !lib->settings->get_bool(lib->settings,
                }                                                                        "%s.make_before_break", FALSE, lib->ns))
                return DESTROY_ME;                        {
                                 DBG1(DBG_IKE, "delete during reauthentication failed, "
                                          "trying to reestablish IKE_SA anyway");
                                 reestablish(this);
                         }
                         break;
                 case IKE_REKEYING:
                         DBG1(DBG_IKE, "rekeying IKE_SA failed, peer not responding");
                         /* FALL */
                 default:
                         reestablish(this);
                         break;
         }          }
        return SUCCESS;        if (this->state != IKE_CONNECTING &&
                 this->state != IKE_REKEYED)
         {
                 charon->bus->ike_updown(charon->bus, &this->public, FALSE);
         }
         return DESTROY_ME;
 }  }
   
 METHOD(ike_sa_t, set_auth_lifetime, status_t,  METHOD(ike_sa_t, set_auth_lifetime, status_t,
Line 2678  METHOD(ike_sa_t, roam, status_t, Line 2724  METHOD(ike_sa_t, roam, status_t,
                         this->task_manager->queue_mobike(this->task_manager, FALSE, TRUE);                          this->task_manager->queue_mobike(this->task_manager, FALSE, TRUE);
                         return this->task_manager->initiate(this->task_manager);                          return this->task_manager->initiate(this->task_manager);
                 }                  }
                   if (lib->settings->get_bool(lib->settings,
                                                                   "%s.check_current_path", FALSE, lib->ns) &&
                           !this->task_manager->busy(this->task_manager))
                   {
                           DBG1(DBG_IKE, "checking if current path still works using DPD");
                           this->task_manager->queue_dpd(this->task_manager);
                           return this->task_manager->initiate(this->task_manager);
                   }
                 return SUCCESS;                  return SUCCESS;
         }          }
   
Line 2928  METHOD(ike_sa_t, inherit_post, void, Line 2982  METHOD(ike_sa_t, inherit_post, void,
                 time_t reauth, delete, now = time_monotonic(NULL);                  time_t reauth, delete, now = time_monotonic(NULL);
   
                 this->stats[STAT_REAUTH] = other->stats[STAT_REAUTH];                  this->stats[STAT_REAUTH] = other->stats[STAT_REAUTH];
                reauth = this->stats[STAT_REAUTH] - now;                reauth = max(0, this->stats[STAT_REAUTH] - now);
                 delete = reauth + this->peer_cfg->get_over_time(this->peer_cfg);                  delete = reauth + this->peer_cfg->get_over_time(this->peer_cfg);
                this->stats[STAT_DELETE] = this->stats[STAT_REAUTH] + delete;                this->stats[STAT_DELETE] = now + delete;
                 DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "                  DBG1(DBG_IKE, "rescheduling reauthentication in %ds after rekeying, "
                          "lifetime reduced to %ds", reauth, delete);                           "lifetime reduced to %ds", reauth, delete);
                 lib->scheduler->schedule_job(lib->scheduler,                  lib->scheduler->schedule_job(lib->scheduler,
Line 3171  ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool  Line 3225  ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool 
                 .unique_id = ref_get(&unique_id),                  .unique_id = ref_get(&unique_id),
                 .keepalive_interval = lib->settings->get_time(lib->settings,                  .keepalive_interval = lib->settings->get_time(lib->settings,
                                                                 "%s.keep_alive", KEEPALIVE_INTERVAL, lib->ns),                                                                  "%s.keep_alive", KEEPALIVE_INTERVAL, lib->ns),
                   .keepalive_dpd_margin = lib->settings->get_time(lib->settings,
                                                                   "%s.keep_alive_dpd_margin", 0, lib->ns),
                 .retry_initiate_interval = lib->settings->get_time(lib->settings,                  .retry_initiate_interval = lib->settings->get_time(lib->settings,
                                                                 "%s.retry_initiate_interval", 0, lib->ns),                                                                  "%s.retry_initiate_interval", 0, lib->ns),
                 .flush_auth_cfg = lib->settings->get_bool(lib->settings,                  .flush_auth_cfg = lib->settings->get_bool(lib->settings,

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>