updates.
authorPekka Riikonen <priikone@silcnet.org>
Sun, 8 Apr 2001 17:54:02 +0000 (17:54 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 8 Apr 2001 17:54:02 +0000 (17:54 +0000)
19 files changed:
CHANGES
README
TODO
apps/silc/client_ops.c
apps/silc/client_ops.h
apps/silc/local_command.c
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/command_reply.h
apps/silcd/server.c
doc/draft-riikonen-silc-ke-auth-02.nroff
doc/draft-riikonen-silc-pp-02.nroff
doc/draft-riikonen-silc-spec-02.nroff
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silccore/silccommand.h

diff --git a/CHANGES b/CHANGES
index b7f8a6720fb907a2caef6578211092e351eeea56..816493ffea4a56b0cd723f4403d9452a980ce607 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,4 @@
-Sun Apr  8 15:30:56 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
+Sun Apr  8 19:30:56 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Made the key generation options to the silcd program.  Added
          -C option, equivalent to client's option.
@@ -6,6 +6,16 @@ Sun Apr  8 15:30:56 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
        * Added new [ServerKeys] config section to the server.  It
          configures the server's public and private key.
 
+       * Defined generic Public Key Payload into the protocol
+         specification to send specific type of public keys and
+         certificates.
+
+       * Defined new command SILC_COMMAND_GETKEY to fetch a client's
+         public key or certificate.
+
+       * Implemented the GETKEY command to the server and to the
+         client library and on user interface.
+
 Sun Apr  8 01:37:21 EEST 2001  Pekka Riikonen <priikone@poseidon.pspt.fi>
 
        * Made preliminary `make install' work.
diff --git a/README b/README
index da6a575df12abb756270da6a78f890a3cb593923..ae1c812ac51ccfa2633df1e7cb3c18af73ca1d04 100644 (file)
--- a/README
+++ b/README
@@ -347,6 +347,10 @@ SILC Commands
                This command is used to send for example informational
                notice messages to the channel.
 
+       /GETKEY <nickname>
+
+               Fetches remote client's public key.
+
 Features
 ========
 
diff --git a/TODO b/TODO
index 8de20df22b4e933786416e22c1e93e8e944a7617..a43ecfd59a04fbeffda2d222e7187455942e0760 100644 (file)
--- a/TODO
+++ b/TODO
@@ -74,21 +74,6 @@ TODO/bugs In SILC Libraries
    more (silcpkcs.h).
 
 
-TODO in the protocol before SILC 0.x
-====================================
-
- o New commands and features in the commands
-   (draft-riikonen-silc-spec-xx.txt):
-
-       o Define GETKEY command to fetch the public key of a server
-         and/or a client in the SILC Network.
-       o Define SENDKEY command to send your public key to a client
-         in the network.  Sending to the server must not be done due
-         to various security reasons (the server must not trust the
-         public keys blindly without third party verification; that's
-         why SENDKEY is not for servers).
-
-
 TODO After 1.0
 ==============
 
index f7c3964c19513376349a307ad2eb35ebb8cb8006..66e88bda2498da934e003d0170e550f237b769c4 100644 (file)
@@ -893,6 +893,28 @@ void silc_command_reply(SilcClient client, SilcClientConnection conn,
       }
       break;
 
+    case SILC_COMMAND_GETKEY:
+      {
+       SilcIdType id_type;
+       void *entry;
+       SilcPublicKey public_key;
+       unsigned char *pk;
+       uint32 pk_len;
+
+       id_type = va_arg(vp, SilcIdType);
+       entry = va_arg(vp, void *);
+       public_key = va_arg(vp, SilcPublicKey);
+
+       pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+
+       if (id_type == SILC_ID_CLIENT) {
+         silc_verify_public_key(client, conn, SILC_SOCKET_TYPE_CLIENT,
+                                pk, pk_len, SILC_SKE_PK_TYPE_SILC);
+       }
+
+       silc_free(pk);
+      }
+
     default:
       break;
     }
index 214aa01f0fe625c369392f0377d66f5678337c48..ebcd0e3178902e8600e5c1c39deed68de7320cbf 100644 (file)
@@ -41,7 +41,9 @@ void silc_connect(SilcClient client, SilcClientConnection conn, int success);
 void silc_disconnect(SilcClient client, SilcClientConnection conn);
 unsigned char *silc_ask_passphrase(SilcClient client, 
                                   SilcClientConnection conn);
-int silc_verify_server_key(SilcClient client, SilcClientConnection conn, 
+int silc_verify_public_key(SilcClient client,
+                          SilcClientConnection conn, 
+                          SilcSocketType conn_type,
                           unsigned char *pk, uint32 pk_len,
                           SilcSKEPKType pk_type);
 int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
index fae582a759befd7769a214a625d30f686f54d9d9..509b4fa2c52f89b35f26dab15d310aaa202cef3f 100644 (file)
@@ -90,7 +90,6 @@ SILC_CLIENT_LCMD_FUNC(version)
    private messages are not really commands, they are message packets,
    however, on user interface it is convenient to show them as commands
    as that is the common way of sending private messages (like in IRC). */
-/* XXX supports only one destination */
 
 SILC_CLIENT_LCMD_FUNC(msg)
 {
index 47462e6974888fa7ab3bd909836de06ffb1e8481..e7e0a0822fe6d3569bd112d7526d43deaaf159ff 100644 (file)
@@ -71,6 +71,7 @@ SilcServerCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
 
   { NULL, 0 },
 };
@@ -4759,3 +4760,167 @@ SILC_SERVER_CMD_FUNC(users)
  out:
   silc_server_command_free(cmd);
 }
+
+/* Server side of command GETKEY. This fetches the client's public key
+   from the server where to the client is connected. */
+
+SILC_SERVER_CMD_FUNC(getkey)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcBuffer packet;
+  SilcClientEntry client;
+  SilcServerEntry server_entry;
+  SilcClientID *client_id = NULL;
+  SilcServerID *server_id = NULL;
+  SilcIDPayload idp = NULL;
+  uint16 ident = silc_command_get_ident(cmd->payload);
+  unsigned char *tmp;
+  uint32 tmp_len;
+  SilcBuffer pk;
+  SilcIdType id_type;
+
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!tmp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+  idp = silc_id_payload_parse_data(tmp, tmp_len);
+  if (!idp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+
+  id_type = silc_id_payload_get_type(idp);
+  if (id_type == SILC_ID_CLIENT) {
+    client_id = silc_id_payload_get_id(idp);
+
+    /* If the client is not found from local list there is no chance it
+       would be locally connected client so send the command further. */
+    client = silc_idlist_find_client_by_id(server->local_list, 
+                                          client_id, NULL);
+    
+    if ((!client && !cmd->pending && !server->standalone) ||
+       (client && !client->connection)) {
+      SilcBuffer tmpbuf;
+      uint16 old_ident;
+      SilcSocketConnection dest_sock;
+      
+      dest_sock = silc_server_get_client_route(server, NULL, 0, 
+                                              client_id, NULL);
+      if (!dest_sock)
+       goto out;
+      
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+      
+      silc_server_packet_send(server, dest_sock,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+      
+      /* Reprocess this packet after received reply from router */
+      silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_getkey,
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      
+      silc_command_set_ident(cmd->payload, old_ident);
+      silc_buffer_free(tmpbuf);
+      return;
+    }
+
+    if (!client && cmd->pending) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+      goto out;
+    }
+
+    /* The client is locally connected, just get the public key and
+       send it back. */
+    tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
+    pk = silc_buffer_alloc(4 + tmp_len);
+    silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+    silc_buffer_format(pk,
+                      SILC_STR_UI_SHORT(tmp_len),
+                      SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+                      SILC_STR_UI_XNSTRING(tmp, tmp_len),
+                      SILC_STR_END);
+    silc_free(tmp);
+
+  } else if (id_type == SILC_ID_SERVER) {
+    server_id = silc_id_payload_get_id(idp);
+
+    /* If the server is not found from local list there is no chance it
+       would be locally connected server so send the command further. */
+    server_entry = silc_idlist_find_server_by_id(server->local_list, 
+                                                server_id, NULL);
+    
+    if ((!server_entry && !cmd->pending && !server->standalone) ||
+       (server_entry && !server_entry->connection)) {
+      SilcBuffer tmpbuf;
+      uint16 old_ident;
+      
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+      
+      silc_server_packet_send(server, server->router->connection,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+      
+      /* Reprocess this packet after received reply from router */
+      silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_getkey,
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      
+      silc_command_set_ident(cmd->payload, old_ident);
+      silc_buffer_free(tmpbuf);
+      return;
+    }
+
+    if (!server_entry && cmd->pending) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                           SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
+      goto out;
+    }
+
+    /* The client is locally connected, just get the public key and
+       send it back. */
+    tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
+    pk = silc_buffer_alloc(4 + tmp_len);
+    silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+    silc_buffer_format(pk,
+                      SILC_STR_UI_SHORT(tmp_len),
+                      SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+                      SILC_STR_UI_XNSTRING(tmp, tmp_len),
+                      SILC_STR_END);
+    silc_free(tmp);
+  } else {
+    goto out;
+  }
+
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
+                                               SILC_STATUS_OK, ident, 2,
+                                               2, tmp, tmp_len,
+                                               3, pk->data, pk->len);
+  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                         packet->data, packet->len, FALSE);
+  silc_buffer_free(packet);
+  silc_buffer_free(pk);
+
+ out:
+  if (idp)
+    silc_id_payload_free(idp);
+  silc_free(client_id);
+  silc_free(server_id);
+  silc_server_command_free(cmd);
+}
index 62527f0f0c1e7e52029bf19faecff617c375bacb..4134ee2e9450d2405c95f99364d1a98f3471dcea 100644 (file)
@@ -154,5 +154,6 @@ SILC_SERVER_CMD_FUNC(shutdown);
 SILC_SERVER_CMD_FUNC(silcoper);
 SILC_SERVER_CMD_FUNC(leave);
 SILC_SERVER_CMD_FUNC(users);
+SILC_SERVER_CMD_FUNC(getkey);
 
 #endif
index a23e0305f0d7285ad1c72fc6262b524baabf4ef5..2bc68693f2f79de17ddeef74b1a0f94e64a8cd0a 100644 (file)
@@ -56,6 +56,7 @@ SilcServerCommandReply silc_command_reply_list[] =
   SILC_SERVER_CMD_REPLY(motd, MOTD),
   SILC_SERVER_CMD_REPLY(join, JOIN),
   SILC_SERVER_CMD_REPLY(users, USERS),
+  SILC_SERVER_CMD_REPLY(getkey, GETKEY),
 
   { NULL, 0 },
 };
@@ -885,7 +886,92 @@ SILC_SERVER_CMD_REPLY_FUNC(users)
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
   SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
-  if (channel_id)
-    silc_free(channel_id);
+  silc_free(channel_id);
+  silc_server_command_reply_free(cmd);
+}
+
+SILC_SERVER_CMD_REPLY_FUNC(getkey)
+{
+  SilcServerCommandReplyContext cmd = (SilcServerCommandReplyContext)context;
+  SilcServer server = cmd->server;
+  SilcCommandStatus status;
+  SilcClientEntry client = NULL;
+  SilcServerEntry server_entry = NULL;
+  SilcClientID *client_id = NULL;
+  SilcServerID *server_id = NULL;
+  SilcSKEPKType type;
+  unsigned char *tmp, *pk;
+  uint32 len;
+  uint16 pk_len;
+  SilcIDPayload idp = NULL;
+  SilcIdType id_type;
+  SilcPublicKey public_key = NULL;
+
+  COMMAND_CHECK_STATUS;
+
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (!tmp)
+    goto out;
+  idp = silc_id_payload_parse_data(tmp, len);
+  if (!idp)
+    goto out;
+
+  /* Get the public key payload */
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+  if (!tmp)
+    goto out;
+
+  /* Decode the public key */
+
+  SILC_GET16_MSB(pk_len, tmp);
+  SILC_GET16_MSB(type, tmp + 2);
+  pk = tmp + 4;
+
+  if (type != SILC_SKE_PK_TYPE_SILC)
+    goto out;
+
+  if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
+    goto out;
+
+  id_type = silc_id_payload_get_type(idp);
+  if (id_type == SILC_ID_CLIENT) {
+    client_id = silc_id_payload_get_id(idp);
+
+    client = silc_idlist_find_client_by_id(server->local_list, client_id,
+                                          NULL);
+    if (!client) {
+      client = silc_idlist_find_client_by_id(server->global_list, 
+                                            client_id, NULL);
+      if (!client)
+       goto out;
+    }
+
+    client->data.public_key = public_key;
+  } else if (id_type == SILC_ID_SERVER) {
+    server_id = silc_id_payload_get_id(idp);
+
+    server_entry = silc_idlist_find_server_by_id(server->local_list, server_id,
+                                                NULL);
+    if (!server_entry) {
+      server_entry = silc_idlist_find_server_by_id(server->global_list, 
+                                                  server_id, NULL);
+      if (!server_entry)
+       goto out;
+    }
+
+    server_entry->data.public_key = public_key;
+  } else {
+    goto out;
+  }
+
+ out:
+  SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_USERS);
+  SILC_SERVER_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_USERS);
+  if (idp)
+    silc_id_payload_free(idp);
+  silc_free(client_id);
+  silc_free(server_id);
+  if (public_key)
+    silc_pkcs_public_key_free(public_key);
   silc_server_command_reply_free(cmd);
 }
index 852642d6ec86e9da59da85fae989281ca86ba644..213ed97932efdaaa684d0de3de033eb790203d56 100644 (file)
@@ -68,5 +68,6 @@ SILC_SERVER_CMD_REPLY_FUNC(info);
 SILC_SERVER_CMD_REPLY_FUNC(motd);
 SILC_SERVER_CMD_REPLY_FUNC(join);
 SILC_SERVER_CMD_REPLY_FUNC(users);
+SILC_SERVER_CMD_REPLY_FUNC(getkey);
 
 #endif
index 87517338e304470f58a5b9e7319e245fbc6988b5..7b1d27f7cf31663bd18c5d3a25ac291cb223eb84 100644 (file)
@@ -3426,7 +3426,7 @@ void silc_server_save_users_on_channel(SilcServer server,
   }
 }
 
-/* Lookups route to the client indicated by `id' client ID. The connection
+/* Lookups route to the client indicated by the `id_data'. The connection
    object and internal data object is returned. Returns NULL if route
    could not be found to the client. If the `client_id' is specified then
    it is used and the `id_data' is ignored. */
@@ -3468,12 +3468,14 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server,
       /* We are of course in this case the client's router thus the real
         "router" of the client is the server who owns the client. Thus
         we will send the packet to that server. */
-      *idata = (SilcIDListData)client->router;
+      if (idata)
+       *idata = (SilcIDListData)client->router;
       return client->router->connection;
     }
 
     /* Seems that client really is directly connected to us */
