]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:utils: Use common command line parser for smbget
authorAndreas Schneider <asn@samba.org>
Thu, 30 Mar 2023 09:19:01 +0000 (11:19 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 5 Apr 2023 01:06:29 +0000 (01:06 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source3/script/tests/test_smbget.sh
source3/utils/smbget.c
source3/utils/wscript_build

index 7f0a1800b2344c4b284c2ff83ee18d281a98b4f1..bb9fde3838c0058b42d1020012721aad91bb815f 100755 (executable)
@@ -142,13 +142,16 @@ test_singlefile_smburl()
        return 0
 }
 
-test_singlefile_rcfile()
+test_singlefile_authfile()
 {
        clear_download_area
-       echo "user $USERNAME%$PASSWORD" >$TMPDIR/rcfile
-       $SMBGET --verbose --nonprompt --rcfile $TMPDIR/rcfile smb://$SERVER_IP/smbget/testfile
+       cat >"${TMPDIR}/authfile" << EOF
+username = $USERNAME
+password = $PASSWORD
+EOF
+       $SMBGET --verbose --authentication-file="${TMPDIR}/authfile" smb://$SERVER_IP/smbget/testfile
        rc=$?
-       rm -f $TMPDIR/rcfile
+       rm -f $TMPDIR/authfile
        if [ $rc -ne 0 ]; then
                echo 'ERROR: RC does not match, expected: 0'
                return 1
@@ -306,7 +309,7 @@ test_msdfs_link()
 {
        clear_download_area
 
-       ${SMBGET} --verbose "-U${USERNAME}%${PASSWORD}" \
+       ${SMBGET} --verbose "-U${SERVER}/${USERNAME}%${PASSWORD}" \
                "smb://${SERVER}/msdfs-share/deeppath/msdfs-src2/readable_file"
        ret=$?
        if [ ${ret} -ne 0 ]; then
@@ -393,7 +396,7 @@ testit "download single file with --update and UPN" test_singlefile_U_UPN ||
 testit "download single file with smb URL" test_singlefile_smburl ||
        failed=$(expr $failed + 1)
 
-testit "download single file with rcfile" test_singlefile_rcfile ||
+testit "download single file with authfile" test_singlefile_authfile ||
        failed=$(expr $failed + 1)
 
 testit "recursive download" test_recursive_U ||
index dca5ded4a9c1c944324d12de4ffc10a2bce7eee8..36b0fd3a8945eb8afcbe2133518b1a2c9bf0d128 100644 (file)
@@ -21,7 +21,7 @@
 #include "lib/cmdline/cmdline.h"
 #include "libsmbclient.h"
 #include "cmdline_contexts.h"
-#include "lib/param/param.h"
+#include "auth/credentials/credentials.h"
 
 static int columns = 0;
 
@@ -41,22 +41,14 @@ static off_t total_bytes = 0;
 #define SMB_DEFAULT_BLOCKSIZE  64000
 
 struct opt {
-       char *workgroup;
-       bool username_specified;
-       char *username;
-       bool password_specified;
-       char *password;
-
        char *outputfile;
        size_t blocksize;
 
-       bool nonprompt;
        bool quiet;
        bool dots;
        bool verbose;
        bool send_stdout;
        bool update;
-       int debuglevel;
        unsigned limit_rate;
 };
 static struct opt opt = { .blocksize = SMB_DEFAULT_BLOCKSIZE };
@@ -101,65 +93,76 @@ static void human_readable(off_t s, char *buffer, int l)
        }
 }
 
+/*
+ * Authentication callback for libsmbclient.
+ *
+ * The command line parser will take care asking for a password interactively!
+ */
 static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen,
                          char *un, int unlen, char *pw, int pwlen)
 {
-       static bool hasasked = false;
-       static char *savedwg;
-       static char *savedun;
-       static char *savedpw;
-
-       if (hasasked) {
-               strncpy(wg, savedwg, wglen - 1);
-               strncpy(un, savedun, unlen - 1);
-               strncpy(pw, savedpw, pwlen - 1);
-               return;
-       }
-       hasasked = true;
-
-       /*
-        * If no user has been specified un is initialized with the current
-        * username of the user who started smbget.
-        */
-       if (opt.username_specified) {
-               strncpy(un, opt.username, unlen - 1);
-       }
-
-       if (!opt.nonprompt && !opt.password_specified && pw[0] == '\0') {
-               char *prompt;
-               int rc;
-
-               rc = asprintf(&prompt,
-                             "Password for [%s] connecting to //%s/%s: ",
-                             un, srv, shr);
-               if (rc == -1) {
-                       return;
+       struct cli_credentials *creds = samba_cmdline_get_creds();
+       const char *username = NULL;
+       const char *password = NULL;
+       const char *domain = NULL;
+       enum smb_signing_setting signing_state =
+               cli_credentials_get_smb_signing(creds);
+       enum credentials_use_kerberos use_kerberos =
+               cli_credentials_get_kerberos_state(creds);
+       enum smb_encryption_setting encryption_state =
+               cli_credentials_get_smb_encryption(creds);
+       const char *use_signing = "auto";
+
+       if (encryption_state >= SMB_ENCRYPTION_DESIRED) {
+               signing_state = SMB_SIGNING_REQUIRED;
+       }
+
+       username = cli_credentials_get_username(creds);
+       if (username != NULL) {
+               strncpy(un, username, unlen - 1);
+       }
+
+       password = cli_credentials_get_password(creds);
+       if (password != NULL) {
+               strncpy(pw, password, pwlen-1);
+       }
+
+       domain = cli_credentials_get_domain(creds);
+       if (domain != NULL) {
+               strncpy(wg, domain, wglen-1);
+       }
+
+       switch (signing_state) {
+       case SMB_SIGNING_REQUIRED:
+               use_signing = "required";
+               break;
+       case SMB_SIGNING_DEFAULT:
+       case SMB_SIGNING_DESIRED:
+       case SMB_SIGNING_IF_REQUIRED:
+               use_signing = "yes";
+               break;
+       case SMB_SIGNING_OFF:
+               use_signing = "off";
+               break;
+       default:
+               use_signing = "auto";
+               break;
+       }
+
+       smbc_set_credentials(domain,
+                            username,
+                            password,
+                            use_kerberos > CRED_USE_KERBEROS_DISABLED,
+                            use_signing);
+
+       if (!opt.quiet && username != NULL) {
+               if (username[0] == '\0') {
+                       printf("Using guest user\n");
+               } else {
+                       printf("Using domain: %s, user: %s\n",
+                               domain,
+                               username);
                }
-               (void)samba_getpass(prompt, pw, pwlen, false, false);
-               free(prompt);
-       } else if (opt.password != NULL) {
-               strncpy(pw, opt.password, pwlen-1);
-       }
-
-       if (opt.workgroup != NULL) {
-               strncpy(wg, opt.workgroup, wglen-1);
-       }
-
-       /* save the values found for later */
-       savedwg = SMB_STRDUP(wg);
-       savedun = SMB_STRDUP(un);
-       savedpw = SMB_STRDUP(pw);
-
-       if (!opt.quiet) {
-               char *wgtmp, *usertmp;
-               wgtmp = SMB_STRNDUP(wg, wglen);
-               usertmp = SMB_STRNDUP(un, unlen);
-               printf("Using workgroup %s, %s%s\n",
-                      wgtmp,
-                      *usertmp ? "user " : "guest user",
-                      usertmp);
-               free(wgtmp);
-               free(usertmp);
        }
 }
 
@@ -736,122 +739,18 @@ static void signal_quit(int v)
        clean_exit();
 }
 
-static int readrcfile(const char *name, const struct poptOption long_options[])
-{
-       FILE *fd = fopen(name, "r");
-       int lineno = 0, i;
-       char var[101], val[101];
-       bool found;
-       int *intdata;
-       char **stringdata;
-       if (!fd) {
-               fprintf(stderr, "Can't open RC file %s\n", name);
-               return 1;
-       }
-
-       while (!feof(fd)) {
-               lineno++;
-               if (fscanf(fd, "%100s %100s\n", var, val) < 2) {
-                       fprintf(stderr,
-                               "Can't parse line %d of %s, ignoring.\n",
-                               lineno, name);
-                       continue;
-               }
-
-               found = false;
-
-               for (i = 0; long_options[i].argInfo; i++) {
-                       if (!long_options[i].longName) {
-                               continue;
-                       }
-                       if (strcmp(long_options[i].longName, var)) {
-                               continue;
-                       }
-                       if (!long_options[i].arg) {
-                               continue;
-                       }
-
-                       switch (long_options[i].argInfo) {
-                       case POPT_ARG_NONE:
-                               intdata = (int *)long_options[i].arg;
-                               if (!strcmp(val, "on")) {
-                                       *intdata = 1;
-                               } else if (!strcmp(val, "off")) {
-                                       *intdata = 0;
-                               } else {
-                                       fprintf(stderr, "Illegal value %s for "
-                                               "%s at line %d in %s\n",
-                                               val, var, lineno, name);
-                               }
-                               break;
-                       case POPT_ARG_INT:
-                               intdata = (int *)long_options[i].arg;
-                               *intdata = atoi(val);
-                               break;
-                       case POPT_ARG_STRING:
-                               stringdata = (char **)long_options[i].arg;
-                               *stringdata = SMB_STRDUP(val);
-                               if (long_options[i].shortName == 'U') {
-                                       char *p;
-                                       opt.username_specified = true;
-                                       p = strchr(*stringdata, '%');
-                                       if (p != NULL) {
-                                               *p = '\0';
-                                               opt.password = p + 1;
-                                               opt.password_specified = true;
-                                       }
-                               }
-                               break;
-                       default:
-                               fprintf(stderr, "Invalid variable %s at "
-                                       "line %d in %s\n",
-                                       var, lineno, name);
-                               break;
-                       }
-
-                       found = true;
-               }
-               if (!found) {
-                       fprintf(stderr,
-                               "Invalid variable %s at line %d in %s\n", var,
-                               lineno, name);
-               }
-       }
-
-       fclose(fd);
-       return 0;
-}
-
 int main(int argc, char **argv)
 {
        int c = 0;
        const char *file = NULL;
-       char *rcfile = NULL;
        bool smb_encrypt = false;
        int resume = 0, recursive = 0;
        TALLOC_CTX *frame = talloc_stackframe();
        bool ok = false;
-       char *p;
        const char **argv_const = discard_const_p(const char *, argv);
        struct poptOption long_options[] = {
                POPT_AUTOHELP
 
-               {
-                       .longName   = "workgroup",
-                       .shortName  = 'w',
-                       .argInfo    = POPT_ARG_STRING,
-                       .arg        = &opt.workgroup,
-                       .val        = 'w',
-                       .descrip    = "Workgroup/domain to use (optional)"
-               },
-               {
-                       .longName   = "user",
-                       .shortName  = 'U',
-                       .argInfo    = POPT_ARG_STRING,
-                       .arg        = &opt.username,
-                       .val        = 'U',
-                       .descrip    = "Username to use"
-               },
                {
                        .longName   = "guest",
                        .shortName  = 'a',
@@ -860,56 +759,38 @@ int main(int argc, char **argv)
                        .val        = 'a',
                        .descrip    = "Work as user guest"
                },
-
-               {
-                       .longName   = "nonprompt",
-                       .shortName  = 'n',
-                       .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'n',
-                       .descrip    = "Don't ask anything (non-interactive)"
-               },
-               {
-                       .longName   = "debuglevel",
-                       .shortName  = 'd',
-                       .argInfo    = POPT_ARG_INT,
-                       .arg        = &opt.debuglevel,
-                       .val        = 'd',
-                       .descrip    = "Debuglevel to use"
-               },
-
                {
                        .longName   = "encrypt",
                        .shortName  = 'e',
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'e',
+                       .arg        = &smb_encrypt,
+                       .val        = 1,
                        .descrip    = "Encrypt SMB transport"
                },
                {
                        .longName   = "resume",
                        .shortName  = 'r',
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'r',
+                       .arg        = &resume,
+                       .val        = 1,
                        .descrip    = "Automatically resume aborted files"
                },
                {
                        .longName   = "update",
                        .shortName  = 'u',
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'u',
+                       .arg        = &opt.update,
+                       .val        = 1,
                        .descrip    = "Download only when remote file is "
                                      "newer than local file or local file "
                                      "is missing"
                },
                {
                        .longName   = "recursive",
-                       .shortName  = 'R',
+                       .shortName  = 0,
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'R',
+                       .arg        = &recursive,
+                       .val        = true,
                        .descrip    = "Recursively download files"
                },
                {
@@ -931,69 +812,60 @@ int main(int argc, char **argv)
                },
                {
                        .longName   = "stdout",
-                       .shortName  = 'O',
+                       .shortName  = 0,
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'O',
+                       .arg        = &opt.send_stdout,
+                       .val        = true,
                        .descrip    = "Write data to stdout"
                },
                {
                        .longName   = "dots",
                        .shortName  = 'D',
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'D',
+                       .arg        = &opt.dots,
+                       .val        = 1,
                        .descrip    = "Show dots as progress indication"
                },
                {
                        .longName   = "quiet",
                        .shortName  = 'q',
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'q',
+                       .arg        = &opt.quiet,
+                       .val        = 1,
                        .descrip    = "Be quiet"
                },
                {
                        .longName   = "verbose",
                        .shortName  = 'v',
                        .argInfo    = POPT_ARG_NONE,
-                       .arg        = NULL,
-                       .val        = 'v',
+                       .arg        = &opt.verbose,
+                       .val        = 1,
                        .descrip    = "Be verbose"
                },
-               {
-                       .longName   = "rcfile",
-                       .shortName  = 'f',
-                       .argInfo    = POPT_ARG_STRING,
-                       .arg        = NULL,
-                       .val        = 'f',
-                       .descrip    = "Use specified rc file"
-               },
                {
                        .longName   = "limit-rate",
+                       .shortName  = 0,
                        .argInfo    = POPT_ARG_INT,
                        .arg        = &opt.limit_rate,
                        .val        = 'l',
                        .descrip    = "Limit download speed to this many KB/s"
                },
 
+               POPT_COMMON_SAMBA
+               POPT_COMMON_CONNECTION
+               POPT_COMMON_CREDENTIALS
+               POPT_LEGACY_S3
+               POPT_COMMON_VERSION
                POPT_TABLEEND
        };
        poptContext pc = NULL;
+       struct cli_credentials *creds = NULL;
 
        smb_init_locale();
 
-       /* only read rcfile if it exists */
-       if (asprintf(&rcfile, "%s/.smbgetrc", getenv("HOME")) == -1) {
-               ok = false;
-               goto done;
-       }
-       if (access(rcfile, F_OK) == 0) {
-               readrcfile(rcfile, long_options);
-       }
-       free(rcfile);
-
-       ok = lp_load_client(lp_default_path());
+       ok = samba_cmdline_init(frame,
+                               SAMBA_CMDLINE_CONFIG_CLIENT,
+                               false);
        if (!ok) {
                goto done;
        }
@@ -1004,73 +876,22 @@ int main(int argc, char **argv)
        signal(SIGINT, signal_quit);
        signal(SIGTERM, signal_quit);
 
-       pc = poptGetContext(argv[0], argc, argv_const, long_options, 0);
+       pc = samba_popt_get_context(getprogname(),
+                                   argc,
+                                   argv_const,
+                                   long_options,
+                                   0);
+       if (pc == NULL) {
+               ok = false;
+               goto done;
+       }
+
+       creds = samba_cmdline_get_creds();
 
-       while ((c = poptGetNextOpt(pc)) > 0) {
+       while ((c = poptGetNextOpt(pc)) != -1) {
                switch (c) {
-               case 'f':
-                       readrcfile(poptGetOptArg(pc), long_options);
-                       break;
                case 'a':
-                       opt.username_specified = true;
-                       opt.username = talloc_strdup(frame, "");
-                       opt.password_specified = true;
-                       opt.password = talloc_strdup(frame, "");
-                       break;
-               case 'e':
-                       smb_encrypt = true;
-                       break;
-               case 'U': {
-                       const char *separator = lp_winbind_separator();
-                       opt.username_specified = true;
-                       opt.username = talloc_strdup(frame, opt.username);
-                       p = strchr(opt.username,'%');
-                       if (p != NULL) {
-                               *p = '\0';
-                               opt.password = p + 1;
-                               opt.password_specified = true;
-                       }
-
-                       /* UPN support */
-                       p = strchr(opt.username, '@');
-                       if (p != NULL && opt.workgroup == NULL) {
-                               *p = '\0';
-                               opt.workgroup = p + 1;
-                       }
-
-                       /* Domain support */
-                       p = strchr(opt.username, separator[0]);
-                       if (p != NULL && opt.workgroup == NULL) {
-                               *p = '\0';
-                               opt.workgroup = opt.username;
-                               opt.username = p + 1;
-                       }
-
-                       break;
-               }
-               case 'n':
-                       opt.nonprompt = true;
-                       break;
-               case 'r':
-                       resume = true;
-                       break;
-               case 'u':
-                       opt.update = true;
-                       break;
-               case 'R':
-                       recursive = true;
-                       break;
-               case 'O':
-                       opt.send_stdout = true;
-                       break;
-               case 'D':
-                       opt.dots = true;
-                       break;
-               case 'q':
-                       opt.quiet = true;
-                       break;
-               case 'v':
-                       opt.verbose = true;
+                       cli_credentials_set_anonymous(creds);
                        break;
                case POPT_ERROR_BADOPT:
                        fprintf(stderr, "\nInvalid option %s: %s\n\n",
@@ -1111,7 +932,7 @@ int main(int argc, char **argv)
 
        samba_cmdline_burn(argc, argv);
 
-       if (smbc_init(get_auth_data, opt.debuglevel) < 0) {
+       if (smbc_init(get_auth_data, debuglevel_get()) < 0) {
                fprintf(stderr, "Unable to initialize libsmbclient\n");
                ok = true;
                goto done;
index 49f97af8c7c3f0ad7be32e6de9748405157c3a49..172457f4b57c3e8723072ace0d384a38e2c50edb 100644 (file)
@@ -63,7 +63,7 @@ bld.SAMBA3_BINARY('smbget',
                  source='smbget.c',
                  deps='''
                  talloc
-                 cmdline
+                 CMDLINE_S3
                  smbclient''')
 
 bld.SAMBA3_BINARY('nmblookup',