Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Vlad Yasevich and committed by
David S. Miller
bbd0d598 4cd57c80

+374 -13
+3 -1
include/net/sctp/constants.h
··· 183 183 SCTP_IERROR_NO_DATA, 184 184 SCTP_IERROR_BAD_STREAM, 185 185 SCTP_IERROR_BAD_PORTS, 186 - 186 + SCTP_IERROR_AUTH_BAD_HMAC, 187 + SCTP_IERROR_AUTH_BAD_KEYID, 188 + SCTP_IERROR_PROTO_VIOLATION, 187 189 } sctp_ierror_t; 188 190 189 191
+1
include/net/sctp/sm.h
··· 143 143 sctp_state_fn_t sctp_sf_do_9_2_reshutack; 144 144 sctp_state_fn_t sctp_sf_eat_fwd_tsn; 145 145 sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast; 146 + sctp_state_fn_t sctp_sf_eat_auth; 146 147 147 148 /* Prototypes for primitive event state functions. */ 148 149 sctp_state_fn_t sctp_sf_do_prm_asoc;
+8
include/net/sctp/structs.h
··· 724 724 */ 725 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 734 __u8 rtt_in_progress; /* Is this chunk used for RTT calculation? */ 728 735 __u8 resent; /* Has this chunk ever been retransmitted. */ 729 736 __u8 has_tsn; /* Does this chunk have a TSN yet? */ ··· 1074 1067 void sctp_inq_free(struct sctp_inq *); 1075 1068 void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet); 1076 1069 struct sctp_chunk *sctp_inq_pop(struct sctp_inq *); 1070 + struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *); 1077 1071 void sctp_inq_set_th_handler(struct sctp_inq *, work_func_t); 1078 1072 1079 1073 /* This is the structure we use to hold outbound chunks. You push
+10
net/sctp/associola.c
··· 1011 1011 state = asoc->state; 1012 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 1024 /* Remember where the last DATA chunk came from so we 1015 1025 * know where to send the SACK. 1016 1026 */
+29
net/sctp/endpointola.c
··· 400 400 sctp_subtype_t subtype; 401 401 sctp_state_t state; 402 402 int error = 0; 403 + int first_time = 1; /* is this the first time through the looop */ 403 404 404 405 if (ep->base.dead) 405 406 return; ··· 412 411 while (NULL != (chunk = sctp_inq_pop(inqueue))) { 413 412 subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); 414 413 414 + /* If the first chunk in the packet is AUTH, do special 415 + * processing specified in Section 6.3 of SCTP-AUTH spec 416 + */ 417 + if (first_time && (subtype.chunk == SCTP_CID_AUTH)) { 418 + struct sctp_chunkhdr *next_hdr; 419 + 420 + next_hdr = sctp_inq_peek(inqueue); 421 + if (!next_hdr) 422 + goto normal; 423 + 424 + /* If the next chunk is COOKIE-ECHO, skip the AUTH 425 + * chunk while saving a pointer to it so we can do 426 + * Authentication later (during cookie-echo 427 + * processing). 428 + */ 429 + if (next_hdr->type == SCTP_CID_COOKIE_ECHO) { 430 + chunk->auth_chunk = skb_clone(chunk->skb, 431 + GFP_ATOMIC); 432 + chunk->auth = 1; 433 + continue; 434 + } 435 + } 436 + normal: 415 437 /* We might have grown an association since last we 416 438 * looked, so try again. 417 439 * ··· 450 426 } 451 427 452 428 state = asoc ? asoc->state : SCTP_STATE_CLOSED; 429 + if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth) 430 + continue; 453 431 454 432 /* Remember where the last DATA chunk came from so we 455 433 * know where to send the SACK. ··· 475 449 */ 476 450 if (!sctp_sk(sk)->ep) 477 451 break; 452 + 453 + if (first_time) 454 + first_time = 0; 478 455 } 479 456 }
+55 -10
net/sctp/input.c
··· 911 911 912 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 914 /* The code below will attempt to walk the chunk and extract 924 915 * parameter information. Before we do that, we need to verify 925 916 * that the chunk length doesn't cause overflow. Otherwise, we'll ··· 955 964 return NULL; 956 965 } 957 966 967 + /* SCTP-AUTH, Section 6.3: 968 + * If the receiver does not find a STCB for a packet containing an AUTH 969 + * chunk as the first chunk and not a COOKIE-ECHO chunk as the second 970 + * chunk, it MUST use the chunks after the AUTH chunk to look up an existing 971 + * association. 972 + * 973 + * This means that any chunks that can help us identify the association need 974 + * to be looked at to find this assocation. 975 + * 976 + * TODO: The only chunk currently defined that can do that is ASCONF, but we 977 + * don't support that functionality yet. 978 + */ 979 + static struct sctp_association *__sctp_rcv_auth_lookup(struct sk_buff *skb, 980 + const union sctp_addr *paddr, 981 + const union sctp_addr *laddr, 982 + struct sctp_transport **transportp) 983 + { 984 + /* XXX - walk through the chunks looking for something that can 985 + * help us find the association. INIT, and INIT-ACK are not permitted. 986 + * That leaves ASCONF, but we don't support that yet. 987 + */ 988 + return NULL; 989 + } 990 + 991 + /* 992 + * There are circumstances when we need to look inside the SCTP packet 993 + * for information to help us find the association. Examples 994 + * include looking inside of INIT/INIT-ACK chunks or after the AUTH 995 + * chunks. 996 + */ 997 + static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, 998 + const union sctp_addr *paddr, 999 + const union sctp_addr *laddr, 1000 + struct sctp_transport **transportp) 1001 + { 1002 + sctp_chunkhdr_t *ch; 1003 + 1004 + ch = (sctp_chunkhdr_t *) skb->data; 1005 + 1006 + /* If this is INIT/INIT-ACK look inside the chunk too. */ 1007 + switch (ch->type) { 1008 + case SCTP_CID_INIT: 1009 + case SCTP_CID_INIT_ACK: 1010 + return __sctp_rcv_init_lookup(skb, laddr, transportp); 1011 + break; 1012 + 1013 + case SCTP_CID_AUTH: 1014 + return __sctp_rcv_auth_lookup(skb, paddr, laddr, transportp); 1015 + break; 1016 + } 1017 + 1018 + return NULL; 1019 + } 1020 + 958 1021 /* Lookup an association for an inbound skb. */ 959 1022 static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb, 960 1023 const union sctp_addr *paddr, ··· 1024 979 * parameters within the INIT or INIT-ACK. 1025 980 */ 1026 981 if (!asoc) 1027 - asoc = __sctp_rcv_init_lookup(skb, laddr, transportp); 982 + asoc = __sctp_rcv_lookup_harder(skb, paddr, laddr, transportp); 1028 983 1029 984 return asoc; 1030 985 }
+19
net/sctp/inqueue.c
··· 100 100 q->immediate.func(&q->immediate); 101 101 } 102 102 103 + /* Peek at the next chunk on the inqeue. */ 104 + struct 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 122 /* Extract a chunk from an SCTP inqueue. 104 123 * 105 124 * WARNING: If you need to put the chunk on another queue, you need to
+216 -2
net/sctp/sm_statefuns.c
··· 138 138 void *arg, 139 139 sctp_cmd_seq_t *commands); 140 140 141 + static 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 146 /* Small helper function that checks if the chunk length 142 147 * is of the appropriate length. The 'required_length' argument 143 148 * is set to be the size of a specific chunk we are testing. ··· 500 495 (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, 501 496 &err_chunk)) { 502 497 503 - SCTP_INC_STATS(SCTP_MIB_ABORTEDS); 504 - 505 498 /* This chunk contains fatal error. It is to be discarded. 506 499 * Send an ABORT, with causes if there is any. 507 500 */ ··· 524 521 sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); 525 522 error = SCTP_ERROR_INV_PARAM; 526 523 } 524 + 525 + /* SCTP-AUTH, Section 6.3: 526 + * It should be noted that if the receiver wants to tear 527 + * down an association in an authenticated way only, the 528 + * handling of malformed packets should not result in 529 + * tearing down the association. 530 + * 531 + * This means that if we only want to abort associations 532 + * in an authenticated way (i.e AUTH+ABORT), then we 533 + * can't destory this association just becuase the packet 534 + * was malformed. 535 + */ 536 + if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 537 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 538 + 539 + SCTP_INC_STATS(SCTP_MIB_ABORTEDS); 527 540 return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, 528 541 asoc, chunk->transport); 529 542 } ··· 717 698 error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC); 718 699 if (error) 719 700 goto nomem_init; 701 + 702 + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo 703 + * is supposed to be authenticated and we have to do delayed 704 + * authentication. We've just recreated the association using 705 + * the information in the cookie and now it's much easier to 706 + * do the authentication. 707 + */ 708 + if (chunk->auth_chunk) { 709 + struct sctp_chunk auth; 710 + sctp_ierror_t ret; 711 + 712 + /* set-up our fake chunk so that we can process it */ 713 + auth.skb = chunk->auth_chunk; 714 + auth.asoc = chunk->asoc; 715 + auth.sctp_hdr = chunk->sctp_hdr; 716 + auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk, 717 + sizeof(sctp_chunkhdr_t)); 718 + skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t)); 719 + auth.transport = chunk->transport; 720 + 721 + ret = sctp_sf_authenticate(ep, new_asoc, type, &auth); 722 + 723 + /* We can now safely free the auth_chunk clone */ 724 + kfree_skb(chunk->auth_chunk); 725 + 726 + if (ret != SCTP_IERROR_NO_ERROR) { 727 + sctp_association_free(new_asoc); 728 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 729 + } 730 + } 720 731 721 732 repl = sctp_make_cookie_ack(new_asoc, chunk); 722 733 if (!repl) ··· 3702 3653 } 3703 3654 3704 3655 /* 3656 + * SCTP-AUTH Section 6.3 Receving authenticated chukns 3657 + * 3658 + * The receiver MUST use the HMAC algorithm indicated in the HMAC 3659 + * Identifier field. If this algorithm was not specified by the 3660 + * receiver in the HMAC-ALGO parameter in the INIT or INIT-ACK chunk 3661 + * during association setup, the AUTH chunk and all chunks after it MUST 3662 + * be discarded and an ERROR chunk SHOULD be sent with the error cause 3663 + * defined in Section 4.1. 3664 + * 3665 + * If an endpoint with no shared key receives a Shared Key Identifier 3666 + * other than 0, it MUST silently discard all authenticated chunks. If 3667 + * the endpoint has at least one endpoint pair shared key for the peer, 3668 + * it MUST use the key specified by the Shared Key Identifier if a 3669 + * key has been configured for that Shared Key Identifier. If no 3670 + * endpoint pair shared key has been configured for that Shared Key 3671 + * Identifier, all authenticated chunks MUST be silently discarded. 3672 + * 3673 + * Verification Tag: 8.5 Verification Tag [Normal verification] 3674 + * 3675 + * The return value is the disposition of the chunk. 3676 + */ 3677 + static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep, 3678 + const struct sctp_association *asoc, 3679 + const sctp_subtype_t type, 3680 + struct sctp_chunk *chunk) 3681 + { 3682 + struct sctp_authhdr *auth_hdr; 3683 + struct sctp_hmac *hmac; 3684 + unsigned int sig_len; 3685 + __u16 key_id; 3686 + __u8 *save_digest; 3687 + __u8 *digest; 3688 + 3689 + /* Pull in the auth header, so we can do some more verification */ 3690 + auth_hdr = (struct sctp_authhdr *)chunk->skb->data; 3691 + chunk->subh.auth_hdr = auth_hdr; 3692 + skb_pull(chunk->skb, sizeof(struct sctp_authhdr)); 3693 + 3694 + /* Make sure that we suport the HMAC algorithm from the auth 3695 + * chunk. 3696 + */ 3697 + if (!sctp_auth_asoc_verify_hmac_id(asoc, auth_hdr->hmac_id)) 3698 + return SCTP_IERROR_AUTH_BAD_HMAC; 3699 + 3700 + /* Make sure that the provided shared key identifier has been 3701 + * configured 3702 + */ 3703 + key_id = ntohs(auth_hdr->shkey_id); 3704 + if (key_id != asoc->active_key_id && !sctp_auth_get_shkey(asoc, key_id)) 3705 + return SCTP_IERROR_AUTH_BAD_KEYID; 3706 + 3707 + 3708 + /* Make sure that the length of the signature matches what 3709 + * we expect. 3710 + */ 3711 + sig_len = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_auth_chunk_t); 3712 + hmac = sctp_auth_get_hmac(ntohs(auth_hdr->hmac_id)); 3713 + if (sig_len != hmac->hmac_len) 3714 + return SCTP_IERROR_PROTO_VIOLATION; 3715 + 3716 + /* Now that we've done validation checks, we can compute and 3717 + * verify the hmac. The steps involved are: 3718 + * 1. Save the digest from the chunk. 3719 + * 2. Zero out the digest in the chunk. 3720 + * 3. Compute the new digest 3721 + * 4. Compare saved and new digests. 3722 + */ 3723 + digest = auth_hdr->hmac; 3724 + skb_pull(chunk->skb, sig_len); 3725 + 3726 + save_digest = kmemdup(digest, sig_len, GFP_ATOMIC); 3727 + if (!save_digest) 3728 + goto nomem; 3729 + 3730 + memset(digest, 0, sig_len); 3731 + 3732 + sctp_auth_calculate_hmac(asoc, chunk->skb, 3733 + (struct sctp_auth_chunk *)chunk->chunk_hdr, 3734 + GFP_ATOMIC); 3735 + 3736 + /* Discard the packet if the digests do not match */ 3737 + if (memcmp(save_digest, digest, sig_len)) { 3738 + kfree(save_digest); 3739 + return SCTP_IERROR_BAD_SIG; 3740 + } 3741 + 3742 + kfree(save_digest); 3743 + chunk->auth = 1; 3744 + 3745 + return SCTP_IERROR_NO_ERROR; 3746 + nomem: 3747 + return SCTP_IERROR_NOMEM; 3748 + } 3749 + 3750 + sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, 3751 + const struct sctp_association *asoc, 3752 + const sctp_subtype_t type, 3753 + void *arg, 3754 + sctp_cmd_seq_t *commands) 3755 + { 3756 + struct sctp_authhdr *auth_hdr; 3757 + struct sctp_chunk *chunk = arg; 3758 + struct sctp_chunk *err_chunk; 3759 + sctp_ierror_t error; 3760 + 3761 + if (!sctp_vtag_verify(chunk, asoc)) { 3762 + sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 3763 + SCTP_NULL()); 3764 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 3765 + } 3766 + 3767 + /* Make sure that the AUTH chunk has valid length. */ 3768 + if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk))) 3769 + return sctp_sf_violation_chunklen(ep, asoc, type, arg, 3770 + commands); 3771 + 3772 + auth_hdr = (struct sctp_authhdr *)chunk->skb->data; 3773 + error = sctp_sf_authenticate(ep, asoc, type, chunk); 3774 + switch (error) { 3775 + case SCTP_IERROR_AUTH_BAD_HMAC: 3776 + /* Generate the ERROR chunk and discard the rest 3777 + * of the packet 3778 + */ 3779 + err_chunk = sctp_make_op_error(asoc, chunk, 3780 + SCTP_ERROR_UNSUP_HMAC, 3781 + &auth_hdr->hmac_id, 3782 + sizeof(__u16)); 3783 + if (err_chunk) { 3784 + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3785 + SCTP_CHUNK(err_chunk)); 3786 + } 3787 + /* Fall Through */ 3788 + case SCTP_IERROR_AUTH_BAD_KEYID: 3789 + case SCTP_IERROR_BAD_SIG: 3790 + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 3791 + break; 3792 + case SCTP_IERROR_PROTO_VIOLATION: 3793 + return sctp_sf_violation_chunklen(ep, asoc, type, arg, 3794 + commands); 3795 + break; 3796 + case SCTP_IERROR_NOMEM: 3797 + return SCTP_DISPOSITION_NOMEM; 3798 + default: 3799 + break; 3800 + } 3801 + 3802 + return SCTP_DISPOSITION_CONSUME; 3803 + } 3804 + 3805 + /* 3705 3806 * Process an unknown chunk. 3706 3807 * 3707 3808 * Section: 3.2. Also, 2.1 in the implementor's guide. ··· 4056 3857 if (!abort) 4057 3858 goto nomem; 4058 3859 3860 + /* SCTP-AUTH, Section 6.3: 3861 + * It should be noted that if the receiver wants to tear 3862 + * down an association in an authenticated way only, the 3863 + * handling of malformed packets should not result in 3864 + * tearing down the association. 3865 + * 3866 + * This means that if we only want to abort associations 3867 + * in an authenticated way (i.e AUTH+ABORT), then we 3868 + * can't destory this association just becuase the packet 3869 + * was malformed. 3870 + */ 3871 + if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) 3872 + goto discard; 3873 + 4059 3874 if (asoc) { 4060 3875 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); 4061 3876 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); ··· 4107 3894 SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); 4108 3895 } 4109 3896 3897 + discard: 4110 3898 sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); 4111 3899 4112 3900 SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
+33
net/sctp/sm_statetable.c
··· 523 523 TYPE_SCTP_FWD_TSN, 524 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 + */ 550 + static 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 + 526 554 static const sctp_sm_table_entry_t 527 555 chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { 528 556 /* SCTP_STATE_EMPTY */ ··· 1002 974 1003 975 if (cid == SCTP_CID_ASCONF_ACK) 1004 976 return &addip_chunk_event_table[1][state]; 977 + } 978 + 979 + if (sctp_auth_enable) { 980 + if (cid == SCTP_CID_AUTH) 981 + return &auth_chunk_event_table[0][state]; 1005 982 } 1006 983 1007 984 return &chunk_event_table_unknown[state];