Return correct command type in SILCOPER in case of error.
[silc.git] / apps / silcd / protocol.c
index f232c3d84f94cb86384443fe1b7f766a502451d9..f20f13360303053feb36925a86ee6a4a1927c884 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2006 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
@@ -326,7 +326,7 @@ int silc_server_protocol_ke_set_keys(SilcServer server,
 SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
                                     SilcUInt32 len, void *context)
 {
-  SilcUInt32 l_protocol_version = 0, r_protocol_version = 0;
+  SilcUInt32 r_protocol_version = 0;
 
   SILC_LOG_INFO(("%s (%s) is version %s", ske->sock->hostname,
                 ske->sock->ip, version));
@@ -338,21 +338,6 @@ SilcSKEStatus silc_ske_check_version(SilcSKE ske, unsigned char *version,
     return SILC_SKE_STATUS_BAD_VERSION;
   }
 
-  if (!silc_parse_version_string(silc_version_string,
-                                &l_protocol_version, NULL, NULL,
-                                NULL, NULL)) {
-    SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version",
-                   ske->sock->hostname, ske->sock->ip, version));
-    return SILC_SKE_STATUS_BAD_VERSION;
-  }
-
-  /* If remote is too new, don't connect */
-  if (l_protocol_version < r_protocol_version) {
-    SILC_LOG_ERROR(("%s (%s) %s is not allowed/supported version",
-                   ske->sock->hostname, ske->sock->ip, version));
-    return SILC_SKE_STATUS_BAD_VERSION;
-  }
-
   ske->sock->version = r_protocol_version;
 
   return SILC_SKE_STATUS_OK;
@@ -436,6 +421,16 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
                             silc_ske_check_version, context);
 
       if (ctx->responder == TRUE) {
+       if (!ctx->packet) {
+         SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
+                         silc_ske_map_status(status), ctx->sock->hostname,
+                         ctx->sock->ip));
+
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, server->schedule, 0, 300000);
+         return;
+       }
+
        /* Start the key exchange by processing the received security
           properties packet from initiator. */
        SILC_LOG_DEBUG(("Process security property list (KE)"));
@@ -488,6 +483,16 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
        SILC_LOG_DEBUG(("Send security property list reply (KE)"));
        status = silc_ske_responder_phase_1(ctx->ske);
       } else {
+       if (!ctx->packet) {
+         SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
+                         silc_ske_map_status(status), ctx->sock->hostname,
+                         ctx->sock->ip));
+
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, server->schedule, 0, 300000);
+         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
@@ -522,6 +527,16 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
        * Phase 2
        */
       if (ctx->responder == TRUE) {
+       if (!ctx->packet) {
+         SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
+                         silc_ske_map_status(status), ctx->sock->hostname,
+                         ctx->sock->ip));
+
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, server->schedule, 0, 300000);
+         return;
+       }
+
        /* Process the received Key Exchange 1 Payload packet from
           the initiator. This also creates our parts of the Diffie
           Hellman algorithm. The silc_server_protocol_ke_continue
@@ -572,6 +587,16 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
        /* End the protocol on the next round */
        protocol->state = SILC_PROTOCOL_STATE_END;
       } else {
+       if (!ctx->packet) {
+         SILC_LOG_ERROR(("Error (%s) during Key Exchange protocol with %s (%s)",
+                         silc_ske_map_status(status), ctx->sock->hostname,
+                         ctx->sock->ip));
+
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, server->schedule, 0, 300000);
+         return;
+       }
+
        /* Finish the protocol. This verifies the Key Exchange 2 payload
           sent by responder. The silc_server_protocol_ke_continue will
           be called after the public key has been verified. */
@@ -653,7 +678,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
      */
 
     /* Send abort notification */