-    *idata = (SilcIDListData)client;
+    if (idata)
+      *idata = (SilcIDListData)client;
     return client->connection;
   }
 
@@ -3481,7 +3483,8 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server,
      server our action is to send the packet to our router. */
   if (server->server_type == SILC_SERVER && !server->standalone) {
     silc_free(id);
-    *idata = (SilcIDListData)server->router;
+    if (idata)
+      *idata = (SilcIDListData)server->router;
     return server->router->connection;
   }
 
@@ -3496,7 +3499,8 @@ SilcSocketConnection silc_server_get_client_route(SilcServer server,
       dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
 
       silc_free(id);
-      *idata = (SilcIDListData)dst_sock->user_data;
+      if (idata)
+       *idata = (SilcIDListData)dst_sock->user_data;
       return dst_sock;
     }
   }
index 56f3d0bdd2193017b1dde412b1ab5adc8bf43d22..8b47ea932ce421a650a2e6121d80d36f08590867 100644 (file)
@@ -471,6 +471,9 @@ o Public Key Type (2 bytes) - The public key (or certificate)
   sending SILC_PACKET_FAILURE message and the connection should
   be closed immediately.
 
+o Public Key (or certicicate) (variable length) - The
+  public key or certificate.
+
 o Public Data Length (2 bytes) - The length of the Public Data
   field, not including any other field.
 
