I'll defer to Andrew and Jeff on this one. We could articulate a compatibility
issue more clearly, but presumably this is not an issue for Windows
(or Samba) servers - but if there is a clear need for this for some other
server let us know so we can continue the discussion.

On Tue, Sep 6, 2011 at 10:26 AM, Martin Wilck
<[email protected]> wrote:
> This patch complements the kernel patch
> "cifs: add server-provided principal name in upcall". When cifs.upcall
> is started with -p, the kernel-provided principal name from the initial
> negotiation with the server will be used to obtain a ticket. If this fails,
> "cifs/<hostname>" and "host/hostname" fallbacks will be tried as fallback.
>
> This will enable kerberos-based CIFS mounts on more servers, and make
> mount.cifs work more similar to smbclient.
>
> Note that the "-p" option must be added in the cifs.upcall line in
> /etc/request-key.conf to activate this.
>
> Signed-off-by: Martin Wilck <[email protected]>
> ---
>  cifs.upcall.8.in |    6 ++++++
>  cifs.upcall.c    |   38 +++++++++++++++++++++++++++++++-------
>  cifs_spnego.h    |    2 +-
>  3 files changed, 38 insertions(+), 8 deletions(-)
>
> diff --git a/cifs.upcall.8.in b/cifs.upcall.8.in
> index 03842b7..7d90d1e 100644
> --- a/cifs.upcall.8.in
> +++ b/cifs.upcall.8.in
> @@ -52,6 +52,12 @@ Traditionally, the kernel has sent only a single uid= 
> parameter to the upcall fo
>  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
> +\-\-principal\-from\-kernel|\-p
> +.RS 4
> +When this option is used, the principal name obtained by the kernel from the 
> CIFS server is used rather than a principal name derived from the host name. 
> If this fails, the host name is used as fallback.
> +This makes it possible to obtain credentials for CIFS servers using 
> nonstandard principal names, and makes cifs mounts behave more similar to 
> smbclient, which also uses the server-provided principal name.
> +.RE
> +.PP
>  \-\-version|\-v
>  .RS 4
>  Print version number and exit\&.
> diff --git a/cifs.upcall.c b/cifs.upcall.c
> index de92092..2adac1d 100644
> --- a/cifs.upcall.c
> +++ b/cifs.upcall.c
> @@ -518,11 +518,13 @@ handle_krb5_mech(const char *oid, const char 
> *principal, DATA_BLOB * secblob,
>  #define DKD_HAVE_PID           0x20
>  #define DKD_HAVE_CREDUID       0x40
>  #define DKD_HAVE_USERNAME      0x80
> +#define DKD_HAVE_PRINCIPAL     0x100
>  #define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC)
>
>  struct decoded_args {
>        int ver;
>        char *hostname;
> +       char *principal;
>        char *ip;
>        char *username;
>        uid_t uid;
> @@ -557,6 +559,21 @@ decode_key_description(const char *desc, struct 
> decoded_args *arg)
>                        }
>                        retval |= DKD_HAVE_HOSTNAME;
>                        syslog(LOG_DEBUG, "host=%s", arg->hostname);
> +               } else if (!strncmp(tkn, "pri=", 4)) {
> +                       if (pos == NULL)
> +                               len = strlen(tkn);
> +                       else
> +                               len = pos - tkn;
> +
> +                       len -= 4;
> +                       SAFE_FREE(arg->principal);
> +                       arg->principal = strndup(tkn + 4, len);
> +                       if (arg->principal == NULL) {
> +                               syslog(LOG_ERR, "Unable to allocate memory");
> +                               return 1;
> +                       }
> +                       retval |= DKD_HAVE_PRINCIPAL;
> +                       syslog(LOG_DEBUG, "pri=%s", arg->principal);
>                } else if (!strncmp(tkn, "ip4=", 4) || !strncmp(tkn, "ip6=", 
> 4)) {
>                        if (pos == NULL)
>                                len = strlen(tkn);
> @@ -755,6 +772,7 @@ static void usage(void)
>  const struct option long_options[] = {
>        {"trust-dns", 0, NULL, 't'},
>        {"legacy-uid", 0, NULL, 'l'},
> +       {"principal-from-kernel", 0, NULL, 'p'},
>        {"version", 0, NULL, 'v'},
>        {NULL, 0, NULL, 0}
>  };
> @@ -768,7 +786,7 @@ int main(const int argc, char *const argv[])
>        size_t datalen;
>        unsigned int have;
>        long rc = 1;
> -       int c, try_dns = 0, legacy_uid = 0;
> +       int c, try_dns = 0, legacy_uid = 0, use_principal = 0;
>        char *buf, *princ = NULL, *ccname = NULL;
>        char hostbuf[NI_MAXHOST], *host;
>        struct decoded_args arg;
> @@ -781,7 +799,7 @@ int main(const int argc, char *const argv[])
>
>        openlog(prog, 0, LOG_DAEMON);
>
> -       while ((c = getopt_long(argc, argv, "cltv", long_options, NULL)) != 
> -1) {
> +       while ((c = getopt_long(argc, argv, "cltpv", long_options, NULL)) != 
> -1) {
>                switch (c) {
>                case 'c':
>                        /* legacy option -- skip it */
> @@ -792,6 +810,9 @@ int main(const int argc, char *const argv[])
>                case 'l':
>                        legacy_uid++;
>                        break;
> +               case 'p':
> +                       use_principal++;
> +                       break;
>                case 'v':
>                        printf("version: %s\n", VERSION);
>                        goto out;
> @@ -873,9 +894,16 @@ int main(const int argc, char *const argv[])
>        host = arg.hostname;
>
>        // do mech specific authorization
> +       oid = OID_KERBEROS5;
>        switch (arg.sec) {
>        case MS_KRB5:
> +               oid = OID_KERBEROS5_OLD;
>        case KRB5:
> +               if (use_principal && have & DKD_HAVE_PRINCIPAL) {
> +                       rc = handle_krb5_mech(oid, arg.principal, &secblob, 
> &sess_key, ccname);
> +                       if (!rc)
> +                               break;
> +               }
>  retry_new_hostname:
>                /* for "cifs/" service name + terminating 0 */
>                datalen = strlen(host) + 5 + 1;
> @@ -885,11 +913,6 @@ retry_new_hostname:
>                        break;
>                }
>
> -               if (arg.sec == MS_KRB5)
> -                       oid = OID_KERBEROS5_OLD;
> -               else
> -                       oid = OID_KERBEROS5;
> -
>                /*
>                 * try getting a cifs/ principal first and then fall back to
>                 * getting a host/ principal if that doesn't work.
> @@ -965,6 +988,7 @@ out:
>        data_blob_free(&sess_key);
>        SAFE_FREE(ccname);
>        SAFE_FREE(arg.hostname);
> +       SAFE_FREE(arg.principal);
>        SAFE_FREE(arg.ip);
>        SAFE_FREE(arg.username);
>        SAFE_FREE(keydata);
> diff --git a/cifs_spnego.h b/cifs_spnego.h
> index f8753a7..d43f965 100644
> --- a/cifs_spnego.h
> +++ b/cifs_spnego.h
> @@ -23,7 +23,7 @@
>  #ifndef _CIFS_SPNEGO_H
>  #define _CIFS_SPNEGO_H
>
> -#define CIFS_SPNEGO_UPCALL_VERSION 2
> +#define CIFS_SPNEGO_UPCALL_VERSION 3
>
>  /*
>  * The version field should always be set to CIFS_SPNEGO_UPCALL_VERSION.
> --
> 1.7.6
>
> --
> 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
>



-- 
Thanks,

Steve
--
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

Reply via email to