Porting to new Toolkit API (key agreement, plus other).
[crypto.git] / apps / irssi / src / silc / core / silc-channels.c
index 14f251ab58642eaa26f0216b23369677c0899f4c..a0e1dcd6146732d04cd0bfadec187fabf4d369ee 100644 (file)
@@ -442,9 +442,9 @@ static void command_away(const char *data, SILC_SERVER_REC *server,
 }
 
 typedef struct {
 }
 
 typedef struct {
-  int type;                    /* 1 = msg, 2 = channel */
-  bool responder;
   SILC_SERVER_REC *server;
   SILC_SERVER_REC *server;
+  int type;                    /* 1 = msg, 2 = channel */
+  SilcBool responder;
 } *KeyInternal;
 
 /* Key agreement callback that is called after the key agreement protocol
 } *KeyInternal;
 
 /* Key agreement callback that is called after the key agreement protocol
@@ -459,7 +459,7 @@ static void keyagr_completion(SilcClient client,
                              SilcClientConnection conn,
                              SilcClientEntry client_entry,
                              SilcKeyAgreementStatus status,
                              SilcClientConnection conn,
                              SilcClientEntry client_entry,
                              SilcKeyAgreementStatus status,
-                             SilcSKEKeyMaterial *key,
+                             SilcSKEKeyMaterial key,
                              void *context)
 {
   KeyInternal i = (KeyInternal)context;
                              void *context)
 {
   KeyInternal i = (KeyInternal)context;
@@ -473,7 +473,7 @@ static void keyagr_completion(SilcClient client,
       /* Set the private key for this client */
       silc_client_del_private_message_key(client, conn, client_entry);
       silc_client_add_private_message_key_ske(client, conn, client_entry,
       /* Set the private key for this client */
       silc_client_del_private_message_key(client, conn, client_entry);
       silc_client_add_private_message_key_ske(client, conn, client_entry,
-                                             NULL, NULL, key, i->responder);
+                                             NULL, NULL, key);
       printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                         SILCTXT_KEY_AGREEMENT_PRIVMSG,
                         client_entry->nickname);
       printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                         SILCTXT_KEY_AGREEMENT_PRIVMSG,
                         client_entry->nickname);
@@ -483,6 +483,7 @@ static void keyagr_completion(SilcClient client,
     break;
 
   case SILC_KEY_AGREEMENT_ERROR:
     break;
 
   case SILC_KEY_AGREEMENT_ERROR:
+  case SILC_KEY_AGREEMENT_NO_MEMORY:
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
     break;
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
     break;
@@ -521,7 +522,6 @@ static void keyagr_completion(SilcClient client,
     silc_free(i);
 }
 
     silc_free(i);
 }
 
