Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/ssl/sslauth.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
#include "cert.h"
6
#include "secitem.h"
7
#include "ssl.h"
8
#include "sslimpl.h"
9
#include "sslproto.h"
10
#include "pk11func.h"
11
#include "ocsp.h"
12
13
/* NEED LOCKS IN HERE.  */
14
CERTCertificate *
15
SSL_PeerCertificate(PRFileDesc *fd)
16
0
{
17
0
    sslSocket *ss;
18
19
0
    ss = ssl_FindSocket(fd);
20
0
    if (!ss) {
21
0
        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
22
0
                 SSL_GETPID(), fd));
23
0
        return 0;
24
0
    }
25
0
    if (ss->opt.useSecurity && ss->sec.peerCert) {
26
0
        return CERT_DupCertificate(ss->sec.peerCert);
27
0
    }
28
0
    return 0;
29
0
}
30
31
/* NEED LOCKS IN HERE.  */
32
CERTCertList *
33
SSL_PeerCertificateChain(PRFileDesc *fd)
34
0
{
35
0
    sslSocket *ss;
36
0
    CERTCertList *chain = NULL;
37
0
    CERTCertificate *cert;
38
0
    ssl3CertNode *cur;
39
40
0
    ss = ssl_FindSocket(fd);
41
0
    if (!ss) {
42
0
        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificateChain",
43
0
                 SSL_GETPID(), fd));
44
0
        return NULL;
45
0
    }
46
0
    if (!ss->opt.useSecurity || !ss->sec.peerCert) {
47
0
        PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
48
0
        return NULL;
49
0
    }
50
0
    chain = CERT_NewCertList();
51
0
    if (!chain) {
52
0
        return NULL;
53
0
    }
54
0
    cert = CERT_DupCertificate(ss->sec.peerCert);
55
0
    if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
56
0
        goto loser;
57
0
    }
58
0
    for (cur = ss->ssl3.peerCertChain; cur; cur = cur->next) {
59
0
        cert = CERT_DupCertificate(cur->cert);
60
0
        if (CERT_AddCertToListTail(chain, cert) != SECSuccess) {
61
0
            goto loser;
62
0
        }
63
0
    }
64
0
    return chain;
65
66
0
loser:
67
0
    CERT_DestroyCertList(chain);
68
0
    return NULL;
69
0
}
70
71
/* NEED LOCKS IN HERE.  */
72
CERTCertificate *
73
SSL_LocalCertificate(PRFileDesc *fd)
74
0
{
75
0
    sslSocket *ss;
76
77
0
    ss = ssl_FindSocket(fd);
78
0
    if (!ss) {
79
0
        SSL_DBG(("%d: SSL[%d]: bad socket in PeerCertificate",
80
0
                 SSL_GETPID(), fd));
81
0
        return NULL;
82
0
    }
83
0
    if (ss->opt.useSecurity) {
84
0
        if (ss->sec.localCert) {
85
0
            return CERT_DupCertificate(ss->sec.localCert);
86
0
        }
87
0
        if (ss->sec.ci.sid && ss->sec.ci.sid->localCert) {
88
0
            return CERT_DupCertificate(ss->sec.ci.sid->localCert);
89
0
        }
90
0
    }
91
0
    return NULL;
92
0
}
93
94
/* NEED LOCKS IN HERE.  */
95
SECStatus
96
SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
97
                   char **ip, char **sp)
98
0
{
99
0
    sslSocket *ss;
100
101
0
    ss = ssl_FindSocket(fd);
102
0
    if (!ss) {
103
0
        SSL_DBG(("%d: SSL[%d]: bad socket in SecurityStatus",
104
0
                 SSL_GETPID(), fd));
105
0
        return SECFailure;
106
0
    }
107
108
0
    if (cp)
109
0
        *cp = 0;
110
0
    if (kp0)
111
0
        *kp0 = 0;
112
0
    if (kp1)
113
0
        *kp1 = 0;
114
0
    if (ip)
115
0
        *ip = 0;
116
0
    if (sp)
117
0
        *sp = 0;
118
0
    if (op) {
119
0
        *op = SSL_SECURITY_STATUS_OFF;
120
0
    }
121
122
0
    if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
123
0
        const ssl3BulkCipherDef *bulkCipherDef;
124
0
        PRBool isDes = PR_FALSE;
125
126
0
        bulkCipherDef = ssl_GetBulkCipherDef(ss->ssl3.hs.suite_def);
127
0
        if (cp) {
128
0
            *cp = PORT_Strdup(bulkCipherDef->short_name);
129
0
        }
130
0
        if (PORT_Strstr(bulkCipherDef->short_name, "DES")) {
131
0
            isDes = PR_TRUE;
132
0
        }
133
134
0
        if (kp0) {
135
0
            *kp0 = bulkCipherDef->key_size * 8;
136
0
            if (isDes)
137
0
                *kp0 = (*kp0 * 7) / 8;
138
0
        }
139
0
        if (kp1) {
140
0
            *kp1 = bulkCipherDef->secret_key_size * 8;
141
0
            if (isDes)
142
0
                *kp1 = (*kp1 * 7) / 8;
143
0
        }
144
0
        if (op) {
145
0
            if (bulkCipherDef->key_size == 0) {
146
0
                *op = SSL_SECURITY_STATUS_OFF;
147
0
            } else if (bulkCipherDef->secret_key_size * 8 < 90) {
148
0
                *op = SSL_SECURITY_STATUS_ON_LOW;
149
0
            } else {
150
0
                *op = SSL_SECURITY_STATUS_ON_HIGH;
151
0
            }
152
0
        }
153
154
0
        if (ip || sp) {
155
0
            CERTCertificate *cert;
156
157
0
            cert = ss->sec.peerCert;
158
0
            if (cert) {
159
0
                if (ip) {
160
0
                    *ip = CERT_NameToAscii(&cert->issuer);
161
0
                }
162
0
                if (sp) {
163
0
                    *sp = CERT_NameToAscii(&cert->subject);
164
0
                }
165
0
            } else {
166
0
                if (ip) {
167
0
                    *ip = PORT_Strdup("no certificate");
168
0
                }
169
0
                if (sp) {
170
0
                    *sp = PORT_Strdup("no certificate");
171
0
                }
172
0
            }
173
0
        }
174
0
    }
