Example #1
0
sslSessionID *
ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, 
              const char * urlSvrName)
{
    sslSessionID **sidp;
    sslSessionID * sid;
    PRUint32       now;

    if (!urlSvrName)
    	return NULL;
    now = ssl_Time();
    LOCK_CACHE;
    sidp = &cache;
    while ((sid = *sidp) != 0) {
	PORT_Assert(sid->cached == in_client_cache);
	PORT_Assert(sid->references >= 1);

	SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid));

	if (sid->expirationTime < now || !sid->references) {
	    /*
	    ** This session-id timed out, or was orphaned.
	    ** Don't even care who it belongs to, blow it out of our cache.
	    */
	    SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d",
			now - sid->creationTime, sid->references));

	    *sidp = sid->next; 			/* delink it from the list. */
	    sid->cached = invalid_cache;	/* mark not on list. */
	    if (!sid->references)
	    	ssl_DestroySID(sid);
	    else
		ssl_FreeLockedSID(sid);		/* drop ref count, free. */

	} else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */
	           (sid->port == port) && /* server port matches */
		   /* proxy (peerID) matches */
		   (((peerID == NULL) && (sid->peerID == NULL)) ||
		    ((peerID != NULL) && (sid->peerID != NULL) &&
		     PORT_Strcmp(sid->peerID, peerID) == 0)) &&
		   /* is cacheable */
		   (sid->version < SSL_LIBRARY_VERSION_3_0 ||
		    sid->u.ssl3.keys.resumable) &&
		   /* server hostname matches. */
	           (sid->urlSvrName != NULL) &&
		   ((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) ||
		    ((sid->peerCert != NULL) && (SECSuccess == 
		      CERT_VerifyCertName(sid->peerCert, urlSvrName))) )
		  ) {
	    /* Hit */
	    sid->lastAccessTime = now;
	    sid->references++;
	    break;
	} else {
	    sidp = &sid->next;
	}
    }
    UNLOCK_CACHE;
    return sid;
}
Example #2
0
/* This is the "default" authCert callback function.  It is called when a 
 * certificate message is received from the peer and the local application
 * has not registered an authCert callback function.
 */
SECStatus
SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
{
    SECStatus          rv;
    CERTCertDBHandle * handle;
    sslSocket *        ss;
    SECCertUsage       certUsage;
    const char *       hostname    = NULL;
    PRTime             now = PR_Now();
    SECItemArray *     certStatusArray;
    
    ss = ssl_FindSocket(fd);
    PORT_Assert(ss != NULL);
    if (!ss) {
	return SECFailure;
    }

    handle = (CERTCertDBHandle *)arg;
    certStatusArray = &ss->sec.ci.sid->peerCertStatus;

    if (certStatusArray->len) {
	PORT_SetError(0);
	if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now,
						  &certStatusArray->items[0],
						  ss->pkcs11PinArg)
		!= SECSuccess) {
	    PRErrorCode error = PR_GetError();
	    PORT_Assert(error != 0);
	}
    }

    /* this may seem backwards, but isn't. */
    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;

    rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage,
			 now, ss->pkcs11PinArg, NULL);

    if ( rv != SECSuccess || isServer )
	return rv;
  
    /* cert is OK.  This is the client side of an SSL connection.
     * Now check the name field in the cert against the desired hostname.
     * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
     */
    hostname = ss->url;
    if (hostname && hostname[0])
	rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
    else 
	rv = SECFailure;
    if (rv != SECSuccess)
	PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);

    return rv;
}
Example #3
0
SECStatus
CertVerifier::VerifySSLServerCert(CERTCertificate* peerCert,
                     /*optional*/ const SECItem* stapledOCSPResponse,
                                  Time time,
                     /*optional*/ void* pinarg,
                                  const char* hostname,
                                  bool saveIntermediatesInPermanentDatabase,
                                  Flags flags,
                 /*optional out*/ ScopedCERTCertList* builtChain,
                 /*optional out*/ SECOidTag* evOidPolicy)
{
  PR_ASSERT(peerCert);
  // XXX: PR_ASSERT(pinarg)
  PR_ASSERT(hostname);
  PR_ASSERT(hostname[0]);

  if (builtChain) {
    *builtChain = nullptr;
  }
  if (evOidPolicy) {
    *evOidPolicy = SEC_OID_UNKNOWN;
  }

  if (!hostname || !hostname[0]) {
    PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
    return SECFailure;
  }

  ScopedCERTCertList builtChainTemp;
  // CreateCertErrorRunnable assumes that CERT_VerifyCertName is only called
  // if VerifyCert succeeded.
  SECStatus rv = VerifyCert(peerCert, certificateUsageSSLServer, time, pinarg,
                            hostname, flags, stapledOCSPResponse,
                            &builtChainTemp, evOidPolicy);
  if (rv != SECSuccess) {
    return rv;
  }

  rv = CERT_VerifyCertName(peerCert, hostname);
  if (rv != SECSuccess) {
    return rv;
  }

  if (saveIntermediatesInPermanentDatabase) {
    SaveIntermediateCerts(builtChainTemp);
  }

  if (builtChain) {
    *builtChain = builtChainTemp.forget();
  }

  return SECSuccess;
}
Example #4
0
/*
 * Callback from SSL for checking a (possibly) expired
 * certificate the peer presents.
 */
