Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add motw to scp and sftp #614

Merged
merged 17 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions contrib/win32/win32compat/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "inc\string.h"
#include "inc\time.h"
#include "..\..\..\atomicio.h"
#include "urlmon.h"

#include <wchar.h>

Expand Down Expand Up @@ -136,6 +137,9 @@ int chroot_path_len = 0;
/* UTF-16 version of the above */
wchar_t* chroot_pathw = NULL;

/* motw zone_id initialized to invalid value */
DWORD motw_zone_id = 5;

int
usleep(unsigned int useconds)
{
Expand Down Expand Up @@ -2136,7 +2140,18 @@ add_mark_of_web(const char* filename)
sprintf_s(fileStreamPath, fileStreamPathLen, "%s:Zone.Identifier", filename);

// ZoneId=3 indicates the file comes from the Internet Zone
const char zoneIdentifier[] = "[ZoneTransfer]\nZoneId=3";
// const char zoneIdentifier[] = "[ZoneTransfer]\nZoneId=3";
tgauth marked this conversation as resolved.
Show resolved Hide resolved
char* zoneIdentifierStr = NULL;
size_t zoneIndentifierLen = strlen("[ZoneTransfer]\nZoneId=") + 1 + 1;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a typo in zoneIndentifierLen, it should be zoneIdentifierLen.


zoneIdentifierStr = malloc(zoneIndentifierLen * sizeof(char));

if (zoneIdentifierStr == NULL) {
return -1;
}

sprintf_s(zoneIdentifierStr, zoneIndentifierLen, "[ZoneTransfer]\nZoneId=%d", motw_zone_id);

int ofd, status = 0;

// create zone identifer file stream and then write the Mark of the Web to it
Expand All @@ -2145,9 +2160,9 @@ add_mark_of_web(const char* filename)
goto cleanup;
}

size_t zoneIndentifierLen = strlen(zoneIdentifier);
// size_t zoneIndentifierLen = strlen(zoneIdentifier);
tgauth marked this conversation as resolved.
Show resolved Hide resolved

if (atomicio(vwrite, ofd, zoneIdentifier, zoneIndentifierLen) != zoneIndentifierLen) {
if (atomicio(vwrite, ofd, zoneIdentifierStr, zoneIndentifierLen) != zoneIndentifierLen) {
status = -1;
}

Expand All @@ -2160,3 +2175,42 @@ add_mark_of_web(const char* filename)
return status;
}

void get_zone_identifier(const char* hostname) {
tgauth marked this conversation as resolved.
Show resolved Hide resolved
static const CLSID CLSID_ISM =
{ 0x7B8A2D94, 0x0AC9, 0x11D1,
{ 0x89, 0x6C, 0x00, 0xC0, 0x4F, 0xB6, 0xBF, 0xC4 } };
static const IID IID_IISM =
{ 0x79EAC9EE, 0xBAF9, 0x11CE,
{ 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B } };
IInternetSecurityManager* IISM;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(&CLSID_ISM, NULL,
CLSCTX_ALL, &IID_IISM, (void**)&IISM);
if (SUCCEEDED(hr) || hr == RPC_E_CHANGED_MODE)
tgauth marked this conversation as resolved.
Show resolved Hide resolved
{
wchar_t* hostname_w = utf8_to_utf16(hostname);
tgauth marked this conversation as resolved.
Show resolved Hide resolved
size_t inputStrLen = wcslen(hostname_w) + wcslen(L"ftp://") + 2;
tgauth marked this conversation as resolved.
Show resolved Hide resolved
wchar_t* inputStr = malloc(inputStrLen * sizeof(wchar_t));
tgauth marked this conversation as resolved.
Show resolved Hide resolved
if (inputStr == NULL) {
return;
}
swprintf_s(inputStr, inputStrLen, L"ftp://%s", hostname_w);
hr = IISM->lpVtbl->MapUrlToZone(IISM, inputStr, &motw_zone_id, 0);
if (hr == S_OK) {
tgauth marked this conversation as resolved.
Show resolved Hide resolved
if (motw_zone_id < 5) {
debug("valid zone identifier value: %d", motw_zone_id);
}
else {
debug("invalid zone identifier value, will not use");
motw_zone_id = 5;
}
}
else {
motw_zone_id = 5;
debug("MapUrlToZone failed");
}
}
else {
debug("failed to co-create instance");
}
}
4 changes: 4 additions & 0 deletions contrib/win32/win32compat/misc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ extern char* chroot_path;
extern int chroot_path_len;
extern wchar_t* chroot_pathw;