index 03d1f40e1165c20d4b3fe247418d2b041a442360..6e3edaea226cddb1ca8e39ac3b62effb6d5baa7f 100644 (file)
@@ -81,6 +81,7 @@ Table of Contents
             2.3.2.1 ID Payload .................................. 16
             2.3.2.2 Argument Payload ............................ 16
             2.3.2.3 Channel Payload ............................. XXX
+            2.3.2.4 Public Key Payload .......................... XXX
       2.3.3 Disconnect Payload .................................. 17
       2.3.4 Success Payload ..................................... 18
       2.3.5 Failure Payload ..................................... 18
@@ -124,22 +125,23 @@ Figure 2:   SILC Packet Header
 Figure 3:   ID Payload
 Figure 4:   Argument Payload
 Figure 5:   Channel Payload
-Figure 6:   Disconnect Payload
-Figure 7:   Success Payload
-Figure 8:   Failure Payload
-Figure 9:   Reject Payload
-Figure 10:  Notify Payload
-Figure 11:  Error Payload
-Figure 12:  Channel Message Payload
-Figure 13:  Channel Key Payload
-Figure 14:  Private Message Payload
-Figure 15:  Private Message Key Payload
-Figure 16:  Command Payload
-Figure 17:  Connection Auth Request Payload
-Figure 18:  New Client Payload
-Figure 19:  New Server Payload
-Figure 20:  Key Agreement Payload
-Figure 21:  Cell Routers Payload
+Figure 6:   Public Key Payload
+Figure 7:   Disconnect Payload
+Figure 8:   Success Payload
+Figure 9:   Failure Payload
+Figure 10:   Reject Payload
+Figure 11:  Notify Payload
+Figure 12:  Error Payload
+Figure 13:  Channel Message Payload
+Figure 14:  Channel Key Payload
+Figure 15:  Private Message Payload
+Figure 16:  Private Message Key Payload
+Figure 17:  Command Payload
+Figure 18:  Connection Auth Request Payload
+Figure 19:  New Client Payload
+Figure 20:  New Server Payload
+Figure 21:  Key Agreement Payload
+Figure 22:  Cell Routers Payload
 
 
 .ti 0
