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