summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/man/include/ldap_id_mapping.xml35
-rw-r--r--src/responder/nss/nsssrv_cmd.c134
-rw-r--r--src/tests/cmocka/test_nss_srv.c192
3 files changed, 361 insertions, 0 deletions
diff --git a/src/man/include/ldap_id_mapping.xml b/src/man/include/ldap_id_mapping.xml
index 71ff248f1..9dda39924 100644
--- a/src/man/include/ldap_id_mapping.xml
+++ b/src/man/include/ldap_id_mapping.xml
@@ -189,4 +189,39 @@ ldap_schema = ad
</refsect3>
</refsect2>
+ <refsect2 id='well_known_sids'>
+ <title>Well-Known SIDs</title>
+ <para>
+ SSSD supports to look up the names of Well-Known SIDs, i.e. SIDs
+ with a special hardcoded meaning. Since the generic users and groups
+ related to those Well-Known SIDs have no equivalent in a Linux/UNIX
+ environment no POSIX IDs are available for those objects.
+ </para>
+ <para>
+ The SID name space is organized in authorities which can be seen as
+ different domains. The authorities for the Well-Known SIDs are
+ <itemizedlist>
+ <listitem><para>Null Authority</para></listitem>
+ <listitem><para>World Authority</para></listitem>
+ <listitem><para>Local Authority</para></listitem>
+ <listitem><para>Creator Authority</para></listitem>
+ <listitem><para>NT Authority</para></listitem>
+ <listitem><para>Built-in</para></listitem>
+ </itemizedlist>
+ The capitalized version of these names are used as domain names when
+ returning the fully qualified name of a Well-Known SID.
+ </para>
+ <para>
+ Since some utilities allow to modify SID based access control
+ information with the help of a name instead of using the SID
+ directly SSSD supports to look up the SID by the name as well. To
+ avoid collisions only the fully qualified names are excepted to look
+ up Well-Known SIDs. As a result the domain names <quote>NULL
+ AUTHORITY</quote>, <quote>WORLD AUTHORITY</quote>, <quote> LOCAL
+ AUTHORITY</quote>, <quote>CREATOR AUTHORITY</quote>, <quote>NT
+ AUTHORITY</quote> and <quote>BUILTIN</quote> should not be used as
+ domain names in <filename>sssd.conf</filename>.
+ </para>
+ </refsect2>
+
</refsect1>
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index d9fc7155b..64bb9bc9f 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -973,6 +973,57 @@ done:
}
}
+static int nss_check_name_of_well_known_sid(struct nss_cmd_ctx *cmdctx,
+ const char *full_name)
+{
+ char *wk_name = NULL;
+ char *wk_dom_name = NULL;
+ const char *wk_sid;
+ int ret;
+ struct sized_string sid;
+ uint8_t *body;
+ size_t blen;
+ struct cli_ctx *cctx;
+ struct nss_ctx *nss_ctx;
+
+ nss_ctx = talloc_get_type(cmdctx->cctx->rctx->pvt_ctx, struct nss_ctx);
+ ret = sss_parse_name(cmdctx, nss_ctx->global_names, full_name,
+ &wk_dom_name, &wk_name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_parse_name failed.\n"));
+ return ret;
+ }
+
+ ret = name_to_well_known_sid(wk_dom_name, wk_name, &wk_sid);
+ talloc_free(wk_dom_name);
+ talloc_free(wk_name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Name [%s] is not the name of a " \
+ "Well-Known SID.\n", full_name));
+ return ret;
+ }
+
+ to_sized_string(&sid, wk_sid);
+
+ cctx = cmdctx->cctx;
+ ret = sss_packet_new(cctx->creq, sid.len + 3 * sizeof(uint32_t),
+ sss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ return ENOMEM;
+ }
+
+ sss_packet_get_body(cctx->creq->out, &body, &blen);
+ ((uint32_t *)body)[0] = 1; /* num results */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+ ((uint32_t *)body)[2] = (uint32_t) SSS_ID_TYPE_GID;
+ memcpy(&body[3*sizeof(uint32_t)], sid.str, sid.len);
+
+ sss_packet_set_error(cctx->creq->out, EOK);
+ sss_cmd_done(cctx, cmdctx);
+ return EOK;
+}
+
static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx);
static void nss_cmd_getbynam_done(struct tevent_req *req);
static int nss_cmd_getpwnam(struct cli_ctx *cctx)
@@ -1037,6 +1088,20 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx)
DEBUG(SSSDBG_TRACE_FUNC, ("Running command [%d] with input [%s].\n",
dctx->cmdctx->cmd, rawname));
+ if (dctx->cmdctx->cmd == SSS_NSS_GETSIDBYNAME) {
+ ret = nss_check_name_of_well_known_sid(cmdctx, rawname);
+ if (ret != ENOENT) {
+ if (ret == EOK) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Name [%s] is the name of a " \
+ "Well-Known SID.\n", rawname));
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("nss_check_name_of_well_known_sid failed.\n"));
+ }
+ goto done;
+ }
+ }
+
/* We need to attach to subdomain request, if the first one is not
* finished yet. We may not be able to lookup object in AD otherwise. */
if (cctx->rctx->get_domains_last_call.tv_sec == 0) {
@@ -4278,6 +4343,64 @@ static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx)
return EOK;
}
+static int nss_check_well_known_sid(struct nss_cmd_ctx *cmdctx)
+{
+ const char *wk_name;
+ const char *wk_dom_name;
+ int ret;
+ char *fq_name = NULL;
+ struct sized_string name;
+ uint8_t *body;
+ size_t blen;
+ struct cli_ctx *cctx;
+ struct nss_ctx *nss_ctx;
+
+ ret = well_known_sid_to_name(cmdctx->secid, &wk_dom_name, &wk_name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_TRACE_ALL, ("SID [%s] is not a Well-Known SID.\n",
+ cmdctx->secid));
+ return ret;
+ }
+
+ if (cmdctx->cmd != SSS_NSS_GETNAMEBYSID) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ ("Well-Known SIDs can only be translated to names.\n"));
+ return EINVAL;
+ }
+
+ if (wk_dom_name != NULL) {
+ nss_ctx = talloc_get_type(cmdctx->cctx->rctx->pvt_ctx, struct nss_ctx);
+ fq_name = sss_tc_fqname2(cmdctx, nss_ctx->global_names,
+ wk_dom_name, wk_dom_name, wk_name);
+ if (fq_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_tc_fqname2 failed.\n"));
+ return ENOMEM;
+ }
+ to_sized_string(&name, fq_name);
+ } else {
+ to_sized_string(&name, wk_name);
+ }
+
+ cctx = cmdctx->cctx;
+ ret = sss_packet_new(cctx->creq, name.len + 3 * sizeof(uint32_t),
+ sss_packet_get_cmd(cctx->creq->in),
+ &cctx->creq->out);
+ if (ret != EOK) {
+ talloc_free(fq_name);
+ return ENOMEM;
+ }
+
+ sss_packet_get_body(cctx->creq->out, &body, &blen);
+ ((uint32_t *)body)[0] = 1; /* num results */
+ ((uint32_t *)body)[1] = 0; /* reserved */
+ ((uint32_t *)body)[2] = (uint32_t) SSS_ID_TYPE_GID;
+ memcpy(&body[3*sizeof(uint32_t)], name.str, name.len);
+
+ sss_packet_set_error(cctx->creq->out, EOK);
+ sss_cmd_done(cctx, cmdctx);
+ return EOK;
+}
+
static int nss_cmd_getbysid(enum sss_cli_command cmd, struct cli_ctx *cctx)
{
@@ -4346,6 +4469,17 @@ static int nss_cmd_getbysid(enum sss_cli_command cmd, struct cli_ctx *cctx)
goto done;
}
+ ret = nss_check_well_known_sid(cmdctx);
+ if (ret != ENOENT) {
+ if (ret == EOK) {
+ DEBUG(SSSDBG_TRACE_ALL, ("SID [%s] is a Well-Known SID.\n",
+ cmdctx->secid));
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, ("nss_check_well_known_sid failed.\n"));
+ }
+ goto done;
+ }
+
ret = responder_get_domain_by_id(cctx->rctx, cmdctx->secid, &dctx->domain);
if (ret == EAGAIN || ret == ENOENT) {
req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, NULL);
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index b5b4565e9..d1a4d4bd8 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -30,6 +30,8 @@
#include "responder/common/negcache.h"
#include "responder/nss/nsssrv.h"
#include "responder/nss/nsssrv_private.h"
+#include "sss_client/idmap/sss_nss_idmap.h"
+#include "util/util_sss_idmap.h"
#define TESTS_PATH "tests_nss"
#define TEST_CONF_DB "test_nss_conf.ldb"
@@ -58,6 +60,7 @@ mock_nctx(TALLOC_CTX *mem_ctx)
{
struct nss_ctx *nctx;
errno_t ret;
+ enum idmap_error_code err;
nctx = talloc_zero(mem_ctx, struct nss_ctx);
if (!nctx) {
@@ -72,6 +75,14 @@ mock_nctx(TALLOC_CTX *mem_ctx)
nctx->neg_timeout = 10;
nctx->pwfield = discard_const("*");
+ err = sss_idmap_init(sss_idmap_talloc, nctx, sss_idmap_talloc_free,
+ &nctx->idmap_ctx);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_init failed.\n"));
+ talloc_free(nctx);
+ return NULL;
+ }
+
return nctx;
}
@@ -605,6 +616,11 @@ void test_nss_setup(struct sss_test_conf_param params[],
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);
@@ -1075,6 +1091,168 @@ void test_nss_getgrnam_mix_subdom(void **state)
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_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_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_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_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_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_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_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);
+}
+
void nss_test_setup(void **state)
{
struct sss_test_conf_param params[] = {
@@ -1177,6 +1355,20 @@ int main(int argc, const char *argv[])
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_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),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */