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 16 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
102 changes: 102 additions & 0 deletions contrib/win32/win32compat/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
#include "w32fd.h"
#include "inc\string.h"
#include "inc\time.h"
#include "..\..\..\atomicio.h"
#include "urlmon.h"

#include <wchar.h>

Expand Down Expand Up @@ -135,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 @@ -2119,3 +2124,100 @@ strrstr(const char *inStr, const char *pattern)

return last;
}

int
add_mark_of_web(const char* filename)
{
if (motw_zone_id > 4) {
return -1;
}
char* fileStreamPath = NULL;
size_t fileStreamPathLen = strlen(filename) + strlen(":Zone.Identifier") + 1;

fileStreamPath = malloc(fileStreamPathLen * sizeof(char));

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

sprintf_s(fileStreamPath, fileStreamPathLen, "%s:Zone.Identifier", filename);

int ofd, status = 0;
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) {
status = -1;
goto cleanup;
}

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

// create zone identifer file stream and then write the Mark of the Web to it
if ((ofd = open(fileStreamPath, O_WRONLY | O_CREAT, USHRT_MAX)) == -1) {
status = -1;
goto cleanup;
}

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

if (close(ofd) == -1) {
status = -1;
}

cleanup:
free(fileStreamPath);
if (zoneIdentifierStr)
free(zoneIdentifierStr);
tgauth marked this conversation as resolved.
Show resolved Hide resolved
return status;
}

/* Gets the zone identifier value based on the provided hostname,
and sets the global motw_zone_id variable with that value. */
void get_zone_identifier(const char* hostname) {
tgauth marked this conversation as resolved.
Show resolved Hide resolved
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (!SUCCEEDED(hr)) {
debug("CoInitializeEx for MapUrlToZone failed");
return;
}
IInternetSecurityManager* pIISM = NULL;
// CLSID_InternetSecurityManager & IID_IInternetSecurityManager declared in urlmon.h
hr = CoCreateInstance(&CLSID_InternetSecurityManager, NULL,
CLSCTX_ALL, &IID_IInternetSecurityManager, (void**)&pIISM);
if (!SUCCEEDED(hr)) {
debug("CoCreateInstance for MapUrlToZone failed");
goto out;
}
wchar_t *hostname_w = NULL, *host_format = NULL;
hostname_w = utf8_to_utf16(hostname);
if (hostname_w == NULL) {
goto cleanup;
}
size_t host_format_len = wcslen(hostname_w) + wcslen(L"ftp://") + 1;
host_format = malloc(host_format_len * sizeof(wchar_t));
if (host_format == NULL) {
goto cleanup;
}
swprintf_s(host_format, host_format_len, L"ftp://%s", hostname_w);
hr = pIISM->lpVtbl->MapUrlToZone(pIISM, host_format, &motw_zone_id, 0);
if (hr == S_OK) {
debug("MapUrlToZone zone identifier value: %d", motw_zone_id);
}
else {
motw_zone_id = 5;
debug("MapUrlToZone failed, resetting motw_zone_id to invalid value");
}
cleanup:
if (pIISM)
pIISM->lpVtbl->Release(pIISM);
if (hostname_w)
free(hostname_w);
if (host_format)
free(host_format);
out:
CoUninitialize();
}
7 changes: 6 additions & 1 deletion 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 @@ -82,4 +85,6 @@ wchar_t* get_final_path_by_handle(HANDLE h);
int lookup_principal_name(const wchar_t * sam_account_name, wchar_t * user_principal_name);
BOOL is_bash_test_env();
int bash_to_win_path(const char *in, char *out, const size_t out_len);
void debug_assert_internal();
void debug_assert_internal();
int add_mark_of_web(const char* filename);
void get_zone_identifier(const char* hostname);
15 changes: 15 additions & 0 deletions scp.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@

#include "sftp-common.h"
#include "sftp-client.h"
#ifdef WINDOWS
#include "misc_internal.h"
#endif // WINDOWS

extern char *__progname;

Expand Down Expand Up @@ -1138,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 @@ -1436,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 @@ -2074,6 +2083,12 @@ sink(int argc, char **argv, const char *src)
omode = mode;
mode |= S_IWUSR;
#ifdef WINDOWS
if (add_mark_of_web(np) == -1) {
if (verbose_mode) {
note_err("%s: add_mark_of_web failed\n", np);
Copy link

@rgl rgl Dec 17, 2022

Choose a reason for hiding this comment

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

why is this message handled differently than in sftp-client.c/sftp-server.c (where is uses debug instead of note_err)?

}
}

// In windows, we would like to inherit the parent folder permissions by setting mode to USHRT_MAX.
if ((ofd = open(np, O_WRONLY|O_CREAT, USHRT_MAX)) == -1) {
#else
Expand Down
5 changes: 5 additions & 0 deletions sftp-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1727,6 +1727,11 @@ do_download(struct sftp_conn *conn, const char *remote_path,
}
}
close(local_fd);
#ifdef WINDOWS
if (add_mark_of_web(local_path) == -1) {
debug("%s: failed to add mark of the web", local_path);
}
#endif // WINDOWS
sshbuf_free(msg);
free(handle);

Expand Down
20 changes: 20 additions & 0 deletions sftp-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@

#include "sftp.h"
#include "sftp-common.h"
#ifdef WINDOWS
#include "misc_internal.h"
#endif // WINDOWS

char *sftp_realpath(const char *, char *); /* sftp-realpath.c */

Expand Down Expand Up @@ -863,6 +866,19 @@ process_write(u_int32_t id)
(r = sshbuf_get_string(iqueue, &data, &len)) != 0)
fatal_fr(r, "parse");

#ifdef WINDOWS
char* filepath = resolved_path_utf8(handle_to_name(handle));
if (filepath == NULL) {
debug("cannot convert handle %d to utf8 filepath for mark of the web", handle);
}
else {
if (add_mark_of_web(filepath) == -1) {
debug("add_mark_of_web to %s failed", filepath);
}
free(filepath);
}
#endif // WINDOWS

debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
id, handle_to_name(handle), handle, (unsigned long long)off, len);
fd = handle_to_fd(handle);
Expand Down Expand Up @@ -1897,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