nfs-ganesha 1.4

test_anon_support.c

Go to the documentation of this file.
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 }