Back to index

lightning-sunbird  0.9+nobinonly
sslauth.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 /* $Id: sslauth.c,v 1.15.2.1 2006/04/20 00:22:58 alexei.volkov.bugs%sun.com Exp $ */
00037 #include "cert.h"
00038 #include "secitem.h"
00039 #include "ssl.h"
00040 #include "sslimpl.h"
00041 #include "sslproto.h"
00042 #include "pk11func.h"
00043 
00044 /* NEED LOCKS IN HERE.  */
00045 CERTCertificate *
00046 SSL_PeerCertificate(PRFileDesc *fd)
00047 {
00048     sslSocket *ss;
00049 
00050     ss = ssl_FindSocket(fd);
00051     if (!ss) {
00052        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
00053                SSL_GETPID(), fd));
00054        return 0;
00055     }
00056     if (ss->opt.useSecurity && ss->sec.peerCert) {
00057        return CERT_DupCertificate(ss->sec.peerCert);
00058     }
00059     return 0;
00060 }
00061 
00062 /* NEED LOCKS IN HERE.  */
00063 CERTCertificate *
00064 SSL_LocalCertificate(PRFileDesc *fd)
00065 {
00066     sslSocket *ss;
00067 
00068     ss = ssl_FindSocket(fd);
00069     if (!ss) {
00070        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
00071                SSL_GETPID(), fd));
00072        return NULL;
00073     }
00074     if (ss->opt.useSecurity) {
00075        if (ss->sec.localCert) {
00076            return CERT_DupCertificate(ss->sec.localCert);
00077        }
00078        if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
00079            return CERT_DupCertificate(ss->sec.ci.sid->localCert);
00080        }
00081     }
00082     return NULL;
00083 }
00084 
00085 
00086 
00087 /* NEED LOCKS IN HERE.  */
00088 SECStatus
00089 SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
00090                  char **ip, char **sp)
00091 {
00092     sslSocket *ss;
00093     const char *cipherName;
00094     PRBool isDes = PR_FALSE;
00095 
00096     ss = ssl_FindSocket(fd);
00097     if (!ss) {
00098        SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
00099                SSL_GETPID(), fd));
00100        return SECFailure;
00101     }
00102 
00103     if (cp) *cp = 0;
00104     if (kp0) *kp0 = 0;
00105     if (kp1) *kp1 = 0;
00106     if (ip) *ip = 0;
00107     if (sp) *sp = 0;
00108     if (op) {
00109        *op = SSL_SECURITY_STATUS_OFF;
00110     }
00111 
00112     if (ss->opt.useSecurity && ss->firstHsDone) {
00113 
00114        if (ss->version < SSL_LIBRARY_VERSION_3_0) {
00115            cipherName = ssl_cipherName[ss->sec.cipherType];
00116        } else {
00117            cipherName = ssl3_cipherName[ss->sec.cipherType];
00118        }
00119        PORT_Assert(cipherName);
00120        if (cipherName) {
00121             if (PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE;
00122 
00123             if (cp) {
00124                 *cp = PORT_Strdup(cipherName);
00125             }
00126         }
00127 
00128        if (kp0) {
00129            *kp0 = ss->sec.keyBits;
00130            if (isDes) *kp0 = (*kp0 * 7) / 8;
00131        }
00132        if (kp1) {
00133            *kp1 = ss->sec.secretKeyBits;
00134            if (isDes) *kp1 = (*kp1 * 7) / 8;
00135        }
00136        if (op) {
00137            if (ss->sec.keyBits == 0) {
00138               *op = SSL_SECURITY_STATUS_OFF;
00139            } else if (ss->sec.secretKeyBits < 90) {
00140               *op = SSL_SECURITY_STATUS_ON_LOW;
00141 
00142            } else {
00143               *op = SSL_SECURITY_STATUS_ON_HIGH;
00144            }
00145        }
00146 
00147        if (ip || sp) {
00148            CERTCertificate *cert;
00149 
00150            cert = ss->sec.peerCert;
00151            if (cert) {
00152               if (ip) {
00153                   *ip = CERT_NameToAscii(&cert->issuer);
00154               }
00155               if (sp) {
00156                   *sp = CERT_NameToAscii(&cert->subject);
00157               }
00158            } else {
00159               if (ip) {
00160                   *ip = PORT_Strdup("no certificate");
00161               }
00162               if (sp) {
00163                   *sp = PORT_Strdup("no certificate");
00164               }
00165            }
00166        }
00167     }
00168 
00169     return SECSuccess;
00170 }
00171 
00172 /************************************************************************/
00173 
00174 /* NEED LOCKS IN HERE.  */
00175 SECStatus
00176 SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
00177 {
00178     sslSocket *ss;
00179 
00180     ss = ssl_FindSocket(s);
00181     if (!ss) {
00182        SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
00183                SSL_GETPID(), s));
00184        return SECFailure;
00185     }
00186 
00187     ss->authCertificate = func;
00188     ss->authCertificateArg = arg;
00189 
00190     return SECSuccess;
00191 }
00192 
00193 /* NEED LOCKS IN HERE.  */
00194 SECStatus 
00195 SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
00196                            void *arg)
00197 {
00198     sslSocket *ss;
00199 
00200     ss = ssl_FindSocket(s);
00201     if (!ss) {
00202        SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
00203                SSL_GETPID(), s));
00204        return SECFailure;
00205     }
00206 
00207     ss->getClientAuthData = func;
00208     ss->getClientAuthDataArg = arg;
00209     return SECSuccess;
00210 }
00211 
00212 /* NEED LOCKS IN HERE.  */
00213 SECStatus 
00214 SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
00215 {
00216     sslSocket *ss;
00217 
00218     ss = ssl_FindSocket(s);
00219     if (!ss) {
00220        SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
00221                SSL_GETPID(), s));
00222        return SECFailure;
00223     }
00224 
00225     ss->pkcs11PinArg = arg;
00226     return SECSuccess;
00227 }
00228 
00229 
00230 /* This is the "default" authCert callback function.  It is called when a 
00231  * certificate message is received from the peer and the local application
00232  * has not registered an authCert callback function.
00233  */
00234 SECStatus
00235 SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
00236 {
00237     SECStatus          rv;
00238     CERTCertDBHandle * handle;
00239     sslSocket *        ss;
00240     SECCertUsage       certUsage;
00241     const char *             hostname    = NULL;
00242     
00243     ss = ssl_FindSocket(fd);
00244     PORT_Assert(ss != NULL);
00245     if (!ss) {
00246        return SECFailure;
00247     }
00248 
00249     handle = (CERTCertDBHandle *)arg;
00250 
00251     /* this may seem backwards, but isn't. */
00252     certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
00253 
00254     rv = CERT_VerifyCertNow(handle, ss->sec.peerCert, checkSig, certUsage,
00255                          ss->pkcs11PinArg);
00256 
00257     if ( rv != SECSuccess || isServer )
00258        return rv;
00259   
00260     /* cert is OK.  This is the client side of an SSL connection.
00261      * Now check the name field in the cert against the desired hostname.
00262      * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
00263      */
00264     hostname = ss->url;
00265     if (hostname && hostname[0])
00266        rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
00267     else 
00268        rv = SECFailure;
00269     if (rv != SECSuccess)
00270        PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
00271 
00272     return rv;
00273 }