diff options
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 162 |
1 files changed, 159 insertions, 3 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 71cc204a9ea..4c02875786a 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -182,6 +182,8 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
182 | sctp_supported_ext_param_t ext_param; | 182 | sctp_supported_ext_param_t ext_param; |
183 | int num_ext = 0; | 183 | int num_ext = 0; |
184 | __u8 extensions[3]; | 184 | __u8 extensions[3]; |
185 | sctp_paramhdr_t *auth_chunks = NULL, | ||
186 | *auth_hmacs = NULL; | ||
185 | 187 | ||
186 | /* RFC 2960 3.3.2 Initiation (INIT) (1) | 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 | * An implementation supporting this extension [ADDIP] MUST list | 216 | * An implementation supporting this extension [ADDIP] MUST list |
215 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and | 217 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and |
216 | * INIT-ACK parameters. | 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 | if (sctp_addip_enable) { | 220 | if (sctp_addip_enable) { |
221 | extensions[num_ext] = SCTP_CID_ASCONF; | 221 | extensions[num_ext] = SCTP_CID_ASCONF; |
@@ -226,6 +226,29 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
226 | chunksize += sizeof(aiparam); | 226 | chunksize += sizeof(aiparam); |
227 | chunksize += vparam_len; | 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 | /* If we have any extensions to report, account for that */ | 252 | /* If we have any extensions to report, account for that */ |
230 | if (num_ext) | 253 | if (num_ext) |
231 | chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; | 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 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); | 308 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); |
286 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | 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 | nodata: | 322 | nodata: |
289 | kfree(addrs.v); | 323 | kfree(addrs.v); |
290 | return retval; | 324 | return retval; |
@@ -305,6 +339,9 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
305 | sctp_supported_ext_param_t ext_param; | 339 | sctp_supported_ext_param_t ext_param; |
306 | int num_ext = 0; | 340 | int num_ext = 0; |
307 | __u8 extensions[3]; | 341 | __u8 extensions[3]; |
342 | sctp_paramhdr_t *auth_chunks = NULL, | ||
343 | *auth_hmacs = NULL, | ||
344 | *auth_random = NULL; | ||
308 | 345 | ||
309 | retval = NULL; | 346 | retval = NULL; |
310 | 347 | ||
@@ -350,6 +387,26 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
350 | chunksize += sizeof(ext_param) + num_ext; | 387 | chunksize += sizeof(ext_param) + num_ext; |
351 | chunksize += sizeof(aiparam); | 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 | /* Now allocate and fill out the chunk. */ | 410 | /* Now allocate and fill out the chunk. */ |
354 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); | 411 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); |
355 | if (!retval) | 412 | if (!retval) |
@@ -381,6 +438,17 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
381 | aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind); | 438 | aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind); |
382 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | 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 | /* We need to remove the const qualifier at this point. */ | 452 | /* We need to remove the const qualifier at this point. */ |
385 | retval->asoc = (struct sctp_association *) asoc; | 453 | retval->asoc = (struct sctp_association *) asoc; |
386 | 454 | ||
@@ -1736,6 +1804,12 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1736 | !asoc->peer.prsctp_capable) | 1804 | !asoc->peer.prsctp_capable) |
1737 | asoc->peer.prsctp_capable = 1; | 1805 | asoc->peer.prsctp_capable = 1; |
1738 | break; | 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 | case SCTP_CID_ASCONF: | 1813 | case SCTP_CID_ASCONF: |
1740 | case SCTP_CID_ASCONF_ACK: | 1814 | case SCTP_CID_ASCONF_ACK: |
1741 | /* don't need to do anything for ASCONF */ | 1815 | /* don't need to do anything for ASCONF */ |
@@ -1871,7 +1945,42 @@ static int sctp_verify_param(const struct sctp_association *asoc, | |||
1871 | case SCTP_PARAM_FWD_TSN_SUPPORT: | 1945 | case SCTP_PARAM_FWD_TSN_SUPPORT: |
1872 | if (sctp_prsctp_enable) | 1946 | if (sctp_prsctp_enable) |
1873 | break; | 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 | /* Fall Through */ | 1982 | /* Fall Through */ |
1983 | fallthrough: | ||
1875 | default: | 1984 | default: |
1876 | SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", | 1985 | SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", |
1877 | ntohs(param.p->type), cid); | 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 | /* Process the initialization parameters. */ | 2087 | /* Process the initialization parameters. */ |
1979 | |||
1980 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2088 | sctp_walk_params(param, peer_init, init_hdr.params) { |
1981 | 2089 | ||
1982 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) | 2090 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) |
1983 | goto clean_up; | 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 | /* Walk list of transports, removing transports in the UNKNOWN state. */ | 2101 | /* Walk list of transports, removing transports in the UNKNOWN state. */ |
1987 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 2102 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
1988 | transport = list_entry(pos, struct sctp_transport, transports); | 2103 | transport = list_entry(pos, struct sctp_transport, transports); |
@@ -2222,6 +2337,47 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
2222 | break; | 2337 | break; |
2223 | } | 2338 | } |
2224 | /* Fall Through */ | 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 | default: | 2381 | default: |
2226 | /* Any unrecognized parameters should have been caught | 2382 | /* Any unrecognized parameters should have been caught |
2227 | * and handled by sctp_verify_param() which should be | 2383 | * and handled by sctp_verify_param() which should be |