xref: /freebsd/crypto/krb5/src/ccapi/common/win/OldCC/util.cxx (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert  * $Header$
3*7f2fe78bSCy Schubert  *
4*7f2fe78bSCy Schubert  * Copyright 2008 Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert #include <windows.h>
28*7f2fe78bSCy Schubert #include <stdio.h>  // for _snprintf
29*7f2fe78bSCy Schubert #include <malloc.h>
30*7f2fe78bSCy Schubert #include <stdlib.h>
31*7f2fe78bSCy Schubert 
32*7f2fe78bSCy Schubert extern "C" {
33*7f2fe78bSCy Schubert #include "cci_debugging.h"
34*7f2fe78bSCy Schubert #include "ccutils.h"
35*7f2fe78bSCy Schubert     }
36*7f2fe78bSCy Schubert 
37*7f2fe78bSCy Schubert #include "util.h"
38*7f2fe78bSCy Schubert #include "secure.hxx"
39*7f2fe78bSCy Schubert 
40*7f2fe78bSCy Schubert 
malloc_alloc_p(size_t size)41*7f2fe78bSCy Schubert void* malloc_alloc_p(size_t size) {
42*7f2fe78bSCy Schubert     return malloc(size);
43*7f2fe78bSCy Schubert     }
44*7f2fe78bSCy Schubert 
free_alloc_p(void * pptr)45*7f2fe78bSCy Schubert void free_alloc_p(void *pptr) {
46*7f2fe78bSCy Schubert     void **real_pptr = (void**)pptr;
47*7f2fe78bSCy Schubert     if (*real_pptr) {
48*7f2fe78bSCy Schubert         free(*real_pptr);
49*7f2fe78bSCy Schubert         *real_pptr = 0;
50*7f2fe78bSCy Schubert         }
51*7f2fe78bSCy Schubert     }
52*7f2fe78bSCy Schubert 
alloc_textual_sid(PSID pSid,LPSTR * pTextualSid)53*7f2fe78bSCy Schubert extern "C" DWORD alloc_textual_sid(
54*7f2fe78bSCy Schubert     PSID pSid,          // binary Sid
55*7f2fe78bSCy Schubert     LPSTR *pTextualSid  // buffer for Textual representation of Sid
56*7f2fe78bSCy Schubert     ) {
57*7f2fe78bSCy Schubert     PSID_IDENTIFIER_AUTHORITY psia;
58*7f2fe78bSCy Schubert     DWORD dwSubAuthorities;
59*7f2fe78bSCy Schubert     DWORD dwSidRev = SID_REVISION;
60*7f2fe78bSCy Schubert     DWORD dwCounter;
61*7f2fe78bSCy Schubert     DWORD dwSidSize;
62*7f2fe78bSCy Schubert 
63*7f2fe78bSCy Schubert     *pTextualSid = 0;
64*7f2fe78bSCy Schubert 
65*7f2fe78bSCy Schubert     //
66*7f2fe78bSCy Schubert     // test if Sid passed in is valid
67*7f2fe78bSCy Schubert     //
68*7f2fe78bSCy Schubert     if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER;
69*7f2fe78bSCy Schubert 
70*7f2fe78bSCy Schubert     // obtain SidIdentifierAuthority
71*7f2fe78bSCy Schubert     psia = GetSidIdentifierAuthority(pSid);
72*7f2fe78bSCy Schubert 
73*7f2fe78bSCy Schubert     // obtain sidsubauthority count
74*7f2fe78bSCy Schubert     dwSubAuthorities =* GetSidSubAuthorityCount(pSid);
75*7f2fe78bSCy Schubert 
76*7f2fe78bSCy Schubert     //
77*7f2fe78bSCy Schubert     // compute buffer length
78*7f2fe78bSCy Schubert     // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
79*7f2fe78bSCy Schubert     //
80*7f2fe78bSCy Schubert     dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
81*7f2fe78bSCy Schubert     *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize);
82*7f2fe78bSCy Schubert     if (!*pTextualSid)
83*7f2fe78bSCy Schubert         return GetLastError();
84*7f2fe78bSCy Schubert 
85*7f2fe78bSCy Schubert     LPSTR TextualSid = *pTextualSid;
86*7f2fe78bSCy Schubert 
87*7f2fe78bSCy Schubert     //
88*7f2fe78bSCy Schubert     // prepare S-SID_REVISION-
89*7f2fe78bSCy Schubert     //
90*7f2fe78bSCy Schubert     wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev );
91*7f2fe78bSCy Schubert 
92*7f2fe78bSCy Schubert     //
93*7f2fe78bSCy Schubert     // prepare SidIdentifierAuthority
94*7f2fe78bSCy Schubert     //
95*7f2fe78bSCy Schubert     if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
96*7f2fe78bSCy Schubert     {
97*7f2fe78bSCy Schubert         wsprintf(TextualSid + lstrlen(TextualSid),
98*7f2fe78bSCy Schubert                  TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
99*7f2fe78bSCy Schubert                  (USHORT)psia->Value[0],
100*7f2fe78bSCy Schubert                  (USHORT)psia->Value[1],
101*7f2fe78bSCy Schubert                  (USHORT)psia->Value[2],
102*7f2fe78bSCy Schubert                  (USHORT)psia->Value[3],
103*7f2fe78bSCy Schubert                  (USHORT)psia->Value[4],
104*7f2fe78bSCy Schubert                  (USHORT)psia->Value[5]);
105*7f2fe78bSCy Schubert     }
106*7f2fe78bSCy Schubert     else
107*7f2fe78bSCy Schubert     {
108*7f2fe78bSCy Schubert         wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"),
109*7f2fe78bSCy Schubert                  (ULONG)(psia->Value[5]      )   +
110*7f2fe78bSCy Schubert                  (ULONG)(psia->Value[4] <<  8)   +
111*7f2fe78bSCy Schubert                  (ULONG)(psia->Value[3] << 16)   +
112*7f2fe78bSCy Schubert                  (ULONG)(psia->Value[2] << 24)   );
113*7f2fe78bSCy Schubert     }
114*7f2fe78bSCy Schubert 
115*7f2fe78bSCy Schubert     //
116*7f2fe78bSCy Schubert     // loop through SidSubAuthorities
117*7f2fe78bSCy Schubert     //
118*7f2fe78bSCy Schubert     for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
119*7f2fe78bSCy Schubert     {
120*7f2fe78bSCy Schubert         wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"),
121*7f2fe78bSCy Schubert                  *GetSidSubAuthority(pSid, dwCounter) );
122*7f2fe78bSCy Schubert     }
123*7f2fe78bSCy Schubert     return 0;
124*7f2fe78bSCy Schubert }
125*7f2fe78bSCy Schubert 
alloc_token_user(HANDLE hToken,PTOKEN_USER * pptu)126*7f2fe78bSCy Schubert DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) {
127*7f2fe78bSCy Schubert     DWORD status = 0;
128*7f2fe78bSCy Schubert     DWORD size = 0;
129*7f2fe78bSCy Schubert     *pptu = 0;
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert     GetTokenInformation(hToken, TokenUser, *pptu, 0, &size);
132*7f2fe78bSCy Schubert     if (size == 0) status = GetLastError();
133*7f2fe78bSCy Schubert 
134*7f2fe78bSCy Schubert     if (!status) {
135*7f2fe78bSCy Schubert         if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size)))
136*7f2fe78bSCy Schubert             status = GetLastError();
137*7f2fe78bSCy Schubert         }
138*7f2fe78bSCy Schubert 
139*7f2fe78bSCy Schubert     if (!status) {
140*7f2fe78bSCy Schubert         if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size))
141*7f2fe78bSCy Schubert             status = GetLastError();
142*7f2fe78bSCy Schubert         }
143*7f2fe78bSCy Schubert 
144*7f2fe78bSCy Schubert     if (status && *pptu) {
145*7f2fe78bSCy Schubert         free_alloc_p(pptu);
146*7f2fe78bSCy Schubert         }
147*7f2fe78bSCy Schubert     return status;
148*7f2fe78bSCy Schubert     }
149*7f2fe78bSCy Schubert 
150*7f2fe78bSCy Schubert DWORD
alloc_username(PSID Sid,LPSTR * pname,LPSTR * pdomain=0)151*7f2fe78bSCy Schubert alloc_username(
152*7f2fe78bSCy Schubert     PSID Sid,
153*7f2fe78bSCy Schubert     LPSTR* pname,
154*7f2fe78bSCy Schubert     LPSTR* pdomain = 0
155*7f2fe78bSCy Schubert     )
156*7f2fe78bSCy Schubert {
157*7f2fe78bSCy Schubert     DWORD status = 0;
158*7f2fe78bSCy Schubert     DWORD name_len = 0;
159*7f2fe78bSCy Schubert     DWORD domain_len = 0;
160*7f2fe78bSCy Schubert     SID_NAME_USE snu;
161*7f2fe78bSCy Schubert     LPSTR name = 0;
162*7f2fe78bSCy Schubert     LPSTR domain = 0;
163*7f2fe78bSCy Schubert 
164*7f2fe78bSCy Schubert     *pname = 0;
165*7f2fe78bSCy Schubert     if (pdomain) *pdomain = 0;
166*7f2fe78bSCy Schubert 
167*7f2fe78bSCy Schubert     LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu);
168*7f2fe78bSCy Schubert     if ((name_len == 0) || (domain_len == 0)) status = GetLastError();
169*7f2fe78bSCy Schubert 
170*7f2fe78bSCy Schubert     if (!status) {
171*7f2fe78bSCy Schubert         if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError();
172*7f2fe78bSCy Schubert         }
173*7f2fe78bSCy Schubert 
174*7f2fe78bSCy Schubert     if (!status) {
175*7f2fe78bSCy Schubert         if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError();
176*7f2fe78bSCy Schubert         }
177*7f2fe78bSCy Schubert 
178*7f2fe78bSCy Schubert     if (!status) {
179*7f2fe78bSCy Schubert         if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError();
180*7f2fe78bSCy Schubert         }
181*7f2fe78bSCy Schubert 
182*7f2fe78bSCy Schubert     if (status) {
183*7f2fe78bSCy Schubert         if (name)   free_alloc_p(&name);
184*7f2fe78bSCy Schubert         if (domain) free_alloc_p(&domain);
185*7f2fe78bSCy Schubert         }
186*7f2fe78bSCy Schubert     else {
187*7f2fe78bSCy Schubert         if (pdomain) {
188*7f2fe78bSCy Schubert             *pname = name;
189*7f2fe78bSCy Schubert             *pdomain = domain;
190*7f2fe78bSCy Schubert             }
191*7f2fe78bSCy Schubert         else {
192*7f2fe78bSCy Schubert             DWORD size = name_len + domain_len + 1;
193*7f2fe78bSCy Schubert             *pname = (LPSTR)malloc_alloc_p(size);
194*7f2fe78bSCy Schubert             if (!*pname) status = GetLastError();
195*7f2fe78bSCy Schubert             else _snprintf(*pname, size, "%s\\%s", name, domain);
196*7f2fe78bSCy Schubert             }
197*7f2fe78bSCy Schubert         }
198*7f2fe78bSCy Schubert     return status;
199*7f2fe78bSCy Schubert     }
200*7f2fe78bSCy Schubert 
get_authentication_id(HANDLE hToken,LUID * pAuthId)201*7f2fe78bSCy Schubert DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) {
202*7f2fe78bSCy Schubert     TOKEN_STATISTICS ts;
203*7f2fe78bSCy Schubert     DWORD len;
204*7f2fe78bSCy Schubert 
205*7f2fe78bSCy Schubert     if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len))
206*7f2fe78bSCy Schubert         return GetLastError();
207*7f2fe78bSCy Schubert     *pAuthId = ts.AuthenticationId;
208*7f2fe78bSCy Schubert     return 0;
209*7f2fe78bSCy Schubert     }
210*7f2fe78bSCy Schubert 
211*7f2fe78bSCy Schubert DWORD
alloc_name_9x(LPSTR * pname,LPSTR postfix)212*7f2fe78bSCy Schubert alloc_name_9x(
213*7f2fe78bSCy Schubert     LPSTR* pname,
214*7f2fe78bSCy Schubert     LPSTR postfix
215*7f2fe78bSCy Schubert     )
216*7f2fe78bSCy Schubert {
217*7f2fe78bSCy Schubert     char prefix[] = "krbcc";
218*7f2fe78bSCy Schubert     DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1;
219*7f2fe78bSCy Schubert 
220*7f2fe78bSCy Schubert     *pname = (LPSTR)malloc_alloc_p(len);
221*7f2fe78bSCy Schubert     if (!*pname) return GetLastError();
222*7f2fe78bSCy Schubert     _snprintf(*pname, len, "%s.%s", prefix, postfix);
223*7f2fe78bSCy Schubert     return 0;
224*7f2fe78bSCy Schubert }
225*7f2fe78bSCy Schubert 
alloc_name_NT(LPSTR * pname,LPSTR postfix)226*7f2fe78bSCy Schubert DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) {
227*7f2fe78bSCy Schubert     DWORD status = 0;
228*7f2fe78bSCy Schubert     HANDLE hToken = 0;
229*7f2fe78bSCy Schubert     LUID auth_id;
230*7f2fe78bSCy Schubert #ifdef _DEBUG
231*7f2fe78bSCy Schubert     PTOKEN_USER ptu = 0;
232*7f2fe78bSCy Schubert     LPSTR name = 0;
233*7f2fe78bSCy Schubert     LPSTR domain = 0;
234*7f2fe78bSCy Schubert     LPSTR sid = 0;
235*7f2fe78bSCy Schubert #endif
236*7f2fe78bSCy Schubert     char prefix[] = "krbcc";
237*7f2fe78bSCy Schubert     // Play it safe and say 3 characters are needed per 8 bits (byte).
238*7f2fe78bSCy Schubert     // Note that 20 characters are needed for a 64-bit number in
239*7f2fe78bSCy Schubert     // decimal (plus one for the string termination.
240*7f2fe78bSCy Schubert     // and include room for sessionId.
241*7f2fe78bSCy Schubert     char lid[3*sizeof(LUID)+1+5];
242*7f2fe78bSCy Schubert     DWORD sessionId;
243*7f2fe78bSCy Schubert     DWORD len = 0;
244*7f2fe78bSCy Schubert 
245*7f2fe78bSCy Schubert     *pname = 0;
246*7f2fe78bSCy Schubert 
247*7f2fe78bSCy Schubert     status = SecureClient::Token(hToken);
248*7f2fe78bSCy Schubert 
249*7f2fe78bSCy Schubert     if (!status) {
250*7f2fe78bSCy Schubert         status = get_authentication_id(hToken, &auth_id);
251*7f2fe78bSCy Schubert         }
252*7f2fe78bSCy Schubert 
253*7f2fe78bSCy Schubert     if (!status) {
254*7f2fe78bSCy Schubert         if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId))
255*7f2fe78bSCy Schubert 	        sessionId = 0;
256*7f2fe78bSCy Schubert         }
257*7f2fe78bSCy Schubert 
258*7f2fe78bSCy Schubert #ifdef _DEBUG
259*7f2fe78bSCy Schubert     if (!status) {status = alloc_token_user(hToken, &ptu);}
260*7f2fe78bSCy Schubert     if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);}
261*7f2fe78bSCy Schubert     if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);}
262*7f2fe78bSCy Schubert #endif
263*7f2fe78bSCy Schubert 
264*7f2fe78bSCy Schubert     if (!status) {
265*7f2fe78bSCy Schubert         _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId);
266*7f2fe78bSCy Schubert         lid[sizeof(lid)-1] = 0; // be safe
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert         len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1;
269*7f2fe78bSCy Schubert         *pname = (LPSTR)malloc_alloc_p(len);
270*7f2fe78bSCy Schubert         if (!*pname) status = GetLastError();
271*7f2fe78bSCy Schubert         }
272*7f2fe78bSCy Schubert 
273*7f2fe78bSCy Schubert     //
274*7f2fe78bSCy Schubert     // We used to allocate a name of the form:
275*7f2fe78bSCy Schubert     // "prefix.domain.name.sid.lid.postfix" (usually under 80
276*7f2fe78bSCy Schubert     // characters, depending on username).  However, XP thought this
277*7f2fe78bSCy Schubert     // was "invalid" (too long?) for some reason.
278*7f2fe78bSCy Schubert     //
279*7f2fe78bSCy Schubert     // Therefore, we now use "prefix.lid.postfix"
280*7f2fe78bSCy Schubert     // and for Terminal server we use "prefix.lid.sessionId.postfix"
281*7f2fe78bSCy Schubert     //
282*7f2fe78bSCy Schubert 
283*7f2fe78bSCy Schubert     if (!status) {
284*7f2fe78bSCy Schubert         _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix);
285*7f2fe78bSCy Schubert         }
286*7f2fe78bSCy Schubert 
287*7f2fe78bSCy Schubert #ifdef _DEBUG
288*7f2fe78bSCy Schubert     if (sid)
289*7f2fe78bSCy Schubert         free_alloc_p(&sid);
290*7f2fe78bSCy Schubert     if (name)
291*7f2fe78bSCy Schubert         free_alloc_p(&name);
292*7f2fe78bSCy Schubert     if (domain)
293*7f2fe78bSCy Schubert         free_alloc_p(&domain);
294*7f2fe78bSCy Schubert     if (ptu)
295*7f2fe78bSCy Schubert         free_alloc_p(&ptu);
296*7f2fe78bSCy Schubert #endif
297*7f2fe78bSCy Schubert     if (hToken && hToken != INVALID_HANDLE_VALUE)
298*7f2fe78bSCy Schubert         CloseHandle(hToken);
299*7f2fe78bSCy Schubert     if (status && *pname)
300*7f2fe78bSCy Schubert         free_alloc_p(pname);
301*7f2fe78bSCy Schubert     return status;
302*7f2fe78bSCy Schubert }
303*7f2fe78bSCy Schubert 
alloc_name(LPSTR * pname,LPSTR postfix,BOOL isNT)304*7f2fe78bSCy Schubert extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) {
305*7f2fe78bSCy Schubert     return isNT ? alloc_name_NT(pname, postfix) :
306*7f2fe78bSCy Schubert         alloc_name_9x(pname, postfix);
307*7f2fe78bSCy Schubert     }
308*7f2fe78bSCy Schubert 
alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR * ppsd)309*7f2fe78bSCy Schubert extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) {
310*7f2fe78bSCy Schubert     DWORD status = 0;
311*7f2fe78bSCy Schubert     HANDLE hToken = 0;
312*7f2fe78bSCy Schubert     PTOKEN_USER ptu = 0;
313*7f2fe78bSCy Schubert     PSID pSid = 0;
314*7f2fe78bSCy Schubert     PACL pAcl = 0;
315*7f2fe78bSCy Schubert     DWORD size = 0;
316*7f2fe78bSCy Schubert     SECURITY_DESCRIPTOR sd;
317*7f2fe78bSCy Schubert 
318*7f2fe78bSCy Schubert     *ppsd = 0;
319*7f2fe78bSCy Schubert 
320*7f2fe78bSCy Schubert     if (!status) {status = SecureClient::Token(hToken);}
321*7f2fe78bSCy Schubert 
322*7f2fe78bSCy Schubert     // Get SID:
323*7f2fe78bSCy Schubert     if (!status) {status = alloc_token_user(hToken, &ptu);}
324*7f2fe78bSCy Schubert 
325*7f2fe78bSCy Schubert     if (!status) {
326*7f2fe78bSCy Schubert         size = GetLengthSid(ptu->User.Sid);
327*7f2fe78bSCy Schubert         pSid = (PSID) malloc_alloc_p(size);
328*7f2fe78bSCy Schubert         if (!pSid) status = GetLastError();
329*7f2fe78bSCy Schubert         }
330*7f2fe78bSCy Schubert     if (!status) {
331*7f2fe78bSCy Schubert         if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError();
332*7f2fe78bSCy Schubert         }
333*7f2fe78bSCy Schubert 
334*7f2fe78bSCy Schubert     if (!status) {
335*7f2fe78bSCy Schubert         // Prepare ACL:
336*7f2fe78bSCy Schubert         size = sizeof(ACL);
337*7f2fe78bSCy Schubert         // Add an ACE:
338*7f2fe78bSCy Schubert         size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid);
339*7f2fe78bSCy Schubert         pAcl = (PACL) malloc_alloc_p(size);
340*7f2fe78bSCy Schubert         if (!pAcl) status = GetLastError();
341*7f2fe78bSCy Schubert         }
342*7f2fe78bSCy Schubert 
343*7f2fe78bSCy Schubert     if (!status) {
344*7f2fe78bSCy Schubert         if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError();
345*7f2fe78bSCy Schubert         }
346*7f2fe78bSCy Schubert 
347*7f2fe78bSCy Schubert     if (!status) {
348*7f2fe78bSCy Schubert         if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError();
349*7f2fe78bSCy Schubert         }
350*7f2fe78bSCy Schubert 
351*7f2fe78bSCy Schubert     if (!status) {
352*7f2fe78bSCy Schubert         // Prepare SD itself:
353*7f2fe78bSCy Schubert         if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError();
354*7f2fe78bSCy Schubert         }
355*7f2fe78bSCy Schubert 
356*7f2fe78bSCy Schubert     if (!status) {
357*7f2fe78bSCy Schubert         if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError();
358*7f2fe78bSCy Schubert         }
359*7f2fe78bSCy Schubert 
360*7f2fe78bSCy Schubert     if (!status) {
361*7f2fe78bSCy Schubert         if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError();
362*7f2fe78bSCy Schubert         }
363*7f2fe78bSCy Schubert 
364*7f2fe78bSCy Schubert     if (!status) {
365*7f2fe78bSCy Schubert         if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER;
366*7f2fe78bSCy Schubert         }
367*7f2fe78bSCy Schubert 
368*7f2fe78bSCy Schubert     if (!status) {
369*7f2fe78bSCy Schubert         // We now have a SD.  Let's copy it.
370*7f2fe78bSCy Schubert         {
371*7f2fe78bSCy Schubert             // This should not succeed.  Instead it should give us the size.
372*7f2fe78bSCy Schubert             BOOL ok = MakeSelfRelativeSD(&sd, 0, &size);
373*7f2fe78bSCy Schubert             }
374*7f2fe78bSCy Schubert         if (size == 0) status = GetLastError();
375*7f2fe78bSCy Schubert         }
376*7f2fe78bSCy Schubert 
377*7f2fe78bSCy Schubert     if (!status) {
378*7f2fe78bSCy Schubert         *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size);
379*7f2fe78bSCy Schubert         if (!*ppsd) status = GetLastError();
380*7f2fe78bSCy Schubert         }
381*7f2fe78bSCy Schubert 
382*7f2fe78bSCy Schubert     if (!status) {
383*7f2fe78bSCy Schubert         if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError();
384*7f2fe78bSCy Schubert         }
385*7f2fe78bSCy Schubert 
386*7f2fe78bSCy Schubert     if (ptu)                free_alloc_p(&ptu);
387*7f2fe78bSCy Schubert     if (pSid)               free_alloc_p(&pSid);
388*7f2fe78bSCy Schubert     if (pAcl)               free_alloc_p(&pAcl);
389*7f2fe78bSCy Schubert     if (hToken && hToken != INVALID_HANDLE_VALUE)   CloseHandle(hToken);
390*7f2fe78bSCy Schubert     if (status && *ppsd)    free_alloc_p(ppsd);
391*7f2fe78bSCy Schubert     return status;
392*7f2fe78bSCy Schubert }
393*7f2fe78bSCy Schubert 
394*7f2fe78bSCy Schubert DWORD
alloc_module_file_name(char * module,char ** pname)395*7f2fe78bSCy Schubert alloc_module_file_name(
396*7f2fe78bSCy Schubert     char* module,
397*7f2fe78bSCy Schubert     char** pname
398*7f2fe78bSCy Schubert     )
399*7f2fe78bSCy Schubert {
400*7f2fe78bSCy Schubert     const DWORD max = 8192;
401*7f2fe78bSCy Schubert     DWORD status = 0;
402*7f2fe78bSCy Schubert     DWORD got = 0;
403*7f2fe78bSCy Schubert     DWORD size = 512; // use low number to test...
404*7f2fe78bSCy Schubert     HMODULE h = 0;
405*7f2fe78bSCy Schubert     BOOL ok = FALSE;
406*7f2fe78bSCy Schubert     char* name = 0;
407*7f2fe78bSCy Schubert 
408*7f2fe78bSCy Schubert     if (!pname)
409*7f2fe78bSCy Schubert         return ERROR_INVALID_PARAMETER;
410*7f2fe78bSCy Schubert     *pname = 0;
411*7f2fe78bSCy Schubert 
412*7f2fe78bSCy Schubert     h = GetModuleHandle(module);
413*7f2fe78bSCy Schubert 
414*7f2fe78bSCy Schubert     if (!h) return GetLastError();
415*7f2fe78bSCy Schubert 
416*7f2fe78bSCy Schubert     // We assume size < max and size > 0
417*7f2fe78bSCy Schubert     while (!status && !ok) {
418*7f2fe78bSCy Schubert         if (size > max) {
419*7f2fe78bSCy Schubert             // XXX - Assert?
420*7f2fe78bSCy Schubert             status = ERROR_INVALID_DATA;
421*7f2fe78bSCy Schubert             continue;
422*7f2fe78bSCy Schubert         }
423*7f2fe78bSCy Schubert         if (name) free_alloc_p(&name);
424*7f2fe78bSCy Schubert         name = (char*)malloc_alloc_p(size + 1);
425*7f2fe78bSCy Schubert         if (!name) {
426*7f2fe78bSCy Schubert             status = ERROR_NOT_ENOUGH_MEMORY;
427*7f2fe78bSCy Schubert             continue;
428*7f2fe78bSCy Schubert         }
429*7f2fe78bSCy Schubert         name[size] = 0;
430*7f2fe78bSCy Schubert         got = GetModuleFileName(h, name, size);
431*7f2fe78bSCy Schubert         if (!got) {
432*7f2fe78bSCy Schubert             status = GetLastError();
433*7f2fe78bSCy Schubert             // sanity check:
434*7f2fe78bSCy Schubert             if (!status) {
435*7f2fe78bSCy Schubert                 // XXX - print nasty message...assert?
436*7f2fe78bSCy Schubert                 status = ERROR_INVALID_DATA;
437*7f2fe78bSCy Schubert             }
438*7f2fe78bSCy Schubert             continue;
439*7f2fe78bSCy Schubert         }
440*7f2fe78bSCy Schubert         // To know we're ok, we need to verify that what we got
441*7f2fe78bSCy Schubert         // was bigger than GetModuleSize thought it got.
442*7f2fe78bSCy Schubert         ok = got && (got < size) && !name[got];
443*7f2fe78bSCy Schubert         size *= 2;
444*7f2fe78bSCy Schubert     }
445*7f2fe78bSCy Schubert     if (status && name)
446*7f2fe78bSCy Schubert         free_alloc_p(&name);
447*7f2fe78bSCy Schubert     else
448*7f2fe78bSCy Schubert         *pname = name;
449*7f2fe78bSCy Schubert     return status;
450*7f2fe78bSCy Schubert }
451*7f2fe78bSCy Schubert 
452*7f2fe78bSCy Schubert DWORD
alloc_module_dir_name(char * module,char ** pname)453*7f2fe78bSCy Schubert alloc_module_dir_name(
454*7f2fe78bSCy Schubert     char* module,
455*7f2fe78bSCy Schubert     char** pname
456*7f2fe78bSCy Schubert     )
457*7f2fe78bSCy Schubert {
458*7f2fe78bSCy Schubert     DWORD status = alloc_module_file_name(module, pname);
459*7f2fe78bSCy Schubert     if (!status) {
460*7f2fe78bSCy Schubert         char* name = *pname;
461*7f2fe78bSCy Schubert         char* p = name + strlen(name);
462*7f2fe78bSCy Schubert         while ((p >= name) && (*p != '\\') && (*p != '/')) p--;
463*7f2fe78bSCy Schubert         if (p < name) {
464*7f2fe78bSCy Schubert             free_alloc_p(pname);
465*7f2fe78bSCy Schubert             status = ERROR_INVALID_DATA;
466*7f2fe78bSCy Schubert         } else {
467*7f2fe78bSCy Schubert             *p = 0;
468*7f2fe78bSCy Schubert         }
469*7f2fe78bSCy Schubert     }
470*7f2fe78bSCy Schubert     return status;
471*7f2fe78bSCy Schubert }
472*7f2fe78bSCy Schubert 
473*7f2fe78bSCy Schubert DWORD
alloc_module_dir_name_with_file(char * module,char * file,char ** pname)474*7f2fe78bSCy Schubert alloc_module_dir_name_with_file(
475*7f2fe78bSCy Schubert     char* module,
476*7f2fe78bSCy Schubert     char* file,
477*7f2fe78bSCy Schubert     char** pname
478*7f2fe78bSCy Schubert     )
479*7f2fe78bSCy Schubert {
480*7f2fe78bSCy Schubert     DWORD status = alloc_module_dir_name(module, pname);
481*7f2fe78bSCy Schubert     if (!status) {
482*7f2fe78bSCy Schubert         char* name = *pname;
483*7f2fe78bSCy Schubert         size_t name_size = strlen(name);
484*7f2fe78bSCy Schubert         size_t size = name_size + 1 + strlen(file) + 1;
485*7f2fe78bSCy Schubert         char* result = (char*)malloc_alloc_p(size);
486*7f2fe78bSCy Schubert         if (!result) {
487*7f2fe78bSCy Schubert             status = ERROR_NOT_ENOUGH_MEMORY;
488*7f2fe78bSCy Schubert             free_alloc_p(pname);
489*7f2fe78bSCy Schubert         } else {
490*7f2fe78bSCy Schubert             strcpy(result, name);
491*7f2fe78bSCy Schubert             result[name_size] = '\\';
492*7f2fe78bSCy Schubert             strcpy(result + name_size + 1, file);
493*7f2fe78bSCy Schubert             free_alloc_p(pname);
494*7f2fe78bSCy Schubert             *pname = result;
495*7f2fe78bSCy Schubert         }
496*7f2fe78bSCy Schubert     }
497*7f2fe78bSCy Schubert     return status;
498*7f2fe78bSCy Schubert }
499*7f2fe78bSCy Schubert 
alloc_cmdline_2_args(char * prog,char * arg1,char * arg2,char ** pname)500*7f2fe78bSCy Schubert DWORD alloc_cmdline_2_args(char* prog,
501*7f2fe78bSCy Schubert                            char* arg1,
502*7f2fe78bSCy Schubert                            char* arg2,
503*7f2fe78bSCy Schubert                            char** pname) {
504*7f2fe78bSCy Schubert     DWORD   status  = 0;
505*7f2fe78bSCy Schubert     size_t  size    = strlen(prog) + strlen(arg1) + strlen(arg2) + 4;
506*7f2fe78bSCy Schubert     char*   result  = (char*)malloc_alloc_p(size);
507*7f2fe78bSCy Schubert     if (!result) {
508*7f2fe78bSCy Schubert         status = ERROR_NOT_ENOUGH_MEMORY;
509*7f2fe78bSCy Schubert         }
510*7f2fe78bSCy Schubert     else {
511*7f2fe78bSCy Schubert         strcpy(result, prog);
512*7f2fe78bSCy Schubert         strcat(result, " ");
513*7f2fe78bSCy Schubert         strcat(result, arg1);
514*7f2fe78bSCy Schubert         strcat(result, " ");
515*7f2fe78bSCy Schubert         strcat(result, arg2);
516*7f2fe78bSCy Schubert         *pname = result;
517*7f2fe78bSCy Schubert         }
518*7f2fe78bSCy Schubert     cci_debug_printf("%s made <%s>", __FUNCTION__, result);
519*7f2fe78bSCy Schubert     return status;
520*7f2fe78bSCy Schubert     }
521