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 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 */ 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 */ 90 HRESULT WINAPI DllUnregisterServer(void) 91 { 92 CryptSIPRemoveProvider(&mySubject); 93 return S_OK; 94 } 95 96 /*********************************************************************** 97 * MsiSIPGetSignedDataMsg (MSISIP.@) 98 */ 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 */ 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