175
176
0
    return SECSuccess;
177
0
}
178
179
/************************************************************************/
180
181
/* NEED LOCKS IN HERE.  */
182
SECStatus
183
SSL_AuthCertificateHook(PRFileDesc *s, SSLAuthCertificate func, void *arg)
184
0
{
185
0
    sslSocket *ss;
186
187
0
    ss = ssl_FindSocket(s);
188
0
    if (!ss) {
189
0
        SSL_DBG(("%d: SSL[%d]: bad socket in AuthCertificateHook",
190
0
                 SSL_GETPID(), s));
191
0
        return SECFailure;
192
0
    }
193
194
0
    ss->authCertificate = func;
195
0
    ss->authCertificateArg = arg;
196
197
0
    return SECSuccess;
198
0
}
199
200
/* NEED LOCKS IN HERE.  */
201
SECStatus
202
SSL_GetClientAuthDataHook(PRFileDesc *s, SSLGetClientAuthData func,
203
                          void *arg)
204
0
{
205
0
    sslSocket *ss;
206
207
0
    ss = ssl_FindSocket(s);
208
0
    if (!ss) {
209
0
        SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
210
0
                 SSL_GETPID(), s));
211
0
        return SECFailure;
212
0
    }
213
214
0
    ss->getClientAuthData = func;
215
0
    ss->getClientAuthDataArg = arg;
216
0
    return SECSuccess;
217
0
}
218
219
/* NEED LOCKS IN HERE.  */
220
SECStatus
221
SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg)
222
0
{
223
0
    sslSocket *ss;
224
225
0
    ss = ssl_FindSocket(s);
226
0
    if (!ss) {
227
0
        SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook",
228
0
                 SSL_GETPID(), s));
229
0
        return SECFailure;
230
0
    }
231
232
0
    ss->pkcs11PinArg = arg;
233
0
    return SECSuccess;
234
0
}
235
236
/* This is the "default" authCert callback function.  It is called when a
237
 * certificate message is received from the peer and the local application
238
 * has not registered an authCert callback function.
239
 */
240
SECStatus
241
SSL_AuthCertificate(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
242
0
{
243
0
    SECStatus rv;
244
0
    CERTCertDBHandle *handle;
245
0
    sslSocket *ss;
246
0
    SECCertUsage certUsage;
247
0
    const char *hostname = NULL;
248
0
    SECItemArray *certStatusArray;
249
250
0
    ss = ssl_FindSocket(fd);
251
0
    PORT_Assert(ss != NULL);
252
0
    if (!ss) {
253
0
        return SECFailure;
254
0
    }
255
256
0
    handle = (CERTCertDBHandle *)arg;
257
0
    certStatusArray = &ss->sec.ci.sid->peerCertStatus;
258
259
0
    PRTime now = ssl_Time(ss);
260
0
    if (certStatusArray->len) {
261
0
        PORT_SetError(0);
262
0
        if (CERT_CacheOCSPResponseFromSideChannel(handle, ss->sec.peerCert, now,
263
0
                                                  &certStatusArray->items[0],
264
0
                                                  ss->pkcs11PinArg) !=
265
0
            SECSuccess) {
266
0
            PORT_Assert(PR_GetError() != 0);
267
0
        }
268
0
    }
269
270
    /* this may seem backwards, but isn't. */
271
0
    certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
272
273
0
    rv = CERT_VerifyCert(handle, ss->sec.peerCert, checkSig, certUsage,
274
0
                         now, ss->pkcs11PinArg, NULL);
275
276
0
    if (rv != SECSuccess || isServer)
277
0
        return rv;
278
279
    /* cert is OK.  This is the client side of an SSL connection.
280
     * Now check the name field in the cert against the desired hostname.
281
     * NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
282
     */
283
0
    hostname = ss->url;
284
0
    if (hostname && hostname[0])
285
0
        rv = CERT_VerifyCertName(ss->sec.peerCert, hostname);
286
0
    else
287
0
        rv = SECFailure;
288
0
    if (rv != SECSuccess)
289
0
        PORT_SetError(SSL_ERROR_BAD_CERT_DOMAIN);
290
291
0
    return rv;
292
0
}