xref: /reactos/dll/win32/msisip/main.c (revision bc2a33a8)
1 /*
2  * Copyright 2008 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include <stdarg.h>
20 #include "windef.h"
21 #include "winbase.h"
22 #include "wincrypt.h"
23 #include "mssip.h"
24 #define COBJMACROS
25 #include "objbase.h"
26 #include "initguid.h"
27 #include "wine/debug.h"
28 
29 WINE_DEFAULT_DEBUG_CHANNEL(msisip);
30 
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)31 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
32 {
33     TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
34 
35     switch (fdwReason)
36     {
37         case DLL_WINE_PREATTACH:
38             return FALSE;    /* prefer native version */
39         case DLL_PROCESS_ATTACH:
40             DisableThreadLibraryCalls(hinstDLL);
41             break;
42     }
43 
44     return TRUE;
45 }
46 
47 static GUID mySubject = { 0x000c10f1, 0x0000, 0x0000,
48  { 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }};
49 
50 /***********************************************************************
51  *              DllRegisterServer (MSISIP.@)
52  */
DllRegisterServer(void)53 HRESULT WINAPI DllRegisterServer(void)
54 {
55     static WCHAR msisip[] = { 'M','S','I','S','I','P','.','D','L','L',0 };
56     static WCHAR getSignedDataMsg[] = { 'M','s','i','S','I','P','G','e','t',
57      'S','i','g','n','e','d','D','a','t','a','M','s','g',0 };
58     static WCHAR putSignedDataMsg[] = { 'M','s','i','S','I','P','P','u','t',
59      'S','i','g','n','e','d','D','a','t','a','M','s','g',0 };
60     static WCHAR createIndirectData[] = { 'M','s','i','S','I','P',
61      'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a',
62      0 };
63     static WCHAR verifyIndirectData[] = { 'M','s','i','S','I','P',
64      'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a',
65      0 };
66     static WCHAR removeSignedDataMsg[] = { 'M','s','i','S','I','P','R','e','m',
67      'o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g', 0 };
68     static WCHAR isMyTypeOfFile[] = { 'M','s','i','S','I','P',
69      'I','s','M','y','T','y','p','e','O','f','F','i','l','e',0 };
70 
71     SIP_ADD_NEWPROVIDER prov;
72 
73     memset(&prov, 0, sizeof(prov));
74     prov.cbStruct = sizeof(prov);
75     prov.pwszDLLFileName = msisip;
76     prov.pgSubject = &mySubject;
77     prov.pwszGetFuncName = getSignedDataMsg;
78     prov.pwszPutFuncName = putSignedDataMsg;
79     prov.pwszCreateFuncName = createIndirectData;
80     prov.pwszVerifyFuncName = verifyIndirectData;
81     prov.pwszRemoveFuncName = removeSignedDataMsg;
82     prov.pwszIsFunctionNameFmt2 = isMyTypeOfFile;
83     prov.pwszGetCapFuncName = NULL;
84     return CryptSIPAddProvider(&prov) ? S_OK : S_FALSE;
85 }
86 
87 /***********************************************************************
88  *              DllUnregisterServer (MSISIP.@)
89  */
DllUnregisterServer(void)90 HRESULT WINAPI DllUnregisterServer(void)
91 {
92     CryptSIPRemoveProvider(&mySubject);
93     return S_OK;
94 }
95 
96 /***********************************************************************
97  *              MsiSIPGetSignedDataMsg  (MSISIP.@)
98  */
MsiSIPGetSignedDataMsg(SIP_SUBJECTINFO * pSubjectInfo,DWORD * pdwEncodingType,DWORD dwIndex,DWORD * pcbSignedDataMsg,BYTE * pbSignedDataMsg)99 BOOL WINAPI MsiSIPGetSignedDataMsg(SIP_SUBJECTINFO *pSubjectInfo,
100  DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg,
101  BYTE *pbSignedDataMsg)
102 {
103     static const WCHAR digitalSig[] = { 5,'D','i','g','i','t','a','l',
104      'S','i','g','n','a','t','u','r','e',0 };
105     BOOL ret = FALSE;
106     IStorage *stg = NULL;
107     HRESULT r;
108     IStream *stm = NULL;
109     BYTE hdr[2], len[sizeof(DWORD)];
110     DWORD count, lenBytes, dataBytes;
111 
112     TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex,
113           pcbSignedDataMsg, pbSignedDataMsg);
114 
115     r = StgOpenStorage(pSubjectInfo->pwsFileName, NULL,
116      STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
117     if (FAILED(r))
118     {
119         TRACE("couldn't open %s\n", debugstr_w(pSubjectInfo->pwsFileName));
120         goto end;
121     }
122 
123     r = IStorage_OpenStream(stg, digitalSig, 0,
124      STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stm);
125     if (FAILED(r))
126     {
127         TRACE("couldn't find digital signature stream\n");
128         goto freestorage;
129     }
130 
131     r = IStream_Read(stm, hdr, sizeof(hdr), &count);
132     if (FAILED(r) || count != sizeof(hdr))
133         goto freestream;
134     if (hdr[0] != 0x30)
135     {
136         WARN("unexpected data in digital sig: 0x%02x%02x\n", hdr[0], hdr[1]);
137         goto freestream;
138     }
139 
140     /* Read the asn.1 length from the stream.  Only supports definite-length
141      * values, which DER-encoded signatures should be.
142      */
143     if (hdr[1] == 0x80)
144     {
145         WARN("indefinite-length encoding not supported!\n");
146         goto freestream;
147     }
148     else if (hdr[1] & 0x80)
149     {
150         DWORD temp;
151         LPBYTE ptr;
152 
153         lenBytes = hdr[1] & 0x7f;
154         if (lenBytes > sizeof(DWORD))
155         {
156             WARN("asn.1 length too long (%d)\n", lenBytes);
157             goto freestream;
158         }
159         r = IStream_Read(stm, len, lenBytes, &count);
160         if (FAILED(r) || count != lenBytes)
161             goto freestream;
162         dataBytes = 0;
163         temp = lenBytes;
164         ptr = len;
165         while (temp--)
166         {
167             dataBytes <<= 8;
168             dataBytes |= *ptr++;
169         }
170     }
171     else
172     {
173         lenBytes = 0;
174         dataBytes = hdr[1];
175     }
176 
177     if (!pbSignedDataMsg)
178     {
179         *pcbSignedDataMsg = 2 + lenBytes + dataBytes;
180         ret = TRUE;
181     }
182     else if (*pcbSignedDataMsg < 2 + lenBytes + dataBytes)
183     {
184         SetLastError(ERROR_INSUFFICIENT_BUFFER);
185         *pcbSignedDataMsg = 2 + lenBytes + dataBytes;
186     }
187     else
188     {
189         LPBYTE ptr = pbSignedDataMsg;
190 
191         memcpy(ptr, hdr, sizeof(hdr));
192         ptr += sizeof(hdr);
193         if (lenBytes)
194         {
195             memcpy(ptr, len, lenBytes);
196             ptr += lenBytes;
197         }
198         r = IStream_Read(stm, ptr, dataBytes, &count);
199         if (SUCCEEDED(r) && count == dataBytes)
200         {
201             *pdwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
202             *pcbSignedDataMsg = 2 + lenBytes + dataBytes;
203             ret = TRUE;
204         }
205     }
206 
207 freestream:
208     IStream_Release(stm);
209 freestorage:
210     IStorage_Release(stg);
211 end:
212 
213     TRACE("returning %d\n", ret);
214     return ret;
215 }
216 
217 DEFINE_GUID(CLSID_MsiTransform, 0x000c1082,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
218 DEFINE_GUID(CLSID_MsiDatabase,  0x000c1084,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
219 DEFINE_GUID(CLSID_MsiPatch,     0x000c1086,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
220 
221 /***********************************************************************
222  *              MsiSIPIsMyTypeOfFile (MSISIP.@)
223  */
MsiSIPIsMyTypeOfFile(WCHAR * name,GUID * subject)224 BOOL WINAPI MsiSIPIsMyTypeOfFile(WCHAR *name, GUID *subject)
225 {
226     BOOL ret = FALSE;
227     IStorage *stg = NULL;
228     HRESULT r;
229 
230     TRACE("(%s, %p)\n", debugstr_w(name), subject);
231 
232     r = StgOpenStorage(name, NULL, STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE,
233      NULL, 0, &stg);
234     if (SUCCEEDED(r))
235     {
236         STATSTG stat;
237 
238         r = IStorage_Stat(stg, &stat, STATFLAG_NONAME);
239         if (SUCCEEDED(r))
240         {
241             if (IsEqualGUID(&stat.clsid, &CLSID_MsiDatabase) ||
242              IsEqualGUID(&stat.clsid, &CLSID_MsiPatch) ||
243              IsEqualGUID(&stat.clsid, &CLSID_MsiTransform))
244             {
245                 ret = TRUE;
246                 *subject = mySubject;
247             }
248         }
249         IStorage_Release(stg);
250     }
251     return ret;
252 }
253