nfs-ganesha 1.4
|
00001 /* 00002 * COPYRIGHT (c) 2011 00003 * The Regents of the University of Michigan 00004 * ALL RIGHTS RESERVED 00005 * 00006 * Permission is granted to use, copy, create derivative works 00007 * and redistribute this software and such derivative works 00008 * for any purpose, so long as the name of The University of 00009 * Michigan is not used in any advertising or publicity 00010 * pertaining to the use of distribution of this software 00011 * without specific, written prior authorization. If the 00012 * above copyright notice or any other identification of the 00013 * University of Michigan is included in any copy of any 00014 * portion of this software, then the disclaimer below must 00015 * also be included. 00016 * 00017 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 00018 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 00019 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 00020 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 00021 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 00022 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 00023 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 00024 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 00025 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 00026 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 00027 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGES. 00029 */ 00030 00031 #ifdef HAVE_CONFIG_H 00032 #include <config.h> 00033 #endif /* HAVE_CONFIG_H */ 00034 00035 #ifndef _GNU_SOURCE 00036 #define _GNU_SOURCE 00037 #endif 00038 00039 #include <stdio.h> 00040 #include <errno.h> 00041 #include <gssapi/gssapi.h> 00042 #include <krb5.h> 00043 00044 #include "gss_util.h" 00045 #include "gss_oids.h" 00046 #include "err_util.h" 00047 #include "svcgssd_krb5.h" 00048 #include "../mount/version.h" 00049 00050 #define MYBUFLEN 1024 00051 00052 char *supported_enctypes_filename = "/proc/fs/nfsd/supported_krb5_enctypes"; 00053 int parsed_num_enctypes = 0; 00054 krb5_enctype *parsed_enctypes = NULL; 00055 char *cached_enctypes = NULL; 00056 00057 /*==========================*/ 00058 /*=== Internal routines ===*/ 00059 /*==========================*/ 00060 00061 /* 00062 * Parse the supported encryption type information 00063 */ 00064 static int 00065 parse_enctypes(char *enctypes) 00066 { 00067 int n = 0; 00068 char *curr, *comma; 00069 int i; 00070 00071 /* Don't parse the same string over and over... */ 00072 if (cached_enctypes && strcmp(cached_enctypes, enctypes) == 0) 00073 return 0; 00074 00075 /* Free any existing cached_enctypes */ 00076 free(cached_enctypes); 00077 00078 if (parsed_enctypes != NULL) { 00079 free(parsed_enctypes); 00080 parsed_enctypes = NULL; 00081 parsed_num_enctypes = 0; 00082 } 00083 00084 /* count the number of commas */ 00085 for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) { 00086 comma = strchr(curr, ','); 00087 if (comma != NULL) 00088 n++; 00089 else 00090 break; 00091 } 00092 00093 /* If no more commas and we're not at the end, there's one more value */ 00094 if (*curr != '\0') 00095 n++; 00096 00097 /* Empty string, return an error */ 00098 if (n == 0) 00099 return ENOENT; 00100 00101 /* Allocate space for enctypes array */ 00102 if ((parsed_enctypes = (int *) calloc(n, sizeof(int))) == NULL) { 00103 return ENOMEM; 00104 } 00105 00106 /* Now parse each value into the array */ 00107 for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) { 00108 parsed_enctypes[i++] = atoi(curr); 00109 comma = strchr(curr, ','); 00110 if (comma == NULL) 00111 break; 00112 } 00113 00114 parsed_num_enctypes = n; 00115 if ((cached_enctypes = malloc(strlen(enctypes)+1))) 00116 strcpy(cached_enctypes, enctypes); 00117 00118 return 0; 00119 } 00120 00121 static void 00122 get_kernel_supported_enctypes(void) 00123 { 00124 FILE *s_e; 00125 int ret; 00126 char buffer[MYBUFLEN + 1]; 00127 00128 memset(buffer, '\0', sizeof(buffer)); 00129 00130 s_e = fopen(supported_enctypes_filename, "r"); 00131 if (s_e == NULL) 00132 goto out_clean_parsed; 00133 00134 ret = fread(buffer, 1, MYBUFLEN, s_e); 00135 if (ret < 0) { 00136 fclose(s_e); 00137 goto out_clean_parsed; 00138 } 00139 fclose(s_e); 00140 if (parse_enctypes(buffer)) { 00141 goto out_clean_parsed; 00142 } 00143 out: 00144 return; 00145 00146 out_clean_parsed: 00147 if (parsed_enctypes != NULL) { 00148 free(parsed_enctypes); 00149 parsed_num_enctypes = 0; 00150 } 00151 goto out; 00152 } 00153 00154 /*==========================*/ 00155 /*=== External routines ===*/ 00156 /*==========================*/ 00157 00158 /* 00159 * Get encryption types supported by the kernel, and then 00160 * call gss_krb5_set_allowable_enctypes() to limit the 00161 * encryption types negotiated. 00162 * 00163 * Returns: 00164 * 0 => all went well 00165 * -1 => there was an error 00166 */ 00167 00168 int 00169 svcgssd_limit_krb5_enctypes(void) 00170 { 00171 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES 00172 u_int maj_stat, min_stat; 00173 krb5_enctype old_kernel_enctypes[] = { 00174 ENCTYPE_DES_CBC_CRC, 00175 ENCTYPE_DES_CBC_MD5, 00176 ENCTYPE_DES_CBC_MD4 }; 00177 krb5_enctype new_kernel_enctypes[] = { 00178 ENCTYPE_AES256_CTS_HMAC_SHA1_96, 00179 ENCTYPE_AES128_CTS_HMAC_SHA1_96, 00180 ENCTYPE_DES3_CBC_SHA1, 00181 ENCTYPE_ARCFOUR_HMAC, 00182 ENCTYPE_DES_CBC_CRC, 00183 ENCTYPE_DES_CBC_MD5, 00184 ENCTYPE_DES_CBC_MD4 }; 00185 krb5_enctype *default_enctypes, *enctypes; 00186 int default_num_enctypes, num_enctypes; 00187 00188 00189 if (linux_version_code() < MAKE_VERSION(2, 6, 35)) { 00190 default_enctypes = old_kernel_enctypes; 00191 default_num_enctypes = 00192 sizeof(old_kernel_enctypes) / sizeof(old_kernel_enctypes[0]); 00193 } else { 00194 default_enctypes = new_kernel_enctypes; 00195 default_num_enctypes = 00196 sizeof(new_kernel_enctypes) / sizeof(new_kernel_enctypes[0]); 00197 } 00198 00199 get_kernel_supported_enctypes(); 00200 00201 if (parsed_enctypes != NULL) { 00202 enctypes = parsed_enctypes; 00203 num_enctypes = parsed_num_enctypes; 00204 printerr(2, "%s: Calling gss_set_allowable_enctypes with %d " 00205 "enctypes from the kernel\n", __func__, num_enctypes); 00206 } else { 00207 enctypes = default_enctypes; 00208 num_enctypes = default_num_enctypes; 00209 printerr(2, "%s: Calling gss_set_allowable_enctypes with %d " 00210 "enctypes from defaults\n", __func__, num_enctypes); 00211 } 00212 00213 maj_stat = gss_set_allowable_enctypes(&min_stat, gssd_creds, 00214 &krb5oid, num_enctypes, enctypes); 00215 if (maj_stat != GSS_S_COMPLETE) { 00216 printerr(1, "WARNING: gss_set_allowable_enctypes failed\n"); 00217 pgsserr("svcgssd_limit_krb5_enctypes: gss_set_allowable_enctypes", 00218 maj_stat, min_stat, &krb5oid); 00219 return -1; 00220 } 00221 #endif 00222 return 0; 00223 }