aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-09-16 22:32:11 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:30 -0400
commit730fc3d05cd4ba4c9ce2de91f3d43349e95dbbf5 (patch)
tree50a59c6592a7546f9d54364f26dc2a03f5f18345
parenta29a5bd4f5c3e8ba2e89688feab8b01c44f1654f (diff)
[SCTP]: Implete SCTP-AUTH parameter processing
Implement processing for the CHUNKS, RANDOM, and HMAC parameters and deal with how this parameters are effected by association restarts. In particular, during unexpeted INIT processing, we need to reply with parameters from the original INIT chunk. Also, after restart, we need to update the old association with new peer parameters and change the association shared keys. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/command.h1
-rw-r--r--net/sctp/associola.c21
-rw-r--r--net/sctp/sm_make_chunk.c162
-rw-r--r--net/sctp/sm_sideeffect.c5
-rw-r--r--net/sctp/sm_statefuns.c35
5 files changed, 220 insertions, 4 deletions
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index f56c8d695a82..b8733364557f 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -102,6 +102,7 @@ typedef enum {
102 SCTP_CMD_SET_SK_ERR, /* Set sk_err */ 102 SCTP_CMD_SET_SK_ERR, /* Set sk_err */
103 SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */ 103 SCTP_CMD_ASSOC_CHANGE, /* generate and send assoc_change event */
104 SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */ 104 SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */
105 SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */
105 SCTP_CMD_LAST 106 SCTP_CMD_LAST
106} sctp_verb_t; 107} sctp_verb_t;
107 108
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 }
288nodata: 322nodata:
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 */
1983fallthrough:
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;
2380fall_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
1263static 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,