aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */