On Sun, 18 Jul 2010 07:18:19 -0400
Jeff Layton <jlay...@redhat.com> wrote:

> On Thu, 15 Jul 2010 17:19:36 -0400
> Jeff Layton <jlay...@redhat.com> wrote:
> 
> > On Thu, 15 Jul 2010 15:24:46 -0500
> > Steve French <smfre...@gmail.com> wrote:
> > 
> > > I merged the first 5 of this series, but wanted to understand what
> > > behavior this changes first (it is probably ok).  With current
> > > userspace code - what changes would a user see with this?
> > > 
> > 
> > With this and the accompanying userspace patch, this makes it so that
> > the credentials cache used when mounting with sec=krb5 is unaffected by
> > the uid= option. The credcache will be determined using the real uid of
> > the user performing the mount. There will be a cifs.upcall option that
> > will make it use the legacy behavior for those that require it for some
> > reason. 
> > 
> > I consider the current situation a bad design decision on my part as
> > the ownership of files on the mount has no direct relationship to the
> > owner of the mount credentials. The mount credentials should always be
> > under the ownership of the user performing the mount. The existing
> > scheme allows someone to use the credcache of another user to perform
> > a mount.
> > 
> > I'll resend the userspace patch in another day or two when I get back
> > from vacation.
> > 
> 
> The corresponding userspace patch for this is below:
> 
> ------------------------[snip]---------------------------
> 
> [PATCH] cifs.upcall: use "creduid=" parm by default when available
> 
> When I did the original krb5 implementation, I goofed and ended up making
> it so that when someone specifies the "uid=" mount option that also affects
> the owner of the krb5 credential cache and not just the ownership of the
> mount. I'm proposing a patch for the kernel to attempt to fix this by
> making the kernel send a "creduid=" parameter in the upcall which is
> intended to be the user that should own the credentials cache.
> 
> That's not necessarily the same user that has "ownership" of the mount.
> Usually the creduid= will be set to the real uid of the user doing the
> mounting. When multisession mounts are introduced they will usually set
> this to the fsuid that walks into the mount.
> 
> To ease the transition, this patch also adds a command line switch that
> makes cifs.upcall use the "legacy" uid= parameter instead. Use that if you
> want it to behave like it used to.
> 
> Signed-off-by: Jeff Layton <jlay...@samba.org>
> ---
>  cifs.upcall.8 |    9 ++++++++-
>  cifs.upcall.c |   32 +++++++++++++++++++++++++++-----
>  2 files changed, 35 insertions(+), 6 deletions(-)
> 
> diff --git a/cifs.upcall.8 b/cifs.upcall.8
> index 7fc1603..815dd04 100644
> --- a/cifs.upcall.8
> +++ b/cifs.upcall.8
> @@ -22,7 +22,7 @@
>  cifs.upcall \- Userspace upcall helper for Common Internet File System (CIFS)
>  .SH "SYNOPSIS"
>  .HP \w'\ 'u
> -cifs\&.upcall [\-\-trust\-dns|\-t] [\-\-version|\-v] {keyid}
> +cifs\&.upcall [\-\-trust\-dns|\-t] [\-\-version|\-v] [\-\-legacy\-uid|\-l] 
> {keyid}
>  .SH "DESCRIPTION"
>  .PP
>  This tool is part of the cifs-utils suite\&.
> @@ -45,6 +45,13 @@ With krb5 upcalls, the name used as the host portion of 
> the service principal de
>  This is less secure than not trusting DNS\&. When using this option, it\'s 
> possible that an attacker could get control of DNS and trick the client into 
> mounting a different server altogether\&. It\'s preferable to instead add 
> server principals to the KDC for every possible hostname, but this option 
> exists for cases where that isn\'t possible\&. The default is to not trust 
> reverse hostname lookups in this fashion\&.
>  .RE
>  .PP
> +\-\-legacy\-uid|\-l
> +.RS 4
> +Traditionally, the kernel has sent only a single uid= parameter to the 
> upcall for the SPNEGO upcall that\'s used to determine what user's credential 
> cache to use. This parameter was generally determined by the uid= mount 
> option, which also governs the ownership of files on the mount\&.
> +.sp
> +Newer kernels send a creduid= option as well, which contains what uid it 
> thinks actually owns the credentials that it\'s looking for\&. At mount time, 
> this is generally set to the real uid of the user doing the mount. For 
> multisession mounts, it's set to the fsuid of the mount user. Set this option 
> if you want cifs.upcall to use the older uid= parameter instead of the 
> creduid= parameter\&.
> +.RE
> +.PP
>  \-\-version|\-v
>  .RS 4
>  Print version number and exit\&.
> diff --git a/cifs.upcall.c b/cifs.upcall.c
> index d4376cc..1f4341d 100644
> --- a/cifs.upcall.c
> +++ b/cifs.upcall.c
> @@ -389,6 +389,7 @@ handle_krb5_mech(const char *oid, const char *principal, 
> DATA_BLOB * secblob,
>  #define DKD_HAVE_IP          0x8
>  #define DKD_HAVE_UID         0x10
>  #define DKD_HAVE_PID         0x20
> +#define DKD_HAVE_CREDUID     0x40
>  #define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC)
>  
>  struct decoded_args {
> @@ -396,6 +397,7 @@ struct decoded_args {
>       char *hostname;
>       char *ip;
>       uid_t uid;
> +     uid_t creduid;
>       pid_t pid;
>       sectype_t sec;
>  };
> @@ -461,6 +463,16 @@ decode_key_description(const char *desc, struct 
> decoded_args *arg)
>                       } else {
>                               retval |= DKD_HAVE_UID;
>                       }
> +             } else if (strncmp(tkn, "creduid=", 8) == 0) {
> +                     errno = 0;
> +                     arg->creduid = strtol(tkn + 8, NULL, 16);
> +                     if (errno != 0) {
> +                             syslog(LOG_ERR, "Invalid creduid format: %s",
> +                                    strerror(errno));
> +                             return 1;
> +                     } else {
> +                             retval |= DKD_HAVE_CREDUID;
> +                     }
>               } else if (strncmp(tkn, "ver=", 4) == 0) {      /* if version */
>                       errno = 0;
>                       arg->ver = strtol(tkn + 4, NULL, 16);
> @@ -584,12 +596,13 @@ static int ip_to_fqdn(const char *addrstr, char *host, 
> size_t hostlen)
>  
>  static void usage(void)
>  {
> -     syslog(LOG_INFO, "Usage: %s [-t] [-v] key_serial", prog);
> -     fprintf(stderr, "Usage: %s [-t] [-v] key_serial\n", prog);
> +     syslog(LOG_INFO, "Usage: %s [-t] [-v] [-l] key_serial", prog);
> +     fprintf(stderr, "Usage: %s [-t] [-v] [-l] key_serial\n", prog);
>  }
>  
>  const struct option long_options[] = {
>       {"trust-dns", 0, NULL, 't'},
> +     {"legacy-uid", 0, NULL, 'l'},
>       {"version", 0, NULL, 'v'},
>       {NULL, 0, NULL, 0}
>  };
> @@ -603,7 +616,7 @@ int main(const int argc, char *const argv[])
>       size_t datalen;
>       unsigned int have;
>       long rc = 1;
> -     int c, try_dns = 0;
> +     int c, try_dns = 0, legacy_uid = 0;
>       char *buf, *princ = NULL, *ccname = NULL;
>       char hostbuf[NI_MAXHOST], *host;
>       struct decoded_args arg = { };
> @@ -621,6 +634,9 @@ int main(const int argc, char *const argv[])
>               case 't':
>                       try_dns++;
>                       break;
> +             case 'l':
> +                     legacy_uid++;
> +                     break;
>               case 'v':
>                       printf("version: %s\n", VERSION);
>                       goto out;
> @@ -677,13 +693,19 @@ int main(const int argc, char *const argv[])
>               goto out;
>       }
>  
> -     if (have & DKD_HAVE_UID) {
> +     if (!legacy_uid && (have & DKD_HAVE_CREDUID)) {
> +             rc = setuid(arg.creduid);
> +             if (rc == -1) {
> +                     syslog(LOG_ERR, "setuid: %s", strerror(errno));
> +                     goto out;
> +             }
> +             ccname = find_krb5_cc(CIFS_DEFAULT_KRB5_DIR, arg.creduid);
> +     } else if (have & DKD_HAVE_UID) {
>               rc = setuid(arg.uid);
>               if (rc == -1) {
>                       syslog(LOG_ERR, "setuid: %s", strerror(errno));
>                       goto out;
>               }
> -
>               ccname = find_krb5_cc(CIFS_DEFAULT_KRB5_DIR, arg.uid);
>       }
>  

Steve has queued the kernel patch up for 2.6.36, so I've gone ahead and
pushed this patch to the cifs-utils git repo. It should make the 4.6
release.

-- 
Jeff Layton <jlay...@redhat.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to