Exemple #1
0
// TODO: Remove #include "pkix/pkixnss.h", #include "cert.h",
// #include "ScopedPtr.h", etc. when this is rewritten to be independent of
// NSS.
Result
CheckNameConstraints(Input encodedNameConstraints,
                     const BackCert& firstChild,
                     KeyPurposeId requiredEKUIfPresent)
{
  ScopedPtr<PLArenaPool, PORT_FreeArena_false>
    arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  if (!arena) {
    return Result::FATAL_ERROR_NO_MEMORY;
  }

  SECItem encodedNameConstraintsSECItem =
    UnsafeMapInputToSECItem(encodedNameConstraints);

  // Owned by arena
  const CERTNameConstraints* constraints =
    CERT_DecodeNameConstraintsExtension(arena.get(),
                                        &encodedNameConstraintsSECItem);
  if (!constraints) {
    return MapPRErrorCodeToResult(PR_GetError());
  }

  for (const BackCert* child = &firstChild; child; child = child->childCert) {
    SECItem childCertDER = UnsafeMapInputToSECItem(child->GetDER());
    ScopedPtr<CERTCertificate, CERT_DestroyCertificate>
      nssCert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &childCertDER,
                                      nullptr, false, true));
    if (!nssCert) {
      return MapPRErrorCodeToResult(PR_GetError());
    }

    bool includeCN = child->endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
                     requiredEKUIfPresent == KeyPurposeId::id_kp_serverAuth;
    // owned by arena
    const CERTGeneralName*
      names(CERT_GetConstrainedCertificateNames(nssCert.get(), arena.get(),
                                                includeCN));
    if (!names) {
      return MapPRErrorCodeToResult(PR_GetError());
    }

    CERTGeneralName* currentName = const_cast<CERTGeneralName*>(names);
    do {
      if (CERT_CheckNameSpace(arena.get(), constraints, currentName)
            != SECSuccess) {
        // XXX: It seems like CERT_CheckNameSpace doesn't always call
        // PR_SetError when it fails, so we ignore what PR_GetError would
        // return. NSS's cert_VerifyCertChainOld does something similar.
        return Result::ERROR_CERT_NOT_IN_NAME_SPACE;
      }
      currentName = CERT_GetNextGeneralName(currentName);
    } while (currentName != names);
  }

  return Success;
}
Exemple #2
0
static nsresult
AppendErrorTextMismatch(const nsString& host, nsIX509Cert* ix509,
                        nsINSSComponent* component, bool wantsHtml,
                        nsString& returnedMessage)
{
  // Prepare a default "not valid for <hostname>" string in case anything
  // goes wrong (or in case the certificate is not valid for any hostnames).
  nsAutoString notValidForHostnameString;
  const char16_t* params[1];
  params[0] = host.get();
  nsresult rv = component->PIPBundleFormatStringFromName(
    "certErrorMismatch", params, 1, notValidForHostnameString);
  if (NS_FAILED(rv)) {
    return rv;
  }
  notValidForHostnameString.Append('\n');

  UniqueCERTCertificate nssCert(ix509->GetCert());
  if (!nssCert) {
    returnedMessage.Append(notValidForHostnameString);
    return NS_OK;
  }

  nsAutoString allNames;
  uint32_t nameCount = GetSubjectAltNames(nssCert.get(), allNames);
  if (nameCount == 0) {
    returnedMessage.Append(notValidForHostnameString);
  } else if (nameCount > 1) {
    nsString message;
    rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple", message);
    if (NS_FAILED(rv)) {
      return rv;
    }
    returnedMessage.Append(message);
    returnedMessage.AppendLiteral("\n  ");
    returnedMessage.Append(allNames);
    returnedMessage.AppendLiteral("  \n");
  } else if (nameCount == 1) {
    params[0] = allNames.get();

    const char* stringID = wantsHtml ? "certErrorMismatchSingle2"
                                     : "certErrorMismatchSinglePlain";
    nsAutoString formattedString;
    rv = component->PIPBundleFormatStringFromName(stringID, params, 1,
                                                  formattedString);
    if (NS_FAILED(rv)) {
      return rv;
    }
    returnedMessage.Append(formattedString);
    returnedMessage.Append('\n');
  }

  return NS_OK;
}
static void
AppendErrorTextMismatch(const nsString &host,
                        nsIX509Cert* ix509,
                        nsINSSComponent *component,
                        bool wantsHtml,
                        nsString &returnedMessage)
{
    const char16_t *params[1];
    nsresult rv;

    ScopedCERTCertificate nssCert(ix509->GetCert());

    if (!nssCert) {
        // We are unable to extract the valid names, say "not valid for name".
        params[0] = host.get();
        nsString formattedString;
        rv = component->PIPBundleFormatStringFromName("certErrorMismatch",
                params, 1,
                formattedString);
        if (NS_SUCCEEDED(rv)) {
            returnedMessage.Append(formattedString);
            returnedMessage.Append('\n');
        }
        return;
    }

    nsString allNames;
    uint32_t nameCount = 0;
    bool useSAN = false;

    if (nssCert)
        useSAN = GetSubjectAltNames(nssCert.get(), component, allNames, nameCount);

    if (!useSAN) {
        char *certName = CERT_GetCommonName(&nssCert->subject);
        if (certName) {
            nsDependentCSubstring commonName(certName, strlen(certName));
            if (IsUTF8(commonName)) {
                // Bug 1024781
                // We should actually check that the common name is a valid dns name or
                // ip address and not any string value before adding it to the display
                // list.
                ++nameCount;
                allNames.Assign(NS_ConvertUTF8toUTF16(commonName));
            }
            PORT_Free(certName);
        }
    }

    if (nameCount > 1) {
        nsString message;
        rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple",
                                              message);
        if (NS_SUCCEEDED(rv)) {
            returnedMessage.Append(message);
            returnedMessage.AppendLiteral("\n  ");
            returnedMessage.Append(allNames);
            returnedMessage.AppendLiteral("  \n");
        }
    }
    else if (nameCount == 1) {
        const char16_t *params[1];
        params[0] = allNames.get();

        const char *stringID;
        if (wantsHtml)
            stringID = "certErrorMismatchSingle2";
        else
            stringID = "certErrorMismatchSinglePlain";

        nsString formattedString;
        rv = component->PIPBundleFormatStringFromName(stringID,
                params, 1,
                formattedString);
        if (NS_SUCCEEDED(rv)) {
            returnedMessage.Append(formattedString);
            returnedMessage.Append('\n');
        }
    }
    else { // nameCount == 0
        nsString message;
        nsresult rv = component->GetPIPNSSBundleString("certErrorMismatchNoNames",
                      message);
        if (NS_SUCCEEDED(rv)) {
            returnedMessage.Append(message);
            returnedMessage.Append('\n');
        }
    }
}