@@ -915,6 +917,45 @@ o Mode Mask (4 bytes) - A mode.  This can be the mode of the
 .in 3
 
 
+.ti 0
+2.3.2.4 Public Key Payload
+
+Generic Public Key Payload may be used to send different types of
+public keys and certificates.
+
+The following diagram represents the Channel Payload Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Public Key Length       |        Public Key Type        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~            Public Key of the party (or certificate)           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 6:  Public Key Payload
+
+
+.in 6
+o Public Key Length (2 bytes) - The length of the Public Key
+  (or certificate) field, not including any other field.
+
+o Public Key Type (2 bytes) - The public key (or certificate) 
+  type.  This field indicates the type of the public key in 
+  the packet.  See the [SILC3] for defined public key types.
+
+o Public Key (or certicicate) (variable length) - The
+  public key or certificate.
+.in 3
+
+
 .ti 0
 2.3.3 Disconnect Payload
 
@@ -943,7 +984,7 @@ the Disconnect Payload.
 .in 3
 
 .ce
-Figure 6:  Disconnect Payload
+Figure 7:  Disconnect Payload
 
 
 
@@ -973,7 +1014,7 @@ This maybe any data, including binary or human readable data.
 .in 3
 
 .ce
-Figure 7:  Success Payload
+Figure 8:  Success Payload
 
 
 .in 6