SECStatus
JSSL_ConfirmExpiredPeerCert(void *arg, PRFileDesc *fd, PRBool checkSig,
             PRBool isServer)
{
    SECStatus rv=SECFailure;
    SECCertUsage certUsage;
    CERTCertificate* peerCert=NULL;
    int64 notAfter, notBefore;

    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;

    peerCert = SSL_PeerCertificate(fd);

    if (peerCert) {
        rv = CERT_GetCertTimes(peerCert, &notBefore, &notAfter);
        if (rv != SECSuccess) goto finish;

        /*
         * Verify the certificate based on it's expiry date. This should
         * always succeed, if the cert is trusted. It doesn't care if
         * the cert has expired.
         */
        rv = CERT_VerifyCert(CERT_GetDefaultCertDB(), peerCert,
                             checkSig, certUsage, 
                             notAfter, NULL /*pinarg*/,
                             NULL /* log */);
    }
    if ( rv != SECSuccess ) goto finish;

    if( ! isServer )  {
        /* This is the client side of an SSL connection.
        * Now check the name field in the cert against the desired hostname.
        * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
        */
        if( peerCert == NULL ) {
            rv = SECFailure;
        } else {
            char* hostname = NULL;
            hostname = SSL_RevealURL(fd); /* really is a hostname, not a URL */
            if (hostname && hostname[0]) {
                rv = CERT_VerifyCertName(peerCert, hostname);
                PORT_Free(hostname);
            } else {
                rv = SECFailure;
            }
        }
    }

finish:
    if (peerCert!=NULL) CERT_DestroyCertificate(peerCert);
    return rv;
}
Example #5
0
/*
 * Callback from SSL for checking certificate the peer (other end of
 * the socket) presents.
 */
SECStatus
JSSL_DefaultCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig,
             PRBool isServer)
{
    char *          hostname = NULL;
    SECStatus         rv    = SECFailure;
    SECCertUsage      certUsage;
    CERTCertificate   *peerCert=NULL;

    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
 

    /* SSL_PeerCertificate() returns a shallow copy of the cert, so we
       must destroy it before we exit this function */

    peerCert   = SSL_PeerCertificate(fd);

    if (peerCert) {
        rv = CERT_VerifyCertNow(CERT_GetDefaultCertDB(), peerCert,
                checkSig, certUsage, NULL /*pinarg*/);
    }

    /* if we're a server, then we don't need to check the CN of the
       certificate, so we can just return whatever returncode we
       have now
     */

    if ( rv != SECSuccess || isServer )  {
        if (peerCert) CERT_DestroyCertificate(peerCert);
            return (int)rv;
        }

    /* cert is OK.  This is the client side of an SSL connection.
     * Now check the name field in the cert against the desired hostname.
     * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
     */
    hostname = SSL_RevealURL(fd);    /* really is a hostname, not a URL */
    if (hostname && hostname[0]) {
        rv = CERT_VerifyCertName(peerCert, hostname);
        PORT_Free(hostname); 
    } else
        rv = SECFailure;

    if (peerCert) CERT_DestroyCertificate(peerCert);
    return rv;
}
Example #6
0
File: nss.c Project: flashfoxter/sx
int sxi_sslctxfun(sxc_client_t *sx, curlev_t *ev, const struct curl_tlssessioninfo *info)
{
    CERTCertificate *cert;
    int rc = cert_from_sessioninfo(sx, info, &cert);
    if (rc)
        return rc;
    sxi_conns_t *conns = sxi_curlev_get_conns(ev);
    const char *hostname = sxi_conns_get_sslname(conns);
    SECStatus ret = CERT_VerifyCertName(cert, hostname);
    if (ret == SECSuccess) {
        sxi_curlev_set_verified(ev, 1);
    } else {
        PRInt32 err = PR_GetError();
        sxi_seterr(sx, SXE_ECOMM, "Certificate is not valid for cluster '%s': %s", hostname,
                   PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT));
        sxi_curlev_set_verified(ev, -1);
        return -1;
    }
    return 0;
}
Example #7
0
SECStatus
SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
{
    SECStatus          rv;
    CERTCertDBHandle * handle;
    sslSocket *        ss;
    SECCertUsage       certUsage;
    const char *             hostname    = NULL;
    
    ss = ssl_FindSocket(fd);
    PORT_Assert(ss != NULL);
    if (!ss) {
	return SECFailure;
    }

    handle = (CERTCertDBHandle *)arg;

    /* this may seem backwards, but isn't. */
    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;

    rv = CERT_VerifyCertNow(handle, ss->sec.peerCert, checkSig, certUsage,
			    ss->pkcs11PinArg);

    if ( rv != SECSuccess || isServer )
	return rv;
  
    /* cert is OK.  This is the client side of an SSL connection.
     * Now check the name field in the cert against the desired hostname.
     * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
     */
    hostname = ss->url;
    if (hostname && hostname[0])
	rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
    else 
	rv = SECFailure;
    if (rv != SECSuccess)
	PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);

    return rv;
}
Example #8
0
/*
 * Callback from SSL for checking a (possibly) expired
 * certificate the peer presents.
 *
 * obj - a jobject -> instance of a class implementing 
 *       the SSLCertificateApprovalCallback interface
 */
