Markus Schaber wrote:
> Julian Foad wrote:
>>   "specify a password ARG (insecure: on many systems,
>>   other users can read the command-line arguments)"
> 
> I fully agree with your concerns about vague warnings. But in my eyes,
> it is also important to point out the alternatives, so that the users
> have an easy way to use them.

and GBG wrote (to me):

> It still leaves a question --- why?  And ppl might think, oh, not in linux,
> I should be safe (remembering that svn is cross platform).
> How about something like: (insecure on any OS that hosts other users) ?

We want to say, very briefly (the command-line help isn't the place for a full 
explanation):

  - that using this option might be insecure;

  - enough of a clue about how/why so user can make an informed choice or know 
what questions to ask if they want to look for more information.

In the interests of getting something in place, I have just committed the 
following help text in r1612230:

  --password ARG           : specify a password ARG (caution: on many operating
                             systems, other users will be able to see this)

(I used "caution:" as I think "insecure" is  too context-dependent and 
judgemental.)
Improvements are welcome, of course.


Still TODO:
  * write a fuller explanation in The Book
  * add a '--password-file' option
  * (maybe) blank out the --password argument after reading it, when possible

I don't plan to work on The Book, or on blanking; contributions are welcome.


I looked at committing a password-file option. A version based on Markus 
Schaber's recent patches is attached. (It's his patch, minus the 
password-env-var option, plus a test suite fix.)

Looking at how the 'rsync' program describes its '--password-file' option:$ man 
rsync

  --password-file
      This option allows you to provide a password in a file for accessing
      an rsync daemon.  The file must not be world readable.  It should
      contain just the password as the first line of the file (all other
      lines are ignored).

Two things we might want to do, that rsync does:

1. Read only the first line of the file, up to but not including a newline. 
"Not including the newline" is the important part here, I think: the patch, as 
is, assumes that any newline in the file is part of the password, which in a 
typical case then fails to work.

