aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_statefuns.c
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 /net/sctp/sm_statefuns.c
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>
Diffstat (limited to 'net/sctp/sm_statefuns.c')
-rw-r--r--net/sctp/sm_statefuns.c218
1 files changed, 216 insertions, 2 deletions
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);