@@ -1005,7 +1046,7 @@ some protocol is sent in the payload.
 .in 3
 
 .ce
-Figure 8:  Failure Payload
+Figure 9:  Failure Payload
 
 
 .in 6
@@ -1039,7 +1080,7 @@ may be binary or human readable data.
 .in 3
 
 .ce
-Figure 9:  Reject Payload
+Figure 10:  Reject Payload
 
 
 .in 6
@@ -1080,7 +1121,7 @@ Notify Payload.
 .in 3
 
 .ce
-Figure 10:  Notify Payload
+Figure 11:  Notify Payload
 
 
 .in 6
@@ -1376,7 +1417,7 @@ that the client takes error packet seriously.
 .in 3
 
 .ce
-Figure 11:  Error Payload
+Figure 12:  Error Payload
 
 
 .in 6
@@ -1451,7 +1492,7 @@ represents the Channel Message Payload.
 .in 3
 
 .ce
-Figure 12:  Channel Message Payload
+Figure 13:  Channel Message Payload
 
 
 .in 6
@@ -1604,7 +1645,7 @@ represents the Channel Key Payload.
 .in 3
 
 .ce
-Figure 13:  Channel Key Payload
+Figure 14:  Channel Key Payload
 
 
 
@@ -1688,7 +1729,7 @@ diagram represents the Private Message Payload.
 .in 3
 
 .ce
-Figure 14:  Private Message Payload
+Figure 15:  Private Message Payload
 
 
 .in 6
@@ -1765,7 +1806,7 @@ diagram represents the Private Message Key Payload.
 .in 3
 
 .ce
-Figure 15:  Private Message Key Payload
+Figure 16:  Private Message Key Payload
 
 
 
@@ -1810,7 +1851,7 @@ represents the Command Payload.
 .in 3
 
 .ce
-Figure 16:  Command Payload
+Figure 17:  Command Payload
 
 
 .in 6
@@ -1892,7 +1933,7 @@ diagram represents the Connection Auth Request Payload.
 .in 3
 
 .ce
-Figure 17:  Connection Auth Request Payload
+Figure 18:  Connection Auth Request Payload
 
 
 .in 6
@@ -2010,7 +2051,7 @@ represents the New Client Payload.
 .in 3
 
 .ce
-Figure 18:  New Client Payload
+Figure 19:  New Client Payload
 
 
 .in 6
@@ -2065,7 +2106,7 @@ the New Server Payload.
 .in 3
 
 .ce
-Figure 19:  New Server Payload
+Figure 20:  New Server Payload
 
 
 .in 6
