Skip to content

Commit 957adaa

Browse files
lxingregkh
authored andcommitted
sctp: delay the authentication for the duplicated cookie-echo chunk
[ Upstream commit 59d8d44 ] Now sctp only delays the authentication for the normal cookie-echo chunk by setting chunk->auth_chunk in sctp_endpoint_bh_rcv(). But for the duplicated one with auth, in sctp_assoc_bh_rcv(), it does authentication first based on the old asoc, which will definitely fail due to the different auth info in the old asoc. The duplicated cookie-echo chunk will create a new asoc with the auth info from this chunk, and the authentication should also be done with the new asoc's auth info for all of the collision 'A', 'B' and 'D'. Otherwise, the duplicated cookie-echo chunk with auth will never pass the authentication and create the new connection. This issue exists since very beginning, and this fix is to make sctp_assoc_bh_rcv() follow the way sctp_endpoint_bh_rcv() does for the normal cookie-echo chunk to delay the authentication. While at it, remove the unused params from sctp_sf_authenticate() and define sctp_auth_chunk_verify() used for all the places that do the delayed authentication. v1->v2: fix the typo in changelog as Marcelo noticed. Acked-by: Marcelo Ricardo Leitner <[email protected]> Signed-off-by: Xin Long <[email protected]> Acked-by: Neil Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e0a532d commit 957adaa

File tree

2 files changed

+77
-40
lines changed

2 files changed

+77
-40
lines changed

net/sctp/associola.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,9 +1000,10 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
10001000
struct sctp_endpoint *ep;
10011001
struct sctp_chunk *chunk;
10021002
struct sctp_inq *inqueue;
1003-
int state;
10041003
sctp_subtype_t subtype;
1004+
int first_time = 1; /* is this the first time through the loop */
10051005
int error = 0;
1006+
int state;
10061007

10071008
/* The association should be held so we should be safe. */
10081009
ep = asoc->ep;
@@ -1013,6 +1014,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
10131014
state = asoc->state;
10141015
subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
10151016

1017+
/* If the first chunk in the packet is AUTH, do special
1018+
* processing specified in Section 6.3 of SCTP-AUTH spec
1019+
*/
1020+
if (first_time && subtype.chunk == SCTP_CID_AUTH) {
1021+
struct sctp_chunkhdr *next_hdr;
1022+
1023+
next_hdr = sctp_inq_peek(inqueue);
1024+
if (!next_hdr)
1025+
goto normal;
1026+
1027+
/* If the next chunk is COOKIE-ECHO, skip the AUTH
1028+
* chunk while saving a pointer to it so we can do
1029+
* Authentication later (during cookie-echo
1030+
* processing).
1031+
*/
1032+
if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
1033+
chunk->auth_chunk = skb_clone(chunk->skb,
1034+
GFP_ATOMIC);
1035+
chunk->auth = 1;
1036+
continue;
1037+
}
1038+
}
1039+
1040+
normal:
10161041
/* SCTP-AUTH, Section 6.3:
10171042
* The receiver has a list of chunk types which it expects
10181043
* to be received only after an AUTH-chunk. This list has
@@ -1051,6 +1076,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
10511076
/* If there is an error on chunk, discard this packet. */
10521077
if (error && chunk)
10531078
chunk->pdiscard = 1;
1079+
1080+
if (first_time)
1081+
first_time = 0;
10541082
}
10551083
sctp_association_put(asoc);
10561084
}

net/sctp/sm_statefuns.c

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,8 @@ static sctp_disposition_t sctp_sf_violation_chunk(
144144
void *arg,
145145
sctp_cmd_seq_t *commands);
146146

147-
static sctp_ierror_t sctp_sf_authenticate(struct net *net,
148-
const struct sctp_endpoint *ep,
147+
static sctp_ierror_t sctp_sf_authenticate(
149148
const struct sctp_association *asoc,
150-
const sctp_subtype_t type,
151149
struct sctp_chunk *chunk);
152150

153151
static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net,
@@ -615,6 +613,38 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net,
615613
return SCTP_DISPOSITION_CONSUME;
616614
}
617615

