source: filezilla/trunk/fuentes/src/putty/windows/winsecur.c @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

File size: 6.2 KB
Line 
1/*
2 * winsecur.c: implementation of winsecur.h.
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7
8#include "putty.h"
9
10#if !defined NO_SECURITY
11
12#define WINSECUR_GLOBAL
13#include "winsecur.h"
14
15int got_advapi(void)
16{
17    static int attempted = FALSE;
18    static int successful;
19    static HMODULE advapi;
20
21    if (!attempted) {
22        attempted = TRUE;
23        advapi = load_system32_dll("advapi32.dll");
24        successful = advapi &&
25            GET_WINDOWS_FUNCTION(advapi, GetSecurityInfo) &&
26            GET_WINDOWS_FUNCTION(advapi, OpenProcessToken) &&
27            GET_WINDOWS_FUNCTION(advapi, GetTokenInformation) &&
28            GET_WINDOWS_FUNCTION(advapi, InitializeSecurityDescriptor) &&
29            GET_WINDOWS_FUNCTION(advapi, SetSecurityDescriptorOwner) &&
30            GET_WINDOWS_FUNCTION(advapi, SetEntriesInAclA);
31    }
32    return successful;
33}
34
35int got_crypt(void)
36{
37    static int attempted = FALSE;
38    static int successful;
39    static HMODULE crypt;
40
41    if (!attempted) {
42        attempted = TRUE;
43        crypt = load_system32_dll("crypt32.dll");
44        successful = crypt &&
45            GET_WINDOWS_FUNCTION(crypt, CryptProtectMemory);
46    }
47    return successful;
48}
49
50PSID get_user_sid(void)
51{
52    HANDLE proc = NULL, tok = NULL;
53    TOKEN_USER *user = NULL;
54    DWORD toklen, sidlen;
55    PSID sid = NULL, ret = NULL;
56
57    if (!got_advapi())
58        goto cleanup;
59
60    if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
61                            GetCurrentProcessId())) == NULL)
62        goto cleanup;
63
64    if (!p_OpenProcessToken(proc, TOKEN_QUERY, &tok))
65        goto cleanup;
66
67    if (!p_GetTokenInformation(tok, TokenUser, NULL, 0, &toklen) &&
68        GetLastError() != ERROR_INSUFFICIENT_BUFFER)
69        goto cleanup;
70
71    if ((user = (TOKEN_USER *)LocalAlloc(LPTR, toklen)) == NULL)
72        goto cleanup;
73
74    if (!p_GetTokenInformation(tok, TokenUser, user, toklen, &toklen))
75        goto cleanup;
76
77    sidlen = GetLengthSid(user->User.Sid);
78
79    sid = (PSID)smalloc(sidlen);
80
81    if (!CopySid(sidlen, sid, user->User.Sid))
82        goto cleanup;
83
84    /* Success. Move sid into the return value slot, and null it out
85     * to stop the cleanup code freeing it. */
86    ret = sid;
87    sid = NULL;
88
89  cleanup:
90    if (proc != NULL)
91        CloseHandle(proc);
92    if (tok != NULL)
93        CloseHandle(tok);
94    if (user != NULL)
95        LocalFree(user);
96    if (sid != NULL)
97        sfree(sid);
98
99    return ret;
100}
101
102int make_private_security_descriptor(DWORD permissions,
103                                     PSECURITY_DESCRIPTOR *psd,
104                                     PACL *acl,
105                                     char **error)
106{
107    SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
108    SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
109    EXPLICIT_ACCESS ea[3];
110    int acl_err;
111    int ret = FALSE;
112
113    /* Initialised once, then kept around to reuse forever */
114    static PSID worldsid, networksid, usersid;
115
116    *psd = NULL;
117    *acl = NULL;
118    *error = NULL;
119
120    if (!got_advapi()) {
121        *error = dupprintf("unable to load advapi32.dll");
122        goto cleanup;
123    }
124
125    if (!usersid) {
126        if ((usersid = get_user_sid()) == NULL) {
127            *error = dupprintf("unable to construct SID for current user: %s",
128                               win_strerror(GetLastError()));
129            goto cleanup;
130        }
131    }
132
133    if (!worldsid) {
134        if (!AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID,
135                                      0, 0, 0, 0, 0, 0, 0, &worldsid)) {
136            *error = dupprintf("unable to construct SID for world: %s",
137                               win_strerror(GetLastError()));
138            goto cleanup;
139        }
140    }
141
142    if (!networksid) {
143        if (!AllocateAndInitializeSid(&nt_auth, 1, SECURITY_NETWORK_RID,
144                                      0, 0, 0, 0, 0, 0, 0, &networksid)) {
145            *error = dupprintf("unable to construct SID for "
146                               "local same-user access only: %s",
147                               win_strerror(GetLastError()));
148            goto cleanup;
149        }
150    }
151
152    memset(ea, 0, sizeof(ea));
153    ea[0].grfAccessPermissions = permissions;
154    ea[0].grfAccessMode = REVOKE_ACCESS;
155    ea[0].grfInheritance = NO_INHERITANCE;
156    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
157    ea[0].Trustee.ptstrName = (LPTSTR)worldsid;
158    ea[1].grfAccessPermissions = permissions;
159    ea[1].grfAccessMode = GRANT_ACCESS;
160    ea[1].grfInheritance = NO_INHERITANCE;
161    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
162    ea[1].Trustee.ptstrName = (LPTSTR)usersid;
163    ea[2].grfAccessPermissions = permissions;
164    ea[2].grfAccessMode = REVOKE_ACCESS;
165    ea[2].grfInheritance = NO_INHERITANCE;
166    ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
167    ea[2].Trustee.ptstrName = (LPTSTR)networksid;
168
169    acl_err = p_SetEntriesInAclA(3, ea, NULL, acl);
170    if (acl_err != ERROR_SUCCESS || *acl == NULL) {
171        *error = dupprintf("unable to construct ACL: %s",
172                           win_strerror(acl_err));
173        goto cleanup;
174    }
175
176    *psd = (PSECURITY_DESCRIPTOR)
177        LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
178    if (!*psd) {
179        *error = dupprintf("unable to allocate security descriptor: %s",
180                           win_strerror(GetLastError()));
181        goto cleanup;
182    }
183
184    if (!InitializeSecurityDescriptor(*psd, SECURITY_DESCRIPTOR_REVISION)) {
185        *error = dupprintf("unable to initialise security descriptor: %s",
186                           win_strerror(GetLastError()));
187        goto cleanup;
188    }
189
190    if (!SetSecurityDescriptorOwner(*psd, usersid, FALSE)) {
191        *error = dupprintf("unable to set owner in security descriptor: %s",
192                           win_strerror(GetLastError()));
193        goto cleanup;
194    }
195
196    if (!SetSecurityDescriptorDacl(*psd, TRUE, *acl, FALSE)) {
197        *error = dupprintf("unable to set DACL in security descriptor: %s",
198                           win_strerror(GetLastError()));
199        goto cleanup;
200    }
201
202    ret = TRUE;
203
204  cleanup:
205    if (!ret) {
206        if (*psd) {
207            LocalFree(*psd);
208            *psd = NULL;
209        }
210        if (*acl) {
211            LocalFree(*acl);
212            *acl = NULL;
213        }
214    } else {
215        sfree(*error);
216        *error = NULL;
217    }
218    return ret;
219}
220
221#endif /* !defined NO_SECURITY */
Note: See TracBrowser for help on using the repository browser.