@@ -2139,7 +2180,7 @@ represents the Key Agreement Payload.
 .in 3
 
 .ce
-Figure 20:  Key Agreement Payload
+Figure 21:  Key Agreement Payload
 
 
 .in 6
@@ -2205,7 +2246,7 @@ represents the Cell Routers Payload.
 .in 3
 
 .ce
-Figure 21:  Cell Routers Payload
+Figure 22:  Cell Routers Payload
 
 
 .in 6
index d945f2aa1270eba1e1183c5f72d930aea5da5910..0cf79690e4d94e6814a58692a09141fd40157858 100644 (file)
@@ -3238,6 +3238,34 @@ List of all defined commands in SILC follows.
             SILC_STATUS_ERR_NOT_ON_CHANNEL
 
 
+   26   SILC_COMMAND_GETKEY
+
+        Max Arguments:  1
+            Arguments:  (1) <ID Payload>
+
+        This command is used to fetch the public key of the client or
+        server indicated by the <ID Payload>.  The public key is fetched
+        from the server where to the client is connected.
+
+        Reply messages to the command:
+
+        Max Arguments:  3
+            Arguments:  (1) <Status Payload>      (2) <ID Payload>
+                        (3) <Public Key Payload>
+
+        This command replies with the client's or server's ID and with
+        the <Public Key Payload>.
+
+        Status messages:
+
+            SILC_STATUS_OK
+            SILC_STATUS_ERR_NOT_REGISTERED
+            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS
+            SILC_STATUS_ERR_TOO_MANY_PARAMS
+            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID
+            SILC_STATUS_ERR_NO_SUCH_SERVER_ID
+
+
    27 - 199
 
         Currently undefined commands.
@@ -3515,6 +3543,11 @@ List of all defined command status messages following.
 
         "The algorithm was not supported."  The server does not support the
         requested algorithm.
+
+   47   SILC_STATUS_ERR_NO_SUCH_SERVER_ID
+
+        "No such Server ID".  Server ID provided does not exist.
+
 .in 3
 
 
index db3946ca272aea406fe4c5d13a02c7aa7442d6d4..ffa55d5c744dce2481e7d41348d4c6268bcb1dc0 100644 (file)
@@ -57,6 +57,7 @@ SilcClientCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER, 3),
   SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", SILC_CF_LAG | SILC_CF_REG, 2),
   SILC_CLIENT_CMD(users, USERS, "USERS", SILC_CF_LAG | SILC_CF_REG, 2),
+  SILC_CLIENT_CMD(getkey, GETKEY, "GETKEY", SILC_CF_LAG | SILC_CF_REG, 2),
 
   { NULL, 0, NULL, 0, 0 },
 };
@@ -2049,3 +2050,64 @@ SILC_CLIENT_CMD_FUNC(users)
  out:
   silc_client_command_free(cmd);
 }
+
+/* Command GETKEY. Used to fetch remote client's public key. */
+
+SILC_CLIENT_CMD_FUNC(getkey)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcClient client = cmd->client;
+  SilcClientEntry client_entry = NULL;
+  uint32 num = 0;
+  char *nickname = NULL, *server = NULL;
+  SilcBuffer idp, buffer;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    client->ops->say(client, conn, "Usage: /GETKEY <nickname>");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  /* Parse the typed nickname. */
+  if (!silc_parse_nickname(cmd->argv[1], &nickname, &server, &num)) {
+    client->ops->say(client, conn, "Bad nickname");
+    COMMAND_ERROR;
+    goto out;
+  }
+
+  /* Find client entry */
+  client_entry = silc_idlist_get_client(client, conn, nickname, server, num,
+                                       TRUE);
+  if (!client_entry) {
+    /* Client entry not found, it was requested thus mark this to be
+       pending command. */
+    silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, 
+                               conn->cmd_ident,  
+                               silc_client_command_destructor,
+                               silc_client_command_getkey, 
+                               silc_client_command_dup(cmd));
+    cmd->pending = 1;
+    return;
+  }
+
+  idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY, 0, 1, 
+                                         1, idp->data, idp->len);
+  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(idp);
+
+  /* Notify application */
+  COMMAND;
+
+ out:
+  silc_client_command_free(cmd);
+}
index a9699527323d29351f2dc83cb10fbf1f936a4cdd..69a94efd267aacd77a4eff669111bd3005d81c46 100644 (file)
@@ -153,5 +153,6 @@ SILC_CLIENT_CMD_FUNC(shutdown);
 SILC_CLIENT_CMD_FUNC(silcoper);
 SILC_CLIENT_CMD_FUNC(leave);
 SILC_CLIENT_CMD_FUNC(users);
