~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/manager/ssl/src/nsCRLManager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contents of this file are subject to the Mozilla Public
 
3
 * License Version 1.1 (the "License"); you may not use this file
 
4
 * except in compliance with the License. You may obtain a copy of
 
5
 * the License at http://www.mozilla.org/MPL/
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS
 
8
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
9
 * implied. See the License for the specific language governing
 
10
 * rights and limitations under the License.
 
11
 * 
 
12
 * The Original Code is the Netscape security libraries.
 
13
 * 
 
14
 * The Initial Developer of the Original Code is Netscape
 
15
 * Communications Corporation.  Portions created by Netscape are 
 
16
 * Copyright (C) 2000 Netscape Communications Corporation.  All
 
17
 * Rights Reserved.
 
18
 * 
 
19
 * Contributor(s):
 
20
 * 
 
21
 * Alternatively, the contents of this file may be used under the
 
22
 * terms of the GNU General Public License Version 2 or later (the
 
23
 * "GPL"), in which case the provisions of the GPL are applicable 
 
24
 * instead of those above.  If you wish to allow use of your 
 
25
 * version of this file only under the terms of the GPL and not to
 
26
 * allow others to use your version of this file under the MPL,
 
27
 * indicate your decision by deleting the provisions above and
 
28
 * replace them with the notice and other provisions required by
 
29
 * the GPL.  If you do not delete the provisions above, a recipient
 
30
 * may use your version of this file under either the MPL or the
 
31
 * GPL.
 
32
 *
 
33
 */
 
34
 
 
35
#include "nsCRLManager.h"
 
36
#include "nsCRLInfo.h"
 
37
 
 
38
#include "nsCOMPtr.h"
 
39
#include "nsIDateTimeFormat.h"
 
40
#include "nsDateTimeFormatCID.h"
 
41
#include "nsComponentManagerUtils.h"
 
42
#include "nsReadableUtils.h"
 
43
#include "nsNSSComponent.h"
 
44
#include "nsIWindowWatcher.h"
 
45
#include "nsCOMPtr.h"
 
46
#include "nsIPrompt.h"
 
47
#include "nsICertificateDialogs.h"
 
48
#include "nsArray.h"
 
49
#include "nsNSSShutDown.h"
 
50
 
 
51
#include "nsNSSCertHeader.h"
 
52
 
 
53
#include "nspr.h"
 
54
extern "C" {
 
55
#include "pk11func.h"
 
56
#include "certdb.h"
 
57
#include "cert.h"
 
58
#include "secerr.h"
 
59
#include "nssb64.h"
 
60
#include "secasn1.h"
 
61
#include "secder.h"
 
62
}
 
63
#include "ssl.h"
 
64
#include "ocsp.h"
 
65
#include "plbase64.h"
 
66
 
 
67
static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
 
68
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
 
69
 
 
70
NS_IMPL_ISUPPORTS1(nsCRLManager, nsICRLManager)
 
71
 
 
72
nsCRLManager::nsCRLManager()
 
73
{
 
74
}
 
75
 
 
76
nsCRLManager::~nsCRLManager()
 
77
{
 
78
}
 
79
 
 
80
NS_IMETHODIMP 
 
81
nsCRLManager::ImportCrl (PRUint8 *aData, PRUint32 aLength, nsIURI * aURI, PRUint32 aType, PRBool doSilentDonwload, const PRUnichar* crlKey)
 
