re-introduced the XAUTH_VID compile option
[strongswan.git] / src / pluto / ipsec_doi.c
index 9323427..14aec44 100644 (file)
@@ -80,7 +80,7 @@
 #endif /* !VENDORID */
 
 /*
- * are we sending an XAUTH VID (Cisco Mode Config Interoperability)?
+ * are we sending an XAUTH VID?
  */
 #ifdef XAUTH_VID
 #define SEND_XAUTH_VID 1
 #define SEND_XAUTH_VID 0
 #endif /* !XAUTH_VID */
 
+/*
+ * are we sending a Cisco Unity VID?
+ */
+#ifdef CISCO_QUIRKS
+#define SEND_CISCO_UNITY_VID   1
+#else /* !CISCO_QUIRKS */
+#define SEND_CISCO_UNITY_VID   0
+#endif /* !CISCO_QUIRKS */
+
 /* MAGIC: perform f, a function that returns notification_t
  * and return from the ENCLOSING stf_status returning function if it fails.
  */
@@ -453,9 +462,11 @@ send_notification_from_state(struct state *st, enum state_kind state,
     if (state == STATE_UNDEFINED)
        state = st->st_state;
 
-    if (IS_QUICK(state)) {
+    if (IS_QUICK(state))
+    {
        p1st = find_phase1_state(st->st_connection, ISAKMP_SA_ESTABLISHED_STATES);
-       if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state))) {
+       if ((p1st == NULL) || (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)))
+       {
            loglog(RC_LOG_SERIOUS,
                "no Phase1 state for Quick mode notification");
            return;
@@ -463,11 +474,13 @@ send_notification_from_state(struct state *st, enum state_kind state,
        send_notification(st, type, p1st, generate_msgid(p1st),
            st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
     }
-    else if (IS_ISAKMP_ENCRYPTED(state)) {
+    else if (IS_ISAKMP_ENCRYPTED(state) && st->st_enc_key.ptr != NULL)
+    {
        send_notification(st, type, st, generate_msgid(st),
            st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
     }
-    else {
+    else
+    {
        /* no ISAKMP SA established - don't encrypt notification */
        send_notification(st, type, NULL, 0,
            st->st_icookie, st->st_rcookie, NULL, 0, PROTO_ISAKMP);
@@ -891,10 +904,12 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
     /* determine how many Vendor ID payloads we will be sending */
     if (SEND_PLUTO_VID)
        vids_to_send++;
-    if (SEND_XAUTH_VID)
+    if (SEND_CISCO_UNITY_VID)
        vids_to_send++;
     if (c->spd.this.cert.type == CERT_PGP)
        vids_to_send++;
+    if (SEND_XAUTH_VID)
+       vids_to_send++;
     /* always send DPD Vendor ID */
        vids_to_send++;
     if (nat_traversal_enabled)
@@ -939,8 +954,8 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
        u_char *sa_start = rbody.cur;
        lset_t auth_policy = policy & POLICY_ID_AUTH_MASK;
 
-       if (!out_sa(&rbody, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
-       , st, TRUE, vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
+       if (!out_sa(&rbody, &oakley_sadb, st, TRUE
+       , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
        {
            reset_cur_state();
            return STF_INTERNAL_ERROR;
@@ -963,17 +978,16 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
        }
     }
 
-    /* if enabled send XAUTH Vendor ID */
-    if (SEND_XAUTH_VID)
+    /* if enabled send Cisco Unity Vendor ID */
+    if (SEND_CISCO_UNITY_VID)
     {
        if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
-       , &rbody, VID_MISC_XAUTH))
+       , &rbody, VID_CISCO_UNITY))
        {
            reset_cur_state();
            return STF_INTERNAL_ERROR;
        }
     }
-
     /* if we  have an OpenPGP certificate we assume an
      * OpenPGP peer and have to send the Vendor ID
      */
@@ -987,6 +1001,17 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
        }
     }
 
+    /* Announce our ability to do eXtended AUTHentication to the peer */
+    if (SEND_XAUTH_VID)
+    {
+       if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+       , &rbody, VID_MISC_XAUTH))
+       {
+           reset_cur_state();
+           return STF_INTERNAL_ERROR;
+       }
+    }
+
     /* Announce our ability to do Dead Peer Detection to the peer */
     {
        if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
@@ -1190,11 +1215,15 @@ generate_skeyids_iv(struct state *st)
     switch (st->st_oakley.auth)
     {
        case OAKLEY_PRESHARED_KEY:
+       case XAUTHInitPreShared:
+       case XAUTHRespPreShared:
            if (!skeyid_preshared(st))
                return FALSE;
            break;
 
        case OAKLEY_RSA_SIG:
+       case XAUTHInitRSA:
+       case XAUTHRespRSA:
            if (!skeyid_digisig(st))
                return FALSE;
            break;
@@ -1759,7 +1788,7 @@ RSA_check_signature(const struct id* peer
     {
        char id_buf[BUF_LEN];   /* arbitrary limit on length of ID reported */
 
-       (void) idtoa(&st->st_connection->spd.that.id, id_buf, sizeof(id_buf));
+       (void) idtoa(peer, id_buf, sizeof(id_buf));
 
        if (s.best_ugh == NULL)
        {
@@ -2462,7 +2491,7 @@ switch_connection(struct msg_digest *md, struct id *peer, bool initiator)
        DBG(DBG_CONTROL,
            char buf[BUF_LEN];
 
-           dntoa_or_null(buf, BUF_LEN, c->spd.this.ca, "%none");
+           dntoa_or_null(buf, BUF_LEN, c->spd.that.ca, "%none");
            DBG_log("required CA:  '%s'", buf);
         )
 
@@ -2950,8 +2979,7 @@ main_inI1_outR1(struct msg_digest *md)
 {
     struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
     struct state *st;
-    struct connection *c = find_host_connection(&md->iface->addr, pluto_port
-                               , &md->sender, md->sender_port, LEMPTY);
+    struct connection *c;
     struct isakmp_proposal proposal;
     pb_stream proposal_pbs;
     pb_stream r_sa_pbs;
@@ -2959,13 +2987,27 @@ main_inI1_outR1(struct msg_digest *md)
     lset_t policy = LEMPTY;
     int vids_to_send = 0;
 
+    /* We preparse the peer's proposal in order to determine
+     * the requested authentication policy (RSA or PSK)
+     */
     RETURN_STF_FAILURE(preparse_isakmp_sa_body(&sa_pd->payload.sa
        , &sa_pd->pbs, &ipsecdoisit, &proposal_pbs, &proposal));
 
+    backup_pbs(&proposal_pbs);
+    RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
+                    , proposal.isap_notrans, &policy));
+    restore_pbs(&proposal_pbs);
+
+    /* We are only considering candidate connections that match
+     * the requested authentication policy (RSA or PSK)
+     */
+    c = find_host_connection(&md->iface->addr, pluto_port
+                          , &md->sender, md->sender_port, policy);
+
     if (c == NULL && md->iface->ike_float)
     {
        c = find_host_connection(&md->iface->addr, NAT_T_IKE_FLOAT_PORT
-               , &md->sender, md->sender_port, LEMPTY);
+               , &md->sender, md->sender_port, policy);
     }
 
     if (c == NULL)
@@ -2983,11 +3025,6 @@ main_inI1_outR1(struct msg_digest *md)
        {
            struct connection *d;
 
-           backup_pbs(&proposal_pbs);
-           RETURN_STF_FAILURE(parse_isakmp_policy(&proposal_pbs
-               , proposal.isap_notrans, &policy));
-           restore_pbs(&proposal_pbs);
-
            d = find_host_connection(&md->iface->addr
                , pluto_port, (ip_address*)NULL, md->sender_port, policy);
 
@@ -3040,6 +3077,13 @@ main_inI1_outR1(struct msg_digest *md)
            c = rw_instantiate(c, &md->sender, md->sender_port, NULL, NULL);
        }
     }
+    else if (c->kind == CK_TEMPLATE)
+    {
+       /* Create an instance
+        * This is a rare case: wildcard peer ID but static peer IP address
+        */
+        c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id);
+    }
 
     /* Set up state */
     md->st = st = new_state();
@@ -3078,10 +3122,12 @@ main_inI1_outR1(struct msg_digest *md)
     /* determine how many Vendor ID payloads we will be sending */
     if (SEND_PLUTO_VID)
        vids_to_send++;
-    if (SEND_XAUTH_VID)
+    if (SEND_CISCO_UNITY_VID)
        vids_to_send++;
     if (md->openpgp)
        vids_to_send++;
+    if (SEND_XAUTH_VID)
+       vids_to_send++;
     /* always send DPD Vendor ID */
        vids_to_send++;
     if (md->nat_traversal_vid && nat_traversal_enabled)
@@ -3113,7 +3159,7 @@ main_inI1_outR1(struct msg_digest *md)
 
     /* SA body in and out */
     RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs
-       ,&proposal, &r_sa_pbs, st));
+       ,&proposal, &r_sa_pbs, st, FALSE));
 
     /* if enabled send Pluto Vendor ID */
     if (SEND_PLUTO_VID)
