99#include < fstream>
1010#include < iostream>
1111#include < string>
12+ #include < utility>
13+ #include < vector>
1214
1315/* This is needed for a standard getpwuid_r on opensolaris */
1416#define _POSIX_PTHREAD_SEMANTICS
@@ -84,6 +86,7 @@ enum ssh_config_opcode_e {
8486 SOC_PROXYJUMP,
8587 SOC_FORWARDAGENT,
8688 SOC_IDENTITYAGENT,
89+ SOC_LOCALFORWARD,
8790 SOC_END /* Keep this one last in the list */
8891};
8992
@@ -121,7 +124,8 @@ enum ssh_options_e {
121124 SSH_OPTIONS_HMAC_S_C,
122125 SSH_OPTIONS_PROXYJUMP,
123126 SSH_OPTIONS_FORWARDAGENT,
124- SSH_OPTIONS_IDENTITYAGENT
127+ SSH_OPTIONS_IDENTITYAGENT,
128+ SSH_OPTIONS_LOCALFORWARD
125129};
126130
127131struct Options {
@@ -141,6 +145,7 @@ struct Options {
141145 int gss_delegate_creds;
142146 int forward_agent;
143147 char *identity_agent;
148+ vector<pair<int , int >> local_forwards;
144149};
145150
146151struct ssh_config_keyword_table_s {
@@ -166,6 +171,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
166171 {" proxyjump" , SOC_PROXYJUMP},
167172 {" forwardagent" , SOC_FORWARDAGENT},
168173 {" identityagent" , SOC_IDENTITYAGENT},
174+ {" localforward" , SOC_LOCALFORWARD},
169175 {NULL , SOC_UNSUPPORTED}};
170176
171177static enum ssh_config_opcode_e ssh_config_get_opcode (char *keyword) {
@@ -1036,6 +1042,36 @@ int ssh_options_set(struct Options *options, enum ssh_options_e type,
10361042 }
10371043 }
10381044 break ;
1045+ case SSH_OPTIONS_LOCALFORWARD:
1046+ v = static_cast <const char *>(value);
1047+ if (v == NULL || v[0 ] == ' \0 ' ) {
1048+ CLOG (INFO, " stdout" ) << " invalid error" << endl;
1049+ return -1 ;
1050+ } else {
1051+ char *forward_entry = strdup (v);
1052+ if (forward_entry == NULL ) {
1053+ CLOG (INFO, " stdout" ) << " error" << endl;
1054+ return -1 ;
1055+ }
1056+
1057+ // Format is [bind_address:]port host:hostport
1058+ char *local_port_str = strtok (forward_entry, " " );
1059+ char *remote_part = strtok (NULL , " " );
1060+
1061+ // TODO: Support bind_address before the local port.
1062+ if (local_port_str && remote_part) {
1063+ int local_port = atoi (local_port_str);
1064+ char *colon_pos = strrchr (remote_part, ' :' );
1065+ if (colon_pos) {
1066+ int remote_port = atoi (colon_pos + 1 );
1067+ options->local_forwards .push_back (
1068+ make_pair (local_port, remote_port));
1069+ }
1070+ }
1071+
1072+ SAFE_FREE (forward_entry);
1073+ }
1074+ break ;
10391075
10401076 default :
10411077 CLOG (INFO, " stdout" ) << " Unknown ssh option" << endl;
@@ -1233,7 +1269,8 @@ static int ssh_config_parse_line(const char *targethost,
12331269
12341270 opcode = ssh_config_get_opcode (keyword);
12351271 if (*parsing == 1 && opcode != SOC_HOST && opcode != SOC_MATCH &&
1236- opcode != SOC_UNSUPPORTED && opcode != SOC_INCLUDE) {
1272+ opcode != SOC_UNSUPPORTED && opcode != SOC_INCLUDE &&
1273+ opcode != SOC_LOCALFORWARD) {
12371274 if (seen[opcode] != 0 ) {
12381275 SAFE_FREE (x);
12391276 return 0 ;
@@ -1401,6 +1438,17 @@ static int ssh_config_parse_line(const char *targethost,
14011438 SAFE_FREE (filename);
14021439 }
14031440 break ;
1441+ case SOC_LOCALFORWARD:
1442+ p = ssh_config_get_str_tok (&s, NULL );
1443+ if (p && *parsing) {
1444+ const char *remote_part = ssh_config_get_str_tok (&s, NULL );
1445+ if (remote_part) {
1446+ char forward_str[1024 ];
1447+ snprintf (forward_str, sizeof (forward_str), " %s %s" , p, remote_part);
1448+ ssh_options_set (options, SSH_OPTIONS_LOCALFORWARD, forward_str);
1449+ }
1450+ }
1451+ break ;
14041452 case SOC_UNSUPPORTED:
14051453 LOG (INFO) << " unsupported config line: " << string (line) << " , ignored" ;
14061454 break ;
0 commit comments