@@ -182,6 +182,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
182
182
sctp_supported_ext_param_t ext_param ;
183
183
int num_ext = 0 ;
184
184
__u8 extensions [3 ];
185
+ sctp_paramhdr_t * auth_chunks = NULL ,
186
+ * auth_hmacs = NULL ;
185
187
186
188
/* RFC 2960 3.3.2 Initiation (INIT) (1)
187
189
*
@@ -214,8 +216,6 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
214
216
* An implementation supporting this extension [ADDIP] MUST list
215
217
* the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and
216
218
* INIT-ACK parameters.
217
- * XXX: We don't support AUTH just yet, so don't list it. AUTH
218
- * support should add it.
219
219
*/
220
220
if (sctp_addip_enable ) {
221
221
extensions [num_ext ] = SCTP_CID_ASCONF ;
@@ -226,6 +226,29 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
226
226
chunksize += sizeof (aiparam );
227
227
chunksize += vparam_len ;
228
228
229
+ /* Account for AUTH related parameters */
230
+ if (sctp_auth_enable ) {
231
+ /* Add random parameter length*/
232
+ chunksize += sizeof (asoc -> c .auth_random );
233
+
234
+ /* Add HMACS parameter length if any were defined */
235
+ auth_hmacs = (sctp_paramhdr_t * )asoc -> c .auth_hmacs ;
236
+ if (auth_hmacs -> length )
237
+ chunksize += ntohs (auth_hmacs -> length );
238
+ else
239
+ auth_hmacs = NULL ;
240
+
241
+ /* Add CHUNKS parameter length */
242
+ auth_chunks = (sctp_paramhdr_t * )asoc -> c .auth_chunks ;
243
+ if (auth_chunks -> length )
244
+ chunksize += ntohs (auth_chunks -> length );
245
+ else
246
+ auth_hmacs = NULL ;
247
+
248
+ extensions [num_ext ] = SCTP_CID_AUTH ;
249
+ num_ext += 1 ;
250
+ }
251
+
229
252
/* If we have any extensions to report, account for that */
230
253
if (num_ext )
231
254
chunksize += sizeof (sctp_supported_ext_param_t ) + num_ext ;
@@ -285,6 +308,17 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
285
308
aiparam .adaptation_ind = htonl (sp -> adaptation_ind );
286
309
sctp_addto_chunk (retval , sizeof (aiparam ), & aiparam );
287
310
311
+ /* Add SCTP-AUTH chunks to the parameter list */
312
+ if (sctp_auth_enable ) {
313
+ sctp_addto_chunk (retval , sizeof (asoc -> c .auth_random ),
314
+ asoc -> c .auth_random );
315
+ if (auth_hmacs )
316
+ sctp_addto_chunk (retval , ntohs (auth_hmacs -> length ),
317
+ auth_hmacs );
318
+ if (auth_chunks )
319
+ sctp_addto_chunk (retval , ntohs (auth_chunks -> length ),
320
+ auth_chunks );
321
+ }
288
322
nodata :
289
323
kfree (addrs .v );
290
324
return retval ;
@@ -305,6 +339,9 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
305
339
sctp_supported_ext_param_t ext_param ;
306
340
int num_ext = 0 ;
307
341
__u8 extensions [3 ];
342
+ sctp_paramhdr_t * auth_chunks = NULL ,
343
+ * auth_hmacs = NULL ,
344
+ * auth_random = NULL ;
308
345
309
346
retval = NULL ;
310
347
@@ -350,6 +387,26 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
350
387
chunksize += sizeof (ext_param ) + num_ext ;
351
388
chunksize += sizeof (aiparam );
352
389
390
+ if (asoc -> peer .auth_capable ) {
391
+ auth_random = (sctp_paramhdr_t * )asoc -> c .auth_random ;
392
+ chunksize += ntohs (auth_random -> length );
393
+
394
+ auth_hmacs = (sctp_paramhdr_t * )asoc -> c .auth_hmacs ;
395
+ if (auth_hmacs -> length )
396
+ chunksize += ntohs (auth_hmacs -> length );
397
+ else
398
+ auth_hmacs = NULL ;
399
+
400
+ auth_chunks = (sctp_paramhdr_t * )asoc -> c .auth_chunks ;
401
+ if (auth_chunks -> length )
402
+ chunksize += ntohs (auth_chunks -> length );
403
+ else
404
+ auth_chunks = NULL ;
405
+
406
+ extensions [num_ext ] = SCTP_CID_AUTH ;
407
+ num_ext += 1 ;
408
+ }
409
+
353
410
/* Now allocate and fill out the chunk. */
354
411
retval = sctp_make_chunk (asoc , SCTP_CID_INIT_ACK , 0 , chunksize );
355
412
if (!retval )
@@ -381,6 +438,17 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
381
438
aiparam .adaptation_ind = htonl (sctp_sk (asoc -> base .sk )-> adaptation_ind );
382
439
sctp_addto_chunk (retval , sizeof (aiparam ), & aiparam );
383
440
441
+ if (asoc -> peer .auth_capable ) {
442
+ sctp_addto_chunk (retval , ntohs (auth_random -> length ),
443
+ auth_random );
444
+ if (auth_hmacs )
445
+ sctp_addto_chunk (retval , ntohs (auth_hmacs -> length ),
446
+ auth_hmacs );
447
+ if (auth_chunks )
448
+ sctp_addto_chunk (retval , ntohs (auth_chunks -> length ),
449
+ auth_chunks );
450
+ }
451
+
384
452
/* We need to remove the const qualifier at this point. */
385
453
retval -> asoc = (struct sctp_association * ) asoc ;
386
454
@@ -1736,6 +1804,12 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
1736
1804
!asoc -> peer .prsctp_capable )
1737
1805
asoc -> peer .prsctp_capable = 1 ;
1738
1806
break ;
1807
+ case SCTP_CID_AUTH :
1808
+ /* if the peer reports AUTH, assume that he
1809
+ * supports AUTH.
1810
+ */
1811
+ asoc -> peer .auth_capable = 1 ;
1812
+ break ;
1739
1813
case SCTP_CID_ASCONF :
1740
1814
case SCTP_CID_ASCONF_ACK :
1741
1815
/* don't need to do anything for ASCONF */
@@ -1871,7 +1945,42 @@ static int sctp_verify_param(const struct sctp_association *asoc,
1871
1945
case SCTP_PARAM_FWD_TSN_SUPPORT :
1872
1946
if (sctp_prsctp_enable )
1873
1947
break ;
1948
+ goto fallthrough ;
1949
+
1950
+ case SCTP_PARAM_RANDOM :
1951
+ if (!sctp_auth_enable )
1952
+ goto fallthrough ;
1953
+
1954
+ /* SCTP-AUTH: Secion 6.1
1955
+ * If the random number is not 32 byte long the association
1956
+ * MUST be aborted. The ABORT chunk SHOULD contain the error
1957
+ * cause 'Protocol Violation'.
1958
+ */
1959
+ if (SCTP_AUTH_RANDOM_LENGTH !=
1960
+ ntohs (param .p -> length ) - sizeof (sctp_paramhdr_t ))
1961
+ return sctp_process_inv_paramlength (asoc , param .p ,
1962
+ chunk , err_chunk );
1963
+ break ;
1964
+
1965
+ case SCTP_PARAM_CHUNKS :
1966
+ if (!sctp_auth_enable )
1967
+ goto fallthrough ;
1968
+
1969
+ /* SCTP-AUTH: Section 3.2
1970
+ * The CHUNKS parameter MUST be included once in the INIT or
1971
+ * INIT-ACK chunk if the sender wants to receive authenticated
1972
+ * chunks. Its maximum length is 260 bytes.
1973
+ */
1974
+ if (260 < ntohs (param .p -> length ))
1975
+ return sctp_process_inv_paramlength (asoc , param .p ,
1976
+ chunk , err_chunk );
1977
+ break ;
1978
+
1979
+ case SCTP_PARAM_HMAC_ALGO :
1980
+ if (!sctp_auth_enable )
1981
+ break ;
1874
1982
/* Fall Through */
1983
+ fallthrough :
1875
1984
default :
1876
1985
SCTP_DEBUG_PRINTK ("Unrecognized param: %d for chunk %d.\n" ,
1877
1986
ntohs (param .p -> type ), cid );
@@ -1976,13 +2085,19 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
1976
2085
}
1977
2086
1978
2087
/* Process the initialization parameters. */
1979
-
1980
2088
sctp_walk_params (param , peer_init , init_hdr .params ) {
1981
2089
1982
2090
if (!sctp_process_param (asoc , param , peer_addr , gfp ))
1983
2091
goto clean_up ;
1984
2092
}
1985
2093
2094
+ /* AUTH: After processing the parameters, make sure that we
2095
+ * have all the required info to potentially do authentications.
2096
+ */
2097
+ if (asoc -> peer .auth_capable && (!asoc -> peer .peer_random ||
2098
+ !asoc -> peer .peer_hmacs ))
2099
+ asoc -> peer .auth_capable = 0 ;
2100
+
1986
2101
/* Walk list of transports, removing transports in the UNKNOWN state. */
1987
2102
list_for_each_safe (pos , temp , & asoc -> peer .transport_addr_list ) {
1988
2103
transport = list_entry (pos , struct sctp_transport , transports );
@@ -2222,6 +2337,47 @@ static int sctp_process_param(struct sctp_association *asoc,
2222
2337
break ;
2223
2338
}
2224
2339
/* Fall Through */
2340
+ goto fall_through ;
2341
+
2342
+ case SCTP_PARAM_RANDOM :
2343
+ if (!sctp_auth_enable )
2344
+ goto fall_through ;
2345
+
2346
+ /* Save peer's random parameter */
2347
+ asoc -> peer .peer_random = kmemdup (param .p ,
2348
+ ntohs (param .p -> length ), gfp );
2349
+ if (!asoc -> peer .peer_random ) {
2350
+ retval = 0 ;
2351
+ break ;
2352
+ }
2353
+ break ;
2354
+
2355
+ case SCTP_PARAM_HMAC_ALGO :
2356
+ if (!sctp_auth_enable )
2357
+ goto fall_through ;
2358
+
2359
+ /* Save peer's HMAC list */
2360
+ asoc -> peer .peer_hmacs = kmemdup (param .p ,
2361
+ ntohs (param .p -> length ), gfp );
2362
+ if (!asoc -> peer .peer_hmacs ) {
2363
+ retval = 0 ;
2364
+ break ;
2365
+ }
2366
+
2367
+ /* Set the default HMAC the peer requested*/
2368
+ sctp_auth_asoc_set_default_hmac (asoc , param .hmac_algo );
2369
+ break ;
2370
+
2371
+ case SCTP_PARAM_CHUNKS :
2372
+ if (!sctp_auth_enable )
2373
+ goto fall_through ;
2374
+
2375
+ asoc -> peer .peer_chunks = kmemdup (param .p ,
2376
+ ntohs (param .p -> length ), gfp );
2377
+ if (!asoc -> peer .peer_chunks )
2378
+ retval = 0 ;
2379
+ break ;
2380
+ fall_through :
2225
2381
default :
2226
2382
/* Any unrecognized parameters should have been caught
2227
2383
* and handled by sctp_verify_param() which should be
0 commit comments