@@ -3125,11 +3171,11 @@ main_inI1_outR1(struct msg_digest *md)
        }
     }
 
-    /* if enabled send XAUTH Vendor ID */
-    if (SEND_XAUTH_VID)
+    /* if enabled send Cisco Unity Vendor ID */
+    if (SEND_CISCO_UNITY_VID)
     {
        if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
-       , &md->rbody, VID_MISC_XAUTH))
+       , &md->rbody, VID_CISCO_UNITY))
        {
            return STF_INTERNAL_ERROR;
        }
@@ -3147,15 +3193,23 @@ main_inI1_outR1(struct msg_digest *md)
        }
     }
 
-    /* Announce our ability to do Dead Peer Detection to the peer */
+    /* Announce our ability to do eXtended AUTHentication to the peer */
+    if (SEND_XAUTH_VID)
     {
        if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
-       , &md->rbody, VID_MISC_DPD))
+       , &md->rbody, VID_MISC_XAUTH))
        {
            return STF_INTERNAL_ERROR;
        }
     }
 
+    /* Announce our ability to do Dead Peer Detection to the peer */
+    if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
+    , &md->rbody, VID_MISC_DPD))
+    {
+       return STF_INTERNAL_ERROR;
+    }
+
     if (md->nat_traversal_vid && nat_traversal_enabled)
     {
        /* reply if NAT-Traversal draft is supported */
@@ -3210,7 +3264,7 @@ main_inR1_outI2(struct msg_digest *md)
            RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX);
         }
        RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
