Skip to content

Commit 3b54f1f

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 30ffa96 commit 3b54f1f

File tree

2 files changed

+75
-41
lines changed

2 files changed

+75
-41
lines changed

net/sctp/associola.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,8 +1025,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
10251025
struct sctp_endpoint *ep;
10261026
struct sctp_chunk *chunk;
10271027
struct sctp_inq *inqueue;
1028-
int state;
1028+
int first_time = 1; /* is this the first time through the loop */
10291029
int error = 0;
1030+
int state;
10301031

10311032
/* The association should be held so we should be safe. */
10321033
ep = asoc->ep;
@@ -1037,6 +1038,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
10371038
state = asoc->state;
10381039
subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
10391040

1041+
/* If the first chunk in the packet is AUTH, do special
1042+
* processing specified in Section 6.3 of SCTP-AUTH spec
1043+
*/
1044+
if (first_time && subtype.chunk == SCTP_CID_AUTH) {
1045+
struct sctp_chunkhdr *next_hdr;
1046+
1047+
next_hdr = sctp_inq_peek(inqueue);
1048+
if (!next_hdr)
1049+
goto normal;
1050+
1051+
/* If the next chunk is COOKIE-ECHO, skip the AUTH
1052+
* chunk while saving a pointer to it so we can do
1053+
* Authentication later (during cookie-echo
1054+
* processing).
1055+
*/
1056+
if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
1057+
chunk->auth_chunk = skb_clone(chunk->skb,
1058+
GFP_ATOMIC);
1059+
chunk->auth = 1;
1060+
continue;
1061+
}
1062+
}
1063+
1064+
normal:
10401065
/* SCTP-AUTH, Section 6.3:
10411066
* The receiver has a list of chunk types which it expects
10421067
* to be received only after an AUTH-chunk. This list has
@@ -1075,6 +1100,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
10751100
/* If there is an error on chunk, discard this packet. */
10761101
if (error && chunk)
10771102
chunk->pdiscard = 1;
1103+
1104+
if (first_time)
1105+
first_time = 0;
10781106
}
10791107
sctp_association_put(asoc);
10801108
}

net/sctp/sm_statefuns.c

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,7 @@ static enum sctp_disposition sctp_sf_violation_chunk(
150150
struct sctp_cmd_seq *commands);
151151

152152
static enum sctp_ierror sctp_sf_authenticate(
153-
struct net *net,
154-
const struct sctp_endpoint *ep,
155153
const struct sctp_association *asoc,
156-
const union sctp_subtype type,
157154
struct sctp_chunk *chunk);
158155

159156
static enum sctp_disposition __sctp_sf_do_9_1_abort(
@@ -618,6 +615,38 @@ enum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net,
618615
return SCTP_DISPOSITION_CONSUME;
619616
}
620617

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

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

791792
repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -1755,13 +1756,15 @@ static enum sctp_disposition sctp_sf_do_dupcook_a(
17551756
GFP_ATOMIC))
17561757
goto nomem;
17571758

1759+
if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
1760+
return SCTP_DISPOSITION_DISCARD;
1761+
17581762
/* Make sure no new addresses are being added during the
17591763
* restart. Though this is a pretty complicated attack
17601764
* since you'd have to get inside the cookie.
17611765
*/
1762-
if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) {
1766+
if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands))
17631767
return SCTP_DISPOSITION_CONSUME;
1764-
}
17651768

17661769
/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
17671770
* the peer has restarted (Action A), it MUST NOT setup a new
@@ -1867,6 +1870,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_b(
18671870
GFP_ATOMIC))
18681871
goto nomem;
18691872

1873+
if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
1874+
return SCTP_DISPOSITION_DISCARD;
1875+
18701876
/* Update the content of current association. */
18711877
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
18721878
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -1961,6 +1967,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
19611967
* a COOKIE ACK.
19621968
*/
19631969

1970+
if (!sctp_auth_chunk_verify(net, chunk, asoc))
1971+
return SCTP_DISPOSITION_DISCARD;
1972+
19641973
/* Don't accidentally move back into established state. */
19651974
if (asoc->state < SCTP_STATE_ESTABLISHED) {
19661975
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -4111,10 +4120,7 @@ enum sctp_disposition sctp_sf_eat_fwd_tsn_fast(
41114120
* The return value is the disposition of the chunk.
41124121
*/
41134122
static enum sctp_ierror sctp_sf_authenticate(
4114-
struct net *net,
4115-
const struct sctp_endpoint *ep,
41164123
const struct sctp_association *asoc,
4117-
const union sctp_subtype type,
41184124
struct sctp_chunk *chunk)
41194125
{
41204126
struct sctp_authhdr *auth_hdr;
@@ -4212,7 +4218,7 @@ enum sctp_disposition sctp_sf_eat_auth(struct net *net,
42124218
commands);
42134219

42144220
auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
4215-
error = sctp_sf_authenticate(net, ep, asoc, type, chunk);
4221+
error = sctp_sf_authenticate(asoc, chunk);
42164222
switch (error) {
42174223
case SCTP_IERROR_AUTH_BAD_HMAC:
42184224
/* Generate the ERROR chunk and discard the rest

0 commit comments

Comments
 (0)