[PATCH 10/13] SCTP: enable per-namespace authentication configuration.

From: Jan Ariyasu
Date: Sat Aug 04 2012 - 17:34:19 EST


This is the first of three patches to set authentication
by namespace. In this patch, the relevant routines in auth.c
now check to see if auth_enable is set as a namespace parameter
instead of checking the global parameter sctp_auth_enable.

Signed-off-by: Jan Ariyasu <jan.ariyasu@xxxxxx>
---
include/net/sctp/auth.h | 14 +++++++++-----
include/net/sctp/structs.h | 3 ++-
net/sctp/associola.c | 7 ++++---
net/sctp/auth.c | 29 +++++++++++++++++++----------
net/sctp/chunk.c | 5 +++--
net/sctp/endpointola.c | 6 ++++--
net/sctp/sm_make_chunk.c | 2 +-
net/sctp/sm_sideeffect.c | 2 +-
net/sctp/sm_statefuns.c | 16 ++++++++--------
net/sctp/socket.c | 10 ++++++----
10 files changed, 57 insertions(+), 37 deletions(-)

diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 49bc957..e4e88cb 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -89,14 +89,15 @@ static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key)
void sctp_auth_key_put(struct sctp_auth_bytes *key);
struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp);
void sctp_auth_destroy_keys(struct list_head *keys);
-int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp);
+int sctp_auth_asoc_init_active_key(struct net *net,
+ struct sctp_association *asoc, gfp_t gfp);
struct sctp_shared_key *sctp_auth_get_shkey(
const struct sctp_association *asoc,
__u16 key_id);
int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep,
struct sctp_association *asoc,
gfp_t gfp);
-int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp);
+int sctp_auth_init_hmacs(struct net *net, struct sctp_endpoint *ep, gfp_t gfp);
void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]);
struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id);
struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc);
@@ -104,8 +105,10 @@ void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc,
struct sctp_hmac_algo_param *hmacs);
int sctp_auth_asoc_verify_hmac_id(const struct sctp_association *asoc,
__be16 hmac_id);
-int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
-int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
+int sctp_auth_send_cid(struct net *net,
+ sctp_cid_t chunk, const struct sctp_association *asoc);
+int sctp_auth_recv_cid(struct net *net,
+ sctp_cid_t chunk, const struct sctp_association *asoc);
void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
struct sk_buff *skb,
struct sctp_auth_chunk *auth, gfp_t gfp);
@@ -117,7 +120,8 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
int sctp_auth_set_key(struct sctp_endpoint *ep,
struct sctp_association *asoc,
struct sctp_authkey *auth_key);
-int sctp_auth_set_active_key(struct sctp_endpoint *ep,
+int sctp_auth_set_active_key(struct net *net,
+ struct sctp_endpoint *ep,
struct sctp_association *asoc,
__u16 key_id);
int sctp_auth_del_key_id(struct sctp_endpoint *ep,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index b016da6..dc2998a 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -805,7 +805,8 @@ struct sctp_datamsg {
can_delay; /* should this message be Nagle delayed */
};

-struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
+struct sctp_datamsg *sctp_datamsg_from_user(struct net *,
+ struct sctp_association *,
struct sctp_sndrcvinfo *,
struct msghdr *, int len);
void sctp_datamsg_free(struct sctp_datamsg *);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index b778eba..b640162 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1147,8 +1147,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
* MUST silently discard these chunks if they are not placed
* after an AUTH chunk in the packet.
*/
- if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
- continue;
+ if (sctp_auth_recv_cid(net, subtype.chunk, asoc) &&
+ !chunk->auth)
+ continue;

/* Remember where the last DATA chunk came from so we
* know where to send the SACK.
@@ -1305,7 +1306,7 @@ void sctp_assoc_update(struct net *net,
new->peer.peer_hmacs = NULL;

sctp_auth_key_put(asoc->asoc_shared_key);
- sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC);
+ sctp_auth_asoc_init_active_key(net, asoc, GFP_ATOMIC);
}

/* Update the retran path for sending a retransmitted packet.
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index bf81204..36d8059 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -390,15 +390,18 @@ nomem:
/* Public interface to creat the association shared key.
* See code above for the algorithm.
*/
-int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp)
+int sctp_auth_asoc_init_active_key(struct net *net,
+ struct sctp_association *asoc,
+ gfp_t gfp)
{
struct sctp_auth_bytes *secret;
struct sctp_shared_key *ep_key;
+ struct sctp_net_params *net_params = sctp_get_params(net);

/* If we don't support AUTH, or peer is not capable
* we don't need to do anything.
*/
- if (!sctp_auth_enable || !asoc->peer.auth_capable)
+ if (!net_params->auth_enable || !asoc->peer.auth_capable)
return 0;

/* If the key_id is non-zero and we couldn't find an
@@ -443,13 +446,14 @@ struct sctp_shared_key *sctp_auth_get_shkey(
* user context. This forces us to pre-allocated all possible transforms
* at the endpoint init time.
*/
-int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp)
+int sctp_auth_init_hmacs(struct net *net, struct sctp_endpoint *ep, gfp_t gfp)
{
struct crypto_hash *tfm = NULL;
__u16 id;
+ struct sctp_net_params *net_params = sctp_get_params(net);

/* if the transforms are already allocted, we are done */
- if (!sctp_auth_enable) {
+ if (!net_params->auth_enable) {
ep->auth_hmacs = NULL;
return 0;
}
@@ -672,18 +676,22 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param)
}

/* Check if peer requested that this chunk is authenticated */
-int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
+int sctp_auth_send_cid(struct net *net, sctp_cid_t chunk,
+ const struct sctp_association *asoc)
{
- if (!sctp_auth_enable || !asoc || !asoc->peer.auth_capable)
+ struct sctp_net_params *net_params = sctp_get_params(net);
+ if (!net_params->auth_enable || !asoc || !asoc->peer.auth_capable)
return 0;

return __sctp_auth_cid(chunk, asoc->peer.peer_chunks);
}

/* Check if we requested that peer authenticate this chunk. */
-int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc)
+int sctp_auth_recv_cid(struct net *net, sctp_cid_t chunk,
+ const struct sctp_association *asoc)
{
- if (!sctp_auth_enable || !asoc)
+ struct sctp_net_params *net_params = sctp_get_params(net);
+ if (!net_params->auth_enable || !asoc)
return 0;

return __sctp_auth_cid(chunk,
@@ -876,7 +884,8 @@ nomem:
return -ENOMEM;
}

-int sctp_auth_set_active_key(struct sctp_endpoint *ep,
+int sctp_auth_set_active_key(struct net *net,
+ struct sctp_endpoint *ep,
struct sctp_association *asoc,
__u16 key_id)
{
@@ -902,7 +911,7 @@ int sctp_auth_set_active_key(struct sctp_endpoint *ep,

if (asoc) {
asoc->active_key_id = key_id;
- sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL);
+ sctp_auth_asoc_init_active_key(net, asoc, GFP_KERNEL);
} else
ep->active_key_id = key_id;

diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 6c85564..5211278 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -169,7 +169,8 @@ static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chu
* with a reasonable guess than always doing our fragmentation on the
* soft-interrupt.
*/
-struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
+struct sctp_datamsg *sctp_datamsg_from_user(struct net *net,
+ struct sctp_association *asoc,
struct sctp_sndrcvinfo *sinfo,
struct msghdr *msgh, int msg_len)
{
@@ -209,7 +210,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
* we need to accound for bundling of the AUTH chunks along with
* DATA.
*/
- if (sctp_auth_send_cid(SCTP_CID_DATA, asoc)) {
+ if (sctp_auth_send_cid(net, SCTP_CID_DATA, asoc)) {
struct sctp_hmac *hmac_desc = sctp_auth_asoc_get_hmac(asoc);

if (hmac_desc)
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index de42bd4..750df47 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -69,6 +69,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
struct sctp_chunks_param *auth_chunks = NULL;
struct sctp_shared_key *null_key;
int err;
+ struct net *net = sock_net(sk);

ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp);
if (!ep->digest)
@@ -163,7 +164,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
list_add(&null_key->key_list, &ep->endpoint_shared_keys);

/* Allocate and initialize transorms arrays for suported HMACs. */
- err = sctp_auth_init_hmacs(ep, gfp);
+ err = sctp_auth_init_hmacs(net, ep, gfp);
if (err)
goto nomem_hmacs;

@@ -465,7 +466,8 @@ normal:
}

state = asoc ? asoc->state : SCTP_STATE_CLOSED;
- if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth)
+ if (sctp_auth_recv_cid(sock_net(sk), subtype.chunk, asoc)
+ && !chunk->auth)
continue;

/* Remember where the last DATA chunk came from so we
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index af02b44..1d6c8b6 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1365,7 +1365,7 @@ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr);

/* Determine if the chunk needs to be authenticated */
- if (sctp_auth_send_cid(type, asoc))
+ if (sctp_auth_send_cid(&init_net, type, asoc))
retval->auth = 1;

/* Set the skb to the belonging sock for accounting. */
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index c683d88..7bd2d6d 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1711,7 +1711,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
break;

case SCTP_CMD_ASSOC_SHKEY:
- error = sctp_auth_asoc_init_active_key(asoc,
+ error = sctp_auth_asoc_init_active_key(net, asoc,
GFP_ATOMIC);
break;
case SCTP_CMD_UPDATE_INITTAG:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 0d4aaa9..4cd027a 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -572,14 +572,14 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net,
* can't destroy this association just because the packet
* was malformed.
*/
- if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
- return sctp_sf_pdiscard(net, ep, asoc, type, arg,
- commands);
+ if (sctp_auth_recv_cid(net, SCTP_CID_ABORT, asoc))
+ return sctp_sf_pdiscard(net, ep, asoc, type,
+ arg, commands);

SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
return sctp_stop_t1_and_abort(net, commands, error,
- ECONNREFUSED, asoc,
- chunk->transport);
+ ECONNREFUSED,
+ asoc, chunk->transport);
}

/* Tag the variable length parameters. Note that we never
@@ -757,7 +757,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net,
* sctp_process_init, set up the assocaition shared keys as
* necessary so that we can potentially authenticate the ACK
*/
- error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC);
+ error = sctp_auth_asoc_init_active_key(net, new_asoc, GFP_ATOMIC);
if (error)
goto nomem_init;

@@ -4364,7 +4364,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
* can't destroy this association just because the packet
* was malformed.
*/
- if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
+ if (sctp_auth_recv_cid(net, SCTP_CID_ABORT, asoc))
goto discard;

/* Make the abort chunk. */
@@ -4490,7 +4490,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen(
struct sctp_paramhdr *param = ext;
struct sctp_chunk *abort = NULL;

- if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
+ if (sctp_auth_recv_cid(net, SCTP_CID_ABORT, asoc))
goto discard;

/* Make the abort chunk. */
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 78e4576..d14ac7d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -101,9 +101,9 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
union sctp_addr *addr, int len);
static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
-static int sctp_send_asconf_add_ip(struct net*, struct sock *,
+static int sctp_send_asconf_add_ip(struct net *, struct sock *,
struct sockaddr *, int);
-static int sctp_send_asconf_del_ip(struct net*, struct sock *,
+static int sctp_send_asconf_del_ip(struct net *, struct sock *,
struct sockaddr *, int);
static int sctp_send_asconf(struct sctp_association *asoc,
struct sctp_chunk *chunk);
@@ -1599,6 +1599,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
__u16 sinfo_flags = 0;
struct sctp_datamsg *datamsg;
int msg_flags = msg->msg_flags;
+ struct net *net = sock_net(sk);

SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %zu)\n",
sk, msg, msg_len);
@@ -1920,7 +1921,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}

/* Break the message into multiple chunks of maximum size. */
- datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
+ datamsg = sctp_datamsg_from_user(net, asoc, sinfo, msg, msg_len);
if (!datamsg) {
err = -ENOMEM;
goto out_free;
@@ -3409,6 +3410,7 @@ static int sctp_setsockopt_active_key(struct sock *sk,
{
struct sctp_authkeyid val;
struct sctp_association *asoc;
+ struct net *net = sock_net(sk);

if (!sctp_auth_enable)
return -EACCES;
@@ -3422,7 +3424,7 @@ static int sctp_setsockopt_active_key(struct sock *sk,
if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
return -EINVAL;

- return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc,
+ return sctp_auth_set_active_key(net, sctp_sk(sk)->ep, asoc,
val.scact_keynumber);
}

--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/