SECStatus
JSSL_JavaCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig,
             PRBool isServer)
{
    CERTCertificate *peerCert=NULL;
    CERTVerifyLog log;
    JNIEnv *env;
    jobject validityStatus;
    jmethodID addReasonMethod;
    int certUsage;
    int checkcn_rv;
    jmethodID approveMethod;
    jboolean result;
    char *hostname=NULL;
    SECStatus retval = SECFailure;
    SECStatus verificationResult;

    PR_ASSERT(arg != NULL);
    PR_ASSERT(fd != NULL);

    /* initialize logging structures */
    log.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if( log.arena == NULL ) return SECFailure;
    log.head = NULL;
    log.tail = NULL;
    log.count = 0;

    /* get the JNI environment */
    if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){
        PR_ASSERT(PR_FALSE);
        goto finish;
    }

    /* First, get a handle on the cert that the peer presented */
    peerCert = SSL_PeerCertificate(fd);
    
    /* if peer didn't present a cert, why am I called? */
    if (peerCert == NULL) goto finish;

    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;

    /* 
     * verify it against current time - (can't use
     * CERT_VerifyCertNow() since it doesn't allow passing of
     * logging parameter)
     */

    verificationResult = CERT_VerifyCert(   CERT_GetDefaultCertDB(),
                            peerCert,
                            checkSig,
                            certUsage,
                            PR_Now(),
                            NULL /*pinarg*/,
                            &log);

    if (verificationResult == SECSuccess && log.count > 0) {
        verificationResult = SECFailure;
    }

    /*
     * Verify the domain name of the cert.
     */
    hostname = SSL_RevealURL(fd);    /* really is a hostname, not a URL */
    if (hostname && hostname[0]) {
        checkcn_rv = CERT_VerifyCertName(peerCert, hostname);
        PORT_Free(hostname);
    } else {
        checkcn_rv = SECFailure;
    }
    if (checkcn_rv != SECSuccess) {
        addToVerifyLog(env, &log,peerCert,SSL_ERROR_BAD_CERT_DOMAIN,0);
        if((*env)->ExceptionOccurred(env) != NULL) goto finish;
        verificationResult = SECFailure;
    }

    /*
     * create a new ValidityStatus object
     */
    {
        jclass clazz;
        jmethodID cons;

        clazz = (*env)->FindClass(env, SSLCERT_APP_CB_VALIDITY_STATUS_CLASS);
        if( clazz == NULL ) goto finish;

        cons = (*env)->GetMethodID(env, clazz,
                        PLAIN_CONSTRUCTOR, PLAIN_CONSTRUCTOR_SIG);
        if( cons == NULL ) goto finish;

        validityStatus = (*env)->NewObject(env, clazz, cons);
        if( validityStatus == NULL ) {
            goto finish;
        }

        /* get the addReason methodID while we're at it */
        addReasonMethod = (*env)->GetMethodID(env, clazz,
            SSLCERT_APP_CB_VALIDITY_STATUS_ADD_REASON_NAME,
            SSLCERT_APP_CB_VALIDITY_STATUS_ADD_REASON_SIG);
        if( addReasonMethod == NULL ) {
            goto finish;
        }
    }
    
    /*
     * Load up the ValidityStatus object with all the reasons for failure
     */
    if (verificationResult == SECFailure)  {
        CERTVerifyLogNode *node;
        int error;
        CERTCertificate *errorcert=NULL;
        int depth;
        jobject ninjacert;

        node = log.head;
        while (node) {
            error = node->error;
            errorcert = node->cert;
            node->cert = NULL;
            depth = node->depth;

            ninjacert = JSS_PK11_wrapCert(env,&errorcert);
            (*env)->CallVoidMethod(env, validityStatus, addReasonMethod,
                error,
                ninjacert,
                depth
                );

            node = node->next;
        }
    }

    /*
     * Call the approval callback
     */
    {
        jobject approvalCallbackObj;
        jclass approvalCallbackClass;
        jobject peerninjacert;

        approvalCallbackObj = (jobject) arg;

        approvalCallbackClass = (*env)->GetObjectClass(env,approvalCallbackObj);
        approveMethod = (*env)->GetMethodID(
            env,
            approvalCallbackClass,
            SSLCERT_APP_CB_APPROVE_NAME,
            SSLCERT_APP_CB_APPROVE_SIG);
        if( approveMethod == NULL ) {
            PR_ASSERT(PR_FALSE);
            goto finish;
        }

        peerninjacert = JSS_PK11_wrapCert(env,&peerCert);
        if( peerninjacert == NULL) {
            PR_ASSERT(PR_FALSE);
            goto finish;
        }
        result = (*env)->CallBooleanMethod(env, approvalCallbackObj,
            approveMethod, peerninjacert, validityStatus);
        if( result == JNI_TRUE ) {
            retval = SECSuccess;
        }
    }

