Implemented public key support to WATCH command.
authorPekka Riikonen <priikone@silcnet.org>
Mon, 23 Feb 2004 21:14:37 +0000 (21:14 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Mon, 23 Feb 2004 21:14:37 +0000 (21:14 +0000)
apps/irssi/docs/help/in/watch.in
apps/irssi/src/silc/core/silc-servers.c
lib/silcclient/client_notify.c
lib/silcclient/command.c

index 962b356453b0990d174df30d2e2e087b95395543..6ee12c3803cb3071b2d7119ad0d78ae710c2b00e 100644 (file)
@@ -6,6 +6,11 @@ When the watched nickname appears in the network, leaves the network
 or its user mode is changed you will be notified for this change.  This
 same command can be used also to remove nicknames from being watched.
 
+This command may also be used to watch users by their public keys.
+Since nicknames are not unique in SILC users may frequently change their
+nickname.  By watching them by public key you will be able to keep
+track of your friends regardless of what nickname they use.
+
 Note that some users may have a user mode set that rejects you from
 receiving notifications about them.  Also note that since nicknames are
 not unique it is possible that same nickname matches several users in
@@ -16,5 +21,7 @@ Examples:
 
     /WATCH -add foobar
     /WATCH -del foobar
+    /WATCH -pubkey +/path/to/add/public_key.pub
+    /WATCH -pubkey -/path/to/del/public_key.pub
 
 See also: WHOIS
index 9d5d661b877278f1507f89524656fb9aa9c2f760..d9fdd00495459e7ec0a7062e906fc0eece28feba 100644 (file)
@@ -442,7 +442,7 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: FILE */
 /* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder] [-auth [<pubkeyfile> <privkeyfile> [<privkey passphrase>]]]*/
 /* SYNTAX: DETACH */
-/* SYNTAX: WATCH [<-add | -del> <nickname>] */
+/* SYNTAX: WATCH [<-add | -del> <nickname>] [-pubkey +|-<pubkeyfile>] */
 /* SYNTAX: STATS */
 /* SYNTAX: ATTR [<-del> <option> [{ <value>}]] */
 /* SYNTAX: SMSG [<-channel>] <target> <message> */
index 0dbde2f9062cd399a29315af5bc21ca878ee91b3..3f92685326e0561003f087e2ab5e793530501b51 100644 (file)
@@ -1356,6 +1356,9 @@ void silc_client_notify_by_server(SilcClient client,
        */
       SilcNotifyType notify = 0;
       bool del_client = FALSE;
+      unsigned char *pk;
+      SilcUInt32 pk_len;
+      SilcPublicKey public_key = NULL;
 
       SILC_LOG_DEBUG(("Notify: WATCH"));
 
@@ -1407,9 +1410,19 @@ void silc_client_notify_by_server(SilcClient client,
        silc_free(tmp_nick);
       }
 
+      /* Get public key, if present */
+      pk = silc_argument_get_arg_type(args, 5, &pk_len);
+      if (pk && !client_entry->public_key) {
+        if (silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key)) {
+         client_entry->public_key = public_key;
+         public_key = NULL;
+       }
+      }
+
       /* Notify application. */
       client->internal->ops->notify(client, conn, type, client_entry,
-                                   tmp, mode, notify);
+                                   tmp, mode, notify,
+                                   client_entry->public_key);
 
       client_entry->mode = mode;
 
@@ -1433,6 +1446,8 @@ void silc_client_notify_by_server(SilcClient client,
                               silc_client_notify_del_client_cb, res,
                               1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
       }
+
+      silc_pkcs_public_key_free(public_key);
     }
     break;
 
index 8130b9d38533164b03d054b6a7fdc17616b69cb3..116ccf50ece274273bbc006491e3c31bc2b4b395 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -361,14 +361,14 @@ SILC_CLIENT_CMD_FUNC(whois)
     obj.data = silc_pkcs_public_key_encode(pk, &obj.data_len);
 
     attrs = silc_attribute_payload_encode(attrs,
-                                          SILC_ATTRIBUTE_USER_PUBLIC_KEY, 
+                                          SILC_ATTRIBUTE_USER_PUBLIC_KEY,
                                           SILC_ATTRIBUTE_FLAG_VALID,
                                           &obj, sizeof(obj));
   }
 
   buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
                                           ++conn->cmd_ident, 3,
-                                          1, nick ? cmd->argv[1] : NULL, 
+                                          1, nick ? cmd->argv[1] : NULL,
                                           nick ? cmd->argv_lens[1] : 0,
                                           2, tmp ? tmp : NULL, tmp ? 4 : 0,
                                           3, attrs ? attrs->data : NULL,
@@ -840,11 +840,11 @@ SILC_CLIENT_CMD_FUNC(quit)
   if (cmd->argc > 1)
     buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, cmd->argc - 1,
                                         &cmd->argv[1], &cmd->argv_lens[1],
-                                        &cmd->argv_types[1], 
+                                        &cmd->argv_types[1],
                                         ++cmd->conn->cmd_ident);
   else
     buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, 0,
