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