82
{
 
83
  nsNSSShutDownPreventionLock locker;
 
84
  nsresult rv;
 
85
  PRArenaPool *arena = NULL;
 
86
  CERTCertificate *caCert;
 
87
  SECItem derName = { siBuffer, NULL, 0 };
 
88
  SECItem derCrl;
 
89
  CERTSignedData sd;
 
90
  SECStatus sec_rv;
 
91
  CERTSignedCrl *crl;
 
92
  nsCAutoString url;
 
93
  nsCOMPtr<nsICRLInfo> crlData;
 
94
  PRBool importSuccessful;
 
95
  PRInt32 errorCode;
 
96
  nsString errorMessage;
 
97
  
 
98
  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
 
99
  if (NS_FAILED(rv)) return rv;
 
100
                 
 
101
  aURI->GetSpec(url);
 
102
  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
103
  if (!arena) {
 
104
    goto loser;
 
105
  }
 
106
  memset(&sd, 0, sizeof(sd));
 
107
 
 
108
  derCrl.data = (unsigned char*)aData;
 
109
  derCrl.len = aLength;
 
110
  sec_rv = CERT_KeyFromDERCrl(arena, &derCrl, &derName);
 
111
  if (sec_rv != SECSuccess) {
 
112
    goto loser;
 
113
  }
 
114
 
 
115
  caCert = CERT_FindCertByName(CERT_GetDefaultCertDB(), &derName);
 
116
  if (!caCert) {
 
117
    if (aType == SEC_KRL_TYPE){
 
118
      goto loser;
 
119
    }
 
120
  } else {
 
121
    sec_rv = SEC_ASN1DecodeItem(arena,
 
122
                            &sd, SEC_ASN1_GET(CERT_SignedDataTemplate), 
 
123
                            &derCrl);
 
124
    if (sec_rv != SECSuccess) {
 
125
      goto loser;
 
126
    }
 
127
    sec_rv = CERT_VerifySignedData(&sd, caCert, PR_Now(),
 
128
                               nsnull);
 
129
    if (sec_rv != SECSuccess) {
 
130
      goto loser;
 
131
    }
 
132
  }
 
133
  
 
134
  crl = SEC_NewCrl(CERT_GetDefaultCertDB(), NS_CONST_CAST(char*, url.get()), &derCrl,
 
135
                   aType);
 
136
  
 
137
  if (!crl) {
 
138
    goto loser;
 
139
  }
 
140
 
 
141
  crlData = new nsCRLInfo(crl);
 
142
  SSL_ClearSessionCache();
 
143
  SEC_DestroyCrl(crl);
 
144
  
 
145
  importSuccessful = PR_TRUE;
 
146
  goto done;
 
147
 
 
148
loser:
 
149
  importSuccessful = PR_FALSE;
 
150
  errorCode = PR_GetError();
 
151
  switch (errorCode) {
 
152
    case SEC_ERROR_CRL_EXPIRED:
 
153
      nssComponent->GetPIPNSSBundleString("CrlImportFailureExpired", errorMessage);
 
154
      break;
 
155
 
 
156
        case SEC_ERROR_CRL_BAD_SIGNATURE:
 
157
      nssComponent->GetPIPNSSBundleString("CrlImportFailureBadSignature", errorMessage);
 
158
      break;
 
159
 
 
160
        case SEC_ERROR_CRL_INVALID:
 
161
      nssComponent->GetPIPNSSBundleString("CrlImportFailureInvalid", errorMessage);
 
162
      break;
 
163
 
 
164
        case SEC_ERROR_OLD_CRL:
 
165
      nssComponent->GetPIPNSSBundleString("CrlImportFailureOld", errorMessage);
 
166
      break;
 
167
 
 
168
        case SEC_ERROR_CRL_NOT_YET_VALID:
 
169
      nssComponent->GetPIPNSSBundleString("CrlImportFailureNotYetValid", errorMessage);
 
170
      break;
 
171
 
 
172
    default:
 
173
      nssComponent->GetPIPNSSBundleString("CrlImportFailureReasonUnknown", errorMessage);
 
174
      errorMessage.AppendInt(errorCode,16);
 
175
      break;
 
176
  }
 
177
 
 
178
done:
 
179
          
 
180
  if(!doSilentDonwload){
 
181
    if (!importSuccessful){
 
182
      nsString message;
 
183
      nsString temp;
 
184
      nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
 
185
      nsCOMPtr<nsIPrompt> prompter;
 
186
      if (wwatch){
 
187
        wwatch->GetNewPrompter(0, getter_AddRefs(prompter));
 
188
        nssComponent->GetPIPNSSBundleString("CrlImportFailure1", message);
 
189
        message.Append(NS_LITERAL_STRING("\n").get());
 
190
        message.Append(errorMessage);
 
191
        nssComponent->GetPIPNSSBundleString("CrlImportFailure2", temp);
 
192
        message.Append(NS_LITERAL_STRING("\n").get());
 
193
        message.Append(temp);
 
194
     
 
195
        if(prompter) {
 
196
          nsPSMUITracker tracker;
 
197
          if (!tracker.isUIForbidden()) {
 
198
            prompter->Alert(0, message.get());
 
199
          }
 
200
        }
 
201
      }
 
202
    } else {
 
203
      nsCOMPtr<nsICertificateDialogs> certDialogs;
 
204
      // Not being able to display the success dialog should not
 
205
      // be a fatal error, so don't return a failure code.
 
206
      {
 
207
        nsPSMUITracker tracker;
 
208
        if (tracker.isUIForbidden()) {
 
209
          rv = NS_ERROR_NOT_AVAILABLE;
 
210
        }
 
211
        else {
 
212
          rv = ::getNSSDialogs(getter_AddRefs(certDialogs),
 
213
            NS_GET_IID(nsICertificateDialogs), NS_CERTIFICATEDIALOGS_CONTRACTID);
 
214
        }
 
215
      }
 
216
      if (NS_SUCCEEDED(rv)) {
 
217
        nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
 
218
        certDialogs->CrlImportStatusDialog(cxt, crlData);
 
219
      }
 
220
    }
 
221
  } else {
 
222
    if(crlKey == nsnull){
 
223
      return NS_ERROR_FAILURE;
 
224
    }
 
225
    nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID,&rv);
 
226
    if (NS_FAILED(rv)){
 
227
      return rv;
 
228
    }
 
229
    
 
230
    nsCAutoString updateErrCntPrefStr(CRL_AUTOUPDATE_ERRCNT_PREF);
 
231
    updateErrCntPrefStr.AppendWithConversion(crlKey);
 
232
    if(importSuccessful){
 
233
      PRUnichar *updateTime;
 
234
      nsCAutoString updateTimeStr;
 
235
      nsCString updateURL;
 
236
      PRInt32 timingTypePref;
 
237
      double dayCnt;
 
238
      char *dayCntStr;
 
239
      nsCAutoString updateTypePrefStr(CRL_AUTOUPDATE_TIMIINGTYPE_PREF);
 
240
      nsCAutoString updateTimePrefStr(CRL_AUTOUPDATE_TIME_PREF);
 
241
      nsCAutoString updateUrlPrefStr(CRL_AUTOUPDATE_URL_PREF);
 
242
      nsCAutoString updateDayCntPrefStr(CRL_AUTOUPDATE_DAYCNT_PREF);
 
243
      nsCAutoString updateFreqCntPrefStr(CRL_AUTOUPDATE_FREQCNT_PREF);
 
244
      updateTypePrefStr.AppendWithConversion(crlKey);
 
245
      updateTimePrefStr.AppendWithConversion(crlKey);
 
246
      updateUrlPrefStr.AppendWithConversion(crlKey);
 
247
      updateDayCntPrefStr.AppendWithConversion(crlKey);
 
248
      updateFreqCntPrefStr.AppendWithConversion(crlKey);
 
249
 
 
250
      pref->GetIntPref(updateTypePrefStr.get(),&timingTypePref);
 
251
      
 
252
      //Compute and update the next download instant
 
253
      if(timingTypePref == TYPE_AUTOUPDATE_TIME_BASED){
 
254
        pref->GetCharPref(updateDayCntPrefStr.get(),&dayCntStr);
 
255
      }else{
 
256
        pref->GetCharPref(updateFreqCntPrefStr.get(),&dayCntStr);
 
257
      }
 
258
      dayCnt = atof(dayCntStr);
 
259
      nsMemory::Free(dayCntStr);
 
260
 
 
261
      PRBool toBeRescheduled = PR_FALSE;
 
262
      if(NS_SUCCEEDED(ComputeNextAutoUpdateTime(crlData, timingTypePref, dayCnt, &updateTime))){
 
263
        updateTimeStr.AssignWithConversion(updateTime);
 
264
        nsMemory::Free(updateTime);
 
265
        pref->SetCharPref(updateTimePrefStr.get(),updateTimeStr.get());
 
266
        //Now, check if this update time is already in the past. This would
 
267
        //imply we have downloaded the same crl, or there is something wrong
 
268
        //with the next update date. We will not reschedule this crl in this
 
269
        //session anymore - or else, we land into a loop. It would anyway be
 
270
        //imported once the browser is restarted.
 
271
        PRTime nextTime;
 
272
        PR_ParseTimeString(updateTimeStr.get(),PR_TRUE, &nextTime);
 
273
        if(LL_CMP(nextTime, > , PR_Now())){
 
274
          toBeRescheduled = PR_TRUE;
 
275
        }
 
276
      }
 
277
      
 
278
      //Update the url to download from, next time
 
279
      crlData->GetLastFetchURL(updateURL);
 
280
      pref->SetCharPref(updateUrlPrefStr.get(),updateURL.get());
 
281
      
 
282
      pref->SetIntPref(updateErrCntPrefStr.get(),0);
 
283
      pref->SavePrefFile(nsnull);
 
284
      
 
285
      if(toBeRescheduled == PR_TRUE){
 
286
        nsAutoString hashKey(crlKey);
 
287
        nssComponent->RemoveCrlFromList(hashKey);
 
288
        nssComponent->DefineNextTimer();
 
289
      }
 
290
 
 
291
    } else{
 
292
      PRInt32 errCnt;
 
293
      nsCAutoString errMsg;
 
294
      nsCAutoString updateErrDetailPrefStr(CRL_AUTOUPDATE_ERRDETAIL_PREF);
 
295
      updateErrDetailPrefStr.AppendWithConversion(crlKey);
 
296
      errMsg.AssignWithConversion(errorMessage.get());
 
297
      rv = pref->GetIntPref(updateErrCntPrefStr.get(),&errCnt);
 
298
      if( (NS_FAILED(rv)) || (errCnt ==0)){
 
299
        pref->SetIntPref(updateErrCntPrefStr.get(),1);
 
300
      }else{
 
301
        pref->SetIntPref(updateErrCntPrefStr.get(),errCnt+1);
 
302
      }
 
303
      pref->SetCharPref(updateErrDetailPrefStr.get(),errMsg.get());
 
304
      pref->SavePrefFile(nsnull);
 
305
    }
 
306
  }
 
