find_port_types.c

Go to the documentation of this file.
00001 /**
00002  *  @file
00003  *  Implementation of the port 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_port_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_port_types";
00035 
00036 /* The register function registers all of a module's functions
00037  * with the library.  */
00038 int find_port_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 
00059         mod->parent_lib = lib;
00060 
00061         /* assign the descriptions */
00062         mod->brief_description = "utility module";
00063         mod->detailed_description =
00064                 "--------------------------------------------------------------------------------\n"
00065                 "This module finds all types in a policy treated as a port type.  A type is\n"
00066                 "considered a port type if it is used in the context of a a portcon statement or\n"
00067                 "the context of the port initial sid.\n";
00068         mod->opt_description =
00069                 "  Module requirements:\n" "    none\n" "  Module dependencies:\n" "    none\n" "  Module options:\n" "    none\n";
00070         mod->severity = SECHK_SEV_NONE;
00071 
00072         /* register functions */
00073         fn_struct = sechk_fn_new();
00074         if (!fn_struct) {
00075                 ERR(NULL, "%s", strerror(ENOMEM));
00076                 errno = ENOMEM;
00077                 return -1;
00078         }
00079         fn_struct->name = strdup(SECHK_MOD_FN_INIT);
00080         if (!fn_struct->name) {
00081                 ERR(NULL, "%s", strerror(ENOMEM));
00082                 errno = ENOMEM;
00083                 return -1;
00084         }
00085         fn_struct->fn = find_port_types_init;
00086         if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
00087                 ERR(NULL, "%s", strerror(ENOMEM));
00088                 errno = ENOMEM;
00089                 return -1;
00090         }
00091 
00092         fn_struct = sechk_fn_new();
00093         if (!fn_struct) {
00094                 ERR(NULL, "%s", strerror(ENOMEM));
00095                 errno = ENOMEM;
00096                 return -1;
00097         }
00098         fn_struct->name = strdup(SECHK_MOD_FN_RUN);
00099         if (!fn_struct->name) {
00100                 ERR(NULL, "%s", strerror(ENOMEM));
00101                 errno = ENOMEM;
00102                 return -1;
00103         }
00104         fn_struct->fn = find_port_types_run;
00105         if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
00106                 ERR(NULL, "%s", strerror(ENOMEM));
00107                 errno = ENOMEM;
00108                 return -1;
00109         }
00110 
00111         mod->data_free = NULL;
00112 
00113         fn_struct = sechk_fn_new();
00114         if (!fn_struct) {
00115                 ERR(NULL, "%s", strerror(ENOMEM));
00116                 errno = ENOMEM;
00117                 return -1;
00118         }
00119         fn_struct->name = strdup(SECHK_MOD_FN_PRINT);
00120         if (!fn_struct->name) {
00121                 ERR(NULL, "%s", strerror(ENOMEM));
00122                 errno = ENOMEM;
00123                 return -1;
00124         }
00125         fn_struct->fn = find_port_types_print;
00126         if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
00127                 ERR(NULL, "%s", strerror(ENOMEM));
00128                 errno = ENOMEM;
00129                 return -1;
00130         }
00131 
00132         fn_struct = sechk_fn_new();
00133         if (!fn_struct) {
00134                 ERR(NULL, "%s", strerror(ENOMEM));
00135                 errno = ENOMEM;
00136                 return -1;
00137         }
00138         fn_struct->name = strdup("get_list");
00139         if (!fn_struct->name) {
00140                 ERR(NULL, "%s", strerror(ENOMEM));
00141                 errno = ENOMEM;
00142                 return -1;
00143         }
00144         fn_struct->fn = &find_port_types_get_list;
00145         if (apol_vector_append(mod->functions, (void *)fn_struct) < 0) {
00146                 ERR(NULL, "%s", strerror(ENOMEM));
00147                 errno = ENOMEM;
00148                 return -1;
00149         }
00150 
00151         return 0;
00152 }
00153 
00154 /* The init function creates the module's private data storage object
00155  * and initializes its values based on the options parsed in the config
00156  * file.
00157  * Add any option processing logic as indicated below. */
00158 int find_port_types_init(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
00159 {
00160         if (!mod || !policy) {
00161                 ERR(policy, "%s", "Invalid parameters");
00162                 errno = EINVAL;
00163                 return -1;
00164         }
00165         if (strcmp(mod_name, mod->name)) {
00166                 ERR(policy, "Wrong module (%s)", mod->name);
00167                 errno = EINVAL;
00168                 return -1;
00169         }
00170 
00171         return 0;
00172 }
00173 
00174 /* The run function performs the check. This function runs only once
00175  * even if called multiple times. All test logic should be placed below
00176  * as instructed. This function allocates the result structure and fills
00177  * in all relavant item and proof data.
00178  * Return Values:
00179  *  -1 System error
00180  *   0 The module "succeeded"   - no negative results found
00181  *   1 The module "failed"      - some negative results found */
00182 int find_port_types_run(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
00183 {
00184         sechk_result_t *res = NULL;
00185         sechk_item_t *item = NULL;
00186         sechk_proof_t *proof = NULL;
00187         char *buff = NULL;
00188         size_t buff_sz = 0, i, j;
00189         apol_vector_t *portcon_vector;
00190         qpol_policy_t *q = apol_policy_get_qpol(policy);
00191         int error = 0;
00192 
00193         if (!mod || !policy) {
00194                 ERR(policy, "%s", "Invalid parameters");
00195                 errno = EINVAL;
00196                 return -1;
00197         }
00198         if (strcmp(mod_name, mod->name)) {
00199                 ERR(policy, "Wrong module (%s)", mod->name);
00200                 errno = EINVAL;
00201                 return -1;
00202         }
00203 
00204         /* if already run return */
00205         if (mod->result)
00206                 return 0;
00207 
00208         res = sechk_result_new();
00209         if (!res) {
00210                 ERR(policy, "%s", strerror(ENOMEM));
00211                 errno = ENOMEM;
00212                 return -1;
00213         }
00214         res->test_name = strdup(mod_name);
00215         if (!res->test_name) {
00216                 error = errno;
00217                 ERR(policy, "%s", strerror(ENOMEM));
00218                 goto find_port_types_run_fail;
00219         }
00220         res->item_type = SECHK_ITEM_TYPE;
00221         if (!(res->items = apol_vector_create(sechk_item_free))) {
00222                 error = errno;
00223                 ERR(policy, "%s", strerror(ENOMEM));
00224                 goto find_port_types_run_fail;
00225         }
00226 
00227         /* search initial SIDs */
00228         const qpol_isid_t *isid = NULL;
00229         buff = NULL;
00230         qpol_policy_get_isid_by_name(q, "port", &isid);
00231         if (isid) {
00232                 const qpol_context_t *context;
00233                 apol_context_t *a_context;
00234                 const qpol_type_t *context_type;
00235                 const char *context_type_name;
00236                 char *tmp;
00237 
00238                 proof = NULL;
00239                 qpol_isid_get_context(q, isid, &context);
00240                 qpol_context_get_type(q, context, &context_type);
00241                 qpol_type_get_name(q, context_type, &context_type_name);
00242                 a_context = apol_context_create_from_qpol_context(policy, context);
00243 
00244                 if (apol_str_append(&buff, &buff_sz, "sid port ") != 0) {
00245                         error = errno;
00246                         ERR(policy, "%s", strerror(ENOMEM));
00247                         apol_context_destroy(&a_context);
00248                         goto find_port_types_run_fail;
00249                 }
00250 
00251                 tmp = apol_context_render(policy, a_context);
00252                 if (apol_str_append(&buff, &buff_sz, tmp) != 0) {
00253                         error = errno;
00254                         ERR(policy, "%s", strerror(ENOMEM));
00255                         apol_context_destroy(&a_context);
00256                         free(tmp);
00257                         goto find_port_types_run_fail;
00258                 }
00259                 free(tmp);
00260                 tmp = NULL;
00261                 apol_context_destroy(&a_context);
00262 
00263                 proof = sechk_proof_new(NULL);
00264                 if (!proof) {
00265                         error = errno;
00266                         ERR(policy, "%s", strerror(ENOMEM));
00267                         goto find_port_types_run_fail;
00268                 }
00269 
00270                 proof->type = SECHK_ITEM_ISID;
00271                 proof->elem = (void *)isid;
00272                 proof->text = buff;
00273 
00274                 /* Have we encountered this type before?  If so, use that type. */
00275                 for (j = 0; j < apol_vector_get_size(res->items); j++) {
00276                         sechk_item_t *res_item = NULL;
00277                         const qpol_type_t *res_type;
00278                         const char *res_type_name;
00279 
00280                         res_item = apol_vector_get_element(res->items, j);
00281                         res_type = res_item->item;
00282                         qpol_type_get_name(q, res_type, &res_type_name);
00283                         if (!strcmp(res_type_name, context_type_name))
00284                                 item = res_item;
00285                 }
00286 
00287                 /* We have not encountered this type yet */
00288                 if (!item) {
00289                         item = sechk_item_new(NULL);
00290                         if (!item) {
00291                                 error = errno;
00292                                 ERR(policy, "%s", strerror(ENOMEM));
00293                                 goto find_port_types_run_fail;
00294                         }
00295                         item->test_result = 1;
00296                         item->item = (void *)context_type;
00297                         if (apol_vector_append(res->items, (void *)item) < 0) {
00298                                 error = errno;
00299                                 ERR(policy, "%s", strerror(ENOMEM));
00300                                 goto find_port_types_run_fail;
00301                         }
00302                 }
00303 
00304                 if (!item->proof) {
00305                         if (!(item->proof = apol_vector_create(sechk_proof_free))) {
00306                                 error = errno;
00307                                 ERR(policy, "%s", strerror(ENOMEM));
00308                                 goto find_port_types_run_fail;
00309                         }
00310                 }
00311                 if (apol_vector_append(item->proof, (void *)proof) < 0) {
00312                         error = errno;
00313                         ERR(policy, "%s", strerror(ENOMEM));
00314                         goto find_port_types_run_fail;
00315                 }
00316         }
00317 
00318         if (apol_portcon_get_by_query(policy, NULL, &portcon_vector) < 0) {
00319                 error = errno;
00320                 goto find_port_types_run_fail;
00321         }
00322 
00323         for (i = 0; i < apol_vector_get_size(portcon_vector); i++) {
00324                 const char *portcon_name = NULL;
00325                 const qpol_portcon_t *portcon = NULL;
00326                 const qpol_context_t *portcon_context = NULL;
00327                 const qpol_type_t *portcon_type = NULL;
00328 
00329                 portcon = apol_vector_get_element(portcon_vector, i);
00330                 qpol_portcon_get_context(q, portcon, &portcon_context);
00331                 qpol_context_get_type(q, portcon_context, &portcon_type);
00332                 qpol_type_get_name(q, portcon_type, &portcon_name);
00333 
00334                 proof = sechk_proof_new(NULL);
00335                 if (!proof) {
00336                         error = errno;
00337                         ERR(policy, "%s", strerror(ENOMEM));
00338                         goto find_port_types_run_fail;
00339                 }
00340                 proof->type = SECHK_ITEM_PORTCON;
00341                 proof->elem = (void *)portcon;
00342                 proof->text = apol_portcon_render(policy, portcon);
00343                 item = NULL;
00344 
00345                 /* Have we encountered this type before?  If so, use that type. */
00346                 for (j = 0; j < apol_vector_get_size(res->items); j++) {
00347                         sechk_item_t *res_item = NULL;
00348                         const qpol_type_t *res_type;
00349                         const char *res_type_name;
00350 
00351                         res_item = apol_vector_get_element(res->items, j);
00352                         res_type = res_item->item;
00353                         qpol_type_get_name(q, res_type, &res_type_name);
00354                         if (!strcmp(res_type_name, portcon_name))
00355                                 item = res_item;
00356                 }
00357 
00358                 /* We have not encountered this type yet */
00359                 if (!item) {
00360                         item = sechk_item_new(NULL);
00361                         if (!item) {
00362                                 error = errno;
00363                                 ERR(policy, "%s", strerror(ENOMEM));
00364                                 goto find_port_types_run_fail;
00365                         }
00366                         item->test_result = 1;
00367                         item->item = (void *)portcon_type;
00368                         if (apol_vector_append(res->items, (void *)item) < 0) {
00369                                 error = errno;
00370                                 ERR(policy, "%s", strerror(ENOMEM));
00371                                 goto find_port_types_run_fail;
00372                         }
00373                 }
00374 
00375                 if (!item->proof) {
00376                         if (!(item->proof = apol_vector_create(sechk_proof_free))) {
00377                                 error = errno;
00378                                 ERR(policy, "%s", strerror(ENOMEM));
00379                                 goto find_port_types_run_fail;
00380                         }
00381                 }
00382                 if (apol_vector_append(item->proof, (void *)proof) < 0) {
00383                         error = errno;
00384                         ERR(policy, "%s", strerror(ENOMEM));
00385                         goto find_port_types_run_fail;
00386                 }
00387                 item = NULL;
00388         }
00389         apol_vector_destroy(&portcon_vector);
00390 
00391         mod->result = res;
00392 
00393         return 0;
00394 
00395       find_port_types_run_fail:
00396         sechk_proof_free(proof);
00397         sechk_item_free(item);
00398         free(buff);
00399         sechk_result_destroy(&res);
00400         errno = error;
00401         return -1;
00402 }
00403 
00404 /* The print function generates the text and prints the
00405  * results to stdout.  */
00406 int find_port_types_print(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
00407 {
00408         unsigned char outformat = 0x00;
00409         sechk_item_t *item = NULL;
00410         sechk_proof_t *proof = NULL;
00411         size_t i = 0, j = 0, k = 0, num_items = 0;
00412         const qpol_type_t *type;
00413         qpol_policy_t *q = apol_policy_get_qpol(policy);
00414         const char *type_name;
00415 
00416         if (!mod || !policy) {
00417                 ERR(policy, "%s", "Invalid parameters");
00418                 errno = EINVAL;
00419                 return -1;
00420         }
00421         if (strcmp(mod_name, mod->name)) {
00422                 ERR(policy, "Wrong module (%s)", mod->name);
00423                 errno = EINVAL;
00424                 return -1;
00425         }
00426 
00427         outformat = mod->outputformat;
00428 
00429         num_items = apol_vector_get_size(mod->result->items);
00430 
00431         if (!mod->result) {
00432                 ERR(policy, "%s", "Module has not been run");
00433                 errno = EINVAL;
00434                 return -1;
00435         }
00436 
00437         if (!outformat || (outformat & SECHK_OUT_QUIET))
00438                 return 0;              /* not an error - no output is requested */
00439 
00440         if (outformat & SECHK_OUT_STATS) {
00441                 printf("Found %i port types.\n", num_items);
00442         }
00443 
00444         /* The list report component is a display of all items
00445          * found without any supporting proof. The default method
00446          * is to display a comma separated list four items to a line
00447          * this may need to be changed for longer items. */
00448         if (outformat & SECHK_OUT_LIST) {
00449                 printf("\n");
00450                 for (i = 0; i < num_items; i++) {
00451                         j++;
00452                         j %= 4;
00453                         item = apol_vector_get_element(mod->result->items, i);
00454                         type = (qpol_type_t *) item->item;
00455                         qpol_type_get_name(q, type, &type_name);
00456                         printf("%s%s", type_name, (char *)((j && i != num_items - 1) ? ", " : "\n"));
00457                 }
00458                 printf("\n");
00459         }
00460 
00461         /* The proof report component is a display of a list of items
00462          * with an indented list of proof statements supporting the result
00463          * of the check for that item (e.g. rules with a given type)
00464          * this field also lists the computed severity of each item
00465          * (see sechk_item_sev in sechecker.c for details on calculation)
00466          * items are printed on a line either with (or, if long, such as a
00467          * rule, followed by) the severity. Each proof element is then
00468          * displayed in an indented list one per line below it. */
00469         if (outformat & SECHK_OUT_PROOF) {
00470                 printf("\n");
00471                 for (j = 0; j < num_items; j++) {
00472                         item = apol_vector_get_element(mod->result->items, j);
00473                         type = (qpol_type_t *) item->item;
00474                         qpol_type_get_name(q, type, &type_name);
00475                         if (item) {
00476                                 printf("%s\n", type_name);
00477                                 for (k = 0; k < apol_vector_get_size(item->proof); k++) {
00478                                         proof = apol_vector_get_element(item->proof, k);
00479                                         if (proof)
00480                                                 printf("\t%s\n", proof->text);
00481                                 }
00482                         }
00483                 }
00484                 printf("\n");
00485         }
00486 
00487         return 0;
00488 }
00489 
00490 int find_port_types_get_list(sechk_module_t * mod, apol_policy_t * policy __attribute__ ((unused)), void *arg)
00491 {
00492         apol_vector_t **v = arg;
00493 
00494         if (!mod || !arg) {
00495                 ERR(NULL, "%s", "Invalid parameters");
00496                 errno = EINVAL;
00497                 return -1;
00498         }
00499         if (strcmp(mod_name, mod->name)) {
00500                 ERR(NULL, "Wrong module (%s)", mod->name);
00501                 errno = EINVAL;
00502                 return -1;
00503         }
00504         if (!mod->result) {
00505                 ERR(NULL, "%s", "Module has not been run");
00506                 errno = EINVAL;
00507                 return -1;
00508         }
00509 
00510         v = &mod->result->items;
00511 
00512         return 0;
00513 }