Re: [PATCH] cifs-utils: Create new binary cifs.idmap for sid to uid/gid mapping (try #3)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, May 23, 2011 at 8:08 AM, Jeff Layton <jlayton@xxxxxxxxxx> wrote:
> On Mon, 23 May 2011 08:04:09 -0500
> Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> wrote:
>
>> On Mon, May 23, 2011 at 7:42 AM, Jeff Layton <jlayton@xxxxxxxxxx> wrote:
>> > On Mon, 23 May 2011 07:26:49 -0500
>> > shirishpargaonkar@xxxxxxxxx wrote:
>> >
>> >> From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
>> >>
>> >> Handle cifs.idmap type of key. Extract a SID string from the description
>> >> and map it to either an uid or gid using winbind APIs.
>> >> If that fails (e.g. because winbind is not installed/running or winbind returns
>> >> an error), try to obtain uid of 'nobody' and gid of 'nogroup'.
>> >> And if that fails, kernel assigns uid and gid (from mount superblock).
>> >>
>> >> Enable including winbind header files and idmapping code conditional
>> >> to winbind devel rpms (header and library).
>> >>
>> >> An entry such as this
>> >>
>> >> create  cifs.idmap   *       *               /usr/sbin/cifs.idmap %k
>> >>
>> >> is needed in the file /etc/request-key.conf.
>> >>
>> >>
>> >> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
>> >> ---
>> >>  Makefile.am      |   11 +++-
>> >>  aclocal/idmap.m4 |   45 +++++++++++
>> >>  cifs.idmap.c     |  221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> >>  cifs.upcall.c    |    1 -
>> >>  configure.ac     |   20 +++++-
>> >>  5 files changed, 294 insertions(+), 4 deletions(-)
>> >>  create mode 100644 aclocal/idmap.m4
>> >>  create mode 100644 cifs.idmap.c
>> >>
>> >> diff --git a/Makefile.am b/Makefile.am
>> >> index 67a0190..c6eeb22 100644
>> >> --- a/Makefile.am
>> >> +++ b/Makefile.am
>> >> @@ -8,8 +8,10 @@ mount_cifs_LDADD = $(LIBCAP) $(CAPNG_LDADD)
>> >>
>> >>  man_MANS = mount.cifs.8
>> >>
>> >> +sbin_PROGRAMS =
>> >> +
>> >>  if CONFIG_CIFSUPCALL
>> >> -sbin_PROGRAMS = cifs.upcall
>> >> +sbin_PROGRAMS += cifs.upcall
>> >>  cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c util.c
>> >>  cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD)
>> >>  man_MANS += cifs.upcall.8
>> >> @@ -30,3 +32,10 @@ bin_PROGRAMS = cifscreds
>> >>  cifscreds_SOURCES = cifscreds.c resolve_host.c util.c
>> >>  cifscreds_LDADD = -lkeyutils
>> >>  endif
>> >> +
>> >> +if CONFIG_CIFSIDMAP
>> >> +sbin_PROGRAMS += cifs.idmap
>> >> +cifs_idmap_SOURCES = cifs.idmap.c
>> >> +cifs_idmap_LDADD = -lkeyutils $(WINB_LDADD)
>> >> +endif
>> >> +
>> >> diff --git a/aclocal/idmap.m4 b/aclocal/idmap.m4
>> >> new file mode 100644
>> >> index 0000000..211d372
>> >> --- /dev/null
>> >> +++ b/aclocal/idmap.m4
>> >> @@ -0,0 +1,45 @@
>> >> +dnl Headers needed by wbclient.h
>> >> +dnl
>> >> +AC_DEFUN([AC_WBCH_COMPL],[
>> >> +[
>> >> +#ifdef HAVE_STDINT_H
>> >> +#include <stdint.h>
>> >> +#endif
>> >> +]
>> >> +[#ifdef HAVE_STDBOOL_H
>> >> +#include <stdbool.h>
>> >> +#endif
>> >> +]
>> >> +[#ifdef HAVE_STDIO_H
>> >> +#include <stdio.h>
>> >> +#endif
>> >> +]
>> >> +[#ifdef HAVE_STDLIB_H
>> >> +#include <stdlib.h>
>> >> +#endif
>> >> +]
>> >> +[#ifdef HAVE_ERRNO_H
>> >> +#include <errno.h>
>> >> +#endif
>> >> +]])
>> >> +
>> >> +dnl Check for wbclient.h header and libwbclietn.so
>> >> +dnl
>> >> +AC_DEFUN([AC_TEST_WBCHL],[
>> >> +if test $enable_cifsidmap != "no"; then
>> >> +     AC_CHECK_HEADERS([wbclient.h], , [
>> >> +                             if test "$enable_cifsidmap" = "yes"; then
>> >> +                                     AC_MSG_ERROR([wbclient.h not found, consider installing libwbclient-devel.])
>> >> +                             else
>> >> +                                     AC_MSG_WARN([wbclient.h not found, consider installing libwbclient-devel. Disabling cifs.idmap.])
>> >> +                                     enable_cifsidmap="no"
>> >> +                             fi
>> >> +                     ], [ AC_WBCH_COMPL ])
>> >> +fi
>> >> +
>> >> +if test $enable_cifsidmap != "no"; then
>> >> +     AC_CHECK_LIB([wbclient], [wbcStringToSid],
>> >> +             [ WINB_LDADD='-lwbclient' ] [ AC_DEFINE(HAVE_LIBWBCLIENT, 1, ["Define var have_libwbclient"]) ], [AC_MSG_ERROR([No functioning wbclient library found!])])
>> >> +     AC_SUBST(WINB_LDADD)
>> >> +fi
>> >> +])
>> >> diff --git a/cifs.idmap.c b/cifs.idmap.c
>> >> new file mode 100644
>> >> index 0000000..7788bf2
>> >> --- /dev/null
>> >> +++ b/cifs.idmap.c
>> >> @@ -0,0 +1,221 @@
>> >> +/*
>> >> +* CIFS idmap helper.
>> >> +* Copyright (C) Shirish Pargaonkar (shirishp@xxxxxxxxxx) 2011
>> >> +*
>> >> +* Used by /sbin/request-key.conf for handling
>> >> +* cifs upcall for SID to uig/gid and uid/gid to SID mapping.
>> >> +* You should have keyutils installed and add
>> >> +* this lines to /etc/request-key.conf file:
>> >> +
>> >> +    create cifs.idmap * * /usr/local/sbin/cifs.idmap %k
>> >> +
>> >> +* This program is free software; you can redistribute it and/or modify
>> >> +* it under the terms of the GNU General Public License as published by
>> >> +* the Free Software Foundation; either version 2 of the License, or
>> >> +* (at your option) any later version.
>> >> +* This program is distributed in the hope that it will be useful,
>> >> +* but WITHOUT ANY WARRANTY; without even the implied warranty of
>> >> +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> >> +* GNU General Public License for more details.
>> >> +* You should have received a copy of the GNU General Public License
>> >> +* along with this program; if not, write to the Free Software
>> >> +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>> >> +*/
>> >> +
>> >> +#ifdef HAVE_CONFIG_H
>> >> +#include "config.h"
>> >> +#endif /* HAVE_CONFIG_H */
>> >> +
>> >> +#include <string.h>
>> >> +#include <getopt.h>
>> >> +#include <syslog.h>
>> >> +#include <dirent.h>
>> >> +#include <sys/types.h>
>> >> +#include <sys/stat.h>
>> >> +#include <unistd.h>
>> >> +#include <keyutils.h>
>> >> +#include <stdint.h>
>> >> +#include <stdbool.h>
>> >> +#include <stdio.h>
>> >> +#include <stdlib.h>
>> >> +#include <errno.h>
>> >> +#include <limits.h>
>> >> +#include <wbclient.h>
>> >> +
>> >> +static const char *prog = "cifs.idmap";
>> >> +
>> >> +static void usage(void)
>> >> +{
>> >> +     fprintf(stderr, "Usage: %s key_serial\n", prog);
>> >> +}
>> >> +
>> >> +char *strget(const char *str, char *substr)
>> >> +{
>> >> +     int len, sublen, retlen;
>> >> +     char *retstr, *substrptr;
>> >> +
>> >> +     sublen = strlen(substr);
>> >> +     substrptr = strstr(str, substr);
>> >> +     if (substrptr) {
>> >> +             len = strlen(substrptr);
>> >> +             substrptr += sublen;
>> >> +
>> >> +             retlen = len - sublen;
>> >> +             if (retlen > 0) {
>> >> +                     retstr = malloc(retlen + 1);
>> >> +                     if (retstr) {
>> >> +                             strncpy(retstr, substrptr, retlen);
>> >> +                             return retstr;
>> >> +                     }
>> >> +             }
>> >> +     }
>> >> +
>> >> +     return NULL;
>> >> +}
>> >> +
>> >
>> > I still worry a bit about bounds checking here, but I think we can trust
>> > keyctl_describe_alloc to give us a NULL terminated string, so let's not
>> > sweat it for now.
>> >
>> >> +static int
>> >> +cifs_idmap(const key_serial_t key, const char *key_descr)
>> >> +{
>> >> +     uid_t uid = 0;
>> >> +     gid_t gid = 0;;
>> >> +     wbcErr rc = 1;
>> >> +     char *sidstr = NULL;
>> >> +     struct wbcDomainSid sid;
>> >> +     struct passwd *pw;
>> >> +     struct group *gr;
>> >> +
>> >> +     /*
>> >> +      * Use winbind to convert received string to a SID and lookup
>> >> +      * name and map that SID to an uid.  If either of these
>> >> +      * function calls return with an error,  use system calls to obtain
>> >> +      * uid of user "nobody". If winbind fails to map a SID to an UID
>> >> +      * and there is no user named "nobody", return error to the
>> >> +      * upcall caller. Otherwise instanticate a key using that uid.
>> >> +      *
>> >> +      * The same applies to SID and gid mapping.  Instead of a
>> >> +      * user "nobody", user "nogroup" is looked up if winbind
>> >> +      * fails to map a SID to a gid.
>> >> +      */
>> >> +     sidstr = strget(key_descr, "os:");
>> >> +     if (sidstr) {
>> >> +             rc = wbcStringToSid(sidstr, &sid);
>> >> +             if (rc)
>> >> +                     syslog(LOG_DEBUG, "Invalid owner string: %s, rc: %d",
>> >> +                             key_descr, rc);
>> >> +             else {
>> >> +                     rc = wbcSidToUid(&sid, &uid);
>> >> +                     if (rc)
>> >> +                             syslog(LOG_DEBUG, "SID %s to uid wbc error: %d",
>> >> +                                             key_descr, rc);
>> >> +             }
>> >> +             if (rc) { /* either of the two wbcSid functions failed */
>> >> +                     pw = getpwnam("nobody");
>> >> +                     if (!pw)
>> >> +                             syslog(LOG_DEBUG, "SID %s to uid pw error: %d",
>> >> +                                     key_descr, rc);
>> >> +                     else {
>> >> +                             uid = pw->pw_uid;
>> >> +                             rc = 0;
>> >> +                     }
>> >                        ^^^^^^^^^^^
>> >                        Is it ever possible that the error from the wb
>> >                        libs will be transient? If so, then mapping
>> >                        this to nobody could be problematic, right?
>> >
>>
>> We can't say. It is possible that the error from winbind is
>> transiet and it is also possible that winbind is not running
>> at all.
>>
>> >                        Might it be better to not map it to anything
>> >                        and let the kernel turn this into the mount
>> >                        uid/gid? If "nobody" really is better then you
>> >                        probably ought to set a short timeout on this
>> >                        key.
>>
>> Even if the key is changed to a transiet, the mapping in cache in kernel
>> is "permanent" i.e. at least till that cache entry is evicted by shrinker,
>> if at all.
>>
>> What we can do is perhaps return different codes to kernel to only
>> mark an entry as mapped when key handling code returns 0, say
>> if it returns 1, then it is nobody/nogroup and do not mark an entry
>> as mapped. If it is error (negative ret code), do not mark an entry
>> as mapped but assign sb uid/gid.
>>
>
> That sounds a bit complicated. Why not just exit without instantiating
> the key if a successful mapping can't be made? With this scheme, you'll
> get different behavior depending on whether cifs.idmap couldn't be
> called, or if it got called and the mapping didn't get made.
>
> I think it might be best to have the user get the same behavior in the
> event of any failure. Thoughts?
>
> --
> Jeff Layton <jlayton@xxxxxxxxxx>
>

I think I am OK with that. So basically we are ruling out assigning
nobody/nogroup as uid/gid.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux