[SSSD] [PATCH] sss_client: Return a different error when sssd is not running

Lukas Slebodnik lslebodn at redhat.com
Wed Nov 12 14:10:43 UTC 2014


ehlo,

The sss nss plugin is present in nsswitch by default due to glibc caching
and problem with long living applications (e.g. GNOME). The SSSD nss plugin
should behave as if it was functioning but had no data even thought sssd is not
running. The errors have to be passed from nss plugin up to the user with
minimal moidiffication.

Resolves:
https://fedorahosted.org/sssd/ticket/2439

How to test:
    * minimal installation of fedora/rhel7 should already contain sss
    in /etc/nsswitch.
    * grep sss /etc/nsswitch
    * package sssd-client should be installed on machine
    * test glibc functions  whether ther return 0 for nonexisting group.
      (there is attached file sssd_error_code_test.c for lazy people :-)
    * the same return code should be with and without sss in /etc/nsswitch.conf
      authconfig --disablesssd --update
      authconfig --enablesssd --update

NOTE: I just patched functions which returned non-zero return code with stopped
sssd, because initgroups, getservent_r, getnetgrent_r returned 0 even with sss
in nsswitch.

There is also alternative solution from Stephen Gallagher which I found after
writing my patch :-)
https://bugzilla.redhat.com/attachment.cgi?id=788567

LS
-------------- next part --------------
>From 6e4ea98aa5c3375bc156e5e25fd25175fde889c3 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lslebodn at redhat.com>
Date: Tue, 11 Nov 2014 13:57:26 +0100
Subject: [PATCH] sss_client: Return a different error when sssd is not running

The sss nss plugin is present in nsswitch by default due to glibc caching
and problem with long living applications (e.g. GNOME). The SSSD nss plugin
should behave as if it was functioning but had no data even thought sssd is not
running. The errors have to be passed from nss plugin up to the user with
minimal moidiffication.

Resolves:
https://fedorahosted.org/sssd/ticket/2439
---
 src/sss_client/nss_group.c    | 16 ++++++++++++++++
 src/sss_client/nss_passwd.c   | 16 ++++++++++++++++
 src/sss_client/nss_services.c | 16 ++++++++++++++++
 3 files changed, 48 insertions(+)

diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c
index 1614c33b5388326d82f1c9c1baaeee472a676cb9..eed19b0e9359fd7d3e5e5b7b012a4bacd0c9c22d 100644
--- a/src/sss_client/nss_group.c
+++ b/src/sss_client/nss_group.c
@@ -439,6 +439,14 @@ enum nss_status _nss_sss_getgrnam_r(const char *name, struct group *result,
     nret = NSS_STATUS_SUCCESS;
 
 out:
+    /* sss is by default in nsswitch.
+     * This is a workaround for problem with stopped sssd.
+     */
+    if (nret == NSS_STATUS_UNAVAIL) {
+        nret = NSS_STATUS_NOTFOUND;
+        errno = 0;
+    }
+
     sss_nss_unlock();
     return nret;
 }
@@ -530,6 +538,14 @@ enum nss_status _nss_sss_getgrgid_r(gid_t gid, struct group *result,
     nret = NSS_STATUS_SUCCESS;
 
 out:
+    /* sss is by default in nsswitch.
+     * This is a workaround for problem with stopped sssd.
+     */
+    if (nret == NSS_STATUS_UNAVAIL) {
+        nret = NSS_STATUS_NOTFOUND;
+        errno = 0;
+    }
+
     sss_nss_unlock();
     return nret;
 }
diff --git a/src/sss_client/nss_passwd.c b/src/sss_client/nss_passwd.c
index 290aed80e0ddd817a0b2c818fdd0816cd2673a41..58e3a2085df4bea22e595b1368bc940a9699345b 100644
--- a/src/sss_client/nss_passwd.c
+++ b/src/sss_client/nss_passwd.c
@@ -218,6 +218,14 @@ enum nss_status _nss_sss_getpwnam_r(const char *name, struct passwd *result,
     nret = NSS_STATUS_SUCCESS;
 
 out:
+    /* sss is by default in nsswitch.
+     * This is a workaround for problem with stopped sssd.
+     */
+    if (nret == NSS_STATUS_UNAVAIL) {
+        nret = NSS_STATUS_NOTFOUND;
+        errno = 0;
+    }
+
     sss_nss_unlock();
     return nret;
 }
