490251
From ab9266a2907fe523937d8576f6de7313d577c2e8 Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Mon, 13 May 2019 16:55:49 +0200
490251
Subject: [PATCH 1/9] s3:smbspool: Add the 'lp' group to the users groups
490251
490251
This is required to access files in /var/spool/cups which have been
490251
temporarily created in there by CUPS.
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 6086efb6808089c431e7307fa239924bfda1185b)
490251
---
490251
 source3/client/smbspool_krb5_wrapper.c | 22 ++++++++++++++++++++++
490251
 1 file changed, 22 insertions(+)
490251
490251
diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c
490251
index 5c4da33238b..e6684fc0d0c 100644
490251
--- a/source3/client/smbspool_krb5_wrapper.c
490251
+++ b/source3/client/smbspool_krb5_wrapper.c
490251
@@ -82,6 +82,7 @@ int main(int argc, char *argv[])
490251
 {
490251
 	char smbspool_cmd[PATH_MAX] = {0};
490251
 	struct passwd *pwd;
490251
+	struct group *g = NULL;
490251
 	char gen_cc[PATH_MAX] = {0};
490251
 	struct stat sb;
490251
 	char *env = NULL;
490251
@@ -89,6 +90,7 @@ int main(int argc, char *argv[])
490251
 	char device_uri[4096] = {0};
490251
 	uid_t uid = (uid_t)-1;
490251
 	gid_t gid = (gid_t)-1;
490251
+	gid_t groups[1] = { (gid_t)-1 };
490251
 	unsigned long tmp;
490251
 	int cmp;
490251
 	int rc;
490251
@@ -176,6 +178,26 @@ int main(int argc, char *argv[])
490251
 		return CUPS_BACKEND_FAILED;
490251
 	}
490251
 
490251
+	/*
490251
+	 * We need the primary group of the 'lp' user. This is needed to access
490251
+	 * temporary files in /var/spool/cups/.
490251
+	 */
490251
+	g = getgrnam("lp");
490251
+	if (g == NULL) {
490251
+		CUPS_SMB_ERROR("Failed to find user 'lp' - %s",
490251
+			       strerror(errno));
490251
+		return CUPS_BACKEND_FAILED;
490251
+	}
490251
+
490251
+	CUPS_SMB_DEBUG("Adding group 'lp' (%u)", g->gr_gid);
490251
+	groups[0] = g->gr_gid;
490251
+	rc = setgroups(sizeof(groups), groups);
490251
+	if (rc != 0) {
490251
+		CUPS_SMB_ERROR("Failed to set groups for 'lp' - %s",
490251
+			       strerror(errno));
490251
+		return CUPS_BACKEND_FAILED;
490251
+	}
490251
+
490251
 	CUPS_SMB_DEBUG("Switching to gid=%d", gid);
490251
 	rc = setgid(gid);
490251
 	if (rc != 0) {
490251
-- 
490251
2.21.0
490251
490251
490251
From d3ab97ba608b0c3000e733e3e56dd7da7bae617a Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Thu, 16 May 2019 13:41:02 +0200
490251
Subject: [PATCH 2/9] s3:smbspool: Print the principal we use to authenticate
490251
 with
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 42492d547661cb7a98c237b32d42ee93de35aba5)
490251
---
490251
 source3/client/smbspool.c | 11 +++++++++++
490251
 1 file changed, 11 insertions(+)
490251
490251
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
490251
index ecaaf3c3f22..98959bb677b 100644
490251
--- a/source3/client/smbspool.c
490251
+++ b/source3/client/smbspool.c
490251
@@ -612,6 +612,7 @@ static bool kerberos_ccache_is_valid(void) {
490251
 		return false;
490251
 	} else {
490251
 		krb5_principal default_princ = NULL;
490251
+		char *princ_name = NULL;
490251
 
490251
 		code = krb5_cc_get_principal(ctx,
490251
 					     ccache,
490251
@@ -621,6 +622,16 @@ static bool kerberos_ccache_is_valid(void) {
490251
 			krb5_free_context(ctx);
490251
 			return false;
490251
 		}
490251
+
490251
+		code = krb5_unparse_name(ctx,
490251
+					 default_princ,
490251
+					 &princ_name);
490251
+		if (code == 0) {
490251
+			fprintf(stderr,
490251
+				"DEBUG: Try to authenticate as %s\n",
490251
+				princ_name);
490251
+			krb5_free_unparsed_name(ctx, princ_name);
490251
+		}
490251
 		krb5_free_principal(ctx, default_princ);
490251
 	}
490251
 	krb5_cc_close(ctx, ccache);
490251
-- 
490251
2.21.0
490251
490251
490251
From b8588870940e282aa2d5f9d553771fcba91681c7 Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Thu, 16 May 2019 14:25:00 +0200
490251
Subject: [PATCH 3/9] s3:smbspool: Add debug for finding KRB5CCNAME
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 3632bfef25e471075886eb7aecddd4cc260db8ba)
490251
---
490251
 source3/client/smbspool_krb5_wrapper.c | 4 ++++
490251
 1 file changed, 4 insertions(+)
490251
490251
diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c
490251
index e6684fc0d0c..2cdcd372ec6 100644
490251
--- a/source3/client/smbspool_krb5_wrapper.c
490251
+++ b/source3/client/smbspool_krb5_wrapper.c
490251
@@ -219,10 +219,14 @@ int main(int argc, char *argv[])
490251
 	env = getenv("KRB5CCNAME");
