Skip to content

Commit 3d64ea9

Browse files
authored
Merge pull request #546 from elfmz/custom-sftp-subsystem
Custom sftp subsystem
2 parents 5ddb326 + c7698a2 commit 3d64ea9

File tree

9 files changed

+105
-21
lines changed

9 files changed

+105
-21
lines changed

NetRocks/configs/plug/eng.lng

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167

168168
"SFTP protocol options"
169169
"Private &key file path:"
170+
"Custom &subsystem request/exec:"
170171
"Max &read block size, bytes:"
171172
"Max &write block size, bytes:"
172173
"Enable &TCP_NODELAY option"

NetRocks/configs/plug/rus.lng

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167

168168
"Настройки протокола SFTP"
169169
"Путь к файлу приватного &ключа:"
170+
"Запрос особой подсистемы:"
170171
"Размер блока чтения, байт:"
171172
"Размер блока записи, байт:"
172173
"Включить опцию &TCP_NODELAY"

NetRocks/src/NetRocks.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ SHAREDSYMBOL int WINAPI _export PutFilesW(HANDLE hPlugin,struct PluginPanelItem
134134

135135
SHAREDSYMBOL int WINAPI _export MakeDirectoryW(HANDLE hPlugin, const wchar_t **Name, int OpMode)
136136
{
137-
return ((PluginImpl *)hPlugin)->MakeDirectory(Name ? *Name : nullptr, OpMode);
137+
return ((PluginImpl *)hPlugin)->MakeDirectory(Name, OpMode);
138138
}
139139

140140
SHAREDSYMBOL int WINAPI ProcessEventW(HANDLE hPlugin, int Event, void * Param)

NetRocks/src/Op/OpMakeDirectory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ class OpMakeDirectory : protected OpBase
1010
public:
1111
OpMakeDirectory(int op_mode, std::shared_ptr<IHost> &base_host, const std::string &base_dir, const std::string &dir_name);
1212
bool Do();
13+
const std::string &DirName() const { return _dir_name; }
1314
};

NetRocks/src/PluginImpl.cpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -456,22 +456,34 @@ int PluginImpl::DeleteFiles(struct PluginPanelItem *PanelItem, int ItemsNumber,
456456
return OpRemove(OpMode, _remote, CurrentSiteDir(true), PanelItem, ItemsNumber).Do() ? TRUE : FALSE;
457457
}
458458

