Added SILC Server library.
[silc.git] / lib / silcclient / protocol.c
index bc229606f6b0f19b2baa618bcac556730b2a05fb..c16d9aa3545570e952a347d05f395b51358f7c85 100644 (file)
@@ -2,14 +2,13 @@
 
   protocol.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  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
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   GNU General Public License for more details.
 
 */
-/*
- * Client side of the protocols.
- */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "client_internal.h"
 
@@ -59,7 +55,7 @@ typedef struct {
   void *completion_context;
 } *VerifyKeyContext;
 
-static void silc_client_verify_key_cb(bool success, void *context)
+static void silc_client_verify_key_cb(SilcBool success, void *context)
 {
   VerifyKeyContext verify = (VerifyKeyContext)context;
 
@@ -114,7 +110,7 @@ void silc_client_protocol_ke_set_keys(SilcSKE ske,
                                      SilcHash hash,
                                      SilcHmac hmac,
                                      SilcSKEDiffieHellmanGroup group,
-                                     bool is_responder)
+                                     SilcBool is_responder)
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
   const char *cname = silc_cipher_get_name(cipher);
@@ -288,6 +284,14 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
                             context);
 
       if (ctx->responder == TRUE) {
+       if (!ctx->packet) {
+         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+                           status));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, client->schedule, 0, 0);
+         return;
+       }
+
        /* Start the key exchange by processing the received security
           properties packet from initiator. */
        status =
@@ -339,6 +343,14 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
        /* Sends the selected security properties to the initiator. */
        status = silc_ske_responder_phase_1(ctx->ske);
       } else {
+       if (!ctx->packet) {
+         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+                           status));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, client->schedule, 0, 0);
+         return;
+       }
+
        /* Call Phase-1 function. This processes the Key Exchange Start
           paylaod reply we just got from the responder. The callback
           function will receive the processed payload where we will
@@ -369,6 +381,14 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
        * Phase 2
        */
       if (ctx->responder == TRUE) {
+       if (!ctx->packet) {
+         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+                           status));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, client->schedule, 0, 0);
+         return;
+       }
+
        /* Process the received Key Exchange 1 Payload packet from
           the initiator. This also creates our parts of the Diffie
           Hellman algorithm. The silc_client_protocol_ke_continue will
@@ -417,6 +437,14 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
        /* End the protocol on the next round */
        protocol->state = SILC_PROTOCOL_STATE_END;
       } else {
+       if (!ctx->packet) {
+         SILC_LOG_WARNING(("Error (type %d) during Key Exchange protocol",
+                           status));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, client->schedule, 0, 0);
+         return;
+       }
+
        /* Finish the protocol. This verifies the Key Exchange 2 payload
           sent by responder. The silc_client_protocol_ke_continue will
           be called after the public key has been verified. */
@@ -633,7 +661,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
        */
       unsigned char *auth_data = NULL;
       SilcUInt32 auth_data_len = 0;
-      unsigned char sign[1024];
+      unsigned char sign[2048 + 1];
 
       switch(ctx->auth_meth) {
       case SILC_AUTH_NONE:
@@ -740,7 +768,7 @@ silc_client_protocol_rekey_validate(SilcClient client,
                                    SilcClientRekeyInternalContext *ctx,
                                    SilcSocketConnection sock,
                                    SilcSKEKeyMaterial *keymat,
-                                   bool send)
+                                   SilcBool send)
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
 
@@ -791,7 +819,7 @@ silc_client_protocol_rekey_validate(SilcClient client,
 static void
 silc_client_protocol_rekey_generate(SilcClient client,
                                    SilcClientRekeyInternalContext *ctx,
-                                   bool send)
+                                   SilcBool send)
 {
   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
   SilcSKEKeyMaterial *keymat;
@@ -820,7 +848,7 @@ silc_client_protocol_rekey_generate(SilcClient client,
 static void
 silc_client_protocol_rekey_generate_pfs(SilcClient client,
                                        SilcClientRekeyInternalContext *ctx,
-                                       bool send)
+                                       SilcBool send)
 {
   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
   SilcSKEKeyMaterial *keymat;
@@ -903,6 +931,13 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
           * using the SKE protocol.
           */
 
+         if (!ctx->packet) {
+           SILC_LOG_WARNING(("Error during Re-key"));
+           protocol->state = SILC_PROTOCOL_STATE_ERROR;
+           silc_protocol_execute(protocol, client->schedule, 0, 300000);
+           return;
+         }
+
          if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
            /* Error in protocol */
            protocol->state = SILC_PROTOCOL_STATE_ERROR;
@@ -938,6 +973,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
           */
 
          /* Send the REKEY_DONE to indicate we will take new keys into use */
+         silc_client_packet_queue_purge(client, ctx->sock);
          silc_client_packet_send(client, ctx->sock,
                                  SILC_PACKET_REKEY_DONE,
                                  NULL, 0, NULL, NULL, NULL, 0, FALSE);
@@ -995,6 +1031,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
          /* Send the REKEY_DONE to indicate we will take new keys into use
             now. */
+         silc_client_packet_queue_purge(client, ctx->sock);
          silc_client_packet_send(client, ctx->sock,
                                  SILC_PACKET_REKEY_DONE,
                                  NULL, 0, NULL, NULL, NULL, 0, FALSE);
@@ -1040,6 +1077,13 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
        /*
         * The packet type must be KE packet
         */
+       if (!ctx->packet) {
+         SILC_LOG_WARNING(("Error during Re-key"));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, client->schedule, 0, 300000);
+         return;
+       }
+
        if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
          /* Error in protocol */
          protocol->state = SILC_PROTOCOL_STATE_ERROR;
@@ -1060,6 +1104,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
     /* Send the REKEY_DONE to indicate we will take new keys into use
        now. */
+    silc_client_packet_queue_purge(client, ctx->sock);
     silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
                            NULL, 0, NULL, NULL, NULL, 0, FALSE);
 
@@ -1067,6 +1112,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
        key to the new key since all packets after this packet must
        encrypted with the new key. */
     silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
+    silc_client_packet_queue_purge(client, ctx->sock);
 
     /* The protocol ends in next stage. */
     protocol->state = SILC_PROTOCOL_STATE_END;
@@ -1077,6 +1123,13 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
      * End protocol
      */
 
+    if (!ctx->packet) {
+      SILC_LOG_WARNING(("Error during Re-key"));
+      protocol->state = SILC_PROTOCOL_STATE_ERROR;
+      silc_protocol_execute(protocol, client->schedule, 0, 300000);
+      return;
+    }
+
     if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
       /* Error in protocol */
       protocol->state = SILC_PROTOCOL_STATE_ERROR;
@@ -1089,6 +1142,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
       silc_client_protocol_rekey_generate_pfs(client, ctx, FALSE);
     else
       silc_client_protocol_rekey_generate(client, ctx, FALSE);
+    silc_client_packet_queue_purge(client, ctx->sock);
 
     /* Protocol has ended, call the final callback */
     if (protocol->final_callback)