490251
 	if (env != NULL && env[0] != 0) {
490251
 		snprintf(gen_cc, sizeof(gen_cc), "%s", env);
490251
+		CUPS_SMB_DEBUG("User already set KRB5CCNAME [%s] as ccache",
490251
+			       gen_cc);
490251
 
490251
 		goto create_env;
490251
 	}
490251
 
490251
+	CUPS_SMB_DEBUG("Trying to guess KRB5CCNAME (FILE, DIR, KEYRING)");
490251
+
490251
 	snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%d", uid);
490251
 
490251
 	rc = lstat(gen_cc, &sb);
490251
-- 
490251
2.21.0
490251
490251
490251
From 30feae8f20fb60999727cc4a6777b2823db46a64 Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Thu, 16 May 2019 17:10:57 +0200
490251
Subject: [PATCH 4/9] s3:smbspool: Use %u format specifier to print uid
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit be596ce3d2455bd49a8ebd311d8c764c37852858)
490251
---
490251
 source3/client/smbspool_krb5_wrapper.c | 6 +++---
490251
 1 file changed, 3 insertions(+), 3 deletions(-)
490251
490251
diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c
490251
index 2cdcd372ec6..3266b90ec1a 100644
490251
--- a/source3/client/smbspool_krb5_wrapper.c
490251
+++ b/source3/client/smbspool_krb5_wrapper.c
490251
@@ -227,13 +227,13 @@ int main(int argc, char *argv[])
490251
 
490251
 	CUPS_SMB_DEBUG("Trying to guess KRB5CCNAME (FILE, DIR, KEYRING)");
490251
 
490251
-	snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%d", uid);
490251
+	snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%u", uid);
490251
 
490251
 	rc = lstat(gen_cc, &sb);
490251
 	if (rc == 0) {
490251
-		snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%d", uid);
490251
+		snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%u", uid);
490251
 	} else {
490251
-		snprintf(gen_cc, sizeof(gen_cc), "/run/user/%d/krb5cc", uid);
490251
+		snprintf(gen_cc, sizeof(gen_cc), "/run/user/%u/krb5cc", uid);
490251
 
490251
 		rc = lstat(gen_cc, &sb);
490251
 		if (rc == 0 && S_ISDIR(sb.st_mode)) {
490251
-- 
490251
2.21.0
490251
490251
490251
From 98b782f300a899ad39fe17fa62ccbe4932e8cd29 Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Thu, 16 May 2019 17:40:43 +0200
490251
Subject: [PATCH 5/9] s3:smbspool: Fallback to default ccache if KRB5CCNAME is
490251
 not set
490251
490251
This could also support the new KCM credential cache storage.
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 6bbdf69e406916107400e2cabdbc831e2a2bbee3)
490251
---
490251
 source3/client/smbspool_krb5_wrapper.c | 79 ++++++++++++++++++--------
490251
 source3/wscript_build                  |  1 +
490251
 2 files changed, 55 insertions(+), 25 deletions(-)
490251
490251
diff --git a/source3/client/smbspool_krb5_wrapper.c b/source3/client/smbspool_krb5_wrapper.c
490251
index 3266b90ec1a..bff1df417e8 100644
490251
--- a/source3/client/smbspool_krb5_wrapper.c
490251
+++ b/source3/client/smbspool_krb5_wrapper.c
490251
@@ -21,6 +21,7 @@
490251
 
490251
 #include "includes.h"
490251
 #include "system/filesys.h"
490251
+#include "system/kerberos.h"
490251
 #include "system/passwd.h"
490251
 
490251
 #include <errno.h>
490251
@@ -68,6 +69,50 @@ static void cups_smb_debug(enum cups_smb_dbglvl_e lvl, const char *format, ...)
490251
 		buffer);
490251
 }
490251
 
