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