307
 
 
308
  return rv;
 
309
}
 
310
 
 
311
NS_IMETHODIMP 
 
312
nsCRLManager::UpdateCRLFromURL( const PRUnichar *url, const PRUnichar* key, PRBool *res)
 
313
{
 
314
  nsresult rv;
 
315
  nsAutoString downloadUrl(url);
 
316
  nsAutoString dbKey(key);
 
317
  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
 
318
  if(NS_FAILED(rv)){
 
319
    *res = PR_FALSE;
 
320
    return rv;
 
321
  }
 
322
 
 
323
  rv = nssComponent->DownloadCRLDirectly(downloadUrl, dbKey);
 
324
  if(NS_FAILED(rv)){
 
325
    *res = PR_FALSE;
 
326
  } else {
 
327
    *res = PR_TRUE;
 
328
  }
 
329
  return NS_OK;
 
330
 
 
331
}
 
332
 
 
333
NS_IMETHODIMP 
 
334
nsCRLManager::RescheduleCRLAutoUpdate(void)
 
335
{
 
336
  nsresult rv;
 
337
  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
 
338
  if(NS_FAILED(rv)){
 
339
    return rv;
 
340
  }
 
341
  rv = nssComponent->DefineNextTimer();
 
342
  return rv;
 
343
}
 
