updates.
[silc.git] / apps / irssi / src / silc / core / client_ops.c
index b873e2cb9ed15ba194820b057a7866d042be3c02..79be2e8c7b4eef61cc9c1e9d7bbbcd1e63e4c332 100644 (file)
@@ -188,6 +188,11 @@ void silc_connect(SilcClient client, SilcClientConnection conn, int success)
 {
   SILC_SERVER_REC *server = conn->context;
 
+  if (!server && !success) {
+    silc_client_close_connection(client, NULL, conn);
+    return;
+  }
+
   if (success) {
     server->connected = TRUE;
     signal_emit("event connected", 1, server);
@@ -328,9 +333,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
   switch(command) {
   case SILC_COMMAND_WHOIS:
     {
-      char buf[1024], *nickname, *username, *realname;
+      char buf[1024], *nickname, *username, *realname, *nick;
       uint32 idle, mode;
       SilcBuffer channels;
+      SilcClientEntry client_entry;
       
       if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
          status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
@@ -348,7 +354,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       if (!success)
        return;
       
-      (void)va_arg(vp, SilcClientEntry);
+      client_entry = va_arg(vp, SilcClientEntry);
       nickname = va_arg(vp, char *);
       username = va_arg(vp, char *);
       realname = va_arg(vp, char *);
@@ -356,9 +362,14 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       mode = va_arg(vp, uint32);
       idle = va_arg(vp, uint32);
       
+      silc_parse_userfqdn(nickname, &nick, NULL);
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                        SILCTXT_WHOIS_USERINFO, nickname, username, 
-                        realname);
+                        SILCTXT_WHOIS_USERINFO, nickname, 
+                        client_entry->username, client_entry->hostname,
+                        nick, client_entry->nickname);
+      printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                        SILCTXT_WHOIS_REALNAME, realname);
+      silc_free(nick);
 
       if (channels) {
        SilcDList list = silc_channel_payload_parse_list(channels);
@@ -673,14 +684,21 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
       id_type = va_arg(vp, uint32);
       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_internal(client, conn, SILC_SOCKET_TYPE_CLIENT,
+
+      if (public_key) {
+       pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+       
+       silc_verify_public_key_internal(client, conn, 
+                                       (id_type == SILC_ID_CLIENT ?
+                                        SILC_SOCKET_TYPE_CLIENT :
+                                        SILC_SOCKET_TYPE_SERVER),
                                        pk, pk_len, SILC_SKE_PK_TYPE_SILC,
                                        NULL, NULL);
-      silc_free(pk);
+       silc_free(pk);
+      } else {
+       printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_GETKEY_NOKEY);
+      }
     }
     break;
     
@@ -949,7 +967,7 @@ void ask_passphrase_completion(const char *passphrase, void *context)
 }
 
 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-                               SilcAskPassphrase completion, void *context)
+                        SilcAskPassphrase completion, void *context)
 {
   AskPassphrase p = silc_calloc(1, sizeof(*p));
   p->completion = completion;
@@ -959,34 +977,69 @@ void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
                          "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p);
 }
 
+typedef struct {
+  SilcGetAuthMeth completion;
+  void *context;
+} *InternalGetAuthMethod;
+
+/* Callback called when we've received the authentication method information
+   from the server after we've requested it. This will get the authentication
+   data from the user if needed. */
+
+static void silc_get_auth_method_callback(SilcClient client,
+                                         SilcClientConnection conn,
+                                         SilcAuthMethod auth_meth,
+                                         void *context)
+{
+  InternalGetAuthMethod internal = (InternalGetAuthMethod)context;
+
+  switch (auth_meth) {
+  case SILC_AUTH_NONE:
+    /* No authentication required. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  case SILC_AUTH_PASSWORD:
+    /* Do not ask the passphrase from user, the library will ask it if
+       we do not provide it here. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  case SILC_AUTH_PUBLIC_KEY:
+    /* Do not get the authentication data now, the library will generate
+       it using our default key, if we do not provide it here. */
+    /* XXX In the future when we support multiple local keys and multiple
+       local certificates we will need to ask from user which one to use. */
+    (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+    break;
+  }
+
+  silc_free(internal);
+}
+
 /* Find authentication method and authentication data by hostname and
    port. The hostname may be IP address as well. The found authentication
    method and authentication data is returned to `auth_meth', `auth_data'
    and `auth_data_len'. The function returns TRUE if authentication method
    is found and FALSE if not. `conn' may be NULL. */
 
-int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-                        char *hostname, uint16 port,
-                        SilcProtocolAuthMeth *auth_meth,
-                        unsigned char **auth_data,
-                        uint32 *auth_data_len)
+void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+                         char *hostname, uint16 port,
+                         SilcGetAuthMeth completion, void *context)
 {
-  bool ret = TRUE;
-  SILC_SERVER_REC *server = conn ? conn->context : NULL;
+  InternalGetAuthMethod internal;
 
   /* XXX must resolve from configuration whether this connection has
      any specific authentication data */
 
-  *auth_meth = SILC_AUTH_NONE;
-  *auth_data = NULL;
-  *auth_data_len = 0;
+  /* If we do not have this connection configured by the user in a
+     configuration file then resolve the authentication method from the
+     server for this session. */
+  internal = silc_calloc(1, sizeof(*internal));
+  internal->completion = completion;
+  internal->context = context;
 
-  if (ret == FALSE) {
-    printformat_module("fe-common/silc", server, NULL,
-                      MSGLEVEL_MODES, SILCTXT_AUTH_METH_UNRESOLVED);
-  }
-
-  return ret;
+  silc_client_request_authentication_method(client, conn, 
+                                           silc_get_auth_method_callback,
+                                           internal);
 }
 
 /* Notifies application that failure packet was received.  This is called
@@ -1026,6 +1079,9 @@ void silc_failure(SilcClient client, SilcClientConnection conn,
     if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
       printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
                         SILCTXT_KE_INCORRECT_SIGNATURE);
+    if (status == SILC_SKE_STATUS_INVALID_COOKIE)
+      printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, 
+                        SILCTXT_KE_INVALID_COOKIE);
   }
 
   if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {