/*
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2015 Red Hat
SSSD tests: PAM responder tests
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <security/pam_modules.h>
#include <popt.h>
#include "tests/cmocka/common_mock.h"
#include "tests/cmocka/common_mock_resp.h"
#include "responder/common/responder_packet.h"
#include "responder/common/negcache.h"
#include "responder/pam/pam_helpers.h"
#include "sss_client/pam_message.h"
#include "sss_client/sss_cli.h"
#include "util/crypto/sss_crypto.h"
#ifdef HAVE_NSS
#include "util/crypto/nss/nss_util.h"
#endif
#ifdef HAVE_TEST_CA
#include "tests/test_CA/SSSD_test_cert_x509_0001.h"
#include "tests/test_CA/SSSD_test_cert_x509_0002.h"
#else
#endif
struct pam_test_ctx {
int ncache_hits;
int exp_pam_status;
bool provider_contacted;
const char *pam_user_fqdn;
const char *wrong_user_fqdn;
};
/* Must be global because it is needed in some wrappers */
{
int ret;
int status;
return ret;
}
return ret;
}
if (child_pid == 0) { /* child */
if (ret == -1) {
exit(-1);
}
} else if (child_pid > 0) {
} else {
return ret;
}
if (child_pid == 0) { /* child */
if (ret == -1) {
exit(-1);
}
} else if (child_pid > 0) {
} else {
return ret;
}
return ret;
}
if (ret < 0) {
return ret;
}
ret = fprintf(fp, "parameters=configdir='sql:%s/src/tests/test_CA/p11_nssdb' dbSlotDescription='SSSD Test Slot' dbTokenDescription='SSSD Test Token' secmod='secmod.db' flags=readOnly \n\n", ABS_BUILD_DIR);
if (ret < 0) {
return ret;
}
if (ret != 0) {
return ret;
}
return ret;
}
if (ret < 0) {
return ret;
}
ret = fprintf(fp, "parameters=configdir='sql:%s/src/tests/test_CA/p11_nssdb_2certs' dbSlotDescription='SSSD Test Slot' dbTokenDescription='SSSD Test Token' secmod='secmod.db' flags=readOnly \n\n", ABS_BUILD_DIR);
if (ret < 0) {
return ret;
}
if (ret != 0) {
return ret;
}
return EOK;
}
static void cleanup_nss_db(void)
{
int ret;
}
}
}
}
}
}
}
}
}
{
/* Two NULLs so that tests can just assign a const to the first slot
* should they need it. The code iterates until first NULL anyway
*/
return NULL;
}
assert_int_equal(ret, 0);
return pctx;
}
{
int ret;
}
return EOK;
}
struct confdb_ctx *cdb)
{
}
struct confdb_ctx *cdb)
{
}
struct sss_test_conf_param pam_params[],
struct sss_test_conf_param monitor_params[],
void **state)
{
/* FIXME - perhaps this should be folded into sssd_domain_init or strictly
* used together
*/
/* Initialize the PAM responder */
/* Create client context */
}
static void pam_test_setup_common(void)
{
"pamuser",
"wronguser",
/* integer values cannot be set by pam_params */
/* Prime the cache with a valid user */
123, 456, "pam user",
NULL, 300, 0);
/* Add entry to the initgr cache to make sure no initgr request is sent to
* the backend */
discard_const("pamuser"),
/* Prime the cache with a user for wrong matches */
321, 654, "wrong user",
NULL, 300, 0);
/* Add entry to the initgr cache to make sure no initgr request is sent to
* the backend */
discard_const("wronguser"),
}
{
{ "enumerate", "false" },
{ "cache_credentials", "true" },
};
{ "p11_child_timeout", "30" },
};
{ "certificate_verification", "no_ocsp"},
};
return 0;
}
#ifdef HAVE_TEST_CA
#ifdef HAVE_NSS
{
{ "enumerate", "false" },
{ "cache_credentials", "true" },
};
{ "p11_child_timeout", "30" },
};
{ "certificate_verification", "no_verification" },
};
return 0;
}
#endif /* HAVE_NSS */
#endif /* HAVE_TEST_CA */
{
{ "enumerate", "false" },
{ "cache_credentials", "true" },
{ "cached_auth_timeout", CACHED_AUTH_TIMEOUT_STR },
};
{ "p11_child_timeout", "30" },
};
{ "certificate_verification", "no_ocsp"},
};
return 0;
}
{
int ret;
pam_test_ctx->pam_user_fqdn, 0);
pam_test_ctx->wrong_user_fqdn, 0);
return 0;
}
{
if (wtype == WRAP_CALL_REAL) {
}
if (len == 0) {
}
return;
}
{
}
{
return sss_mock_type(enum sss_cli_command);
}
{
return EOK;
}
{
}
{
pam_test_ctx->provider_contacted = true;
/* Set expected status */
return EOK;
}
const char *name,
const char *pwd,
const char *fa2,
const char *svc,
bool contact_dp)
{
int ret;
char *s_name;
char *dom;
} else {
pi.pam_user_size = 0;
}
} else {
}
}
svc = "pam_test_service";
}
assert_int_equal(ret, 0);
} else {
}
if (contact_dp) {
}
}
const char *name,
const char *pwd,
const char *fa2)
{
}
const char *pin, const char *token_name,
const char *module_name, const char *key_id,
const char *service,
bool only_one_provider_call)
{
int ret;
bool already_mocked = false;
} else {
pi.pam_user_size = 0;
}
key_id, 0,
&needed_size);
}
assert_int_equal(ret, 0);
already_mocked = true;
}
if (!(only_one_provider_call && already_mocked)) {
}
}
}
{
assert_int_equal(status, 0);
return EOK;
}
{
assert_int_equal(status, 0);
+ sizeof(TEST_TOKEN_NAME)));
+ sizeof(TEST_TOKEN_NAME)
+ sizeof(TEST_MODULE_NAME)
+ sizeof(TEST_KEY_ID)
+ sizeof(TEST_PROMPT)));
rp += sizeof(TEST_TOKEN_NAME);
rp += sizeof(TEST_MODULE_NAME);
rp += sizeof(TEST_KEY_ID);
rp += sizeof(TEST_PROMPT);
return EOK;
}
const char *name2)
{
assert_int_equal(status, 0);
} else {
} else {
}
}
+ sizeof(TEST_TOKEN_NAME)
+ sizeof(TEST_MODULE_NAME)
+ sizeof(TEST_KEY_ID)
+ sizeof(TEST_PROMPT)));
rp += sizeof(TEST_TOKEN_NAME);
rp += sizeof(TEST_MODULE_NAME);
rp += sizeof(TEST_KEY_ID);
rp += sizeof(TEST_PROMPT);
+ sizeof(TEST_TOKEN_NAME)
+ sizeof(TEST_MODULE_NAME)
+ sizeof(TEST2_KEY_ID)
+ sizeof(TEST2_PROMPT)));
rp += sizeof(TEST_TOKEN_NAME);
rp += sizeof(TEST_MODULE_NAME);
rp += sizeof(TEST2_KEY_ID);
rp += sizeof(TEST2_PROMPT);
}
return EOK;
}
{
NULL);
}
{
NULL);
}
{
}
{
}
{
"pamuser@"TEST_DOM_NAME);
}
{
assert_int_equal(status, 0);
return EOK;
}
{
}
{
}
{
}
{
}
{
}
{
assert_int_equal(status, 0);
assert_int_equal(val, 0);
return EOK;
}
{
assert_int_equal(status, 0);
assert_int_equal(val, 0);
return EOK;
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* make sure pam_status is not touched by setting it to a value which is
* not used by SSSD. */
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
/* Cached on-line authentication */
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
common_test_pam_cached_auth("12345");
/* Back end should be contacted */
"12345");
/* Reset before next call */
pam_test_ctx->provider_contacted = false;
common_test_pam_cached_auth("12345");
/* Back end should not be contacted */
}
{
int ret;
"12345");
common_test_pam_cached_auth("11111");
/* Back end should be contacted */
}
/* test cached_auth_timeout option */
{
int ret;
"12345");
common_test_pam_cached_auth("12345");
/* Back end should be contacted */
}
/* too long since last on-line authentication */
{
int ret;
"12345");
0);
common_test_pam_cached_auth("12345");
/* Back end should be contacted */
}
{
int ret;
common_test_pam_cached_auth("12345678");
/* Reset before next call */
pam_test_ctx->provider_contacted = false;
common_test_pam_cached_auth("12345678");
}
{
int ret;
common_test_pam_cached_auth("1111abcde");
}
/* Off-line authentication */
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345");
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345");
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345");
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345");
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345",
SSS_AUTHTOK_TYPE_2FA, 5);
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345",
SSS_AUTHTOK_TYPE_2FA, 5);
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345",
SSS_AUTHTOK_TYPE_2FA, 5);
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345",
SSS_AUTHTOK_TYPE_2FA, 5);
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
NULL, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345");
true);
/* Wait until the test finishes with EOK */
}
{
int ret;
"12345");
true);
/* Wait until the test finishes with EOK */
}
{
}
{
int ret;
/* Wait until the test finishes with EOK */
}
{
int ret;
}
return EOK;
}
{
int ret;
return EOK;
}
{
int ret;
}
return EOK;
}
{
int ret;
}
return EOK;
}
{
int ret;
test_lookup_by_cert_cb, NULL, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
test_lookup_by_cert_cb, SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
/* Test if PKCS11_LOGIN_TOKEN_NAME is added for the gdm-smartcard service */
{
int ret;
"gdm-smartcard", test_lookup_by_cert_cb,
SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
/* If no logon name is given the user is looked by certificate first.
* Since there is a matching user the upcoming lookup by name will find
* the user entry. But since we force the lookup by name to go to the
* backend to make sure the group-membership data is up to date the
* backend response has to be mocked twice.
* Additionally sss_parse_inp_recv() must be mocked because the cache
* request will be done with the username found by the certificate
* lookup. */
test_lookup_by_cert_cb, SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
/* If no logon name is given the user is looked by certificate first.
* Since user name hint is enabled we do not have to search the user
* during pre-auth and there is no need for an extra mocked response as in
* test_pam_preauth_cert_no_logon_name. */
test_lookup_by_cert_cb, SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
false);
/* Wait until the test finishes with EOK */
}
{
int ret;
false);
/* Wait until the test finishes with EOK */
}
{
int ret;
NULL, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
test_lookup_by_cert_cb, NULL, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Here the last option must be set to true because the backend is only
* connected once. During authentication the backend is connected first to
* see if it can handle Smartcard authentication, but before that the user
* is looked up. Since the first mocked reply already adds the certificate
* to the user entry the lookup by certificate will already find the user
* in the cache and no second request to the backend is needed. */
"NSS-Internal",
"C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
/* Assume backend cannot handle Smartcard credentials */
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Here the last option must be set to true because the backend is only
* connected once. During authentication the backend is connected first to
* see if it can handle Smartcard authentication, but before that the user
* is looked up. Since the first mocked reply already adds the certificate
* to the user entry the lookup by certificate will already find the user
* in the cache and no second request to the backend is needed. */
"NSS-Internal",
"C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
/* Assume backend cannot handle Smartcard credentials */
/* Wait until the test finishes with EOK */
}
{
int ret;
/* Here the last option must be set to true because the backend is only
* connected once. During authentication the backend is connected first to
* see if it can handle Smartcard authentication, but before that the user
* is looked up. Since the first mocked reply already adds the certificate
* to the user entry the lookup by certificate will already find the user
* in the cache and no second request to the backend is needed. */
/* Assume backend cannot handle Smartcard credentials */
/* Wait until the test finishes with EOK */
}
{
int ret;
"NSS-Internal",
"C554C9F82C2A9D58B70921C143304153A8A42F17", NULL,
true);
/* Assume backend cannot handle Smartcard credentials */
/* Wait until the test finishes with EOK */
}
{
int ret;
test_lookup_by_cert_cb, SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
SSSD_TEST_CERT_0001, false);
/* Wait until the test finishes with EOK */
}
{
int ret;
char *env;
{ CONFDB_PAM_VERBOSITY, "1" },
};
sizeof(offline_auth_data), offline_auth_data);
/* pd->resp_list points to the SSS_PAM_USER_INFO and pd->resp_list->next
* to the SSS_PAM_ENV_ITEM message. */
/* Test CONFDB_PAM_VERBOSITY option */
/* SSS_PAM_USER_INFO_OFFLINE_AUTH message will only be shown with
* pam_verbosity 2 or above if cache password never expires. */
/* Test CONFDB_PAM_RESPONSE_FILTER option */
/* for all services */
/* service name does not match */
/* multiple rules with a match */
"ENV:MyEnv:MyService, "
"ENV:stu:xyz";
}
{
int ret;
return ret;
}
/* This config option is only read on startup, which is not executed
* in test, so we can't just pass in a param
*/
return 0;
}
{
int ret;
/* The domain is POSIX, the request will skip over it */
}
{
int ret;
/* A different service than the app one can authenticate against a POSIX domain */
/* Wait until the test finishes with EOK */
}
{
{ "domain_type", "application" },
};
};
};
/* This config option is only read on startup, which is not executed
* in test, so we can't just pass in a param
*/
return 0;
}
{
int ret;
/* The domain is POSIX, the request will skip over it */
/* Wait until the test finishes with EOK */
}
{
int ret;
/* A different service than the app one can authenticate against a POSIX domain */
}
{
int rv;
int no_cleanup = 0;
int opt;
_("Do not delete the test database after a test run"), NULL },
};
#ifdef HAVE_TEST_CA
/* p11_child is not built without NSS */
#ifdef HAVE_NSS
#endif /* HAVE_NSS */
#endif /* HAVE_TEST_CA */
};
/* Set debug level to invalid value so we can decide if -d 0 was used. */
switch (opt) {
default:
return 1;
}
}
/* Even though normally the tests should clean up after themselves
* they might not after a failed run. Remove the old DB to be sure */
rv = setup_nss_db();
exit(-1);
}
if (rv == 0 && !no_cleanup) {
}
#ifdef HAVE_NSS
/* Cleanup NSS and NSPR to make Valgrind happy. */
#endif
return rv;
}