Re: [PATCH] cifs-utils: handle cifs_idmap type of key to map a SID to either an uid or gid (try #5)

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

 



On Fri, 11 Feb 2011 12:49:09 -0600
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).
> 
> 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 <shirishpargaonkar@xxxxxxxxx>
> ---
>  Makefile.am   |    2 +-
>  cifs.upcall.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 99 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
>  
>  #
> diff --git a/cifs.upcall.c b/cifs.upcall.c
> index 479517c..fe8a6ad 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,91 @@ 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++;
> +
> +	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) {
> +			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) {
> +			rc = keyctl_instantiate(key, &uid, sizeof(uid_t), 0);
> +			if (rc)
> +				syslog(LOG_ERR, "%s: key inst: %s",
> +					__func__, strerror(errno));
> +		}

	Instead of all this if then nesting and continual checking for
	the value of rc, I think it would be easier to follow the logic
	and maintain this if it instead either did a "goto out" in the
	error cases or just did a return when it hits an error.

> +	} 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) {
> +			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) {
> +			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");
				  ^^^^^^^^^^^^^^
		Might be helpful to know what that SID is, don't you
		think?
> +
> +	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 +925,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 <jlayton@xxxxxxxxxx>
--
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