-           , &proposal_pbs, &proposal, NULL, st));
+           , &proposal_pbs, &proposal, NULL, st, TRUE));
     }
 
     if (nat_traversal_enabled && md->nat_traversal_vid)
@@ -3295,9 +3349,11 @@ main_inI2_outR2(struct msg_digest *md)
     pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
  
     /* send CR if auth is RSA and no preloaded RSA public key exists*/
-    bool send_cr = !no_cr_send && (st->st_oakley.auth == OAKLEY_RSA_SIG) &&
-                  !has_preloaded_public_key(st);
-   
+    bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+                || st->st_oakley.auth == XAUTHInitRSA
+                || st->st_oakley.auth == XAUTHRespRSA;
+    bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st);
+
     u_int8_t np = ISAKMP_NEXT_NONE;
 
     /* KE in */
@@ -3432,14 +3488,18 @@ main_inR2_outI3(struct msg_digest *md)
 {
     struct state *const st = md->st;
     pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
-    int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
-       ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
     pb_stream id_pbs;  /* ID Payload; also used for hash calculation */
 
     certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
     cert_t mycert = st->st_connection->spd.this.cert;
     bool requested, send_cert, send_cr;
 
+    bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+                || st->st_oakley.auth == XAUTHInitRSA
+                || st->st_oakley.auth == XAUTHRespRSA;
+
+    int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
+
     /* KE in */
     RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
 
@@ -3461,31 +3521,29 @@ main_inR2_outI3(struct msg_digest *md)
      */
     requested = cert_policy == CERT_SEND_IF_ASKED
                && st->st_connection->got_certrequest;
-    send_cert = st->st_oakley.auth == OAKLEY_RSA_SIG
-               && mycert.type != CERT_NONE
+    send_cert = RSA_auth && mycert.type != CERT_NONE
                && (cert_policy == CERT_ALWAYS_SEND || requested);
 
     /* send certificate request if we don't have a preloaded RSA public key */
     send_cr = !no_cr_send && send_cert && !has_preloaded_public_key(st);
 
     /* done parsing; initialize crypto  */
-
     compute_dh_shared(st, st->st_gr, st->st_oakley.group);
     if (!generate_skeyids_iv(st))
        return STF_FAIL + AUTHENTICATION_FAILED;
 
-       if (st->nat_traversal & NAT_T_WITH_NATD)
-       {
-           nat_traversal_natd_lookup(md);
-       }
-       if (st->nat_traversal)
-       {
-           nat_traversal_show_result(st->nat_traversal, md->sender_port);
-       }
-       if (st->nat_traversal & NAT_T_WITH_KA)
-       {
-           nat_traversal_new_ka_event();
-       }
+    if (st->nat_traversal & NAT_T_WITH_NATD)
+    {
+       nat_traversal_natd_lookup(md);
+    }
+    if (st->nat_traversal)
+    {
+       nat_traversal_show_result(st->nat_traversal, md->sender_port);
+    }
+    if (st->nat_traversal & NAT_T_WITH_KA)
+    {
+       nat_traversal_new_ka_event();
+    }
 
     /*************** build output packet HDR*;IDii;HASH/SIG_I ***************/
     /* ??? NOTE: this is almost the same as main_inI3_outR3's code */
@@ -3506,7 +3564,7 @@ main_inR2_outI3(struct msg_digest *md)
     }
 
     /* CERT out */
