nfs-ganesha 1.4
|
00001 #include "config.h" 00002 00003 #include <stdlib.h> 00004 #include <stdio.h> 00005 #include <string.h> 00006 00007 #include "nfs_exports.h" 00008 #include "config_parsing.h" 00009 #include "log.h" 00010 #include "nfs_core.h" 00011 #include "nfs_stat.h" 00012 #include "../MainNFSD/nfs_init.h" 00013 00014 /* These parameters are used throughout Ganesha code and must be initilized. */ 00015 nfs_parameter_t nfs_param; 00016 char ganesha_exec_path[MAXPATHLEN] = "/usr/bin/gpfs.ganesha.nfsd"; 00017 00018 #undef ANON_UID 00019 #undef ANON_GID 00020 00021 #define OP_MOUNT 0 00022 #define OP_READ 1 00023 #define OP_WRITE 2 00024 #define OP_MDONLY_READ 3 00025 #define OP_MDONLY_WRITE 4 00026 00027 const char *opnames[] = {"MOUNT", "READ", "WRITE", "MDONLY_READ", "MDONLY_WRITE" }; 00028 00029 #define ROOT_UID 0 00030 #define ROOT_GID 0 00031 #define USER_UID 1000 00032 #define USER_GID 1000 00033 #define ANON_UID -234 00034 #define ANON_GID -782 00035 #define INVALID_UID -9999 00036 #define INVALID_GID -9999 00037 00038 void init_vars(hash_table_t **ht_ip_stats, pool_t *ip_stats_pool) 00039 { 00040 int rc; 00041 00042 /* Get the FSAL functions */ 00043 FSAL_LoadFunctions(); 00044 00045 /* Get the FSAL consts */ 00046 FSAL_LoadConsts(); 00047 00048 nfs_set_param_default(&nfs_param); 00049 00050 /*ht_ip_stats*/ 00051 *ht_ip_stats = nfs_Init_ip_stats(nfs_param.ip_stats_param); 00052 /* if((*ht_ip_stats = HashTable_Init(nfs_param.ip_stats_param.hash_param)) == NULL) 00053 { 00054 LogCrit(COMPONENT_INIT, "NFS IP_STATS: Cannot init IP stats cache"); 00055 return NULL; 00056 }*/ 00057 00058 if(*ht_ip_stats == NULL) 00059 { 00060 LogCrit(COMPONENT_INIT, "NFS_INIT: Error while initializing IP/stats cache"); 00061 exit(1); 00062 } 00063 00064 /*ip_stats_pool*/ 00065 ip_stats_pool = pool_init("IP Stats Cache Pool", 00066 sizeof(nfs_ip_stats_t), 00067 pool_basic_substrate, 00068 NULL, NULL, NULL); 00069 00070 if(!(ip_stats_pool)) 00071 { 00072 LogCrit(COMPONENT_INIT, "NFS_INIT: Error while allocating IP stats cache pool"); 00073 LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno); 00074 exit(1); 00075 } 00076 } 00077 00078 struct user_cred test_access(char *addr, char *hostname, 00079 hash_table_t *ht_ip_stats, 00080 pool_t *ip_stats_pool, 00081 exportlist_t *pexport, int uid, 00082 int gid, int operation) 00083 { 00084 struct svc_req ptr_req; 00085 exportlist_client_entry_t pclient_found; 00086 struct user_cred user_credentials; 00087 unsigned int nfs_prog; 00088 unsigned int mnt_prog; 00089 sockaddr_t ssaddr; 00090 sockaddr_t *pssaddr = &ssaddr; 00091 int errcode; 00092 int export_check_result; 00093 bool_t proc_makes_write; 00094 00095 if (operation == OP_WRITE || operation == OP_MDONLY_WRITE) 00096 proc_makes_write = TRUE; 00097 else 00098 proc_makes_write = FALSE; 00099 00100 user_credentials.caller_uid = INVALID_UID; 00101 user_credentials.caller_gid = INVALID_GID; 00102 00103 /*pssaddr*/ 00104 errcode = ipstring_to_sockaddr(addr, pssaddr); 00105 if (errcode != 0) 00106 { 00107 perror ("getaddrinfo"); 00108 return user_credentials; 00109 } 00110 00111 /* ptr_req */ 00112 memset(&ptr_req, 0, sizeof(struct svc_req)); 00113 ptr_req.rq_cred.oa_flavor = AUTH_UNIX; 00114 ptr_req.rq_proc = 23232; 00115 /*nfs_prog*/ 00116 nfs_prog = nfs_param.core_param.program[P_NFS]; 00117 00118 /*mnt_prog*/ 00119 mnt_prog = nfs_param.core_param.program[P_MNT]; 00120 if (operation == OP_MOUNT) 00121 ptr_req.rq_prog = mnt_prog; 00122 else 00123 ptr_req.rq_prog = nfs_prog; 00124 00125 /*user_credentials*/ 00126 user_credentials.caller_uid = uid; 00127 user_credentials.caller_gid = gid; 00128 00129 export_check_result = nfs_export_check_access(pssaddr, 00130 &ptr_req, 00131 pexport, 00132 nfs_prog, 00133 mnt_prog, 00134 ht_ip_stats, 00135 ip_stats_pool, 00136 &pclient_found, 00137 &user_credentials, 00138 proc_makes_write); 00139 00140 /* This is the function used to changed uid/gid when they should 00141 * be anonymous. */ 00142 nfs_check_anon(&pclient_found, pexport, &user_credentials); 00143 return user_credentials; 00144 } 00145 00146 int main(int argc, char *argv[]) 00147 { 00148 hash_table_t *ht_ip_stats; 00149 pool_t *ip_stats_pool; 00150 exportlist_t pexport; 00151 int root, read, write, mdonly_read, mdonly_write, 00152 root_user, uid, operation, 00153 nonroot, accesstype, 00154 squashall, gid, return_status=0; 00155 char *ip = "192.0.2.10"; 00156 // char *match_str = "192.0.2.10"; 00157 char *match_str = "*"; 00158 char *hostname = "hostname"; 00159 struct user_cred user_credentials; 00160 00161 SetDefaultLogging("TEST"); 00162 SetNamePgm("test_mnt_proto"); 00163 00164 init_vars(&ht_ip_stats, &ip_stats_pool); 00165 00166 printf("TESTING THE NEW ACCESS LIST FORMAT\n------------------------------------\n"); 00167 printf("TEST: root read write mdonly_read mdonly_write : uid operation\n"); 00168 /* loop through all combinations of new access list uses. */ 00169 for(root=0; root < 2; root++) 00170 for(read=0; read < 2; read++) 00171 for(write=0; write < 2; write++) 00172 for(mdonly_read=0; mdonly_read < 2; mdonly_read++) 00173 for(mdonly_write=0; mdonly_write < 2; mdonly_write++) 00174 for(squashall=0; squashall < 2; squashall++) 00175 { 00176 memset(&pexport, 0, sizeof(pexport)); 00177 00178 /* These strings come from local defines in ../support/exports.c */ 00179 if (root) 00180 parseAccessParam("Root_Access", match_str, &pexport, EXPORT_OPTION_ROOT); 00181 if (read) 00182 parseAccessParam("R_Access", match_str, &pexport, EXPORT_OPTION_READ_ACCESS); 00183 if (write) 00184 parseAccessParam("RW_Access", match_str, &pexport, 00185 EXPORT_OPTION_READ_ACCESS | EXPORT_OPTION_WRITE_ACCESS); 00186 if (mdonly_read) 00187 parseAccessParam("MDONLY_RO_Access", match_str, &pexport, EXPORT_OPTION_MD_READ_ACCESS); 00188 if (mdonly_write) 00189 parseAccessParam("MDONLY_Access", match_str, &pexport, 00190 EXPORT_OPTION_MD_WRITE_ACCESS | EXPORT_OPTION_MD_READ_ACCESS); 00191 00192 /* This is critical */ 00193 pexport.new_access_list_version = 1; 00194 pexport.all_anonymous = squashall; 00195 pexport.anonymous_uid = ANON_UID; 00196 pexport.anonymous_gid = ANON_GID; 00197 00198 /* With this export entry test both root and user access. */ 00199 for(root_user=0; root_user < 2; root_user++) 00200 for(operation=0; operation < 5; operation++) 00201 { 00202 if (root_user == 0) { 00203 uid = USER_UID; 00204 gid = USER_GID; 00205 } 00206 else { 00207 uid = ROOT_UID; 00208 gid = ROOT_GID; 00209 } 00210 00211 printf("TEST: %d %d %d %d %d : %d SQ%d -- %s", 00212 root, read, write, mdonly_read, mdonly_write, uid, squashall, opnames[operation]); 00213 struct user_cred user_credentials; 00214 00215 user_credentials = test_access(ip, hostname, ht_ip_stats, &ip_stats_pool, 00216 &pexport, uid, gid, operation); 00217 if (user_credentials.caller_uid == INVALID_UID || user_credentials.caller_gid == INVALID_GID) 00218 { 00219 printf(" ... FAIL - INVALID uid/gid\n"); 00220 return_status = 1; 00221 } 00222 else if (squashall && (user_credentials.caller_uid != ANON_UID || user_credentials.caller_gid != ANON_GID)) 00223 { 00224 printf(" ... FAIL [%d,%d] - uid/gid should be anonymous when squashall is activated.\n", 00225 user_credentials.caller_uid, user_credentials.caller_gid); 00226 return_status = 1; 00227 } 00228 else if (operation != OP_MOUNT && !squashall && uid == 0 && !root && 00229 (read || write || mdonly_read || mdonly_write) && 00230 (user_credentials.caller_uid != ANON_UID || user_credentials.caller_gid != ANON_GID)) 00231 { 00232 printf(" ... FAIL [%d,%d] - Root user should be anonymous when access is obtained through nonroot client entry.\n", 00233 user_credentials.caller_uid, user_credentials.caller_gid); 00234 return_status = 1; 00235 } 00236 else if (operation != OP_MOUNT && !squashall && uid == 0 && root && 00237 (user_credentials.caller_uid == ANON_UID || user_credentials.caller_gid == ANON_GID)) 00238 { 00239 printf(" ... FAIL [%d,%d] - Root user should not be anonymous when access is obtained through root client entry.\n", 00240 user_credentials.caller_uid, user_credentials.caller_gid); 00241 return_status = 1; 00242 } 00243 else 00244 printf(" ... PASS\n"); 00245 } 00246 } 00247 00248 /* loop through all combinations of old access list uses. */ 00249 printf("\n\nTESTING THE OLDER ACCESS LIST FORMAT\n------------------------------------\n"); 00250 printf("TEST: root nonroot accesstype : uid operation\n"); 00251 /* loop through all combinations of new access list uses. */ 00252 for(root=0; root < 2; root++) 00253 for(nonroot=0; nonroot < 2; nonroot++) 00254 for(accesstype=1; accesstype < 4; accesstype++) 00255 for(squashall=0; squashall < 2; squashall++) 00256 { 00257 memset(&pexport, 0, sizeof(pexport)); 00258 00259 /* These strings come from local defines in ../support/exports.c */ 00260 if (root) 00261 parseAccessParam("Root_Access", match_str, &pexport, EXPORT_OPTION_ROOT); 00262 if (nonroot) 00263 parseAccessParam("Access", match_str, &pexport, EXPORT_OPTION_READ_ACCESS|EXPORT_OPTION_WRITE_ACCESS); 00264 00265 if (accesstype == OP_READ) 00266 pexport.access_type = ACCESSTYPE_RO; 00267 else if (accesstype == OP_WRITE) 00268 pexport.access_type = ACCESSTYPE_RW; 00269 else if (accesstype == OP_MDONLY_READ) 00270 pexport.access_type = ACCESSTYPE_MDONLY_RO; 00271 else if (accesstype == OP_MDONLY_WRITE) 00272 pexport.access_type = ACCESSTYPE_MDONLY; 00273 else 00274 printf("FAIL: INVALID access_type \n"); 00275 00276 /* This is critical */ 00277 pexport.new_access_list_version = 0; 00278 pexport.all_anonymous = squashall; 00279 pexport.anonymous_uid = ANON_UID; 00280 pexport.anonymous_gid = ANON_GID; 00281 00282 /* With this export entry test both root and user access. */ 00283 for(root_user=0; root_user < 2; root_user++) 00284 for(operation=0; operation < 5; operation++) 00285 { 00286 if (root_user == 0) { 00287 uid = USER_UID; 00288 gid = USER_GID; 00289 } 00290 else { 00291 uid = ROOT_UID; 00292 gid = ROOT_GID; 00293 } 00294 00295 printf("TEST: %d %d SQ%d -- ", root, nonroot, squashall); 00296 if (accesstype == OP_READ) 00297 printf("ACCESSTYPE_RO "); 00298 else if (accesstype == OP_WRITE) 00299 printf("ACCESSTYPE_RW "); 00300 else if (accesstype == OP_MDONLY_READ) 00301 printf("ACCESSTYPE_MDONLY_RO "); 00302 else if (accesstype == OP_MDONLY_WRITE) 00303 printf("ACCESSTYPE_MDONLY "); 00304 else 00305 printf("INVALID "); 00306 printf(": %d ",uid); 00307 printf("%s", opnames[operation]); 00308 00309 user_credentials = test_access(ip, hostname, ht_ip_stats, &ip_stats_pool, 00310 &pexport, uid, gid, operation); 00311 00312 /* anonymous uid/gid doesn't apply during a mount */ 00313 if (operation == OP_MOUNT) 00314 printf(" ... PASS - uid/gid doesn't matter during mount\n"); 00315 /* a write on a ro filesystem would return an error, uid/gid don't matter. */ 00316 else if ((operation == OP_MDONLY_WRITE || operation == OP_WRITE) && (accesstype == OP_MDONLY_READ || accesstype == OP_READ)) 00317 printf(" ... PASS - uid/gid doesn't matter when access is denied\n"); 00318 /* a write on an mdonly-rw filesystem would return an error, uid/gid don't matter. */ 00319 else if (operation == OP_WRITE && accesstype == OP_MDONLY_WRITE) 00320 printf(" ... PASS - uid/gid doesn't matter when access is denied\n"); 00321 else if (user_credentials.caller_uid == INVALID_UID || user_credentials.caller_gid == INVALID_GID) 00322 { 00323 printf(" ... FAIL INVALID uid/gid\n"); 00324 return_status = 1; 00325 } 00326 else if (squashall && (user_credentials.caller_uid != ANON_UID || user_credentials.caller_gid != ANON_GID)) 00327 { 00328 printf(" ... FAIL [%d,%d] Squash all was active but uid/gid was not anonymous.\n", 00329 user_credentials.caller_uid, user_credentials.caller_gid); 00330 return_status = 1; 00331 } 00332 else if (!squashall && uid == 0 && !root && nonroot && 00333 (user_credentials.caller_uid != ANON_UID || user_credentials.caller_gid != ANON_GID)) 00334 { 00335 printf(" ... FAIL [%d,%d] Root user gained access through nonroot client entry, should be anonymous.\n", 00336 user_credentials.caller_uid, user_credentials.caller_gid); 00337 return_status = 1; 00338 } 00339 else if (!squashall && uid == 0 && root && 00340 (user_credentials.caller_uid == ANON_UID || user_credentials.caller_gid == ANON_GID)) 00341 { 00342 printf(" ... FAIL [%d,%d] Root user gained permission through root client entry, should not be anonymous.\n", 00343 user_credentials.caller_uid, user_credentials.caller_gid); 00344 return_status = 1; 00345 } 00346 else 00347 printf(" ... PASS\n"); 00348 } 00349 } 00350 00351 printf("----------------------------------------------------\n"); 00352 if (!return_status) 00353 printf("ALL ANONYMOUS SUPPORT TESTS COMPLETED SUCCESSFULLY!!\n"); 00354 else 00355 printf("ANONYMOUS SUPPORT TESTS FAILED!!\n"); 00356 printf("----------------------------------------------------\n"); 00357 return return_status; 00358 }