+SILC_CLIENT_CMD_FUNC(getkey);
 
 #endif
index 3b34d5b52cb1138403f0ab8f2212d109f3b985b8..d91710fae7f754b10c49adbf03dcca6ff63e5072 100644 (file)
@@ -57,12 +57,13 @@ SilcClientCommandReply silc_command_reply_list[] =
   SILC_CLIENT_CMD_REPLY(cmode, CMODE),
   SILC_CLIENT_CMD_REPLY(cumode, CUMODE),
   SILC_CLIENT_CMD_REPLY(kick, KICK),
+  SILC_CLIENT_CMD_REPLY(ban, BAN),
   SILC_CLIENT_CMD_REPLY(close, CLOSE),
   SILC_CLIENT_CMD_REPLY(shutdown, SHUTDOWN),
   SILC_CLIENT_CMD_REPLY(silcoper, SILCOPER),
   SILC_CLIENT_CMD_REPLY(leave, LEAVE),
   SILC_CLIENT_CMD_REPLY(users, USERS),
-  SILC_CLIENT_CMD_REPLY(ban, BAN),
+  SILC_CLIENT_CMD_REPLY(getkey, GETKEY),
 
   { NULL, 0 },
 };
@@ -106,6 +107,7 @@ const SilcCommandStatusMessage silc_command_status_messages[] = {
   { STAT(BAD_CHANNEL),     "Bad channel name" },
   { STAT(AUTH_FAILED),     "Authentication failed" },
   { STAT(UNKNOWN_ALGORITHM), "Unsupported algorithm" },
+  { STAT(NO_SUCH_SERVER_ID), "No such Server ID" },
 
   { 0, NULL }
 };
@@ -1396,6 +1398,59 @@ SILC_CLIENT_CMD_REPLY_FUNC(connect)
   silc_client_command_reply_free(cmd);
 }
 
+SILC_CLIENT_CMD_REPLY_FUNC(ban)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+  SilcCommandStatus status;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcChannelEntry channel;
+  SilcChannelID *channel_id;
+  unsigned char *tmp;
+  uint32 len;
+
+  tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
+  SILC_GET16_MSB(status, tmp);
+  if (status != SILC_STATUS_OK) {
+    cmd->client->ops->say(cmd->client, conn,
+            "%s", silc_client_command_status_message(status));
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+
+  /* Take Channel ID */
+  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (!tmp)
+    goto out;
+
+  channel_id = silc_id_payload_parse_id(tmp, len);
+  if (!channel_id)
+    goto out;
+
+  /* Get the channel entry */
+  if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
+                                  SILC_ID_CHANNEL, &id_cache)) {
+    silc_free(channel_id);
+    COMMAND_REPLY_ERROR;
+    goto out;
+  }
+  
+  channel = (SilcChannelEntry)id_cache->context;
+
+  /* Get the ban list */
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+
+  /* Notify application */
+  COMMAND_REPLY((ARGS, channel, tmp));
+
+  /* Execute any pending command callbacks */
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN);
+
+ out:
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_BAN);
+  silc_client_command_reply_free(cmd);
+}
+
 SILC_CLIENT_CMD_REPLY_FUNC(close)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
@@ -1652,16 +1707,26 @@ SILC_CLIENT_CMD_REPLY_FUNC(users)
   silc_client_command_reply_free(cmd);
 }
 
-SILC_CLIENT_CMD_REPLY_FUNC(ban)
+/* Received command reply to GETKEY command. WE've received the remote
+   client's public key. */
+
+SILC_CLIENT_CMD_REPLY_FUNC(getkey)
 {
   SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
   SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
   SilcCommandStatus status;
-  SilcIDCacheEntry id_cache = NULL;
-  SilcChannelEntry channel;
-  SilcChannelID *channel_id;
-  unsigned char *tmp;
+  SilcIDCacheEntry id_cache;
+  SilcIDPayload idp = NULL;
+  SilcClientID *client_id = NULL;
+  SilcClientEntry client_entry;
+  SilcSKEPKType type;
+  unsigned char *tmp, *pk;
   uint32 len;
+  uint16 pk_len;
+  SilcIdType id_type;
+  SilcPublicKey public_key = NULL;
+
+  SILC_LOG_DEBUG(("Start"));
 
   tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
   SILC_GET16_MSB(status, tmp);
@@ -1672,35 +1737,55 @@ SILC_CLIENT_CMD_REPLY_FUNC(ban)
     goto out;
   }
 
