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