RSS

NSS Responder

28 Jan

There are mainly two responders in SSSD: NSS and PAM.

The role of a Responder is:

  1. it receives request messages from a matching SSS Client
  2. fulfills the requests in one of two following ways:
  3. Either directly retrieving a valid cached result from the sysdb Cache, or
  4. Or asks the Backend to update the sysdb Cache and then retrieves an up-to-date result from the sysdb Cache.
  5. sends back response messages to the matching SSS Client

The NSS server consists of two major task of: the NSS client and the Data Provider. The NSS client requests data (request for user by name or by id etc )and receives the result from the NSS responder.

A very simple way to understand the flow can be following: As explained by my mentor (Jakub Jhrozek) 🙂
“The Data Provider can be though of as “the server”. It is the component that is called when there is no data available to the NSS responder. Maybe it would be easier to grasp how the NSS responder works with a
mini-algorithm:
0. Request comes in to gather data about an entity. This is
simulated in the test by calling
will_return(__wrap_sss_packet_get_cmd), in real world the function
sss_packet_get_cmd is called.
1. The NSS responder checks if the data is available in the cache by
calling the sysdb functions.
1a. If the data is available in the cache, it is returned. The
request ends, go to 2.
1b. If the data is not available in the cache, the Data Provider
is asked for the data. Execution waits for the Data Provider to
finish and then returns to 1.
1c. If the data is not available in the cache and the Data
Provider was checked already, set negative result and go to 2.
2. Result (positive or negative) is returned to the client. “
Now, let us take a function in order to understand its working:
/* Testsuite for getuid */
static void mock_input_id(uint8_t *id)
{
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
will_return(__wrap_sss_packet_get_body, id);
}
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);uint8_t id = 101;
mock_input_id(&id);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
mock_fill_user();/* Query for that user, 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);
}
Let us look into the above function test_nss_getpwuid()
1)
/* 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);
We are adding a valid user to system database.
2)
mock_input_id(&id);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
mock_fill_user();
Here, we are creating dummy packet with the above statements. Our test driver will be named __wrap_sss_packet_get_cmd() and this will replace the original sss_packet_get_cmd() function. We use __wrap since a linker flag makes it easy to “wrap” calls when named starting with “__wrap”.
will_return(function, value) : This way “value” is enqueued to the queue of mock values.
mock() : Likewise with mock() call, one value is dequeued from the mock value queue. We are writing mock of the original function, which instructs what value to be returned once mock is called in the function. mock_input_id() that will instruct __wrap_sss_packet_get_body() mentioned above, to return a uint32_t in the buffer.
3)
/* Query for that user, 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);
With sss_cmd_execute we tell program to ‘execute GETPWUID‘ and when that is ready, call test_nss_getpwuid_check(), written above. The function nss_cmd_getpwnuid will then get executed and it will read the data we prepared with mock_input_id(). When whole processing finishes, the callback test_nss_getpwnam_check will get executed.
Let us discuss more about other functionalities it in upcoming posts 🙂
Advertisements
 
Leave a comment

Posted by on January 28, 2014 in Uncategorized

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: