Simo suggests the algorithm supplied in the comments. For now, we don't try to guess the domainname when the hostname is not qualified, but add a comment with what needs to be done in order to support that. Signed-off-by: Jeff Layton <jlayton@xxxxxxxxx> --- cifs.upcall.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 78 insertions(+), 15 deletions(-) diff --git a/cifs.upcall.c b/cifs.upcall.c index d33e639..57ed0ba 100644 --- a/cifs.upcall.c +++ b/cifs.upcall.c @@ -45,6 +45,7 @@ #include <time.h> #include <netdb.h> #include <arpa/inet.h> +#include <ctype.h> #include "util.h" #include "replace.h" @@ -747,6 +748,23 @@ static int ip_to_fqdn(const char *addrstr, char *host, size_t hostlen) return 0; } +/* + * Copy a hostname from src to dst and uppercase it. Stop at the first '.' in + * the name or the end of src string. Append a '$'. + */ +static void +set_ad_principal(char *dst, char *src) +{ + while(*src && *src != '.') { + *dst = toupper(*src); + ++dst; + ++src; + } + *dst = '$'; + ++dst; + *dst = '\0'; +} + static void usage(void) { fprintf(stderr, "Usage: %s [-t] [-v] [-l] key_serial\n", prog); @@ -877,26 +895,71 @@ int main(const int argc, char *const argv[]) switch (arg.sec) { case MS_KRB5: case KRB5: -retry_new_hostname: + /* + * Simo Sorce's suggested scheme for picking a principal + * name, based on a supplied hostname. + * + * INPUT: fooo + * TRY in order: + * FOOO$@REALM + * cifs/fooo.<guessed domain ?>@REALM + * host/fooo.<guessed domain ?>@REALM + * + * INPUT: bar.example.com + * TRY in order: + * cifs/bar.example.com@REALM + * BAR$@REALM + * host/bar.example.com@REALM + */ 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. - */ - strlcpy(princ, "cifs/", sizeof(princ)); - strlcpy(princ + 5, host, sizeof(princ) - 5); - rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); - if (!rc) - break; - - memcpy(princ, "host/", 5); - rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); - if (!rc) - break; +retry_new_hostname: + /* If hostname has a '.', assume it's a FQDN */ + if (strchr(host, '.')) { + /* try "cifs/hostname" first */ + rc = snprintf(princ, sizeof(princ), "cifs/%s", host); + if (rc < 0 || (size_t)rc >= sizeof(princ)) { + syslog(LOG_ERR,"Unable to set hostname %s in buffer.", host); + goto out; + } + rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); + if (!rc) + break; + + /* now try AD-style name */ + set_ad_principal(princ, host); + rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); + if (!rc) + break; + + /* and now "host/" */ + rc = snprintf(princ, sizeof(princ), "host/%s", host); + if (rc < 0 || (size_t)rc >= sizeof(princ)) { + syslog(LOG_ERR,"Unable to set hostname %s in buffer.", host); + goto out; + } + rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); + if (!rc) + break; + } else { + /* shortname: try AD-style first */ + set_ad_principal(princ, host); + rc = handle_krb5_mech(oid, princ, &secblob, &sess_key, ccname); + if (!rc) + break; + + /* + * FIXME: try to guess the DNS domain name for the host. We + * must require that the kernel sends the IP addr in the upcall. + * + * Use getaddrinfo() to resolve the hostname of the server and + * set ai_canonname. Then use the domainname in ai canonname + * to turn the unqualified hostname into a FQDN. + */ + } if (!try_dns || !(have & DKD_HAVE_IP)) break; -- 1.7.6.4 -- 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