(The first thing I tried was "echo my-password > foo; svn --password-file=foo 
...".)

2. It says the file must not be world-readable. That seems a sensible 
precaution. I think we should do that too, on operating systems 
where that makes sense.


Thoughts?

- Julian
Add a new global option '--password-file'.

TODO (noted from reading about rsync's --password-file option):
  * Read only the first line of the file, up to but not including a newline.
  * The file must not be world readable.

Patch by: schabi
          me

* subversion/svn/svn.c
  (svn_cl__longopt_t, svn_cl__global_options): Add opt_auth_password_file.
  (svn_cl__options): Add the '--password-file' option.
  (sub_main): Add opt_auth_password_file. Check for multiple use of stdin.

* subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
  Update the expected output accordingly.
--This line, and those below, will be ignored--

Index: subversion/svn/svn.c
===================================================================
--- subversion/svn/svn.c        (revision 1612230)
+++ subversion/svn/svn.c        (working copy)
@@ -65,12 +65,13 @@
 
 /* Add an identifier here for long options that don't have a short
    option. Options that have both long and short options should just
    use the short option letter as identifier.  */
 typedef enum svn_cl__longopt_t {
   opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID,
+  opt_auth_password_file,
   opt_auth_username,
   opt_autoprops,
   opt_changelist,
   opt_config_dir,
   opt_config_options,
   /* diff options */
@@ -192,12 +193,14 @@ const apr_getopt_option_t svn_cl__option
   {"show-updates",  'u', 0, N_("display update information")},
   {"username",      opt_auth_username, 1, N_("specify a username ARG")},
   {"password",      opt_auth_password, 1,
                     N_("specify a password ARG (caution: on many operating\n"
                        "                             "
                        "systems, other users will be able to see this)")},
+  {"password-file", opt_auth_password_file, 1,
+                    N_("read a password from the specified file ARG")},
   {"extensions",    'x', 1,
                     N_("Specify differencing options for external diff or\n"
                        "                             "
                        "internal diff or blame. Default: '-u'. Options are\n"
                        "                             "
                        "separated by spaces. Internal diff and blame take:\n"
@@ -423,13 +426,14 @@ const apr_getopt_option_t svn_cl__option
 
 /* Options that apply to all commands.  (While not every command may
    currently require authentication or be interactive, allowing every
    command to take these arguments allows scripts to just pass them
    willy-nilly to every invocation of 'svn') . */
 const int svn_cl__global_options[] =
-{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive,
+{ opt_auth_username, opt_auth_password, opt_auth_password_file,
+  opt_no_auth_cache, opt_non_interactive,
   opt_force_interactive, opt_trust_server_cert, opt_config_dir,
   opt_config_options, 0
 };
 
 /* Options for giving a log message.  (Some of these also have other uses.)
  */
@@ -2018,22 +2022,37 @@ sub_main(int *exit_code, int argc, const
         break;
       case 'F':
         /* We read the raw file content here.  We will convert it to UTF-8
          * later (if it's a log/lock message or an svn:* prop value),
          * according to the value of the '--encoding' option. */
         SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+        if (strcmp(utf8_opt_arg, "-") == 0)
+          {
+            if (reading_file_from_stdin)
+              return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                      _("stdin ('-') must not be specified "
+                                        "more than once"));
+            reading_file_from_stdin = TRUE;
+          }
         SVN_ERR(svn_stringbuf_from_file2(&(opt_state.filedata),
                                          utf8_opt_arg, pool));
-        reading_file_from_stdin = (strcmp(utf8_opt_arg, "-") == 0);
         dash_F_arg = utf8_opt_arg;
         break;
       case opt_targets:
         {
           svn_stringbuf_t *buffer, *buffer_utf8;
 
           SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+          if (strcmp(utf8_opt_arg, "-") == 0)
+            {
+              if (reading_file_from_stdin)
+                return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                        _("stdin ('-') must not be specified "
+                                          "more than once"));
+              reading_file_from_stdin = TRUE;
+            }
           SVN_ERR(svn_stringbuf_from_file2(&buffer, utf8_opt_arg, pool));
           SVN_ERR(svn_utf_stringbuf_to_utf8(&buffer_utf8, buffer, pool));
           opt_state.targets = svn_cstring_split(buffer_utf8->data, "\n\r",
                                                 TRUE, pool);
         }
         break;
@@ -2097,12 +2116,30 @@ sub_main(int *exit_code, int argc, const
                                         opt_arg, pool));
         break;
       case opt_auth_password:
         SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password,
                                         opt_arg, pool));
         break;
+      case opt_auth_password_file:
+        {
+          svn_stringbuf_t *buffer, *buffer_utf8;
+
+          SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool));
+          if (strcmp(utf8_opt_arg, "-") == 0)
+            {
+              if (reading_file_from_stdin)
+                return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+                                        _("stdin ('-') must not be specified "
+                                          "more than once"));
+              reading_file_from_stdin = TRUE;
+            }
+          SVN_ERR(svn_stringbuf_from_file2(&buffer, utf8_opt_arg, pool));
+          SVN_ERR(svn_utf_stringbuf_to_utf8(&buffer_utf8, buffer, pool));
+          opt_state.auth_password = buffer_utf8->data;
+        }
+        break;
       case opt_encoding:
         opt_state.encoding = apr_pstrdup(pool, opt_arg);
         break;
       case opt_xml:
         opt_state.xml = TRUE;
         break;
Index: subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
===================================================================
--- subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout       
(revision 1612234)
+++ subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout       
(working copy)
@@ -114,12 +114,13 @@ Valid options:
   --search-and ARG         : combine ARG with the previous search pattern
 
 Global options:
   --username ARG           : specify a username ARG
   --password ARG           : specify a password ARG (caution: on many operating
                              systems, other users will be able to see this)
+  --password-file ARG      : read a password from the specified file ARG
   --no-auth-cache          : do not cache authentication tokens
   --non-interactive        : do no interactive prompting (default is to prompt
                              only if standard input is a terminal device)
   --force-interactive      : do interactive prompting even if standard input
                              is not a terminal device
   --trust-server-cert      : accept SSL server certificates from unknown
@@ -198,12 +199,13 @@ Valid options:
                              (shorthand: 'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l')
 
 Global options:
   --username ARG           : specify a username ARG
   --password ARG           : specify a password ARG (caution: on many operating
                              systems, other users will be able to see this)
+  --password-file ARG      : read a password from the specified file ARG
   --no-auth-cache          : do not cache authentication tokens
   --non-interactive        : do no interactive prompting (default is to prompt
                              only if standard input is a terminal device)
   --force-interactive      : do interactive prompting even if standard input
                              is not a terminal device
   --trust-server-cert      : accept SSL server certificates from unknown

Reply via email to