344
 
 
345
/*
 
346
 * getCRLs
 
347
 *
 
348
 * Export a set of certs and keys from the database to a PKCS#12 file.
 
349
*/
 
350
 
 
351
NS_IMETHODIMP 
 
352
nsCRLManager::GetCrls(nsIArray ** aCrls)
 
353
{
 
354
  nsNSSShutDownPreventionLock locker;
 
355
  SECStatus sec_rv;
 
356
  CERTCrlHeadNode *head = nsnull;
 
357
  CERTCrlNode *node = nsnull;
 
358
  nsCOMPtr<nsIMutableArray> crlsArray;
 
359
  nsresult rv;
 
360
  rv = NS_NewArray(getter_AddRefs(crlsArray));
 
361
  if (NS_FAILED(rv)) {
 
362
    return rv;
 
363
  }
 
364
 
 
365
  // Get the list of certs //
 
366
  sec_rv = SEC_LookupCrls(CERT_GetDefaultCertDB(), &head, -1);
 
367
  if (sec_rv != SECSuccess) {
 
368
    goto loser;
 
369
  }
 
370
 
 
371
  if (head) {
 
372
    for (node=head->first; node != nsnull; node = node->next) {
 
373
 
 
374
      nsCOMPtr<nsICRLInfo> entry = new nsCRLInfo((node->crl));
 
375
      crlsArray->AppendElement(entry, PR_FALSE);
 
376
    }
 
377
    PORT_FreeArena(head->arena, PR_FALSE);
 
378
  }
 
379
 
 
380
  *aCrls = crlsArray;
 
381
  NS_IF_ADDREF(*aCrls);
 
382
  return NS_OK;
 
383
loser:
 
384
  return NS_ERROR_FAILURE;;
 
385
}
 
