Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Vlad Yasevich and committed by
David S. Miller
65b07e5d bbd0d598

+657
+16
include/net/sctp/auth.h
··· 43 43 struct sctp_endpoint; 44 44 struct sctp_association; 45 45 struct sctp_authkey; 46 + struct sctp_hmacalgo; 46 47 47 48 /* 48 49 * Define a generic struct that will hold all the info ··· 110 109 void sctp_auth_calculate_hmac(const struct sctp_association *asoc, 111 110 struct sk_buff *skb, 112 111 struct sctp_auth_chunk *auth, gfp_t gfp); 112 + 113 + /* API Helpers */ 114 + int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id); 115 + int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, 116 + struct sctp_hmacalgo *hmacs); 117 + int sctp_auth_set_key(struct sctp_endpoint *ep, 118 + struct sctp_association *asoc, 119 + struct sctp_authkey *auth_key); 120 + int sctp_auth_set_active_key(struct sctp_endpoint *ep, 121 + struct sctp_association *asoc, 122 + __u16 key_id); 123 + int sctp_auth_del_key_id(struct sctp_endpoint *ep, 124 + struct sctp_association *asoc, 125 + __u16 key_id); 126 + 113 127 #endif
+4
include/net/sctp/ulpevent.h
··· 128 128 struct sctp_chunk *chunk, 129 129 gfp_t gfp); 130 130 131 + struct sctp_ulpevent *sctp_ulpevent_make_authkey( 132 + const struct sctp_association *asoc, __u16 key_id, 133 + __u32 indication, gfp_t gfp); 134 + 131 135 void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, 132 136 struct msghdr *); 133 137 __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event);
+90
include/net/sctp/user.h
··· 103 103 #define SCTP_PARTIAL_DELIVERY_POINT SCTP_PARTIAL_DELIVERY_POINT 104 104 SCTP_MAX_BURST, /* Set/Get max burst */ 105 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 122 /* Internal Socket Options. Some of the sctp library functions are 108 123 * implemented using these socket options. ··· 385 370 386 371 enum { SCTP_PARTIAL_DELIVERY_ABORTED=0, }; 387 372 373 + struct sctp_authkey_event { 374 + __u16 auth_type; 375 + __u16 auth_flags; 376 + __u32 auth_length; 377 + __u16 auth_keynumber; 378 + __u16 auth_altkeynumber; 379 + __u32 auth_indication; 380 + sctp_assoc_t auth_assoc_id; 381 + }; 382 + 383 + enum { SCTP_AUTH_NEWKEY = 0, }; 384 + 385 + 388 386 /* 389 387 * Described in Section 7.3 390 388 * Ancillary Data and Notification Interest Options ··· 433 405 struct sctp_shutdown_event sn_shutdown_event; 434 406 struct sctp_adaptation_event sn_adaptation_event; 435 407 struct sctp_pdapi_event sn_pdapi_event; 408 + struct sctp_authkey_event sn_authkey_event; 436 409 }; 437 410 438 411 /* Section 5.3.1 ··· 450 421 SCTP_SHUTDOWN_EVENT, 451 422 SCTP_PARTIAL_DELIVERY_EVENT, 452 423 SCTP_ADAPTATION_INDICATION, 424 + SCTP_AUTHENTICATION_EVENT, 453 425 }; 454 426 455 427 /* Notification error codes used to fill up the error fields in some ··· 569 539 __u32 spp_flags; 570 540 } __attribute__((packed, aligned(4))); 571 541 542 + /* 543 + * 7.1.18. Add a chunk that must be authenticated (SCTP_AUTH_CHUNK) 544 + * 545 + * This set option adds a chunk type that the user is requesting to be 546 + * received only in an authenticated way. Changes to the list of chunks 547 + * will only effect future associations on the socket. 548 + */ 549 + struct sctp_authchunk { 550 + __u8 sauth_chunk; 551 + }; 552 + 553 + /* 554 + * 7.1.19. Get or set the list of supported HMAC Identifiers (SCTP_HMAC_IDENT) 555 + * 556 + * This option gets or sets the list of HMAC algorithms that the local 557 + * endpoint requires the peer to use. 558 + */ 559 + struct sctp_hmacalgo { 560 + __u16 shmac_num_idents; 561 + __u16 shmac_idents[]; 562 + }; 563 + 564 + /* 565 + * 7.1.20. Set a shared key (SCTP_AUTH_KEY) 566 + * 567 + * This option will set a shared secret key which is used to build an 568 + * association shared key. 569 + */ 570 + struct sctp_authkey { 571 + sctp_assoc_t sca_assoc_id; 572 + __u16 sca_keynumber; 573 + __u16 sca_keylen; 574 + __u8 sca_key[]; 575 + }; 576 + 577 + /* 578 + * 7.1.21. Get or set the active shared key (SCTP_AUTH_ACTIVE_KEY) 579 + * 580 + * This option will get or set the active shared key to be used to build 581 + * the association shared key. 582 + */ 583 + 584 + struct sctp_authkeyid { 585 + sctp_assoc_t scact_assoc_id; 586 + __u16 scact_keynumber; 587 + }; 588 + 589 + 572 590 /* 7.1.23. Delayed Ack Timer (SCTP_DELAYED_ACK_TIME) 573 591 * 574 592 * This options will get or set the delayed ack timer. The time is set ··· 683 605 __u16 sstat_outstrms; 684 606 __u32 sstat_fragmentation_point; 685 607 struct sctp_paddrinfo sstat_primary; 608 + }; 609 + 610 + /* 611 + * 7.2.3. Get the list of chunks the peer requires to be authenticated 612 + * (SCTP_PEER_AUTH_CHUNKS) 613 + * 614 + * This option gets a list of chunks for a specified association that 615 + * the peer requires to be received authenticated only. 616 + */ 617 + struct sctp_authchunks { 618 + sctp_assoc_t gauth_assoc_id; 619 + uint8_t gauth_chunks[]; 686 620 }; 687 621 688 622 /*
+193
net/sctp/auth.c
··· 743 743 if (free_key) 744 744 sctp_auth_key_put(asoc_key); 745 745 } 746 + 747 + /* API Helpers */ 748 + 749 + /* Add a chunk to the endpoint authenticated chunk list */ 750 + int 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 */ 772 + int 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 + */ 806 + int 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; 860 + nomem: 861 + if (!replace) 862 + sctp_auth_shkey_free(cur_key); 863 + 864 + return -ENOMEM; 865 + } 866 + 867 + int 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 + 900 + int 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 + }
+13
net/sctp/sm_statefuns.c
··· 3848 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 3864 return SCTP_DISPOSITION_CONSUME; 3852 3865 } 3853 3866
+304
net/sctp/socket.c
··· 2946 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 + */ 2956 + static 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 + */ 2985 + static 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); 3011 + out: 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 + */ 3022 + static 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); 3049 + out: 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 + */ 3060 + static 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 + */ 3085 + static 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 3107 /* API 6.2 setsockopt(), getsockopt() 2950 3108 * 2951 3109 * Applications use setsockopt() and getsockopt() to set or retrieve ··· 3226 3068 break; 3227 3069 case SCTP_MAX_BURST: 3228 3070 retval = sctp_setsockopt_maxburst(sk, optval, optlen); 3071 + break; 3072 + case SCTP_AUTH_CHUNK: 3073 + retval = sctp_setsockopt_auth_chunk(sk, optval, optlen); 3074 + break; 3075 + case SCTP_HMAC_IDENT: 3076 + retval = sctp_setsockopt_hmac_ident(sk, optval, optlen); 3077 + break; 3078 + case SCTP_AUTH_KEY: 3079 + retval = sctp_setsockopt_auth_key(sk, optval, optlen); 3080 + break; 3081 + case SCTP_AUTH_ACTIVE_KEY: 3082 + retval = sctp_setsockopt_active_key(sk, optval, optlen); 3083 + break; 3084 + case SCTP_AUTH_DELETE_KEY: 3085 + retval = sctp_setsockopt_del_key(sk, optval, optlen); 3229 3086 break; 3230 3087 default: 3231 3088 retval = -ENOPROTOOPT; ··· 5013 4840 return -ENOTSUPP; 5014 4841 } 5015 4842 4843 + static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, 4844 + char __user *optval, int __user *optlen) 4845 + { 4846 + struct sctp_hmac_algo_param *hmacs; 4847 + __u16 param_len; 4848 + 4849 + hmacs = sctp_sk(sk)->ep->auth_hmacs_list; 4850 + param_len = ntohs(hmacs->param_hdr.length); 4851 + 4852 + if (len < param_len) 4853 + return -EINVAL; 4854 + if (put_user(len, optlen)) 4855 + return -EFAULT; 4856 + if (copy_to_user(optval, hmacs->hmac_ids, len)) 4857 + return -EFAULT; 4858 + 4859 + return 0; 4860 + } 4861 + 4862 + static int sctp_getsockopt_active_key(struct sock *sk, int len, 4863 + char __user *optval, int __user *optlen) 4864 + { 4865 + struct sctp_authkeyid val; 4866 + struct sctp_association *asoc; 4867 + 4868 + if (len < sizeof(struct sctp_authkeyid)) 4869 + return -EINVAL; 4870 + if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) 4871 + return -EFAULT; 4872 + 4873 + asoc = sctp_id2assoc(sk, val.scact_assoc_id); 4874 + if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) 4875 + return -EINVAL; 4876 + 4877 + if (asoc) 4878 + val.scact_keynumber = asoc->active_key_id; 4879 + else 4880 + val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; 4881 + 4882 + return 0; 4883 + } 4884 + 4885 + static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, 4886 + char __user *optval, int __user *optlen) 4887 + { 4888 + struct sctp_authchunks val; 4889 + struct sctp_association *asoc; 4890 + struct sctp_chunks_param *ch; 4891 + char __user *to; 4892 + 4893 + if (len <= sizeof(struct sctp_authchunks)) 4894 + return -EINVAL; 4895 + 4896 + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) 4897 + return -EFAULT; 4898 + 4899 + to = val.gauth_chunks; 4900 + asoc = sctp_id2assoc(sk, val.gauth_assoc_id); 4901 + if (!asoc) 4902 + return -EINVAL; 4903 + 4904 + ch = asoc->peer.peer_chunks; 4905 + 4906 + /* See if the user provided enough room for all the data */ 4907 + if (len < ntohs(ch->param_hdr.length)) 4908 + return -EINVAL; 4909 + 4910 + len = ntohs(ch->param_hdr.length); 4911 + if (put_user(len, optlen)) 4912 + return -EFAULT; 4913 + if (copy_to_user(to, ch->chunks, len)) 4914 + return -EFAULT; 4915 + 4916 + return 0; 4917 + } 4918 + 4919 + static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, 4920 + char __user *optval, int __user *optlen) 4921 + { 4922 + struct sctp_authchunks val; 4923 + struct sctp_association *asoc; 4924 + struct sctp_chunks_param *ch; 4925 + char __user *to; 4926 + 4927 + if (len <= sizeof(struct sctp_authchunks)) 4928 + return -EINVAL; 4929 + 4930 + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) 4931 + return -EFAULT; 4932 + 4933 + to = val.gauth_chunks; 4934 + asoc = sctp_id2assoc(sk, val.gauth_assoc_id); 4935 + if (!asoc && val.gauth_assoc_id && sctp_style(sk, UDP)) 4936 + return -EINVAL; 4937 + 4938 + if (asoc) 4939 + ch = (struct sctp_chunks_param*)asoc->c.auth_chunks; 4940 + else 4941 + ch = sctp_sk(sk)->ep->auth_chunk_list; 4942 + 4943 + if (len < ntohs(ch->param_hdr.length)) 4944 + return -EINVAL; 4945 + 4946 + len = ntohs(ch->param_hdr.length); 4947 + if (put_user(len, optlen)) 4948 + return -EFAULT; 4949 + if (copy_to_user(to, ch->chunks, len)) 4950 + return -EFAULT; 4951 + 4952 + return 0; 4953 + } 4954 + 5016 4955 SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, 5017 4956 char __user *optval, int __user *optlen) 5018 4957 { ··· 5247 4962 break; 5248 4963 case SCTP_MAX_BURST: 5249 4964 retval = sctp_getsockopt_maxburst(sk, len, optval, optlen); 4965 + break; 4966 + case SCTP_AUTH_KEY: 4967 + case SCTP_AUTH_CHUNK: 4968 + case SCTP_AUTH_DELETE_KEY: 4969 + retval = -EOPNOTSUPP; 4970 + break; 4971 + case SCTP_HMAC_IDENT: 4972 + retval = sctp_getsockopt_hmac_ident(sk, len, optval, optlen); 4973 + break; 4974 + case SCTP_AUTH_ACTIVE_KEY: 4975 + retval = sctp_getsockopt_active_key(sk, len, optval, optlen); 4976 + break; 4977 + case SCTP_PEER_AUTH_CHUNKS: 4978 + retval = sctp_getsockopt_peer_auth_chunks(sk, len, optval, 4979 + optlen); 4980 + break; 4981 + case SCTP_LOCAL_AUTH_CHUNKS: 4982 + retval = sctp_getsockopt_local_auth_chunks(sk, len, optval, 4983 + optlen); 5250 4984 break; 5251 4985 default: 5252 4986 retval = -ENOPROTOOPT;
+37
net/sctp/ulpevent.c
··· 813 813 return NULL; 814 814 } 815 815 816 + struct 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; 848 + fail: 849 + return NULL; 850 + } 851 + 852 + 816 853 /* Return the notification type, assuming this is a notification 817 854 * event. 818 855 */