LCOV - code coverage report
Current view: top level - src/common - restricted_token.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 2 2 100.0 %
Date: 2017-09-29 13:40:31 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * restricted_token.c
       4             :  *      helper routine to ensure restricted token on Windows
       5             :  *
       6             :  *
       7             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       8             :  * Portions Copyright (c) 1994, Regents of the University of California
       9             :  *
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/common/restricted_token.c
      13             :  *
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : 
      17             : #ifndef FRONTEND
      18             : #error "This file is not expected to be compiled for backend code"
      19             : #endif
      20             : 
      21             : #include "postgres_fe.h"
      22             : 
      23             : #include "common/restricted_token.h"
      24             : 
      25             : #ifdef WIN32
      26             : 
      27             : /* internal vars */
      28             : char       *restrict_env;
      29             : 
      30             : typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
      31             : 
      32             : /* Windows API define missing from some versions of MingW headers */
      33             : #ifndef  DISABLE_MAX_PRIVILEGE
      34             : #define DISABLE_MAX_PRIVILEGE   0x1
      35             : #endif
      36             : 
      37             : /*
      38             :  * Create a restricted token and execute the specified process with it.
      39             :  *
      40             :  * Returns restricted token on success and 0 on failure.
      41             :  *
      42             :  * On NT4, or any other system not containing the required functions, will
      43             :  * NOT execute anything.
      44             :  */
      45             : HANDLE
      46             : CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, const char *progname)
      47             : {
      48             :     BOOL        b;
      49             :     STARTUPINFO si;
      50             :     HANDLE      origToken;
      51             :     HANDLE      restrictedToken;
      52             :     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
      53             :     SID_AND_ATTRIBUTES dropSids[2];
      54             :     __CreateRestrictedToken _CreateRestrictedToken = NULL;
      55             :     HANDLE      Advapi32Handle;
      56             : 
      57             :     ZeroMemory(&si, sizeof(si));
      58             :     si.cb = sizeof(si);
      59             : 
      60             :     Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
      61             :     if (Advapi32Handle != NULL)
      62             :     {
      63             :         _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
      64             :     }
      65             : 
      66             :     if (_CreateRestrictedToken == NULL)
      67             :     {
      68             :         fprintf(stderr, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
      69             :         if (Advapi32Handle != NULL)
      70             :             FreeLibrary(Advapi32Handle);
      71             :         return 0;
      72             :     }
      73             : 
      74             :     /* Open the current token to use as a base for the restricted one */
      75             :     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
      76             :     {
      77             :         fprintf(stderr, _("%s: could not open process token: error code %lu\n"), progname, GetLastError());
      78             :         return 0;
      79             :     }
      80             : 
      81             :     /* Allocate list of SIDs to remove */
      82             :     ZeroMemory(&dropSids, sizeof(dropSids));
      83             :     if (!AllocateAndInitializeSid(&NtAuthority, 2,
      84             :                                   SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
      85             :                                   0, &dropSids[0].Sid) ||
      86             :         !AllocateAndInitializeSid(&NtAuthority, 2,
      87             :                                   SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
      88             :                                   0, &dropSids[1].Sid))
      89             :     {
      90             :         fprintf(stderr, _("%s: could not allocate SIDs: error code %lu\n"),
      91             :                 progname, GetLastError());
      92             :         return 0;
      93             :     }
      94             : 
      95             :     b = _CreateRestrictedToken(origToken,
      96             :                                DISABLE_MAX_PRIVILEGE,
      97             :                                sizeof(dropSids) / sizeof(dropSids[0]),
      98             :                                dropSids,
      99             :                                0, NULL,
     100             :                                0, NULL,
     101             :                                &restrictedToken);
     102             : 
     103             :     FreeSid(dropSids[1].Sid);
     104             :     FreeSid(dropSids[0].Sid);
     105             :     CloseHandle(origToken);
     106             :     FreeLibrary(Advapi32Handle);
     107             : 
     108             :     if (!b)
     109             :     {
     110             :         fprintf(stderr, _("%s: could not create restricted token: error code %lu\n"),
     111             :                 progname, GetLastError());
     112             :         return 0;
     113             :     }
     114             : 
     115             : #ifndef __CYGWIN__
     116             :     AddUserToTokenDacl(restrictedToken);
     117             : #endif
     118             : 
     119             :     if (!CreateProcessAsUser(restrictedToken,
     120             :                              NULL,
     121             :                              cmd,
     122             :                              NULL,
     123             :                              NULL,
     124             :                              TRUE,
     125             :                              CREATE_SUSPENDED,
     126             :                              NULL,
     127             :                              NULL,
     128             :                              &si,
     129             :                              processInfo))
     130             : 
     131             :     {
     132             :         fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
     133             :         return 0;
     134             :     }
     135             : 
     136             :     ResumeThread(processInfo->hThread);
     137             :     return restrictedToken;
     138             : }
     139             : #endif
     140             : 
     141             : /*
     142             :  * On Windows make sure that we are running with a restricted token,
     143             :  * On other platforms do nothing.
     144             :  */
     145             : void
     146           1 : get_restricted_token(const char *progname)
     147             : {
     148             : #ifdef WIN32
     149             :     HANDLE      restrictedToken;
     150             : 
     151             :     /*
     152             :      * Before we execute another program, make sure that we are running with a
     153             :      * restricted token. If not, re-execute ourselves with one.
     154             :      */
     155             : 
     156             :     if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
     157             :         || strcmp(restrict_env, "1") != 0)
     158             :     {
     159             :         PROCESS_INFORMATION pi;
     160             :         char       *cmdline;
     161             : 
     162             :         ZeroMemory(&pi, sizeof(pi));
     163             : 
     164             :         cmdline = pg_strdup(GetCommandLine());
     165             : 
     166             :         putenv("PG_RESTRICT_EXEC=1");
     167             : 
     168             :         if ((restrictedToken = CreateRestrictedProcess(cmdline, &pi, progname)) == 0)
     169             :         {
     170             :             fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, GetLastError());
     171             :         }
     172             :         else
     173             :         {
     174             :             /*
     175             :              * Successfully re-execed. Now wait for child process to capture
     176             :              * exitcode.
     177             :              */
     178             :             DWORD       x;
     179             : 
     180             :             CloseHandle(restrictedToken);
     181             :             CloseHandle(pi.hThread);
     182             :             WaitForSingleObject(pi.hProcess, INFINITE);
     183             : 
     184             :             if (!GetExitCodeProcess(pi.hProcess, &x))
     185             :             {
     186             :                 fprintf(stderr, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
     187             :                 exit(1);
     188             :             }
     189             :             exit(x);
     190             :         }
     191             :     }
     192             : #endif
     193           1 : }

Generated by: LCOV version 1.11