test_nss_srv.c revision e4549c5364461644723361d688badde7fe137a25
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/*
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen Authors:
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen Jakub Hrozek <jhrozek@redhat.com>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen Copyright (C) 2013 Red Hat
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen SSSD tests: NSS responder tests
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen This program is free software; you can redistribute it and/or modify
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen it under the terms of the GNU General Public License as published by
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen the Free Software Foundation; either version 3 of the License, or
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen (at your option) any later version.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen This program is distributed in the hope that it will be useful,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen GNU General Public License for more details.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen You should have received a copy of the GNU General Public License
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen*/
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include <talloc.h>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include <tevent.h>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include <errno.h>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include <popt.h>
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen#include "tests/cmocka/common_mock.h"
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen#include "tests/cmocka/common_mock_resp.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "responder/common/negcache.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "responder/nss/nsssrv.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "responder/nss/nsssrv_private.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "sss_client/idmap/sss_nss_idmap.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen#include "util/util_sss_idmap.h"
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen#define TESTS_PATH "tests_nss"
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen#define TEST_CONF_DB "test_nss_conf.ldb"
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen#define TEST_DOM_NAME "nss_test"
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen#define TEST_SYSDB_FILE "cache_"TEST_DOM_NAME".ldb"
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen#define TEST_SUBDOM_NAME "test.subdomain"
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen#define TEST_ID_PROVIDER "ldap"
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainenstruct nss_test_ctx {
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen struct sss_test_ctx *tctx;
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen struct sss_domain_info *subdom;
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen struct resp_ctx *rctx;
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen struct cli_ctx *cctx;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen struct sss_cmd_table *nss_cmds;
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen struct nss_ctx *nctx;
78c471cb3d6467b7bb889330a86912cb8493e0fdTimo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen bool ncache_hit;
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen};
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenconst char *global_extra_attrs[] = {"phone", "mobile", NULL};
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenstruct nss_test_ctx *nss_test_ctx;
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen/* Mock NSS structure */
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenstruct nss_ctx *
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenmock_nctx(TALLOC_CTX *mem_ctx)
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen struct nss_ctx *nctx;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen errno_t ret;
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen enum idmap_error_code err;
d43c646d4b84635aa795946555be04a553d5413aTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen nctx = talloc_zero(mem_ctx, struct nss_ctx);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (!nctx) {
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return NULL;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen }
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen ret = sss_ncache_init(nctx, &nctx->ncache);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (ret != EOK) {
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen talloc_free(nctx);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return NULL;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen }
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen nctx->neg_timeout = 10;
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen nctx->pwfield = discard_const("*");
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen err = sss_idmap_init(sss_idmap_talloc, nctx, sss_idmap_talloc_free,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen &nctx->idmap_ctx);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (err != IDMAP_SUCCESS) {
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen DEBUG(SSSDBG_FATAL_FAILURE, "sss_idmap_init failed.\n");
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen talloc_free(nctx);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return NULL;
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen }
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return nctx;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen}
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen/* Mock reading requests from a client. Use values passed from mock
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen * instead
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen */
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenvoid __real_sss_packet_get_body(struct sss_packet *packet,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen uint8_t **body, size_t *blen);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenvoid __wrap_sss_packet_get_body(struct sss_packet *packet,
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen uint8_t **body, size_t *blen)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen enum sss_test_wrapper_call wtype = sss_mock_type(enum sss_test_wrapper_call);
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen size_t len;
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen
09ea3aa6bc03544a9e712d263f07976255aaaaf0Timo Sirainen if (wtype == WRAP_CALL_REAL) {
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return __real_sss_packet_get_body(packet, body, blen);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen }
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen *body = sss_mock_ptr_type(uint8_t *);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen len = sss_mock_type(size_t);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (len == 0) {
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen len = strlen((const char *) *body)+1;
78c471cb3d6467b7bb889330a86912cb8493e0fdTimo Sirainen }
78c471cb3d6467b7bb889330a86912cb8493e0fdTimo Sirainen *blen = len;
78c471cb3d6467b7bb889330a86912cb8493e0fdTimo Sirainen return;
78c471cb3d6467b7bb889330a86912cb8493e0fdTimo Sirainen}
78c471cb3d6467b7bb889330a86912cb8493e0fdTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/* Mock returning result to client. Terminate the unit test instead. */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainentypedef int (*cmd_cb_fn_t)(uint32_t, uint8_t *, size_t );
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic void set_cmd_cb(cmd_cb_fn_t fn)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_cmd_done, fn);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenvoid __wrap_sss_cmd_done(struct cli_ctx *cctx, void *freectx)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen struct sss_packet *packet = cctx->creq->out;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen uint8_t *body;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen size_t blen;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen cmd_cb_fn_t check_cb;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen check_cb = sss_mock_ptr_type(cmd_cb_fn_t);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen __real_sss_packet_get_body(packet, &body, &blen);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
88c2db95c4a0f8f7986a63cd57cf4b6850d76543Timo Sirainen nss_test_ctx->tctx->error = check_cb(sss_packet_get_status(packet),
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen body, blen);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen nss_test_ctx->tctx->done = true;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
88c2db95c4a0f8f7986a63cd57cf4b6850d76543Timo Sirainenenum sss_cli_command __wrap_sss_packet_get_cmd(struct sss_packet *packet)
88c2db95c4a0f8f7986a63cd57cf4b6850d76543Timo Sirainen{
88c2db95c4a0f8f7986a63cd57cf4b6850d76543Timo Sirainen return sss_mock_type(enum sss_cli_command);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
88c2db95c4a0f8f7986a63cd57cf4b6850d76543Timo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenint __wrap_sss_cmd_send_empty(struct cli_ctx *cctx, TALLOC_CTX *freectx)
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen{
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen nss_test_ctx->tctx->done = true;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen nss_test_ctx->tctx->error = ENOENT;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return EOK;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen}
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen/* Intercept negative cache lookups */
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenint __real_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen struct sss_domain_info *dom, const char *name);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenint __wrap_sss_ncache_check_user(struct sss_nc_ctx *ctx, int ttl,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen struct sss_domain_info *dom, const char *name)
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen{
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen int ret;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen ret = __real_sss_ncache_check_user(ctx, ttl, dom, name);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (ret == EEXIST) {
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen nss_test_ctx->ncache_hit = true;
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen }
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen return ret;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen}
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainenint __real_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenint __wrap_sss_ncache_check_uid(struct sss_nc_ctx *ctx, int ttl, uid_t uid)
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen{
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen int ret;
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen ret = __real_sss_ncache_check_uid(ctx, ttl, uid);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (ret == EEXIST) {
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen nss_test_ctx->ncache_hit = true;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen }
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen return ret;
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen}
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen/* Mock input from the client library */
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainenstatic void mock_input_user_or_group(const char *username)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen will_return(__wrap_sss_packet_get_body, username);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, 0);
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void mock_input_id(TALLOC_CTX *mem_ctx, uint32_t id)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen uint8_t *body;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen body = talloc_zero_array(mem_ctx, uint8_t, 4);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (body == NULL) return;
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen SAFEALIGN_SETMEM_UINT32(body, id, NULL);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
1704aa6b56b6a97bab6e995bcf7170b0c6527291Timo Sirainen will_return(__wrap_sss_packet_get_body, body);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, sizeof(uint32_t));
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainenstatic void mock_fill_user(void)
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* One packet for the entry and one for num entries */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
1704aa6b56b6a97bab6e995bcf7170b0c6527291Timo Sirainenstatic void mock_fill_group_with_members(unsigned members)
1704aa6b56b6a97bab6e995bcf7170b0c6527291Timo Sirainen{
1704aa6b56b6a97bab6e995bcf7170b0c6527291Timo Sirainen unsigned i;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (members == 0) return;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
8d6cb44a0161d88743756733f83c4fb278485987Timo Sirainen
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen /* Member header , one per member */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen for (i=0; i<members; i++) {
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen }
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic int parse_user_packet(uint8_t *body, size_t blen, struct passwd *pwd)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen size_t rp = 2 * sizeof(uint32_t);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen SAFEALIGN_COPY_UINT32(&pwd->pw_uid, body+rp, &rp);
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen SAFEALIGN_COPY_UINT32(&pwd->pw_gid, body+rp, &rp);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen /* Sequence of null terminated strings (name, passwd, gecos, dir, shell) */
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen pwd->pw_name = (char *) body+rp;
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen rp += strlen(pwd->pw_name) + 1;
e80203675151ef9d4f3f850cf02041042eb13096Timo Sirainen if (rp >= blen) return EINVAL;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen pwd->pw_passwd = (char *) body+rp;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen rp += strlen(pwd->pw_passwd) + 1;
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen if (rp >= blen) return EINVAL;
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen
1e21e6be70994b1aa9e52ca0e2f51afefca6d0dfTimo Sirainen pwd->pw_gecos = (char *) body+rp;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen rp += strlen(pwd->pw_gecos) + 1;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (rp >= blen) return EINVAL;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen pwd->pw_dir = (char *) body+rp;
b97514e470fc4c78f6f1ce4660f1e5aec559c3b4Timo Sirainen rp += strlen(pwd->pw_dir) + 1;
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen if (rp >= blen) return EINVAL;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen pwd->pw_shell = (char *) body+rp;
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen rp += strlen(pwd->pw_shell) + 1;
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen if (rp != blen) return EINVAL;
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen return EOK;
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen}
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainenstatic int parse_group_packet(uint8_t *body, size_t blen, struct group *gr, uint32_t *nmem)
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen size_t rp = 2 * sizeof(uint32_t); /* Len and reserved */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen unsigned i;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen SAFEALIGN_COPY_UINT32(&gr->gr_gid, body+rp, &rp);
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen SAFEALIGN_COPY_UINT32(nmem, body+rp, &rp);
4ac5448461b63de9637de839fbc611a3d503287cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen gr->gr_name = (char *) body+rp;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen rp += strlen(gr->gr_name) + 1;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (rp >= blen) return EINVAL;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
e03ec0b7b9d92551331bc509bcd86920544171d1Timo Sirainen gr->gr_passwd = (char *) body+rp;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen rp += strlen(gr->gr_passwd) + 1;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (*nmem > 0) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen gr->gr_mem = talloc_zero_array(nss_test_ctx, char *, *nmem);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (gr->gr_mem == NULL) return ENOMEM;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen for (i = 0; i < *nmem; i++) {
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (rp >= blen) return EINVAL;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen gr->gr_mem[i] = talloc_strdup(gr->gr_mem, (char *) body+rp);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen rp += strlen(gr->gr_mem[i]) + 1;
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen }
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen }
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen /* Make sure we exactly matched the end of the packet */
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen if (rp != blen) return EINVAL;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return EOK;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
c7480644202e5451fbed448508ea29a25cffc99cTimo Sirainen/* ====================== The tests =============================== */
/* Check getting cached and valid user from cache. Account callback will
* not be called and test_nss_getpwnam_check will make sure the user is
* the same as the test entered before starting
*/
static int test_nss_getpwnam_check(uint32_t status, uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 123);
assert_int_equal(pwd.pw_gid, 456);
assert_string_equal(pwd.pw_name, "testuser");
assert_string_equal(pwd.pw_shell, "/bin/sh");
assert_string_equal(pwd.pw_passwd, "*");
return EOK;
}
void test_nss_getpwnam(void **state)
{
errno_t ret;
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuser", 123, 456, "test user",
"/home/testuser", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testuser");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getpwnam_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
/* Test that searching for a nonexistant user yields ENOENT.
* Account callback will be called
*/
void test_nss_getpwnam_neg(void **state)
{
errno_t ret;
mock_input_user_or_group("testuser_neg");
mock_account_recv_simple();
assert_true(nss_test_ctx->ncache_hit == false);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with ENOENT */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, ENOENT);
assert_true(nss_test_ctx->ncache_hit == false);
/* Test that subsequent search for a nonexistent user yields
* ENOENT and Account callback is not called, on the other hand
* the ncache functions will be called
*/
nss_test_ctx->tctx->done = false;
mock_input_user_or_group("testuser_neg");
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with ENOENT */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, ENOENT);
/* Negative cache was hit this time */
assert_true(nss_test_ctx->ncache_hit == true);
}
static int test_nss_getpwnam_search_acct_cb(void *pvt)
{
errno_t ret;
struct nss_test_ctx *ctx = talloc_get_type(pvt, struct nss_test_ctx);
ret = sysdb_add_user(ctx->tctx->dom,
"testuser_search", 567, 890, "test search",
"/home/testsearch", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
return EOK;
}
static int test_nss_getpwnam_search_check(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 567);
assert_int_equal(pwd.pw_gid, 890);
assert_string_equal(pwd.pw_name, "testuser_search");
assert_string_equal(pwd.pw_shell, "/bin/sh");
return EOK;
}
void test_nss_getpwnam_search(void **state)
{
errno_t ret;
struct ldb_result *res;
mock_input_user_or_group("testuser_search");
mock_account_recv(0, 0, NULL, test_nss_getpwnam_search_acct_cb, nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
set_cmd_cb(test_nss_getpwnam_search_check);
ret = sysdb_getpwnam(nss_test_ctx, nss_test_ctx->tctx->dom,
"testuser_search", &res);
assert_int_equal(ret, EOK);
assert_int_equal(res->count, 0);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
/* test_nss_getpwnam_search_check will check the user attributes */
ret = sysdb_getpwnam(nss_test_ctx, nss_test_ctx->tctx->dom,
"testuser_search", &res);
assert_int_equal(ret, EOK);
assert_int_equal(res->count, 1);
}
/* Test that searching for a user that is expired in the cache goes to the DP
* which updates the record and the NSS responder returns the updated record
*
* The user's shell attribute is updated.
*/
static int test_nss_getpwnam_update_acct_cb(void *pvt)
{
errno_t ret;
struct nss_test_ctx *ctx = talloc_get_type(pvt, struct nss_test_ctx);
ret = sysdb_store_user(ctx->tctx->dom,
"testuser_update", NULL, 10, 11, "test user",
"/home/testuser", "/bin/ksh", NULL,
NULL, NULL, 300, 0);
assert_int_equal(ret, EOK);
return EOK;
}
static int test_nss_getpwnam_update_check(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 10);
assert_int_equal(pwd.pw_gid, 11);
assert_string_equal(pwd.pw_name, "testuser_update");
assert_string_equal(pwd.pw_shell, "/bin/ksh");
return EOK;
}
void test_nss_getpwnam_update(void **state)
{
errno_t ret;
struct ldb_result *res;
const char *shell;
/* Prime the cache with a valid but expired user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuser_update", 10, 11, "test user",
"/home/testuser", "/bin/sh", NULL,
NULL, 1, 1);
assert_int_equal(ret, EOK);
/* Mock client input */
mock_input_user_or_group("testuser_update");
/* Mock client command */
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
/* Call this function when user is updated by the mock DP request */
mock_account_recv(0, 0, NULL, test_nss_getpwnam_update_acct_cb, nss_test_ctx);
/* Call this function to check what the responder returned to the client */
set_cmd_cb(test_nss_getpwnam_update_check);
/* Mock output buffer */
mock_fill_user();
/* Fire the command */
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
/* Check the user was updated in the cache */
ret = sysdb_getpwnam(nss_test_ctx, nss_test_ctx->tctx->dom,
"testuser_update", &res);
assert_int_equal(ret, EOK);
assert_int_equal(res->count, 1);
shell = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SHELL, NULL);
assert_string_equal(shell, "/bin/ksh");
}
/* Check that a FQDN is returned if the domain is FQDN-only and a
* FQDN is requested
*/
static int test_nss_getpwnam_check_fqdn(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
nss_test_ctx->cctx->rctx->domains[0].fqnames = false;
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 124);
assert_int_equal(pwd.pw_gid, 457);
assert_string_equal(pwd.pw_name, "testuser_fqdn@"TEST_DOM_NAME);
assert_string_equal(pwd.pw_shell, "/bin/sh");
return EOK;
}
void test_nss_getpwnam_fqdn(void **state)
{
errno_t ret;
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuser_fqdn", 124, 457, "test user",
"/home/testuser", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testuser_fqdn@"TEST_DOM_NAME);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getpwnam_check_fqdn);
nss_test_ctx->cctx->rctx->domains[0].fqnames = true;
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
/* Check that a user with a space in his username is returned fine.
*/
static int test_nss_getpwnam_check_space(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 225);
assert_int_equal(pwd.pw_gid, 558);
assert_string_equal(pwd.pw_name, "space user");
assert_string_equal(pwd.pw_shell, "/bin/sh");
return EOK;
}
void test_nss_getpwnam_space(void **state)
{
errno_t ret;
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"space user", 225, 558, "space user",
"/home/testuser", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("space user");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getpwnam_check_space);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getpwnam_check_space_sub(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 225);
assert_int_equal(pwd.pw_gid, 558);
assert_string_equal(pwd.pw_name, "space_user");
assert_string_equal(pwd.pw_shell, "/bin/sh");
return EOK;
}
void test_nss_getpwnam_space_sub(void **state)
{
errno_t ret;
/* Set whitespace substitution */
nss_test_ctx->rctx->override_space = '_';
mock_input_user_or_group("space user");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getpwnam_check_space_sub);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
nss_test_ctx->rctx->override_space = '\0';
assert_int_equal(ret, EOK);
}
void test_nss_getpwnam_space_sub_query(void **state)
{
errno_t ret;
/* Set whitespace substitution */
nss_test_ctx->rctx->override_space = '_';
mock_input_user_or_group("space_user");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getpwnam_check_space_sub);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
nss_test_ctx->rctx->override_space = '\0';
assert_int_equal(ret, EOK);
}
/*
* Check that FQDN processing is able to handle arbitrarily sized
* delimeter
*/
static int test_nss_getpwnam_check_fancy_fqdn(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
nss_test_ctx->cctx->rctx->domains[0].fqnames = false;
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 125);
assert_int_equal(pwd.pw_gid, 458);
assert_string_equal(pwd.pw_name, "testuser_fqdn_fancy@@@@@"TEST_DOM_NAME);
assert_string_equal(pwd.pw_shell, "/bin/sh");
return EOK;
}
void test_nss_getpwnam_fqdn_fancy(void **state)
{
errno_t ret;
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuser_fqdn_fancy", 125, 458, "test user",
"/home/testuser", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testuser_fqdn_fancy@"TEST_DOM_NAME);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getpwnam_check_fancy_fqdn);
nss_test_ctx->cctx->rctx->domains[0].fqnames = true;
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
/* Check getting cached and valid id from cache. Account callback will
* not be called and test_nss_getpwuid_check will make sure the id is
* the same as the test entered before starting
*/
static int test_nss_getpwuid_check(uint32_t status, uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 101);
assert_int_equal(pwd.pw_gid, 401);
assert_string_equal(pwd.pw_name, "testuser1");
assert_string_equal(pwd.pw_shell, "/bin/sh");
assert_string_equal(pwd.pw_passwd, "*");
return EOK;
}
void test_nss_getpwuid(void **state)
{
errno_t ret;
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuser1", 101, 401, "test user1",
"/home/testuser1", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
uint32_t id = 101;
mock_input_id(nss_test_ctx, id);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
mock_fill_user();
/* Query for that id, call a callback when command finishes */
set_cmd_cb(test_nss_getpwuid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
/* Test that searching for a nonexistent id yields ENOENT.
* Account callback will be called
*/
void test_nss_getpwuid_neg(void **state)
{
errno_t ret;
uint8_t id = 102;
mock_input_id(nss_test_ctx, id);
mock_account_recv_simple();
assert_true(nss_test_ctx->ncache_hit == false);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with ENOENT */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, ENOENT);
assert_true(nss_test_ctx->ncache_hit == false);
/* Test that subsequent search for a nonexistent id yields
* ENOENT and Account callback is not called, on the other hand
* the ncache functions will be called
*/
nss_test_ctx->tctx->done = false;
mock_input_id(nss_test_ctx, id);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with ENOENT */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, ENOENT);
/* Negative cache was hit this time */
assert_true(nss_test_ctx->ncache_hit == true);
}
static int test_nss_getpwuid_search_acct_cb(void *pvt)
{
errno_t ret;
struct nss_test_ctx *ctx = talloc_get_type(pvt, struct nss_test_ctx);
ret = sysdb_add_user(ctx->tctx->dom,
"exampleuser_search", 107, 987, "example search",
"/home/examplesearch", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
return EOK;
}
static int test_nss_getpwuid_search_check(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 107);
assert_int_equal(pwd.pw_gid, 987);
assert_string_equal(pwd.pw_name, "exampleuser_search");
assert_string_equal(pwd.pw_shell, "/bin/sh");
return EOK;
}
void test_nss_getpwuid_search(void **state)
{
errno_t ret;
struct ldb_result *res;
uint8_t id = 107;
mock_input_id(nss_test_ctx, id);
mock_account_recv(0, 0, NULL, test_nss_getpwuid_search_acct_cb, nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
mock_fill_user();
set_cmd_cb(test_nss_getpwuid_search_check);
ret = sysdb_getpwuid(nss_test_ctx, nss_test_ctx->tctx->dom,
107, &res);
assert_int_equal(ret, EOK);
assert_int_equal(res->count, 0);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
/* test_nss_getpwuid_search_check will check the id attributes */
ret = sysdb_getpwuid(nss_test_ctx, nss_test_ctx->tctx->dom,
107, &res);
assert_int_equal(ret, EOK);
assert_int_equal(res->count, 1);
}
/* Test that searching for an id that is expired in the cache goes to the DP
* which updates the record and the NSS responder returns the updated record
*
* The user's shell attribute is updated.
*/
static int test_nss_getpwuid_update_acct_cb(void *pvt)
{
errno_t ret;
struct nss_test_ctx *ctx = talloc_get_type(pvt, struct nss_test_ctx);
ret = sysdb_store_user(ctx->tctx->dom,
"exampleuser_update", NULL, 109, 11000, "example user",
"/home/exampleuser", "/bin/ksh", NULL,
NULL, NULL, 300, 0);
assert_int_equal(ret, EOK);
return EOK;
}
static int test_nss_getpwuid_update_check(uint32_t status,
uint8_t *body, size_t blen)
{
struct passwd pwd;
errno_t ret;
assert_int_equal(status, EOK);
ret = parse_user_packet(body, blen, &pwd);
assert_int_equal(ret, EOK);
assert_int_equal(pwd.pw_uid, 109);
assert_int_equal(pwd.pw_gid, 11000);
assert_string_equal(pwd.pw_name, "exampleuser_update");
assert_string_equal(pwd.pw_shell, "/bin/ksh");
return EOK;
}
void test_nss_getpwuid_update(void **state)
{
errno_t ret;
struct ldb_result *res;
const char *shell;
/* Prime the cache with a valid but expired user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"exampleuser_update", 109, 11000, "example user",
"/home/exampleuser", "/bin/sh", NULL,
NULL, 1, 1);
assert_int_equal(ret, EOK);
/* Mock client input */
uint8_t id = 109;
mock_input_id(nss_test_ctx, id);
/* Mock client command */
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
/* Call this function when id is updated by the mock DP request */
mock_account_recv(0, 0, NULL, test_nss_getpwuid_update_acct_cb, nss_test_ctx);
/* Call this function to check what the responder returned to the client */
set_cmd_cb(test_nss_getpwuid_update_check);
/* Mock output buffer */
mock_fill_user();
/* Fire the command */
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
/* Check the user was updated in the cache */
ret = sysdb_getpwuid(nss_test_ctx, nss_test_ctx->tctx->dom,
109, &res);
assert_int_equal(ret, EOK);
assert_int_equal(res->count, 1);
shell = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SHELL, NULL);
assert_string_equal(shell, "/bin/ksh");
}
/* Testsuite setup and teardown */
void test_nss_setup(struct sss_test_conf_param params[],
void **state)
{
errno_t ret;
nss_test_ctx = talloc_zero(NULL, struct nss_test_ctx);
assert_non_null(nss_test_ctx);
nss_test_ctx->tctx = create_dom_test_ctx(nss_test_ctx, TESTS_PATH,
TEST_CONF_DB, TEST_DOM_NAME,
TEST_ID_PROVIDER, params);
assert_non_null(nss_test_ctx->tctx);
nss_test_ctx->nss_cmds = get_nss_cmds();
assert_non_null(nss_test_ctx->nss_cmds);
/* FIXME - perhaps this should be folded into sssd_domain_init or stricty
* used together
*/
ret = sss_names_init(nss_test_ctx, nss_test_ctx->tctx->confdb,
TEST_DOM_NAME, &nss_test_ctx->tctx->dom->names);
assert_int_equal(ret, EOK);
/* Initialize the NSS responder */
nss_test_ctx->nctx = mock_nctx(nss_test_ctx);
assert_non_null(nss_test_ctx->nctx);
ret = sss_names_init(nss_test_ctx->nctx, nss_test_ctx->tctx->confdb,
NULL, &nss_test_ctx->nctx->global_names);
assert_int_equal(ret, EOK);
assert_non_null(nss_test_ctx->nctx->global_names);
nss_test_ctx->rctx = mock_rctx(nss_test_ctx, nss_test_ctx->tctx->ev,
nss_test_ctx->tctx->dom, nss_test_ctx->nctx);
assert_non_null(nss_test_ctx->rctx);
nss_test_ctx->rctx->cdb = nss_test_ctx->tctx->confdb;
nss_test_ctx->nctx->rctx = nss_test_ctx->rctx;
/* Create client context */
nss_test_ctx->cctx = mock_cctx(nss_test_ctx, nss_test_ctx->rctx);
assert_non_null(nss_test_ctx->cctx);
}
static int test_nss_getgrnam_check(struct group *expected, struct group *gr, const int nmem)
{
int i;
assert_int_equal(gr->gr_gid, expected->gr_gid);
assert_string_equal(gr->gr_name, expected->gr_name);
assert_string_equal(gr->gr_passwd, expected->gr_passwd);
for (i = 0; i < nmem; i++) {
assert_string_equal(gr->gr_mem[i], expected->gr_mem[i]);
}
return EOK;
}
static int test_nss_getgrnam_no_members_check(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
struct group expected = {
.gr_gid = 1123,
.gr_name = discard_const("testgroup"),
.gr_passwd = discard_const("*"),
.gr_mem = NULL,
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 0);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
/* Test that requesting a valid, cached group with no members returns a valid
* group structure
*/
void test_nss_getgrnam_no_members(void **state)
{
errno_t ret;
/* Prime the cache with a valid group */
ret = sysdb_add_group(nss_test_ctx->tctx->dom,
"testgroup", 1123,
NULL, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testgroup");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(0);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_no_members_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_members_check(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
const char *exp_members[] = { "testmember1", "testmember2" };
struct group expected = {
.gr_gid = 1124,
.gr_name = discard_const("testgroup_members"),
.gr_passwd = discard_const("*"),
.gr_mem = discard_const(exp_members)
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 2);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
/* Test that requesting a valid, cached group with some members returns a valid
* group structure with those members present
*/
void test_nss_getgrnam_members(void **state)
{
errno_t ret;
/* Prime the cache with a valid group and some members */
ret = sysdb_add_group(nss_test_ctx->tctx->dom,
"testgroup_members", 1124,
NULL, 300, 0);
assert_int_equal(ret, EOK);
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testmember1", 2001, 456, "test member1",
"/home/testmember2", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testmember2", 2002, 456, "test member2",
"/home/testmember2", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
ret = sysdb_add_group_member(nss_test_ctx->tctx->dom,
"testgroup_members", "testmember1",
SYSDB_MEMBER_USER, false);
assert_int_equal(ret, EOK);
ret = sysdb_add_group_member(nss_test_ctx->tctx->dom,
"testgroup_members", "testmember2",
SYSDB_MEMBER_USER, false);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testgroup_members");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(2);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_members_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_members_check_fqdn(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
const char *exp_members[] = { "testmember1@"TEST_DOM_NAME,
"testmember2@"TEST_DOM_NAME };
struct group expected = {
.gr_gid = 1124,
.gr_name = discard_const("testgroup_members@"TEST_DOM_NAME),
.gr_passwd = discard_const("*"),
.gr_mem = discard_const(exp_members)
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 2);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
/* Test that requesting a valid, cached group with some members returns a valid
* group structure with those members present as fully qualified names
*/
void test_nss_getgrnam_members_fqdn(void **state)
{
errno_t ret;
nss_test_ctx->tctx->dom->fqnames = true;
mock_input_user_or_group("testgroup_members@"TEST_DOM_NAME);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(2);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_members_check_fqdn);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
/* Restore FQDN settings */
nss_test_ctx->tctx->dom->fqnames = false;
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_members_check_subdom(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
const char *exp_members[] = { "submember1@"TEST_SUBDOM_NAME,
"submember2@"TEST_SUBDOM_NAME };
struct group expected = {
.gr_gid = 2124,
.gr_name = discard_const("testsubdomgroup@"TEST_SUBDOM_NAME),
.gr_passwd = discard_const("*"),
.gr_mem = discard_const(exp_members)
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 2);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
/* Test that requesting a valid, cached group with some members returns a valid
* group structure with those members present as fully qualified names
*/
void test_nss_getgrnam_members_subdom(void **state)
{
errno_t ret;
nss_test_ctx->tctx->dom->fqnames = true;
/* Add a group from a subdomain and two members from the same subdomain
*/
ret = sysdb_add_group(nss_test_ctx->subdom,
"testsubdomgroup@"TEST_SUBDOM_NAME,
2124, NULL, 300, 0);
assert_int_equal(ret, EOK);
ret = sysdb_add_user(nss_test_ctx->subdom,
"submember1@"TEST_SUBDOM_NAME,
4001, 456, "test subdomain member1",
"/home/submember1", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
ret = sysdb_add_user(nss_test_ctx->subdom,
"submember2@"TEST_SUBDOM_NAME,
2002, 456, "test subdomain member2",
"/home/submember2", "/bin/sh", NULL,
NULL, 300, 0);
assert_int_equal(ret, EOK);
ret = sysdb_add_group_member(nss_test_ctx->subdom,
"testsubdomgroup@"TEST_SUBDOM_NAME,
"submember1@"TEST_SUBDOM_NAME,
SYSDB_MEMBER_USER, false);
assert_int_equal(ret, EOK);
ret = sysdb_add_group_member(nss_test_ctx->subdom,
"testsubdomgroup@"TEST_SUBDOM_NAME,
"submember2@"TEST_SUBDOM_NAME,
SYSDB_MEMBER_USER, false);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testsubdomgroup@"TEST_SUBDOM_NAME);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(2);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_members_check_subdom);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
/* Restore FQDN settings */
nss_test_ctx->tctx->dom->fqnames = false;
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_check_mix_dom(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
const char *exp_members[] = { "testmember1",
"testmember2",
"submember1@"TEST_SUBDOM_NAME };
struct group expected = {
.gr_gid = 1124,
.gr_name = discard_const("testgroup_members"),
.gr_passwd = discard_const("*"),
.gr_mem = discard_const(exp_members)
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 3);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
void test_nss_getgrnam_mix_dom(void **state)
{
errno_t ret;
const char *group_strdn = NULL;
const char *add_groups[] = { NULL, NULL };
/* Add a subdomain user to a parent domain group */
group_strdn = sysdb_group_strdn(nss_test_ctx,
nss_test_ctx->tctx->dom->name,
"testgroup_members");
assert_non_null(group_strdn);
add_groups[0] = group_strdn;
ret = sysdb_update_members_dn(nss_test_ctx->subdom,
"submember1@"TEST_SUBDOM_NAME,
SYSDB_MEMBER_USER,
add_groups, NULL);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testgroup_members");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(3);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_check_mix_dom);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_check_mix_dom_fqdn(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
const char *exp_members[] = { "testmember1@"TEST_DOM_NAME,
"testmember2@"TEST_DOM_NAME,
"submember1@"TEST_SUBDOM_NAME };
struct group expected = {
.gr_gid = 1124,
.gr_name = discard_const("testgroup_members@"TEST_DOM_NAME),
.gr_passwd = discard_const("*"),
.gr_mem = discard_const(exp_members)
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 3);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
void test_nss_getgrnam_mix_dom_fqdn(void **state)
{
errno_t ret;
nss_test_ctx->tctx->dom->fqnames = true;
mock_input_user_or_group("testgroup_members@"TEST_DOM_NAME);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(3);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_check_mix_dom_fqdn);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
/* Restore FQDN settings */
nss_test_ctx->tctx->dom->fqnames = false;
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_check_mix_subdom(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
const char *exp_members[] = { "submember1@"TEST_SUBDOM_NAME,
"submember2@"TEST_SUBDOM_NAME,
"testmember1@"TEST_DOM_NAME };
struct group expected = {
.gr_gid = 2124,
.gr_name = discard_const("testsubdomgroup@"TEST_SUBDOM_NAME),
.gr_passwd = discard_const("*"),
.gr_mem = discard_const(exp_members)
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 3);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
void test_nss_getgrnam_mix_subdom(void **state)
{
errno_t ret;
const char *group_strdn = NULL;
const char *add_groups[] = { NULL, NULL };
/* Add a subdomain user to a parent domain group */
group_strdn = sysdb_group_strdn(nss_test_ctx,
nss_test_ctx->subdom->name,
"testsubdomgroup@"TEST_SUBDOM_NAME);
assert_non_null(group_strdn);
add_groups[0] = group_strdn;
ret = sysdb_update_members_dn(nss_test_ctx->tctx->dom,
"testmember1",
SYSDB_MEMBER_USER,
add_groups, NULL);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testsubdomgroup@"TEST_SUBDOM_NAME);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(3);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_check_mix_subdom);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_space_check(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
struct group expected = {
.gr_gid = 2123,
.gr_name = discard_const("space group"),
.gr_passwd = discard_const("*"),
.gr_mem = NULL,
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 0);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
/* Test that requesting a valid, cached group with space in its name returns a valid
* group structure
*/
void test_nss_getgrnam_space(void **state)
{
errno_t ret;
/* Prime the cache with a valid group */
ret = sysdb_add_group(nss_test_ctx->tctx->dom,
"space group", 2123,
NULL, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("space group");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(0);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_space_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getgrnam_space_sub_check(uint32_t status,
uint8_t *body, size_t blen)
{
int ret;
uint32_t nmem;
struct group gr;
struct group expected = {
.gr_gid = 2123,
.gr_name = discard_const("space_group"),
.gr_passwd = discard_const("*"),
.gr_mem = NULL,
};
assert_int_equal(status, EOK);
ret = parse_group_packet(body, blen, &gr, &nmem);
assert_int_equal(ret, EOK);
assert_int_equal(nmem, 0);
ret = test_nss_getgrnam_check(&expected, &gr, nmem);
assert_int_equal(ret, EOK);
return EOK;
}
/* Test that requesting a valid, cached group with space in its name returns a valid
* group structure
*/
void test_nss_getgrnam_space_sub(void **state)
{
errno_t ret;
/* Set whitespace substitution */
nss_test_ctx->rctx->override_space = '_';
mock_input_user_or_group("space group");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM);
mock_fill_group_with_members(0);
/* Query for that group, call a callback when command finishes */
set_cmd_cb(test_nss_getgrnam_space_sub_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
nss_test_ctx->rctx->override_space = '\0';
assert_int_equal(ret, EOK);
}
static int test_nss_well_known_sid_check(uint32_t status,
uint8_t *body, size_t blen)
{
const char *name;
enum sss_id_type type;
size_t rp = 2 * sizeof(uint32_t);
char *expected_result = sss_mock_ptr_type(char *);
if (expected_result == NULL) {
assert_int_equal(status, EINVAL);
assert_int_equal(blen, 0);
} else {
assert_int_equal(status, EOK);
SAFEALIGN_COPY_UINT32(&type, body+rp, &rp);
name = (char *) body+rp;
assert_int_equal(type, SSS_ID_TYPE_GID);
assert_string_equal(name, expected_result);
}
return EOK;
}
void test_nss_well_known_getnamebysid(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "S-1-5-32-550");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETNAMEBYSID);
will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
will_return(test_nss_well_known_sid_check, "Print Operators@BUILTIN");
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETNAMEBYSID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void test_nss_well_known_getnamebysid_special(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "S-1-2-0");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETNAMEBYSID);
will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
will_return(test_nss_well_known_sid_check, "LOCAL@LOCAL AUTHORITY");
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETNAMEBYSID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void test_nss_well_known_getnamebysid_non_existing(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "S-1-5-32-123");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETNAMEBYSID);
will_return(test_nss_well_known_sid_check, NULL);
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETNAMEBYSID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void test_nss_well_known_getidbysid_failure(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "S-1-5-32-550");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETIDBYSID);
will_return(test_nss_well_known_sid_check, NULL);
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETIDBYSID,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void test_nss_well_known_getsidbyname(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "Cryptographic Operators@BUILTIN");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
will_return(test_nss_well_known_sid_check, "S-1-5-32-569");
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void test_nss_well_known_getsidbyname_nonexisting(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "Abc@BUILTIN");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
will_return(test_nss_well_known_sid_check, NULL);
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void test_nss_well_known_getsidbyname_special(void **state)
{
errno_t ret;
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, "CREATOR OWNER@CREATOR AUTHORITY");
will_return(__wrap_sss_packet_get_body, 0);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME);
will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
will_return(test_nss_well_known_sid_check, "S-1-3-0");
set_cmd_cb(test_nss_well_known_sid_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getorigbyname_check(uint32_t status, uint8_t *body,
size_t blen)
{
const char *s;
enum sss_id_type id_type;
size_t rp = 2 * sizeof(uint32_t);
assert_int_equal(status, EOK);
SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp);
assert_int_equal(id_type, SSS_ID_TYPE_UID);
/* Sequence of null terminated strings */
s = (char *) body+rp;
assert_string_equal(s, SYSDB_SID_STR);
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "S-1-2-3-4");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME);
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "orig_name");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM);
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "1234");
rp += strlen(s) + 1;
assert_int_equal(rp, blen);
return EOK;
}
void test_nss_getorigbyname(void **state)
{
errno_t ret;
struct sysdb_attrs *attrs;
attrs = sysdb_new_attrs(nss_test_ctx);
assert_non_null(attrs);
ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4");
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME,
"orig_name");
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234);
assert_int_equal(ret, EOK);
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuserorig", 1234, 5689, "test user orig",
"/home/testuserorig", "/bin/sh", NULL,
attrs, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testuserorig");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME);
will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getorigbyname_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
static int test_nss_getorigbyname_extra_check(uint32_t status, uint8_t *body,
size_t blen)
{
const char *s;
enum sss_id_type id_type;
size_t rp = 2 * sizeof(uint32_t);
assert_int_equal(status, EOK);
SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp);
assert_int_equal(id_type, SSS_ID_TYPE_UID);
/* Sequence of null terminated strings */
s = (char *) body+rp;
assert_string_equal(s, SYSDB_SID_STR);
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "S-1-2-3-4");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME);
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "orig_name");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM);
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "1234");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "phone");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "+12-34 56 78");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "mobile");
rp += strlen(s) + 1;
assert_true(rp < blen);
s = (char *) body+rp;
assert_string_equal(s, "+98-76 54 32");
rp += strlen(s) + 1;
assert_int_equal(rp, blen);
return EOK;
}
void test_nss_getorigbyname_extra_attrs(void **state)
{
errno_t ret;
struct sysdb_attrs *attrs;
attrs = sysdb_new_attrs(nss_test_ctx);
assert_non_null(attrs);
ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4");
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME,
"orig_name");
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234);
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_string(attrs, "phone", "+12-34 56 78");
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_string(attrs, "mobile", "+98-76 54 32");
assert_int_equal(ret, EOK);
ret = sysdb_attrs_add_string(attrs, "not_extra", "abc");
assert_int_equal(ret, EOK);
/* Prime the cache with a valid user */
ret = sysdb_add_user(nss_test_ctx->tctx->dom,
"testuserorigextra", 2345, 6789,
"test user orig extra",
"/home/testuserorigextra", "/bin/sh", NULL,
attrs, 300, 0);
assert_int_equal(ret, EOK);
mock_input_user_or_group("testuserorigextra");
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME);
will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
/* Query for that user, call a callback when command finishes */
set_cmd_cb(test_nss_getorigbyname_extra_check);
ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME,
nss_test_ctx->nss_cmds);
assert_int_equal(ret, EOK);
/* Wait until the test finishes with EOK */
ret = test_ev_loop(nss_test_ctx->tctx);
assert_int_equal(ret, EOK);
}
void nss_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
{ NULL, NULL }, /* Sentinel */
};
test_nss_setup(params, state);
}
void nss_fqdn_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
{ "full_name_format", "%1$s@%2$s" },
{ NULL, NULL }, /* Sentinel */
};
test_nss_setup(params, state);
}
void nss_test_setup_extra_attr(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
{ NULL, NULL }, /* Sentinel */
};
test_nss_setup(params, state);
nss_test_ctx->nctx->extra_attributes = global_extra_attrs;
}
void nss_subdom_test_setup(void **state)
{
const char *const testdom[4] = { TEST_SUBDOM_NAME, "TEST.SUB", "test", "S-3" };
struct sss_domain_info *subdomain;
errno_t ret;
nss_test_setup(state);
subdomain = new_subdomain(nss_test_ctx, nss_test_ctx->tctx->dom,
testdom[0], testdom[1], testdom[2], testdom[3],
false, false, NULL);
assert_non_null(subdomain);
ret = sysdb_subdomain_store(nss_test_ctx->tctx->sysdb,
testdom[0], testdom[1], testdom[2], testdom[3],
false, false, NULL);
assert_int_equal(ret, EOK);
ret = sysdb_update_subdomains(nss_test_ctx->tctx->dom);
assert_int_equal(ret, EOK);
nss_test_ctx->subdom = subdomain;
}
void nss_fqdn_fancy_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
{ "enumerate", "false" },
{ "full_name_format", "%1$s@@@@@%2$s" },
{ NULL, NULL }, /* Sentinel */
};
test_nss_setup(params, state);
}
void nss_test_teardown(void **state)
{
talloc_free(nss_test_ctx);
}
int main(int argc, const char *argv[])
{
int rv;
int no_cleanup = 0;
poptContext pc;
int opt;
struct poptOption long_options[] = {
POPT_AUTOHELP
SSSD_DEBUG_OPTS
{"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0,
_("Do not delete the test database after a test run"), NULL },
POPT_TABLEEND
};
const UnitTest tests[] = {
unit_test_setup_teardown(test_nss_getpwnam,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwuid,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_neg,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwuid_neg,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_search,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwuid_search,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_update,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwuid_update,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_fqdn,
nss_fqdn_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_fqdn_fancy,
nss_fqdn_fancy_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_space,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_space_sub,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getpwnam_space_sub_query,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_no_members,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_members,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_members_fqdn,
nss_fqdn_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_members_subdom,
nss_subdom_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_mix_dom,
nss_subdom_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_mix_dom_fqdn,
nss_subdom_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_mix_subdom,
nss_subdom_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_space,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getgrnam_space_sub,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getnamebysid,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getnamebysid_special,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getnamebysid_non_existing,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getidbysid_failure,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getsidbyname,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getsidbyname_nonexisting,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_well_known_getsidbyname_special,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getorigbyname,
nss_test_setup, nss_test_teardown),
unit_test_setup_teardown(test_nss_getorigbyname_extra_attrs,
nss_test_setup_extra_attr, nss_test_teardown),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
debug_level = SSSDBG_INVALID;
pc = poptGetContext(argv[0], argc, argv, long_options, 0);
while((opt = poptGetNextOpt(pc)) != -1) {
switch(opt) {
default:
fprintf(stderr, "\nInvalid option %s: %s\n\n",
poptBadOption(pc, 0), poptStrerror(opt));
poptPrintUsage(pc, stderr, 0);
return 1;
}
}
poptFreeContext(pc);
DEBUG_CLI_INIT(debug_level);
/* Even though normally the tests should clean up after themselves
* they might not after a failed run. Remove the old db to be sure */
tests_set_cwd();
test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_SYSDB_FILE);
test_dom_suite_setup(TESTS_PATH);
rv = run_tests(tests);
if (rv == 0 && !no_cleanup) {
test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_SYSDB_FILE);
}
return rv;
}