diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 21 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 162 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 5 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 35 |
4 files changed, 219 insertions, 4 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ee4b212e66b1..3bdd8dcb76a7 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -415,6 +415,9 @@ void sctp_association_free(struct sctp_association *asoc) | |||
415 | 415 | ||
416 | /* Free peer's cached cookie. */ | 416 | /* Free peer's cached cookie. */ |
417 | kfree(asoc->peer.cookie); | 417 | kfree(asoc->peer.cookie); |
418 | kfree(asoc->peer.peer_random); | ||
419 | kfree(asoc->peer.peer_chunks); | ||
420 | kfree(asoc->peer.peer_hmacs); | ||
418 | 421 | ||
419 | /* Release the transport structures. */ | 422 | /* Release the transport structures. */ |
420 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 423 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
@@ -1145,7 +1148,23 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1145 | } | 1148 | } |
1146 | } | 1149 | } |
1147 | 1150 | ||
1148 | /* SCTP-AUTH: XXX something needs to be done here*/ | 1151 | /* SCTP-AUTH: Save the peer parameters from the new assocaitions |
1152 | * and also move the association shared keys over | ||
1153 | */ | ||
1154 | kfree(asoc->peer.peer_random); | ||
1155 | asoc->peer.peer_random = new->peer.peer_random; | ||
1156 | new->peer.peer_random = NULL; | ||
1157 | |||
1158 | kfree(asoc->peer.peer_chunks); | ||
1159 | asoc->peer.peer_chunks = new->peer.peer_chunks; | ||
1160 | new->peer.peer_chunks = NULL; | ||
1161 | |||
1162 | kfree(asoc->peer.peer_hmacs); | ||
1163 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; | ||
1164 | new->peer.peer_hmacs = NULL; | ||
1165 | |||
1166 | sctp_auth_key_put(asoc->asoc_shared_key); | ||
1167 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); | ||
1149 | } | 1168 | } |
1150 | 1169 | ||
1151 | /* Update the retran path for sending a retransmitted packet. | 1170 | /* Update the retran path for sending a retransmitted packet. |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 71cc204a9ea5..4c02875786ac 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 |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 8d7890083493..bbdc938da86f 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -1524,6 +1524,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1524 | sctp_cmd_adaptation_ind(commands, asoc); | 1524 | sctp_cmd_adaptation_ind(commands, asoc); |
1525 | break; | 1525 | break; |
1526 | 1526 | ||
1527 | case SCTP_CMD_ASSOC_SHKEY: | ||
1528 | error = sctp_auth_asoc_init_active_key(asoc, | ||
1529 | GFP_ATOMIC); | ||
1530 | break; | ||
1531 | |||
1527 | default: | 1532 | default: |
1528 | printk(KERN_WARNING "Impossible command: %u, %p\n", | 1533 | printk(KERN_WARNING "Impossible command: %u, %p\n", |
1529 | cmd->verb, cmd->obj.ptr); | 1534 | cmd->verb, cmd->obj.ptr); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ec0328b1cdb1..385486360fe9 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -549,6 +549,11 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
549 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 549 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
550 | SCTP_STATE(SCTP_STATE_COOKIE_ECHOED)); | 550 | SCTP_STATE(SCTP_STATE_COOKIE_ECHOED)); |
551 | 551 | ||
552 | /* SCTP-AUTH: genereate the assocition shared keys so that | ||
553 | * we can potentially signe the COOKIE-ECHO. | ||
554 | */ | ||
555 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_SHKEY, SCTP_NULL()); | ||
556 | |||
552 | /* 5.1 C) "A" shall then send the State Cookie received in the | 557 | /* 5.1 C) "A" shall then send the State Cookie received in the |
553 | * INIT ACK chunk in a COOKIE ECHO chunk, ... | 558 | * INIT ACK chunk in a COOKIE ECHO chunk, ... |
554 | */ | 559 | */ |
@@ -686,6 +691,14 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
686 | peer_init, GFP_ATOMIC)) | 691 | peer_init, GFP_ATOMIC)) |
687 | goto nomem_init; | 692 | goto nomem_init; |
688 | 693 | ||
694 | /* SCTP-AUTH: Now that we've populate required fields in | ||
695 | * sctp_process_init, set up the assocaition shared keys as | ||
696 | * necessary so that we can potentially authenticate the ACK | ||
697 | */ | ||
698 | error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC); | ||
699 | if (error) | ||
700 | goto nomem_init; | ||
701 | |||
689 | repl = sctp_make_cookie_ack(new_asoc, chunk); | 702 | repl = sctp_make_cookie_ack(new_asoc, chunk); |
690 | if (!repl) | 703 | if (!repl) |
691 | goto nomem_init; | 704 | goto nomem_init; |
@@ -1247,6 +1260,26 @@ static void sctp_tietags_populate(struct sctp_association *new_asoc, | |||
1247 | new_asoc->c.initial_tsn = asoc->c.initial_tsn; | 1260 | new_asoc->c.initial_tsn = asoc->c.initial_tsn; |
1248 | } | 1261 | } |
1249 | 1262 | ||
1263 | static void sctp_auth_params_populate(struct sctp_association *new_asoc, | ||
1264 | const struct sctp_association *asoc) | ||
1265 | { | ||
1266 | /* Only perform this if AUTH extension is enabled */ | ||
1267 | if (!sctp_auth_enable) | ||
1268 | return; | ||
1269 | |||
1270 | /* We need to provide the same parameter information as | ||
1271 | * was in the original INIT. This means that we need to copy | ||
1272 | * the HMACS, CHUNKS, and RANDOM parameter from the original | ||
1273 | * assocaition. | ||
1274 | */ | ||
1275 | memcpy(new_asoc->c.auth_random, asoc->c.auth_random, | ||
1276 | sizeof(asoc->c.auth_random)); | ||
1277 | memcpy(new_asoc->c.auth_hmacs, asoc->c.auth_hmacs, | ||
1278 | sizeof(asoc->c.auth_hmacs)); | ||
1279 | memcpy(new_asoc->c.auth_chunks, asoc->c.auth_chunks, | ||
1280 | sizeof(asoc->c.auth_chunks)); | ||
1281 | } | ||
1282 | |||
1250 | /* | 1283 | /* |
1251 | * Compare vtag/tietag values to determine unexpected COOKIE-ECHO | 1284 | * Compare vtag/tietag values to determine unexpected COOKIE-ECHO |
1252 | * handling action. | 1285 | * handling action. |
@@ -1404,6 +1437,8 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1404 | 1437 | ||
1405 | sctp_tietags_populate(new_asoc, asoc); | 1438 | sctp_tietags_populate(new_asoc, asoc); |
1406 | 1439 | ||
1440 | sctp_auth_params_populate(new_asoc, asoc); | ||
1441 | |||
1407 | /* B) "Z" shall respond immediately with an INIT ACK chunk. */ | 1442 | /* B) "Z" shall respond immediately with an INIT ACK chunk. */ |
1408 | 1443 | ||
1409 | /* If there are errors need to be reported for unknown parameters, | 1444 | /* If there are errors need to be reported for unknown parameters, |