-#if 0
 /* Local command KEY. This command is used to set and unset private
    keys for channels, set and unset private keys for private messages
    with remote clients and to send key agreement requests and
 /* Local command KEY. This command is used to set and unset private
    keys for channels, set and unset private keys for private messages
    with remote clients and to send key agreement requests and
@@ -542,8 +542,8 @@ typedef struct {
 
 static void silc_client_command_key_get_clients(SilcClient client,
                                                SilcClientConnection conn,
 
 static void silc_client_command_key_get_clients(SilcClient client,
                                                SilcClientConnection conn,
-                                               SilcClientEntry *clients,
-                                               SilcUInt32 clients_count,
+                                               SilcStatus status,
+                                               SilcDList clients,
                                                void *context)
 {
   KeyGetClients internal = (KeyGetClients)context;
                                                void *context)
 {
   KeyGetClients internal = (KeyGetClients)context;
@@ -569,11 +569,11 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
                        WI_ITEM_REC *item)
 {
   SilcClientConnection conn;
                        WI_ITEM_REC *item)
 {
   SilcClientConnection conn;
-  SilcClientEntry *entrys, client_entry = NULL;
-  SilcUInt32 entry_count;
+  SilcClientEntry client_entry = NULL;
+  SilcDList clients;
   SILC_CHANNEL_REC *chanrec = NULL;
   SilcChannelEntry channel_entry = NULL;
   SILC_CHANNEL_REC *chanrec = NULL;
   SilcChannelEntry channel_entry = NULL;
-  char *nickname = NULL, *tmp;
+  char nickname[128 + 1], *tmp;
   int command = 0, port = 0, type = 0;
   char *hostname = NULL;
   KeyInternal internal = NULL;
   int command = 0, port = 0, type = 0;
   char *hostname = NULL;
   KeyInternal internal = NULL;
@@ -581,6 +581,10 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   unsigned char **argv;
   SilcUInt32 *argv_lens, *argv_types;
   char *bindhost = NULL;
   unsigned char **argv;
   SilcUInt32 *argv_lens, *argv_types;
   char *bindhost = NULL;
+  SilcChannelEntry ch = NULL;
+  SilcDList ckeys;
+  SilcBool udp = FALSE;
+  int i;
 
   CMD_SILC_SERVER(server);
 
 
   CMD_SILC_SERVER(server);
 
@@ -608,19 +612,19 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
   if (type == 1) {
     if (argv[2][0] == '*') {
 
   if (type == 1) {
     if (argv[2][0] == '*') {
-      nickname = strdup("*");
+      strcpy(nickname, "*");
     } else {
       /* Parse the typed nickname. */
     } else {
       /* Parse the typed nickname. */
-      if (!silc_parse_userfqdn(argv[2], &nickname, NULL)) {
+      if (!silc_parse_userfqdn(argv[2], nickname, sizeof(nickname), NULL, 0)) {
        printformat_module("fe-common/silc", server, NULL,
                           MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
        return;
       }
 
       /* Find client entry */
        printformat_module("fe-common/silc", server, NULL,
                           MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
        return;
       }
 
       /* Find client entry */
-      entrys = silc_client_get_clients_local(silc_client, conn, nickname,
-                                            argv[2], &entry_count);
-      if (!entrys) {
+      clients = silc_client_get_clients_local(silc_client, conn, nickname,
+                                             argv[2]);
+      if (!clients) {
        KeyGetClients inter = silc_calloc(1, sizeof(*inter));
        inter->server = server;
        inter->data = strdup(data);
        KeyGetClients inter = silc_calloc(1, sizeof(*inter));
        inter->server = server;
        inter->data = strdup(data);
@@ -630,8 +634,9 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
                                silc_client_command_key_get_clients, inter);
        goto out;
       }
                                silc_client_command_key_get_clients, inter);
        goto out;
       }
-      client_entry = entrys[0];
-      silc_free(entrys);
+
+      client_entry = silc_dlist_get(clients);
+      silc_client_list_free(silc_client, conn, clients);
     }
   }
 
     }
   }
 
