]> asedeno.scripts.mit.edu Git - PuTTY_svn.git/blob - windows/winsecur.c
Switch to using SIDs in make_private_security_descriptor().
[PuTTY_svn.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 int 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
35 int 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
50 PSID 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
102 int 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 (!SetSecurityDescriptorDacl(*psd, TRUE, *acl, FALSE)) {
191         *error = dupprintf("unable to set DACL in security descriptor: %s",
192                            win_strerror(GetLastError()));
193         goto cleanup;
194     }
195
196     ret = TRUE;
197
198   cleanup:
199     if (!ret) {
200         if (*psd) {
201             LocalFree(*psd);
202             *psd = NULL;
203         }
204         if (*acl) {
205             LocalFree(*acl);
206             *acl = NULL;
207         }
208     } else {
209         sfree(*error);
210         *error = NULL;
211     }
212     return ret;
213 }
214
215 #endif /* !defined NO_SECURITY */