]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winsecur.c
Put back in a missing dynamic-load wrapper on SetSecurityInfo.
[PuTTY.git] / windows / winsecur.c
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
15 /* Initialised once, then kept around to reuse forever */
16 static PSID worldsid, networksid, usersid;
17
18
19 int got_advapi(void)
20 {
21     static int attempted = FALSE;
22     static int successful;
23     static HMODULE advapi;
24
25     if (!attempted) {
26         attempted = TRUE;
27         advapi = load_system32_dll("advapi32.dll");
28         successful = advapi &&
29             GET_WINDOWS_FUNCTION(advapi, GetSecurityInfo) &&
30             GET_WINDOWS_FUNCTION(advapi, SetSecurityInfo) &&
31             GET_WINDOWS_FUNCTION(advapi, OpenProcessToken) &&
32             GET_WINDOWS_FUNCTION(advapi, GetTokenInformation) &&
33             GET_WINDOWS_FUNCTION(advapi, InitializeSecurityDescriptor) &&
34             GET_WINDOWS_FUNCTION(advapi, SetSecurityDescriptorOwner) &&
35             GET_WINDOWS_FUNCTION(advapi, SetEntriesInAclA);
36     }
37     return successful;
38 }
39
40 PSID get_user_sid(void)
41 {
42     HANDLE proc = NULL, tok = NULL;
43     TOKEN_USER *user = NULL;
44     DWORD toklen, sidlen;
45     PSID sid = NULL, ret = NULL;
46
47     if (!got_advapi())
48         goto cleanup;
49
50     if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
51                             GetCurrentProcessId())) == NULL)
52         goto cleanup;
53
54     if (!p_OpenProcessToken(proc, TOKEN_QUERY, &tok))
55         goto cleanup;
56
57     if (!p_GetTokenInformation(tok, TokenUser, NULL, 0, &toklen) &&
58         GetLastError() != ERROR_INSUFFICIENT_BUFFER)
59         goto cleanup;
60
61     if ((user = (TOKEN_USER *)LocalAlloc(LPTR, toklen)) == NULL)
62         goto cleanup;
63
64     if (!p_GetTokenInformation(tok, TokenUser, user, toklen, &toklen))
65         goto cleanup;
66
67     sidlen = GetLengthSid(user->User.Sid);
68
69     sid = (PSID)smalloc(sidlen);
70
71     if (!CopySid(sidlen, sid, user->User.Sid))
72         goto cleanup;
73
74     /* Success. Move sid into the return value slot, and null it out
75      * to stop the cleanup code freeing it. */
76     ret = sid;
77     sid = NULL;
78
79   cleanup:
80     if (proc != NULL)
81         CloseHandle(proc);
82     if (tok != NULL)
83         CloseHandle(tok);
84     if (user != NULL)
85         LocalFree(user);
86     if (sid != NULL)
87         sfree(sid);
88
89     return ret;
90 }
91
92 int getsids(char *error)
93 {
94     SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
95     SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
96     int ret;
97
98     error=NULL;
99
100     if (!usersid) {
101         if ((usersid = get_user_sid()) == NULL) {
102             error = dupprintf("unable to construct SID for current user: %s",
103                                win_strerror(GetLastError()));
104             goto cleanup;
105         }
106     }
107
108     if (!worldsid) {
109         if (!AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID,
110                                       0, 0, 0, 0, 0, 0, 0, &worldsid)) {
111             error = dupprintf("unable to construct SID for world: %s",
112                                win_strerror(GetLastError()));
113             goto cleanup;
114         }
115     }
116
117     if (!networksid) {
118         if (!AllocateAndInitializeSid(&nt_auth, 1, SECURITY_NETWORK_RID,
119                                       0, 0, 0, 0, 0, 0, 0, &networksid)) {
120             error = dupprintf("unable to construct SID for "
121                                "local same-user access only: %s",
122                                win_strerror(GetLastError()));
123             goto cleanup;
124         }
125     }
126
127     ret=TRUE;
128
129  cleanup:
130     if (ret) {
131       sfree(error);
132       error = NULL;
133     }
134     return ret;
135 }
136   
137
138 int make_private_security_descriptor(DWORD permissions,
139                                      PSECURITY_DESCRIPTOR *psd,
140                                      PACL *acl,
141                                      char **error)
142 {
143     SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
144     SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
145     EXPLICIT_ACCESS ea[3];
146     int acl_err;
147     int ret = FALSE;
148
149
150     *psd = NULL;
151     *acl = NULL;
152     *error = NULL;
153
154     if (!getsids(*error))
155       goto cleanup;
156
157     memset(ea, 0, sizeof(ea));
158     ea[0].grfAccessPermissions = permissions;
159     ea[0].grfAccessMode = REVOKE_ACCESS;
160     ea[0].grfInheritance = NO_INHERITANCE;
161     ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
162     ea[0].Trustee.ptstrName = (LPTSTR)worldsid;
163     ea[1].grfAccessPermissions = permissions;
164     ea[1].grfAccessMode = GRANT_ACCESS;
165     ea[1].grfInheritance = NO_INHERITANCE;
166     ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
167     ea[1].Trustee.ptstrName = (LPTSTR)usersid;
168     ea[2].grfAccessPermissions = permissions;
169     ea[2].grfAccessMode = REVOKE_ACCESS;
170     ea[2].grfInheritance = NO_INHERITANCE;
171     ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
172     ea[2].Trustee.ptstrName = (LPTSTR)networksid;
173
174     acl_err = p_SetEntriesInAclA(3, ea, NULL, acl);
175     if (acl_err != ERROR_SUCCESS || *acl == NULL) {
176         *error = dupprintf("unable to construct ACL: %s",
177                            win_strerror(acl_err));
178         goto cleanup;
179     }
180
181     *psd = (PSECURITY_DESCRIPTOR)
182         LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
183     if (!*psd) {
184         *error = dupprintf("unable to allocate security descriptor: %s",
185                            win_strerror(GetLastError()));
186         goto cleanup;
187     }
188
189     if (!InitializeSecurityDescriptor(*psd, SECURITY_DESCRIPTOR_REVISION)) {
190         *error = dupprintf("unable to initialise security descriptor: %s",
191                            win_strerror(GetLastError()));
192         goto cleanup;
193     }
194
195     if (!SetSecurityDescriptorOwner(*psd, usersid, FALSE)) {
196         *error = dupprintf("unable to set owner in security descriptor: %s",
197                            win_strerror(GetLastError()));
198         goto cleanup;
199     }
200
201     if (!SetSecurityDescriptorDacl(*psd, TRUE, *acl, FALSE)) {
202         *error = dupprintf("unable to set DACL in security descriptor: %s",
203                            win_strerror(GetLastError()));
204         goto cleanup;
205     }
206
207     ret = TRUE;
208
209   cleanup:
210     if (!ret) {
211         if (*psd) {
212             LocalFree(*psd);
213             *psd = NULL;
214         }
215         if (*acl) {
216             LocalFree(*acl);
217             *acl = NULL;
218         }
219     } else {
220         sfree(*error);
221         *error = NULL;
222     }
223     return ret;
224 }
225
226 int setprocessacl(char *error)
227 {
228     SID_IDENTIFIER_AUTHORITY world_auth = SECURITY_WORLD_SID_AUTHORITY;
229     SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
230     EXPLICIT_ACCESS ea[2];
231     int acl_err;
232     int ret=FALSE;
233     PACL acl = NULL;
234
235     static const nastyace=WRITE_DAC | WRITE_OWNER |
236         PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
237         PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION |
238         PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION |
239         PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE |
240         PROCESS_SUSPEND_RESUME;
241
242     if (!getsids(error))
243         goto cleanup;
244
245     memset(ea, 0, sizeof(ea));
246
247     /* Everyone: deny */
248     ea[0].grfAccessPermissions = nastyace;
249     ea[0].grfAccessMode = DENY_ACCESS;
250     ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
251     ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
252     ea[0].Trustee.ptstrName = (LPTSTR)worldsid;
253
254     /* User: user ace */
255     ea[1].grfAccessPermissions = ~nastyace & 0x1fff;
256     ea[1].grfAccessMode = GRANT_ACCESS;
257     ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
258     ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
259     ea[1].Trustee.ptstrName = (LPTSTR)usersid;
260
261     acl_err = p_SetEntriesInAclA(2, ea, NULL, &acl);
262
263     if (acl_err != ERROR_SUCCESS || acl == NULL) {
264         error = dupprintf("unable to construct ACL: %s",
265                           win_strerror(acl_err));
266         goto cleanup;
267     }
268
269     if (ERROR_SUCCESS != p_SetSecurityInfo
270         (GetCurrentProcess(), SE_KERNEL_OBJECT,
271          OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
272          usersid, NULL, acl, NULL)) {
273         error=dupprintf("Unable to set process ACL: %s",
274                         win_strerror(GetLastError()));
275         goto cleanup;
276     }
277                       
278
279     ret=TRUE;
280     
281   cleanup:
282     if (!ret) {
283         if (acl) {
284             LocalFree(acl);
285             acl = NULL;
286         }
287     }
288     return ret;
289 }  
290 #endif /* !defined NO_SECURITY */