From affe1a4a72047a1227d45707c6bdd706cf02ba84 Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Wed, 28 Aug 2024 21:21:19 +1200 Subject: [PATCH] Add new command to remove individual port forwards Previously there were only commands to remove *all* forwards of a given type. --- doc/changes.md | 3 +++ doc/ssh-readme.md | 10 +++++++++ kermit/k95/ckolssh.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ kermit/k95/ckonssh.c | 20 +++++++++++++++++ kermit/k95/ckossh.c | 42 +++++++++++++++++++++++++++++++++++ kermit/k95/ckossh.h | 2 ++ kermit/k95/ckuus2.c | 10 +++++++++ kermit/k95/ckuus3.c | 2 +- kermit/k95/ckuusr.c | 51 ++++++++++++++++++++++++++++++++++++++++++- kermit/k95/ckuusr.h | 4 ++++ 10 files changed, 194 insertions(+), 2 deletions(-) diff --git a/doc/changes.md b/doc/changes.md index b3edff27..336ba535 100644 --- a/doc/changes.md +++ b/doc/changes.md @@ -14,6 +14,9 @@ Nothing yet establishing a connection with `SSH ADD { local, remote }` and remove all forwards of a given type with `SSH CLEAR { local, remote }`. These commands don't yet have any effect on an already established SSH connection. +* New command to allow removing individual port forwards (`SSH REMOVE + { local, remote }`) - previously Kermit 95 only had commands to remove *all* + forwarded ports of a given type. * X11 forwarding is back. Turn on with `SET SSH X11 ON`, and set your display with `SET TELNET ENV DISPLAY` * The SSH backend has been moved into a DLL. On startup, C-Kermit attempts to diff --git a/doc/ssh-readme.md b/doc/ssh-readme.md index 7eb073bd..ed4adfa6 100644 --- a/doc/ssh-readme.md +++ b/doc/ssh-readme.md @@ -91,6 +91,16 @@ SSH LOAD filename enable all SSH commands and be used for all SSH operations until Kermit is restarted. +SSH REMOVE LOCAL-PORT-FORWARD local-port + Removes the local port forward with the specified local-port from + the local port forwarding list. This has no effect on any active + connection. + +SSH REMOVE REMOTE-PORT-FORWARD remote-port", + Removes the remote port forward with the specified remote-port from + the remote port forwarding list. This has no effect on any active + connection. + set ssh v2 key-exchange-methods {CURVE25519-SHA256, CURVE25519-SHA256@LIBSSH.ORG, DIFFIE-HELLMAN-GROUP1-SHA1, DIFFIE-HELLMAN-GROUP14-SHA1, DIFFIE-HELLMAN-GROUP14-SHA256, diff --git a/kermit/k95/ckolssh.c b/kermit/k95/ckolssh.c index c4ef2475..3287821c 100644 --- a/kermit/k95/ckolssh.c +++ b/kermit/k95/ckolssh.c @@ -794,6 +794,8 @@ int ssh_dll_init(ssh_init_parameters_t *params) { params->p_install_funcs("ssh_fwd_local_port", ssh_fwd_local_port); params->p_install_funcs("ssh_fwd_clear_remote_ports", ssh_fwd_clear_remote_ports); params->p_install_funcs("ssh_fwd_clear_local_ports", ssh_fwd_clear_local_ports); + params->p_install_funcs("ssh_fwd_remove_remote_port", ssh_fwd_remove_remote_port); + params->p_install_funcs("ssh_fwd_remove_local_port", ssh_fwd_remove_local_port); params->p_install_funcs("ssh_fwd_get_ports", ssh_fwd_get_ports); #ifdef SSHTEST params->p_install_funcs("sshkey_v1_change_comment", sshkey_v1_change_comment); /* TODO */ @@ -1987,6 +1989,56 @@ int ssh_fwd_clear_local_ports(BOOL apply) { return 0; } +static int ssh_fwd_remove_port(int type, int port, BOOL apply) { + + for (int i = 0; i < MAX_PORT_FORWARDS; i++) { + if (port_forwards[i].type == type && port_forwards[i].port == port) { + + if (apply) { + /* TODO: Also remove from the active connection (if any) */ + } + + port_forwards[i].type = SSH_PORT_FORWARD_INVALID; + port_forwards[i].port = 0; + port_forwards[i].host_port = 0; + + if (port_forwards[i].hostname != NULL) { + free(port_forwards[i].hostname); + port_forwards[i].hostname = NULL; + } + + if (port_forwards[i].address != NULL) { + free(port_forwards[i].address); + port_forwards[i].address = NULL; + } + } + } + + return 0; +} + +/** Remove a single reverse/remote port forward. + * + * @param port Reverse port forward to remove + * @param apply Also remove the port forward from any active session. Does not + * close any established connections. + * @return 0 on success + */ +int ssh_fwd_remove_remote_port(int port, BOOL apply) { + return ssh_fwd_remove_port(SSH_PORT_FORWARD_REMOTE, port, apply); +} + +/** Remove a single direct/local port forward. + * + * @param port Direct port forward to remove + * @param apply Also remove the port forward from any active session. Does not + * close any established connections. + * @return 0 on success + */ +int ssh_fwd_remove_local_port(int port, BOOL apply) { + return ssh_fwd_remove_port(SSH_PORT_FORWARD_LOCAL, port, apply); +} + /** Gets all forwarded ports. The final entry in the list has a type of * SSH_PORT_FORWARD_NULL. * diff --git a/kermit/k95/ckonssh.c b/kermit/k95/ckonssh.c index ee4131e5..aca68ce7 100644 --- a/kermit/k95/ckonssh.c +++ b/kermit/k95/ckonssh.c @@ -431,6 +431,8 @@ int ssh_dll_init(ssh_init_parameters_t *params) { params->p_install_funcs("ssh_fwd_local_port", ssh_fwd_local_port); params->p_install_funcs("ssh_fwd_clear_remote_ports", ssh_fwd_clear_remote_ports); params->p_install_funcs("ssh_fwd_clear_local_ports", ssh_fwd_clear_local_ports); + params->p_install_funcs("ssh_fwd_remove_remote_port", ssh_fwd_remove_remote_port); + params->p_install_funcs("ssh_fwd_remove_local_port", ssh_fwd_remove_local_port); params->p_install_funcs("ssh_fwd_get_ports", ssh_fwd_get_ports); #ifdef SSHTEST params->p_install_funcs("sshkey_v1_change_comment", sshkey_v1_change_comment); @@ -921,6 +923,24 @@ int ssh_fwd_clear_local_ports(BOOL apply) { return 0; } +/** Remove a single reverse/remote port forward. + * + * @param port Reverse port forward to remove + * @param apply Also remove the port forward from any active session. Does not + * close any established connections. + * @return 0 on success + */ +int ssh_fwd_remove_remote_port(int port, BOOL apply); + +/** Remove a single direct/local port forward. + * + * @param port Direct port forward to remove + * @param apply Also remove the port forward from any active session. Does not + * close any established connections. + * @return 0 on success + */ +int ssh_fwd_remove_local_port(int port, BOOL apply); + /** Gets all forwarded ports. The final entry in the list has a type of * SSH_PORT_FORWARD_NULL. * diff --git a/kermit/k95/ckossh.c b/kermit/k95/ckossh.c index 73197c36..34eae8ac 100644 --- a/kermit/k95/ckossh.c +++ b/kermit/k95/ckossh.c @@ -189,6 +189,8 @@ typedef int (*p_ssh_fwd_remote_port_t)(char*, int, char *, int, BOOL); typedef int (*p_ssh_fwd_local_port_t)(char*, int,char *,int, BOOL); typedef int (*p_ssh_fwd_clear_local_ports_t)(BOOL); typedef int (*p_ssh_fwd_clear_remote_ports_t)(BOOL); +typedef int (*p_ssh_fwd_remove_remote_port_t)(int, BOOL); +typedef int (*p_ssh_fwd_remove_local_port_t)(int, BOOL); typedef ssh_port_forward_t* (*p_ssh_fwd_get_ports_t)(); #ifdef SSHTEST typedef int (*p_sshkey_v1_change_comment_t)(char *, char *, char *); @@ -230,6 +232,8 @@ static p_ssh_fwd_remote_port_t p_ssh_fwd_remote_port = NULL; static p_ssh_fwd_local_port_t p_ssh_fwd_local_port = NULL; static p_ssh_fwd_clear_remote_ports_t p_ssh_fwd_clear_remote_ports = NULL; static p_ssh_fwd_clear_local_ports_t p_ssh_fwd_clear_local_ports = NULL; +static p_ssh_fwd_remove_remote_port_t p_ssh_fwd_remove_remote_port = NULL; +static p_ssh_fwd_remove_local_port_t p_ssh_fwd_remove_local_port = NULL; static p_ssh_fwd_get_ports_t p_ssh_fwd_get_ports = NULL; #ifdef SSHTEST static p_sshkey_v1_change_comment_t p_sshkey_v1_change_comment = NULL; /* TODO */ @@ -323,6 +327,10 @@ void ssh_install_func(const char* function, const void* p_function) { p_ssh_fwd_clear_remote_ports = F_CAST(p_ssh_fwd_clear_remote_ports_t) p_function; else if ( !strcmp(function,"ssh_fwd_clear_local_ports") ) p_ssh_fwd_clear_local_ports = F_CAST(p_ssh_fwd_clear_local_ports_t) p_function; + else if ( !strcmp(function,"ssh_fwd_remove_remote_port") ) + p_ssh_fwd_remove_remote_port = F_CAST(p_ssh_fwd_remove_remote_port_t) p_function; + else if ( !strcmp(function,"ssh_fwd_remove_local_port") ) + p_ssh_fwd_remove_local_port = F_CAST(p_ssh_fwd_remove_local_port_t) p_function; else if ( !strcmp(function,"ssh_fwd_get_ports") ) p_ssh_fwd_get_ports = F_CAST(p_ssh_fwd_get_ports_t) p_function; #ifdef SSHTEST @@ -494,6 +502,8 @@ int ssh_dll_unload(int quiet) { p_ssh_fwd_local_port = NULL; p_ssh_fwd_clear_remote_ports = NULL; p_ssh_fwd_clear_local_ports = NULL; + p_ssh_fwd_remove_remote_port = NULL; + p_ssh_fwd_remove_local_port = NULL; p_ssh_fwd_get_ports = NULL; #ifdef SSHTEST p_sshkey_v1_change_comment = NULL; /* TODO */ @@ -893,6 +903,38 @@ int ssh_fwd_clear_local_ports(BOOL apply) { return -1; } + /** Remove a single reverse/remote port forward. + * + * @param port Reverse port forward to remove + * @param apply Also remove the port forward from any active session. Does not + * close any established connections. + * @return 0 on success + */ +int ssh_fwd_remove_remote_port(int port, BOOL apply) { + if (p_ssh_fwd_remove_remote_port) + return p_ssh_fwd_remove_remote_port(port, apply); + + /* optional feature not available */ + + return -1; +} + +/** Remove a single direct/local port forward. + * + * @param port Direct port forward to remove + * @param apply Also remove the port forward from any active session. Does not + * close any established connections. + * @return 0 on success + */ +int ssh_fwd_remove_local_port(int port, BOOL apply) { + if (p_ssh_fwd_remove_local_port) + return p_ssh_fwd_remove_local_port(port, apply); + + /* optional feature not available */ + + return -1; +} + /** Gets all forwarded ports. The final entry in the list has a type of * SSH_PORT_FORWARD_NULL. * diff --git a/kermit/k95/ckossh.h b/kermit/k95/ckossh.h index 596a25b0..952d425b 100644 --- a/kermit/k95/ckossh.h +++ b/kermit/k95/ckossh.h @@ -131,6 +131,8 @@ _PROTOTYP(int ssh_fwd_remote_port, (char* address, int port, char * host, int ho _PROTOTYP(int ssh_fwd_local_port,(char* address, int port,char * host, int host_port, BOOL apply)); _PROTOTYP(int ssh_fwd_clear_remote_ports,(BOOL apply)); _PROTOTYP(int ssh_fwd_clear_local_ports,(BOOL apply)); +_PROTOTYP(int ssh_fwd_remove_remote_port,(int port, BOOL apply)); +_PROTOTYP(int ssh_fwd_remove_local_port,(int port, BOOL apply)); _PROTOTYP(const ssh_port_forward_t* ssh_fwd_get_ports,()); #ifdef SSHTEST diff --git a/kermit/k95/ckuus2.c b/kermit/k95/ckuus2.c index f632e9e5..57ae4981 100644 --- a/kermit/k95/ckuus2.c +++ b/kermit/k95/ckuus2.c @@ -908,6 +908,16 @@ static char * hmxxssh[] = { " An example of a /COMMAND to execute C-Kermit in SERVER mode is:", " SSH OPEN hostname /COMMAND:{kermit -x -l 0}", " ", +"SSH REMOVE LOCAL-PORT-FORWARD local-port", +" Removes the local port forward with the specified local-port from", +" the local port forwarding list. This has no effect on any active ", +" connection.", +" ", +"SSH REMOVE REMOTE-PORT-FORWARD remote-port", +" Removes the remote port forward with the specified remote-port from", +" the remote port forwarding list. This has no effect on any active ", +" connection.", +" ", #ifdef COMMENT "SSH V2 REKEY", " Requests that an existing SSH V2 connection generate new session keys.", diff --git a/kermit/k95/ckuus3.c b/kermit/k95/ckuus3.c index a8ebb469..d87b7a73 100644 --- a/kermit/k95/ckuus3.c +++ b/kermit/k95/ckuus3.c @@ -8246,7 +8246,7 @@ shossh() { ); } if (ssh_feature_supported(SSH_FEAT_X11_FWD)) { - extern char* tn_env_disp; /* ckctel.c */ + extern char tn_env_disp[64]; /* ckctel.c */ printf(" ssh x11-forwarding: %s\n",showooa(ssh_get_iparam(SSH_IPARAM_XFW))); printf(" ssh x11-forwarding display: %s\n",showstring(tn_env_disp)); /* TODO: Show the display - tn_env_disp */ diff --git a/kermit/k95/ckuusr.c b/kermit/k95/ckuusr.c index 5729a613..f03a41be 100644 --- a/kermit/k95/ckuusr.c +++ b/kermit/k95/ckuusr.c @@ -2416,6 +2416,13 @@ static struct keytab sshclr[] = { }; static int nsshclr = (sizeof(sshclr) / sizeof(struct keytab)) - 1; +static struct keytab sshrem[] = { + { "local-port-forward", SSHR_LPF, 0 }, + { "remote-port-forward", SSHR_RPF, 0 }, + { "", 0, 0 } +}; +static int nsshrem = (sizeof(sshrem) / sizeof(struct keytab)) - 1; + struct keytab sshopnsw[] = { { "/command", SSHSW_CMD, CM_ARG }, { "/password", SSHSW_PWD, CM_ARG }, @@ -2436,6 +2443,7 @@ static struct keytab sshkwtab[] = { { "key", XSSH_KEY, 0 }, /* SSH_FEAT_KEY_MGMT */ { "load", XSSH_LOAD, CM_INV }, { "open", XSSH_OPN, 0 }, + { "remove", XSSH_REM, 0 }, /* SSH_FEAT_PORT_FWD */ { "v2", XSSH_V2, 0 }, /* SSH_FEAT_REKEY_MANUAL */ { "", 0, 0 } }; @@ -10844,7 +10852,8 @@ necessary DLLs did not load. Use SHOW NETWORK to check network status.\n"); * backend */ for (z = 0; z < nsshcmd; z++) { if ((sshkwtab[z].kwval == XSSH_ADD || sshkwtab[z].kwval == XSSH_CLR - || sshkwtab[z].kwval == XSSH_FLP || sshkwtab[z].kwval == XSSH_FRP) + || sshkwtab[z].kwval == XSSH_FLP || sshkwtab[z].kwval == XSSH_FRP + || sshkwtab[z].kwval == XSSH_REM) && !ssh_feature_supported(SSH_FEAT_PORT_FWD)) { /* Port forwarding * "ssh add" - adds port fowards @@ -11290,6 +11299,46 @@ necessary DLLs did not load. Use SHOW NETWORK to check network status.\n"); return(-2); } return(success = 1); /* or whatever */ + } + case XSSH_REM: { + int port; + + if (!ssh_feature_supported(SSH_FEAT_PORT_FWD)) { + printf("\r\nPort forwarding is not supported by the current SSH backend\r\n"); + return(-9); + } + if ((y = cmkey(sshrem,nsshrem,"","", xxstring)) < 0) { + if (y == -3) { + printf("?remove what?\n"); + return(-9); + } + return(y); + } + + if ((x = cmnum((cx == SSHR_LPF) ? + "Local port number" : "Remote port number", + "",10,&port,xxstring)) < 0) { + return(x); + } + + /* TODO: A switch to apply these changes to any active connection + * rather than only affecting future connections + */ + + if ((x = cmcfm()) < 0) { + return(x); + } + switch (y) { + case SSHR_LPF: + ssh_fwd_remove_local_port(port, FALSE); + break; + case SSHR_RPF: + ssh_fwd_remove_remote_port(port, FALSE); + break; + default: + return(-2); + } + return(success = 1); /* or whatever */ } case XSSH_AGT: { /* SSH AGENT */ int doeach = 0; diff --git a/kermit/k95/ckuusr.h b/kermit/k95/ckuusr.h index bb963f66..2cff5ad6 100644 --- a/kermit/k95/ckuusr.h +++ b/kermit/k95/ckuusr.h @@ -2722,6 +2722,7 @@ struct stringint { /* String and (wide) integer */ #define XSSH_CLR 7 #define XSSH_AGT 8 #define XSSH_LOAD 9 +#define XSSH_REM 10 #ifdef COMMENT #define SSHKT_1R 0 /* SSH KEY TYPE symbols */ @@ -2766,6 +2767,9 @@ struct stringint { /* String and (wide) integer */ #define SSHC_LPF 1 #define SSHC_RPF 2 +#define SSHR_LPF 1 +#define SSHR_RPF 2 + #define XSSH2_RKE 1 #define SSHF_LCL 1