ikev1: Add an option to accept unencrypted ID/HASH payloads
authorMartin Willi <martin@revosec.ch>
Mon, 14 Apr 2014 12:42:27 +0000 (14:42 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 17 Apr 2014 06:52:28 +0000 (08:52 +0200)
Even in Main Mode, some Sonicwall boxes seem to send ID/HASH payloads in
unencrypted form, probably to allow PSK lookup based on the ID payloads. We
by default reject that, but accept it if the
charon.accept_unencrypted_mainmode_messages option is set in strongswan.conf.

Initial patch courtesy of Paul Stewart.

conf/options/charon.opt
src/libcharon/encoding/message.c

index c6f4f1e..aaf4fdc 100644 (file)
@@ -8,6 +8,21 @@ charon {}
        **charon-cmd** instead of **charon**). For many options defaults can be
        defined in the **libstrongswan** section.
 
+charon.accept_unencrypted_mainmode_messages = no
+       Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+
+       Accept unencrypted ID and HASH payloads in IKEv1 Main Mode.
+
+       Some implementations send the third Main Mode message unencrypted, probably
+       to find the PSKs for the specified ID for authentication. This is very
+       similar to Aggressive Mode, and has the same security implications: A
+       passive attacker can sniff the negotiated Identity, and start brute forcing
+       the PSK using the HASH payload.
+
+       It is recommended to keep this option to no, unless you know exactly
+       what the implications are and require compatibility to such devices (for
+       example, some SonicWall boxes).
+
 charon.block_threshold = 5
        Maximum number of half-open IKE_SAs for a single peer IP.
 
index 11e735a..3a1014e 100644 (file)
@@ -1923,6 +1923,24 @@ static status_t decrypt_and_extract(private_message_t *this, keymat_t *keymat,
 }
 
 /**
+ * Do we accept unencrypted ID/HASH payloads in Main Mode, as seen from
+ * some SonicWall boxes?
+ */
+static bool accept_unencrypted_mm(private_message_t *this, payload_type_t type)
+{
+       if (this->exchange_type == ID_PROT)
+       {
+               if (type == ID_V1 || type == HASH_V1)
+               {
+                       return lib->settings->get_bool(lib->settings,
+                                                                       "%s.accept_unencrypted_mainmode_messages",
+                                                                       FALSE, lib->ns);
+               }
+       }
+       return FALSE;
+}
+
+/**
  * Decrypt payload from the encryption payload
  */
 static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
@@ -1978,7 +1996,8 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
                        this->exchange_type != AGGRESSIVE)
                {
                        rule = get_payload_rule(this, type);
-                       if (!rule || rule->encrypted)
+                       if ((!rule || rule->encrypted) &&
+                               !accept_unencrypted_mm(this, type))
                        {
                                DBG1(DBG_ENC, "payload type %N was not encrypted",
                                         payload_type_names, type);