-    if ( st->st_oakley.auth == OAKLEY_RSA_SIG)
+    if (RSA_auth)
     {
        DBG(DBG_CONTROL,
            DBG_log("our certificate policy is %s"
@@ -3662,6 +3720,8 @@ main_id_and_auth(struct msg_digest *md
     switch (st->st_oakley.auth)
     {
     case OAKLEY_PRESHARED_KEY:
+    case XAUTHInitPreShared:
+    case XAUTHRespPreShared:
        {
            pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
 
@@ -3678,6 +3738,8 @@ main_id_and_auth(struct msg_digest *md
        break;
 
     case OAKLEY_RSA_SIG:
+    case XAUTHInitRSA:
+    case XAUTHRespRSA:
        r = RSA_check_signature(&peer, st, hash_val, hash_len
            , &md->chain[ISAKMP_NEXT_SIG]->pbs
 #ifdef USE_KEYRR
@@ -3855,6 +3917,7 @@ main_inI3_outR3_tail(struct msg_digest *md
     pb_stream r_id_pbs;        /* ID Payload; also used for hash calculation */
     certpolicy_t cert_policy;
     cert_t mycert;
+    bool RSA_auth;
     bool send_cert;
     bool requested;
 
@@ -3877,7 +3940,10 @@ main_inI3_outR3_tail(struct msg_digest *md
     mycert = st->st_connection->spd.this.cert;
     requested = cert_policy == CERT_SEND_IF_ASKED
                && st->st_connection->got_certrequest;
-    send_cert = st->st_oakley.auth == OAKLEY_RSA_SIG
+    RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+           || st->st_oakley.auth == XAUTHInitRSA
+            || st->st_oakley.auth == XAUTHRespRSA;
+    send_cert = RSA_auth
                && mycert.type != CERT_NONE
                && (cert_policy == CERT_ALWAYS_SEND || requested);
 
@@ -3895,8 +3961,7 @@ main_inI3_outR3_tail(struct msg_digest *md
      */
     echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
 
-    auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
-       ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
+    auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
 
     /* IDir out */
     {
@@ -3915,7 +3980,7 @@ main_inI3_outR3_tail(struct msg_digest *md
     }
 
     /* CERT out */
-    if (st->st_oakley.auth == OAKLEY_RSA_SIG)
+    if (RSA_auth)
     {
        DBG(DBG_CONTROL,
            DBG_log("our certificate policy is %s"