aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-10-03 20:51:34 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:31 -0400
commitbbd0d59809f923ea2b540cbd781b32110e249f6e (patch)
tree8a278cfa0e7bcc7b415e93baf6d1a93536efe17a
parent4cd57c8078fae0a4b1bf421191e94626d0cba92a (diff)
[SCTP]: Implement the receive and verification of AUTH chunk
This patch implements the receive path needed to process authenticated chunks. Add ability to process the AUTH chunk and handle edge cases for authenticated COOKIE-ECHO as well. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/constants.h4
-rw-r--r--include/net/sctp/sm.h1
-rw-r--r--include/net/sctp/structs.h8
-rw-r--r--net/sctp/associola.c10
-rw-r--r--net/sctp/endpointola.c29
-rw-r--r--net/sctp/input.c65
-rw-r--r--net/sctp/inqueue.c19
-rw-r--r--net/sctp/sm_statefuns.c218
-rw-r--r--net/sctp/sm_statetable.c33
9 files changed, 374 insertions, 13 deletions
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 777118f06dba..da8354e8e33c 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -183,7 +183,9 @@ typedef enum {
183 SCTP_IERROR_NO_DATA, 183 SCTP_IERROR_NO_DATA,
184 SCTP_IERROR_BAD_STREAM, 184 SCTP_IERROR_BAD_STREAM,
185 SCTP_IERROR_BAD_PORTS, 185 SCTP_IERROR_BAD_PORTS,
186 186 SCTP_IERROR_AUTH_BAD_HMAC,
187 SCTP_IERROR_AUTH_BAD_KEYID,
188 SCTP_IERROR_PROTO_VIOLATION,
187} sctp_ierror_t; 189} sctp_ierror_t;
188 190
189 191
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 148cdb4b9606..bf2f5ed69c15 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -143,6 +143,7 @@ sctp_state_fn_t sctp_sf_do_asconf_ack;
143sctp_state_fn_t sctp_sf_do_9_2_reshutack; 143sctp_state_fn_t sctp_sf_do_9_2_reshutack;
144sctp_state_fn_t sctp_sf_eat_fwd_tsn; 144sctp_state_fn_t sctp_sf_eat_fwd_tsn;
145sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast; 145sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
146sctp_state_fn_t sctp_sf_eat_auth;
146 147
147/* Prototypes for primitive event state functions. */ 148/* Prototypes for primitive event state functions. */
148sctp_state_fn_t sctp_sf_do_prm_asoc; 149sctp_state_fn_t sctp_sf_do_prm_asoc;
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 31841c3a7fe8..47e54f8e2b65 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -724,6 +724,13 @@ struct sctp_chunk {
724 */ 724 */
725 struct sctp_transport *transport; 725 struct sctp_transport *transport;
726 726
727 /* SCTP-AUTH: For the special case inbound processing of COOKIE-ECHO
728 * we need save a pointer to the AUTH chunk, since the SCTP-AUTH
729 * spec violates the principle premis that all chunks are processed
730 * in order.
731 */
732 struct sk_buff *auth_chunk;
733
727 __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */ 734 __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */
728 __u8 resent; /* Has this chunk ever been retransmitted. */ 735 __u8 resent; /* Has this chunk ever been retransmitted. */
729 __u8 has_tsn; /* Does this chunk have a TSN yet? */ 736 __u8 has_tsn; /* Does this chunk have a TSN yet? */
@@ -1067,6 +1074,7 @@ void sctp_inq_init(struct sctp_inq *);
1067void sctp_inq_free(struct sctp_inq *); 1074void sctp_inq_free(struct sctp_inq *);
1068void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet); 1075void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
1069struct sctp_chunk *sctp_inq_pop(struct sctp_inq *); 1076struct sctp_chunk *sctp_inq_pop(struct sctp_inq *);
1077struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *);
1070void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t); 1078void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t);
1071 1079
1072/* This is the structure we use to hold outbound chunks. You push 1080/* This is the structure we use to hold outbound chunks. You push
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 3bdd8dcb76a7..03158e3665da 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1011,6 +1011,16 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
1011 state = asoc->state; 1011 state = asoc->state;
1012 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); 1012 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
1013 1013
1014 /* SCTP-AUTH, Section 6.3:
1015 * The receiver has a list of chunk types which it expects
1016 * to be received only after an AUTH-chunk. This list has
1017 * been sent to the peer during the association setup. It
1018 * MUST silently discard these chunks if they are not placed
1019 * after an AUTH chunk in the packet.
1020 */
1021 if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
1022 continue;
1023
1014 /* Remember where the last DATA chunk came from so we 1024 /* Remember where the last DATA chunk came from so we
1015 * know where to send the SACK. 1025 * know where to send the SACK.
1016 */ 1026 */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index c8d5023606a5..2d2d81ef4a69 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -400,6 +400,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
400 sctp_subtype_t subtype; 400 sctp_subtype_t subtype;
401 sctp_state_t state; 401 sctp_state_t state;
402 int error = 0; 402 int error = 0;
403 int first_time = 1; /* is this the first time through the looop */
403 404
404 if (ep->base.dead) 405 if (ep->base.dead)
405 return; 406 return;
@@ -411,6 +412,29 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
411 while (NULL != (chunk = sctp_inq_pop(inqueue))) { 412 while (NULL != (chunk = sctp_inq_pop(inqueue))) {
412 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); 413 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
413 414
415 /* If the first chunk in the packet is AUTH, do special
416 * processing specified in Section 6.3 of SCTP-AUTH spec
417 */
418 if (first_time && (subtype.chunk == SCTP_CID_AUTH)) {
419 struct sctp_chunkhdr *next_hdr;
420
421 next_hdr = sctp_inq_peek(inqueue);
422 if (!next_hdr)
423 goto normal;
424
425 /* If the next chunk is COOKIE-ECHO, skip the AUTH
426 * chunk while saving a pointer to it so we can do
427 * Authentication later (during cookie-echo
428 * processing).
429 */
430 if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
431 chunk->auth_chunk = skb_clone(chunk->skb,
432 GFP_ATOMIC);
433 chunk->auth = 1;
434 continue;
435 }
436 }
437normal:
414 /* We might have grown an association since last we 438 /* We might have grown an association since last we
415 * looked, so try again. 439 * looked, so try again.
416 * 440 *
@@ -426,6 +450,8 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
426 } 450 }
427 451
428 state = asoc ? asoc->state : SCTP_STATE_CLOSED; 452 state = asoc ? asoc->state : SCTP_STATE_CLOSED;
453 if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
454 continue;
429 455
430 /* Remember where the last DATA chunk came from so we 456 /* Remember where the last DATA chunk came from so we
431 * know where to send the SACK. 457 * know where to send the SACK.
@@ -449,5 +475,8 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work)
449 */ 475 */
450 if (!sctp_sk(sk)->ep) 476 if (!sctp_sk(sk)->ep)
451 break; 477 break;
478
479 if (first_time)
480 first_time = 0;
452 } 481 }
453} 482}
diff --git a/net/sctp/input.c b/net/sctp/input.c
index f9a0c9276e3b..86503e7fa21e 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -911,15 +911,6 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
911 911
912 ch = (sctp_chunkhdr_t *) skb->data; 912 ch = (sctp_chunkhdr_t *) skb->data;
913 913
914 /* If this is INIT/INIT-ACK look inside the chunk too. */
915 switch (ch->type) {
916 case SCTP_CID_INIT:
917 case SCTP_CID_INIT_ACK:
918 break;
919 default:
920 return NULL;
921 }
922
923 /* The code below will attempt to walk the chunk and extract 914 /* The code below will attempt to walk the chunk and extract
924 * parameter information. Before we do that, we need to verify 915 * parameter information. Before we do that, we need to verify
925 * that the chunk length doesn't cause overflow. Otherwise, we'll 916 * that the chunk length doesn't cause overflow. Otherwise, we'll
@@ -964,6 +955,60 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
964 return NULL; 955 return NULL;
965} 956}
966 957
958/* SCTP-AUTH, Section 6.3:
959* If the receiver does not find a STCB for a packet containing an AUTH
960* chunk as the first chunk and not a COOKIE-ECHO chunk as the second
961* chunk, it MUST use the chunks after the AUTH chunk to look up an existing
962* association.
963*
964* This means that any chunks that can help us identify the association need
965* to be looked at to find this assocation.
966*
967* TODO: The only chunk currently defined that can do that is ASCONF, but we
968* don't support that functionality yet.
969*/
970static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb,
971 const union sctp_addr *paddr,
972 const union sctp_addr *laddr,
973 struct sctp_transport **transportp)
974{
975 /* XXX - walk through the chunks looking for something that can
976 * help us find the association. INIT, and INIT-ACK are not permitted.
977 * That leaves ASCONF, but we don't support that yet.
978 */
979 return NULL;
980}
981
982/*
983 * There are circumstances when we need to look inside the SCTP packet
984 * for information to help us find the association. Examples
985 * include looking inside of INIT/INIT-ACK chunks or after the AUTH
986 * chunks.
987 */
988static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb,
989 const union sctp_addr *paddr,
990 const union sctp_addr *laddr,
991 struct sctp_transport **transportp)
992{
993 sctp_chunkhdr_t *ch;
994
995 ch = (sctp_chunkhdr_t *) skb->data;
996
997 /* If this is INIT/INIT-ACK look inside the chunk too. */
998 switch (ch->type) {
999 case SCTP_CID_INIT:
1000 case SCTP_CID_INIT_ACK:
1001 return __sctp_rcv_init_lookup(skb, laddr, transportp);
1002 break;
1003
1004 case SCTP_CID_AUTH:
1005 return __sctp_rcv_auth_lookup(skb, paddr, laddr, transportp);
1006 break;
1007 }
1008
1009 return NULL;
1010}
1011
967/* Lookup an association for an inbound skb. */ 1012/* Lookup an association for an inbound skb. */
968static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb, 1013static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
969 const union sctp_addr *paddr, 1014 const union sctp_addr *paddr,
@@ -979,7 +1024,7 @@ static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
979 * parameters within the INIT or INIT-ACK. 1024 * parameters within the INIT or INIT-ACK.
980 */ 1025 */
981 if (!asoc) 1026 if (!asoc)
982 asoc = __sctp_rcv_init_lookup(skb, laddr, transportp); 1027 asoc = __sctp_rcv_lookup_harder(skb, paddr, laddr, transportp);
983 1028
984 return asoc; 1029 return asoc;
985} 1030}
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index e4ea7fdf36ed..f10fe7fbf24c 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -100,6 +100,25 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
100 q->immediate.func(&q->immediate); 100 q->immediate.func(&q->immediate);
101} 101}
102 102
103/* Peek at the next chunk on the inqeue. */
104struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *queue)
105{
106 struct sctp_chunk *chunk;
107 sctp_chunkhdr_t *ch = NULL;
108
109 chunk = queue->in_progress;
110 /* If there is no more chunks in this packet, say so */
111 if (chunk->singleton ||
112 chunk->end_of_packet ||
113 chunk->pdiscard)
114 return NULL;
115
116 ch = (sctp_chunkhdr_t *)chunk->chunk_end;
117
118 return ch;
119}
120
121
103/* Extract a chunk from an SCTP inqueue. 122/* Extract a chunk from an SCTP inqueue.
104 * 123 *
105 * WARNING: If you need to put the chunk on another queue, you need to 124 * WARNING: If you need to put the chunk on another queue, you need to
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 385486360fe9..5aef4aafdfdc 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -138,6 +138,11 @@ static sctp_disposition_t sctp_sf_violation_chunk(
138 void *arg, 138 void *arg,
139 sctp_cmd_seq_t *commands); 139 sctp_cmd_seq_t *commands);
140 140
141static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
142 const struct sctp_association *asoc,
143 const sctp_subtype_t type,
144 struct sctp_chunk *chunk);
145
141/* Small helper function that checks if the chunk length 146/* Small helper function that checks if the chunk length
142 * is of the appropriate length. The 'required_length' argument 147 * is of the appropriate length. The 'required_length' argument
143 * is set to be the size of a specific chunk we are testing. 148 * is set to be the size of a specific chunk we are testing.
@@ -495,8 +500,6 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
495 (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, 500 (sctp_init_chunk_t *)chunk->chunk_hdr, chunk,
496 &err_chunk)) { 501 &err_chunk)) {
497 502
498 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
499
500 /* This chunk contains fatal error. It is to be discarded. 503 /* This chunk contains fatal error. It is to be discarded.
501 * Send an ABORT, with causes if there is any. 504 * Send an ABORT, with causes if there is any.
502 */ 505 */
@@ -521,6 +524,22 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
521 sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); 524 sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
522 error = SCTP_ERROR_INV_PARAM; 525 error = SCTP_ERROR_INV_PARAM;
523 } 526 }
527
528 /* SCTP-AUTH, Section 6.3:
529 * It should be noted that if the receiver wants to tear
530 * down an association in an authenticated way only, the
531 * handling of malformed packets should not result in
532 * tearing down the association.
533 *
534 * This means that if we only want to abort associations
535 * in an authenticated way (i.e AUTH+ABORT), then we
536 * can't destory this association just becuase the packet
537 * was malformed.
538 */
539 if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
540 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
541
542 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
524 return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, 543 return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,
525 asoc, chunk->transport); 544 asoc, chunk->transport);
526 } 545 }
@@ -699,6 +718,36 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
699 if (error) 718 if (error)
700 goto nomem_init; 719 goto nomem_init;
701 720
721 /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
722 * is supposed to be authenticated and we have to do delayed
723 * authentication. We've just recreated the association using
724 * the information in the cookie and now it's much easier to
725 * do the authentication.
726 */
727 if (chunk->auth_chunk) {
728 struct sctp_chunk auth;
729 sctp_ierror_t ret;
730
731 /* set-up our fake chunk so that we can process it */
732 auth.skb = chunk->auth_chunk;
733 auth.asoc = chunk->asoc;
734 auth.sctp_hdr = chunk->sctp_hdr;
735 auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk,
736 sizeof(sctp_chunkhdr_t));
737 skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));
738 auth.transport = chunk->transport;
739
740 ret = sctp_sf_authenticate(ep, new_asoc, type, &auth);
741
742 /* We can now safely free the auth_chunk clone */
743 kfree_skb(chunk->auth_chunk);
744
745 if (ret != SCTP_IERROR_NO_ERROR) {
746 sctp_association_free(new_asoc);
747 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
748 }
749 }
750
702 repl = sctp_make_cookie_ack(new_asoc, chunk); 751 repl = sctp_make_cookie_ack(new_asoc, chunk);
703 if (!repl) 752 if (!repl)
704 goto nomem_init; 753 goto nomem_init;
@@ -3653,6 +3702,156 @@ gen_shutdown:
3653} 3702}
3654 3703
3655/* 3704/*
3705 * SCTP-AUTH Section 6.3 Receving authenticated chukns
3706 *
3707 * The receiver MUST use the HMAC algorithm indicated in the HMAC
3708 * Identifier field. If this algorithm was not specified by the
3709 * receiver in the HMAC-ALGO parameter in the INIT or INIT-ACK chunk
3710 * during association setup, the AUTH chunk and all chunks after it MUST
3711 * be discarded and an ERROR chunk SHOULD be sent with the error cause
3712 * defined in Section 4.1.
3713 *
3714 * If an endpoint with no shared key receives a Shared Key Identifier
3715 * other than 0, it MUST silently discard all authenticated chunks. If
3716 * the endpoint has at least one endpoint pair shared key for the peer,
3717 * it MUST use the key specified by the Shared Key Identifier if a
3718 * key has been configured for that Shared Key Identifier. If no
3719 * endpoint pair shared key has been configured for that Shared Key
3720 * Identifier, all authenticated chunks MUST be silently discarded.
3721 *
3722 * Verification Tag: 8.5 Verification Tag [Normal verification]
3723 *
3724 * The return value is the disposition of the chunk.
3725 */
3726static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
3727 const struct sctp_association *asoc,
3728 const sctp_subtype_t type,
3729 struct sctp_chunk *chunk)
3730{
3731 struct sctp_authhdr *auth_hdr;
3732 struct sctp_hmac *hmac;
3733 unsigned int sig_len;
3734 __u16 key_id;
3735 __u8 *save_digest;
3736 __u8 *digest;
3737
3738 /* Pull in the auth header, so we can do some more verification */
3739 auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
3740 chunk->subh.auth_hdr = auth_hdr;
3741 skb_pull(chunk->skb, sizeof(struct sctp_authhdr));
3742
3743 /* Make sure that we suport the HMAC algorithm from the auth
3744 * chunk.
3745 */
3746 if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id))
3747 return SCTP_IERROR_AUTH_BAD_HMAC;
3748
3749 /* Make sure that the provided shared key identifier has been
3750 * configured
3751 */
3752 key_id = ntohs(auth_hdr->shkey_id);
3753 if (key_id != asoc->active_key_id && !sctp_auth_get_shkey(asoc, key_id))
3754 return SCTP_IERROR_AUTH_BAD_KEYID;
3755
3756
3757 /* Make sure that the length of the signature matches what
3758 * we expect.
3759 */
3760 sig_len = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_auth_chunk_t);
3761 hmac = sctp_auth_get_hmac(ntohs(auth_hdr->hmac_id));
3762 if (sig_len != hmac->hmac_len)
3763 return SCTP_IERROR_PROTO_VIOLATION;
3764
3765 /* Now that we've done validation checks, we can compute and
3766 * verify the hmac. The steps involved are:
3767 * 1. Save the digest from the chunk.
3768 * 2. Zero out the digest in the chunk.
3769 * 3. Compute the new digest
3770 * 4. Compare saved and new digests.
3771 */
3772 digest = auth_hdr->hmac;
3773 skb_pull(chunk->skb, sig_len);
3774
3775 save_digest = kmemdup(digest, sig_len, GFP_ATOMIC);
3776 if (!save_digest)
3777 goto nomem;
3778
3779 memset(digest, 0, sig_len);
3780
3781 sctp_auth_calculate_hmac(asoc, chunk->skb,
3782 (struct sctp_auth_chunk *)chunk->chunk_hdr,
3783 GFP_ATOMIC);
3784
3785 /* Discard the packet if the digests do not match */
3786 if (memcmp(save_digest, digest, sig_len)) {
3787 kfree(save_digest);
3788 return SCTP_IERROR_BAD_SIG;
3789 }
3790
3791 kfree(save_digest);
3792 chunk->auth = 1;
3793
3794 return SCTP_IERROR_NO_ERROR;
3795nomem:
3796 return SCTP_IERROR_NOMEM;
3797}
3798
3799sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
3800 const struct sctp_association *asoc,
3801 const sctp_subtype_t type,
3802 void *arg,
3803 sctp_cmd_seq_t *commands)
3804{
3805 struct sctp_authhdr *auth_hdr;
3806 struct sctp_chunk *chunk = arg;
3807 struct sctp_chunk *err_chunk;
3808 sctp_ierror_t error;
3809
3810 if (!sctp_vtag_verify(chunk, asoc)) {
3811 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
3812 SCTP_NULL());
3813 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
3814 }
3815
3816 /* Make sure that the AUTH chunk has valid length. */
3817 if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk)))
3818 return sctp_sf_violation_chunklen(ep, asoc, type, arg,
3819 commands);
3820
3821 auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
3822 error = sctp_sf_authenticate(ep, asoc, type, chunk);
3823 switch (error) {
3824 case SCTP_IERROR_AUTH_BAD_HMAC:
3825 /* Generate the ERROR chunk and discard the rest
3826 * of the packet
3827 */
3828 err_chunk = sctp_make_op_error(asoc, chunk,
3829 SCTP_ERROR_UNSUP_HMAC,
3830 &auth_hdr->hmac_id,
3831 sizeof(__u16));
3832 if (err_chunk) {
3833 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
3834 SCTP_CHUNK(err_chunk));
3835 }
3836 /* Fall Through */
3837 case SCTP_IERROR_AUTH_BAD_KEYID:
3838 case SCTP_IERROR_BAD_SIG:
3839 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
3840 break;
3841 case SCTP_IERROR_PROTO_VIOLATION:
3842 return sctp_sf_violation_chunklen(ep, asoc, type, arg,
3843 commands);
3844 break;
3845 case SCTP_IERROR_NOMEM:
3846 return SCTP_DISPOSITION_NOMEM;
3847 default:
3848 break;
3849 }
3850
3851 return SCTP_DISPOSITION_CONSUME;
3852}
3853
3854/*
3656 * Process an unknown chunk. 3855 * Process an unknown chunk.
3657 * 3856 *
3658 * Section: 3.2. Also, 2.1 in the implementor's guide. 3857 * Section: 3.2. Also, 2.1 in the implementor's guide.
@@ -3857,6 +4056,20 @@ static sctp_disposition_t sctp_sf_abort_violation(
3857 if (!abort) 4056 if (!abort)
3858 goto nomem; 4057 goto nomem;
3859 4058
4059 /* SCTP-AUTH, Section 6.3:
4060 * It should be noted that if the receiver wants to tear
4061 * down an association in an authenticated way only, the
4062 * handling of malformed packets should not result in
4063 * tearing down the association.
4064 *
4065 * This means that if we only want to abort associations
4066 * in an authenticated way (i.e AUTH+ABORT), then we
4067 * can't destory this association just becuase the packet
4068 * was malformed.
4069 */
4070 if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
4071 goto discard;
4072
3860 if (asoc) { 4073 if (asoc) {
3861 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 4074 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
3862 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); 4075 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
@@ -3894,6 +4107,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
3894 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); 4107 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
3895 } 4108 }
3896 4109
4110discard:
3897 sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); 4111 sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
3898 4112
3899 SCTP_INC_STATS(SCTP_MIB_ABORTEDS); 4113 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index ddb0ba3974b0..a93a4bc8f68f 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -523,6 +523,34 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN
523 TYPE_SCTP_FWD_TSN, 523 TYPE_SCTP_FWD_TSN,
524}; /*state_fn_t prsctp_chunk_event_table[][] */ 524}; /*state_fn_t prsctp_chunk_event_table[][] */
525 525
526#define TYPE_SCTP_AUTH { \
527 /* SCTP_STATE_EMPTY */ \
528 TYPE_SCTP_FUNC(sctp_sf_ootb), \
529 /* SCTP_STATE_CLOSED */ \
530 TYPE_SCTP_FUNC(sctp_sf_ootb), \
531 /* SCTP_STATE_COOKIE_WAIT */ \
532 TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
533 /* SCTP_STATE_COOKIE_ECHOED */ \
534 TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
535 /* SCTP_STATE_ESTABLISHED */ \
536 TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
537 /* SCTP_STATE_SHUTDOWN_PENDING */ \
538 TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
539 /* SCTP_STATE_SHUTDOWN_SENT */ \
540 TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
541 /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
542 TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
543 /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
544 TYPE_SCTP_FUNC(sctp_sf_eat_auth), \
545} /* TYPE_SCTP_AUTH */
546
547/* The primary index for this table is the chunk type.
548 * The secondary index for this table is the state.
549 */
550static const sctp_sm_table_entry_t auth_chunk_event_table[SCTP_NUM_AUTH_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
551 TYPE_SCTP_AUTH,
552}; /*state_fn_t auth_chunk_event_table[][] */
553
526static const sctp_sm_table_entry_t 554static const sctp_sm_table_entry_t
527chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { 555chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
528 /* SCTP_STATE_EMPTY */ 556 /* SCTP_STATE_EMPTY */
@@ -976,5 +1004,10 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
976 return &addip_chunk_event_table[1][state]; 1004 return &addip_chunk_event_table[1][state];
977 } 1005 }
978 1006
1007 if (sctp_auth_enable) {
1008 if (cid == SCTP_CID_AUTH)
1009 return &auth_chunk_event_table[0][state];
1010 }
1011
979 return &chunk_event_table_unknown[state]; 1012 return &chunk_event_table_unknown[state];
980} 1013}