find_netif_types.c

Go to the documentation of this file.
00001 /**
00002  *  @file
00003  *  Implementation of the netif types utility module.
00004  *
00005  *  @author Kevin Carr kcarr@tresys.com
00006  *  @author Jeremy A. Mowery jmowery@tresys.com
00007  *  @author Jason Tang jtang@tresys.com
00008  *  @author David Windsor dwindsor@tresys.com
00009  *
00010  *  Copyright (C) 2005-2007 Tresys Technology, LLC
00011  *
00012  *  This program is free software; you can redistribute it and/or modify
00013  *  it under the terms of the GNU General Public License as published by
00014  *  the Free Software Foundation; either version 2 of the License, or
00015  *  (at your option) any later version.
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU General Public License for more details.
00021  *
00022  *  You should have received a copy of the GNU General Public License
00023  *  along with this program; if not, write to the Free Software
00024  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00025  */
00026 
00027 #include "find_netif_types.h"
00028 #include <apol/netcon-query.h>
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <errno.h>
00033 
00034 static const char *const mod_name = "find_netif_types";
00035 
00036 /* The register function registers all of a module's functions
00037  * with the library. */
00038 int find_netif_types_register(sechk_lib_t * lib)
00039 {
00040         sechk_module_t *mod = NULL;
00041         sechk_fn_t *fn_struct = NULL;
00042 
00043         if (!lib) {
00044                 ERR(NULL, "%s", "No library");
00045                 errno = EINVAL;
00046                 return -1;
00047         }
00048 
00049         /* Modules are declared by the config file and their name and options
00050          * are stored in the module array.  The name is looked up to determine
00051          * where to store the function structures */
00052         mod = sechk_lib_get_module(mod_name, lib);
00053         if (!mod) {
00054                 ERR(NULL, "%s", "Module unknown");
00055                 errno = EINVAL;
00056                 return -1;
00057         }
00058         mod->parent_lib = lib;
00059 
00060         /* assign the descriptions */
00061         mod->brief_description = "utility module";
00062         mod->detailed_description =
00063                 "--------------------------------------------------------------------------------\n"
00064                 "This module finds all types in a policy treated as a netif type.  A type is\n"
00065                 "a netif type if it is used in the internace context in a netifcon statement or\n"
00066                 "the context of the netif initial sid.\n";
00067         mod->opt_description =
00068                 "  Module requirements:\n" "    none\n" "  Module dependencies:\n" "    none\n" "  Module options:\n" "    none\n";
00069         mod->severity = SECHK_SEV_NONE;
00070 
00071         /* register functions */
00072         fn_struct = sechk_fn_new();
00073         if (!fn_struct) {
00074                 ERR(NULL, "%s", strerror(ENOMEM));
00075                 errno = ENOMEM;
00076                 return -1;
00077         }
00078         fn_struct->name = strdup(SECHK_MOD_FN_INIT);
00079         if (!fn_struct->name) {
00080                 ERR(NULL, "%s", strerror(ENOMEM));
00081                 errno = ENOMEM;
00082                 return -1;
00083         }
00084         fn_struct->fn = find_netif_types_init;
00085         apol_vector_append(mod->functions, (void *)fn_struct);
00086 
00087         fn_struct = sechk_fn_new();
00088         if (!fn_struct) {
00089                 ERR(NULL, "%s", strerror(ENOMEM));
00090                 errno = ENOMEM;
00091                 return -1;
00092         }
00093         fn_struct->name = strdup(SECHK_MOD_FN_RUN);
00094         if (!fn_struct->name) {
00095                 ERR(NULL, "%s", strerror(ENOMEM));
00096                 errno = ENOMEM;
00097                 return -1;
00098         }
00099         fn_struct->fn = find_netif_types_run;
00100         apol_vector_append(mod->functions, (void *)fn_struct);
00101 
00102         mod->data_free = NULL;
00103 
00104         fn_struct = sechk_fn_new();
00105         if (!fn_struct) {
00106                 ERR(NULL, "%s", strerror(ENOMEM));
00107                 errno = ENOMEM;
00108                 return -1;
00109         }
00110         fn_struct->name = strdup(SECHK_MOD_FN_PRINT);
00111         if (!fn_struct->name) {
00112                 ERR(NULL, "%s", strerror(ENOMEM));
00113                 errno = ENOMEM;
00114                 return -1;
00115         }
00116         fn_struct->fn = find_netif_types_print;
00117         apol_vector_append(mod->functions, (void *)fn_struct);
00118 
00119         fn_struct = sechk_fn_new();
00120         if (!fn_struct) {
00121                 ERR(NULL, "%s", strerror(ENOMEM));
00122                 errno = ENOMEM;
00123                 return -1;
00124         }
00125         fn_struct->name = strdup("get_list");
00126         if (!fn_struct->name) {
00127                 ERR(NULL, "%s", strerror(ENOMEM));
00128                 errno = ENOMEM;
00129                 return -1;
00130         }
00131         fn_struct->fn = find_netif_types_get_list;
00132         apol_vector_append(mod->functions, (void *)fn_struct);
00133 
00134         return 0;
00135 }
00136 
00137 /* The init function creates the module's private data storage object
00138  * and initializes its values based on the options parsed in the config
00139  * file. */
00140 int find_netif_types_init(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
00141 {
00142         if (!mod || !policy) {
00143                 ERR(policy, "%s", "Invalid parameters");
00144                 errno = EINVAL;
00145                 return -1;
00146         }
00147         if (strcmp(mod_name, mod->name)) {
00148                 ERR(policy, "Wrong module (%s)", mod->name);
00149                 errno = EINVAL;
00150                 return -1;
00151         }
00152 
00153         return 0;
00154 }
00155 
00156 /* The run function performs the check. This function runs only once
00157  * even if called multiple times. All test logic should be placed below
00158  * as instructed. This function allocates the result structure and fills
00159  * in all relavant item and proof data.
00160  * Return Values:
00161  *  -1 System error
00162  *   0 The module "succeeded"   - no negative results found
00163  *   1 The module "failed"      - some negative results found */
00164 int find_netif_types_run(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
00165 {
00166         sechk_result_t *res = NULL;
00167         sechk_item_t *item = NULL;
00168         sechk_proof_t *proof = NULL;
00169         char *buff = NULL;
00170         size_t i, buff_sz = 0;
00171         apol_vector_t *netifcon_vector;
00172         qpol_policy_t *q = apol_policy_get_qpol(policy);
00173         int error = 0;
00174 
00175         if (!mod || !policy) {
00176                 ERR(policy, "%s", "Invalid parameters");
00177                 errno = EINVAL;
00178                 return -1;
00179         }
00180         if (strcmp(mod_name, mod->name)) {
00181                 ERR(policy, "Wrong module (%s)", mod->name);
00182                 errno = EINVAL;
00183                 return -1;
00184         }
00185 
00186         /* if already run return */
00187         if (mod->result)
00188                 return 0;
00189 
00190         res = sechk_result_new();
00191         if (!res) {
00192                 ERR(policy, "%s", strerror(ENOMEM));
00193                 errno = ENOMEM;
00194                 return -1;
00195         }
00196         res->test_name = strdup(mod_name);
00197         if (!res->test_name) {
00198                 error = errno;
00199                 ERR(policy, "%s", strerror(ENOMEM));
00200                 goto find_netif_types_run_fail;
00201         }
00202         res->item_type = SECHK_ITEM_TYPE;
00203         if (!(res->items = apol_vector_create(sechk_item_free))) {
00204                 error = errno;
00205                 ERR(policy, "%s", strerror(ENOMEM));
00206                 goto find_netif_types_run_fail;
00207         }
00208 
00209         /* search initial SIDs */
00210         const qpol_isid_t *isid = NULL;
00211 
00212         buff = NULL;
00213         qpol_policy_get_isid_by_name(q, "netif", &isid);
00214         if (isid) {
00215                 const qpol_context_t *context;
00216                 apol_context_t *a_context;
00217                 const qpol_type_t *context_type;
00218                 const char *context_type_name;
00219                 char *tmp;
00220 
00221                 proof = NULL;
00222                 qpol_isid_get_context(q, isid, &context);
00223                 qpol_context_get_type(q, context, &context_type);
00224                 qpol_type_get_name(q, context_type, &context_type_name);
00225                 a_context = apol_context_create_from_qpol_context(policy, context);
00226 
00227                 if (apol_str_append(&buff, &buff_sz, "sid netif ") != 0) {
00228                         error = errno;
00229                         ERR(policy, "%s", strerror(ENOMEM));
00230                         apol_context_destroy(&a_context);
00231                         goto find_netif_types_run_fail;
00232                 }
00233 
00234                 tmp = apol_context_render(policy, a_context);
00235                 if (apol_str_append(&buff, &buff_sz, tmp) != 0) {
00236                         error = errno;
00237                         ERR(policy, "%s", strerror(ENOMEM));
00238                         free(tmp);
00239                         apol_context_destroy(&a_context);
00240                         goto find_netif_types_run_fail;
00241                 }
00242                 apol_context_destroy(&a_context);
00243                 free(tmp);
00244                 tmp = NULL;
00245 
00246                 item = sechk_item_new(NULL);
00247                 if (!item) {
00248                         error = errno;
00249                         ERR(policy, "%s", strerror(ENOMEM));
00250                         goto find_netif_types_run_fail;
00251                 }
00252                 item->test_result = 1;
00253 
00254                 proof = sechk_proof_new(NULL);
00255                 if (!proof) {
00256                         error = errno;
00257                         ERR(policy, "%s", strerror(ENOMEM));
00258                         goto find_netif_types_run_fail;
00259                 }
00260 
00261                 proof->type = SECHK_ITEM_ISID;
00262                 proof->elem = (void *)isid;
00263                 proof->text = buff;
00264 
00265                 item->item = (void *)context_type;
00266                 if (!item->proof) {
00267                         if (!(item->proof = apol_vector_create(sechk_proof_free))) {
00268                                 error = errno;
00269                                 ERR(policy, "%s", strerror(ENOMEM));
00270                                 goto find_netif_types_run_fail;
00271                         }
00272                 }
00273                 if (apol_vector_append(item->proof, (void *)proof) < 0) {
00274                         error = errno;
00275                         ERR(policy, "%s", strerror(ENOMEM));
00276                         goto find_netif_types_run_fail;
00277                 }
00278                 if (apol_vector_append(res->items, (void *)item) < 0) {
00279                         error = errno;
00280                         ERR(policy, "%s", strerror(ENOMEM));
00281                         goto find_netif_types_run_fail;
00282                 }
00283         }
00284 
00285         if (apol_netifcon_get_by_query(policy, NULL, &netifcon_vector) < 0) {
00286                 error = errno;
00287                 goto find_netif_types_run_fail;
00288         }
00289 
00290         for (i = 0; i < apol_vector_get_size(netifcon_vector); i++) {
00291                 const char *msg_con_name = NULL;
00292                 const char *if_con_name = NULL;
00293                 qpol_netifcon_t *netifcon = NULL;
00294                 const qpol_context_t *msg_con = NULL;
00295                 const qpol_context_t *if_con = NULL;
00296                 const qpol_type_t *msg_type = NULL;
00297                 const qpol_type_t *if_type = NULL;
00298                 size_t j = 0;
00299 
00300                 netifcon = apol_vector_get_element(netifcon_vector, i);
00301                 qpol_netifcon_get_msg_con(q, netifcon, &msg_con);
00302                 qpol_netifcon_get_if_con(q, netifcon, &if_con);
00303                 qpol_context_get_type(q, msg_con, &msg_type);
00304                 qpol_context_get_type(q, if_con, &if_type);
00305                 qpol_type_get_name(q, msg_type, &msg_con_name);
00306                 qpol_type_get_name(q, if_type, &if_con_name);
00307 
00308                 proof = sechk_proof_new(NULL);
00309                 if (!proof) {
00310                         error = errno;
00311                         ERR(policy, "%s", strerror(ENOMEM));
00312                         goto find_netif_types_run_fail;
00313                 }
00314                 proof->type = SECHK_ITEM_NETIFCON;
00315                 proof->elem = netifcon;
00316                 proof->text = apol_netifcon_render(policy, netifcon);
00317                 item = NULL;
00318 
00319                 for (j = 0; j < apol_vector_get_size(res->items); j++) {
00320                         sechk_item_t *res_item = NULL;
00321                         const qpol_type_t *res_type;
00322                         const char *res_type_name;
00323 
00324                         res_item = apol_vector_get_element(res->items, j);
00325                         res_type = (qpol_type_t *) res_item->item;
00326                         qpol_type_get_name(q, res_type, &res_type_name);
00327                         if (!strcmp(res_type_name, if_con_name))
00328                                 item = res_item;
00329                 }
00330 
00331                 if (!item) {
00332                         item = sechk_item_new(NULL);
00333                         if (!item) {
00334                                 error = errno;
00335                                 ERR(policy, "%s", strerror(ENOMEM));
00336                                 goto find_netif_types_run_fail;
00337                         }
00338                         item->test_result = 1;
00339                         item->item = (void *)if_type;
00340                         if (apol_vector_append(res->items, (void *)item) < 0) {
00341                                 error = errno;
00342                                 ERR(policy, "%s", strerror(ENOMEM));
00343                                 goto find_netif_types_run_fail;
00344                         }
00345                 }
00346                 if (!item->proof) {
00347                         if (!(item->proof = apol_vector_create(sechk_proof_free))) {
00348                                 error = errno;
00349                                 ERR(policy, "%s", strerror(ENOMEM));
00350                                 goto find_netif_types_run_fail;
00351                         }
00352                 }
00353                 if (apol_vector_append(item->proof, (void *)proof) < 0) {
00354                         error = errno;
00355                         ERR(policy, "%s", strerror(ENOMEM));
00356                         goto find_netif_types_run_fail;
00357                 }
00358                 item = NULL;
00359         }
00360         apol_vector_destroy(&netifcon_vector);
00361 
00362         mod->result = res;
00363 
00364         return 0;
00365 
00366       find_netif_types_run_fail:
00367         sechk_proof_free(proof);
00368         sechk_item_free(item);
00369         free(buff);
00370         sechk_result_destroy(&res);
00371         errno = error;
00372         return -1;
00373 }
00374 
00375 /* The print output function generates the text and prints the
00376  * results to stdout. The outline below prints
00377  * the standard format of a renetif section. Some modules may
00378  * not have results in a format that can be represented by this
00379  * outline and will need a different specification. It is
00380  * required that each of the flags for output components be
00381  * tested in this function (stats, list, proof, detailed, and brief) */
00382 int find_netif_types_print(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
00383 {
00384         unsigned char outformat = 0x00;
00385         sechk_item_t *item = NULL;
00386         sechk_proof_t *proof = NULL;
00387         size_t i = 0, j = 0, k = 0, num_items = 0;
00388         const qpol_type_t *type;
00389         qpol_policy_t *q = apol_policy_get_qpol(policy);
00390         const char *type_name;
00391 
00392         if (!mod || !policy) {
00393                 ERR(policy, "%s", "Invalid parameters");
00394                 errno = EINVAL;
00395                 return -1;
00396         }
00397         if (strcmp(mod_name, mod->name)) {
00398                 ERR(policy, "Wrong module (%s)", mod->name);
00399                 errno = EINVAL;
00400                 return -1;
00401         }
00402 
00403         outformat = mod->outputformat;
00404 
00405         num_items = apol_vector_get_size(mod->result->items);
00406 
00407         if (!mod->result) {
00408                 ERR(policy, "%s", "Module has not been run");
00409                 errno = EINVAL;
00410                 return -1;
00411         }
00412 
00413         if (!outformat || (outformat & SECHK_OUT_QUIET))
00414                 return 0;              /* not an error - no output is requested */
00415 
00416         if (outformat & SECHK_OUT_STATS) {
00417                 printf("Found %i netif types.\n", num_items);
00418         }
00419 
00420         /* The list renetif component is a display of all items
00421          * found without any supnetifing proof. The default method
00422          * is to display a comma separated list four items to a line
00423          * this may need to be changed for longer items. */
00424         if (outformat & SECHK_OUT_LIST) {
00425                 printf("\n");
00426                 for (i = 0; i < num_items; i++) {
00427                         j++;
00428                         j %= 4;
00429                         item = apol_vector_get_element(mod->result->items, i);
00430                         type = (qpol_type_t *) item->item;
00431                         qpol_type_get_name(q, type, &type_name);
00432                         printf("%s%s", type_name, (char *)((j && i != num_items - 1) ? ", " : "\n"));
00433                 }
00434                 printf("\n");
00435         }
00436 
00437         /* The proof renetif component is a display of a list of items
00438          * with an indented list of proof statements supnetifing the result
00439          * of the check for that item (e.g. rules with a given type)
00440          * this field also lists the computed severity of each item
00441          * (see sechk_item_sev in sechecker.c for details on calculation)
00442          * items are printed on a line either with (or, if long, such as a
00443          * rule, followed by) the severity. Each proof element is then
00444          * displayed in an indented list one per line below it. */
00445         if (outformat & SECHK_OUT_PROOF) {
00446                 printf("\n");
00447                 for (j = 0; j < num_items; j++) {
00448                         item = apol_vector_get_element(mod->result->items, j);
00449                         type = (qpol_type_t *) item->item;
00450                         qpol_type_get_name(q, type, &type_name);
00451                         if (item) {
00452                                 printf("%s\n", type_name);
00453                                 for (k = 0; k < apol_vector_get_size(item->proof); k++) {
00454                                         proof = apol_vector_get_element(item->proof, k);
00455                                         if (proof)
00456                                                 printf("\t%s\n", proof->text);
00457                                 }
00458                         }
00459                 }
00460                 printf("\n");
00461         }
00462 
00463         return 0;
00464 }
00465 
00466 int find_netif_types_get_list(sechk_module_t * mod, apol_policy_t * policy, void *arg)
00467 {
00468         apol_vector_t **v = arg;
00469 
00470         if (!mod || !arg) {
00471                 ERR(policy, "%s", "Invalid parameters");
00472                 errno = EINVAL;
00473                 return -1;
00474         }
00475         if (strcmp(mod_name, mod->name)) {
00476                 ERR(policy, "Wrong module (%s)", mod->name);
00477                 errno = EINVAL;
00478                 return -1;
00479         }
00480         if (!mod->result) {
00481                 ERR(policy, "%s", "Module has not been run");
00482                 errno = EINVAL;
00483                 return -1;
00484         }
00485 
00486         v = &mod->result->items;
00487 
00488         return 0;
00489 }