Bug 458256. Use LoadLibraryW instead of LoadLibrary (patch by DougT). r+sr=vlad
[wine-gecko.git] / xpinstall / src / CertReader.cpp
blob83063243c6bd90172db70e414a62806aa5f26ffc
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is XPInstall Signing.
16 * The Initial Developer of the Original Code is Doug Turner.
17 * Portions created by the Initial Developer are Copyright (C) 2002
18 * the Initial Developer. All Rights Reserved.
20 * Contributor(s):
22 * Alternatively, the contents of this file may be used under the terms of
23 * either the GNU General Public License Version 2 or later (the "GPL"), or
24 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25 * in which case the provisions of the GPL or the LGPL are applicable instead
26 * of those above. If you wish to allow use of your version of this file only
27 * under the terms of either the GPL or the LGPL, and not to allow others to
28 * use your version of this file under the terms of the MPL, indicate your
29 * decision by deleting the provisions above and replace them with the notice
30 * and other provisions required by the GPL or the LGPL. If you do not delete
31 * the provisions above, a recipient may use your version of this file under
32 * the terms of any one of the MPL, the GPL or the LGPL.
34 * ***** END LICENSE BLOCK ***** */
36 #include "zlib.h"
37 #include "zipstruct.h"
39 #include "CertReader.h"
41 #include "nsCRT.h"
42 #include "nsIServiceManager.h"
43 #include "nsISignatureVerifier.h"
44 #include "nsIInputStream.h"
45 #include "nsIPrincipal.h"
46 #include "nsIURI.h"
47 #include "nsPICertNotification.h"
50 #include "nsNetUtil.h"
52 // just a guess at the max size of the cert.
53 #define MAX_SIGNATURE_SIZE (32*1024)
57 * x t o i n t
59 * Converts a two byte ugly endianed integer
60 * to our platform's integer.
64 static unsigned int xtoint (unsigned char *ii)
66 return (int) (ii [0]) | ((int) ii [1] << 8);
70 * x t o l o n g
72 * Converts a four byte ugly endianed integer
73 * to our platform's integer.
77 static unsigned long xtolong (unsigned char *ll)
79 unsigned long ret;
81 ret = ((((unsigned long) ll [0]) << 0) |
82 (((unsigned long) ll [1]) << 8) |
83 (((unsigned long) ll [2]) << 16) |
84 (((unsigned long) ll [3]) << 24) );
86 return ret;
89 static int my_inflate(unsigned char* compr, PRUint32 comprLen, unsigned char* uncompr, PRUint32 uncomprLen)
91 int err;
92 z_stream d_stream; /* decompression stream */
93 memset (&d_stream, 0, sizeof (d_stream));
95 // buffer is way to small to even deal with.
96 if (uncomprLen < 10)
97 return -1;
99 *uncompr = '\0';
101 if (inflateInit2 (&d_stream, -MAX_WBITS) != Z_OK)
102 return -1;
104 d_stream.next_in = compr;
105 d_stream.avail_in = (uInt)comprLen;
107 d_stream.next_out = uncompr;
108 d_stream.avail_out = (uInt)uncomprLen;
110 err = inflate(&d_stream, Z_NO_FLUSH);
112 if (err != Z_OK && err != Z_STREAM_END) {
113 inflateEnd(&d_stream);
114 return -1;
117 err = inflateEnd(&d_stream);
118 if (err != Z_OK) {
119 return -1;
121 return 0;
124 CertReader::CertReader(nsIURI* aURI, nsISupports* aContext, nsPICertNotification* aObs):
125 mContext(aContext),
126 mURI(aURI),
127 mObserver(aObs)
131 CertReader::~CertReader()
135 NS_IMPL_ISUPPORTS2(CertReader, nsIStreamListener, nsIRequestObserver)
137 NS_IMETHODIMP
138 CertReader::OnStartRequest(nsIRequest *request, nsISupports* context)
140 mVerifier = do_GetService(SIGNATURE_VERIFIER_CONTRACTID);
141 if (!mVerifier)
142 return NS_BINDING_ABORTED;
144 mLeftoverBuffer.Truncate();
145 return NS_OK;
148 NS_IMETHODIMP
149 CertReader::OnDataAvailable(nsIRequest *request,
150 nsISupports* context,
151 nsIInputStream *aIStream,
152 PRUint32 aSourceOffset,
153 PRUint32 aLength)
155 if (!mVerifier)
156 return NS_BINDING_ABORTED;
158 char buf[4096];
159 PRUint32 amt, size;
160 nsresult rv;
162 while (aLength)
164 size = PR_MIN(aLength, sizeof(buf));
166 rv = aIStream->Read(buf, size, &amt);
167 if (NS_FAILED(rv))
168 return rv;
170 aLength -= amt;
172 mLeftoverBuffer.Append(buf, amt);
174 if (mLeftoverBuffer.Length() < ZIPLOCAL_SIZE)
175 continue;
177 const char* caret = mLeftoverBuffer.get();
179 ZipLocal_* ziplocal = (ZipLocal_*) caret;
181 if (xtolong(ziplocal->signature) != LOCALSIG)
182 return NS_BINDING_ABORTED;
184 // did we read the entire file entry into memory?
185 PRUint32 fileEntryLen = (ZIPLOCAL_SIZE +
186 xtoint(ziplocal->filename_len) +
187 xtoint(ziplocal->extrafield_len) +
188 xtolong(ziplocal->size));
191 // prevent downloading a huge file on an unsigned cert
192 if (fileEntryLen > MAX_SIGNATURE_SIZE)
193 return NS_BINDING_ABORTED;
195 if (mLeftoverBuffer.Length() < fileEntryLen)
197 // we are just going to buffer and continue.
198 continue;
201 // the assumption here is that we have the fileEntry in mLeftoverBuffer
203 int err = 0;
204 unsigned char* orgData = nsnull;
205 unsigned char* sigData = nsnull;
206 const char* data = (caret +
207 ZIPLOCAL_SIZE +
208 xtoint(ziplocal->filename_len) +
209 xtoint(ziplocal->extrafield_len));
211 PRUint32 sigSize = 0;
212 PRUint32 orgSize = xtolong ((unsigned char *) ziplocal->orglen);
213 PRUint32 cSize = xtolong ((unsigned char *) ziplocal->size);
215 switch (xtoint(ziplocal->method))
217 case STORED:
218 // file is uncompressed, can use the data where it is
219 sigSize = cSize;
220 sigData = (unsigned char*)data;
221 break;
223 case DEFLATED:
224 if (orgSize == 0 || orgSize > MAX_SIGNATURE_SIZE)
225 return NS_BINDING_ABORTED;
227 orgData = (unsigned char*)malloc(orgSize);
228 if (!orgData)
229 return NS_BINDING_ABORTED;
231 err = my_inflate((unsigned char*)data,
232 cSize,
233 orgData,
234 orgSize);
236 sigSize = orgSize;
237 sigData = orgData;
238 break;
240 default:
241 // unsupported compression method
242 err = Z_DATA_ERROR;
243 break;
246 if (err == 0)
248 PRInt32 verifyError;
249 rv = mVerifier->VerifySignature((char*)sigData, sigSize, nsnull, 0,
250 &verifyError, getter_AddRefs(mPrincipal));
252 if (orgData)
253 free(orgData);
255 // Cancel the load now that we've verified the signature
256 return NS_BINDING_ABORTED;
259 return NS_OK; // continue reading
262 NS_IMETHODIMP
263 CertReader::OnStopRequest(nsIRequest *request, nsISupports* context,
264 nsresult aStatus)
266 mObserver->OnCertAvailable(mURI,
267 mContext,
268 aStatus,
269 mPrincipal);
271 return NS_OK;