/* motw zone_id */
extern DWORD motw_zone_id;

/* removes first '/' for Windows paths that are unix styled. Ex: /c:/ab.cd */
wchar_t * resolved_path_utf16(const char *);
char* resolved_path_utf8(const char *);
Expand Down Expand Up @@ -84,3 +87,4 @@ BOOL is_bash_test_env();
int bash_to_win_path(const char *in, char *out, const size_t out_len);
void debug_assert_internal();
int add_mark_of_web(const char* filename);
void get_zone_identifier(const char* hostname);
20 changes: 17 additions & 3 deletions scp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,9 @@ do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
reminp, remoutp, pidp) < 0)
return NULL;
}
#ifdef WINDOWS
get_zone_identifier(host);
#endif // WINDOWS
return do_init(*reminp, *remoutp, 32768, 64, limit_kbps);
}

Expand Down Expand Up @@ -1439,6 +1442,9 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
continue;
}
/* SCP */
#ifdef WINDOWS
get_zone_identifier(host);
#endif // WINDOWS
xasprintf(&bp, "%s -f %s%s",
cmd, *src == '-' ? "-- " : "", src);
if (do_cmd(ssh_program, host, suser, sport, 0, bp,
Expand Down Expand Up @@ -2077,9 +2083,17 @@ sink(int argc, char **argv, const char *src)
omode = mode;
mode |= S_IWUSR;
#ifdef WINDOWS
if (add_mark_of_web(np) == -1) {
run_err("%s: failed to add mark of the web\n", np);
exit(1);
if (motw_zone_id == 5) {
if (verbose_mode)
PaulHigin marked this conversation as resolved.
Show resolved Hide resolved
note_err("%s: will not add mark of the web due to push \
from local to remote scenario, or MapUrlToZone API failure\n", np);
}
else {
if (add_mark_of_web(np) == -1) {
if (verbose_mode) {
note_err("%s: add_mark_of_web failed\n", np);
}
}
}

// In windows, we would like to inherit the parent folder permissions by setting mode to USHRT_MAX.
Expand Down
8 changes: 2 additions & 6 deletions sftp-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1728,12 +1728,8 @@ do_download(struct sftp_conn *conn, const char *remote_path,
}
close(local_fd);
#ifdef WINDOWS
if (add_mark_of_web(local_path) == -1) {
// (resume_flag ? 0 : O_TRUNC) on line 1355 requires us
// to add the mark of the web after transferring the file.
// if MOTW fails, we need to remove the file before exiting
remove(local_path);
fatal_f("%s: failed to add mark of the web", local_path);
if (motw_zone_id == 5 || add_mark_of_web(local_path) == -1) {
tgauth marked this conversation as resolved.
Show resolved Hide resolved
debug("%s: failed to add mark of the web", local_path);
}
#endif // WINDOWS
sshbuf_free(msg);
Expand Down
14 changes: 9 additions & 5 deletions sftp-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,14 +869,14 @@ process_write(u_int32_t id)
#ifdef WINDOWS
char* filepath = resolved_path_utf8(handle_to_name(handle));
if (filepath == NULL) {
fatal_f("cannot convert handle %d to utf8 filepath for mark of the web", handle);
debug("cannot convert handle %d to utf8 filepath for mark of the web", handle);
}
if (add_mark_of_web(filepath) == -1) {
debug("add_mark_of_web to %s failed", filepath);
else {
if (motw_zone_id == 5 || add_mark_of_web(filepath) == -1) {
debug("add_mark_of_web to %s failed", filepath);
}
free(filepath);
fatal_f("failed to add mark of the web");
}
free(filepath);
#endif // WINDOWS

debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
Expand Down Expand Up @@ -1913,6 +1913,10 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
logit("session opened for local user %s from [%s]",
pw->pw_name, client_addr);

#ifdef WINDOWS
get_zone_identifier(client_addr);
#endif // WINDOWS

in = STDIN_FILENO;
out = STDOUT_FILENO;

Expand Down
3 changes: 3 additions & 0 deletions sftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2637,6 +2637,9 @@ main(int argc, char **argv)
freeargs(&args);

conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
#ifdef WINDOWS
get_zone_identifier(host);
#endif //WINDOWS
if (conn == NULL)
fatal("Couldn't initialise connection to server");

Expand Down