finish:
    if( peerCert != NULL ) {
        CERT_DestroyCertificate(peerCert);
    }
    PORT_FreeArena(log.arena, PR_FALSE);
    return retval;
}
Example #9
0
/* Function: SECStatus myAuthCertificate()
 *
 * Purpose: This function is our custom certificate authentication handler.
 * 
 * Note: This implementation is essentially the same as the default 
 *       SSL_AuthCertificate().
 */
SECStatus 
myAuthCertificate(void *arg, PRFileDesc *socket, 
                  PRBool checksig, PRBool isServer) 
{

    SECCertificateUsage certUsage;
    CERTCertificate *   cert;
    void *              pinArg;
    char *              hostName;
    SECStatus           secStatus;

    if (!arg || !socket) {
	errWarn("myAuthCertificate");
	return SECFailure;
    }

    /* Define how the cert is being used based upon the isServer flag. */

    certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;

    cert = SSL_PeerCertificate(socket);
	
    pinArg = SSL_RevealPinArg(socket);
    
    if (dumpChain == PR_TRUE) {
        dumpCertChain(cert, certUsage);
    }

    secStatus = CERT_VerifyCertificateNow((CERTCertDBHandle *)arg,
				   cert,
				   checksig,
				   certUsage,
				   pinArg,
                                   NULL);

    /* If this is a server, we're finished. */
    if (isServer || secStatus != SECSuccess) {
	SECU_printCertProblems(stderr, (CERTCertDBHandle *)arg, cert, 
			  checksig, certUsage, pinArg, PR_FALSE);
	CERT_DestroyCertificate(cert);
	return secStatus;
    }

    /* Certificate is OK.  Since this is the client side of an SSL
     * connection, we need to verify that the name field in the cert
     * matches the desired hostname.  This is our defense against
     * man-in-the-middle attacks.
     */

    /* SSL_RevealURL returns a hostName, not an URL. */
    hostName = SSL_RevealURL(socket);

    if (hostName && hostName[0]) {
	secStatus = CERT_VerifyCertName(cert, hostName);
    } else {
	PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
	secStatus = SECFailure;
    }

    if (hostName)
	PR_Free(hostName);

    CERT_DestroyCertificate(cert);
    return secStatus;
}