-                                        NULL, NULL, NULL, 
+                                        NULL, NULL, NULL,
                                         ++cmd->conn->cmd_ident);
   silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND,
                          NULL, 0, NULL, NULL,
@@ -1105,7 +1105,7 @@ SILC_CLIENT_CMD_FUNC(ping)
   idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
 
   /* Send the command */
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_PING,
                                          ++conn->cmd_ident, 1,
                                          1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
@@ -1301,12 +1301,12 @@ SILC_CLIENT_CMD_FUNC(motd)
 
   /* Send TOPIC command to the server */
   if (cmd->argc == 1)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD,
                                            ++conn->cmd_ident, 1,
                                            1, conn->remote_host,
                                            strlen(conn->remote_host));
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD,
                                            ++conn->cmd_ident, 1,
                                            1, cmd->argv[1],
                                            cmd->argv_lens[1]);
@@ -1941,7 +1941,7 @@ SILC_CLIENT_CMD_FUNC(cumode)
 
   /* Send the command packet. We support sending only one mode at once
      that requires an argument. */
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE, 
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE,
                                          ++conn->cmd_ident,
                                          auth ? 4 : 3,
                                          1, chidp->data, chidp->len,
@@ -2037,12 +2037,12 @@ SILC_CLIENT_CMD_FUNC(kick)
   idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
   idp2 = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
   if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK,
                                            ++conn->cmd_ident, 2,
                                            1, idp->data, idp->len,
                                            2, idp2->data, idp2->len);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK,
                                            ++conn->cmd_ident, 3,
                                            1, idp->data, idp->len,
                                            2, idp2->data, idp2->len,
@@ -2083,7 +2083,7 @@ static void silc_client_command_oper_send(unsigned char *data,
                                    data, data_len);
   }
 
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER, 
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER,
                                          ++conn->cmd_ident, 2,
                                          1, cmd->argv[1],
                                          strlen(cmd->argv[1]),
@@ -2156,7 +2156,7 @@ static void silc_client_command_silcoper_send(unsigned char *data,
                                    data, data_len);
   }
 
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER, 
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER,
                                          ++conn->cmd_ident, 2,
                                          1, cmd->argv[1],
                                          strlen(cmd->argv[1]),
@@ -2338,8 +2338,10 @@ SILC_CLIENT_CMD_FUNC(watch)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer, idp = NULL;
+  SilcBuffer buffer, idp = NULL, args = NULL;
   int type = 0;
+  const char *pubkey = NULL;
+  bool pubkey_add = TRUE;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -2358,19 +2360,51 @@ SILC_CLIENT_CMD_FUNC(watch)
     type = 2;
   } else if (!strcasecmp(cmd->argv[1], "-del")) {
     type = 3;
+  } else if (!strcasecmp(cmd->argv[1], "-pubkey") && cmd->argc >= 3) {
+    type = 4;
+    pubkey = cmd->argv[2] + 1;
+    if (cmd->argv[2][0] == '-')
+      pubkey_add = FALSE;
   } else {
     COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
 
+  if (pubkey) {
+    SilcPublicKey pk;
+
+    if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_PEM)) {
+      if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_BIN)) {
+       SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+           "Could not load public key %s, check the filename",
+           pubkey);
+       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+       goto out;
+      }
+    }
+
+    args = silc_buffer_alloc_size(2);
+    silc_buffer_format(args,
+                      SILC_STR_UI_SHORT(1),
+                      SILC_STR_END);
+    buffer = silc_pkcs_public_key_payload_encode(pk);
+    args = silc_argument_payload_encode_one(args, buffer->data, buffer->len,
+                                           pubkey_add ? 0x00 : 0x01);
+    silc_buffer_free(buffer);
+    silc_pkcs_public_key_free(pk);
+  }
+
   buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
                                          ++conn->cmd_ident, 2,
                                          1, idp->data, idp->len,
-                                         type, cmd->argv[2],
+                                         type,
+                                         pubkey ? args->data : cmd->argv[2],
+                                         pubkey ? args->len :
                                          cmd->argv_lens[2]);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
+  silc_buffer_free(args);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2423,7 +2457,7 @@ SILC_CLIENT_CMD_FUNC(leave)
 
   /* Send LEAVE command to the server */
   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_LEAVE, 
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_LEAVE,
                                          ++conn->cmd_ident, 1,
                                          1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
@@ -2588,7 +2622,7 @@ SILC_CLIENT_CMD_FUNC(getkey)
     idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
   }
 
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY, 
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY,
                                          ++conn->cmd_ident, 1,
                                          1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
@@ -2698,13 +2732,13 @@ SILC_CLIENT_CMD_FUNC(connect)
   }
 
   if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT,
                                            ++conn->cmd_ident, 2,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]),
                                            2, port, 4);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT,
                                            ++conn->cmd_ident, 1,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]));
@@ -2749,13 +2783,13 @@ SILC_CLIENT_CMD_FUNC(close)
   }
 
   if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE,
                                            ++conn->cmd_ident, 2,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]),
                                            2, port, 4);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE,
                                            ++conn->cmd_ident, 1,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]));