]> asedeno.scripts.mit.edu Git - PuTTY_svn.git/blob - windows/winsecur.c
Pass the right number of entries to SetEntriesInAcl!
[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                                      PSID *networksid,
105                                      PACL *acl,
106                                      char **error)
107 {
108     SID_IDENTIFIER_AUTHORITY nt_auth = SECURITY_NT_AUTHORITY;
109     EXPLICIT_ACCESS ea[3];
110     int ret = FALSE;
111
112     *psd = NULL;
113     *networksid = NULL;
114     *acl = NULL;
115     *error = NULL;
116
117     if (!got_advapi()) {
118         *error = dupprintf("unable to load advapi32.dll");
119         goto cleanup;
120     }
121
122     if (!AllocateAndInitializeSid(&nt_auth, 1, SECURITY_NETWORK_RID,
123                                   0, 0, 0, 0, 0, 0, 0, networksid)) {
124         *error = dupprintf("unable to construct SID for "
125                            "local same-user access only: %s",
126                            win_strerror(GetLastError()));
127         goto cleanup;
128     }
129
130     memset(ea, 0, sizeof(ea));
131     ea[0].grfAccessPermissions = permissions;
132     ea[0].grfAccessMode = REVOKE_ACCESS;
133     ea[0].grfInheritance = NO_INHERITANCE;
134     ea[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
135     ea[0].Trustee.ptstrName = "EVERYONE";
136     ea[1].grfAccessPermissions = permissions;
137     ea[1].grfAccessMode = GRANT_ACCESS;
138     ea[1].grfInheritance = NO_INHERITANCE;
139     ea[1].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
140     ea[1].Trustee.ptstrName = "CURRENT_USER";
141     ea[2].grfAccessPermissions = permissions;
142     ea[2].grfAccessMode = REVOKE_ACCESS;
143     ea[2].grfInheritance = NO_INHERITANCE;
144     ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
145     ea[2].Trustee.ptstrName = (LPTSTR)*networksid;
146
147     if (p_SetEntriesInAclA(3, ea, NULL, acl) != ERROR_SUCCESS || *acl == NULL) {
148         *error = dupprintf("unable to construct ACL: %s",
149                            win_strerror(GetLastError()));
150         goto cleanup;
151     }
152
153     *psd = (PSECURITY_DESCRIPTOR)
154         LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
155     if (!*psd) {
156         *error = dupprintf("unable to allocate security descriptor: %s",
157                            win_strerror(GetLastError()));
158         goto cleanup;
159     }
160
161     if (!InitializeSecurityDescriptor(*psd, SECURITY_DESCRIPTOR_REVISION)) {
162         *error = dupprintf("unable to initialise security descriptor: %s",
163                            win_strerror(GetLastError()));
164         goto cleanup;
165     }
166
167     if (!SetSecurityDescriptorDacl(*psd, TRUE, *acl, FALSE)) {
168         *error = dupprintf("unable to set DACL in security descriptor: %s",
169                            win_strerror(GetLastError()));
170         goto cleanup;
171     }
172
173     ret = TRUE;
174
175   cleanup:
176     if (!ret) {
177         if (*psd) {
178             LocalFree(*psd);
179             *psd = NULL;
180         }
181         if (*networksid) {
182             LocalFree(*networksid);
183             *networksid = NULL;
184         }
185         if (*acl) {
186             LocalFree(*acl);
187             *acl = NULL;
188         }
189     } else {
190         sfree(*error);
191         *error = NULL;
192     }
193     return ret;
194 }
195
196 #endif /* !defined NO_SECURITY */