2006-04-23 18:26:03 +00:00
|
|
|
/*
|
|
|
|
* cmdline.c - command-line parsing shared between many of the
|
|
|
|
* PuTTY applications
|
|
|
|
*/
|
|
|
|
|
2002-09-02 13:32:37 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "putty.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Some command-line parameters need to be saved up until after
|
|
|
|
* we've loaded the saved session which will form the basis of our
|
|
|
|
* eventual running configuration. For this we use the macro
|
|
|
|
* SAVEABLE, which notices if the `need_save' parameter is set and
|
|
|
|
* saves the parameter and value on a list.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2002-09-02 13:32:37 +00:00
|
|
|
* We also assign priorities to saved parameters, just to slightly
|
|
|
|
* ameliorate silly ordering problems. For example, if you specify
|
|
|
|
* a saved session to load, it will be loaded _before_ all your
|
|
|
|
* local modifications such as -L are evaluated; and if you specify
|
|
|
|
* a protocol and a port, the protocol is set up first so that the
|
|
|
|
* port can override its choice of port number.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2003-03-22 10:36:28 +00:00
|
|
|
* (In fact -load is not saved at all, since in at least Plink the
|
|
|
|
* processing of further command-line options depends on whether or
|
|
|
|
* not the loaded session contained a hostname. So it must be
|
|
|
|
* executed immediately.)
|
2002-09-02 13:32:37 +00:00
|
|
|
*/
|
|
|
|
|
2003-03-22 10:36:28 +00:00
|
|
|
#define NPRIORITIES 2
|
2002-09-02 13:32:37 +00:00
|
|
|
|
|
|
|
struct cmdline_saved_param {
|
|
|
|
char *p, *value;
|
|
|
|
};
|
|
|
|
struct cmdline_saved_param_set {
|
|
|
|
struct cmdline_saved_param *params;
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
size_t nsaved, savesize;
|
2002-09-02 13:32:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* C guarantees this structure will be initialised to all zero at
|
|
|
|
* program start, which is exactly what we want.
|
|
|
|
*/
|
|
|
|
static struct cmdline_saved_param_set saves[NPRIORITIES];
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
static void cmdline_save_param(const char *p, const char *value, int pri)
|
2002-09-02 13:32:37 +00:00
|
|
|
{
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
sgrowarray(saves[pri].params, saves[pri].savesize, saves[pri].nsaved);
|
2015-05-15 10:15:42 +00:00
|
|
|
saves[pri].params[saves[pri].nsaved].p = dupstr(p);
|
|
|
|
saves[pri].params[saves[pri].nsaved].value = dupstr(value);
|
2002-09-02 13:32:37 +00:00
|
|
|
saves[pri].nsaved++;
|
|
|
|
}
|
|
|
|
|
2010-01-17 16:20:45 +00:00
|
|
|
static char *cmdline_password = NULL;
|
|
|
|
|
2003-12-19 12:44:46 +00:00
|
|
|
void cmdline_cleanup(void)
|
|
|
|
{
|
|
|
|
int pri;
|
|
|
|
|
2010-01-17 16:20:45 +00:00
|
|
|
if (cmdline_password) {
|
2019-09-08 19:29:00 +00:00
|
|
|
smemclr(cmdline_password, strlen(cmdline_password));
|
|
|
|
sfree(cmdline_password);
|
|
|
|
cmdline_password = NULL;
|
2010-01-17 16:20:45 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
|
2010-01-17 16:20:45 +00:00
|
|
|
for (pri = 0; pri < NPRIORITIES; pri++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
sfree(saves[pri].params);
|
|
|
|
saves[pri].params = NULL;
|
|
|
|
saves[pri].savesize = 0;
|
|
|
|
saves[pri].nsaved = 0;
|
2010-01-17 16:20:45 +00:00
|
|
|
}
|
2003-12-19 12:44:46 +00:00
|
|
|
}
|
|
|
|
|
2002-09-02 13:32:37 +00:00
|
|
|
#define SAVEABLE(pri) do { \
|
|
|
|
if (need_save) { cmdline_save_param(p, value, pri); return ret; } \
|
|
|
|
} while (0)
|
|
|
|
|
2005-10-30 20:24:09 +00:00
|
|
|
/*
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
* Similar interface to seat_get_userpass_input(), except that here a
|
2022-10-23 11:31:29 +00:00
|
|
|
* SPR(K)_INCOMPLETE return means that we aren't capable of processing
|
|
|
|
* the prompt and someone else should do it.
|
2005-10-30 20:24:09 +00:00
|
|
|
*/
|
Fix command-line password handling in Restart Session.
When the user provides a password on the PuTTY command line, via -pw
or -pwfile, the flag 'tried_once' inside cmdline_get_passwd_input() is
intended to arrange that we only try sending that password once, and
after we've sent it, we don't try again.
But this plays badly with the 'Restart Session' operation. If the
connection is lost and then restarted at user request, we _do_ want to
send that password again!
So this commit moves that static variable out into a small state
structure held by the client of cmdline_get_passwd_input. Each client
can decide how to manage that state itself.
Clients that support 'Restart Session' - i.e. just GUI PuTTY itself -
will initialise the state at the same time as instantiating the
backend, so that every time the session is restarted, we return
to (correctly) believing that we _haven't_ yet tried the password
provided on the command line.
But clients that don't support 'Restart Session' - i.e. Plink and file
transfer tools - can do the same thing that cmdline.c was doing
before: just keep the state in a static variable.
This also means that the GUI login tools will now retain the
command-line password in memory, whereas previously they'd have wiped
it out once it was used. But the other tools will still wipe and free
the password, because I've also added a 'bool restartable' flag to
cmdline_get_passwd_input to let it know when it _is_ allowed to do
that.
In the GUI tools, I don't see any way to get round that, because if
the session is restarted you _have_ to still have the password to use
again. (And you can't infer that that will never happen from the
CONF_close_on_exit setting, because that too could be changed in
mid-session.) On the other hand, I think it's not all that worrying,
because the use of either -pw or -pwfile means that a persistent copy
of your password is *already* stored somewhere, so another one isn't
too big a stretch.
(Due to the change of -pw policy in 0.77, the effect of this bug was
that an attempt to reconnect in a session set up this way would lead
to "Configured password was not accepted". In 0.76, the failure mode
was different: PuTTY would interactively prompt for the password,
having wiped it out of memory after it was used the first time round.)
2022-05-18 12:04:56 +00:00
|
|
|
SeatPromptResult cmdline_get_passwd_input(
|
|
|
|
prompts_t *p, cmdline_get_passwd_input_state *state, bool restartable)
|
2015-05-15 10:15:42 +00:00
|
|
|
{
|
2005-10-30 20:24:09 +00:00
|
|
|
/*
|
|
|
|
* We only handle prompts which don't echo (which we assume to be
|
|
|
|
* passwords), and (currently) we only cope with a password prompt
|
2022-10-23 13:00:07 +00:00
|
|
|
* that comes in a prompt-set on its own. Also, we don't use a
|
|
|
|
* command-line password for any kind of prompt which is destined
|
|
|
|
* for local use rather than to be sent to the server: the idea is
|
|
|
|
* to pre-fill _passwords_, not private-key passphrases (for which
|
|
|
|
* there are better alternatives available).
|
2005-10-30 20:24:09 +00:00
|
|
|
*/
|
2022-10-23 13:00:07 +00:00
|
|
|
if (p->n_prompts != 1 || p->prompts[0]->echo || !p->to_server) {
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
return SPR_INCOMPLETE;
|
2005-10-30 20:24:09 +00:00
|
|
|
}
|
2002-09-02 13:32:37 +00:00
|
|
|
|
2005-10-30 20:24:09 +00:00
|
|
|
/*
|
|
|
|
* If we've tried once, return utter failure (no more passwords left
|
|
|
|
* to try).
|
|
|
|
*/
|
Fix command-line password handling in Restart Session.
When the user provides a password on the PuTTY command line, via -pw
or -pwfile, the flag 'tried_once' inside cmdline_get_passwd_input() is
intended to arrange that we only try sending that password once, and
after we've sent it, we don't try again.
But this plays badly with the 'Restart Session' operation. If the
connection is lost and then restarted at user request, we _do_ want to
send that password again!
So this commit moves that static variable out into a small state
structure held by the client of cmdline_get_passwd_input. Each client
can decide how to manage that state itself.
Clients that support 'Restart Session' - i.e. just GUI PuTTY itself -
will initialise the state at the same time as instantiating the
backend, so that every time the session is restarted, we return
to (correctly) believing that we _haven't_ yet tried the password
provided on the command line.
But clients that don't support 'Restart Session' - i.e. Plink and file
transfer tools - can do the same thing that cmdline.c was doing
before: just keep the state in a static variable.
This also means that the GUI login tools will now retain the
command-line password in memory, whereas previously they'd have wiped
it out once it was used. But the other tools will still wipe and free
the password, because I've also added a 'bool restartable' flag to
cmdline_get_passwd_input to let it know when it _is_ allowed to do
that.
In the GUI tools, I don't see any way to get round that, because if
the session is restarted you _have_ to still have the password to use
again. (And you can't infer that that will never happen from the
CONF_close_on_exit setting, because that too could be changed in
mid-session.) On the other hand, I think it's not all that worrying,
because the use of either -pw or -pwfile means that a persistent copy
of your password is *already* stored somewhere, so another one isn't
too big a stretch.
(Due to the change of -pw policy in 0.77, the effect of this bug was
that an attempt to reconnect in a session set up this way would lead
to "Configured password was not accepted". In 0.76, the failure mode
was different: PuTTY would interactively prompt for the password,
having wiped it out of memory after it was used the first time round.)
2022-05-18 12:04:56 +00:00
|
|
|
if (state->tried)
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
return SPR_SW_ABORT("Configured password was not accepted");
|
2005-10-30 20:24:09 +00:00
|
|
|
|
Fix error handling when command-line password fails.
In cmdline_get_passwd_input(), there's a boolean 'tried_once' which is
set the first time the function returns the password set by -pw or
-pwfile. The idea, as clearly commented in the code, was that if
cmdline_get_password_input asks for that password _again_, we return
failure, as if the user had refused to make a second attempt.
But that wasn't actually what happened, because when we set tried_once
to true, we also set cmdline_password to NULL, which causes the second
call to the function to behave as if no password was ever provided at
all. So after the -pw password failed, we'd fall back to asking
interactively.
This change moves the check of cmdline_password to after the check of
tried_once, restoring the originally intended behaviour: password
authentication will now _only_ be done via the pre-set password, if
there is one.
This seems like an xkcd #1172 kind of change: now that it's been wrong
for a while, _someone_ has probably found the unintended behaviour
useful, and started relying on it. So it may become necessary to add
an option to set the behaviour either way. But for the moment, let's
try it the way I originally intended it.
2021-12-28 15:15:53 +00:00
|
|
|
/*
|
|
|
|
* If we never had a password available in the first place, we
|
|
|
|
* can't do anything in any case. (But we delay this test until
|
Fix command-line password handling in Restart Session.
When the user provides a password on the PuTTY command line, via -pw
or -pwfile, the flag 'tried_once' inside cmdline_get_passwd_input() is
intended to arrange that we only try sending that password once, and
after we've sent it, we don't try again.
But this plays badly with the 'Restart Session' operation. If the
connection is lost and then restarted at user request, we _do_ want to
send that password again!
So this commit moves that static variable out into a small state
structure held by the client of cmdline_get_passwd_input. Each client
can decide how to manage that state itself.
Clients that support 'Restart Session' - i.e. just GUI PuTTY itself -
will initialise the state at the same time as instantiating the
backend, so that every time the session is restarted, we return
to (correctly) believing that we _haven't_ yet tried the password
provided on the command line.
But clients that don't support 'Restart Session' - i.e. Plink and file
transfer tools - can do the same thing that cmdline.c was doing
before: just keep the state in a static variable.
This also means that the GUI login tools will now retain the
command-line password in memory, whereas previously they'd have wiped
it out once it was used. But the other tools will still wipe and free
the password, because I've also added a 'bool restartable' flag to
cmdline_get_passwd_input to let it know when it _is_ allowed to do
that.
In the GUI tools, I don't see any way to get round that, because if
the session is restarted you _have_ to still have the password to use
again. (And you can't infer that that will never happen from the
CONF_close_on_exit setting, because that too could be changed in
mid-session.) On the other hand, I think it's not all that worrying,
because the use of either -pw or -pwfile means that a persistent copy
of your password is *already* stored somewhere, so another one isn't
too big a stretch.
(Due to the change of -pw policy in 0.77, the effect of this bug was
that an attempt to reconnect in a session set up this way would lead
to "Configured password was not accepted". In 0.76, the failure mode
was different: PuTTY would interactively prompt for the password,
having wiped it out of memory after it was used the first time round.)
2022-05-18 12:04:56 +00:00
|
|
|
* after trying once, so that even if we free cmdline_password
|
|
|
|
* below, we'll still remember that we _used_ to have one.)
|
Fix error handling when command-line password fails.
In cmdline_get_passwd_input(), there's a boolean 'tried_once' which is
set the first time the function returns the password set by -pw or
-pwfile. The idea, as clearly commented in the code, was that if
cmdline_get_password_input asks for that password _again_, we return
failure, as if the user had refused to make a second attempt.
But that wasn't actually what happened, because when we set tried_once
to true, we also set cmdline_password to NULL, which causes the second
call to the function to behave as if no password was ever provided at
all. So after the -pw password failed, we'd fall back to asking
interactively.
This change moves the check of cmdline_password to after the check of
tried_once, restoring the originally intended behaviour: password
authentication will now _only_ be done via the pre-set password, if
there is one.
This seems like an xkcd #1172 kind of change: now that it's been wrong
for a while, _someone_ has probably found the unintended behaviour
useful, and started relying on it. So it may become necessary to add
an option to set the behaviour either way. But for the moment, let's
try it the way I originally intended it.
2021-12-28 15:15:53 +00:00
|
|
|
*/
|
|
|
|
if (!cmdline_password)
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
return SPR_INCOMPLETE;
|
Fix error handling when command-line password fails.
In cmdline_get_passwd_input(), there's a boolean 'tried_once' which is
set the first time the function returns the password set by -pw or
-pwfile. The idea, as clearly commented in the code, was that if
cmdline_get_password_input asks for that password _again_, we return
failure, as if the user had refused to make a second attempt.
But that wasn't actually what happened, because when we set tried_once
to true, we also set cmdline_password to NULL, which causes the second
call to the function to behave as if no password was ever provided at
all. So after the -pw password failed, we'd fall back to asking
interactively.
This change moves the check of cmdline_password to after the check of
tried_once, restoring the originally intended behaviour: password
authentication will now _only_ be done via the pre-set password, if
there is one.
This seems like an xkcd #1172 kind of change: now that it's been wrong
for a while, _someone_ has probably found the unintended behaviour
useful, and started relying on it. So it may become necessary to add
an option to set the behaviour either way. But for the moment, let's
try it the way I originally intended it.
2021-12-28 15:15:53 +00:00
|
|
|
|
2011-10-02 11:50:45 +00:00
|
|
|
prompt_set_result(p->prompts[0], cmdline_password);
|
Fix command-line password handling in Restart Session.
When the user provides a password on the PuTTY command line, via -pw
or -pwfile, the flag 'tried_once' inside cmdline_get_passwd_input() is
intended to arrange that we only try sending that password once, and
after we've sent it, we don't try again.
But this plays badly with the 'Restart Session' operation. If the
connection is lost and then restarted at user request, we _do_ want to
send that password again!
So this commit moves that static variable out into a small state
structure held by the client of cmdline_get_passwd_input. Each client
can decide how to manage that state itself.
Clients that support 'Restart Session' - i.e. just GUI PuTTY itself -
will initialise the state at the same time as instantiating the
backend, so that every time the session is restarted, we return
to (correctly) believing that we _haven't_ yet tried the password
provided on the command line.
But clients that don't support 'Restart Session' - i.e. Plink and file
transfer tools - can do the same thing that cmdline.c was doing
before: just keep the state in a static variable.
This also means that the GUI login tools will now retain the
command-line password in memory, whereas previously they'd have wiped
it out once it was used. But the other tools will still wipe and free
the password, because I've also added a 'bool restartable' flag to
cmdline_get_passwd_input to let it know when it _is_ allowed to do
that.
In the GUI tools, I don't see any way to get round that, because if
the session is restarted you _have_ to still have the password to use
again. (And you can't infer that that will never happen from the
CONF_close_on_exit setting, because that too could be changed in
mid-session.) On the other hand, I think it's not all that worrying,
because the use of either -pw or -pwfile means that a persistent copy
of your password is *already* stored somewhere, so another one isn't
too big a stretch.
(Due to the change of -pw policy in 0.77, the effect of this bug was
that an attempt to reconnect in a session set up this way would lead
to "Configured password was not accepted". In 0.76, the failure mode
was different: PuTTY would interactively prompt for the password,
having wiped it out of memory after it was used the first time round.)
2022-05-18 12:04:56 +00:00
|
|
|
state->tried = true;
|
|
|
|
|
|
|
|
if (!restartable) {
|
|
|
|
/*
|
|
|
|
* If there's no possibility of needing to do this again after
|
|
|
|
* a 'Restart Session' event, then wipe our copy of the
|
|
|
|
* password out of memory.
|
|
|
|
*/
|
|
|
|
smemclr(cmdline_password, strlen(cmdline_password));
|
|
|
|
sfree(cmdline_password);
|
|
|
|
cmdline_password = NULL;
|
|
|
|
}
|
|
|
|
|
Richer data type for interactive prompt results.
All the seat functions that request an interactive prompt of some kind
to the user - both the main seat_get_userpass_input and the various
confirmation dialogs for things like host keys - were using a simple
int return value, with the general semantics of 0 = "fail", 1 =
"proceed" (and in the case of seat_get_userpass_input, answers to the
prompts were provided), and -1 = "request in progress, wait for a
callback".
In this commit I change all those functions' return types to a new
struct called SeatPromptResult, whose primary field is an enum
replacing those simple integer values.
The main purpose is that the enum has not three but _four_ values: the
"fail" result has been split into 'user abort' and 'software abort'.
The distinction is that a user abort occurs as a result of an
interactive UI action, such as the user clicking 'cancel' in a dialog
box or hitting ^D or ^C at a terminal password prompt - and therefore,
there's no need to display an error message telling the user that the
interactive operation has failed, because the user already knows,
because they _did_ it. 'Software abort' is from any other cause, where
PuTTY is the first to know there was a problem, and has to tell the
user.
We already had this 'user abort' vs 'software abort' distinction in
other parts of the code - the SSH backend has separate termination
functions which protocol layers can call. But we assumed that any
failure from an interactive prompt request fell into the 'user abort'
category, which is not true. A couple of examples: if you configure a
host key fingerprint in your saved session via the SSH > Host keys
pane, and the server presents a host key that doesn't match it, then
verify_ssh_host_key would report that the user had aborted the
connection, and feel no need to tell the user what had gone wrong!
Similarly, if a password provided on the command line was not
accepted, then (after I fixed the semantics of that in the previous
commit) the same wrong handling would occur.
So now, those Seat prompt functions too can communicate whether the
user or the software originated a connection abort. And in the latter
case, we also provide an error message to present to the user. Result:
in those two example cases (and others), error messages should no
longer go missing.
Implementation note: to avoid the hassle of having the error message
in a SeatPromptResult being a dynamically allocated string (and hence,
every recipient of one must always check whether it's non-NULL and
free it on every exit path, plus being careful about copying the
struct around), I've instead arranged that the structure contains a
function pointer and a couple of parameters, so that the string form
of the message can be constructed on demand. That way, the only users
who need to free it are the ones who actually _asked_ for it in the
first place, which is a much smaller set.
(This is one of the rare occasions that I regret not having C++'s
extra features available in this code base - a unique_ptr or
shared_ptr to a string would have been just the thing here, and the
compiler would have done all the hard work for me of remembering where
to insert the frees!)
2021-12-28 17:52:00 +00:00
|
|
|
return SPR_OK;
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool cmdline_check_unavailable(int flag, const char *p)
|
2002-09-02 13:32:37 +00:00
|
|
|
{
|
|
|
|
if (cmdline_tooltype & flag) {
|
2019-09-08 19:29:00 +00:00
|
|
|
cmdline_error("option \"%s\" not available in this tool", p);
|
|
|
|
return true;
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
return false;
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define UNAVAILABLE_IN(flag) do { \
|
|
|
|
if (cmdline_check_unavailable(flag, p)) return ret; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Process a standard command-line parameter. `p' is the parameter
|
|
|
|
* in question; `value' is the subsequent element of argv, which
|
|
|
|
* may or may not be required as an operand to the parameter.
|
2004-07-24 19:25:49 +00:00
|
|
|
* If `need_save' is 1, arguments which need to be saved as
|
|
|
|
* described at this top of this file are, for later execution;
|
|
|
|
* if 0, they are processed normally. (-1 is a special value used
|
|
|
|
* by pterm to count arguments for a preliminary pass through the
|
|
|
|
* argument list; it causes immediate return with an appropriate
|
|
|
|
* value with no action taken.)
|
2002-09-02 13:32:37 +00:00
|
|
|
* Return value is 2 if both arguments were used; 1 if only p was
|
|
|
|
* used; 0 if the parameter wasn't one we recognised; -2 if it
|
|
|
|
* should have been 2 but value was NULL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define RETURN(x) do { \
|
|
|
|
if ((x) == 2 && !value) return -2; \
|
|
|
|
ret = x; \
|
2003-03-31 12:10:53 +00:00
|
|
|
if (need_save < 0) return x; \
|
2002-09-02 13:32:37 +00:00
|
|
|
} while (0)
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool seen_hostname_argument = false;
|
|
|
|
static bool seen_port_argument = false;
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
static bool seen_verbose_option = false;
|
2020-01-30 06:40:22 +00:00
|
|
|
static bool loaded_session = false;
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
bool cmdline_verbose(void) { return seen_verbose_option; }
|
|
|
|
bool cmdline_seat_verbose(Seat *seat) { return cmdline_verbose(); }
|
|
|
|
bool cmdline_lp_verbose(LogPolicy *lp) { return cmdline_verbose(); }
|
2020-01-30 06:40:22 +00:00
|
|
|
bool cmdline_loaded_session(void) { return loaded_session; }
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
|
2020-02-02 10:00:42 +00:00
|
|
|
static void set_protocol(Conf *conf, int protocol)
|
|
|
|
{
|
|
|
|
settings_set_default_protocol(protocol);
|
|
|
|
conf_set_int(conf, CONF_protocol, protocol);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void set_port(Conf *conf, int port)
|
|
|
|
{
|
|
|
|
settings_set_default_port(port);
|
|
|
|
conf_set_int(conf, CONF_port, port);
|
|
|
|
}
|
|
|
|
|
2015-05-15 10:15:42 +00:00
|
|
|
int cmdline_process_param(const char *p, char *value,
|
|
|
|
int need_save, Conf *conf)
|
2002-09-02 13:32:37 +00:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
if (p[0] != '-') {
|
|
|
|
if (need_save < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Common handling for the tools whose initial command-line
|
|
|
|
* arguments specify a hostname to connect to, i.e. PuTTY and
|
|
|
|
* Plink. Doesn't count the file transfer tools, because their
|
|
|
|
* hostname specification appears as part of a more
|
|
|
|
* complicated scheme.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((cmdline_tooltype & TOOLTYPE_HOST_ARG) &&
|
|
|
|
!seen_hostname_argument &&
|
|
|
|
(!(cmdline_tooltype & TOOLTYPE_HOST_ARG_FROM_LAUNCHABLE_LOAD) ||
|
|
|
|
!loaded_session || !conf_launchable(conf))) {
|
|
|
|
/*
|
|
|
|
* Treat this argument as a host name, if we have not yet
|
|
|
|
* seen a host name argument or -load.
|
|
|
|
*
|
|
|
|
* Exception, in some tools (Plink): if we have seen -load
|
|
|
|
* but it didn't create a launchable session, then we
|
|
|
|
* still accept a hostname argument following that -load.
|
|
|
|
* This allows you to make saved sessions that configure
|
|
|
|
* lots of other stuff (colour schemes, terminal settings
|
|
|
|
* etc) and then say 'putty -load sessionname hostname'.
|
|
|
|
*
|
|
|
|
* Also, we carefully _don't_ test conf for launchability
|
|
|
|
* if we haven't been explicitly told to load a session
|
|
|
|
* (otherwise saving a host name into Default Settings
|
|
|
|
* would cause 'putty' on its own to immediately launch
|
|
|
|
* the default session and never be able to do anything
|
|
|
|
* else).
|
|
|
|
*/
|
|
|
|
if (!strncmp(p, "telnet:", 7)) {
|
|
|
|
/*
|
|
|
|
* If the argument starts with "telnet:", set the
|
|
|
|
* protocol to Telnet and process the string as a
|
|
|
|
* Telnet URL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Skip the "telnet:" or "telnet://" prefix.
|
|
|
|
*/
|
|
|
|
p += 7;
|
|
|
|
if (p[0] == '/' && p[1] == '/')
|
|
|
|
p += 2;
|
|
|
|
conf_set_int(conf, CONF_protocol, PROT_TELNET);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The next thing we expect is a host name.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
const char *host = p;
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
p += host_strcspn(p, ":/");
|
|
|
|
buf = dupprintf("%.*s", (int)(p - host), host);
|
|
|
|
conf_set_str(conf, CONF_host, buf);
|
|
|
|
sfree(buf);
|
2018-10-29 19:50:29 +00:00
|
|
|
seen_hostname_argument = true;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the host name is followed by a colon, then
|
|
|
|
* expect a port number after it.
|
|
|
|
*/
|
|
|
|
if (*p == ':') {
|
|
|
|
p++;
|
|
|
|
|
|
|
|
conf_set_int(conf, CONF_port, atoi(p));
|
|
|
|
/*
|
|
|
|
* Set the flag that will stop us from treating
|
|
|
|
* the next argument as a separate port; this one
|
|
|
|
* counts as explicitly provided.
|
|
|
|
*/
|
2018-10-29 19:50:29 +00:00
|
|
|
seen_port_argument = true;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
} else {
|
|
|
|
conf_set_int(conf, CONF_port, -1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
char *user = NULL, *hostname = NULL;
|
|
|
|
const char *hostname_after_user;
|
|
|
|
int port_override = -1;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, treat it as a bare host name.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (cmdline_tooltype & TOOLTYPE_HOST_ARG_PROTOCOL_PREFIX) {
|
|
|
|
/*
|
|
|
|
* Here Plink checks for a comma-separated
|
|
|
|
* protocol prefix, e.g. 'ssh,hostname' or
|
|
|
|
* 'ssh,user@hostname'.
|
|
|
|
*
|
|
|
|
* I'm not entirely sure why; this behaviour dates
|
|
|
|
* from 2000 and isn't explained. But I _think_ it
|
|
|
|
* has to do with CVS transport or similar use
|
|
|
|
* cases, in which the end user invokes the SSH
|
|
|
|
* client indirectly, via some means that only
|
|
|
|
* lets them pass a single string argument, and it
|
|
|
|
* was occasionally useful to shoehorn the choice
|
|
|
|
* of protocol into that argument.
|
|
|
|
*/
|
|
|
|
const char *comma = strchr(p, ',');
|
|
|
|
if (comma) {
|
|
|
|
char *prefix = dupprintf("%.*s", (int)(comma - p), p);
|
2018-10-05 06:03:46 +00:00
|
|
|
const struct BackendVtable *vt =
|
2018-09-11 15:23:38 +00:00
|
|
|
backend_vt_from_name(prefix);
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (vt) {
|
2020-02-02 10:00:42 +00:00
|
|
|
set_protocol(conf, vt->protocol);
|
2018-09-11 15:23:38 +00:00
|
|
|
port_override = vt->default_port;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
} else {
|
|
|
|
cmdline_error("unrecognised protocol prefix '%s'",
|
|
|
|
prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
sfree(prefix);
|
|
|
|
p = comma + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hostname_after_user = p;
|
|
|
|
if (cmdline_tooltype & TOOLTYPE_HOST_ARG_CAN_BE_SESSION) {
|
|
|
|
/*
|
|
|
|
* If the hostname argument can also be a saved
|
|
|
|
* session (see below), then here we also check
|
|
|
|
* for a user@ prefix, which will override the
|
|
|
|
* username from the saved session.
|
|
|
|
*
|
|
|
|
* (If the hostname argument _isn't_ a saved
|
|
|
|
* session, we don't do this.)
|
|
|
|
*/
|
|
|
|
const char *at = strrchr(p, '@');
|
|
|
|
if (at) {
|
|
|
|
user = dupprintf("%.*s", (int)(at - p), p);
|
|
|
|
hostname_after_user = at + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write the whole hostname argument (minus only that
|
|
|
|
* optional protocol prefix) into the existing Conf,
|
|
|
|
* for tools that don't treat it as a saved session
|
|
|
|
* and as a fallback for those that do.
|
|
|
|
*/
|
|
|
|
hostname = dupstr(p + strspn(p, " \t"));
|
|
|
|
len = strlen(hostname);
|
|
|
|
while (len > 0 && (hostname[len-1] == ' ' ||
|
|
|
|
hostname[len-1] == '\t'))
|
|
|
|
hostname[--len] = '\0';
|
2018-10-29 19:50:29 +00:00
|
|
|
seen_hostname_argument = true;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
conf_set_str(conf, CONF_host, hostname);
|
|
|
|
|
|
|
|
if ((cmdline_tooltype & TOOLTYPE_HOST_ARG_CAN_BE_SESSION) &&
|
|
|
|
!loaded_session) {
|
|
|
|
/*
|
|
|
|
* For some tools, we equivocate between a
|
2019-09-08 19:29:00 +00:00
|
|
|
* hostname argument and an argument naming a
|
|
|
|
* saved session. Here we attempt to load a
|
|
|
|
* session with the specified name, and if that
|
|
|
|
* session exists and is launchable, we overwrite
|
|
|
|
* the entire Conf with it.
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
*
|
|
|
|
* We skip this check if a -load option has
|
|
|
|
* already happened, so that
|
|
|
|
*
|
|
|
|
* plink -load non-launchable-session hostname
|
|
|
|
*
|
|
|
|
* will treat 'hostname' as a hostname _even_ if a
|
|
|
|
* saved session called 'hostname' exists. (This
|
|
|
|
* doesn't lose any functionality someone could
|
|
|
|
* have needed, because if 'hostname' did cause a
|
|
|
|
* session to be loaded, then it would overwrite
|
|
|
|
* everything from the previously loaded session.
|
|
|
|
* So if that was the behaviour someone wanted,
|
|
|
|
* then they could get it by leaving off the
|
|
|
|
* -load completely.)
|
2019-09-08 19:29:00 +00:00
|
|
|
*/
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
Conf *conf2 = conf_new();
|
2019-02-27 20:31:48 +00:00
|
|
|
if (do_defaults(hostname_after_user, conf2) &&
|
|
|
|
conf_launchable(conf2)) {
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
conf_copy_into(conf, conf2);
|
2018-10-29 19:50:29 +00:00
|
|
|
loaded_session = true;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
/* And override the username if one was given. */
|
|
|
|
if (user)
|
|
|
|
conf_set_str(conf, CONF_username, user);
|
|
|
|
}
|
|
|
|
conf_free(conf2);
|
|
|
|
}
|
|
|
|
|
|
|
|
sfree(hostname);
|
|
|
|
sfree(user);
|
|
|
|
|
|
|
|
if (port_override >= 0)
|
|
|
|
conf_set_int(conf, CONF_port, port_override);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
} else if ((cmdline_tooltype & TOOLTYPE_PORT_ARG) &&
|
|
|
|
!seen_port_argument) {
|
|
|
|
/*
|
|
|
|
* If we've already got a host name from the command line
|
|
|
|
* (either as a hostname argument or a qualifying -load),
|
|
|
|
* but not a port number, then treat the next argument as
|
|
|
|
* a port number.
|
|
|
|
*
|
|
|
|
* We handle this by calling ourself recursively to
|
|
|
|
* pretend we received a -P argument, so that it will be
|
|
|
|
* deferred until it's a good moment to run it.
|
|
|
|
*/
|
|
|
|
char *dup = dupstr(p); /* 'value' is not a const char * */
|
|
|
|
int retd = cmdline_process_param("-P", dup, 1, conf);
|
|
|
|
sfree(dup);
|
|
|
|
assert(retd == 2);
|
2018-10-29 19:50:29 +00:00
|
|
|
seen_port_argument = true;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Refuse to recognise this argument, and give it back to
|
|
|
|
* the tool's own command-line processing.
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-02 13:32:37 +00:00
|
|
|
if (!strcmp(p, "-load")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
/* This parameter must be processed immediately rather than being
|
|
|
|
* saved. */
|
|
|
|
do_defaults(value, conf);
|
|
|
|
loaded_session = true;
|
|
|
|
return 2;
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
2020-02-22 11:52:30 +00:00
|
|
|
for (size_t i = 0; backends[i]; i++) {
|
|
|
|
if (p[0] == '-' && !strcmp(p+1, backends[i]->id)) {
|
|
|
|
RETURN(1);
|
2020-02-22 15:29:45 +00:00
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
2020-02-22 11:52:30 +00:00
|
|
|
SAVEABLE(0);
|
|
|
|
set_protocol(conf, backends[i]->protocol);
|
|
|
|
if (backends[i]->default_port)
|
|
|
|
set_port(conf, backends[i]->default_port);
|
|
|
|
if (backends[i]->protocol == PROT_SERIAL) {
|
|
|
|
/* Special handling: the 'where to connect to' argument will
|
|
|
|
* have been placed into CONF_host, but for this protocol, it
|
|
|
|
* needs to be in CONF_serline */
|
|
|
|
conf_set_str(conf, CONF_serline,
|
|
|
|
conf_get_str(conf, CONF_host));
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2009-08-10 20:55:19 +00:00
|
|
|
}
|
2002-09-02 13:32:37 +00:00
|
|
|
if (!strcmp(p, "-v")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NO_VERBOSE_OPTION);
|
|
|
|
seen_verbose_option = true;
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-l")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_str(conf, CONF_username, value);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
2008-06-01 11:16:32 +00:00
|
|
|
if (!strcmp(p, "-loghost")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_str(conf, CONF_loghost, value);
|
2008-06-01 11:16:32 +00:00
|
|
|
}
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
if (!strcmp(p, "-hostkey")) {
|
|
|
|
char *dup;
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
dup = dupstr(value);
|
|
|
|
if (!validate_manual_hostkey(dup)) {
|
|
|
|
cmdline_error("'%s' is not a valid format for a manual host "
|
|
|
|
"key specification", value);
|
|
|
|
sfree(dup);
|
|
|
|
return ret;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_str_str(conf, CONF_ssh_manual_hostkeys, dup, "");
|
New option to manually configure the expected host key(s).
This option is available from the command line as '-hostkey', and is
also configurable through the GUI. When enabled, it completely
replaces all of the automated host key management: the server's host
key will be checked against the manually configured list, and the
connection will be allowed or disconnected on that basis, and the host
key store in the registry will not be either consulted or updated.
The main aim is to provide a means of automatically running Plink,
PSCP or PSFTP deep inside Windows services where HKEY_CURRENT_USER
isn't available to have stored the right host key in. But it also
permits you to specify a list of multiple host keys, which means a
second use case for the same mechanism will probably be round-robin
DNS names that select one of several servers with different host keys.
Host keys can be specified as the standard MD5 fingerprint or as an
SSH-2 base64 blob, and are canonicalised on input. (The base64 blob is
more unwieldy, especially with Windows command-line length limits, but
provides a means of specifying the _whole_ public key in case you
don't trust MD5. I haven't bothered to provide an analogous mechanism
for SSH-1, on the basis that anyone worrying about MD5 should have
stopped using SSH-1 already!)
[originally from svn r10220]
2014-09-09 11:46:24 +00:00
|
|
|
sfree(dup);
|
|
|
|
}
|
2003-04-05 11:45:21 +00:00
|
|
|
if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char type, *q, *qq, *key, *val;
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
if (strcmp(p, "-D")) {
|
|
|
|
/*
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
* For -L or -R forwarding types:
|
|
|
|
*
|
2019-09-08 19:29:00 +00:00
|
|
|
* We expect _at least_ two colons in this string. The
|
|
|
|
* possible formats are `sourceport:desthost:destport',
|
|
|
|
* or `sourceip:sourceport:desthost:destport' if you're
|
|
|
|
* specifying a particular loopback address. We need to
|
|
|
|
* replace the one between source and dest with a \t;
|
|
|
|
* this means we must find the second-to-last colon in
|
|
|
|
* the string.
|
|
|
|
*
|
|
|
|
* (This looks like a foolish way of doing it given the
|
|
|
|
* existence of strrchr, but it's more efficient than
|
|
|
|
* two strrchrs - not to mention that the second strrchr
|
|
|
|
* would require us to modify the input string!)
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
|
|
|
type = p[1]; /* 'L' or 'R' */
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
q = qq = host_strchr(value, ':');
|
|
|
|
while (qq) {
|
|
|
|
char *qqq = host_strchr(qq+1, ':');
|
|
|
|
if (qqq)
|
|
|
|
q = qq;
|
|
|
|
qq = qqq;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!q) {
|
|
|
|
cmdline_error("-%c expects at least two colons in its"
|
|
|
|
" argument", type);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
key = dupprintf("%c%.*s", type, (int)(q - value), value);
|
|
|
|
val = dupstr(q+1);
|
|
|
|
} else {
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
/*
|
|
|
|
* Dynamic port forwardings are entered under the same key
|
|
|
|
* as if they were local (because they occupy the same
|
|
|
|
* port space - a local and a dynamic forwarding on the
|
|
|
|
* same local port are mutually exclusive), with the
|
|
|
|
* special value "D" (which can be distinguished from
|
|
|
|
* anything in the ordinary -L case by containing no
|
|
|
|
* colon).
|
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
key = dupprintf("L%s", value);
|
|
|
|
val = dupstr("D");
|
|
|
|
}
|
|
|
|
conf_set_str_str(conf, CONF_portfwd, key, val);
|
|
|
|
sfree(key);
|
|
|
|
sfree(val);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
2006-08-28 15:12:37 +00:00
|
|
|
if ((!strcmp(p, "-nc"))) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *host, *portp;
|
2006-08-28 15:12:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
2006-08-28 15:12:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
portp = host_strchr(value, ':');
|
|
|
|
if (!portp) {
|
|
|
|
cmdline_error("-nc expects argument of form 'host:port'");
|
|
|
|
return ret;
|
|
|
|
}
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
host = dupprintf("%.*s", (int)(portp - value), value);
|
|
|
|
conf_set_str(conf, CONF_ssh_nc_host, host);
|
|
|
|
conf_set_int(conf, CONF_ssh_nc_port, atoi(portp + 1));
|
2011-07-15 18:21:30 +00:00
|
|
|
sfree(host);
|
2006-08-28 15:12:37 +00:00
|
|
|
}
|
2002-09-02 13:32:37 +00:00
|
|
|
if (!strcmp(p, "-m")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
const char *filename;
|
|
|
|
FILE *fp;
|
2002-09-02 13:32:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
2002-09-02 13:32:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
filename = value;
|
2002-09-02 13:32:37 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
fp = fopen(filename, "r");
|
|
|
|
if (!fp) {
|
|
|
|
cmdline_error("unable to open command file \"%s\"", filename);
|
|
|
|
return ret;
|
|
|
|
}
|
2019-02-11 06:58:07 +00:00
|
|
|
strbuf *command = strbuf_new();
|
|
|
|
char readbuf[4096];
|
2019-09-08 19:29:00 +00:00
|
|
|
while (1) {
|
2019-02-11 06:58:07 +00:00
|
|
|
size_t nread = fread(readbuf, 1, sizeof(readbuf), fp);
|
|
|
|
if (nread == 0)
|
|
|
|
break;
|
|
|
|
put_data(command, readbuf, nread);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
conf_set_str(conf, CONF_remote_cmd, command->s);
|
|
|
|
conf_set_str(conf, CONF_remote_cmd2, "");
|
|
|
|
conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */
|
|
|
|
strbuf_free(command);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-P")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
2021-02-21 16:41:36 +00:00
|
|
|
SAVEABLE(1); /* lower priority than -ssh, -telnet, etc */
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_int(conf, CONF_port, atoi(value));
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-pw")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(1);
|
|
|
|
/* We delay evaluating this until after the protocol is decided,
|
|
|
|
* so that we can warn if it's of no use with the selected protocol */
|
|
|
|
if (conf_get_int(conf, CONF_protocol) != PROT_SSH)
|
|
|
|
cmdline_error("the -pw option can only be used with the "
|
|
|
|
"SSH protocol");
|
|
|
|
else {
|
2022-01-29 18:05:00 +00:00
|
|
|
if (cmdline_password) {
|
|
|
|
smemclr(cmdline_password, strlen(cmdline_password));
|
|
|
|
sfree(cmdline_password);
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
cmdline_password = dupstr(value);
|
|
|
|
/* Assuming that `value' is directly from argv, make a good faith
|
|
|
|
* attempt to trample it, to stop it showing up in `ps' output
|
|
|
|
* on Unix-like systems. Not guaranteed, of course. */
|
|
|
|
smemclr(value, strlen(value));
|
|
|
|
}
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 17:04:15 +00:00
|
|
|
if (!strcmp(p, "-pwfile")) {
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(1);
|
|
|
|
/* We delay evaluating this until after the protocol is decided,
|
|
|
|
* so that we can warn if it's of no use with the selected protocol */
|
|
|
|
if (conf_get_int(conf, CONF_protocol) != PROT_SSH)
|
|
|
|
cmdline_error("the -pwfile option can only be used with the "
|
|
|
|
"SSH protocol");
|
|
|
|
else {
|
|
|
|
Filename *fn = filename_from_str(value);
|
|
|
|
FILE *fp = f_open(fn, "r", false);
|
|
|
|
if (!fp) {
|
|
|
|
cmdline_error("unable to open password file '%s'", value);
|
|
|
|
} else {
|
2022-01-29 18:05:00 +00:00
|
|
|
if (cmdline_password) {
|
|
|
|
smemclr(cmdline_password, strlen(cmdline_password));
|
|
|
|
sfree(cmdline_password);
|
|
|
|
}
|
|
|
|
|
2021-09-28 17:04:15 +00:00
|
|
|
cmdline_password = chomp(fgetline(fp));
|
|
|
|
if (!cmdline_password) {
|
|
|
|
cmdline_error("unable to read a password from file '%s'",
|
|
|
|
value);
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
filename_free(fn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-19 12:05:12 +00:00
|
|
|
if (!strcmp(p, "-agent") || !strcmp(p, "-pagent") ||
|
2019-09-08 19:29:00 +00:00
|
|
|
!strcmp(p, "-pageant")) {
|
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_tryagent, true);
|
2006-02-19 12:05:12 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-noagent") || !strcmp(p, "-nopagent") ||
|
2019-09-08 19:29:00 +00:00
|
|
|
!strcmp(p, "-nopageant")) {
|
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_tryagent, false);
|
2006-02-19 12:05:12 +00:00
|
|
|
}
|
New option to reject 'trivial' success of userauth.
Suggested by Manfred Kaiser, who also wrote most of this patch
(although outlying parts, like documentation and SSH-1 support, are by
me).
This is a second line of defence against the kind of spoofing attacks
in which a malicious or compromised SSH server rushes the client
through the userauth phase of SSH without actually requiring any auth
inputs (passwords or signatures or whatever), and then at the start of
the connection phase it presents something like a spoof prompt,
intended to be taken for part of userauth by the user but in fact with
some more sinister purpose.
Our existing line of defence against this is the trust sigil system,
and as far as I know, that's still working. This option allows a bit of
extra defence in depth: if you don't expect your SSH server to
trivially accept authentication in the first place, then enabling this
option will cause PuTTY to disconnect if it unexpectedly does so,
without the user having to spot the presence or absence of a fiddly
little sigil anywhere.
Several types of authentication count as 'trivial'. The obvious one is
the SSH-2 "none" method, which clients always try first so that the
failure message will tell them what else they can try, and which a
server can instead accept in order to authenticate you unconditionally.
But there are two other ways to do it that we know of: one is to run
keyboard-interactive authentication and send an empty INFO_REQUEST
packet containing no actual prompts for the user, and another even
weirder one is to send USERAUTH_SUCCESS in response to the user's
preliminary *offer* of a public key (instead of sending the usual PK_OK
to request an actual signature from the key).
This new option detects all of those, by clearing the 'is_trivial_auth'
flag only when we send some kind of substantive authentication response
(be it a password, a k-i prompt response, a signature, or a GSSAPI
token). So even if there's a further path through the userauth maze we
haven't spotted, that somehow avoids sending anything substantive, this
strategy should still pick it up.
2021-06-19 14:39:15 +00:00
|
|
|
|
|
|
|
if (!strcmp(p, "-no-trivial-auth")) {
|
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_ssh_no_trivial_userauth, true);
|
|
|
|
}
|
|
|
|
|
2017-07-06 08:18:27 +00:00
|
|
|
if (!strcmp(p, "-share")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_ssh_connection_sharing, true);
|
2017-07-06 08:18:27 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-noshare")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_ssh_connection_sharing, false);
|
2017-07-06 08:18:27 +00:00
|
|
|
}
|
2002-09-02 13:32:37 +00:00
|
|
|
if (!strcmp(p, "-A")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_agentfwd, true);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-a")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_agentfwd, false);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(p, "-X")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_x11_forward, true);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-x")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_x11_forward, false);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(p, "-t")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(1); /* lower priority than -m */
|
|
|
|
conf_set_bool(conf, CONF_nopty, false);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-T")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(1);
|
|
|
|
conf_set_bool(conf, CONF_nopty, true);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
2004-10-13 13:43:11 +00:00
|
|
|
if (!strcmp(p, "-N")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_ssh_no_shell, true);
|
2004-10-13 13:43:11 +00:00
|
|
|
}
|
|
|
|
|
2002-09-02 13:32:37 +00:00
|
|
|
if (!strcmp(p, "-C")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_bool(conf, CONF_compression, true);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(p, "-1")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_int(conf, CONF_sshprot, 0); /* ssh protocol 1 only */
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-2")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_int(conf, CONF_sshprot, 3); /* ssh protocol 2 only */
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(p, "-i")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
Filename *fn;
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
fn = filename_from_str(value);
|
|
|
|
conf_set_filename(conf, CONF_keyfile, fn);
|
2011-10-02 11:01:57 +00:00
|
|
|
filename_free(fn);
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
Support for detached certificates in userauth.
This is triggered by a new config option, or alternatively a -cert
command-line option. You provide a certificate file (i.e. a public key
containing one of the cert key formats), and then, whenever you
authenticate with a private key that matches the public key inside
that certificate, the certificate will be sent to the server in place
of whatever public key it would have used before.
I expect this to be more convenient for some users than the approach
of baking the certificate into a modified version of the PPK file -
especially users who want to use different certificates on the same
key, either in sequence (if a CA continually reissues certificates
with short lifetimes) or in parallel (if different hosts trust
different CAs).
In particular, this substitution is applied consistently, even when
doing authentication via an agent. So if your bare private key is held
in Pageant, you can _still_ specify a detached certificate, and PuTTY
will spot that the key it's picked from Pageant matches that
certificate, and do the same substitution.
The detached certificate also overrides an existing certificate, if
there was one on the public key already.
2022-04-21 09:55:44 +00:00
|
|
|
if (!strcmp(p, "-cert")) {
|
|
|
|
Filename *fn;
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
fn = filename_from_str(value);
|
|
|
|
conf_set_filename(conf, CONF_detached_cert, fn);
|
|
|
|
filename_free(fn);
|
|
|
|
}
|
|
|
|
|
2004-12-30 16:45:11 +00:00
|
|
|
if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
2022-05-21 09:23:01 +00:00
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
2019-09-08 19:29:00 +00:00
|
|
|
SAVEABLE(1);
|
|
|
|
conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV4);
|
2004-12-30 16:45:11 +00:00
|
|
|
}
|
|
|
|
if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
2022-05-21 09:23:01 +00:00
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
2019-09-08 19:29:00 +00:00
|
|
|
SAVEABLE(1);
|
|
|
|
conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV6);
|
2004-12-30 16:45:11 +00:00
|
|
|
}
|
2009-08-10 20:55:19 +00:00
|
|
|
if (!strcmp(p, "-sercfg")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char* nextitem;
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(1);
|
|
|
|
if (conf_get_int(conf, CONF_protocol) != PROT_SERIAL)
|
|
|
|
cmdline_error("the -sercfg option can only be used with the "
|
|
|
|
"serial protocol");
|
|
|
|
/* Value[0] contains one or more , separated values, like 19200,8,n,1,X */
|
|
|
|
nextitem = value;
|
|
|
|
while (nextitem[0] != '\0') {
|
|
|
|
int length, skip;
|
|
|
|
char *end = strchr(nextitem, ',');
|
|
|
|
if (!end) {
|
|
|
|
length = strlen(nextitem);
|
|
|
|
skip = 0;
|
|
|
|
} else {
|
|
|
|
length = end - nextitem;
|
|
|
|
nextitem[length] = '\0';
|
|
|
|
skip = 1;
|
|
|
|
}
|
|
|
|
if (length == 1) {
|
|
|
|
switch (*nextitem) {
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
conf_set_int(conf, CONF_serstopbits, 2 * (*nextitem-'0'));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
conf_set_int(conf, CONF_serdatabits, *nextitem-'0');
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
conf_set_int(conf, CONF_serparity, SER_PAR_NONE);
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
conf_set_int(conf, CONF_serparity, SER_PAR_ODD);
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
conf_set_int(conf, CONF_serparity, SER_PAR_EVEN);
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
conf_set_int(conf, CONF_serparity, SER_PAR_MARK);
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
conf_set_int(conf, CONF_serparity, SER_PAR_SPACE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'N':
|
|
|
|
conf_set_int(conf, CONF_serflow, SER_FLOW_NONE);
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
conf_set_int(conf, CONF_serflow, SER_FLOW_XONXOFF);
|
|
|
|
break;
|
|
|
|
case 'R':
|
|
|
|
conf_set_int(conf, CONF_serflow, SER_FLOW_RTSCTS);
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
conf_set_int(conf, CONF_serflow, SER_FLOW_DSRDTR);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
cmdline_error("Unrecognised suboption \"-sercfg %c\"",
|
|
|
|
*nextitem);
|
|
|
|
}
|
|
|
|
} else if (length == 3 && !strncmp(nextitem,"1.5",3)) {
|
|
|
|
/* Messy special case */
|
|
|
|
conf_set_int(conf, CONF_serstopbits, 3);
|
|
|
|
} else {
|
|
|
|
int serspeed = atoi(nextitem);
|
|
|
|
if (serspeed != 0) {
|
|
|
|
conf_set_int(conf, CONF_serspeed, serspeed);
|
|
|
|
} else {
|
|
|
|
cmdline_error("Unrecognised suboption \"-sercfg %s\"",
|
|
|
|
nextitem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nextitem += length + skip;
|
|
|
|
}
|
2009-08-10 20:55:19 +00:00
|
|
|
}
|
2015-09-24 16:30:04 +00:00
|
|
|
|
2015-11-08 11:57:39 +00:00
|
|
|
if (!strcmp(p, "-sessionlog")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
Filename *fn;
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER);
|
|
|
|
/* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */
|
|
|
|
SAVEABLE(0);
|
|
|
|
fn = filename_from_str(value);
|
|
|
|
conf_set_filename(conf, CONF_logfilename, fn);
|
|
|
|
conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
|
2015-11-08 11:57:39 +00:00
|
|
|
filename_free(fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(p, "-sshlog") ||
|
2015-09-24 16:30:04 +00:00
|
|
|
!strcmp(p, "-sshrawlog")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
Filename *fn;
|
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
fn = filename_from_str(value);
|
|
|
|
conf_set_filename(conf, CONF_logfilename, fn);
|
|
|
|
conf_set_int(conf, CONF_logtype,
|
2015-09-24 16:30:04 +00:00
|
|
|
!strcmp(p, "-sshlog") ? LGTYP_PACKETS :
|
|
|
|
/* !strcmp(p, "-sshrawlog") ? */ LGTYP_SSHRAW);
|
|
|
|
filename_free(fn);
|
|
|
|
}
|
|
|
|
|
2020-11-22 08:45:48 +00:00
|
|
|
if (!strcmp(p, "-logoverwrite")) {
|
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_int(conf, CONF_logxfovr, LGXF_OVR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(p, "-logappend")) {
|
|
|
|
RETURN(1);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
|
|
|
conf_set_int(conf, CONF_logxfovr, LGXF_APN);
|
|
|
|
}
|
|
|
|
|
2016-05-03 13:31:10 +00:00
|
|
|
if (!strcmp(p, "-proxycmd")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(2);
|
|
|
|
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
|
|
|
SAVEABLE(0);
|
2016-05-03 13:31:10 +00:00
|
|
|
conf_set_int(conf, CONF_proxy_type, PROXY_CMD);
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_str(conf, CONF_proxy_telnet_command, value);
|
2016-05-03 13:31:10 +00:00
|
|
|
}
|
|
|
|
|
2017-01-28 21:56:28 +00:00
|
|
|
#ifdef _WINDOWS
|
|
|
|
/*
|
|
|
|
* Cross-tool options only available on Windows.
|
|
|
|
*/
|
|
|
|
if (!strcmp(p, "-restrict-acl") || !strcmp(p, "-restrict_acl") ||
|
|
|
|
!strcmp(p, "-restrictacl")) {
|
2019-09-08 19:29:00 +00:00
|
|
|
RETURN(1);
|
2017-01-28 21:56:28 +00:00
|
|
|
restrict_process_acl();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
return ret; /* unrecognised */
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
void cmdline_run_saved(Conf *conf)
|
2002-09-02 13:32:37 +00:00
|
|
|
{
|
2020-01-29 06:35:53 +00:00
|
|
|
for (size_t pri = 0; pri < NPRIORITIES; pri++) {
|
|
|
|
for (size_t i = 0; i < saves[pri].nsaved; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
cmdline_process_param(saves[pri].params[i].p,
|
|
|
|
saves[pri].params[i].value, 0, conf);
|
2015-05-15 10:15:42 +00:00
|
|
|
sfree(saves[pri].params[i].p);
|
|
|
|
sfree(saves[pri].params[i].value);
|
|
|
|
}
|
|
|
|
saves[pri].nsaved = 0;
|
|
|
|
}
|
2002-09-02 13:32:37 +00:00
|
|
|
}
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool cmdline_host_ok(Conf *conf)
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
{
|
|
|
|
/*
|
2018-10-29 19:50:29 +00:00
|
|
|
* Return true if the command-line arguments we've processed in
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
* TOOLTYPE_HOST_ARG mode are sufficient to justify launching a
|
|
|
|
* session.
|
|
|
|
*/
|
|
|
|
assert(cmdline_tooltype & TOOLTYPE_HOST_ARG);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Of course, if we _can't_ launch a session, the answer is
|
|
|
|
* clearly no.
|
|
|
|
*/
|
|
|
|
if (!conf_launchable(conf))
|
2018-10-29 19:50:29 +00:00
|
|
|
return false;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* But also, if we haven't seen either a -load option or a
|
|
|
|
* hostname argument, i.e. the only saved settings we've loaded
|
|
|
|
* are Default Settings plus any non-hostname-based stuff from the
|
|
|
|
* command line, then the answer is still no, _even_ if this Conf
|
|
|
|
* is launchable. Otherwise, if you saved your favourite hostname
|
|
|
|
* into Default Settings, then just running 'putty' without
|
|
|
|
* arguments would connect to it without ever offering you the
|
|
|
|
* option to connect to something else or change the setting.
|
|
|
|
*/
|
|
|
|
if (!seen_hostname_argument && !loaded_session)
|
2018-10-29 19:50:29 +00:00
|
|
|
return false;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
return true;
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
}
|