@@ -301,6 +309,14 @@ enum nss_status _nss_sss_getpwuid_r(uid_t uid, struct passwd *result,
     nret = NSS_STATUS_SUCCESS;
 
 out:
+    /* sss is by default in nsswitch.
+     * This is a workaround for problem with stopped sssd.
+     */
+    if (nret == NSS_STATUS_UNAVAIL) {
+        nret = NSS_STATUS_NOTFOUND;
+        errno = 0;
+    }
+
     sss_nss_unlock();
     return nret;
 }
diff --git a/src/sss_client/nss_services.c b/src/sss_client/nss_services.c
index 64e0b43e1643e4e76d2381a6b062335c3d513a21..1984cf431ca2444de29b23ff516d1a818c201870 100644
--- a/src/sss_client/nss_services.c
+++ b/src/sss_client/nss_services.c
@@ -255,6 +255,14 @@ _nss_sss_getservbyname_r(const char *name,
     nret = NSS_STATUS_SUCCESS;
 
 out:
+    /* sss is by default in nsswitch.
+     * This is a workaround for problem with stopped sssd.
+     */
+    if (nret == NSS_STATUS_UNAVAIL) {
+        nret = NSS_STATUS_NOTFOUND;
+        errno = 0;
+    }
+
     sss_nss_unlock();
     return nret;
 }
@@ -354,6 +362,14 @@ _nss_sss_getservbyport_r(int port, const char *protocol,
     nret = NSS_STATUS_SUCCESS;
 
 out:
+    /* sss is by default in nsswitch.
+     * This is a workaround for problem with stopped sssd.
+     */
+    if (nret == NSS_STATUS_UNAVAIL) {
+        nret = NSS_STATUS_NOTFOUND;
+        errno = 0;
+    }
+
     sss_nss_unlock();
     return nret;
 }
-- 
2.1.0

-------------- next part --------------
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#include <errno.h>

int main(void)
{
        struct group *g = malloc(sizeof(struct group));
        struct group *g_result = malloc(sizeof(struct group));
        char *buf;
        int ret;
        long buflen = sysconf(_SC_GETGR_R_SIZE_MAX);

        buf = malloc(buflen);

        errno = 0;
        ret = getgrgid_r(10001, g, buf, buflen, &g_result);
        printf("getgrgid_r ret=%d, result=%p, errno=%d\n",
               ret, g_result, errno);

        errno = 0;
        ret = getgrnam_r("superman", g, buf, buflen, &g_result);
        printf("getgrnam_r ret=%d, result=%p, errno=%d\n",
               ret, g_result, errno);

        struct passwd *pwd = malloc(sizeof(struct passwd));
        struct passwd *p_result = malloc(sizeof(struct passwd));
        buflen = sysconf(_SC_GETPW_R_SIZE_MAX);

        errno = 0;
        ret = getpwnam_r("superman", pwd,  buf, buflen, &p_result);
        printf("getpwnam_r ret=%d, result=%p, errno=%d\n",
               ret, p_result, errno);

        errno = 0;
        ret = getpwuid_r(10001, pwd,  buf, buflen, &p_result);
        printf("getpwuid_r ret=%d, result=%p, ernno=%d\n",
               ret, p_result, errno);

        struct servent *s_result = NULL;

        int port =  htons(3);
        char *protop = NULL;
        struct servent s = { 0, };

        errno = 0;
        ret = getservbyport_r(port, protop, &s,
                              buf, buflen, &s_result);
        printf("getservbyport_r ret=%d, result=%p, errno=%d\n",
               ret, s_result, errno);

        errno = 0;
        ret = getservbyname_r("superman", protop, &s,
                              buf, buflen, &s_result);
        printf("getservbyname_r ret=%d, result=%p, errno=%d\n",
               ret, s_result, errno);

        errno = 0;
        ret = initgroups("superman", getgid());
        printf("initgroups ret=%d, errno=%d\n", ret, errno);

        errno = 0;
        ret = getservent_r(&s, buf, buflen, &s_result);
        printf("getservent_r: ret=%d, result=%p, errno=%d\n",
               ret, s_result, errno);

        char *host, *user, *domain;
        errno = 0;
        ret = getnetgrent_r(&host, &user, &domain, buf, buflen);
        printf("getnetgrent_r: ret=%d, errno=%d\n",
               ret, errno);

        errno = 0;
        ret = innetgr("superman", NULL, NULL, NULL);
        printf("innetgr: ret=%d, errno=%d\n",
               ret, errno);

        return 0;
}


More information about the sssd-devel mailing list