#include "putty.h"
#include "storage.h"
#include "tree234.h"
+#include "winsecur.h"
#define WM_AGENT_CALLBACK (WM_APP + 4)
int len;
};
-void fatalbox(char *p, ...)
+void fatalbox(const char *p, ...)
{
va_list ap;
fprintf(stderr, "FATAL ERROR: ");
}
cleanup_exit(1);
}
-void modalfatalbox(char *p, ...)
+void modalfatalbox(const char *p, ...)
{
va_list ap;
fprintf(stderr, "FATAL ERROR: ");
}
cleanup_exit(1);
}
-void nonfatal(char *p, ...)
+void nonfatal(const char *p, ...)
{
va_list ap;
fprintf(stderr, "ERROR: ");
vfprintf(stderr, p, ap);
va_end(ap);
fputc('\n', stderr);
- if (logctx) {
- log_free(logctx);
- logctx = NULL;
- }
}
-void connection_fatal(void *frontend, char *p, ...)
+void connection_fatal(void *frontend, const char *p, ...)
{
va_list ap;
fprintf(stderr, "FATAL ERROR: ");
}
cleanup_exit(1);
}
-void cmdline_error(char *p, ...)
+void cmdline_error(const char *p, ...)
{
va_list ap;
fprintf(stderr, "plink: ");
{
return FALSE;
}
-void ldisc_update(void *frontend, int echo, int edit)
+void frontend_echoedit_update(void *frontend, int echo, int edit)
{
/* Update stdin read mode to reflect changes in line discipline. */
DWORD mode;
return FALSE; /* do not respond to incoming EOF with outgoing */
}
-int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
+int get_userpass_input(prompts_t *p, const unsigned char *in, int inlen)
{
int ret;
ret = cmdline_get_passwd_input(p, in, inlen);
*/
static void usage(void)
{
- printf("PuTTY Link: command-line connection utility\n");
+ printf("Plink: command-line connection utility\n");
printf("%s\n", ver);
printf("Usage: plink [options] [user@]host [command]\n");
printf(" (\"host\" can also be a PuTTY saved session name)\n");
printf(" -P port connect to specified port\n");
printf(" -l user connect with specified username\n");
printf(" -batch disable all interactive prompts\n");
+ printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n");
+ printf(" Specify the serial configuration (serial only)\n");
printf("The following options only apply to SSH connections:\n");
printf(" -pw passw login with specified password\n");
printf(" -D [listen-IP:]listen-port\n");
printf(" -1 -2 force use of particular protocol version\n");
printf(" -4 -6 force use of IPv4 or IPv6\n");
printf(" -C enable compression\n");
- printf(" -i key private key file for authentication\n");
+ printf(" -i key private key file for user authentication\n");
printf(" -noagent disable use of Pageant\n");
printf(" -agent enable use of Pageant\n");
+ printf(" -hostkey aa:bb:cc:...\n");
+ printf(" manually specify a host key (may be repeated)\n");
printf(" -m file read remote command(s) from file\n");
printf(" -s remote command is an SSH subsystem (SSH-2 only)\n");
printf(" -N don't start a shell/command (SSH-2 only)\n");
printf(" -nc host:port\n");
printf(" open tunnel in place of session (SSH-2 only)\n");
- printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n");
- printf(" Specify the serial configuration (serial only)\n");
+ printf(" -sshlog file\n");
+ printf(" -sshrawlog file\n");
+ printf(" log protocol details to a file\n");
+ printf(" -shareexists\n");
+ printf(" test whether a connection-sharing upstream exists\n");
exit(1);
}
}
}
+const int share_can_be_downstream = TRUE;
+const int share_can_be_upstream = TRUE;
+
int main(int argc, char **argv)
{
int sending;
int errors;
int got_host = FALSE;
int use_subsystem = 0;
+ int just_test_share_exists = FALSE;
unsigned long now, next, then;
sklist = NULL;
} else if (!strcmp(p, "-pgpfp")) {
pgp_fingerprints();
exit(1);
+ } else if (!strcmp(p, "-shareexists")) {
+ just_test_share_exists = TRUE;
} else {
fprintf(stderr, "plink: unknown option \"%s\"\n", p);
errors = 1;
q += 2;
conf_set_int(conf, CONF_protocol, PROT_TELNET);
p = q;
- while (*p && *p != ':' && *p != '/')
- p++;
+ p += host_strcspn(p, ":/");
c = *p;
if (*p)
*p++ = '\0';
}
}
+#if !defined UNPROTECT && !defined NO_SECURITY
+ /*
+ * Protect our process.
+ */
+ {
+ char *error = NULL;
+ if (!setprocessacl(error)) {
+ char *message = dupprintf("Could not restrict process ACL: %s",
+ error);
+ logevent(NULL, message);
+ sfree(message);
+ sfree(error);
+ }
+ }
+#endif
+
if (errors)
return 1;
}
}
- /*
- * Trim off a colon suffix if it's there.
- */
- host[strcspn(host, ":")] = '\0';
+ /*
+ * Trim a colon suffix off the hostname if it's there. In
+ * order to protect unbracketed IPv6 address literals
+ * against this treatment, we do not do this if there's
+ * _more_ than one colon.
+ */
+ {
+ char *c = host_strchr(host, ':');
+
+ if (c) {
+ char *d = host_strchr(c+1, ':');
+ if (!d)
+ *c = '\0';
+ }
+ }
/*
* Remove any remaining whitespace.
return 1;
}
+ /*
+ * Plink doesn't provide any way to add forwardings after the
+ * connection is set up, so if there are none now, we can safely set
+ * the "simple" flag.
+ */
+ if (conf_get_int(conf, CONF_protocol) == PROT_SSH &&
+ !conf_get_int(conf, CONF_x11_forward) &&
+ !conf_get_int(conf, CONF_agentfwd) &&
+ !conf_get_str_nthstrkey(conf, CONF_portfwd, 0))
+ conf_set_int(conf, CONF_ssh_simple, TRUE);
+
logctx = log_init(NULL, conf);
console_provide_logctx(logctx);
+ if (just_test_share_exists) {
+ if (!back->test_for_upstream) {
+ fprintf(stderr, "Connection sharing not supported for connection "
+ "type '%s'\n", back->name);
+ return 1;
+ }
+ if (back->test_for_upstream(conf_get_str(conf, CONF_host),
+ conf_get_int(conf, CONF_port), conf))
+ return 0;
+ else
+ return 1;
+ }
+
/*
* Start up the connection.
*/
sending = TRUE;
}
- if (run_timers(now, &next)) {
+ if (toplevel_callback_pending()) {
+ ticks = 0;
+ next = now;
+ } else if (run_timers(now, &next)) {
then = now;
now = GETTICKCOUNT();
if (now - then > next - then)
ticks = next - now;
} else {
ticks = INFINITE;
+ /* no need to initialise next here because we can never
+ * get WAIT_TIMEOUT */
}
handles = handle_get_events(&nhandles);