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