diff options
-rw-r--r-- | net/sctp/associola.c | 34 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 83 | ||||
-rw-r--r-- | net/sctp/output.c | 4 | ||||
-rw-r--r-- | net/sctp/protocol.c | 3 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 9 |
5 files changed, 133 insertions, 0 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 9bad8ba0feda..ee4b212e66b1 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -74,6 +74,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
74 | { | 74 | { |
75 | struct sctp_sock *sp; | 75 | struct sctp_sock *sp; |
76 | int i; | 76 | int i; |
77 | sctp_paramhdr_t *p; | ||
78 | int err; | ||
77 | 79 | ||
78 | /* Retrieve the SCTP per socket area. */ | 80 | /* Retrieve the SCTP per socket area. */ |
79 | sp = sctp_sk((struct sock *)sk); | 81 | sp = sctp_sk((struct sock *)sk); |
@@ -298,6 +300,30 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
298 | asoc->default_timetolive = sp->default_timetolive; | 300 | asoc->default_timetolive = sp->default_timetolive; |
299 | asoc->default_rcv_context = sp->default_rcv_context; | 301 | asoc->default_rcv_context = sp->default_rcv_context; |
300 | 302 | ||
303 | /* AUTH related initializations */ | ||
304 | INIT_LIST_HEAD(&asoc->endpoint_shared_keys); | ||
305 | err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp); | ||
306 | if (err) | ||
307 | goto fail_init; | ||
308 | |||
309 | asoc->active_key_id = ep->active_key_id; | ||
310 | asoc->asoc_shared_key = NULL; | ||
311 | |||
312 | asoc->default_hmac_id = 0; | ||
313 | /* Save the hmacs and chunks list into this association */ | ||
314 | if (ep->auth_hmacs_list) | ||
315 | memcpy(asoc->c.auth_hmacs, ep->auth_hmacs_list, | ||
316 | ntohs(ep->auth_hmacs_list->param_hdr.length)); | ||
317 | if (ep->auth_chunk_list) | ||
318 | memcpy(asoc->c.auth_chunks, ep->auth_chunk_list, | ||
319 | ntohs(ep->auth_chunk_list->param_hdr.length)); | ||
320 | |||
321 | /* Get the AUTH random number for this association */ | ||
322 | p = (sctp_paramhdr_t *)asoc->c.auth_random; | ||
323 | p->type = SCTP_PARAM_RANDOM; | ||
324 | p->length = htons(sizeof(sctp_paramhdr_t) + SCTP_AUTH_RANDOM_LENGTH); | ||
325 | get_random_bytes(p+1, SCTP_AUTH_RANDOM_LENGTH); | ||
326 | |||
301 | return asoc; | 327 | return asoc; |
302 | 328 | ||
303 | fail_init: | 329 | fail_init: |
@@ -407,6 +433,12 @@ void sctp_association_free(struct sctp_association *asoc) | |||
407 | if (asoc->addip_last_asconf) | 433 | if (asoc->addip_last_asconf) |
408 | sctp_chunk_free(asoc->addip_last_asconf); | 434 | sctp_chunk_free(asoc->addip_last_asconf); |
409 | 435 | ||
436 | /* AUTH - Free the endpoint shared keys */ | ||
437 | sctp_auth_destroy_keys(&asoc->endpoint_shared_keys); | ||
438 | |||
439 | /* AUTH - Free the association shared key */ | ||
440 | sctp_auth_key_put(asoc->asoc_shared_key); | ||
441 | |||
410 | sctp_association_put(asoc); | 442 | sctp_association_put(asoc); |
411 | } | 443 | } |
412 | 444 | ||
@@ -1112,6 +1144,8 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
1112 | sctp_assoc_set_id(asoc, GFP_ATOMIC); | 1144 | sctp_assoc_set_id(asoc, GFP_ATOMIC); |
1113 | } | 1145 | } |
1114 | } | 1146 | } |
1147 | |||
1148 | /* SCTP-AUTH: XXX something needs to be done here*/ | ||
1115 | } | 1149 | } |
1116 | 1150 | ||
1117 | /* Update the retran path for sending a retransmitted packet. | 1151 | /* Update the retran path for sending a retransmitted packet. |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 22371185efb6..c8d5023606a5 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -69,12 +69,56 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
69 | struct sock *sk, | 69 | struct sock *sk, |
70 | gfp_t gfp) | 70 | gfp_t gfp) |
71 | { | 71 | { |
72 | struct sctp_hmac_algo_param *auth_hmacs = NULL; | ||
73 | struct sctp_chunks_param *auth_chunks = NULL; | ||
74 | struct sctp_shared_key *null_key; | ||
75 | int err; | ||
76 | |||
72 | memset(ep, 0, sizeof(struct sctp_endpoint)); | 77 | memset(ep, 0, sizeof(struct sctp_endpoint)); |
73 | 78 | ||
74 | ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); | 79 | ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); |
75 | if (!ep->digest) | 80 | if (!ep->digest) |
76 | return NULL; | 81 | return NULL; |
77 | 82 | ||
83 | if (sctp_auth_enable) { | ||
84 | /* Allocate space for HMACS and CHUNKS authentication | ||
85 | * variables. There are arrays that we encode directly | ||
86 | * into parameters to make the rest of the operations easier. | ||
87 | */ | ||
88 | auth_hmacs = kzalloc(sizeof(sctp_hmac_algo_param_t) + | ||
89 | sizeof(__u16) * SCTP_AUTH_NUM_HMACS, gfp); | ||
90 | if (!auth_hmacs) | ||
91 | goto nomem; | ||
92 | |||
93 | auth_chunks = kzalloc(sizeof(sctp_chunks_param_t) + | ||
94 | SCTP_NUM_CHUNK_TYPES, gfp); | ||
95 | if (!auth_chunks) | ||
96 | goto nomem; | ||
97 | |||
98 | /* Initialize the HMACS parameter. | ||
99 | * SCTP-AUTH: Section 3.3 | ||
100 | * Every endpoint supporting SCTP chunk authentication MUST | ||
101 | * support the HMAC based on the SHA-1 algorithm. | ||
102 | */ | ||
103 | auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO; | ||
104 | auth_hmacs->param_hdr.length = | ||
105 | htons(sizeof(sctp_paramhdr_t) + 2); | ||
106 | auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1); | ||
107 | |||
108 | /* Initialize the CHUNKS parameter */ | ||
109 | auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; | ||
110 | |||
111 | /* If the Add-IP functionality is enabled, we must | ||
112 | * authenticate, ASCONF and ASCONF-ACK chunks | ||
113 | */ | ||
114 | if (sctp_addip_enable) { | ||
115 | auth_chunks->chunks[0] = SCTP_CID_ASCONF; | ||
116 | auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; | ||
117 | auth_chunks->param_hdr.length = | ||
118 | htons(sizeof(sctp_paramhdr_t) + 2); | ||
119 | } | ||
120 | } | ||
121 | |||
78 | /* Initialize the base structure. */ | 122 | /* Initialize the base structure. */ |
79 | /* What type of endpoint are we? */ | 123 | /* What type of endpoint are we? */ |
80 | ep->base.type = SCTP_EP_TYPE_SOCKET; | 124 | ep->base.type = SCTP_EP_TYPE_SOCKET; |
@@ -114,7 +158,36 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
114 | ep->last_key = ep->current_key = 0; | 158 | ep->last_key = ep->current_key = 0; |
115 | ep->key_changed_at = jiffies; | 159 | ep->key_changed_at = jiffies; |
116 | 160 | ||
161 | /* SCTP-AUTH extensions*/ | ||
162 | INIT_LIST_HEAD(&ep->endpoint_shared_keys); | ||
163 | null_key = sctp_auth_shkey_create(0, GFP_KERNEL); | ||
164 | if (!null_key) | ||
165 | goto nomem; | ||
166 | |||
167 | list_add(&null_key->key_list, &ep->endpoint_shared_keys); | ||
168 | |||
169 | /* Allocate and initialize transorms arrays for suported HMACs. */ | ||
170 | err = sctp_auth_init_hmacs(ep, gfp); | ||
171 | if (err) | ||
172 | goto nomem_hmacs; | ||
173 | |||
174 | /* Add the null key to the endpoint shared keys list and | ||
175 | * set the hmcas and chunks pointers. | ||
176 | */ | ||
177 | ep->auth_hmacs_list = auth_hmacs; | ||
178 | ep->auth_chunk_list = auth_chunks; | ||
179 | |||
117 | return ep; | 180 | return ep; |
181 | |||
182 | nomem_hmacs: | ||
183 | sctp_auth_destroy_keys(&ep->endpoint_shared_keys); | ||
184 | nomem: | ||
185 | /* Free all allocations */ | ||
186 | kfree(auth_hmacs); | ||
187 | kfree(auth_chunks); | ||
188 | kfree(ep->digest); | ||
189 | return NULL; | ||
190 | |||
118 | } | 191 | } |
119 | 192 | ||
120 | /* Create a sctp_endpoint with all that boring stuff initialized. | 193 | /* Create a sctp_endpoint with all that boring stuff initialized. |
@@ -187,6 +260,16 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) | |||
187 | /* Free the digest buffer */ | 260 | /* Free the digest buffer */ |
188 | kfree(ep->digest); | 261 | kfree(ep->digest); |
189 | 262 | ||
263 | /* SCTP-AUTH: Free up AUTH releated data such as shared keys | ||
264 | * chunks and hmacs arrays that were allocated | ||
265 | */ | ||
266 | sctp_auth_destroy_keys(&ep->endpoint_shared_keys); | ||
267 | kfree(ep->auth_hmacs_list); | ||
268 | kfree(ep->auth_chunk_list); | ||
269 | |||
270 | /* AUTH - Free any allocated HMAC transform containers */ | ||
271 | sctp_auth_destroy_hmacs(ep->auth_hmacs); | ||
272 | |||
190 | /* Cleanup. */ | 273 | /* Cleanup. */ |
191 | sctp_inq_free(&ep->base.inqueue); | 274 | sctp_inq_free(&ep->base.inqueue); |
192 | sctp_bind_addr_free(&ep->base.bind_addr); | 275 | sctp_bind_addr_free(&ep->base.bind_addr); |
diff --git a/net/sctp/output.c b/net/sctp/output.c index d85543def754..49b9f5f031a4 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -79,7 +79,9 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, | |||
79 | packet->vtag = vtag; | 79 | packet->vtag = vtag; |
80 | packet->has_cookie_echo = 0; | 80 | packet->has_cookie_echo = 0; |
81 | packet->has_sack = 0; | 81 | packet->has_sack = 0; |
82 | packet->has_auth = 0; | ||
82 | packet->ipfragok = 0; | 83 | packet->ipfragok = 0; |
84 | packet->auth = NULL; | ||
83 | 85 | ||
84 | if (ecn_capable && sctp_packet_empty(packet)) { | 86 | if (ecn_capable && sctp_packet_empty(packet)) { |
85 | chunk = sctp_get_ecne_prepend(packet->transport->asoc); | 87 | chunk = sctp_get_ecne_prepend(packet->transport->asoc); |
@@ -121,8 +123,10 @@ struct sctp_packet *sctp_packet_init(struct sctp_packet *packet, | |||
121 | packet->vtag = 0; | 123 | packet->vtag = 0; |
122 | packet->has_cookie_echo = 0; | 124 | packet->has_cookie_echo = 0; |
123 | packet->has_sack = 0; | 125 | packet->has_sack = 0; |
126 | packet->has_auth = 0; | ||
124 | packet->ipfragok = 0; | 127 | packet->ipfragok = 0; |
125 | packet->malloced = 0; | 128 | packet->malloced = 0; |
129 | packet->auth = NULL; | ||
126 | return packet; | 130 | return packet; |
127 | } | 131 | } |
128 | 132 | ||
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 3ec8b12b6da4..4e6b59e8b695 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1185,6 +1185,9 @@ SCTP_STATIC __init int sctp_init(void) | |||
1185 | /* Enable PR-SCTP by default. */ | 1185 | /* Enable PR-SCTP by default. */ |
1186 | sctp_prsctp_enable = 1; | 1186 | sctp_prsctp_enable = 1; |
1187 | 1187 | ||
1188 | /* Disable AUTH by default. */ | ||
1189 | sctp_auth_enable = 0; | ||
1190 | |||
1188 | sctp_sysctl_register(); | 1191 | sctp_sysctl_register(); |
1189 | 1192 | ||
1190 | INIT_LIST_HEAD(&sctp_address_families); | 1193 | INIT_LIST_HEAD(&sctp_address_families); |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 39b10ee2f017..0669778e4335 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -254,6 +254,15 @@ static ctl_table sctp_table[] = { | |||
254 | .mode = 0644, | 254 | .mode = 0644, |
255 | .proc_handler = &proc_dointvec, | 255 | .proc_handler = &proc_dointvec, |
256 | }, | 256 | }, |
257 | { | ||
258 | .ctl_name = CTL_UNNUMBERED, | ||
259 | .procname = "auth_enable", | ||
260 | .data = &sctp_auth_enable, | ||
261 | .maxlen = sizeof(int), | ||
262 | .mode = 0644, | ||
263 | .proc_handler = &proc_dointvec, | ||
264 | .strategy = &sysctl_intvec | ||
265 | }, | ||
257 | { .ctl_name = 0 } | 266 | { .ctl_name = 0 } |
258 | }; | 267 | }; |
259 | 268 | ||