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
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.
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 ***** */
37 #include "zipstruct.h"
39 #include "CertReader.h"
42 #include "nsIServiceManager.h"
43 #include "nsISignatureVerifier.h"
44 #include "nsIInputStream.h"
45 #include "nsIPrincipal.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)
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);
72 * Converts a four byte ugly endianed integer
73 * to our platform's integer.
77 static unsigned long xtolong (unsigned char *ll
)
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) );
89 static int my_inflate(unsigned char* compr
, PRUint32 comprLen
, unsigned char* uncompr
, PRUint32 uncomprLen
)
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.
101 if (inflateInit2 (&d_stream
, -MAX_WBITS
) != Z_OK
)
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
);
117 err
= inflateEnd(&d_stream
);
124 CertReader::CertReader(nsIURI
* aURI
, nsISupports
* aContext
, nsPICertNotification
* aObs
):
131 CertReader::~CertReader()
135 NS_IMPL_ISUPPORTS2(CertReader
, nsIStreamListener
, nsIRequestObserver
)
138 CertReader::OnStartRequest(nsIRequest
*request
, nsISupports
* context
)
140 mVerifier
= do_GetService(SIGNATURE_VERIFIER_CONTRACTID
);
142 return NS_BINDING_ABORTED
;
144 mLeftoverBuffer
.Truncate();
149 CertReader::OnDataAvailable(nsIRequest
*request
,
150 nsISupports
* context
,
151 nsIInputStream
*aIStream
,
152 PRUint32 aSourceOffset
,
156 return NS_BINDING_ABORTED
;
164 size
= PR_MIN(aLength
, sizeof(buf
));
166 rv
= aIStream
->Read(buf
, size
, &amt
);
172 mLeftoverBuffer
.Append(buf
, amt
);
174 if (mLeftoverBuffer
.Length() < ZIPLOCAL_SIZE
)
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.
201 // the assumption here is that we have the fileEntry in mLeftoverBuffer
204 unsigned char* orgData
= nsnull
;
205 unsigned char* sigData
= nsnull
;
206 const char* data
= (caret
+
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
))
218 // file is uncompressed, can use the data where it is
220 sigData
= (unsigned char*)data
;
224 if (orgSize
== 0 || orgSize
> MAX_SIGNATURE_SIZE
)
225 return NS_BINDING_ABORTED
;
227 orgData
= (unsigned char*)malloc(orgSize
);
229 return NS_BINDING_ABORTED
;
231 err
= my_inflate((unsigned char*)data
,
241 // unsupported compression method
249 rv
= mVerifier
->VerifySignature((char*)sigData
, sigSize
, nsnull
, 0,
250 &verifyError
, getter_AddRefs(mPrincipal
));
255 // Cancel the load now that we've verified the signature
256 return NS_BINDING_ABORTED
;
259 return NS_OK
; // continue reading
263 CertReader::OnStopRequest(nsIRequest
*request
, nsISupports
* context
,
266 mObserver
->OnCertAvailable(mURI
,