From 080d20ca7f56f869106d513c07654e5868ab6e60 Mon Sep 17 00:00:00 2001
From: Juan Jose Santamaria Flecha <juanjo.santamaria@gmail.com>
Date: Mon, 16 Jan 2023 06:27:59 -0500
Subject: [PATCH] [PATCH 1/4] WIP: Make mkdtemp() more secure on Windows.

Our POSIX mkdtemp() implementation in src/port/mkdtemp.c code would
create directories with default permissions on Windows.  Fix, using
native Windows API instead of mkdir().
---
 src/port/mkdtemp.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/src/port/mkdtemp.c b/src/port/mkdtemp.c
index 4578e83..64a0641 100644
--- a/src/port/mkdtemp.c
+++ b/src/port/mkdtemp.c
@@ -80,6 +80,10 @@ __RCSID("$NetBSD: gettemp.c,v 1.17 2014/01/21 19:09:48 seanb Exp $");
 #include <stdlib.h>
 #include <unistd.h>
 
+#ifdef WIN32
+#include <sddl.h>
+#endif
+
 #ifdef NOT_POSTGRESQL
 #if HAVE_NBTOOL_CONFIG_H
 #define GETTEMP		__nbcompat_gettemp
@@ -187,8 +191,50 @@ GETTEMP(char *path, int *doopen, int domkdir)
 		}
 		else if (domkdir)
 		{
+#ifdef WIN32
+			HANDLE				hToken = NULL;
+			DWORD				dwBufferSize = 0;
+			PTOKEN_USER			pTokenUser = NULL;
+			char			   *pSid = NULL;
+			char				pSdd[570];
+			SECURITY_ATTRIBUTES	sa = {sizeof(SECURITY_ATTRIBUTES)};
+
+			/* open the access token associated with the calling process */
+			if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+				_dosmaperr(GetLastError());
+
+			/* get the size of the memory buffer needed for the SID */
+			(void)GetTokenInformation(hToken, TokenUser, NULL, 0, &dwBufferSize);
+
+			pTokenUser = (PTOKEN_USER)malloc(dwBufferSize);
+			memset(pTokenUser, 0, dwBufferSize);
+
+			/* retrieve the token information in a TOKEN_USER structure */
+			if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize,
+				&dwBufferSize))
+				_dosmaperr(GetLastError());
+
+			CloseHandle(hToken);
+			ConvertSidToStringSid(pTokenUser->User.Sid, &pSid);
+			free(pTokenUser);
+
+			/*
+			 * Security descriptor for granting access to system, administrators and
+			 * current user.
+			 */
+			sprintf(pSdd, "O:%sD:(A;OICIID;FA;;;SY)(A;OICIID;FA;;;BA)(A;OICIID;FA;;;%s)",
+					pSid, pSid);
+			LocalFree(pSid);
+
+			if (ConvertStringSecurityDescriptorToSecurityDescriptor(pSdd, SDDL_REVISION_1,
+				&sa.lpSecurityDescriptor, NULL) && CreateDirectory(path, &sa))
+				return 1;
+
+			_dosmaperr(GetLastError());
+#else
 			if (mkdir(path, 0700) >= 0)
 				return 1;
+#endif
 			if (errno != EEXIST)
 				return 0;
 		}
-- 
2.11.0