386
 
 
387
/*
 
388
 * deletetCrl
 
389
 *
 
390
 * Delete a Crl entry from the cert db.
 
391
*/
 
392
NS_IMETHODIMP 
 
393
nsCRLManager::DeleteCrl(PRUint32 aCrlIndex)
 
394
{
 
395
  nsNSSShutDownPreventionLock locker;
 
396
  CERTSignedCrl *realCrl = nsnull;
 
397
  CERTCrlHeadNode *head = nsnull;
 
398
  CERTCrlNode *node = nsnull;
 
399
  SECStatus sec_rv;
 
400
  PRUint32 i;
 
401
 
 
402
  // Get the list of certs //
 
403
  sec_rv = SEC_LookupCrls(CERT_GetDefaultCertDB(), &head, -1);
 
404
  if (sec_rv != SECSuccess) {
 
405
    goto loser;
 
406
  }
 
407
 
 
408
  if (head) {
 
409
    for (i = 0, node=head->first; node != nsnull; i++, node = node->next) {
 
410
      if (i != aCrlIndex) {
 
411
        continue;
 
412
      }
 
413
      realCrl = SEC_FindCrlByName(CERT_GetDefaultCertDB(), &(node->crl->crl.derName), node->type);
 
414
      SEC_DeletePermCRL(realCrl);
 
415
      SEC_DestroyCrl(realCrl);
 
416
      SSL_ClearSessionCache();
 
417
    }
 
418
    PORT_FreeArena(head->arena, PR_FALSE);
 
419
  }
 
420
  return NS_OK;
 
421
loser:
 
422
  return NS_ERROR_FAILURE;;
 
423
}
 
424
 
 
425
NS_IMETHODIMP
 
