• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
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/
8  *
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
12  * License.
13  *
14  * The Original Code is the Netscape security libraries.
15  *
16  * The Initial Developer of the Original Code is
17  * Netscape Communications Corporation.
18  * Portions created by the Initial Developer are Copyright (C) 1994-2000
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  *
23  * Alternatively, the contents of this file may be used under the terms of
24  * either the GNU General Public License Version 2 or later (the "GPL"), or
25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26  * in which case the provisions of the GPL or the LGPL are applicable instead
27  * of those above. If you wish to allow use of your version of this file only
28  * under the terms of either the GPL or the LGPL, and not to allow others to
29  * use your version of this file under the terms of the MPL, indicate your
30  * decision by deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL or the LGPL. If you do not delete
32  * the provisions above, a recipient may use your version of this file under
33  * the terms of any one of the MPL, the GPL or the LGPL.
34  *
35  * ***** END LICENSE BLOCK ***** */
36 /* $Id: sslauth.c,v 1.16 2006/04/20 00:20:45 alexei.volkov.bugs%sun.com Exp $ */
37 #include "cert.h"
38 #include "secitem.h"
39 #include "ssl.h"
40 #include "sslimpl.h"
41 #include "sslproto.h"
42 #include "pk11func.h"
43 
44 /* NEED LOCKS IN HERE.  */
45 CERTCertificate *
SSL_PeerCertificate(PRFileDesc * fd)46 SSL_PeerCertificate(PRFileDesc *fd)
47 {
48     sslSocket *ss;
49 
50     ss = ssl_FindSocket(fd);
51     if (!ss) {
52 	SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
53 		 SSL_GETPID(), fd));
54 	return 0;
55     }
56     if (ss->opt.useSecurity && ss->sec.peerCert) {
57 	return CERT_DupCertificate(ss->sec.peerCert);
58     }
59     return 0;
60 }
61 
62 /* NEED LOCKS IN HERE.  */
63 CERTCertificate *
SSL_LocalCertificate(PRFileDesc * fd)64 SSL_LocalCertificate(PRFileDesc *fd)
65 {
66     sslSocket *ss;
67 
68     ss = ssl_FindSocket(fd);
69     if (!ss) {
70 	SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
71 		 SSL_GETPID(), fd));
72 	return NULL;
73     }
74     if (ss->opt.useSecurity) {
75     	if (ss->sec.localCert) {
76 	    return CERT_DupCertificate(ss->sec.localCert);
77 	}
78 	if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
79 	    return CERT_DupCertificate(ss->sec.ci.sid->localCert);
80 	}
81     }
82     return NULL;
83 }
84 
85 
86 
87 /* NEED LOCKS IN HERE.  */
88 SECStatus
SSL_SecurityStatus(PRFileDesc * fd,int * op,char ** cp,int * kp0,int * kp1,char ** ip,char ** sp)89 SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
90 		   char **ip, char **sp)
91 {
92     sslSocket *ss;
93     const char *cipherName;
94     PRBool isDes = PR_FALSE;
95 
96     ss = ssl_FindSocket(fd);
97     if (!ss) {
98 	SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
99 		 SSL_GETPID(), fd));
100 	return SECFailure;
101     }
102 
103     if (cp) *cp = 0;
104     if (kp0) *kp0 = 0;
105     if (kp1) *kp1 = 0;
106     if (ip) *ip = 0;
107     if (sp) *sp = 0;
108     if (op) {
109 	*op = SSL_SECURITY_STATUS_OFF;
110     }
111 
112     if (ss->opt.useSecurity && ss->firstHsDone) {
113 
114 	if (ss->version < SSL_LIBRARY_VERSION_3_0) {
115 	    cipherName = ssl_cipherName[ss->sec.cipherType];
116 	} else {
117 	    cipherName = ssl3_cipherName[ss->sec.cipherType];
118 	}
119 	PORT_Assert(cipherName);
120 	if (cipherName) {
121             if (PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE;
122 
123             if (cp) {
124                 *cp = PORT_Strdup(cipherName);
125             }
126         }
127 
128 	if (kp0) {
129 	    *kp0 = ss->sec.keyBits;
130 	    if (isDes) *kp0 = (*kp0 * 7) / 8;
131 	}
132 	if (kp1) {
133 	    *kp1 = ss->sec.secretKeyBits;
134 	    if (isDes) *kp1 = (*kp1 * 7) / 8;
135 	}
136 	if (op) {
137 	    if (ss->sec.keyBits == 0) {
138 		*op = SSL_SECURITY_STATUS_OFF;
139 	    } else if (ss->sec.secretKeyBits < 90) {
140 		*op = SSL_SECURITY_STATUS_ON_LOW;
141 
142 	    } else {
143 		*op = SSL_SECURITY_STATUS_ON_HIGH;
144 	    }
145 	}
146 
147 	if (ip || sp) {
148 	    CERTCertificate *cert;
149 
150 	    cert = ss->sec.peerCert;
151 	    if (cert) {
152 		if (ip) {
153 		    *ip = CERT_NameToAscii(&cert->issuer);
154 		}
155 		if (sp) {
156 		    *sp = CERT_NameToAscii(&cert->subject);
157 		}
158 	    } else {
159 		if (ip) {
160 		    *ip = PORT_Strdup("no certificate");
161 		}
162 		if (sp) {
163 		    *sp = PORT_Strdup("no certificate");
164 		}
165 	    }
166 	}
167     }
168 
169     return SECSuccess;
170 }
171 
172 /************************************************************************/
173 
174 /* NEED LOCKS IN HERE.  */
175 SECStatus
SSL_AuthCertificateHook(PRFileDesc * s,SSLAuthCertificate func,void * arg)176 SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
177 {
178     sslSocket *ss;
179 
180     ss = ssl_FindSocket(s);
181     if (!ss) {
182 	SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
183 		 SSL_GETPID(), s));
184 	return SECFailure;
185     }
186 
187     ss->authCertificate = func;
188     ss->authCertificateArg = arg;
189 
190     return SECSuccess;
191 }
192 
193 /* NEED LOCKS IN HERE.  */
194 SECStatus
SSL_GetClientAuthDataHook(PRFileDesc * s,SSLGetClientAuthData func,void * arg)195 SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
196 			      void *arg)
197 {
198     sslSocket *ss;
199 
200     ss = ssl_FindSocket(s);
201     if (!ss) {
202 	SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
203 		 SSL_GETPID(), s));
204 	return SECFailure;
205     }
206 
207     ss->getClientAuthData = func;
208     ss->getClientAuthDataArg = arg;
209     return SECSuccess;
210 }
211 
212 /* NEED LOCKS IN HERE.  */
213 SECStatus
SSL_SetPKCS11PinArg(PRFileDesc * s,void * arg)214 SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
215 {
216     sslSocket *ss;
217 
218     ss = ssl_FindSocket(s);
219     if (!ss) {
220 	SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
221 		 SSL_GETPID(), s));
222 	return SECFailure;
223     }
224 
225     ss->pkcs11PinArg = arg;
226     return SECSuccess;
227 }
228 
229 
230 /* This is the "default" authCert callback function.  It is called when a
231  * certificate message is received from the peer and the local application
232  * has not registered an authCert callback function.
233  */
234 SECStatus
SSL_AuthCertificate(void * arg,PRFileDesc * fd,PRBool checkSig,PRBool isServer)235 SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
236 {
237     SECStatus          rv;
238     CERTCertDBHandle * handle;
239     sslSocket *        ss;
240     SECCertUsage       certUsage;
241     const char *             hostname    = NULL;
242 
243     ss = ssl_FindSocket(fd);
244     PORT_Assert(ss != NULL);
245     if (!ss) {
246 	return SECFailure;
247     }
248 
249     handle = (CERTCertDBHandle *)arg;
250 
251     /* this may seem backwards, but isn't. */
252     certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
253 
254     rv = CERT_VerifyCertNow(handle, ss->sec.peerCert, checkSig, certUsage,
255 			    ss->pkcs11PinArg);
256 
257     if ( rv != SECSuccess || isServer )
258 	return rv;
259 
260     /* cert is OK.  This is the client side of an SSL connection.
261      * Now check the name field in the cert against the desired hostname.
262      * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
263      */
264     hostname = ss->url;
265     if (hostname && hostname[0])
266 	rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
267     else
268 	rv = SECFailure;
269     if (rv != SECSuccess)
270 	PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
271 
272     return rv;
273 }
274