diff options
Diffstat (limited to 'net/sctp/auth.c')
| -rw-r--r-- | net/sctp/auth.c | 101 | 
1 files changed, 94 insertions, 7 deletions
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index de4c78d4a21e..4278764d82b8 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -389,7 +389,7 @@ int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)  	/* If we don't support AUTH, or peer is not capable  	 * we don't need to do anything.  	 */ -	if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) +	if (!asoc->peer.auth_capable)  		return 0;  	/* If the key_id is non-zero and we couldn't find an @@ -675,7 +675,7 @@ int sctp_auth_send_cid(enum sctp_cid chunk, const struct sctp_association *asoc)  	if (!asoc)  		return 0; -	if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) +	if (!asoc->peer.auth_capable)  		return 0;  	return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); @@ -687,7 +687,7 @@ int sctp_auth_recv_cid(enum sctp_cid chunk, const struct sctp_association *asoc)  	if (!asoc)  		return 0; -	if (!asoc->ep->auth_enable) +	if (!asoc->peer.auth_capable)  		return 0;  	return __sctp_auth_cid(chunk, @@ -831,10 +831,15 @@ int sctp_auth_set_key(struct sctp_endpoint *ep,  	/* Try to find the given key id to see if  	 * we are doing a replace, or adding a new key  	 */ -	if (asoc) +	if (asoc) { +		if (!asoc->peer.auth_capable) +			return -EACCES;  		sh_keys = &asoc->endpoint_shared_keys; -	else +	} else { +		if (!ep->auth_enable) +			return -EACCES;  		sh_keys = &ep->endpoint_shared_keys; +	}  	key_for_each(shkey, sh_keys) {  		if (shkey->key_id == auth_key->sca_keynumber) { @@ -875,10 +880,15 @@ int sctp_auth_set_active_key(struct sctp_endpoint *ep,  	int found = 0;  	/* The key identifier MUST correst to an existing key */ -	if (asoc) +	if (asoc) { +		if (!asoc->peer.auth_capable) +			return -EACCES;  		sh_keys = &asoc->endpoint_shared_keys; -	else +	} else { +		if (!ep->auth_enable) +			return -EACCES;  		sh_keys = &ep->endpoint_shared_keys; +	}  	key_for_each(key, sh_keys) {  		if (key->key_id == key_id) { @@ -911,11 +921,15 @@ int sctp_auth_del_key_id(struct sctp_endpoint *ep,  	 * The key identifier MUST correst to an existing key  	 */  	if (asoc) { +		if (!asoc->peer.auth_capable) +			return -EACCES;  		if (asoc->active_key_id == key_id)  			return -EINVAL;  		sh_keys = &asoc->endpoint_shared_keys;  	} else { +		if (!ep->auth_enable) +			return -EACCES;  		if (ep->active_key_id == key_id)  			return -EINVAL; @@ -950,11 +964,15 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,  	 * The key identifier MUST correst to an existing key  	 */  	if (asoc) { +		if (!asoc->peer.auth_capable) +			return -EACCES;  		if (asoc->active_key_id == key_id)  			return -EINVAL;  		sh_keys = &asoc->endpoint_shared_keys;  	} else { +		if (!ep->auth_enable) +			return -EACCES;  		if (ep->active_key_id == key_id)  			return -EINVAL; @@ -989,3 +1007,72 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,  	return 0;  } + +int sctp_auth_init(struct sctp_endpoint *ep, gfp_t gfp) +{ +	int err = -ENOMEM; + +	/* Allocate space for HMACS and CHUNKS authentication +	 * variables.  There are arrays that we encode directly +	 * into parameters to make the rest of the operations easier. +	 */ +	if (!ep->auth_hmacs_list) { +		struct sctp_hmac_algo_param *auth_hmacs; + +		auth_hmacs = kzalloc(struct_size(auth_hmacs, hmac_ids, +						 SCTP_AUTH_NUM_HMACS), gfp); +		if (!auth_hmacs) +			goto nomem; +		/* Initialize the HMACS parameter. +		 * SCTP-AUTH: Section 3.3 +		 *    Every endpoint supporting SCTP chunk authentication MUST +		 *    support the HMAC based on the SHA-1 algorithm. +		 */ +		auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO; +		auth_hmacs->param_hdr.length = +				htons(sizeof(struct sctp_paramhdr) + 2); +		auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1); +		ep->auth_hmacs_list = auth_hmacs; +	} + +	if (!ep->auth_chunk_list) { +		struct sctp_chunks_param *auth_chunks; + +		auth_chunks = kzalloc(sizeof(*auth_chunks) + +				      SCTP_NUM_CHUNK_TYPES, gfp); +		if (!auth_chunks) +			goto nomem; +		/* Initialize the CHUNKS parameter */ +		auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; +		auth_chunks->param_hdr.length = +				htons(sizeof(struct sctp_paramhdr)); +		ep->auth_chunk_list = auth_chunks; +	} + +	/* Allocate and initialize transorms arrays for supported +	 * HMACs. +	 */ +	err = sctp_auth_init_hmacs(ep, gfp); +	if (err) +		goto nomem; + +	return 0; + +nomem: +	/* Free all allocations */ +	kfree(ep->auth_hmacs_list); +	kfree(ep->auth_chunk_list); +	ep->auth_hmacs_list = NULL; +	ep->auth_chunk_list = NULL; +	return err; +} + +void sctp_auth_free(struct sctp_endpoint *ep) +{ +	kfree(ep->auth_hmacs_list); +	kfree(ep->auth_chunk_list); +	ep->auth_hmacs_list = NULL; +	ep->auth_chunk_list = NULL; +	sctp_auth_destroy_hmacs(ep->auth_hmacs); +	ep->auth_hmacs = NULL; +}  |