LCOV - code coverage report
Current view: top level - tests - auth-tests.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 108 137 78.8 %
Date: 2015-10-19 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     Test for local authentication utilities
       5             : 
       6             :     Authors:
       7             :         Sumit Bose <sbose@redhat.com>
       8             : 
       9             :     Copyright (C) 2010 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <stdlib.h>
      26             : #include <unistd.h>
      27             : #include <sys/stat.h>
      28             : #include <sys/types.h>
      29             : #include <errno.h>
      30             : #include <string.h>
      31             : #include <popt.h>
      32             : #include <talloc.h>
      33             : #include <tevent.h>
      34             : 
      35             : #include <check.h>
      36             : 
      37             : #include "util/util.h"
      38             : #include "confdb/confdb.h"
      39             : #include "db/sysdb.h"
      40             : #include "tests/common.h"
      41             : 
      42             : #define TESTS_PATH "tp_" BASE_FILE_STEM
      43             : #define TEST_CONF_FILE "tests_conf.ldb"
      44             : 
      45             : struct sysdb_test_ctx {
      46             :     struct sysdb_ctx *sysdb;
      47             :     struct confdb_ctx *confdb;
      48             :     struct tevent_context *ev;
      49             :     struct sss_domain_info *domain;
      50             : };
      51             : 
      52          16 : static int setup_sysdb_tests(struct sysdb_test_ctx **ctx)
      53             : {
      54             :     struct sysdb_test_ctx *test_ctx;
      55             :     char *conf_db;
      56             :     int ret;
      57             : 
      58             :     const char *val[2];
      59          16 :     val[1] = NULL;
      60             : 
      61             :     /* Create tests directory if it doesn't exist */
      62             :     /* (relative to current dir) */
      63          16 :     ret = mkdir(TESTS_PATH, 0775);
      64          16 :     if (ret == -1 && errno != EEXIST) {
      65           0 :         fail("Could not create %s directory", TESTS_PATH);
      66             :         return EFAULT;
      67             :     }
      68             : 
      69          16 :     test_ctx = talloc_zero(NULL, struct sysdb_test_ctx);
      70          16 :     if (test_ctx == NULL) {
      71           0 :         fail("Could not allocate memory for test context");
      72             :         return ENOMEM;
      73             :     }
      74             : 
      75             :     /* Create an event context
      76             :      * It will not be used except in confdb_init and sysdb_init
      77             :      */
      78          16 :     test_ctx->ev = tevent_context_init(test_ctx);
      79          16 :     if (test_ctx->ev == NULL) {
      80           0 :         fail("Could not create event context");
      81             :         talloc_free(test_ctx);
      82             :         return EIO;
      83             :     }
      84             : 
      85          16 :     conf_db = talloc_asprintf(test_ctx, "%s/%s", TESTS_PATH, TEST_CONF_FILE);
      86          16 :     if (conf_db == NULL) {
      87           0 :         fail("Out of memory, aborting!");
      88             :         talloc_free(test_ctx);
      89             :         return ENOMEM;
      90             :     }
      91          16 :     DEBUG(SSSDBG_MINOR_FAILURE, "CONFDB: %s\n", conf_db);
      92             : 
      93             :     /* Connect to the conf db */
      94          16 :     ret = confdb_init(test_ctx, &test_ctx->confdb, conf_db);
      95          16 :     if (ret != EOK) {
      96           0 :         fail("Could not initialize connection to the confdb");
      97             :         talloc_free(test_ctx);
      98             :         return ret;
      99             :     }
     100             : 
     101          16 :     val[0] = "LOCAL";
     102          16 :     ret = confdb_add_param(test_ctx->confdb, true,
     103             :                            "config/sssd", "domains", val);
     104          16 :     if (ret != EOK) {
     105           0 :         fail("Could not initialize domains placeholder");
     106             :         talloc_free(test_ctx);
     107             :         return ret;
     108             :     }
     109             : 
     110          16 :     val[0] = "local";
     111          16 :     ret = confdb_add_param(test_ctx->confdb, true,
     112             :                            "config/domain/LOCAL", "id_provider", val);
     113          16 :     if (ret != EOK) {
     114           0 :         fail("Could not initialize provider");
     115             :         talloc_free(test_ctx);
     116             :         return ret;
     117             :     }
     118             : 
     119          16 :     val[0] = "TRUE";
     120          16 :     ret = confdb_add_param(test_ctx->confdb, true,
     121             :                            "config/domain/LOCAL", "enumerate", val);
     122          16 :     if (ret != EOK) {
     123           0 :         fail("Could not initialize LOCAL domain");
     124             :         talloc_free(test_ctx);
     125             :         return ret;
     126             :     }
     127             : 
     128          16 :     val[0] = "TRUE";
     129          16 :     ret = confdb_add_param(test_ctx->confdb, true,
     130             :                            "config/domain/LOCAL", "cache_credentials", val);
     131          16 :     if (ret != EOK) {
     132           0 :         fail("Could not initialize LOCAL domain");
     133             :         talloc_free(test_ctx);
     134             :         return ret;
     135             :     }
     136             : 
     137          16 :     ret = sssd_domain_init(test_ctx, test_ctx->confdb, "local",
     138             :                            TESTS_PATH, &test_ctx->domain);
     139          16 :     if (ret != EOK) {
     140           0 :         fail("Could not initialize connection to the sysdb (%d)", ret);
     141             :         talloc_free(test_ctx);
     142             :         return ret;
     143             :     }
     144          16 :     test_ctx->sysdb = test_ctx->domain->sysdb;
     145             : 
     146          16 :     *ctx = test_ctx;
     147          16 :     return EOK;
     148             : }
     149             : 
     150          16 : static void do_failed_login_test(uint32_t failed_login_attempts,
     151             :                                  time_t last_failed_login,
     152             :                                  int offline_failed_login_attempts,
     153             :                                  int offline_failed_login_delay,
     154             :                                  int expected_result,
     155             :                                  int expected_counter,
     156             :                                  time_t expected_delay)
     157             : {
     158          16 :     struct sysdb_test_ctx *test_ctx = NULL;
     159             :     int ret;
     160             :     const char *val[2];
     161          16 :     val[1] = NULL;
     162             :     struct ldb_message *ldb_msg;
     163             :     uint32_t returned_failed_login_attempts;
     164             :     time_t delayed_until;
     165             : 
     166             :     /* Setup */
     167          16 :     ret = setup_sysdb_tests(&test_ctx);
     168          16 :     fail_unless(ret == EOK, "Could not set up the test");
     169             : 
     170          16 :     val[0] = talloc_asprintf(test_ctx, "%u", offline_failed_login_attempts);
     171          16 :     fail_unless(val[0] != NULL, "talloc_sprintf failed");
     172          16 :     ret = confdb_add_param(test_ctx->confdb, true,
     173             :                            "config/pam", CONFDB_PAM_FAILED_LOGIN_ATTEMPTS, val);
     174          16 :     fail_unless(ret == EOK, "Could not set offline_failed_login_attempts");
     175             : 
     176          16 :     val[0] = talloc_asprintf(test_ctx, "%u", offline_failed_login_delay);
     177          16 :     ret = confdb_add_param(test_ctx->confdb, true,
     178             :                            "config/pam", CONFDB_PAM_FAILED_LOGIN_DELAY, val);
     179          16 :     fail_unless(ret == EOK, "Could not set offline_failed_login_delay");
     180             : 
     181          16 :     ldb_msg = ldb_msg_new(test_ctx);
     182          16 :     fail_unless(ldb_msg != NULL, "ldb_msg_new failed");
     183             : 
     184          16 :     ret = ldb_msg_add_fmt(ldb_msg, SYSDB_FAILED_LOGIN_ATTEMPTS, "%u",
     185             :                           failed_login_attempts);
     186          16 :     fail_unless(ret == EOK, "ldb_msg_add_string failed");
     187             : 
     188          16 :     ret = ldb_msg_add_fmt(ldb_msg, SYSDB_LAST_FAILED_LOGIN, "%lld",
     189             :                           (long long) last_failed_login);
     190          16 :     fail_unless(ret == EOK, "ldb_msg_add_string failed");
     191             : 
     192          16 :     ret = check_failed_login_attempts(test_ctx->confdb, ldb_msg,
     193             :                                       &returned_failed_login_attempts,
     194             :                                       &delayed_until);
     195          16 :     fail_unless(ret == expected_result,
     196             :                 "check_failed_login_attempts returned wrong error code, "
     197             :                 "expected [%d], got [%d]", expected_result, ret);
     198             : 
     199          16 :     fail_unless(returned_failed_login_attempts == expected_counter,
     200             :                 "check_failed_login_attempts returned wrong number of failed "
     201             :                 "login attempts, expected [%d], got [%d]",
     202             :                 expected_counter, failed_login_attempts);
     203             : 
     204          16 :     fail_unless(delayed_until == expected_delay,
     205             :                 "check_failed_login_attempts wrong delay, "
     206             :                 "expected [%d], got [%d]",
     207             :                 expected_delay, delayed_until);
     208             : 
     209          16 :     talloc_free(test_ctx);
     210          16 : }
     211             : 
     212           1 : START_TEST(test_failed_login_attempts)
     213             : {
     214             :     time_t now;
     215             : 
     216             :     /* if offline_failed_login_attempts == 0 a login is never denied */
     217           1 :     do_failed_login_test(0,          0, 0, 5, EOK, 0, -1);
     218           1 :     do_failed_login_test(0, time(NULL), 0, 5, EOK, 0, -1);
     219           1 :     do_failed_login_test(2,          0, 0, 5, EOK, 2, -1);
     220           1 :     do_failed_login_test(2, time(NULL), 0, 5, EOK, 2, -1);
     221             : 
     222           1 :     do_failed_login_test(0,          0, 0, 0, EOK, 0, -1);
     223           1 :     do_failed_login_test(0, time(NULL), 0, 0, EOK, 0, -1);
     224           1 :     do_failed_login_test(2,          0, 0, 0, EOK, 2, -1);
     225           1 :     do_failed_login_test(2, time(NULL), 0, 0, EOK, 2, -1);
     226             : 
     227             :     /* if offline_failed_login_attempts != 0 and
     228             :      * offline_failed_login_delay == 0 a login is denied if the number of
     229             :      * failed attempts >= offline_failed_login_attempts */
     230           1 :     do_failed_login_test(0,          0, 2, 0, EOK, 0, -1);
     231           1 :     do_failed_login_test(0, time(NULL), 2, 0, EOK, 0, -1);
     232           1 :     do_failed_login_test(2,          0, 2, 0, ERR_AUTH_DENIED, 2, -1);
     233           1 :     do_failed_login_test(2, time(NULL), 2, 0, ERR_AUTH_DENIED, 2, -1);
     234             : 
     235             :     /* if offline_failed_login_attempts != 0 and
     236             :      * offline_failed_login_delay != 0 a login is denied only if the number of
     237             :      * failed attempts >= offline_failed_login_attempts AND the last failed
     238             :      * login attempt is not longer than offline_failed_login_delay ago */
     239           1 :     do_failed_login_test(0,          0, 2, 5, EOK, 0, -1);
     240           1 :     do_failed_login_test(0, time(NULL), 2, 5, EOK, 0, -1);
     241           1 :     do_failed_login_test(2,          0, 2, 5, EOK, 0, -1);
     242           1 :     now = time(NULL);
     243           1 :     do_failed_login_test(2, now, 2, 5, ERR_AUTH_DENIED, 2, (now + 5 * 60));
     244             : 
     245             : }
     246           1 : END_TEST
     247             : 
     248           1 : Suite *auth_suite (void)
     249             : {
     250           1 :     Suite *s = suite_create ("auth");
     251             : 
     252           1 :     TCase *tc_auth = tcase_create ("auth");
     253             : 
     254           1 :     tcase_add_test (tc_auth, test_failed_login_attempts);
     255           1 :     tcase_set_timeout(tc_auth, 60);
     256             : 
     257           1 :     suite_add_tcase (s, tc_auth);
     258             : 
     259           1 :     return s;
     260             : }
     261             : 
     262           2 : static int clean_db_dir(void)
     263             : {
     264             :     int ret;
     265             : 
     266           2 :     ret = unlink(TESTS_PATH"/"TEST_CONF_FILE);
     267           2 :     if (ret != EOK && errno != ENOENT) {
     268           0 :         fprintf(stderr, "Could not delete the test config ldb file (%d) (%s)\n",
     269           0 :                 errno, strerror(errno));
     270           0 :         return ret;
     271             :     }
     272             : 
     273           2 :     ret = unlink(TESTS_PATH"/"LOCAL_SYSDB_FILE);
     274           2 :     if (ret != EOK && errno != ENOENT) {
     275           0 :         fprintf(stderr, "Could not delete the test config ldb file (%d) (%s)\n",
     276           0 :                 errno, strerror(errno));
     277           0 :         return ret;
     278             :     }
     279             : 
     280           2 :     ret = rmdir(TESTS_PATH);
     281           2 :     if (ret != EOK && errno != ENOENT) {
     282           0 :         fprintf(stderr, "Could not delete the test directory (%d) (%s)\n",
     283           0 :                 errno, strerror(errno));
     284           0 :         return ret;
     285             :     }
     286             : 
     287           2 :     return EOK;
     288             : }
     289             : 
     290           1 : int main(int argc, const char *argv[])
     291             : {
     292             :     int ret;
     293             :     int opt;
     294             :     int failure_count;
     295             :     poptContext pc;
     296           1 :     Suite *s = auth_suite ();
     297           1 :     SRunner *sr = srunner_create (s);
     298             : 
     299           6 :     struct poptOption long_options[] = {
     300             :         POPT_AUTOHELP
     301           5 :         SSSD_MAIN_OPTS
     302             :         POPT_TABLEEND
     303             :     };
     304             : 
     305             :     /* Set debug level to invalid value so we can deside if -d 0 was used. */
     306           1 :     debug_level = SSSDBG_INVALID;
     307             : 
     308           1 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     309           1 :     while((opt = poptGetNextOpt(pc)) != -1) {
     310             :         switch(opt) {
     311             :         default:
     312           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
     313             :                     poptBadOption(pc, 0), poptStrerror(opt));
     314           0 :             poptPrintUsage(pc, stderr, 0);
     315           0 :             return 1;
     316             :         }
     317             :     }
     318           1 :     poptFreeContext(pc);
     319             : 
     320           1 :     DEBUG_CLI_INIT(debug_level);
     321             : 
     322           1 :     tests_set_cwd();
     323             : 
     324           1 :     ret = clean_db_dir();
     325           1 :     if (ret != EOK) {
     326           0 :         fprintf(stderr, "Could not delete the db directory (%d) (%s)\n",
     327           0 :                 errno, strerror(errno));
     328           0 :         return EXIT_FAILURE;
     329             :     }
     330             : 
     331           1 :     srunner_run_all(sr, CK_ENV);
     332           1 :     failure_count = srunner_ntests_failed (sr);
     333           1 :     srunner_free (sr);
     334           1 :     if (failure_count == 0) {
     335           1 :         ret = clean_db_dir();
     336           1 :         if (ret != EOK) {
     337           0 :             fprintf(stderr, "Could not delete the db directory (%d) (%s)\n",
     338           0 :                     errno, strerror(errno));
     339           0 :             return EXIT_FAILURE;
     340             :         }
     341             : 
     342           1 :         return EXIT_SUCCESS;
     343             :     }
     344           0 :     return  EXIT_FAILURE;
     345             : }

Generated by: LCOV version 1.10