Merge tag 'selinux-pr-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git...
[muen/linux.git] / net / sctp / sm_statefuns.c
index 42659ab68c381053c5302a1999461244f1dcc7ad..dd0594a109610eac4b92c4932e9d81299d0d957e 100644 (file)
@@ -664,7 +664,7 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
                                         void *arg,
                                         struct sctp_cmd_seq *commands)
 {
                                         void *arg,
                                         struct sctp_cmd_seq *commands)
 {
-       struct sctp_ulpevent *ev, *ai_ev = NULL;
+       struct sctp_ulpevent *ev, *ai_ev = NULL, *auth_ev = NULL;
        struct sctp_association *new_asoc;
        struct sctp_init_chunk *peer_init;
        struct sctp_chunk *chunk = arg;
        struct sctp_association *new_asoc;
        struct sctp_init_chunk *peer_init;
        struct sctp_chunk *chunk = arg;
@@ -825,6 +825,14 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
                        goto nomem_aiev;
        }
 
                        goto nomem_aiev;
        }
 
+       if (!new_asoc->peer.auth_capable) {
+               auth_ev = sctp_ulpevent_make_authkey(new_asoc, 0,
+                                                    SCTP_AUTH_NO_AUTH,
+                                                    GFP_ATOMIC);
+               if (!auth_ev)
+                       goto nomem_authev;
+       }
+
        /* Add all the state machine commands now since we've created
         * everything.  This way we don't introduce memory corruptions
         * during side-effect processing and correclty count established
        /* Add all the state machine commands now since we've created
         * everything.  This way we don't introduce memory corruptions
         * during side-effect processing and correclty count established
@@ -852,8 +860,14 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                SCTP_ULPEVENT(ai_ev));
 
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                SCTP_ULPEVENT(ai_ev));
 
+       if (auth_ev)
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                               SCTP_ULPEVENT(auth_ev));
+
        return SCTP_DISPOSITION_CONSUME;
 
        return SCTP_DISPOSITION_CONSUME;
 
+nomem_authev:
+       sctp_ulpevent_free(ai_ev);
 nomem_aiev:
        sctp_ulpevent_free(ev);
 nomem_ev:
 nomem_aiev:
        sctp_ulpevent_free(ev);
 nomem_ev:
@@ -961,6 +975,15 @@ enum sctp_disposition sctp_sf_do_5_1E_ca(struct net *net,
                                SCTP_ULPEVENT(ev));
        }
 
                                SCTP_ULPEVENT(ev));
        }
 
+       if (!asoc->peer.auth_capable) {
+               ev = sctp_ulpevent_make_authkey(asoc, 0, SCTP_AUTH_NO_AUTH,
+                                               GFP_ATOMIC);
+               if (!ev)
+                       goto nomem;
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                               SCTP_ULPEVENT(ev));
+       }
+
        return SCTP_DISPOSITION_CONSUME;
 nomem:
        return SCTP_DISPOSITION_NOMEM;
        return SCTP_DISPOSITION_CONSUME;
 nomem:
        return SCTP_DISPOSITION_NOMEM;
@@ -1921,6 +1944,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_b(
        if (asoc->peer.adaptation_ind)
                sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL());
 
        if (asoc->peer.adaptation_ind)
                sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL());
 
+       if (!asoc->peer.auth_capable)
+               sctp_add_cmd_sf(commands, SCTP_CMD_PEER_NO_AUTH, SCTP_NULL());
+
        return SCTP_DISPOSITION_CONSUME;
 
 nomem:
        return SCTP_DISPOSITION_CONSUME;
 
 nomem:
@@ -1967,7 +1993,7 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
                                        struct sctp_cmd_seq *commands,
                                        struct sctp_association *new_asoc)
 {
                                        struct sctp_cmd_seq *commands,
                                        struct sctp_association *new_asoc)
 {
-       struct sctp_ulpevent *ev = NULL, *ai_ev = NULL;
+       struct sctp_ulpevent *ev = NULL, *ai_ev = NULL, *auth_ev = NULL;
        struct sctp_chunk *repl;
 
        /* Clarification from Implementor's Guide:
        struct sctp_chunk *repl;
 
        /* Clarification from Implementor's Guide:
@@ -2014,6 +2040,14 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
                                goto nomem;
 
                }
                                goto nomem;
 
                }
+
+               if (!asoc->peer.auth_capable) {
+                       auth_ev = sctp_ulpevent_make_authkey(asoc, 0,
+                                                            SCTP_AUTH_NO_AUTH,
+                                                            GFP_ATOMIC);
+                       if (!auth_ev)
+                               goto nomem;
+               }
        }
 
        repl = sctp_make_cookie_ack(new_asoc, chunk);
        }
 
        repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -2028,10 +2062,15 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
        if (ai_ev)
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                        SCTP_ULPEVENT(ai_ev));
        if (ai_ev)
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                        SCTP_ULPEVENT(ai_ev));
+       if (auth_ev)
+               sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+                               SCTP_ULPEVENT(auth_ev));
 
        return SCTP_DISPOSITION_CONSUME;
 
 nomem:
 
        return SCTP_DISPOSITION_CONSUME;
 
 nomem:
+       if (auth_ev)
+               sctp_ulpevent_free(auth_ev);
        if (ai_ev)
                sctp_ulpevent_free(ai_ev);
        if (ev)
        if (ai_ev)
                sctp_ulpevent_free(ai_ev);
        if (ev)
@@ -4132,6 +4171,7 @@ static enum sctp_ierror sctp_sf_authenticate(
                                        const union sctp_subtype type,
                                        struct sctp_chunk *chunk)
 {
                                        const union sctp_subtype type,
                                        struct sctp_chunk *chunk)
 {
+       struct sctp_shared_key *sh_key = NULL;
        struct sctp_authhdr *auth_hdr;
        __u8 *save_digest, *digest;
        struct sctp_hmac *hmac;
        struct sctp_authhdr *auth_hdr;
        __u8 *save_digest, *digest;
        struct sctp_hmac *hmac;
@@ -4153,9 +4193,11 @@ static enum sctp_ierror sctp_sf_authenticate(
         * configured
         */
        key_id = ntohs(auth_hdr->shkey_id);
         * configured
         */
        key_id = ntohs(auth_hdr->shkey_id);