490251
+static bool kerberos_get_default_ccache(char *ccache_buf, size_t len)
490251
+{
490251
+	krb5_context ctx;
490251
+	const char *ccache_name = NULL;
490251
+	char *full_ccache_name = NULL;
490251
+	krb5_ccache ccache = NULL;
490251
+	krb5_error_code code;
490251
+
490251
+	code = krb5_init_context(&ctx;;
490251
+	if (code != 0) {
490251
+		return false;
490251
+	}
490251
+
490251
+	ccache_name = krb5_cc_default_name(ctx);
490251
+	if (ccache_name == NULL) {
490251
+		krb5_free_context(ctx);
490251
+		return false;
490251
+	}
490251
+
490251
+	code = krb5_cc_resolve(ctx, ccache_name, &ccache);
490251
+	if (code != 0) {
490251
+		krb5_free_context(ctx);
490251
+		return false;
490251
+	}
490251
+
490251
+	code = krb5_cc_get_full_name(ctx, ccache, &full_ccache_name);
490251
+	krb5_cc_close(ctx, ccache);
490251
+	if (code != 0) {
490251
+		krb5_free_context(ctx);
490251
+		return false;
490251
+	}
490251
+
490251
+	snprintf(ccache_buf, len, "%s", full_ccache_name);
490251
+
490251
+#ifdef SAMBA4_USES_HEIMDAL
490251
+	free(full_ccache_name);
490251
+#else
490251
+	krb5_free_string(ctx, full_ccache_name);
490251
+#endif
490251
+	krb5_free_context(ctx);
490251
+
490251
+	return true;
490251
+}
490251
+
490251
 /*
490251
  * This is a helper binary to execute smbspool.
490251
  *
490251
@@ -84,7 +129,6 @@ int main(int argc, char *argv[])
490251
 	struct passwd *pwd;
490251
 	struct group *g = NULL;
490251
 	char gen_cc[PATH_MAX] = {0};
490251
-	struct stat sb;
490251
 	char *env = NULL;
490251
 	char auth_info_required[256] = {0};
490251
 	char device_uri[4096] = {0};
490251
@@ -92,6 +136,7 @@ int main(int argc, char *argv[])
490251
 	gid_t gid = (gid_t)-1;
490251
 	gid_t groups[1] = { (gid_t)-1 };
490251
 	unsigned long tmp;
490251
+	bool ok;
490251
 	int cmp;
490251
 	int rc;
490251
 
490251
@@ -225,32 +270,16 @@ int main(int argc, char *argv[])
490251
 		goto create_env;
490251
 	}
490251
 
490251
-	CUPS_SMB_DEBUG("Trying to guess KRB5CCNAME (FILE, DIR, KEYRING)");
490251
-
490251
-	snprintf(gen_cc, sizeof(gen_cc), "/tmp/krb5cc_%u", uid);
490251
-
490251
-	rc = lstat(gen_cc, &sb);
490251
-	if (rc == 0) {
490251
-		snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%u", uid);
490251
-	} else {
490251
-		snprintf(gen_cc, sizeof(gen_cc), "/run/user/%u/krb5cc", uid);
490251
-
490251
-		rc = lstat(gen_cc, &sb);
490251
-		if (rc == 0 && S_ISDIR(sb.st_mode)) {
490251
-			snprintf(gen_cc,
490251
-				 sizeof(gen_cc),
490251
-				 "DIR:/run/user/%d/krb5cc",
490251
-				 uid);
490251
-		} else {
490251
-#if defined(__linux__)
490251
-			snprintf(gen_cc,
490251
-				 sizeof(gen_cc),
490251
-				 "KEYRING:persistent:%d",
490251
-				 uid);
490251
-#endif
490251
-		}
490251
+	ok = kerberos_get_default_ccache(gen_cc, sizeof(gen_cc));
490251
+	if (ok) {
490251
+		CUPS_SMB_DEBUG("Use default KRB5CCNAME [%s]",
490251
+			       gen_cc);
490251
+		goto create_env;
490251
 	}
490251
 
490251
+	/* Fallback to a FILE ccache */
490251
+	snprintf(gen_cc, sizeof(gen_cc), "FILE:/tmp/krb5cc_%u", uid);
490251
+
490251
 create_env:
490251
 	/*
490251
 	 * Make sure we do not have LD_PRELOAD or other security relevant
490251
diff --git a/source3/wscript_build b/source3/wscript_build
490251
index 15c93e46bc3..694acbfa754 100644
490251
--- a/source3/wscript_build
490251
+++ b/source3/wscript_build
490251
@@ -1120,6 +1120,7 @@ bld.SAMBA3_BINARY('smbspool_krb5_wrapper',
490251
                  deps='''
490251
                       DYNCONFIG
490251
                       cups
490251
+                      krb5
490251
                       ''',
490251
                  install_path='${LIBEXECDIR}/samba',
490251
                  enabled=bld.CONFIG_SET('HAVE_CUPS'))
490251
-- 
490251
2.21.0
490251
490251
490251
From 0ffe2ecb356780264b157a03157875758431102f Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Mon, 13 May 2019 16:48:31 +0200
490251
Subject: [PATCH 6/9] s3:smbspool: Print the filename we failed to open
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 281274572bcc3125fe6026a01ef7bf7ef584a0dd)
490251
---
490251
 source3/client/smbspool.c | 4 +++-
490251
 1 file changed, 3 insertions(+), 1 deletion(-)
490251
490251
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
490251
index 98959bb677b..43f0cbc04e1 100644
490251
--- a/source3/client/smbspool.c
490251
+++ b/source3/client/smbspool.c
490251
@@ -223,7 +223,9 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 
490251
 		fp = fopen(print_file, "rb");
490251
 		if (fp == NULL) {
490251
-			perror("ERROR: Unable to open print file");
490251
+			fprintf(stderr,
490251
+				"ERROR: Unable to open print file: %s",
490251
+				print_file);
490251
 			goto done;
490251
 		}
490251
 
490251
-- 
490251
2.21.0
490251
490251
490251
From 9d662cda9def334de3a27cab7d77ab6c9deb3f16 Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Mon, 13 May 2019 18:54:02 +0200
490251
Subject: [PATCH 7/9] s3:smbspool: Always try to authenticate using Kerberos
490251
490251
If username and password is given, then fallback to NTLM. However try
490251
kinit first. Also we correctly handle NULL passwords in the meantime and
490251
this makes it easier to deal with issues.
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 3d719a1f85db8e423dc3a4116a2228961d5ac48d)
490251
---
490251
 source3/client/smbspool.c | 90 ++++++++++++++++++++++-----------------
490251
 1 file changed, 51 insertions(+), 39 deletions(-)
490251
490251
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
490251
index 43f0cbc04e1..f8e6a76ba11 100644
490251
--- a/source3/client/smbspool.c
490251
+++ b/source3/client/smbspool.c
490251
@@ -87,8 +87,8 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 	int             port;	/* Port number */
490251
 	char            uri[1024],	/* URI */
490251
 	               *sep,	/* Pointer to separator */
490251
-	               *tmp, *tmp2,	/* Temp pointers to do escaping */
490251
-	               *password;	/* Password */
490251
+	               *tmp, *tmp2;	/* Temp pointers to do escaping */
490251
+	const char     *password = NULL;	/* Password */
490251
 	char           *username,	/* Username */
490251
 	               *server,	/* Server name */
490251
 	               *printer;/* Printer name */
490251
@@ -292,8 +292,6 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 		if ((tmp2 = strchr_m(tmp, ':')) != NULL) {
490251
 			*tmp2++ = '\0';
490251
 			password = uri_unescape_alloc(tmp2);
490251
-		} else {
490251
-			password = empty_str;
490251
 		}
490251
 		username = uri_unescape_alloc(tmp);
490251
 	} else {
490251
@@ -301,14 +299,15 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 			username = empty_str;
490251
 		}
