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