459-
int PluginImpl::MakeDirectory(const wchar_t *Name, int OpMode)
459+
int PluginImpl::MakeDirectory(const wchar_t **Name, int OpMode)
460460
{
461-
fprintf(stderr, "NetRocks::MakeDirectory('%ls', 0x%x)\n", Name, OpMode);
461+
fprintf(stderr, "NetRocks::MakeDirectory('%ls', 0x%x)\n", Name ? *Name : L"NULL", OpMode);
462462
if (!_remote) {
463463
return FALSE;
464464
}
465-
if (_cur_dir[0]) {
466-
std::string tmp;
467-
if (Name) {
468-
Wide2MB(Name, tmp);
469-
}
470-
return OpMakeDirectory(OpMode, _remote, CurrentSiteDir(true), Name ? tmp.c_str() : nullptr).Do();
471-
} else {
472-
;//todo
465+
if (!_cur_dir[0]) {
466+
// todo: create virtual dir in sites list
467+
return FALSE;
473468
}
474-
return FALSE;
469+
470+
std::string tmp;
471+
if (Name && *Name) {
472+
Wide2MB(*Name, tmp);
473+
}
474+
OpMakeDirectory op(OpMode, _remote, CurrentSiteDir(true), Name ? tmp.c_str() : nullptr);
475+
if (!op.Do()) {
476+
return FALSE;
477+
}
478+
if (Name && !IS_SILENT(OpMode)) {
479+
tmp = op.DirName();
480+
const std::wstring name_w = StrMB2Wide(tmp);
481+
wcsncpy(_mk_dir, name_w.c_str(), ARRAYSIZE(_mk_dir) - 1);
482+
_mk_dir[ARRAYSIZE(_mk_dir) - 1] = 0;
483+
*Name = _mk_dir;
484+
}
485+
486+
return TRUE;;
475487
}
476488

477489
int PluginImpl::ProcessKey(int Key, unsigned int ControlState)

NetRocks/src/PluginImpl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class PluginImpl
1010
{
1111
friend class AllNetRocks;
1212

13-
wchar_t _panel_title[64], _cur_dir[MAX_PATH];
13+
wchar_t _panel_title[64], _cur_dir[MAX_PATH], _mk_dir[MAX_PATH];
1414
bool _cur_dir_absolute = false;
1515
std::vector<std::wstring> _dir_stack;
1616

@@ -40,7 +40,7 @@ class PluginImpl
4040
int DeleteFiles(struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode);
4141
int GetFiles(struct PluginPanelItem *PanelItem, int ItemsNumber, int Move, const wchar_t *DestPath, int OpMode);
4242
int PutFiles(struct PluginPanelItem *PanelItem, int ItemsNumber, int Move, const wchar_t *SrcPath, int OpMode);
43-
int MakeDirectory(const wchar_t *Name, int OpMode);
43+
int MakeDirectory(const wchar_t **Name, int OpMode);
4444
int ProcessKey(int Key, unsigned int ControlState);
4545
int ProcessEventCommand(const wchar_t *cmd);
4646
};

NetRocks/src/Protocol/ProtocolSFTP.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,44 @@ ProtocolSFTP::ProtocolSFTP(const std::string &host, unsigned int port,
274274
throw ProtocolAuthFailedError();//"Authentification failed", ssh_get_error(_conn->ssh), rc);
275275
}
276276

277-
_conn->sftp = sftp_new(_conn->ssh);
277+
const std::string &subsystem = protocol_options.GetString("CustomSubsystem");
278+
if (!subsystem.empty() && protocol_options.GetInt("UseCustomSubsystem", 0) != 0) {
279+
ssh_channel channel = ssh_channel_new(_conn->ssh);
280+
if (channel == nullptr)
281+
throw ProtocolError("SSH channel new", ssh_get_error(_conn->ssh));
282+
283+
int rc = ssh_channel_open_session(channel);
284+
if (rc != SSH_OK) {
285+
ssh_channel_free(channel);
286+
throw ProtocolError("SFTP channel open", ssh_get_error(_conn->ssh));
287+
}
288+
if (subsystem.find('/') == std::string::npos) {
289+
rc = ssh_channel_request_subsystem(channel, subsystem.c_str());
290+
} else {
291+
rc = ssh_channel_request_exec(channel, subsystem.c_str());
292+
}
293+
294+
if (rc != SSH_OK) {
295+
ssh_channel_free(channel);
296+
throw ProtocolError("SFTP custom subsystem", ssh_get_error(_conn->ssh));
297+
}
298+
299+
_conn->sftp = sftp_new_channel(_conn->ssh, channel);
300+
if (!_conn->sftp) {
301+
ssh_channel_free(channel);
302+
throw ProtocolError("SFTP channel", ssh_get_error(_conn->ssh));
303+
}
304+
305+
#if (LIBSSH_VERSION_INT >= SSH_VERSION_INT(0, 8, 3))
306+
if (!_conn->sftp->read_packet) {
307+
_conn->sftp->read_packet = (struct sftp_packet_struct *)calloc(1, sizeof(struct sftp_packet_struct));
308+
_conn->sftp->read_packet->payload = ssh_buffer_new();
309+
}
310+
#endif
311+
} else {
312+
_conn->sftp = sftp_new(_conn->ssh);
313+
}
314+
278315
if (_conn->sftp == nullptr)
279316
throw ProtocolError("SFTP session", ssh_get_error(_conn->ssh));
280317

NetRocks/src/UI/Settings/ConfigureProtocolSFTP.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
================ SFTP Protocol options =====================
1212
| [ ] Private key file path: |
1313
| [EDIT....................................................] |
14+
| [ ] Custom subsystem request: |
15+
| [EDIT....................................................] |
1416
| Max read block size, bytes: [9999999] |
1517
| Max write block size, bytes: [9999999] |
1618
| [ ] Enable TCP_NODELAY option |
@@ -26,15 +28,16 @@ class ProtocolOptionsSFTP : protected BaseDialog
2628
{
2729
int _i_ok = -1, _i_cancel = -1;
2830
int _i_privkey_enable = -1, _i_privkey_path = -1;
31+
int _i_use_custom_subsystem = -1, _i_custom_subsystem = -1;
2932
int _i_max_read_block_size = -1, _i_max_write_block_size = -1;
3033
int _i_tcp_nodelay = -1, _i_tcp_quickack = -1;
3134
//int _i_enable_sandbox = -1;
3235

33-
bool _keypath_enabled = true, _ok_enabled = true;
36+
bool _keypath_enabled = true, _subsystem_enabled = true, _ok_enabled = true;
3437

3538
void UpdateEnableds(bool due_privkey_enable_clicked)
3639
{
37-
bool ok_enabled = true, keypath_enabled = false;
40+
bool ok_enabled = true, keypath_enabled = false, subsystem_enabled = false;
3841
if (IsCheckedDialogControl(_i_privkey_enable)) {
3942
ok_enabled = false;
4043
keypath_enabled = true;
@@ -54,6 +57,16 @@ class ProtocolOptionsSFTP : protected BaseDialog
5457
}
5558
}
5659

60+
subsystem_enabled = IsCheckedDialogControl(_i_use_custom_subsystem);
61+
62+
if (ok_enabled && subsystem_enabled) {
63+
std::string str;
64+
TextFromDialogControl(_i_privkey_path, str);
65+
if (str.empty()) {
66+
ok_enabled = false;
67+
}
68+
}
69+
5770
if (ok_enabled != _ok_enabled) {
5871
_ok_enabled = ok_enabled;
5972
SetEnabledDialogControl(_i_ok, ok_enabled);
@@ -63,6 +76,12 @@ class ProtocolOptionsSFTP : protected BaseDialog
6376
_keypath_enabled = keypath_enabled;
6477
SetEnabledDialogControl(_i_privkey_path, keypath_enabled);
6578
}
79+
80+
if (subsystem_enabled != _subsystem_enabled) {
81+
_subsystem_enabled= subsystem_enabled;
82+
SetEnabledDialogControl(_i_custom_subsystem, subsystem_enabled);
83+
}
84+
6685
}
6786

6887
LONG_PTR DlgProc(int msg, int param1, LONG_PTR param2)
@@ -74,8 +93,8 @@ class ProtocolOptionsSFTP : protected BaseDialog
7493
#endif
7594

7695
if ( msg == DN_INITDIALOG
77-
|| (msg == DN_BTNCLICK && param1 == _i_privkey_enable)
78-
|| (msg == DN_EDITCHANGE && param1 == _i_privkey_path) ) {
96+
|| (msg == DN_BTNCLICK && (param1 == _i_privkey_enable || param1 == _i_use_custom_subsystem))
97+
|| (msg == DN_EDITCHANGE && (param1 == _i_privkey_path || param1 == _i_custom_subsystem)) ) {
7998
UpdateEnableds(msg == DN_BTNCLICK && param1 == _i_privkey_enable);
8099
}
81100

@@ -85,12 +104,19 @@ class ProtocolOptionsSFTP : protected BaseDialog
85104
public:
86105
ProtocolOptionsSFTP()
87106
{
88-
_di.Add(DI_DOUBLEBOX, 3,1,64,10, 0, MSFTPOptionsTitle);
107+
_di.Add(DI_DOUBLEBOX, 3,1,64,12, 0, MSFTPOptionsTitle);
108+
89109
_di.SetLine(2);
90110
_i_privkey_enable = _di.AddAtLine(DI_CHECKBOX, 5,62, 0, MSFTPPrivateKeyPath);
91111
_di.NextLine();
92112
_i_privkey_path = _di.AddAtLine(DI_EDIT, 5,62, 0, "");
93113

114+
_di.NextLine();
115+
_i_use_custom_subsystem = _di.AddAtLine(DI_CHECKBOX, 5,62, 0, MSFTPCustomSubsystem);
116+
_di.NextLine();
117+
_i_custom_subsystem = _di.AddAtLine(DI_EDIT, 5,62, 0, "");
118+
119+
94120
_di.NextLine();
95121
_di.AddAtLine(DI_TEXT, 5,50, 0, MSFTPMaxReadBlockSize);
96122
_i_max_read_block_size = _di.AddAtLine(DI_FIXEDIT, 51,60, DIF_MASKEDIT, "32768", "9999999999");
@@ -129,7 +155,8 @@ class ProtocolOptionsSFTP : protected BaseDialog
129155
LongLongToDialogControl(_i_max_write_block_size, std::max((int)512, sc.GetInt("MaxWriteBlock", 32768)));
130156
SetCheckedDialogControl(_i_tcp_nodelay, sc.GetInt("TcpNoDelay", 0) != 0);
131157
SetCheckedDialogControl(_i_tcp_quickack, sc.GetInt("TcpQuickAck", 0) != 0);
132-
158+
SetCheckedDialogControl(_i_use_custom_subsystem, sc.GetInt("UseCustomSubsystem", 0) != 0);
159+
TextToDialogControl(_i_custom_subsystem, sc.GetString("CustomSubsystem"));
133160
// SetCheckedDialogControl(_i_enable_sandbox, sc.GetInt("Sandbox", 0) != 0);
134161
if (Show(L"ProtocolOptionsSFTP", 6, 2) == _i_ok) {
135162
sc.SetInt("PrivKeyEnable", IsCheckedDialogControl(_i_privkey_enable) ? 1 : 0);
@@ -140,6 +167,10 @@ class ProtocolOptionsSFTP : protected BaseDialog
140167
sc.SetInt("MaxWriteBlock", std::max((int)512, (int)LongLongFromDialogControl(_i_max_write_block_size)));
141168
sc.SetInt("TcpNoDelay", IsCheckedDialogControl(_i_tcp_nodelay) ? 1 : 0);
142169
sc.SetInt("TcpQuickAck", IsCheckedDialogControl(_i_tcp_quickack) ? 1 : 0);
170+
sc.SetInt("UseCustomSubsystem", IsCheckedDialogControl(_i_use_custom_subsystem) ? 1 : 0);
171+
TextFromDialogControl(_i_custom_subsystem, str);
172+
sc.SetString("CustomSubsystem", str);
173+
143174
// sc.SetInt("Sandbox", IsCheckedDialogControl(_i_enable_sandbox) ? 1 : 0);
144175
options = sc.Serialize();
145176
}

NetRocks/src/lng.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ enum LanguageID
170170

171171
MSFTPOptionsTitle,
172172
MSFTPPrivateKeyPath,
173+
MSFTPCustomSubsystem,
173174
MSFTPMaxReadBlockSize,
174175
MSFTPMaxWriteBlockSize,
175176
MSFTPTCPNodelay,

0 commit comments

Comments
 (0)