diff options
author | Andreas Schneider <asn@samba.org> | 2019-05-14 11:35:46 +0200 |
---|---|---|
committer | Andreas Schneider <asn@cryptomilk.org> | 2019-05-23 09:41:17 +0000 |
commit | d9af3dc02e98a3eb22441dfbdeddbaca0af078ea (patch) | |
tree | a23d4b694ac0551da7ca7723fabf15c85e6c6547 /source3/client | |
parent | 93acd880801524c5e621df7b5bf5ad650f93cec3 (diff) | |
download | samba-d9af3dc02e98a3eb22441dfbdeddbaca0af078ea.tar.gz |
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 <asn@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
Diffstat (limited to 'source3/client')
-rw-r--r-- | source3/client/smbspool.c | 250 |
1 files changed, 145 insertions, 105 deletions
diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c index 79e210dd12e..ad988eb0df9 100644 --- a/source3/client/smbspool.c +++ b/source3/client/smbspool.c @@ -61,12 +61,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 @@ -90,16 +105,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; @@ -296,8 +310,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"); @@ -369,27 +384,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); @@ -436,10 +463,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 @@ -455,17 +481,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... @@ -498,16 +523,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; @@ -516,12 +541,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) { @@ -544,20 +568,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); @@ -565,13 +585,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. */ @@ -584,7 +600,8 @@ smb_complete_connection(const char *myname, } #endif - return cli; + *output_cli = cli; + return NT_STATUS_OK; } static bool kerberos_ccache_is_valid(void) { @@ -650,49 +667,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 */ @@ -700,59 +716,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; } @@ -798,7 +838,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); } /* @@ -816,7 +856,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", @@ -832,7 +872,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); } |