490251
 
490251
-		if ((password = getenv("AUTH_PASSWORD")) == NULL) {
490251
-			password = empty_str;
490251
+		env = getenv("AUTH_PASSWORD");
490251
+		if (env != NULL && strlen(env) > 0) {
490251
+			password = env;
490251
 		}
490251
 
490251
 		server = uri + 6;
490251
 	}
490251
 
490251
-	if (password != empty_str) {
490251
+	if (password != NULL) {
490251
 		auth_info_required = "username,password";
490251
 	}
490251
 
490251
@@ -513,6 +512,7 @@ smb_complete_connection(const char *myname,
490251
 	NTSTATUS        nt_status;
490251
 	struct cli_credentials *creds = NULL;
490251
 	bool use_kerberos = false;
490251
+	bool fallback_after_kerberos = false;
490251
 
490251
 	/* Start the SMB connection */
490251
 	*need_auth = false;
490251
@@ -523,27 +523,21 @@ smb_complete_connection(const char *myname,
490251
 		return NULL;
490251
 	}
490251
 
490251
-	/*
490251
-	 * We pretty much guarantee password must be valid or a pointer to a
490251
-	 * 0 char.
490251
-	 */
490251
-	if (!password) {
490251
-		*need_auth = true;
490251
-		return NULL;
490251
-	}
490251
-
490251
 	if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
490251
-		auth_info_required = "negotiate";
490251
 		use_kerberos = true;
490251
 	}
490251
 
490251
+	if (flags & CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS) {
490251
+		fallback_after_kerberos = true;
490251
+	}
490251
+
490251
 	creds = cli_session_creds_init(cli,
490251
 				       username,
490251
 				       workgroup,
490251
 				       NULL, /* realm */
490251
 				       password,
490251
 				       use_kerberos,
490251
-				       false, /* fallback_after_kerberos */
490251
+				       fallback_after_kerberos,
490251
 				       false, /* use_ccache */
490251
 				       false); /* password_is_nt_hash */
490251
 	if (creds == NULL) {
490251
@@ -659,6 +653,10 @@ smb_connect(const char *workgroup,	/* I - Workgroup */
490251
 	struct cli_state *cli;	/* New connection */
490251
 	char           *myname = NULL;	/* Client name */
490251
 	struct passwd  *pwd;
490251
+	int flags = CLI_FULL_CONNECTION_USE_KERBEROS;
490251
+	bool use_kerberos = false;
490251
+	const char *user = username;
490251
+	int cmp;
490251
 
490251
 	/*
490251
          * Get the names and addresses of the client and server...
490251
@@ -668,42 +666,56 @@ smb_connect(const char *workgroup,	/* I - Workgroup */
490251
 		return NULL;
490251
 	}
490251
 
490251
-	/*
490251
-	 * See if we have a username first.  This is for backwards compatible
490251
-	 * behavior with 3.0.14a
490251
-	 */
490251
 
490251
-	if (username == NULL || username[0] == '\0') {
490251
-		if (kerberos_ccache_is_valid()) {
490251
-			goto kerberos_auth;
490251
+	cmp = strcmp(auth_info_required, "negotiate");
490251
+	if (cmp == 0) {
490251
+		if (!kerberos_ccache_is_valid()) {
490251
+			return NULL;
490251
 		}
490251
+		user = jobusername;
490251
+
490251
+		use_kerberos = true;
490251
+		fprintf(stderr,
490251
+			"DEBUG: Try to connect using Kerberos ...\n");
490251
+	}
490251
+
490251
+	cmp = strcmp(auth_info_required, "username,password");
490251
+	if (cmp == 0) {
490251
+		if (username == NULL || username[0] == '\0') {
490251
+			return NULL;
490251
+		}
490251
+
490251
+		/* Fallback to NTLM */
490251
+		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
490251
+
490251
+		fprintf(stderr,
490251
+			"DEBUG: Try to connect using username/password ...\n");
490251
+	}
490251
+
490251
+	cmp = strcmp(auth_info_required, "none");
490251
+	if (cmp == 0) {
490251
+		fprintf(stderr,
490251
+			"DEBUG: This backend doesn't support none auth ...\n");
490251
+		return NULL;
490251
 	}
490251
 
490251
 	cli = smb_complete_connection(myname,
490251
 				      server,
490251
 				      port,
490251
-				      username,
490251
+				      user,
490251
 				      password,
490251
 				      workgroup,
490251
 				      share,
490251
-				      0,
490251
+				      flags,
490251
 				      need_auth);
490251
 	if (cli != NULL) {
490251
-		fputs("DEBUG: Connected with username/password...\n", stderr);
490251
+		fprintf(stderr, "DEBUG: SMB connection established.\n");
490251
 		return (cli);
490251
 	}
490251
 
490251
-kerberos_auth:
490251
-	/*
490251
-	 * Try to use the user kerberos credentials (if any) to authenticate
490251
-	 */
490251
-	cli = smb_complete_connection(myname, server, port, jobusername, "",
490251
-				      workgroup, share,
490251
-				 CLI_FULL_CONNECTION_USE_KERBEROS, need_auth);
490251
-
490251
-	if (cli) {
490251
-		fputs("DEBUG: Connected using Kerberos...\n", stderr);
490251
-		return (cli);
490251
+	if (!use_kerberos) {
490251
+		fprintf(stderr, "ERROR: SMB connection failed!\n");
490251
+		return NULL;
490251
 	}
490251
 
490251
 	/* give a chance for a passwordless NTLMSSP session setup */
490251
-- 
490251
2.21.0
490251
490251
490251
From 56f58726a1f3b98e64e9f6b27c275cc0044e2a9f Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Thu, 16 May 2019 18:24:32 +0200
490251
Subject: [PATCH 8/9] s3:smbspool: Add debug messages to
490251
 kerberos_ccache_is_valid()
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit 93acd880801524c5e621df7b5bf5ad650f93cec3)
490251
---
490251
 source3/client/smbspool.c | 7 +++++++
490251
 1 file changed, 7 insertions(+)
490251
490251
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
490251
index f8e6a76ba11..ed5837daa0d 100644
490251
--- a/source3/client/smbspool.c
490251
+++ b/source3/client/smbspool.c
490251
@@ -599,11 +599,15 @@ static bool kerberos_ccache_is_valid(void) {
490251
 
490251
 	ccache_name = krb5_cc_default_name(ctx);
490251
 	if (ccache_name == NULL) {
490251
+		DBG_ERR("Failed to get default ccache name\n");
490251
+		krb5_free_context(ctx);
490251
 		return false;
490251
 	}
490251
 
490251
 	code = krb5_cc_resolve(ctx, ccache_name, &ccache);
490251
 	if (code != 0) {
490251
+		DBG_ERR("Failed to resolve ccache name: %s\n",
490251
+			ccache_name);
490251
 		krb5_free_context(ctx);
490251
 		return false;
490251
 	} else {
490251
@@ -614,6 +618,9 @@ static bool kerberos_ccache_is_valid(void) {
490251
 					     ccache,
490251
 					     &default_princ);
490251
 		if (code != 0) {
490251
+			DBG_ERR("Failed to get default principal from "
490251
+				"ccache: %s\n",
490251
+				ccache_name);
490251
 			krb5_cc_close(ctx, ccache);
490251
 			krb5_free_context(ctx);
490251
 			return false;
490251
-- 
490251
2.21.0
490251
490251
490251
From cec536a0437b28e207cb69c318cb5769575d1761 Mon Sep 17 00:00:00 2001
490251
From: Andreas Schneider <asn@samba.org>
490251
Date: Tue, 14 May 2019 11:35:46 +0200
490251
Subject: [PATCH 9/9] s3:smbspool: Use NTSTATUS return codes
490251
490251
This allows us to simplify some code and return better errors.
490251
490251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13939
490251
490251
Signed-off-by: Andreas Schneider <asn@samba.org>
490251
Reviewed-by: Guenther Deschner <gd@samba.org>
490251
(cherry picked from commit d9af3dc02e98a3eb22441dfbdeddbaca0af078ea)
490251
---
490251
 source3/client/smbspool.c | 250 ++++++++++++++++++++++----------------
490251
 1 file changed, 145 insertions(+), 105 deletions(-)
490251
490251
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c
490251
index ed5837daa0d..1c09ca0826d 100644
490251
--- a/source3/client/smbspool.c
490251
+++ b/source3/client/smbspool.c
490251
@@ -60,12 +60,27 @@
490251
  * Local functions...
490251
  */
490251
 
490251
-static int      get_exit_code(struct cli_state * cli, NTSTATUS nt_status);
490251
+static int      get_exit_code(NTSTATUS nt_status);
490251
 static void     list_devices(void);
490251
-static struct cli_state *smb_complete_connection(const char *, const char *,
490251
-	int, const char *, const char *, const char *, const char *, int, bool *need_auth);
490251
-static struct cli_state *smb_connect(const char *, const char *, int, const
490251
-	char *, const char *, const char *, const char *, bool *need_auth);
490251
+static NTSTATUS
490251
+smb_complete_connection(struct cli_state **output_cli,
490251
+			const char *myname,
490251
+			const char *server,
490251
+			int port,
490251
+			const char *username,
490251
+			const char *password,
490251
+			const char *workgroup,
490251
+			const char *share,
490251
+			int flags);
490251
+static NTSTATUS
490251
+smb_connect(struct cli_state **output_cli,
490251
+	    const char *workgroup,
490251
+	    const char *server,
490251
+	    const int port,
490251
+	    const char *share,
490251
+	    const char *username,
490251
+	    const char *password,
490251
+	    const char *jobusername);
490251
 static int      smb_print(struct cli_state *, const char *, FILE *);
490251
 static char    *uri_unescape_alloc(const char *);
490251
 #if 0
490251
@@ -89,16 +104,15 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 	               *sep,	/* Pointer to separator */
490251
 	               *tmp, *tmp2;	/* Temp pointers to do escaping */
490251
 	const char     *password = NULL;	/* Password */
490251
-	char           *username,	/* Username */
490251
-	               *server,	/* Server name */
490251
+	const char     *username = NULL;	/* Username */
490251
+	char           *server,	/* Server name */
490251
 	               *printer;/* Printer name */
490251
 	const char     *workgroup;	/* Workgroup */
490251
 	FILE           *fp;	/* File to print */
490251
 	int             status = 1;	/* Status of LPD job */
490251
-	struct cli_state *cli;	/* SMB interface */
490251
-	char            empty_str[] = "";
490251
+	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
490251
+	struct cli_state *cli = NULL;	/* SMB interface */
490251
 	int             tries = 0;
490251
-	bool		need_auth = true;
490251
 	const char     *dev_uri = NULL;
490251
 	const char     *env = NULL;
490251
 	const char     *config_file = NULL;
490251
@@ -295,8 +309,9 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 		}
490251
 		username = uri_unescape_alloc(tmp);
490251
 	} else {
490251
-		if ((username = getenv("AUTH_USERNAME")) == NULL) {
490251
-			username = empty_str;
490251
+		env = getenv("AUTH_USERNAME");
490251
+		if (env != NULL && strlen(env) > 0) {
490251
+			username = env;
490251
 		}
490251
 
490251
 		env = getenv("AUTH_PASSWORD");
490251
@@ -368,27 +383,39 @@ main(int argc,			/* I - Number of command-line arguments */
490251
 	load_interfaces();
490251
 
490251
 	do {
490251
-		cli = smb_connect(workgroup,
490251
-				  server,
490251
-				  port,
490251
-				  printer,
490251
-				  username,
490251
-				  password,
490251
-				  print_user,
490251
-				  &need_auth);
490251
-		if (cli == NULL) {
490251
-			if (need_auth) {
490251
-				exit(2);
490251
+		nt_status = smb_connect(&cli,
490251
+					workgroup,
490251
+					server,
490251
+					port,
490251
+					printer,
490251
+					username,
490251
+					password,
490251
+					print_user);
490251
+		if (!NT_STATUS_IS_OK(nt_status)) {
490251
+			status = get_exit_code(nt_status);
490251
+			if (status == 2) {
490251
+				fprintf(stderr,
490251
+					"DEBUG: Unable to connect to CIFS "
490251
+					"host: %s",
490251
+					nt_errstr(nt_status));
490251
+				goto done;
490251
 			} else if (getenv("CLASS") == NULL) {
490251
-				fprintf(stderr, "ERROR: Unable to connect to CIFS host, will retry in 60 seconds...\n");
490251
+				fprintf(stderr,
490251
+					"ERROR: Unable to connect to CIFS "
490251
+					"host: %s. Will retry in 60 "
490251
+					"seconds...\n",
490251
+					nt_errstr(nt_status));
490251
 				sleep(60);
490251
 				tries++;
490251
 			} else {
490251
-				fprintf(stderr, "ERROR: Unable to connect to CIFS host, trying next printer...\n");
490251
+				fprintf(stderr,
490251
+					"ERROR: Unable to connect to CIFS "
490251
+					"host: %s. Trying next printer...\n",
490251
+					nt_errstr(nt_status));
490251
 				goto done;
490251
 			}
490251
 		}
490251
-	} while ((cli == NULL) && (tries < MAX_RETRY_CONNECT));
490251
+	} while (!NT_STATUS_IS_OK(nt_status) && (tries < MAX_RETRY_CONNECT));
490251
 
490251
 	if (cli == NULL) {
490251
 		fprintf(stderr, "ERROR: Unable to connect to CIFS host after (tried %d times)\n", tries);
490251
@@ -435,10 +462,9 @@ done:
490251
  */
490251
 
490251
 static int
490251
-get_exit_code(struct cli_state * cli,
490251
-	      NTSTATUS nt_status)
490251
+get_exit_code(NTSTATUS nt_status)
490251
 {
490251
-	int i;
490251
+	size_t i;
490251
 
490251
 	/* List of NTSTATUS errors that are considered
490251
 	 * authentication errors
490251
@@ -454,17 +480,16 @@ get_exit_code(struct cli_state * cli,
490251
 	};
490251
 
490251
 
490251
-	fprintf(stderr, "DEBUG: get_exit_code(cli=%p, nt_status=%s [%x])\n",
490251
-		cli, nt_errstr(nt_status), NT_STATUS_V(nt_status));
490251
+	fprintf(stderr,
490251
+		"DEBUG: get_exit_code(nt_status=%s [%x])\n",
490251
+		nt_errstr(nt_status), NT_STATUS_V(nt_status));
490251
 
490251
 	for (i = 0; i < ARRAY_SIZE(auth_errors); i++) {
490251
 		if (!NT_STATUS_EQUAL(nt_status, auth_errors[i])) {
490251
 			continue;
490251
 		}
490251
 
490251
-		if (cli) {
490251
-			fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
490251
-		}
490251
+		fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
490251
 
490251
 		/*
490251
 		 * 2 = authentication required...
490251
@@ -497,16 +522,16 @@ list_devices(void)
490251
 }
490251
 
490251
 
490251
-static struct cli_state *
490251
-smb_complete_connection(const char *myname,
490251
+static NTSTATUS
490251
+smb_complete_connection(struct cli_state **output_cli,
490251
+			const char *myname,
490251
 			const char *server,
490251
 			int port,
490251
 			const char *username,
490251
 			const char *password,
490251
 			const char *workgroup,
490251
 			const char *share,
490251
-			int flags,
490251
-			bool *need_auth)
490251
+			int flags)
490251
 {
490251
 	struct cli_state *cli;	/* New connection */
490251
 	NTSTATUS        nt_status;
490251
@@ -515,12 +540,11 @@ smb_complete_connection(const char *myname,
490251
 	bool fallback_after_kerberos = false;
490251
 
490251
 	/* Start the SMB connection */
490251
-	*need_auth = false;
490251
 	nt_status = cli_start_connection(&cli, myname, server, NULL, port,
490251
 					 SMB_SIGNING_DEFAULT, flags);
490251
 	if (!NT_STATUS_IS_OK(nt_status)) {
490251
 		fprintf(stderr, "ERROR: Connection failed: %s\n", nt_errstr(nt_status));
490251
-		return NULL;
490251
+		return nt_status;
490251
 	}
490251
 
490251
 	if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
490251
@@ -543,20 +567,16 @@ smb_complete_connection(const char *myname,
490251
 	if (creds == NULL) {
490251
 		fprintf(stderr, "ERROR: cli_session_creds_init failed\n");
490251
 		cli_shutdown(cli);
490251
-		return NULL;
490251
+		return NT_STATUS_NO_MEMORY;
490251
 	}
490251
 
490251
 	nt_status = cli_session_setup_creds(cli, creds);
490251
 	if (!NT_STATUS_IS_OK(nt_status)) {
490251
 		fprintf(stderr, "ERROR: Session setup failed: %s\n", nt_errstr(nt_status));
490251
 
490251
-		if (get_exit_code(cli, nt_status) == 2) {
490251
-			*need_auth = true;
490251
-		}
490251
-
490251
 		cli_shutdown(cli);
490251
 
490251
-		return NULL;
490251
+		return nt_status;
490251
 	}
490251
 
490251
 	nt_status = cli_tree_connect_creds(cli, share, "?????", creds);
490251
@@ -564,13 +584,9 @@ smb_complete_connection(const char *myname,
490251
 		fprintf(stderr, "ERROR: Tree connect failed (%s)\n",
490251
 			nt_errstr(nt_status));
490251
 
490251
-		if (get_exit_code(cli, nt_status) == 2) {
490251
-			*need_auth = true;
490251
-		}
490251
-
490251
 		cli_shutdown(cli);
490251
 
490251
-		return NULL;
490251
+		return nt_status;
490251
 	}
490251
 #if 0
490251
 	/* Need to work out how to specify this on the URL. */
490251
@@ -583,7 +599,8 @@ smb_complete_connection(const char *myname,
490251
 	}
490251
 #endif
490251
 
490251
-	return cli;
490251
+	*output_cli = cli;
490251
+	return NT_STATUS_OK;
490251
 }
490251
 
490251
 static bool kerberos_ccache_is_valid(void) {
490251
@@ -647,49 +664,48 @@ static bool kerberos_ccache_is_valid(void) {
490251
  * 'smb_connect()' - Return a connection to a server.
490251
  */
490251
 
490251
-static struct cli_state *	/* O - SMB connection */
490251
-smb_connect(const char *workgroup,	/* I - Workgroup */
490251
+static NTSTATUS
490251
+smb_connect(struct cli_state **output_cli,
490251
+	    const char *workgroup,	/* I - Workgroup */
490251
 	    const char *server,	/* I - Server */
490251
 	    const int port,	/* I - Port */
490251
 	    const char *share,	/* I - Printer */
490251
 	    const char *username,	/* I - Username */
490251
 	    const char *password,	/* I - Password */
490251
-	    const char *jobusername,	/* I - User who issued the print job */
490251
-	    bool *need_auth)
490251
-{				/* O - Need authentication? */
490251
-	struct cli_state *cli;	/* New connection */
490251
+	    const char *jobusername)	/* I - User who issued the print job */
490251
+{
490251
+	struct cli_state *cli = NULL;	/* New connection */
490251
 	char           *myname = NULL;	/* Client name */
490251
 	struct passwd  *pwd;
490251
 	int flags = CLI_FULL_CONNECTION_USE_KERBEROS;
490251
 	bool use_kerberos = false;
490251
 	const char *user = username;
490251
-	int cmp;
490251
+	NTSTATUS nt_status;
490251
 
490251
 	/*
490251
          * Get the names and addresses of the client and server...
490251
          */
490251
 	myname = get_myname(talloc_tos());
490251
 	if (!myname) {
490251
-		return NULL;
490251
+		return NT_STATUS_NO_MEMORY;
490251
 	}
490251
 
490251
 
490251
-	cmp = strcmp(auth_info_required, "negotiate");
490251
-	if (cmp == 0) {
490251
+	if (strcmp(auth_info_required, "negotiate") == 0) {
490251
 		if (!kerberos_ccache_is_valid()) {
490251
-			return NULL;
490251
+			fprintf(stderr,
490251
+				"ERROR: No valid Kerberos credential cache "
490251
+				"found!\n");
490251
+			return NT_STATUS_LOGON_FAILURE;
490251
 		}
490251
 		user = jobusername;
490251
 
490251
 		use_kerberos = true;
490251
 		fprintf(stderr,
490251
 			"DEBUG: Try to connect using Kerberos ...\n");
490251
-	}
490251
-
490251
-	cmp = strcmp(auth_info_required, "username,password");
490251
-	if (cmp == 0) {
490251
-		if (username == NULL || username[0] == '\0') {
490251
-			return NULL;
490251
+	} else if (strcmp(auth_info_required, "username,password") == 0) {
490251
+		if (username == NULL) {
490251
+			return NT_STATUS_INVALID_ACCOUNT_NAME;
490251
 		}
490251
 
490251
 		/* Fallback to NTLM */
490251
@@ -697,59 +713,83 @@ smb_connect(const char *workgroup,	/* I - Workgroup */
490251
 
490251
 		fprintf(stderr,
490251
 			"DEBUG: Try to connect using username/password ...\n");
490251
-	}
490251
+	} else {
490251
+		if (username != NULL) {
490251
+			flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
490251
+		} else if (kerberos_ccache_is_valid()) {
490251
+			auth_info_required = "negotiate";
490251
 
490251
-	cmp = strcmp(auth_info_required, "none");
490251
-	if (cmp == 0) {
490251
-		fprintf(stderr,
490251
-			"DEBUG: This backend doesn't support none auth ...\n");
490251
-		return NULL;
490251
+			user = jobusername;
490251
+			use_kerberos = true;
490251
+		} else {
490251
+			fprintf(stderr,
490251
+				"DEBUG: This backend requires credentials!\n");
490251
+			return NT_STATUS_ACCESS_DENIED;
490251
+		}
490251
 	}
490251
 
490251
-	cli = smb_complete_connection(myname,
490251
-				      server,
490251
-				      port,
490251
-				      user,
490251
-				      password,
490251
-				      workgroup,
490251
-				      share,
490251
-				      flags,
490251
-				      need_auth);
490251
-	if (cli != NULL) {
490251
+	nt_status = smb_complete_connection(&cli,
490251
+					    myname,
490251
+					    server,
490251
+					    port,
490251
+					    user,
490251
+					    password,
490251
+					    workgroup,
490251
+					    share,
490251
+					    flags);
490251
+	if (NT_STATUS_IS_OK(nt_status)) {
490251
 		fprintf(stderr, "DEBUG: SMB connection established.\n");
490251
-		return (cli);
490251
+
490251
+		*output_cli = cli;
490251
+		return NT_STATUS_OK;
490251
 	}
490251
 
490251
 	if (!use_kerberos) {
490251
 		fprintf(stderr, "ERROR: SMB connection failed!\n");
490251
-		return NULL;
490251
+		return nt_status;
490251
 	}
490251
 
490251
 	/* give a chance for a passwordless NTLMSSP session setup */
490251
 	pwd = getpwuid(geteuid());
490251
 	if (pwd == NULL) {
490251
-		return NULL;
490251
-	}
490251
-
490251
-	cli = smb_complete_connection(myname, server, port, pwd->pw_name, "",
490251
-				      workgroup, share, 0, need_auth);
490251
-
490251
-	if (cli) {
490251
+		return NT_STATUS_ACCESS_DENIED;
490251
+	}
490251
+
490251
+	nt_status = smb_complete_connection(&cli,
490251
+					    myname,
490251
+					    server,
490251
+					    port,
490251
+					    pwd->pw_name,
490251
+					    "",
490251
+					    workgroup,
490251
+					    share,
490251
+					    0);
490251
+	if (NT_STATUS_IS_OK(nt_status)) {
490251
 		fputs("DEBUG: Connected with NTLMSSP...\n", stderr);
490251
-		return (cli);
490251
+
490251
+		*output_cli = cli;
490251
+		return NT_STATUS_OK;
490251
 	}
490251
 
490251
 	/*
490251
          * last try. Use anonymous authentication
490251
          */
490251
 
490251
-	cli = smb_complete_connection(myname, server, port, "", "",
490251
-				      workgroup, share, 0, need_auth);
490251
-	/*
490251
-         * Return the new connection...
490251
-         */
490251
-
490251
-	return (cli);
490251
+	nt_status = smb_complete_connection(&cli,
490251
+					    myname,
490251
+					    server,
490251
+					    port,
490251
+					    "",
490251
+					    "",
490251
+					    workgroup,
490251
+					    share,
490251
+					    0);
490251
+	if (NT_STATUS_IS_OK(nt_status)) {
490251
+		*output_cli = cli;
490251
+		return NT_STATUS_OK;
490251
+	}
490251
+
490251
+	return nt_status;
490251
 }
490251
 
490251
 
490251
@@ -795,7 +835,7 @@ smb_print(struct cli_state * cli,	/* I - SMB connection */
490251
 	if (!NT_STATUS_IS_OK(nt_status)) {
490251
 		fprintf(stderr, "ERROR: %s opening remote spool %s\n",
490251
 			nt_errstr(nt_status), title);
490251
-		return get_exit_code(cli, nt_status);
490251
+		return get_exit_code(nt_status);
490251
 	}
490251
 
490251
 	/*
490251
@@ -813,7 +853,7 @@ smb_print(struct cli_state * cli,	/* I - SMB connection */
490251
 		status = cli_writeall(cli, fnum, 0, (uint8_t *)buffer,
490251
 				      tbytes, nbytes, NULL);
490251
 		if (!NT_STATUS_IS_OK(status)) {
490251
-			int ret = get_exit_code(cli, status);
490251
+			int ret = get_exit_code(status);
490251
 			fprintf(stderr, "ERROR: Error writing spool: %s\n",
490251
 				nt_errstr(status));
490251
 			fprintf(stderr, "DEBUG: Returning status %d...\n",
490251
@@ -829,7 +869,7 @@ smb_print(struct cli_state * cli,	/* I - SMB connection */
490251
 	if (!NT_STATUS_IS_OK(nt_status)) {
490251
 		fprintf(stderr, "ERROR: %s closing remote spool %s\n",
490251
 			nt_errstr(nt_status), title);
490251
-		return get_exit_code(cli, nt_status);
490251
+		return get_exit_code(nt_status);
490251
 	} else {
490251
 		return (0);
490251
 	}
490251
-- 
490251
2.21.0
490251