LCOV - code coverage report
Current view: top level - tests/cmocka - test_ifp.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 188 192 97.9 %
Date: 2015-10-19 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Jakub Hrozek <jhrozek@redhat.com>
       4             : 
       5             :     Copyright (C) 2013 Red Hat
       6             : 
       7             :     SSSD tests: InfoPipe responder
       8             : 
       9             :     This program is free software; you can redistribute it and/or modify
      10             :     it under the terms of the GNU General Public License as published by
      11             :     the Free Software Foundation; either version 3 of the License, or
      12             :     (at your option) any later version.
      13             : 
      14             :     This program is distributed in the hope that it will be useful,
      15             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :     GNU General Public License for more details.
      18             : 
      19             :     You should have received a copy of the GNU General Public License
      20             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include <popt.h>
      24             : 
      25             : #include "db/sysdb.h"
      26             : #include "tests/cmocka/common_mock.h"
      27             : #include "tests/cmocka/common_mock_resp.h"
      28             : #include "responder/ifp/ifp_private.h"
      29             : #include "sbus/sssd_dbus_private.h"
      30             : 
      31             : /* dbus library checks for valid object paths when unit testing, we don't
      32             :  * want that */
      33             : #undef DBUS_TYPE_OBJECT_PATH
      34             : #define DBUS_TYPE_OBJECT_PATH ((int) 's')
      35             : 
      36             : static struct ifp_ctx *
      37           3 : mock_ifp_ctx(TALLOC_CTX *mem_ctx)
      38             : {
      39             :     struct ifp_ctx *ifp_ctx;
      40             : 
      41           3 :     ifp_ctx = talloc_zero(mem_ctx, struct ifp_ctx);
      42           3 :     assert_non_null(ifp_ctx);
      43             : 
      44           3 :     ifp_ctx->rctx = mock_rctx(ifp_ctx, NULL, NULL, NULL);
      45           3 :     assert_non_null(ifp_ctx->rctx);
      46             : 
      47           3 :     ifp_ctx->rctx->allowed_uids = talloc_array(ifp_ctx->rctx, uint32_t, 1);
      48           3 :     assert_non_null(ifp_ctx->rctx->allowed_uids);
      49           3 :     ifp_ctx->rctx->allowed_uids[0] = geteuid();
      50           3 :     ifp_ctx->rctx->allowed_uids_count = 1;
      51             : 
      52           3 :     ifp_ctx->sysbus = talloc_zero(ifp_ctx, struct sysbus_ctx);
      53           3 :     assert_non_null(ifp_ctx->sysbus);
      54             : 
      55           3 :     ifp_ctx->sysbus->conn = talloc_zero(ifp_ctx, struct sbus_connection);
      56           3 :     assert_non_null(ifp_ctx->sysbus->conn);
      57             : 
      58           3 :     return ifp_ctx;
      59             : }
      60             : 
      61             : static struct sbus_request *
      62           4 : mock_sbus_request(TALLOC_CTX *mem_ctx, uid_t client)
      63             : {
      64             :     struct sbus_request *sr;
      65             : 
      66           4 :     sr = talloc_zero(mem_ctx, struct sbus_request);
      67           4 :     assert_non_null(sr);
      68             : 
      69           4 :     sr->conn = talloc_zero(sr, struct sbus_connection);
      70           4 :     assert_non_null(sr->conn);
      71             : 
      72           4 :     sr->message = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
      73           4 :     assert_non_null(sr->message);
      74           4 :     dbus_message_set_serial(sr->message, 1);
      75             : 
      76           4 :     sr->client = client;
      77             : 
      78           4 :     return sr;
      79             : }
      80             : 
      81           1 : void ifp_test_req_create(void **state)
      82             : {
      83             :     struct ifp_req *ireq;
      84             :     struct sbus_request *sr;
      85             :     struct ifp_ctx *ifp_ctx;
      86             :     errno_t ret;
      87             : 
      88           1 :     assert_true(leak_check_setup());
      89             : 
      90           1 :     ifp_ctx = mock_ifp_ctx(global_talloc_context);
      91           1 :     assert_non_null(ifp_ctx);
      92           1 :     check_leaks_push(ifp_ctx);
      93             : 
      94           1 :     sr = mock_sbus_request(ifp_ctx, geteuid());
      95           1 :     assert_non_null(sr);
      96           1 :     check_leaks_push(sr);
      97             : 
      98           1 :     ret = ifp_req_create(sr, ifp_ctx, &ireq);
      99           1 :     assert_int_equal(ret, EOK);
     100           1 :     talloc_free(ireq);
     101             : 
     102           1 :     assert_true(check_leaks_pop(sr) == true);
     103           1 :     talloc_free(sr);
     104             : 
     105           1 :     assert_true(check_leaks_pop(ifp_ctx) == true);
     106           1 :     talloc_free(ifp_ctx);
     107             : 
     108           1 :     assert_true(leak_check_teardown());
     109           1 : }
     110             : 
     111           1 : void ifp_test_req_wrong_uid(void **state)
     112             : {
     113             :     struct ifp_req *ireq;
     114             :     struct sbus_request *sr;
     115             :     struct ifp_ctx *ifp_ctx;
     116             :     errno_t ret;
     117             : 
     118           1 :     assert_true(leak_check_setup());
     119             : 
     120           1 :     ifp_ctx = mock_ifp_ctx(global_talloc_context);
     121           1 :     assert_non_null(ifp_ctx);
     122           1 :     check_leaks_push(ifp_ctx);
     123             : 
     124           1 :     sr = mock_sbus_request(ifp_ctx, geteuid()+1);
     125           1 :     assert_non_null(sr);
     126             : 
     127           1 :     ret = ifp_req_create(sr, ifp_ctx, &ireq);
     128           1 :     assert_int_equal(ret, EACCES);
     129           1 :     talloc_free(sr);
     130             : 
     131           1 :     assert_true(check_leaks_pop(ifp_ctx) == true);
     132           1 :     talloc_free(ifp_ctx);
     133             : 
     134           1 :     assert_true(leak_check_teardown());
     135           1 : }
     136             : 
     137           1 : void test_el_to_dict(void **state)
     138             : {
     139             :     static struct sbus_request *sr;
     140             :     dbus_bool_t dbret;
     141             :     DBusMessageIter iter;
     142             :     DBusMessageIter iter_dict;
     143             :     struct ldb_message_element *el;
     144             :     errno_t ret;
     145             :     char *attr_name;
     146             :     char *attr_val;
     147             : 
     148           1 :     sr = mock_sbus_request(global_talloc_context, geteuid());
     149           1 :     assert_non_null(sr);
     150             : 
     151           1 :     el = talloc(sr, struct ldb_message_element);
     152           1 :     assert_non_null(el);
     153           1 :     el->name = "numbers";
     154           1 :     el->values = talloc_array(el, struct ldb_val, 2);
     155           1 :     assert_non_null(el->values);
     156           1 :     el->num_values = 2;
     157           1 :     el->values[0].data = (uint8_t *) discard_const("one");
     158           1 :     el->values[0].length = strlen("one") + 1;
     159           1 :     el->values[1].data = (uint8_t *) discard_const("two");
     160           1 :     el->values[1].length = strlen("two") + 1;
     161             : 
     162           1 :     dbus_message_iter_init_append(sr->message, &iter);
     163           1 :     dbret = dbus_message_iter_open_container(
     164             :                                       &iter, DBUS_TYPE_ARRAY,
     165             :                                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
     166             :                                       DBUS_TYPE_STRING_AS_STRING
     167             :                                       DBUS_TYPE_VARIANT_AS_STRING
     168             :                                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
     169             :                                       &iter_dict);
     170           1 :     assert_true(dbret == TRUE);
     171             : 
     172           1 :     ret = ifp_add_ldb_el_to_dict(&iter_dict, el);
     173           1 :     assert_int_equal(ret, EOK);
     174             : 
     175           1 :     dbret = dbus_message_iter_close_container(&iter, &iter_dict);
     176           1 :     assert_true(dbret == TRUE);
     177             : 
     178             :     /* Test the reply contains what we expect */
     179           1 :     dbus_message_iter_init(sr->message, &iter);
     180           1 :     assert_int_equal(dbus_message_iter_get_arg_type(&iter),
     181             :                      DBUS_TYPE_ARRAY);
     182           1 :     dbus_message_iter_recurse(&iter, &iter);
     183           1 :     assert_int_equal(dbus_message_iter_get_arg_type(&iter),
     184             :                      DBUS_TYPE_DICT_ENTRY);
     185             : 
     186           1 :     dbus_message_iter_recurse(&iter, &iter_dict);
     187           1 :     dbus_message_iter_get_basic(&iter_dict, &attr_name);
     188           1 :     assert_string_equal(attr_name, "numbers");
     189             : 
     190           1 :     dbus_message_iter_next(&iter_dict);
     191           1 :     assert_int_equal(dbus_message_iter_get_arg_type(&iter_dict),
     192             :                      DBUS_TYPE_VARIANT);
     193           1 :     dbus_message_iter_recurse(&iter_dict, &iter_dict);
     194           1 :     assert_int_equal(dbus_message_iter_get_arg_type(&iter_dict),
     195             :                      DBUS_TYPE_ARRAY);
     196             : 
     197           1 :     dbus_message_iter_recurse(&iter_dict, &iter_dict);
     198           1 :     dbus_message_iter_get_basic(&iter_dict, &attr_val);
     199           1 :     assert_string_equal(attr_val, "one");
     200           1 :     assert_true(dbus_message_iter_next(&iter_dict));
     201           1 :     dbus_message_iter_get_basic(&iter_dict, &attr_val);
     202           1 :     assert_string_equal(attr_val, "two");
     203           1 :     assert_false(dbus_message_iter_next(&iter_dict));
     204             : 
     205           1 :     talloc_free(sr);
     206           1 : }
     207             : 
     208          11 : static void assert_string_list_equal(const char **s1,
     209             :                                      const char **s2)
     210             : {
     211             :     int i;
     212             : 
     213          57 :     for (i=0; s1[i]; i++) {
     214          46 :         assert_non_null(s2[i]);
     215          46 :         assert_string_equal(s1[i], s2[i]);
     216             :     }
     217             : 
     218          11 :     assert_null(s2[i]);
     219          11 : }
     220             : 
     221           7 : static void attr_parse_test(const char *expected[], const char *input)
     222             : {
     223             :     const char **res;
     224             :     TALLOC_CTX *test_ctx;
     225             : 
     226           7 :     test_ctx = talloc_new(NULL);
     227           7 :     assert_non_null(test_ctx);
     228             : 
     229           7 :     res = ifp_parse_user_attr_list(test_ctx, input);
     230             : 
     231           7 :     if (expected) {
     232             :         /* Positive test */
     233           6 :         assert_non_null(res);
     234           6 :         assert_string_list_equal(res, expected);
     235             :     } else {
     236             :         /* Negative test */
     237           1 :         assert_null(res);
     238             :     }
     239             : 
     240           7 :     talloc_free(test_ctx);
     241           7 : }
     242             : 
     243           5 : static void attr_parse_test_ex(const char *expected[], const char *input,
     244             :                                const char **defaults)
     245             : {
     246             :     const char **res;
     247             :     TALLOC_CTX *test_ctx;
     248             : 
     249           5 :     test_ctx = talloc_new(NULL);
     250           5 :     assert_non_null(test_ctx);
     251             : 
     252           5 :     res = parse_attr_list_ex(test_ctx, input, defaults);
     253             : 
     254           5 :     if (expected) {
     255             :         /* Positive test */
     256           5 :         assert_non_null(res);
     257           5 :         assert_string_list_equal(res, expected);
     258             :     } else {
     259             :         /* Negative test */
     260           0 :         assert_null(res);
     261             :     }
     262             : 
     263           5 :     talloc_free(test_ctx);
     264           5 : }
     265             : 
     266           1 : void test_attr_acl(void **state)
     267             : {
     268             :     /* Test defaults */
     269           1 :     const char *exp_defaults[] = { SYSDB_NAME, SYSDB_UIDNUM,
     270             :                                    SYSDB_GIDNUM, SYSDB_GECOS,
     271             :                                    SYSDB_HOMEDIR, SYSDB_SHELL,
     272             :                                    "groups", NULL };
     273           1 :     attr_parse_test(exp_defaults, NULL);
     274             : 
     275             :     /* Test adding some attributes to the defaults */
     276           1 :     const char *exp_add[] = { "telephoneNumber", "streetAddress",
     277             :                               SYSDB_NAME, SYSDB_UIDNUM,
     278             :                               SYSDB_GIDNUM, SYSDB_GECOS,
     279             :                               SYSDB_HOMEDIR, SYSDB_SHELL,
     280             :                               "groups", NULL };
     281           1 :     attr_parse_test(exp_add, "+telephoneNumber, +streetAddress");
     282             : 
     283             :     /* Test removing some attributes to the defaults */
     284           1 :     const char *exp_rm[] = { SYSDB_NAME,
     285             :                              SYSDB_GIDNUM, SYSDB_GECOS,
     286             :                              SYSDB_HOMEDIR, "groups",
     287             :                              NULL };
     288           1 :     attr_parse_test(exp_rm, "-"SYSDB_SHELL ",-"SYSDB_UIDNUM);
     289             : 
     290             :     /* Test both add and remove */
     291           1 :     const char *exp_add_rm[] = { "telephoneNumber",
     292             :                                  SYSDB_NAME, SYSDB_UIDNUM,
     293             :                                  SYSDB_GIDNUM, SYSDB_GECOS,
     294             :                                  SYSDB_HOMEDIR, "groups",
     295             :                                  NULL };
     296           1 :     attr_parse_test(exp_add_rm, "+telephoneNumber, -"SYSDB_SHELL);
     297             : 
     298             :     /* Test rm trumps add */
     299           1 :     const char *exp_add_rm_override[] = { SYSDB_NAME, SYSDB_UIDNUM,
     300             :                                           SYSDB_GIDNUM, SYSDB_GECOS,
     301             :                                           SYSDB_HOMEDIR, SYSDB_SHELL,
     302             :                                           "groups", NULL };
     303           1 :     attr_parse_test(exp_add_rm_override,
     304             :                     "+telephoneNumber, -telephoneNumber, +telephoneNumber");
     305             : 
     306             :     /* Remove all */
     307           1 :     const char *rm_all[] = { NULL };
     308           1 :     attr_parse_test(rm_all,  "-"SYSDB_NAME ", -"SYSDB_UIDNUM
     309             :                              ", -"SYSDB_GIDNUM ", -"SYSDB_GECOS
     310             :                              ", -"SYSDB_HOMEDIR ", -"SYSDB_SHELL", -groups");
     311             : 
     312             :     /* Malformed list */
     313           1 :     attr_parse_test(NULL,  "missing_plus_or_minus");
     314           1 : }
     315             : 
     316           1 : void test_attr_acl_ex(void **state)
     317             : {
     318             :     /* Test defaults */
     319           1 :     const char *exp_defaults[] = { "abc", "123", "xyz", NULL };
     320           1 :     attr_parse_test_ex(exp_defaults, NULL, exp_defaults);
     321             : 
     322             :     /* Test adding some attributes to the defaults */
     323           1 :     const char *exp_add[] = { "telephoneNumber", "streetAddress",
     324             :                               "abc", "123", "xyz",
     325             :                               NULL };
     326           1 :     attr_parse_test_ex(exp_add, "+telephoneNumber, +streetAddress",
     327             :                        exp_defaults);
     328             : 
     329             :     /* Test removing some attributes to the defaults */
     330           1 :     const char *exp_rm[] = { "123", NULL };
     331           1 :     attr_parse_test_ex(exp_rm, "-abc, -xyz", exp_defaults);
     332             : 
     333             :     /* Test adding with empty defaults */
     334           1 :     const char *exp_add_empty[] = { "telephoneNumber", "streetAddress",
     335             :                                     NULL };
     336           1 :     attr_parse_test_ex(exp_add_empty, "+telephoneNumber, +streetAddress", NULL);
     337             : 
     338             :     /* Test removing with empty defaults */
     339           1 :     const char *rm_all[] = { NULL };
     340           1 :     attr_parse_test_ex(rm_all, "-telephoneNumber, -streetAddress", NULL);
     341           1 : }
     342             : 
     343           1 : void test_attr_allowed(void **state)
     344             : {
     345           1 :     const char *whitelist[] = { "name", "gecos", NULL };
     346           1 :     const char *emptylist[] = { NULL };
     347             : 
     348           1 :     assert_true(ifp_attr_allowed(whitelist, "name"));
     349           1 :     assert_true(ifp_attr_allowed(whitelist, "gecos"));
     350             : 
     351           1 :     assert_false(ifp_attr_allowed(whitelist, "password"));
     352             : 
     353           1 :     assert_false(ifp_attr_allowed(emptylist, "name"));
     354           1 :     assert_false(ifp_attr_allowed(NULL, "name"));
     355           1 : }
     356             : 
     357             : struct ifp_test_req_ctx {
     358             :     struct ifp_req *ireq;
     359             :     struct sbus_request *sr;
     360             :     struct ifp_ctx *ifp_ctx;
     361             : };
     362             : 
     363           1 : static int ifp_test_req_setup(void **state)
     364             : {
     365             :     struct ifp_test_req_ctx *test_ctx;
     366             :     errno_t ret;
     367             : 
     368           1 :     assert_true(leak_check_setup());
     369             : 
     370           1 :     test_ctx = talloc_zero(global_talloc_context, struct ifp_test_req_ctx);
     371           1 :     assert_non_null(test_ctx);
     372           1 :     test_ctx->ifp_ctx = mock_ifp_ctx(test_ctx);
     373           1 :     assert_non_null(test_ctx->ifp_ctx);
     374             : 
     375           1 :     test_ctx->sr = mock_sbus_request(test_ctx, geteuid());
     376           1 :     assert_non_null(test_ctx->sr);
     377             : 
     378           1 :     ret = ifp_req_create(test_ctx->sr, test_ctx->ifp_ctx, &test_ctx->ireq);
     379           1 :     assert_int_equal(ret, EOK);
     380           1 :     assert_non_null(test_ctx->ireq);
     381             : 
     382           1 :     check_leaks_push(test_ctx);
     383           1 :     *state = test_ctx;
     384           1 :     return 0;
     385             : }
     386             : 
     387           1 : static int ifp_test_req_teardown(void **state)
     388             : {
     389           1 :     struct ifp_test_req_ctx *test_ctx = talloc_get_type_abort(*state,
     390             :                                                 struct ifp_test_req_ctx);
     391             : 
     392           1 :     assert_true(check_leaks_pop(test_ctx) == true);
     393             : 
     394           1 :     dbus_message_unref(test_ctx->sr->message);
     395           1 :     talloc_free(test_ctx);
     396             : 
     397           1 :     assert_true(leak_check_teardown());
     398           1 :     return 0;
     399             : }
     400             : 
     401           1 : int main(int argc, const char *argv[])
     402             : {
     403             :     poptContext pc;
     404             :     int opt;
     405           6 :     struct poptOption long_options[] = {
     406             :         POPT_AUTOHELP
     407           5 :         SSSD_DEBUG_OPTS
     408             :         POPT_TABLEEND
     409             :     };
     410             : 
     411           1 :     const struct CMUnitTest tests[] = {
     412             :         cmocka_unit_test(ifp_test_req_create),
     413             :         cmocka_unit_test(ifp_test_req_wrong_uid),
     414             :         cmocka_unit_test_setup_teardown(test_el_to_dict,
     415             :                                         ifp_test_req_setup,
     416             :                                         ifp_test_req_teardown),
     417             :         cmocka_unit_test(test_attr_acl),
     418             :         cmocka_unit_test(test_attr_acl_ex),
     419             :         cmocka_unit_test(test_attr_allowed),
     420             :     };
     421             : 
     422             :     /* Set debug level to invalid value so we can deside if -d 0 was used. */
     423           1 :     debug_level = SSSDBG_INVALID;
     424             : 
     425           1 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     426           1 :     while((opt = poptGetNextOpt(pc)) != -1) {
     427             :         switch(opt) {
     428             :         default:
     429           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
     430             :                     poptBadOption(pc, 0), poptStrerror(opt));
     431           0 :             poptPrintUsage(pc, stderr, 0);
     432           0 :             return 1;
     433             :         }
     434             :     }
     435           1 :     poptFreeContext(pc);
     436             : 
     437           1 :     DEBUG_CLI_INIT(debug_level);
     438             : 
     439             :     /* Even though normally the tests should clean up after themselves
     440             :      * they might not after a failed run. Remove the old db to be sure */
     441           1 :     tests_set_cwd();
     442             : 
     443           1 :     return cmocka_run_group_tests(tests, NULL, NULL);
     444             : }

Generated by: LCOV version 1.10