@@ -664,42 +669,17 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
     if (argc >= 5) {
       char *cipher = NULL, *hmac = NULL;
 
     if (argc >= 5) {
       char *cipher = NULL, *hmac = NULL;
 
+      if (argc >= 6)
+       cipher = argv[5];
+      if (argc >= 7)
+       hmac = argv[6];
+
       if (type == 1 && client_entry) {
        /* Set private message key */
       if (type == 1 && client_entry) {
        /* Set private message key */
-       bool responder = FALSE;
-
        silc_client_del_private_message_key(silc_client, conn, client_entry);
        silc_client_del_private_message_key(silc_client, conn, client_entry);
-
-       if (argc >= 6) {
-         if (!strcasecmp(argv[5], "-responder"))
-           responder = TRUE;
-         else
-           cipher = argv[5];
-       }
-       if (argc >= 7) {
-         if (!strcasecmp(argv[6], "-responder"))
-           responder = TRUE;
-         else
-           hmac = argv[6];
-       }
-       if (argc >= 8) {
-         if (!strcasecmp(argv[7], "-responder"))
-           responder = TRUE;
-       }
-
        silc_client_add_private_message_key(silc_client, conn, client_entry,
                                            cipher, hmac,
        silc_client_add_private_message_key(silc_client, conn, client_entry,
                                            cipher, hmac,
-                                           argv[4], argv_lens[4],
-                                           (argv[4][0] == '*' ?
-                                            TRUE : FALSE), responder);
-
-       /* Send the key to the remote client so that it starts using it
-          too. */
-       /* XXX for now we don't do this.  This feature is pretty stupid
-          and should perhaps be removed altogether from SILC.
-       silc_client_send_private_message_key(silc_client, conn,
-                                            client_entry, TRUE);
-       */
+                                           argv[4], argv_lens[4]);
       } else if (type == 2) {
        /* Set private channel key */
        if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
       } else if (type == 2) {
        /* Set private channel key */
        if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
@@ -709,11 +689,6 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
          goto out;
        }
 
          goto out;
        }
 
-       if (argc >= 6)
-         cipher = argv[5];
-       if (argc >= 7)
-         hmac = argv[6];
-
        if (!silc_client_add_channel_private_key(silc_client, conn,
                                                 channel_entry, NULL,
                                                 cipher, hmac,
        if (!silc_client_add_channel_private_key(silc_client, conn,
                                                 channel_entry, NULL,
                                                 cipher, hmac,
@@ -743,8 +718,6 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       silc_client_del_private_message_key(silc_client, conn, client_entry);
     } else if (type == 2) {
       /* Unset channel key(s) */
       silc_client_del_private_message_key(silc_client, conn, client_entry);
     } else if (type == 2) {
       /* Unset channel key(s) */
-      SilcChannelPrivateKey *keys;
-      SilcUInt32 keys_count;
       int number;
 
       if (argc == 4)
       int number;
 
       if (argc == 4)
@@ -753,26 +726,31 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
       if (argc > 4) {
        number = atoi(argv[4]);
 
       if (argc > 4) {
        number = atoi(argv[4]);
-       keys = silc_client_list_channel_private_keys(silc_client, conn,
-                                                    channel_entry,
-                                                    &keys_count);
-       if (!keys)
+       ckeys = silc_client_list_channel_private_keys(silc_client, conn,
+                                                     channel_entry);
+       if (!ckeys)
          goto out;
 
          goto out;
 
-       if (!number || number > keys_count) {
-         silc_client_free_channel_private_keys(keys, keys_count);
+       if (!number || number > silc_dlist_count(ckeys)) {
+         silc_dlist_uninit(ckeys);
          goto out;
        }
 
          goto out;
        }
 
+       for (i = 0; i < number; i++)
+         ch = silc_dlist_get(ckeys);
+       if (!ch)
+         goto out;
+
        silc_client_del_channel_private_key(silc_client, conn, channel_entry,
        silc_client_del_channel_private_key(silc_client, conn, channel_entry,
-                                           keys[number - 1]);
-       silc_client_free_channel_private_keys(keys, keys_count);
+                                           ch);
+       silc_dlist_uninit(ckeys);
       }
 
       goto out;
     }
   }
 
       }
 
       goto out;
     }
   }
 
+#if 0
   /* List command */
   if (!strcasecmp(argv[3], "list")) {
     command = 3;
   /* List command */
   if (!strcasecmp(argv[3], "list")) {
     command = 3;
@@ -852,20 +830,17 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       silc_client_free_private_message_keys(keys, keys_count);
 
     } else if (type == 2) {
       silc_client_free_private_message_keys(keys, keys_count);
 
     } else if (type == 2) {
-      SilcChannelPrivateKey *keys;
-      SilcUInt32 keys_count;
-      int k, i, len;
+      int k, len;
       char buf[1024];
 
       char buf[1024];
 
-      keys = silc_client_list_channel_private_keys(silc_client, conn,
-                                                  channel_entry,
-                                                  &keys_count);
+      ckeys = silc_client_list_channel_private_keys(silc_client, conn,
+                                                   channel_entry);
 
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                         SILCTXT_CH_PRIVATE_KEY_LIST,
                         channel_entry->channel_name);
 
 
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                         SILCTXT_CH_PRIVATE_KEY_LIST,
                         channel_entry->channel_name);
 
-      if (!keys)
+      if (!ckeys)
        goto out;
 
       for (k = 0; k < keys_count; k++) {
        goto out;
 
       for (k = 0; k < keys_count; k++) {
@@ -897,6 +872,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
     goto out;
   }
 
     goto out;
   }
+#endif /* 0 */
 
   /* Send command is used to send key agreement */
   if (!strcasecmp(argv[3], "agreement")) {
 
   /* Send command is used to send key agreement */
   if (!strcasecmp(argv[3], "agreement")) {
@@ -904,8 +880,14 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
     if (argc >= 5)
       hostname = argv[4];
 
     if (argc >= 5)
       hostname = argv[4];
-    if (argc >= 6)
-      port = atoi(argv[5]);
+    if (argc >= 6) {
+      if (!strcasecmp(argv[5], "UDP"))
+       udp = TRUE;
+      else
+       port = atoi(argv[5]);
+    }
+    if (argc >= 7)
+      udp = TRUE;
 
     internal = silc_calloc(1, sizeof(*internal));
     internal->type = type;
 
     internal = silc_calloc(1, sizeof(*internal));
     internal->type = type;
@@ -913,7 +895,6 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
     if (!hostname) {
       if (settings_get_bool("use_auto_addr")) {
 
     if (!hostname) {
       if (settings_get_bool("use_auto_addr")) {
-
         hostname = (char *)settings_get_str("auto_public_ip");
 
        /* If the hostname isn't set, treat this case as if auto_public_ip
         hostname = (char *)settings_get_str("auto_public_ip");
 
        /* If the hostname isn't set, treat this case as if auto_public_ip
@@ -940,8 +921,14 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
     if (argc >= 5)
       hostname = argv[4];
 
     if (argc >= 5)
       hostname = argv[4];
-    if (argc >= 6)
-      port = atoi(argv[5]);
+    if (argc >= 6) {
+      if (!strcasecmp(argv[5], "UDP"))
+       udp = TRUE;
+      else
+       port = atoi(argv[5]);
+    }
+    if (argc >= 7)
+      udp = TRUE;
 
     internal = silc_calloc(1, sizeof(*internal));
     internal->type = type;
 
     internal = silc_calloc(1, sizeof(*internal));
     internal->type = type;
@@ -953,39 +940,40 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
     command = 6;
     if (type == 2) {
       /* Unset channel key(s) */
     command = 6;
     if (type == 2) {
       /* Unset channel key(s) */
-      SilcChannelPrivateKey *keys;
-      SilcUInt32 keys_count;
       int number;
 
       int number;
 
-      keys = silc_client_list_channel_private_keys(silc_client, conn,
-                                                  channel_entry,
-                                                  &keys_count);
-      if (!keys)
+      ckeys = silc_client_list_channel_private_keys(silc_client, conn,
+                                                   channel_entry);
+      if (!ckeys)
        goto out;
 
       if (argc == 4) {
        chanrec->cur_key++;
        goto out;
 
       if (argc == 4) {
        chanrec->cur_key++;
-       if (chanrec->cur_key >= keys_count)
+       if (chanrec->cur_key >= silc_dlist_count(ckeys))
          chanrec->cur_key = 0;
       }
 
       if (argc > 4) {
        number = atoi(argv[4]);
          chanrec->cur_key = 0;
       }
 
       if (argc > 4) {
        number = atoi(argv[4]);
-       if (!number || number > keys_count)
+       if (!number || number > silc_dlist_count(ckeys))
          chanrec->cur_key = 0;
        else
          chanrec->cur_key = number - 1;
       }
 
          chanrec->cur_key = 0;
        else
          chanrec->cur_key = number - 1;
       }
 
+      for (i = 0; i < chanrec->cur_key; i++)
+       ch = silc_dlist_get(ckeys);
+      if (!ch)
+       goto out;
+
       /* Set the current channel private key */
       silc_client_current_channel_private_key(silc_client, conn,
       /* Set the current channel private key */
       silc_client_current_channel_private_key(silc_client, conn,
-                                             channel_entry,
-                                             keys[chanrec->cur_key]);
+                                             channel_entry, ch);
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                        SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
+                        SILCTXT_CH_PRIVATE_KEY_CHANGE, i + 1,
                         channel_entry->channel_name);
 
                         channel_entry->channel_name);
 
-      silc_client_free_channel_private_keys(keys, keys_count);
+      silc_dlist_uninit(ckeys);
       goto out;
     }
   }
       goto out;
     }
   }
@@ -998,13 +986,22 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   }
 
   if (command == 4 && client_entry) {
   }
 
   if (command == 4 && client_entry) {
+    SilcClientConnectionParams params;
+
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT, argv[2]);
     internal->responder = TRUE;
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT, argv[2]);
     internal->responder = TRUE;
+
+    memset(&params, 0, sizeof(params));
+    params.local_ip = hostname;
+    params.bind_ip = bindhost;
+    params.local_port = port;
+    params.udp = udp;
+    params.timeout_secs = settings_get_int("key_exchange_timeout_secs");
+
     silc_client_send_key_agreement(
     silc_client_send_key_agreement(
-                          silc_client, conn, client_entry, hostname,
-                          bindhost, port,
-                          settings_get_int("key_exchange_timeout_secs"),
+                          silc_client, conn, client_entry, &params,
+                          irssi_pubkey, irssi_privkey,
                           keyagr_completion, internal);
     if (!hostname)
       silc_free(internal);
                           keyagr_completion, internal);
     if (!hostname)
       silc_free(internal);
@@ -1012,19 +1009,43 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   }
 
   if (command == 5 && client_entry && hostname) {
   }
 
   if (command == 5 && client_entry && hostname) {
+    SilcClientConnectionParams params;
+
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
     internal->responder = FALSE;
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
     internal->responder = FALSE;
-    silc_client_perform_key_agreement(silc_client, conn, client_entry,
+
+    memset(&params, 0, sizeof(params));
+    if (udp) {
+      if (settings_get_bool("use_auto_addr")) {
+       params.local_ip = (char *)settings_get_str("auto_public_ip");
+       if ((params.local_ip) && (*params.local_ip == '\0')) {
+         params.local_ip = silc_net_localip();
+       } else {
+         params.bind_ip = (char *)settings_get_str("auto_bind_ip");
+         if ((params.bind_ip) && (*params.bind_ip == '\0'))
+           params.bind_ip = NULL;
+         params.local_port = settings_get_int("auto_bind_port");
+       }
+      }
+      if (!params.local_ip)
+       params.local_ip = silc_net_localip();
+    }
+    params.udp = udp;
+    params.timeout_secs = settings_get_int("key_exchange_timeout_secs");
+
+    silc_client_perform_key_agreement(silc_client, conn, client_entry, &params,
+                                     irssi_pubkey, irssi_privkey,
                                      hostname, port, keyagr_completion,
                                      internal);
     goto out;
   }
 
  out:
                                      hostname, port, keyagr_completion,
                                      internal);
     goto out;
   }
 
  out:
