aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-09-16 22:34:00 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:32 -0400
commit65b07e5d0d09c77e98050b5f0146ead29e5add32 (patch)
treeb5c5ac79969401238ce2c01d3999016238b02b93
parentbbd0d59809f923ea2b540cbd781b32110e249f6e (diff)
[SCTP]: API updates to suport SCTP-AUTH extensions.
Add SCTP-AUTH API. The API implemented here was agreed to between implementors at the 9th SCTP Interop. It will be documented in the next revision of the SCTP socket API spec. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/auth.h16
-rw-r--r--include/net/sctp/ulpevent.h4
-rw-r--r--include/net/sctp/user.h90
-rw-r--r--net/sctp/auth.c193
-rw-r--r--net/sctp/sm_statefuns.c13
-rw-r--r--net/sctp/socket.c304
-rw-r--r--net/sctp/ulpevent.c37
7 files changed, 657 insertions, 0 deletions
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 10c8010552ff..4945954a16af 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -43,6 +43,7 @@
43struct sctp_endpoint; 43struct sctp_endpoint;
44struct sctp_association; 44struct sctp_association;
45struct sctp_authkey; 45struct sctp_authkey;
46struct sctp_hmacalgo;
46 47
47/* 48/*
48 * Define a generic struct that will hold all the info 49 * Define a generic struct that will hold all the info
@@ -109,4 +110,19 @@ int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc);
109void sctp_auth_calculate_hmac(const struct sctp_association *asoc, 110void sctp_auth_calculate_hmac(const struct sctp_association *asoc,
110 struct sk_buff *skb, 111 struct sk_buff *skb,
111 struct sctp_auth_chunk *auth, gfp_t gfp); 112 struct sctp_auth_chunk *auth, gfp_t gfp);
113
114/* API Helpers */
115int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id);
116int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
117 struct sctp_hmacalgo *hmacs);
118int sctp_auth_set_key(struct sctp_endpoint *ep,
119 struct sctp_association *asoc,
120 struct sctp_authkey *auth_key);
121int sctp_auth_set_active_key(struct sctp_endpoint *ep,
122 struct sctp_association *asoc,
123 __u16 key_id);
124int sctp_auth_del_key_id(struct sctp_endpoint *ep,
125 struct sctp_association *asoc,
126 __u16 key_id);
127
112#endif 128#endif
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index de88ed5b0ba6..922a151eb93c 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -128,6 +128,10 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
128 struct sctp_chunk *chunk, 128 struct sctp_chunk *chunk,
129 gfp_t gfp); 129 gfp_t gfp);
130 130
131struct sctp_ulpevent *sctp_ulpevent_make_authkey(
132 const struct sctp_association *asoc, __u16 key_id,
133 __u32 indication, gfp_t gfp);
134
131void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, 135void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event,
132 struct msghdr *); 136 struct msghdr *);
133__u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event); 137__u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 6d2b57758cca..00848b641f59 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -103,6 +103,21 @@ enum sctp_optname {
103#define SCTP_PARTIAL_DELIVERY_POINT SCTP_PARTIAL_DELIVERY_POINT 103#define SCTP_PARTIAL_DELIVERY_POINT SCTP_PARTIAL_DELIVERY_POINT
104 SCTP_MAX_BURST, /* Set/Get max burst */ 104 SCTP_MAX_BURST, /* Set/Get max burst */
105#define SCTP_MAX_BURST SCTP_MAX_BURST 105#define SCTP_MAX_BURST SCTP_MAX_BURST
106 SCTP_AUTH_CHUNK, /* Set only: add a chunk type to authenticat */
107#define SCTP_AUTH_CHUNK SCTP_AUTH_CHUNK
108 SCTP_HMAC_IDENT,
109#define SCTP_HMAC_IDENT SCTP_HMAC_IDENT
110 SCTP_AUTH_KEY,
111#define SCTP_AUTH_KEY SCTP_AUTH_KEY
112 SCTP_AUTH_ACTIVE_KEY,
113#define SCTP_AUTH_ACTIVE_KEY SCTP_AUTH_ACTIVE_KEY
114 SCTP_AUTH_DELETE_KEY,
115#define SCTP_AUTH_DELETE_KEY SCTP_AUTH_DELETE_KEY
116 SCTP_PEER_AUTH_CHUNKS, /* Read only */
117#define SCTP_PEER_AUTH_CHUNKS SCTP_PEER_AUTH_CHUNKS
118 SCTP_LOCAL_AUTH_CHUNKS, /* Read only */
119#define SCTP_LOCAL_AUTH_CHUNKS SCTP_LOCAL_AUTH_CHUNKS
120
106 121
107 /* Internal Socket Options. Some of the sctp library functions are 122 /* Internal Socket Options. Some of the sctp library functions are
108 * implemented using these socket options. 123 * implemented using these socket options.
@@ -370,6 +385,19 @@ struct sctp_pdapi_event {
370 385
371enum { SCTP_PARTIAL_DELIVERY_ABORTED=0, }; 386enum { SCTP_PARTIAL_DELIVERY_ABORTED=0, };
372 387
388struct sctp_authkey_event {
389 __u16 auth_type;
390 __u16 auth_flags;
391 __u32 auth_length;
392 __u16 auth_keynumber;
393 __u16 auth_altkeynumber;
394 __u32 auth_indication;
395 sctp_assoc_t auth_assoc_id;
396};
397
398enum { SCTP_AUTH_NEWKEY = 0, };
399
400
373/* 401/*
374 * Described in Section 7.3 402 * Described in Section 7.3
375 * Ancillary Data and Notification Interest Options 403 * Ancillary Data and Notification Interest Options
@@ -405,6 +433,7 @@ union sctp_notification {
405 struct sctp_shutdown_event sn_shutdown_event; 433 struct sctp_shutdown_event sn_shutdown_event;
406 struct sctp_adaptation_event sn_adaptation_event; 434 struct sctp_adaptation_event sn_adaptation_event;
407 struct sctp_pdapi_event sn_pdapi_event; 435 struct sctp_pdapi_event sn_pdapi_event;
436 struct sctp_authkey_event sn_authkey_event;
408}; 437};
409 438
410/* Section 5.3.1 439/* Section 5.3.1
@@ -421,6 +450,7 @@ enum sctp_sn_type {
421 SCTP_SHUTDOWN_EVENT, 450 SCTP_SHUTDOWN_EVENT,
422 SCTP_PARTIAL_DELIVERY_EVENT, 451 SCTP_PARTIAL_DELIVERY_EVENT,
423 SCTP_ADAPTATION_INDICATION, 452 SCTP_ADAPTATION_INDICATION,
453 SCTP_AUTHENTICATION_EVENT,
424}; 454};
425 455
426/* Notification error codes used to fill up the error fields in some 456/* Notification error codes used to fill up the error fields in some
@@ -539,6 +569,54 @@ struct sctp_paddrparams {
539 __u32 spp_flags; 569 __u32 spp_flags;
540} __attribute__((packed, aligned(4))); 570} __attribute__((packed, aligned(4)));
541 571
572/*
573 * 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK)
574 *
575 * This set option adds a chunk type that the user is requesting to be
576 * received only in an authenticated way. Changes to the list of chunks
577 * will only effect future associations on the socket.
578 */
579struct sctp_authchunk {
580 __u8 sauth_chunk;
581};
582
583/*
584 * 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT)
585 *
586 * This option gets or sets the list of HMAC algorithms that the local
587 * endpoint requires the peer to use.
588*/
589struct sctp_hmacalgo {
590 __u16 shmac_num_idents;
591 __u16 shmac_idents[];
592};
593
594/*
595 * 7.1.20. Set a shared key (SCTP_AUTH_KEY)
596 *
597 * This option will set a shared secret key which is used to build an
598 * association shared key.
599 */
600struct sctp_authkey {
601 sctp_assoc_t sca_assoc_id;
602 __u16 sca_keynumber;
603 __u16 sca_keylen;
604 __u8 sca_key[];
605};
606
607/*
608 * 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY)
609 *
610 * This option will get or set the active shared key to be used to build
611 * the association shared key.
612 */
613
614struct sctp_authkeyid {
615 sctp_assoc_t scact_assoc_id;
616 __u16 scact_keynumber;
617};
618
619
542/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) 620/* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME)
543 * 621 *
544 * This options will get or set the delayed ack timer. The time is set 622 * This options will get or set the delayed ack timer. The time is set
@@ -608,6 +686,18 @@ struct sctp_status {
608}; 686};
609 687
610/* 688/*
689 * 7.2.3. Get the list of chunks the peer requires to be authenticated
690 * (SCTP_PEER_AUTH_CHUNKS)
691 *
692 * This option gets a list of chunks for a specified association that
693 * the peer requires to be received authenticated only.
694 */
695struct sctp_authchunks {
696 sctp_assoc_t gauth_assoc_id;
697 uint8_t gauth_chunks[];
698};
699
700/*
611 * 8.3, 8.5 get all peer/local addresses in an association. 701 * 8.3, 8.5 get all peer/local addresses in an association.
612 * This parameter struct is used by SCTP_GET_PEER_ADDRS and 702 * This parameter struct is used by SCTP_GET_PEER_ADDRS and
613 * SCTP_GET_LOCAL_ADDRS socket options used internally to implement 703 * SCTP_GET_LOCAL_ADDRS socket options used internally to implement
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index 2a29409a38d9..781810724714 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -743,3 +743,196 @@ free:
743 if (free_key) 743 if (free_key)
744 sctp_auth_key_put(asoc_key); 744 sctp_auth_key_put(asoc_key);
745} 745}
746
747/* API Helpers */
748
749/* Add a chunk to the endpoint authenticated chunk list */
750int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id)
751{
752 struct sctp_chunks_param *p = ep->auth_chunk_list;
753 __u16 nchunks;
754 __u16 param_len;
755
756 /* If this chunk is already specified, we are done */
757 if (__sctp_auth_cid(chunk_id, p))
758 return 0;
759
760 /* Check if we can add this chunk to the array */
761 param_len = ntohs(p->param_hdr.length);
762 nchunks = param_len - sizeof(sctp_paramhdr_t);
763 if (nchunks == SCTP_NUM_CHUNK_TYPES)
764 return -EINVAL;
765
766 p->chunks[nchunks] = chunk_id;
767 p->param_hdr.length = htons(param_len + 1);
768 return 0;
769}
770
771/* Add hmac identifires to the endpoint list of supported hmac ids */
772int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
773 struct sctp_hmacalgo *hmacs)
774{
775 int has_sha1 = 0;
776 __u16 id;
777 int i;
778
779 /* Scan the list looking for unsupported id. Also make sure that
780 * SHA1 is specified.
781 */
782 for (i = 0; i < hmacs->shmac_num_idents; i++) {
783 id = hmacs->shmac_idents[i];
784
785 if (SCTP_AUTH_HMAC_ID_SHA1 == id)
786 has_sha1 = 1;
787
788 if (!sctp_hmac_list[id].hmac_name)
789 return -EOPNOTSUPP;
790 }
791
792 if (!has_sha1)
793 return -EINVAL;
794
795 memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0],
796 hmacs->shmac_num_idents * sizeof(__u16));
797 ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) +
798 hmacs->shmac_num_idents * sizeof(__u16));
799 return 0;
800}
801
802/* Set a new shared key on either endpoint or association. If the
803 * the key with a same ID already exists, replace the key (remove the
804 * old key and add a new one).
805 */
806int sctp_auth_set_key(struct sctp_endpoint *ep,
807 struct sctp_association *asoc,
808 struct sctp_authkey *auth_key)
809{
810 struct sctp_shared_key *cur_key = NULL;
811 struct sctp_auth_bytes *key;
812 struct list_head *sh_keys;
813 int replace = 0;
814
815 /* Try to find the given key id to see if
816 * we are doing a replace, or adding a new key
817 */
818 if (asoc)
819 sh_keys = &asoc->endpoint_shared_keys;
820 else
821 sh_keys = &ep->endpoint_shared_keys;
822
823 key_for_each(cur_key, sh_keys) {
824 if (cur_key->key_id == auth_key->sca_keynumber) {
825 replace = 1;
826 break;
827 }
828 }
829
830 /* If we are not replacing a key id, we need to allocate
831 * a shared key.
832 */
833 if (!replace) {
834 cur_key = sctp_auth_shkey_create(auth_key->sca_keynumber,
835 GFP_KERNEL);
836 if (!cur_key)
837 return -ENOMEM;
838 }
839
840 /* Create a new key data based on the info passed in */
841 key = sctp_auth_create_key(auth_key->sca_keylen, GFP_KERNEL);
842 if (!key)
843 goto nomem;
844
845 memcpy(key->data, &auth_key->sca_key[0], auth_key->sca_keylen);
846
847 /* If we are replacing, remove the old keys data from the
848 * key id. If we are adding new key id, add it to the
849 * list.
850 */
851 if (replace)
852 sctp_auth_key_put(cur_key->key);
853 else
854 list_add(&cur_key->key_list, sh_keys);
855
856 cur_key->key = key;
857 sctp_auth_key_hold(key);
858
859 return 0;
860nomem:
861 if (!replace)
862 sctp_auth_shkey_free(cur_key);
863
864 return -ENOMEM;
865}
866
867int sctp_auth_set_active_key(struct sctp_endpoint *ep,
868 struct sctp_association *asoc,
869 __u16 key_id)
870{
871 struct sctp_shared_key *key;
872 struct list_head *sh_keys;
873 int found = 0;
874
875 /* The key identifier MUST correst to an existing key */
876 if (asoc)
877 sh_keys = &asoc->endpoint_shared_keys;
878 else
879 sh_keys = &ep->endpoint_shared_keys;
880
881 key_for_each(key, sh_keys) {
882 if (key->key_id == key_id) {
883 found = 1;
884 break;
885 }
886 }
887
888 if (!found)
889 return -EINVAL;
890
891 if (asoc) {
892 asoc->active_key_id = key_id;
893 sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL);
894 } else
895 ep->active_key_id = key_id;
896
897 return 0;
898}
899
900int sctp_auth_del_key_id(struct sctp_endpoint *ep,
901 struct sctp_association *asoc,
902 __u16 key_id)
903{
904 struct sctp_shared_key *key;
905 struct list_head *sh_keys;
906 int found = 0;
907
908 /* The key identifier MUST NOT be the current active key
909 * The key identifier MUST correst to an existing key
910 */
911 if (asoc) {
912 if (asoc->active_key_id == key_id)
913 return -EINVAL;
914
915 sh_keys = &asoc->endpoint_shared_keys;
916 } else {
917 if (ep->active_key_id == key_id)
918 return -EINVAL;
919
920 sh_keys = &ep->endpoint_shared_keys;
921 }
922
923 key_for_each(key, sh_keys) {
924 if (key->key_id == key_id) {
925 found = 1;
926 break;
927 }
928 }
929
930 if (!found)
931 return -EINVAL;
932
933 /* Delete the shared key */
934 list_del_init(&key->key_list);
935 sctp_auth_shkey_free(key);
936
937 return 0;
938}
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 5aef4aafdfdc..f01b408508ff 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3848,6 +3848,19 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
3848 break; 3848 break;
3849 } 3849 }
3850 3850
3851 if (asoc->active_key_id != ntohs(auth_hdr->shkey_id)) {
3852 struct sctp_ulpevent *ev;
3853
3854 ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id),
3855 SCTP_AUTH_NEWKEY, GFP_ATOMIC);
3856
3857 if (!ev)
3858 return -ENOMEM;
3859
3860 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
3861 SCTP_ULPEVENT(ev));
3862 }
3863
3851 return SCTP_DISPOSITION_CONSUME; 3864 return SCTP_DISPOSITION_CONSUME;
3852} 3865}
3853 3866
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 7738915011a0..f3e1a9c811ad 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2946,6 +2946,164 @@ static int sctp_setsockopt_maxburst(struct sock *sk,
2946 return 0; 2946 return 0;
2947} 2947}
2948 2948
2949/*
2950 * 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK)
2951 *
2952 * This set option adds a chunk type that the user is requesting to be
2953 * received only in an authenticated way. Changes to the list of chunks
2954 * will only effect future associations on the socket.
2955 */
2956static int sctp_setsockopt_auth_chunk(struct sock *sk,
2957 char __user *optval,
2958 int optlen)
2959{
2960 struct sctp_authchunk val;
2961
2962 if (optlen != sizeof(struct sctp_authchunk))
2963 return -EINVAL;
2964 if (copy_from_user(&val, optval, optlen))
2965 return -EFAULT;
2966
2967 switch (val.sauth_chunk) {
2968 case SCTP_CID_INIT:
2969 case SCTP_CID_INIT_ACK:
2970 case SCTP_CID_SHUTDOWN_COMPLETE:
2971 case SCTP_CID_AUTH:
2972 return -EINVAL;
2973 }
2974
2975 /* add this chunk id to the endpoint */
2976 return sctp_auth_ep_add_chunkid(sctp_sk(sk)->ep, val.sauth_chunk);
2977}
2978
2979/*
2980 * 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT)
2981 *
2982 * This option gets or sets the list of HMAC algorithms that the local
2983 * endpoint requires the peer to use.
2984 */
2985static int sctp_setsockopt_hmac_ident(struct sock *sk,
2986 char __user *optval,
2987 int optlen)
2988{
2989 struct sctp_hmacalgo *hmacs;
2990 int err;
2991
2992 if (optlen < sizeof(struct sctp_hmacalgo))
2993 return -EINVAL;
2994
2995 hmacs = kmalloc(optlen, GFP_KERNEL);
2996 if (!hmacs)
2997 return -ENOMEM;
2998
2999 if (copy_from_user(hmacs, optval, optlen)) {
3000 err = -EFAULT;
3001 goto out;
3002 }
3003
3004 if (hmacs->shmac_num_idents == 0 ||
3005 hmacs->shmac_num_idents > SCTP_AUTH_NUM_HMACS) {
3006 err = -EINVAL;
3007 goto out;
3008 }
3009
3010 err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs);
3011out:
3012 kfree(hmacs);
3013 return err;
3014}
3015
3016/*
3017 * 7.1.20. Set a shared key (SCTP_AUTH_KEY)
3018 *
3019 * This option will set a shared secret key which is used to build an
3020 * association shared key.
3021 */
3022static int sctp_setsockopt_auth_key(struct sock *sk,
3023 char __user *optval,
3024 int optlen)
3025{
3026 struct sctp_authkey *authkey;
3027 struct sctp_association *asoc;
3028 int ret;
3029
3030 if (optlen <= sizeof(struct sctp_authkey))
3031 return -EINVAL;
3032
3033 authkey = kmalloc(optlen, GFP_KERNEL);
3034 if (!authkey)
3035 return -ENOMEM;
3036
3037 if (copy_from_user(authkey, optval, optlen)) {
3038 ret = -EFAULT;
3039 goto out;
3040 }
3041
3042 asoc = sctp_id2assoc(sk, authkey->sca_assoc_id);
3043 if (!asoc && authkey->sca_assoc_id && sctp_style(sk, UDP)) {
3044 ret = -EINVAL;
3045 goto out;
3046 }
3047
3048 ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey);
3049out:
3050 kfree(authkey);
3051 return ret;
3052}
3053
3054/*
3055 * 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY)
3056 *
3057 * This option will get or set the active shared key to be used to build
3058 * the association shared key.
3059 */
3060static int sctp_setsockopt_active_key(struct sock *sk,
3061 char __user *optval,
3062 int optlen)
3063{
3064 struct sctp_authkeyid val;
3065 struct sctp_association *asoc;
3066
3067 if (optlen != sizeof(struct sctp_authkeyid))
3068 return -EINVAL;
3069 if (copy_from_user(&val, optval, optlen))
3070 return -EFAULT;
3071
3072 asoc = sctp_id2assoc(sk, val.scact_assoc_id);
3073 if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
3074 return -EINVAL;
3075
3076 return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc,
3077 val.scact_keynumber);
3078}
3079
3080/*
3081 * 7.1.22. Delete a shared key (SCTP_AUTH_DELETE_KEY)
3082 *
3083 * This set option will delete a shared secret key from use.
3084 */
3085static int sctp_setsockopt_del_key(struct sock *sk,
3086 char __user *optval,
3087 int optlen)
3088{
3089 struct sctp_authkeyid val;
3090 struct sctp_association *asoc;
3091
3092 if (optlen != sizeof(struct sctp_authkeyid))
3093 return -EINVAL;
3094 if (copy_from_user(&val, optval, optlen))
3095 return -EFAULT;
3096
3097 asoc = sctp_id2assoc(sk, val.scact_assoc_id);
3098 if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
3099 return -EINVAL;
3100
3101 return sctp_auth_del_key_id(sctp_sk(sk)->ep, asoc,
3102 val.scact_keynumber);
3103
3104}
3105
3106
2949/* API 6.2 setsockopt(), getsockopt() 3107/* API 6.2 setsockopt(), getsockopt()
2950 * 3108 *
2951 * Applications use setsockopt() and getsockopt() to set or retrieve 3109 * Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3069,6 +3227,21 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
3069 case SCTP_MAX_BURST: 3227 case SCTP_MAX_BURST:
3070 retval = sctp_setsockopt_maxburst(sk, optval, optlen); 3228 retval = sctp_setsockopt_maxburst(sk, optval, optlen);
3071 break; 3229 break;
3230 case SCTP_AUTH_CHUNK:
3231 retval = sctp_setsockopt_auth_chunk(sk, optval, optlen);
3232 break;
3233 case SCTP_HMAC_IDENT:
3234 retval = sctp_setsockopt_hmac_ident(sk, optval, optlen);
3235 break;
3236 case SCTP_AUTH_KEY:
3237 retval = sctp_setsockopt_auth_key(sk, optval, optlen);
3238 break;
3239 case SCTP_AUTH_ACTIVE_KEY:
3240 retval = sctp_setsockopt_active_key(sk, optval, optlen);
3241 break;
3242 case SCTP_AUTH_DELETE_KEY:
3243 retval = sctp_setsockopt_del_key(sk, optval, optlen);
3244 break;
3072 default: 3245 default:
3073 retval = -ENOPROTOOPT; 3246 retval = -ENOPROTOOPT;
3074 break; 3247 break;
@@ -4840,6 +5013,118 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
4840 return -ENOTSUPP; 5013 return -ENOTSUPP;
4841} 5014}
4842 5015
5016static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
5017 char __user *optval, int __user *optlen)
5018{
5019 struct sctp_hmac_algo_param *hmacs;
5020 __u16 param_len;
5021
5022 hmacs = sctp_sk(sk)->ep->auth_hmacs_list;
5023 param_len = ntohs(hmacs->param_hdr.length);
5024
5025 if (len < param_len)
5026 return -EINVAL;
5027 if (put_user(len, optlen))
5028 return -EFAULT;
5029 if (copy_to_user(optval, hmacs->hmac_ids, len))
5030 return -EFAULT;
5031
5032 return 0;
5033}
5034
5035static int sctp_getsockopt_active_key(struct sock *sk, int len,
5036 char __user *optval, int __user *optlen)
5037{
5038 struct sctp_authkeyid val;
5039 struct sctp_association *asoc;
5040
5041 if (len < sizeof(struct sctp_authkeyid))
5042 return -EINVAL;
5043 if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid)))
5044 return -EFAULT;
5045
5046 asoc = sctp_id2assoc(sk, val.scact_assoc_id);
5047 if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP))
5048 return -EINVAL;
5049
5050 if (asoc)
5051 val.scact_keynumber = asoc->active_key_id;
5052 else
5053 val.scact_keynumber = sctp_sk(sk)->ep->active_key_id;
5054
5055 return 0;
5056}
5057
5058static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
5059 char __user *optval, int __user *optlen)
5060{
5061 struct sctp_authchunks val;
5062 struct sctp_association *asoc;
5063 struct sctp_chunks_param *ch;
5064 char __user *to;
5065
5066 if (len <= sizeof(struct sctp_authchunks))
5067 return -EINVAL;
5068
5069 if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
5070 return -EFAULT;
5071
5072 to = val.gauth_chunks;
5073 asoc = sctp_id2assoc(sk, val.gauth_assoc_id);
5074 if (!asoc)
5075 return -EINVAL;
5076
5077 ch = asoc->peer.peer_chunks;
5078
5079 /* See if the user provided enough room for all the data */
5080 if (len < ntohs(ch->param_hdr.length))
5081 return -EINVAL;
5082
5083 len = ntohs(ch->param_hdr.length);
5084 if (put_user(len, optlen))
5085 return -EFAULT;
5086 if (copy_to_user(to, ch->chunks, len))
5087 return -EFAULT;
5088
5089 return 0;
5090}
5091
5092static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
5093 char __user *optval, int __user *optlen)
5094{
5095 struct sctp_authchunks val;
5096 struct sctp_association *asoc;
5097 struct sctp_chunks_param *ch;
5098 char __user *to;
5099
5100 if (len <= sizeof(struct sctp_authchunks))
5101 return -EINVAL;
5102
5103 if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
5104 return -EFAULT;
5105
5106 to = val.gauth_chunks;
5107 asoc = sctp_id2assoc(sk, val.gauth_assoc_id);
5108 if (!asoc && val.gauth_assoc_id && sctp_style(sk, UDP))
5109 return -EINVAL;
5110
5111 if (asoc)
5112 ch = (struct sctp_chunks_param*)asoc->c.auth_chunks;
5113 else
5114 ch = sctp_sk(sk)->ep->auth_chunk_list;
5115
5116 if (len < ntohs(ch->param_hdr.length))
5117 return -EINVAL;
5118
5119 len = ntohs(ch->param_hdr.length);
5120 if (put_user(len, optlen))
5121 return -EFAULT;
5122 if (copy_to_user(to, ch->chunks, len))
5123 return -EFAULT;
5124
5125 return 0;
5126}
5127
4843SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, 5128SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
4844 char __user *optval, int __user *optlen) 5129 char __user *optval, int __user *optlen)
4845{ 5130{
@@ -4963,6 +5248,25 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
4963 case SCTP_MAX_BURST: 5248 case SCTP_MAX_BURST:
4964 retval = sctp_getsockopt_maxburst(sk, len, optval, optlen); 5249 retval = sctp_getsockopt_maxburst(sk, len, optval, optlen);
4965 break; 5250 break;
5251 case SCTP_AUTH_KEY:
5252 case SCTP_AUTH_CHUNK:
5253 case SCTP_AUTH_DELETE_KEY:
5254 retval = -EOPNOTSUPP;
5255 break;
5256 case SCTP_HMAC_IDENT:
5257 retval = sctp_getsockopt_hmac_ident(sk, len, optval, optlen);
5258 break;
5259 case SCTP_AUTH_ACTIVE_KEY:
5260 retval = sctp_getsockopt_active_key(sk, len, optval, optlen);
5261 break;
5262 case SCTP_PEER_AUTH_CHUNKS:
5263 retval = sctp_getsockopt_peer_auth_chunks(sk, len, optval,
5264 optlen);
5265 break;
5266 case SCTP_LOCAL_AUTH_CHUNKS:
5267 retval = sctp_getsockopt_local_auth_chunks(sk, len, optval,
5268 optlen);
5269 break;
4966 default: 5270 default:
4967 retval = -ENOPROTOOPT; 5271 retval = -ENOPROTOOPT;
4968 break; 5272 break;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 5dc094b9732d..2c17c7efad46 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -813,6 +813,43 @@ fail:
813 return NULL; 813 return NULL;
814} 814}
815 815
816struct sctp_ulpevent *sctp_ulpevent_make_authkey(
817 const struct sctp_association *asoc, __u16 key_id,
818 __u32 indication, gfp_t gfp)
819{
820 struct sctp_ulpevent *event;
821 struct sctp_authkey_event *ak;
822 struct sk_buff *skb;
823
824 event = sctp_ulpevent_new(sizeof(struct sctp_authkey_event),
825 MSG_NOTIFICATION, gfp);
826 if (!event)
827 goto fail;
828
829 skb = sctp_event2skb(event);
830 ak = (struct sctp_authkey_event *)
831 skb_put(skb, sizeof(struct sctp_authkey_event));
832
833 ak->auth_type = SCTP_AUTHENTICATION_EVENT;
834 ak->auth_flags = 0;
835 ak->auth_length = sizeof(struct sctp_authkey_event);
836
837 ak->auth_keynumber = key_id;
838 ak->auth_altkeynumber = 0;
839 ak->auth_indication = indication;
840
841 /*
842 * The association id field, holds the identifier for the association.
843 */
844 sctp_ulpevent_set_owner(event, asoc);
845 ak->auth_assoc_id = sctp_assoc2id(asoc);
846
847 return event;
848fail:
849 return NULL;
850}
851
852
816/* Return the notification type, assuming this is a notification 853/* Return the notification type, assuming this is a notification
817 * event. 854 * event.
818 */ 855 */