summaryrefslogtreecommitdiff
path: root/psutil/arch/windows/security.c
blob: 4e2c7435b22cb45c5e3b900f077414a6c3d4e646 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Security related functions for Windows platform (Set privileges such as
 * SE DEBUG).
 */

#include <windows.h>
#include <Python.h>
#include "../../_psutil_common.h"


static BOOL
psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) {
    TOKEN_PRIVILEGES tp;
    LUID luid;
    TOKEN_PRIVILEGES tpPrevious;
    DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);

    if (! LookupPrivilegeValue(NULL, Privilege, &luid)) {
        PyErr_SetFromOSErrnoWithSyscall("LookupPrivilegeValue");
        return 1;
    }

    // first pass.  get current privilege setting
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = 0;

    if (! AdjustTokenPrivileges(
            hToken,
            FALSE,
            &tp,
            sizeof(TOKEN_PRIVILEGES),
            &tpPrevious,
            &cbPrevious))
    {
        PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges");
        return 1;
    }

    // Second pass. Set privilege based on previous setting.
    tpPrevious.PrivilegeCount = 1;
    tpPrevious.Privileges[0].Luid = luid;

    if (bEnablePrivilege)
        tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
    else
        tpPrevious.Privileges[0].Attributes ^=
            (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);

    if (! AdjustTokenPrivileges(
            hToken,
            FALSE,
            &tpPrevious,
            cbPrevious,
            NULL,
            NULL))
    {
        PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges");
        return 1;
    }

    return 0;
}


static HANDLE
psutil_get_thisproc_token() {
    HANDLE hToken = NULL;
    HANDLE me = GetCurrentProcess();

    if (! OpenProcessToken(
            me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        if (GetLastError() == ERROR_NO_TOKEN)
        {
            if (! ImpersonateSelf(SecurityImpersonation)) {
                PyErr_SetFromOSErrnoWithSyscall("ImpersonateSelf");
                return NULL;
            }
            if (! OpenProcessToken(
                    me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
            {
                PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken");
                return NULL;
            }
        }
        else {
            PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken");
            return NULL;
        }
    }

    return hToken;
}


static void
psutil_print_err() {
    char *msg = "psutil module couldn't set SE DEBUG mode for this process; " \
        "please file an issue against psutil bug tracker";
    psutil_debug(msg);
    if (GetLastError() != ERROR_ACCESS_DENIED)
        PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1);
    PyErr_Clear();
}


/*
 * Set this process in SE DEBUG mode so that we have more chances of
 * querying processes owned by other users, including many owned by
 * Administrator and Local System.
 * https://docs.microsoft.com/windows-hardware/drivers/debugger/debug-privilege
 * This is executed on module import and we don't crash on error.
 */
int
psutil_set_se_debug() {
    HANDLE hToken;
    int err = 1;

    if ((hToken = psutil_get_thisproc_token()) == NULL) {
        // "return 1;" to get an exception
        psutil_print_err();
        return 0;
    }

    if (psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE) != 0) {
        // "return 1;" to get an exception
        psutil_print_err();
    }

    RevertToSelf();
    CloseHandle(hToken);
    return 0;
}