Avoid NULL dereference when leaving a channel with a private key.
[silc.git] / lib / silcclient / client_channel.c
index 077399b213db7784ee66ef31876df75426d00f93..4120695d76af08286853fa5fc5bdf31f0f767220 100644 (file)
@@ -626,8 +626,14 @@ SilcBool silc_client_del_channel_private_keys(SilcClient client,
   }
 
   channel->internal.curr_key = NULL;
-  channel->cipher = silc_cipher_get_name(channel->internal.send_key);
-  channel->hmac = silc_hmac_get_name(channel->internal.hmac);
+  if (channel->internal.send_key)
+    channel->cipher = silc_cipher_get_name(channel->internal.send_key);
+  else
+    channel->cipher = NULL;
+  if (channel->internal.hmac)
+    channel->hmac = silc_hmac_get_name(channel->internal.hmac);
+  else
+    channel->hmac = NULL;
 
   silc_dlist_uninit(channel->internal.private_keys);
   channel->internal.private_keys = NULL;
@@ -887,12 +893,29 @@ void silc_client_empty_channel(SilcClient client,
 
 SilcBool silc_client_channel_save_public_keys(SilcChannelEntry channel,
                                              unsigned char *chpk_list,
-                                             SilcUInt32 chpk_list_len)
+                                             SilcUInt32 chpk_list_len,
+                                             SilcBool remove_all)
 {
   SilcArgumentDecodedList a, b;
   SilcDList chpks;
   SilcBool found;
 
+  if (remove_all) {
+    /* Remove all channel public keys */
+    if (!channel->channel_pubkeys)
+      return FALSE;
+
+    silc_dlist_start(channel->channel_pubkeys);
+    while ((b = silc_dlist_get(channel->channel_pubkeys)))
+      silc_dlist_del(channel->channel_pubkeys, b);
+
+    silc_dlist_uninit(channel->channel_pubkeys);
+    channel->channel_pubkeys = NULL;
+
+    return TRUE;
+  }
+
+  /* Parse channel public key list and add or remove public keys */
   chpks = silc_argument_list_parse_decoded(chpk_list, chpk_list_len,
                                           SILC_ARGUMENT_PUBLIC_KEY);
   if (!chpks)