-  /* Take Channel ID */
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
   if (!tmp)
     goto out;
+  idp = silc_id_payload_parse_data(tmp, len);
+  if (!idp)
+    goto out;
 
-  channel_id = silc_id_payload_parse_id(tmp, len);
-  if (!channel_id)
+  /* Get the public key payload */
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+  if (!tmp)
     goto out;
 
-  /* Get the channel entry */
-  if (!silc_idcache_find_by_id_one(conn->channel_cache, (void *)channel_id,
-                                  SILC_ID_CHANNEL, &id_cache)) {
-    silc_free(channel_id);
-    COMMAND_REPLY_ERROR;
+  /* Decode the public key */
+
+  SILC_GET16_MSB(pk_len, tmp);
+  SILC_GET16_MSB(type, tmp + 2);
+  pk = tmp + 4;
+
+  if (type != SILC_SKE_PK_TYPE_SILC)
     goto out;
-  }
-  
-  channel = (SilcChannelEntry)id_cache->context;
 
-  /* Get the ban list */
-  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
+  if (!silc_pkcs_public_key_decode(pk, pk_len, &public_key))
+    goto out;
 
-  /* Notify application */
-  COMMAND_REPLY((ARGS, channel, tmp));
+  id_type = silc_id_payload_get_type(idp);
+  if (id_type == SILC_ID_CLIENT) {
+    client_id = silc_id_payload_get_id(idp);
 
-  /* Execute any pending command callbacks */
-  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_BAN);
+    if (!silc_idcache_find_by_id_one(conn->client_cache, (void *)client_id,
+                                    SILC_ID_CLIENT, &id_cache))
+      goto out;
+
+    client_entry = (SilcClientEntry)id_cache->context;
+
+    /* Notify application */
+    COMMAND_REPLY((ARGS, id_type, client_entry, public_key));
+  } else if (id_type == SILC_ID_SERVER) {
+    /* XXX we don't have server entries at all */
+    goto out;
+  } else {
+    goto out;
+  }
 
  out:
-  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_BAN);
+  SILC_CLIENT_PENDING_DESTRUCTOR(cmd, SILC_COMMAND_GETKEY);
+  if (idp)
+    silc_id_payload_free(idp);
+  if (public_key)
+    silc_pkcs_public_key_free(public_key);
+  silc_free(client_id);
   silc_client_command_reply_free(cmd);
 }
index ed09ab5974a7337b07323d445d08d300c56b4d4c..8c3951a495f9af5d37e07eab0fc4732f09ca8022 100644 (file)
@@ -92,11 +92,12 @@ SILC_CLIENT_CMD_REPLY_FUNC(umode);
 SILC_CLIENT_CMD_REPLY_FUNC(cmode);
 SILC_CLIENT_CMD_REPLY_FUNC(cumode);
 SILC_CLIENT_CMD_REPLY_FUNC(kick);
+SILC_CLIENT_CMD_REPLY_FUNC(ban);
 SILC_CLIENT_CMD_REPLY_FUNC(close);
 SILC_CLIENT_CMD_REPLY_FUNC(shutdown);
 SILC_CLIENT_CMD_REPLY_FUNC(silcoper);
 SILC_CLIENT_CMD_REPLY_FUNC(leave);
 SILC_CLIENT_CMD_REPLY_FUNC(users);
-SILC_CLIENT_CMD_REPLY_FUNC(ban);
+SILC_CLIENT_CMD_REPLY_FUNC(getkey);
 
 #endif
index 2f835e91941c7a4ebf146fe7ece4e7e18109ee6b..2b069bc2082b33b81bd83eb2fc399fbc48f932ae 100644 (file)
@@ -85,6 +85,7 @@ typedef enum {
 #define SILC_COMMAND_SILCOPER          23
 #define SILC_COMMAND_LEAVE             24
 #define SILC_COMMAND_USERS             25
+#define SILC_COMMAND_GETKEY            26
 
 /* Reserved */
 #define SILC_COMMAND_RESERVED           255
@@ -134,6 +135,7 @@ typedef uint16 SilcCommandStatus;
 #define SILC_STATUS_ERR_BAD_CHANNEL         44
 #define SILC_STATUS_ERR_AUTH_FAILED         45
 #define SILC_STATUS_ERR_UNKNOWN_ALGORITHM   46
+#define SILC_STATUS_ERR_NO_SUCH_SERVER_ID   47
 
 /* Prototypes */
 SilcCommandPayload silc_command_payload_parse(SilcBuffer buffer);