-
-
Notifications
You must be signed in to change notification settings - Fork 174
/
SshSetupHandler.cpp
149 lines (129 loc) · 5.07 KB
/
SshSetupHandler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "SshSetupHandler.hpp"
#include "SubprocessToString.hpp"
namespace et {
const string SshSetupHandler::ETTERMINAL_BIN = "etterminal";
string genCommand(const string& passkey, const string& id,
const string& clientTerm, const string& user, bool kill,
const string& etterminal_path, const string& options) {
string ssh_script_prefix;
string etterminal_bin = etterminal_path.empty()
? SshSetupHandler::ETTERMINAL_BIN
: etterminal_path;
string command = "echo '" + id + "/" + passkey + "_" + clientTerm + "' | " +
etterminal_bin + " " + options;
// Kill old ET sessions of the user
if (kill) {
ssh_script_prefix =
"pkill etterminal -u " + user + "; sleep 0.5; " + ssh_script_prefix;
}
return ssh_script_prefix + command;
}
string SshSetupHandler::SetupSsh(const string& user, const string& host,
const string& host_alias, int port,
const string& jumphost,
const string& jServerFifo, bool kill,
int vlevel, const string& cmd_prefix,
const string& serverFifo,
const std::vector<std::string>& ssh_options) {
string clientTerm("xterm-256color");
auto envString = getenv("TERM");
if (envString != NULL) {
// Default to xterm-256color
clientTerm = envString;
}
string passkey = genRandomAlphaNum(32);
string id = genRandomAlphaNum(16);
id[0] = id[1] = id[2] = 'X'; // For compatibility with old servers that do
// not generate their own keys
string cmdoptions{"--verbose=" + std::to_string(vlevel)};
if (!serverFifo.empty()) {
cmdoptions += " --serverfifo=" + serverFifo;
}
string SSH_SCRIPT_DST =
genCommand(passkey, id, clientTerm, user, kill, cmd_prefix, cmdoptions);
string SSH_USER_PREFIX = "";
if (!user.empty()) {
SSH_USER_PREFIX += user + "@";
}
std::vector<std::string> ssh_args;
if (!jumphost.empty()) {
ssh_args = {
"-J",
jumphost,
};
}
ssh_args.push_back(SSH_USER_PREFIX + host_alias);
for (auto& arg : ssh_options) {
ssh_args.push_back("-o" + arg);
}
ssh_args.push_back(SSH_SCRIPT_DST);
std::string ssh_concat;
for (const auto& piece : ssh_args) ssh_concat += piece + " ";
VLOG(1) << "Trying ssh with args: " << ssh_concat << endl;
auto sshBuffer = SubprocessToStringInteractive("ssh", ssh_args);
try {
if (sshBuffer.length() <= 0) {
// Ssh failed
CLOG(INFO, "stdout")
<< "Error starting ET process through ssh, please make sure your "
"ssh works first"
<< endl;
exit(1);
}
auto passKeyIndex = sshBuffer.find(string("IDPASSKEY:"));
if (passKeyIndex == string::npos) {
// Returned value not contain "IDPASSKEY:"
CLOG(INFO, "stdout")
<< "Error in authentication with etserver: " << sshBuffer
<< ", please make sure you don't print anything in server's "
".bashrc/.zshrc"
<< endl;
exit(1);
}
auto idpasskey = sshBuffer.substr(passKeyIndex + 10, 16 + 1 + 32);
auto idpasskey_splited = split(idpasskey, '/');
id = idpasskey_splited[0];
passkey = idpasskey_splited[1];
LOG(INFO) << "etserver started";
} catch (const runtime_error& err) {
CLOG(INFO, "stdout") << "Error initializing connection" << err.what()
<< endl;
}
// start jumpclient daemon on jumphost.
if (!jumphost.empty()) {
/* If jumphost is set, we need to pass dst host and port to jumphost
* and connect to jumphost here */
string jump_cmdoptions{"--verbose=" + std::to_string(vlevel)};
if (!jServerFifo.empty()) {
jump_cmdoptions += " --serverfifo=" + jServerFifo;
}
jump_cmdoptions = jump_cmdoptions + " --jump --dsthost=" + host +
" --dstport=" + to_string(port);
string SSH_SCRIPT_JUMP = genCommand(passkey, id, clientTerm, user, kill,
cmd_prefix, jump_cmdoptions);
string sshLinkBuffer =
SubprocessToStringInteractive("ssh", {jumphost, SSH_SCRIPT_JUMP});
if (sshLinkBuffer.length() <= 0) {
// At this point "ssh -J jumphost dst" already works.
CLOG(INFO, "stdout") << "etserver jumpclient failed to start" << endl;
exit(1);
}
try {
auto idpasskey = split(sshLinkBuffer, ':')[1];
idpasskey.erase(idpasskey.find_last_not_of(" \n\r\t") + 1);
idpasskey = idpasskey.substr(0, 16 + 1 + 32);
auto idpasskey_splited = split(idpasskey, '/');
id = idpasskey_splited[0];
passkey = idpasskey_splited[1];
} catch (const runtime_error& err) {
CLOG(INFO, "stdout") << "Error initializing connection" << err.what()
<< endl;
}
}
if (id.length() == 0 || passkey.length() == 0) {
STFATAL << "Somehow missing id or passkey: " << id.length() << " "
<< passkey.length();
}
return id + "/" + passkey;
}
} // namespace et