-       if (key_id != asoc->active_key_id && !sctp_auth_get_shkey(asoc, key_id))
-               return SCTP_IERROR_AUTH_BAD_KEYID;
-
+       if (key_id != asoc->active_key_id) {
+               sh_key = sctp_auth_get_shkey(asoc, key_id);
+               if (!sh_key)
+                       return SCTP_IERROR_AUTH_BAD_KEYID;
+       }
 
        /* Make sure that the length of the signature matches what
         * we expect.
 
        /* Make sure that the length of the signature matches what
         * we expect.
@@ -4184,7 +4226,7 @@ static enum sctp_ierror sctp_sf_authenticate(
 
        sctp_auth_calculate_hmac(asoc, chunk->skb,
                                 (struct sctp_auth_chunk *)chunk->chunk_hdr,
 
        sctp_auth_calculate_hmac(asoc, chunk->skb,
                                 (struct sctp_auth_chunk *)chunk->chunk_hdr,
-                                GFP_ATOMIC);
+                                sh_key, GFP_ATOMIC);
 
        /* Discard the packet if the digests do not match */
        if (memcmp(save_digest, digest, sig_len)) {
 
        /* Discard the packet if the digests do not match */
        if (memcmp(save_digest, digest, sig_len)) {
@@ -4261,7 +4303,7 @@ enum sctp_disposition sctp_sf_eat_auth(struct net *net,
                struct sctp_ulpevent *ev;
 
                ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id),
                struct sctp_ulpevent *ev;
 
                ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id),
-                                   SCTP_AUTH_NEWKEY, GFP_ATOMIC);
+                                   SCTP_AUTH_NEW_KEY, GFP_ATOMIC);
 
                if (!ev)
                        return -ENOMEM;
 
                if (!ev)
                        return -ENOMEM;