-  silc_free(nickname);
+  return;
 }
 
 }
 
+#if 0
 void silc_list_key(const char *pub_filename, int verbose)
 {
   SilcPublicKey public_key;
 void silc_list_key(const char *pub_filename, int verbose)
 {
   SilcPublicKey public_key;
@@ -1226,7 +1247,7 @@ void silc_channels_init(void)
   command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
   command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
   command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
   command_bind_silc("action", MODULE_NAME, (SIGNAL_FUNC) command_action);
   command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
   command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
-  //  command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
+  command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
   //  command_bind("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
 
   //command_set_options("listkeys", "clients servers");
   //  command_bind("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
 
   //command_set_options("listkeys", "clients servers");
@@ -1249,7 +1270,7 @@ void silc_channels_deinit(void)
   command_unbind("action", (SIGNAL_FUNC) command_action);
   command_unbind("notice", (SIGNAL_FUNC) command_notice);
   command_unbind("away", (SIGNAL_FUNC) command_away);
   command_unbind("action", (SIGNAL_FUNC) command_action);
   command_unbind("notice", (SIGNAL_FUNC) command_notice);
   command_unbind("away", (SIGNAL_FUNC) command_away);
-  //  command_unbind("key", (SIGNAL_FUNC) command_key);
+  command_unbind("key", (SIGNAL_FUNC) command_key);
   //  command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
 
   silc_nicklist_deinit();
   //  command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
 
   silc_nicklist_deinit();