-    silc_ske_abort(ctx->ske, ctx->ske->status);
+    if (ctx->ske)
+      silc_ske_abort(ctx->ske, ctx->ske->status);
 
     /* Unregister the timeout task since the protocol has ended.
        This was the timeout task to be executed if the protocol is
@@ -892,6 +918,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
        SILC_LOG_INFO(("Performing authentication protocol for %s (%s)",
                       ctx->sock->hostname, ctx->sock->ip));
 
+       if (!ctx->packet) {
+         SILC_LOG_ERROR(("Bad authentication protocol request"));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, server->schedule, 0, 300000);
+         return;
+       }
+
        /* Parse the received authentication data packet. The received
           payload is Connection Auth Payload. */
        ret = silc_buffer_unformat(ctx->packet->buffer,
@@ -1360,6 +1393,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
           * using the SKE protocol.
           */
 
+         if (!ctx->packet) {
+           SILC_LOG_ERROR(("Error during Re-key, with %s (%s)",
+                           ctx->sock->hostname, ctx->sock->ip));
+           protocol->state = SILC_PROTOCOL_STATE_ERROR;
+           silc_protocol_execute(protocol, server->schedule, 0, 300000);
+           return;
+         }
+
          if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_1) {
            SILC_LOG_ERROR(("Error during Re-key (R PFS): re-key state is "
                            "incorrect (received %d, expected %d packet), "
@@ -1400,6 +1441,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
           */
 
          /* Send the REKEY_DONE to indicate we will take new keys into use */
+         silc_server_packet_queue_purge(server, ctx->sock);
          silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                                  0, NULL, 0, FALSE);
 
@@ -1456,6 +1498,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
 
          /* Send the REKEY_DONE to indicate we will take new keys into use
             now. */
+         silc_server_packet_queue_purge(server, ctx->sock);
          silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                                  0, NULL, 0, FALSE);
 
@@ -1499,6 +1542,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
        /*
         * The packet type must be KE packet
         */
+       if (!ctx->packet) {
+         SILC_LOG_ERROR(("Error during Re-key, with %s (%s)",
+                         ctx->sock->hostname, ctx->sock->ip));
+         protocol->state = SILC_PROTOCOL_STATE_ERROR;
+         silc_protocol_execute(protocol, server->schedule, 0, 300000);
+         return;
+       }
+
        if (ctx->packet->type != SILC_PACKET_KEY_EXCHANGE_2) {
          SILC_LOG_ERROR(("Error during Re-key (I PFS): re-key state is "
                          "incorrect (received %d, expected %d packet), "
@@ -1524,6 +1575,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
 
     /* Send the REKEY_DONE to indicate we will take new keys into use
        now. */
+    silc_server_packet_queue_purge(server, ctx->sock);
     silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                            0, NULL, 0, FALSE);
 
@@ -1531,6 +1583,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
        key to the new key since all packets after this packet must
        encrypted with the new key. */
     silc_server_protocol_rekey_generate_pfs(server, ctx, TRUE);
+    silc_server_packet_queue_purge(server, ctx->sock);
 
     /* The protocol ends in next stage. */
     protocol->state = SILC_PROTOCOL_STATE_END;
@@ -1541,6 +1594,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
      * End protocol
      */
 
+    if (!ctx->packet) {
+      SILC_LOG_ERROR(("Error during Re-key, with %s (%s)",
+                    ctx->sock->hostname, ctx->sock->ip));
+      protocol->state = SILC_PROTOCOL_STATE_ERROR;
+      silc_protocol_execute(protocol, server->schedule, 0, 300000);
+      return;
+    }
+
     if (ctx->packet->type != SILC_PACKET_REKEY_DONE) {
       SILC_LOG_ERROR(("Error during Re-key (%s PFS): re-key state is "
                      "incorrect (received %d, expected %d packet), "
@@ -1558,6 +1619,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
       silc_server_protocol_rekey_generate_pfs(server, ctx, FALSE);
     else
       silc_server_protocol_rekey_generate(server, ctx, FALSE);
+    silc_server_packet_queue_purge(server, ctx->sock);
 
     /* Assure that after calling final callback there cannot be pending
        executions for this protocol anymore. This just unregisters any
@@ -1576,7 +1638,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
      * Error occured
      */
 
-    if (ctx->pfs == TRUE)
+    if (ctx->pfs == TRUE && ctx->ske)
       /* Send abort notification */
       silc_ske_abort(ctx->ske, ctx->ske->status);