2 * prompt.c -- ask the user for authentication information.
4 * ====================================================================
5 * Licensed to the Apache Software Foundation (ASF) under one
6 * or more contributor license agreements. See the NOTICE file
7 * distributed with this work for additional information
8 * regarding copyright ownership. The ASF licenses this file
9 * to you under the Apache License, Version 2.0 (the
10 * "License"); you may not use this file except in compliance
11 * with the License. You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing,
16 * software distributed under the License is distributed on an
17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 * KIND, either express or implied. See the License for the
19 * specific language governing permissions and limitations
21 * ====================================================================
24 /* ==================================================================== */
32 #include <apr_portable.h>
34 #include "svn_cmdline.h"
35 #include "svn_ctype.h"
36 #include "svn_string.h"
38 #include "svn_error.h"
41 #include "private/svn_cmdline_private.h"
42 #include "svn_private_config.h"
46 #elif defined(HAVE_TERMIOS_H)
53 /* Descriptor of an open terminal */
54 typedef struct terminal_handle_t terminal_handle_t;
55 struct terminal_handle_t
57 apr_file_t *infd; /* input file handle */
58 apr_file_t *outfd; /* output file handle */
59 svn_boolean_t noecho; /* terminal echo was turned off */
60 svn_boolean_t close_handles; /* close handles when closing the terminal */
61 apr_pool_t *pool; /* pool associated with the file handles */
64 svn_boolean_t restore_state; /* terminal state was changed */
65 apr_os_file_t osinfd; /* OS-specific handle for infd */
66 struct termios attr; /* saved terminal attributes */
70 /* Initialize safe state of terminal_handle_t. */
72 terminal_handle_init(terminal_handle_t *terminal,
73 apr_file_t *infd, apr_file_t *outfd,
74 svn_boolean_t noecho, svn_boolean_t close_handles,
77 memset(terminal, 0, sizeof(*terminal));
78 terminal->infd = infd;
79 terminal->outfd = outfd;
80 terminal->noecho = noecho;
81 terminal->close_handles = close_handles;
82 terminal->pool = pool;
86 * Common pool cleanup handler for terminal_handle_t. Closes TERMINAL.
87 * If CLOSE_HANDLES is TRUE, close the terminal file handles.
88 * If RESTORE_STATE is TRUE, restores the TERMIOS flags of the terminal.
91 terminal_cleanup_handler(terminal_handle_t *terminal,
92 svn_boolean_t close_handles,
93 svn_boolean_t restore_state)
95 apr_status_t status = APR_SUCCESS;
98 /* Restore terminal state flags. */
99 if (restore_state && terminal->restore_state)
100 tcsetattr(terminal->osinfd, TCSANOW, &terminal->attr);
103 /* Close terminal handles. */
104 if (close_handles && terminal->close_handles)
106 apr_file_t *const infd = terminal->infd;
107 apr_file_t *const outfd = terminal->outfd;
111 terminal->infd = NULL;
112 status = apr_file_close(infd);
115 if (!status && outfd && outfd != infd)
117 terminal->outfd = NULL;
118 status = apr_file_close(terminal->outfd);
124 /* Normal pool cleanup for a terminal. */
125 static apr_status_t terminal_plain_cleanup(void *baton)
127 return terminal_cleanup_handler(baton, FALSE, TRUE);
130 /* Child pool cleanup for a terminal -- does not restore echo state. */
131 static apr_status_t terminal_child_cleanup(void *baton)
133 return terminal_cleanup_handler(baton, FALSE, FALSE);
136 /* Explicitly close the terminal, removing its cleanup handlers. */
138 terminal_close(terminal_handle_t *terminal)
142 /* apr_pool_cleanup_kill() removes both normal and child cleanup */
143 apr_pool_cleanup_kill(terminal->pool, terminal, terminal_plain_cleanup);
145 status = terminal_cleanup_handler(terminal, TRUE, TRUE);
147 return svn_error_create(status, NULL, _("Can't close terminal"));
151 /* Allocate and open *TERMINAL. If NOECHO is TRUE, try to turn off
152 terminal echo. Use POOL for all allocations.*/
154 terminal_open(terminal_handle_t **terminal, svn_boolean_t noecho,
160 /* On Windows, we'll use the console API directly if the process has
161 a console attached; otherwise we'll just use stdin and stderr. */
162 const HANDLE conin = CreateFileW(L"CONIN$", GENERIC_READ,
163 FILE_SHARE_READ | FILE_SHARE_WRITE,
165 FILE_ATTRIBUTE_NORMAL, NULL);
166 *terminal = apr_palloc(pool, sizeof(terminal_handle_t));
167 if (conin != INVALID_HANDLE_VALUE)
169 /* The process has a console. */
171 terminal_handle_init(*terminal, NULL, NULL, noecho, FALSE, NULL);
175 /* Without evidence to the contrary, we'll assume this is *nix and
176 try to open /dev/tty. If that fails, we'll use stdin for input
177 and stderr for prompting. */
179 status = apr_file_open(&tmpfd, "/dev/tty",
180 APR_READ | APR_WRITE,
181 APR_OS_DEFAULT, pool);
182 *terminal = apr_palloc(pool, sizeof(terminal_handle_t));
185 /* We have a terminal handle that we can use for input and output. */
186 terminal_handle_init(*terminal, tmpfd, tmpfd, FALSE, TRUE, pool);
191 /* There is no terminal. Sigh. */
195 status = apr_file_open_stdin(&infd, pool);
197 return svn_error_wrap_apr(status, _("Can't open stdin"));
198 status = apr_file_open_stderr(&outfd, pool);
200 return svn_error_wrap_apr(status, _("Can't open stderr"));
201 terminal_handle_init(*terminal, infd, outfd, FALSE, FALSE, pool);
204 #ifdef HAVE_TERMIOS_H
205 /* Set terminal state */
206 if (0 == apr_os_file_get(&(*terminal)->osinfd, (*terminal)->infd))
208 if (0 == tcgetattr((*terminal)->osinfd, &(*terminal)->attr))
210 struct termios attr = (*terminal)->attr;
211 /* Turn off signal handling and canonical input mode */
212 attr.c_lflag &= ~(ISIG | ICANON);
213 attr.c_cc[VMIN] = 1; /* Read one byte at a time */
214 attr.c_cc[VTIME] = 0; /* No timeout, wait indefinitely */
215 attr.c_lflag &= ~(ECHO); /* Turn off echo */
216 if (0 == tcsetattr((*terminal)->osinfd, TCSAFLUSH, &attr))
218 (*terminal)->noecho = noecho;
219 (*terminal)->restore_state = TRUE;
223 #endif /* HAVE_TERMIOS_H */
225 /* Register pool cleanup to close handles and restore echo state. */
226 apr_pool_cleanup_register((*terminal)->pool, *terminal,
227 terminal_plain_cleanup,
228 terminal_child_cleanup);
232 /* Write a null-terminated STRING to TERMINAL.
233 Use POOL for allocations related to converting STRING from UTF-8. */
235 terminal_puts(const char *string, terminal_handle_t *terminal,
240 const char *converted;
242 err = svn_cmdline_cstring_from_utf8(&converted, string, pool);
245 svn_error_clear(err);
246 converted = svn_cmdline_cstring_from_utf8_fuzzy(string, pool);
250 if (!terminal->outfd)
252 /* See terminal_open; we're using Console I/O. */
258 status = apr_file_write_full(terminal->outfd, converted,
259 strlen(converted), NULL);
261 status = apr_file_flush(terminal->outfd);
263 return svn_error_wrap_apr(status, _("Can't write to terminal"));
267 /* These codes can be returned from terminal_getc instead of a character. */
268 #define TERMINAL_NONE 0x80000 /* no character read, retry */
269 #define TERMINAL_DEL (TERMINAL_NONE + 1) /* the input was a deleteion */
270 #define TERMINAL_EOL (TERMINAL_NONE + 2) /* end of input/end of line */
271 #define TERMINAL_EOF (TERMINAL_NONE + 3) /* end of file during input */
273 /* Helper for terminal_getc: writes CH to OUTFD as a control char. */
276 echo_control_char(char ch, apr_file_t *outfd)
278 if (svn_ctype_iscntrl(ch))
280 const char substitute = (ch < 32? '@' + ch : '?');
281 apr_file_putc('^', outfd);
282 apr_file_putc(substitute, outfd);
284 else if (svn_ctype_isprint(ch))
286 /* Pass printable characters unchanged. */
287 apr_file_putc(ch, outfd);
291 /* Everything else is strange. */
292 apr_file_putc('^', outfd);
293 apr_file_putc('!', outfd);
298 /* Read one character or control code from TERMINAL, returning it in CODE.
299 if CAN_ERASE and the input was a deletion, emit codes to erase the
300 last character displayed on the terminal.
301 Use POOL for all allocations. */
303 terminal_getc(int *code, terminal_handle_t *terminal,
304 svn_boolean_t can_erase, apr_pool_t *pool)
306 const svn_boolean_t echo = !terminal->noecho;
307 apr_status_t status = APR_SUCCESS;
313 /* See terminal_open; we're using Console I/O. */
315 /* The following was hoisted from APR's getpass for Windows. */
316 int concode = _getch();
319 case '\r': /* end-of-line */
320 *code = TERMINAL_EOL;
325 case EOF: /* end-of-file */
326 case 26: /* Ctrl+Z */
327 *code = TERMINAL_EOF;
329 _cputs((concode == EOF ? "[EOF]\r\n" : "^Z\r\n"));
332 case 3: /* Ctrl+C, Ctrl+Break */
333 /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */
336 return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
338 case 0: /* Function code prefix */
340 concode = (concode << 4) | _getch();
341 /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */
342 if (concode == 0xE53 || concode == 0xE4B
343 || concode == 0x053 || concode == 0x04B)
345 *code = TERMINAL_DEL;
351 *code = TERMINAL_NONE;
358 *code = TERMINAL_DEL;
364 if (!apr_iscntrl(concode))
366 *code = (int)(unsigned char)concode;
367 _putch(echo ? concode : '*');
371 *code = TERMINAL_NONE;
377 #elif defined(HAVE_TERMIOS_H)
378 if (terminal->restore_state)
380 /* We're using a bytewise-immediate termios input */
381 const struct termios *const attr = &terminal->attr;
383 status = apr_file_getc(&ch, terminal->infd);
385 return svn_error_wrap_apr(status, _("Can't read from terminal"));
387 if (ch == attr->c_cc[VINTR] || ch == attr->c_cc[VQUIT])
390 echo_control_char(ch, terminal->outfd);
391 return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
393 else if (ch == '\r' || ch == '\n' || ch == attr->c_cc[VEOL])
396 *code = TERMINAL_EOL;
397 apr_file_putc('\n', terminal->outfd);
399 else if (ch == '\b' || ch == attr->c_cc[VERASE])
402 *code = TERMINAL_DEL;
405 apr_file_putc('\b', terminal->outfd);
406 apr_file_putc(' ', terminal->outfd);
407 apr_file_putc('\b', terminal->outfd);
410 else if (ch == attr->c_cc[VEOF])
413 *code = TERMINAL_EOF;
414 echo_control_char(ch, terminal->outfd);
416 else if (ch == attr->c_cc[VSUSP])
419 *code = TERMINAL_NONE;
422 else if (!apr_iscntrl(ch))
424 /* Normal character */
425 *code = (int)(unsigned char)ch;
426 apr_file_putc((echo ? ch : '*'), terminal->outfd);
430 /* Ignored character */
431 *code = TERMINAL_NONE;
432 apr_file_putc('\a', terminal->outfd);
436 #endif /* HAVE_TERMIOS_H */
438 /* Fall back to plain stream-based I/O. */
440 /* Wait for input on termin. This code is based on
441 apr_wait_for_io_or_timeout().
442 Note that this will return an EINTR on a signal. */
444 apr_pollfd_t pollset;
447 pollset.desc_type = APR_POLL_FILE;
448 pollset.desc.f = terminal->infd;
450 pollset.reqevents = APR_POLLIN;
452 status = apr_poll(&pollset, 1, &n, -1);
454 if (n == 1 && pollset.rtnevents & APR_POLLIN)
455 status = APR_SUCCESS;
460 status = apr_file_getc(&ch, terminal->infd);
461 if (APR_STATUS_IS_EINTR(status))
463 *code = TERMINAL_NONE;
466 else if (APR_STATUS_IS_EOF(status))
468 *code = TERMINAL_EOF;
472 return svn_error_wrap_apr(status, _("Can't read from terminal"));
474 *code = (int)(unsigned char)ch;
479 /* Set @a *result to the result of prompting the user with @a
480 * prompt_msg. Use @ *pb to get the cancel_func and cancel_baton.
481 * Do not call the cancel_func if @a *pb is NULL.
482 * Allocate @a *result in @a pool.
484 * If @a hide is true, then try to avoid displaying the user's input.
487 prompt(const char **result,
488 const char *prompt_msg,
490 svn_cmdline_prompt_baton2_t *pb,
493 /* XXX: If this functions ever starts using members of *pb
494 * which were not included in svn_cmdline_prompt_baton_t,
495 * we need to update svn_cmdline_prompt_user2 and its callers. */
497 svn_boolean_t saw_first_half_of_eol = FALSE;
498 svn_stringbuf_t *strbuf = svn_stringbuf_create_empty(pool);
499 terminal_handle_t *terminal;
503 SVN_ERR(terminal_open(&terminal, hide, pool));
504 SVN_ERR(terminal_puts(prompt_msg, terminal, pool));
508 SVN_ERR(terminal_getc(&code, terminal, (strbuf->len > 0), pool));
510 /* Check for cancellation after a character has been read, some
511 input processing modes may eat ^C and we'll only notice a
512 cancellation signal after characters have been read --
513 sometimes even after a newline. */
515 SVN_ERR(pb->cancel_func(pb->cancel_baton));
520 /* Nothing useful happened; retry. */
524 /* Delete the last input character. terminal_getc takes care
525 of erasing the feedback from the terminal, if applicable. */
526 svn_stringbuf_chop(strbuf, 1);
530 /* End-of-line means end of input. Trick the EOL-detection code
531 below to stop reading. */
532 saw_first_half_of_eol = TRUE;
533 c = APR_EOL_STR[1]; /* Could be \0 but still stops reading. */
537 return svn_error_create(
539 terminal_close(terminal),
540 _("End of file while reading from terminal"));
543 /* Convert the returned code back to the character. */
547 if (saw_first_half_of_eol)
549 if (c == APR_EOL_STR[1])
552 saw_first_half_of_eol = FALSE;
554 else if (c == APR_EOL_STR[0])
556 /* GCC might complain here: "warning: will never be executed"
557 * That's fine. This is a compile-time check for "\r\n\0" */
558 if (sizeof(APR_EOL_STR) == 3)
560 saw_first_half_of_eol = TRUE;
563 else if (sizeof(APR_EOL_STR) == 2)
566 /* ### APR_EOL_STR holds more than two chars? Who
567 ever heard of such a thing? */
568 SVN_ERR_MALFUNCTION();
571 svn_stringbuf_appendbyte(strbuf, c);
574 if (terminal->noecho)
576 /* If terminal echo was turned off, make sure future output
577 to the terminal starts on a new line, as expected. */
578 SVN_ERR(terminal_puts(APR_EOL_STR, terminal, pool));
580 SVN_ERR(terminal_close(terminal));
582 return svn_cmdline_cstring_to_utf8(result, strbuf->data, pool);
587 /** Prompt functions for auth providers. **/
589 /* Helper function for auth provider prompters: mention the
590 * authentication @a realm on stderr, in a manner appropriate for
591 * preceding a prompt; or if @a realm is null, then do nothing.
594 maybe_print_realm(const char *realm, apr_pool_t *pool)
598 terminal_handle_t *terminal;
599 SVN_ERR(terminal_open(&terminal, FALSE, pool));
600 SVN_ERR(terminal_puts(
602 _("Authentication realm: %s\n"), realm),
604 SVN_ERR(terminal_close(terminal));
611 /* This implements 'svn_auth_simple_prompt_func_t'. */
613 svn_cmdline_auth_simple_prompt(svn_auth_cred_simple_t **cred_p,
616 const char *username,
617 svn_boolean_t may_save,
620 svn_auth_cred_simple_t *ret = apr_pcalloc(pool, sizeof(*ret));
621 const char *pass_prompt;
622 svn_cmdline_prompt_baton2_t *pb = baton;
624 SVN_ERR(maybe_print_realm(realm, pool));
627 ret->username = apr_pstrdup(pool, username);
629 SVN_ERR(prompt(&(ret->username), _("Username: "), FALSE, pb, pool));
631 pass_prompt = apr_psprintf(pool, _("Password for '%s': "), ret->username);
632 SVN_ERR(prompt(&(ret->password), pass_prompt, TRUE, pb, pool));
633 ret->may_save = may_save;
639 /* This implements 'svn_auth_username_prompt_func_t'. */
641 svn_cmdline_auth_username_prompt(svn_auth_cred_username_t **cred_p,
644 svn_boolean_t may_save,
647 svn_auth_cred_username_t *ret = apr_pcalloc(pool, sizeof(*ret));
648 svn_cmdline_prompt_baton2_t *pb = baton;
650 SVN_ERR(maybe_print_realm(realm, pool));
652 SVN_ERR(prompt(&(ret->username), _("Username: "), FALSE, pb, pool));
653 ret->may_save = may_save;
659 /* This implements 'svn_auth_ssl_server_trust_prompt_func_t'. */
661 svn_cmdline_auth_ssl_server_trust_prompt
662 (svn_auth_cred_ssl_server_trust_t **cred_p,
665 apr_uint32_t failures,
666 const svn_auth_ssl_server_cert_info_t *cert_info,
667 svn_boolean_t may_save,
671 svn_stringbuf_t *msg;
672 svn_cmdline_prompt_baton2_t *pb = baton;
673 svn_stringbuf_t *buf = svn_stringbuf_createf
674 (pool, _("Error validating server certificate for '%s':\n"), realm);
676 if (failures & SVN_AUTH_SSL_UNKNOWNCA)
678 svn_stringbuf_appendcstr
680 _(" - The certificate is not issued by a trusted authority. Use the\n"
681 " fingerprint to validate the certificate manually!\n"));
684 if (failures & SVN_AUTH_SSL_CNMISMATCH)
686 svn_stringbuf_appendcstr
687 (buf, _(" - The certificate hostname does not match.\n"));
690 if (failures & SVN_AUTH_SSL_NOTYETVALID)
692 svn_stringbuf_appendcstr
693 (buf, _(" - The certificate is not yet valid.\n"));
696 if (failures & SVN_AUTH_SSL_EXPIRED)
698 svn_stringbuf_appendcstr
699 (buf, _(" - The certificate has expired.\n"));
702 if (failures & SVN_AUTH_SSL_OTHER)
704 svn_stringbuf_appendcstr
705 (buf, _(" - The certificate has an unknown error.\n"));
708 msg = svn_stringbuf_createf
710 _("Certificate information:\n"
712 " - Valid: from %s until %s\n"
714 " - Fingerprint: %s\n"),
716 cert_info->valid_from,
717 cert_info->valid_until,
718 cert_info->issuer_dname,
719 cert_info->fingerprint);
720 svn_stringbuf_appendstr(buf, msg);
724 svn_stringbuf_appendcstr
725 (buf, _("(R)eject, accept (t)emporarily or accept (p)ermanently? "));
729 svn_stringbuf_appendcstr(buf, _("(R)eject or accept (t)emporarily? "));
731 SVN_ERR(prompt(&choice, buf->data, FALSE, pb, pool));
733 if (choice[0] == 't' || choice[0] == 'T')
735 *cred_p = apr_pcalloc(pool, sizeof(**cred_p));
736 (*cred_p)->may_save = FALSE;
737 (*cred_p)->accepted_failures = failures;
739 else if (may_save && (choice[0] == 'p' || choice[0] == 'P'))
741 *cred_p = apr_pcalloc(pool, sizeof(**cred_p));
742 (*cred_p)->may_save = TRUE;
743 (*cred_p)->accepted_failures = failures;
754 /* This implements 'svn_auth_ssl_client_cert_prompt_func_t'. */
756 svn_cmdline_auth_ssl_client_cert_prompt
757 (svn_auth_cred_ssl_client_cert_t **cred_p,
760 svn_boolean_t may_save,
763 svn_auth_cred_ssl_client_cert_t *cred = NULL;
764 const char *cert_file = NULL;
765 const char *abs_cert_file = NULL;
766 svn_cmdline_prompt_baton2_t *pb = baton;
768 SVN_ERR(maybe_print_realm(realm, pool));
769 SVN_ERR(prompt(&cert_file, _("Client certificate filename: "),
771 SVN_ERR(svn_dirent_get_absolute(&abs_cert_file, cert_file, pool));
773 cred = apr_palloc(pool, sizeof(*cred));
774 cred->cert_file = abs_cert_file;
775 cred->may_save = may_save;
782 /* This implements 'svn_auth_ssl_client_cert_pw_prompt_func_t'. */
784 svn_cmdline_auth_ssl_client_cert_pw_prompt
785 (svn_auth_cred_ssl_client_cert_pw_t **cred_p,
788 svn_boolean_t may_save,
791 svn_auth_cred_ssl_client_cert_pw_t *cred = NULL;
793 const char *text = apr_psprintf(pool, _("Passphrase for '%s': "), realm);
794 svn_cmdline_prompt_baton2_t *pb = baton;
796 SVN_ERR(prompt(&result, text, TRUE, pb, pool));
798 cred = apr_pcalloc(pool, sizeof(*cred));
799 cred->password = result;
800 cred->may_save = may_save;
806 /* This is a helper for plaintext prompt functions. */
808 plaintext_prompt_helper(svn_boolean_t *may_save_plaintext,
809 const char *realmstring,
810 const char *prompt_string,
811 const char *prompt_text,
815 const char *answer = NULL;
816 svn_boolean_t answered = FALSE;
817 svn_cmdline_prompt_baton2_t *pb = baton;
818 const char *config_path = NULL;
819 terminal_handle_t *terminal;
822 SVN_ERR(svn_config_get_user_config_path(&config_path, pb->config_dir,
823 SVN_CONFIG_CATEGORY_SERVERS, pool));
825 SVN_ERR(terminal_open(&terminal, FALSE, pool));
826 SVN_ERR(terminal_puts(apr_psprintf(pool, prompt_text,
827 realmstring, config_path),
829 SVN_ERR(terminal_close(terminal));
833 svn_error_t *err = prompt(&answer, prompt_string, FALSE, pb, pool);
836 if (err->apr_err == SVN_ERR_CANCELLED)
838 svn_error_clear(err);
839 *may_save_plaintext = FALSE;
845 if (apr_strnatcasecmp(answer, _("yes")) == 0 ||
846 apr_strnatcasecmp(answer, _("y")) == 0)
848 *may_save_plaintext = TRUE;
851 else if (apr_strnatcasecmp(answer, _("no")) == 0 ||
852 apr_strnatcasecmp(answer, _("n")) == 0)
854 *may_save_plaintext = FALSE;
858 prompt_string = _("Please type 'yes' or 'no': ");
865 /* This implements 'svn_auth_plaintext_prompt_func_t'. */
867 svn_cmdline_auth_plaintext_prompt(svn_boolean_t *may_save_plaintext,
868 const char *realmstring,
872 const char *prompt_string = _("Store password unencrypted (yes/no)? ");
873 const char *prompt_text =
874 _("\n-----------------------------------------------------------------------"
875 "\nATTENTION! Your password for authentication realm:\n"
879 "can only be stored to disk unencrypted! You are advised to configure\n"
880 "your system so that Subversion can store passwords encrypted, if\n"
881 "possible. See the documentation for details.\n"
883 "You can avoid future appearances of this warning by setting the value\n"
884 "of the 'store-plaintext-passwords' option to either 'yes' or 'no' in\n"
886 "-----------------------------------------------------------------------\n"
889 return plaintext_prompt_helper(may_save_plaintext, realmstring,
890 prompt_string, prompt_text, baton,
894 /* This implements 'svn_auth_plaintext_passphrase_prompt_func_t'. */
896 svn_cmdline_auth_plaintext_passphrase_prompt(svn_boolean_t *may_save_plaintext,
897 const char *realmstring,
901 const char *prompt_string = _("Store passphrase unencrypted (yes/no)? ");
902 const char *prompt_text =
903 _("\n-----------------------------------------------------------------------\n"
904 "ATTENTION! Your passphrase for client certificate:\n"
908 "can only be stored to disk unencrypted! You are advised to configure\n"
909 "your system so that Subversion can store passphrase encrypted, if\n"
910 "possible. See the documentation for details.\n"
912 "You can avoid future appearances of this warning by setting the value\n"
913 "of the 'store-ssl-client-cert-pp-plaintext' option to either 'yes' or\n"
915 "-----------------------------------------------------------------------\n"
918 return plaintext_prompt_helper(may_save_plaintext, realmstring,
919 prompt_string, prompt_text, baton,
924 /** Generic prompting. **/
927 svn_cmdline_prompt_user2(const char **result,
928 const char *prompt_str,
929 svn_cmdline_prompt_baton_t *baton,
932 /* XXX: We know prompt doesn't use the new members
933 * of svn_cmdline_prompt_baton2_t. */
934 return prompt(result, prompt_str, FALSE /* don't hide input */,
935 (svn_cmdline_prompt_baton2_t *)baton, pool);
938 /* This implements 'svn_auth_gnome_keyring_unlock_prompt_func_t'. */
940 svn_cmdline__auth_gnome_keyring_unlock_prompt(char **keyring_password,
941 const char *keyring_name,
945 const char *password;
946 const char *pass_prompt;
947 svn_cmdline_prompt_baton2_t *pb = baton;
949 pass_prompt = apr_psprintf(pool, _("Password for '%s' GNOME keyring: "),
951 SVN_ERR(prompt(&password, pass_prompt, TRUE, pb, pool));
952 *keyring_password = apr_pstrdup(pool, password);