426
nsCRLManager::ComputeNextAutoUpdateTime(nsICRLInfo *info, 
 
427
  PRUint32 autoUpdateType, double dayCnt, PRUnichar **nextAutoUpdate)
 
428
{
 
429
  if (!info)
 
430
    return NS_ERROR_FAILURE;
 
431
 
 
432
  PRTime microsecInDayCnt;
 
433
  PRTime now = PR_Now();
 
434
  PRTime tempTime;
 
435
  PRInt64 diff = 0;
 
436
  PRInt64 secsInDay = 86400UL;
 
437
  PRInt64 temp;
 
438
  PRInt64 cycleCnt = 0;
 
439
  PRInt64 secsInDayCnt;
 
440
  PRFloat64 tmpData;
 
441
  
 
442
  LL_L2F(tmpData,secsInDay);
 
443
  LL_MUL(tmpData,dayCnt,tmpData);
 
444
  LL_F2L(secsInDayCnt,tmpData);
 
445
  LL_MUL(microsecInDayCnt, secsInDayCnt, PR_USEC_PER_SEC);
 
446
    
 
447
  PRTime lastUpdate;
 
448
  PRTime nextUpdate;
 
449
  
 
450
  nsresult rv;
 
451
 
 
452
  rv = info->GetLastUpdate(&lastUpdate);
 
453
  if (NS_FAILED(rv))
 
454
    return rv;
 
455
 
 
456
  rv = info->GetNextUpdate(&nextUpdate);
 
457
  if (NS_FAILED(rv))
 
458
    return rv;
 
459
 
 
460
  switch (autoUpdateType) {
 
461
  case TYPE_AUTOUPDATE_FREQ_BASED:
 
462
    LL_SUB(diff, now, lastUpdate);             //diff is the no of micro sec between now and last update
 
463
    LL_DIV(cycleCnt, diff, microsecInDayCnt);   //temp is the number of full cycles from lst update
 
464
    LL_MOD(temp, diff, microsecInDayCnt);
 
465
    if(!(LL_IS_ZERO(temp))) {
 
466
      LL_ADD(cycleCnt,cycleCnt,1);            //no of complete cycles till next autoupdate instant
 
467
    }
 
468
    LL_MUL(temp,cycleCnt,microsecInDayCnt);    //micro secs from last update
 
469
    LL_ADD(tempTime, lastUpdate, temp);
 
470
    break;  
 
471
  case TYPE_AUTOUPDATE_TIME_BASED:
 
472
    LL_SUB(tempTime, nextUpdate, microsecInDayCnt);
 
473
    break;
 
474
  default:
 
475
    return NS_ERROR_NOT_IMPLEMENTED;
 
476
  }
 
477
 
 
478
  //Now, a basic constraing is that the next auto update date can never be after
 
479
  //next update, if one is defined
 
480
  if(LL_CMP(nextUpdate , > , 0 )) {
 
481
    if(LL_CMP(tempTime , > , nextUpdate)) {
 
482
      tempTime = nextUpdate;
 
483
    }
 
484
  }
 
485
 
 
486
  nsAutoString nextAutoUpdateDate;
 
487
  PRExplodedTime explodedTime;
 
488
  nsCOMPtr<nsIDateTimeFormat> dateFormatter = do_CreateInstance(kDateTimeFormatCID, &rv);
 
489
  if (NS_FAILED(rv))
 
490
    return rv;
 
491
  PR_ExplodeTime(tempTime, PR_GMTParameters, &explodedTime);
 
492
  dateFormatter->FormatPRExplodedTime(nsnull, kDateFormatShort, kTimeFormatSeconds,
 
493
                                      &explodedTime, nextAutoUpdateDate);
 
494
  *nextAutoUpdate = ToNewUnicode(nextAutoUpdateDate);
 
495
 
 
496
  return NS_OK;
 
497
}
 
498