On Thu, 21 Apr 2011 09:15:59 -0500
[email protected] wrote:
> From: Shirish Pargaonkar <[email protected]>
>
> 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).
>
> An entry such as this
>
> create cifs.cifs_idmap * * /usr/sbin/cifs.upcall %k
>
> is needed in the file /etc/request-key.conf.
>
>
> Signed-off-by: Shirish Pargaonkar <[email protected]>
> ---
> Makefile.am | 2 +-
> cifs.upcall.c | 110
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 111 insertions(+), 1 deletions(-)
>
> diff --git a/Makefile.am b/Makefile.am
> index 67a0190..c9018ae 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -11,7 +11,7 @@ man_MANS = mount.cifs.8
> if CONFIG_CIFSUPCALL
> 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)
> +cifs_upcall_LDADD = -ltalloc -lwbclient -lkeyutils $(KRB5_LDADD)
> man_MANS += cifs.upcall.8
>
NAK:
This needs autoconf tests to ensure that libwbclient is actually
present and usable, and it needs to be able to build when it isn't.
> #
> diff --git a/cifs.upcall.c b/cifs.upcall.c
> index 479517c..68a8059 100644
> --- a/cifs.upcall.c
> +++ b/cifs.upcall.c
> @@ -45,6 +45,13 @@
> #include <time.h>
> #include <netdb.h>
> #include <arpa/inet.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <limits.h>
> +#include <wbclient.h>
>
> #include "util.h"
> #include "replace.h"
> @@ -695,6 +702,103 @@ static int cifs_resolver(const key_serial_t key, const
> char *key_descr)
> return 0;
> }
>
> +static int
> +cifs_sid_resolver(const key_serial_t key, const char *key_descr)
> +{
> + int i;
> + uid_t uid = 0;
> + gid_t gid = 0;;
> + wbcErr rc = 1;
> + const char *keyend = key_descr;
> + struct wbcDomainSid sid;
> + struct passwd *pw;
> + struct group *gr;
> +
> + /* skip next 4 ';' delimiters to get to description */
> + for (i = 1; i <= 4; ++i) {
> + keyend = index(keyend + 1, ';');
> + if (!keyend) {
> + syslog(LOG_ERR, "invalid key description: %s",
> + key_descr);
> + return 1;
> + }
> + }
> + keyend++;
> +
> + /*
> + * 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.
> + */
> + if (strncmp(keyend, "os", 2) == 0) {
> + keyend = index(keyend + 1, ':');
> + keyend++;
> + rc = wbcStringToSid(keyend, &sid);
> + if (rc)
> + syslog(LOG_DEBUG, "O strtosid: %s, rc: %d", keyend, rc);
> + else {
> + rc = wbcSidToUid(&sid, &uid);
> + if (rc)
> + syslog(LOG_DEBUG, "SID %s to uid wbc error: %d",
> + keyend, 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",
> + keyend, rc);
> + else {
> + uid = pw->pw_uid;
> + rc = 0;
> + }
> + }
> + if (!rc) { /* SID has been mapped to a uid */
> + rc = keyctl_instantiate(key, &uid, sizeof(uid_t), 0);
> + if (rc)
> + syslog(LOG_ERR, "%s: key inst: %s",
> + __func__, strerror(errno));
> + }
> + } else if (strncmp(keyend, "gs", 2) == 0) {
> + keyend = index(keyend + 1, ':');
> + keyend++;
> + rc = wbcStringToSid(keyend, &sid);
> + if (rc)
> + syslog(LOG_DEBUG, "O strtosid: %s, rc: %d", keyend, rc);
> + else {
> + rc = wbcSidToGid(&sid, &gid);
> + if (rc)
> + syslog(LOG_DEBUG, "SID %s to gid wbc error: %d",
> + keyend, rc);
> + }
> + if (rc) { /* either of the two wbcSid functions failed */
> + gr = getgrnam("nogroup");
> + if (!gr)
> + syslog(LOG_DEBUG, "SID %s to gid pw error: %d",
> + keyend, rc);
> + else {
> + gid = gr->gr_gid;
> + rc = 0;
> + }
> + }
> + if (!rc) { /* SID has been mapped to a gid */
> + rc = keyctl_instantiate(key, &gid, sizeof(gid_t), 0);
> + if (rc)
> + syslog(LOG_ERR, "%s: key inst: %s",
> + __func__, strerror(errno));
> + }
> + } else
> + syslog(LOG_DEBUG, "Invalid SID: %s", keyend);
> +
> + return rc;
> +}
> +
> /*
> * Older kernels sent IPv6 addresses without colons. Well, at least
> * they're fixed-length strings. Convert these addresses to have colon
> @@ -833,6 +937,12 @@ int main(const int argc, char *const argv[])
> goto out;
> }
>
> + if ((strncmp(buf, "cifs.cifs_idmap", sizeof("cifs.cifs_idmap") - 1)
> + == 0)) {
> + rc = cifs_sid_resolver(key, buf);
> + goto out;
> + }
> +
> have = decode_key_description(buf, &arg);
> SAFE_FREE(buf);
> if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
--
Jeff Layton <[email protected]>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html