Fix reference counting for key exchange handling.
authorKp <kp@valhallalegends.com>
Sat, 28 Jun 2008 05:28:25 +0000 (00:28 -0500)
committerKp <kp@valhallalegends.com>
Sun, 9 Nov 2008 07:06:38 +0000 (02:06 -0500)
When a key exchange times out, the SKE can be freed before the user
responds.  Switch the SKE callbacks to obtain their own reference to the
object to prevent this.

lib/silcske/silcske.c
lib/silcske/silcske_i.h

index bac8a5c4fac9b8feb642da88c272092fa4a1ccb3..00d393229239f3a2bba9520c8c4e1bfcd6f153d1 100644 (file)
@@ -957,7 +957,7 @@ static SilcBool silc_ske_packet_send(SilcSKE ske,
 static void silc_ske_completion(SilcSKE ske)
 {
   /* Call the completion callback */
-  if (!ske->freed && !ske->aborted && ske->callbacks->completed) {
+  if (!ske->aborted && ske->callbacks->completed) {
     if (ske->status != SILC_SKE_STATUS_OK)
       ske->callbacks->completed(ske, ske->status, NULL, NULL, NULL,
                                ske->callbacks->context);
@@ -973,8 +973,6 @@ static void silc_ske_finished(SilcFSM fsm, void *fsm_context,
                              void *destructor_context)
 {
   SilcSKE ske = fsm_context;
-  ske->running = FALSE;
-  if (ske->freed)
     silc_ske_free(ske);
 }
 
@@ -1036,13 +1034,10 @@ SilcSKE silc_ske_alloc(SilcRng rng, SilcSchedule schedule,
 
 void silc_ske_free(SilcSKE ske)
 {
-  SILC_LOG_DEBUG(("Freeing Key Exchange object"));
-
   if (!ske)
     return;
 
-  if (ske->running) {
-    ske->freed = TRUE;
+  SILC_LOG_DEBUG(("Freeing Key Exchange object %p: aborted=%u refcount=%hu", ske, ske->aborted, ske->refcnt));
 
     if (ske->aborted) {
       /* If already aborted, destroy the session immediately */
@@ -1054,8 +1049,6 @@ void silc_ske_free(SilcSKE ske)
        silc_fsm_next(&ske->fsm, silc_ske_st_initiator_failure);
       silc_fsm_continue_sync(&ske->fsm);
     }
-    return;
-  }
 
   ske->refcnt--;
   if (ske->refcnt > 0)
@@ -1102,7 +1095,7 @@ void silc_ske_free(SilcSKE ske)
   silc_free(ske->hash);
   silc_free(ske->callbacks);
 
-  memset(ske, 'F', sizeof(*ske));
+  memset(ske, 0xdd, sizeof(*ske));
   silc_free(ske);
 }
 
@@ -1805,7 +1798,7 @@ SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
                                      SilcSKEParams params,
                                      SilcSKEStartPayload start_payload)
 {
-  SILC_LOG_DEBUG(("Start SKE as initiator"));
+  SILC_LOG_DEBUG(("Start SKE %p as initiator; stream=%p; params=%p; start_payload=%p", ske, stream, params, start_payload));
 
   if (!ske || !stream || !params || !params->version)
     return NULL;
@@ -1831,7 +1824,7 @@ SilcAsyncOperation silc_ske_initiator(SilcSKE ske,
   ske->timeout = params->timeout_secs ? params->timeout_secs : 30;
   ske->start_payload = start_payload;
   ske->version = params->version;
-  ske->running = TRUE;
+  ++ ske->refcnt;
 
   /* Link to packet stream to get key exchange packets */
   ske->stream = stream;
@@ -2418,7 +2411,7 @@ SilcAsyncOperation silc_ske_responder(SilcSKE ske,
   ske->version = params->version;
   if (!ske->version)
     return NULL;
-  ske->running = TRUE;
+  ++ ske->refcnt;
 
   /* Link to packet stream to get key exchange packets */
   ske->stream = stream;
@@ -2676,8 +2669,8 @@ silc_ske_rekey_initiator(SilcSKE ske,
 
   ske->rekey = rekey;
   ske->responder = FALSE;
-  ske->running = TRUE;
   ske->rekeying = TRUE;
+  ++ ske->refcnt;
 
   /* Link to packet stream to get key exchange packets */
   ske->stream = stream;
@@ -2953,9 +2946,9 @@ silc_ske_rekey_responder(SilcSKE ske,
 
   ske->rekey = rekey;
   ske->responder = TRUE;
-  ske->running = TRUE;
   ske->rekeying = TRUE;
   ske->packet = packet;
+  ++ ske->refcnt;
 
   /* Link to packet stream to get key exchange packets */
   ske->stream = stream;
index 051324550b66727f0f413281fae1b8466df22b40..e716f58d44df22dcfe66bc82398160f1112a7ae9 100644 (file)
@@ -91,9 +91,7 @@ struct SilcSKEStruct {
   SilcUInt16 refcnt;                 /* Reference counter */
 
   unsigned int aborted    : 1;        /* Set when SKE aborted */
-  unsigned int freed      : 1;       /* Set when freed during session */
   unsigned int responder  : 1;       /* Set when we are responder side */
-  unsigned int running    : 1;       /* Set when SKE is running */
   unsigned int rekeying   : 1;       /* Set when rekeying */
 };