616+
static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,
617+
const struct sctp_association *asoc)
618+
{
619+
struct sctp_chunk auth;
620+
621+
if (!chunk->auth_chunk)
622+
return true;
623+
624+
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
625+
* is supposed to be authenticated and we have to do delayed
626+
* authentication. We've just recreated the association using
627+
* the information in the cookie and now it's much easier to
628+
* do the authentication.
629+
*/
630+
631+
/* Make sure that we and the peer are AUTH capable */
632+
if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
633+
return false;
634+
635+
/* set-up our fake chunk so that we can process it */
636+
auth.skb = chunk->auth_chunk;
637+
auth.asoc = chunk->asoc;
638+
auth.sctp_hdr = chunk->sctp_hdr;
639+
auth.chunk_hdr = (struct sctp_chunkhdr *)
640+
skb_push(chunk->auth_chunk,
641+
sizeof(struct sctp_chunkhdr));
642+
skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr));
643+
auth.transport = chunk->transport;
644+
645+
return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR;
646+
}
647+
618648
/*
619649
* Respond to a normal COOKIE ECHO chunk.
620650
* We are the side that is being asked for an association.
@@ -751,36 +781,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
751781
if (error)
752782
goto nomem_init;
753783

754-
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
755-
* is supposed to be authenticated and we have to do delayed
756-
* authentication. We've just recreated the association using
757-
* the information in the cookie and now it's much easier to
758-
* do the authentication.
759-
*/
760-
if (chunk->auth_chunk) {
761-
struct sctp_chunk auth;
762-
sctp_ierror_t ret;
763-
764-
/* Make sure that we and the peer are AUTH capable */
765-
if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
766-
sctp_association_free(new_asoc);
767-
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
768-
}
769-
770-
/* set-up our fake chunk so that we can process it */
771-
auth.skb = chunk->auth_chunk;
772-
auth.asoc = chunk->asoc;
773-
auth.sctp_hdr = chunk->sctp_hdr;
774-
auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk,
775-
sizeof(sctp_chunkhdr_t));
776-
skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));
777-
auth.transport = chunk->transport;
778-
779-
ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
780-
if (ret != SCTP_IERROR_NO_ERROR) {
781-
sctp_association_free(new_asoc);
782-
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
783-
}
784+
if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) {
785+
sctp_association_free(new_asoc);
786+
return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
784787
}
785788

786789
repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -1717,13 +1720,15 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net,
17171720
GFP_ATOMIC))
17181721
goto nomem;
17191722

1723+
if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
1724+
return SCTP_DISPOSITION_DISCARD;
1725+
17201726
/* Make sure no new addresses are being added during the
17211727
* restart. Though this is a pretty complicated attack
17221728
* since you'd have to get inside the cookie.
17231729
*/
1724-
if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) {
1730+
if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands))
17251731
return SCTP_DISPOSITION_CONSUME;
1726-
}
17271732

17281733
/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
17291734
* the peer has restarted (Action A), it MUST NOT setup a new
@@ -1828,6 +1833,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(struct net *net,
18281833
GFP_ATOMIC))
18291834
goto nomem;
18301835

1836+
if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
1837+
return SCTP_DISPOSITION_DISCARD;
1838+
18311839
/* Update the content of current association. */
18321840
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
18331841
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -1920,6 +1928,9 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net,
19201928
* a COOKIE ACK.
19211929
*/
19221930

1931+
if (!sctp_auth_chunk_verify(net, chunk, asoc))
1932+
return SCTP_DISPOSITION_DISCARD;
1933+
19231934
/* Don't accidentally move back into established state. */
19241935
if (asoc->state < SCTP_STATE_ESTABLISHED) {
19251936
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -3985,10 +3996,8 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
39853996
*
39863997
* The return value is the disposition of the chunk.
39873998
*/
3988-
static sctp_ierror_t sctp_sf_authenticate(struct net *net,
3989-
const struct sctp_endpoint *ep,
3999+
static sctp_ierror_t sctp_sf_authenticate(
39904000
const struct sctp_association *asoc,
3991-
const sctp_subtype_t type,
39924001
struct sctp_chunk *chunk)
39934002
{
39944003
struct sctp_authhdr *auth_hdr;
@@ -4087,7 +4096,7 @@ sctp_disposition_t sctp_sf_eat_auth(struct net *net,
40874096
commands);
40884097

40894098
auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
4090-
error = sctp_sf_authenticate(net, ep, asoc, type, chunk);
4099+
error = sctp_sf_authenticate(asoc, chunk);
40914100
switch (error) {
40924101
case SCTP_IERROR_AUTH_BAD_HMAC:
40934102
/* Generate the ERROR chunk and discard the rest

0 commit comments

Comments
 (0)