Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/ssl/sslcon.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Basic SSL handshake functions.
3
 *
4
 * This Source Code Form is subject to the terms of the Mozilla Public
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
6
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8
#include "nssrenam.h"
9
#include "cert.h"
10
#include "secitem.h"
11
#include "sechash.h"
12
#include "cryptohi.h" /* for SGN_ funcs */
13
#include "keyhi.h"    /* for SECKEY_ high level functions. */
14
#include "ssl.h"
15
#include "sslimpl.h"
16
#include "sslproto.h"
17
#include "ssl3prot.h"
18
#include "sslerr.h"
19
#include "pk11func.h"
20
#include "prinit.h"
21
#include "prtime.h" /* for PR_Now() */
22
23
/*
24
** Put a string tag in the library so that we can examine an executable
25
** and see what kind of security it supports.
26
*/
27
const char *ssl_version = "SECURITY_VERSION:"
28
                          " +us"
29
                          " +export"
30
#ifdef TRACE
31
                          " +trace"
32
#endif
33
#ifdef DEBUG
34
                          " +debug"
35
#endif
36
    ;
37
38
/***********************************************************************
39
 * Gathers in and handles records/messages until either the handshake is
40
 * complete or application data is available.
41
 *
42
 * Called from ssl_Do1stHandshake() via function pointer ss->handshake.
43
 * Caller must hold handshake lock.
44
 * This function acquires and releases the RecvBufLock.
45
 *
46
 * returns SECSuccess for success.
47
 * returns SECWouldBlock when that value is returned by
48
 *  ssl3_GatherCompleteHandshake().
49
 * returns SECFailure on all other errors.
50
 *
51
 * The gather functions called by ssl_GatherRecord1stHandshake are expected
52
 *  to return values interpreted as follows:
53
 *  1 : the function completed without error.
54
 *  0 : the function read EOF.
55
 * -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
56
 * -2 : the function wants ssl_GatherRecord1stHandshake to be called again
57
 *  immediately, by ssl_Do1stHandshake.
58
 *
59
 * This code is similar to, and easily confused with, DoRecv() in sslsecur.c
60
 *
61
 * This function is called from ssl_Do1stHandshake().
62
 * The following functions put ssl_GatherRecord1stHandshake into ss->handshake:
63
 *  ssl_BeginClientHandshake
64
 *  ssl3_RestartHandshakeAfterCertReq
65
 *  ssl3_RestartHandshakeAfterServerCert
66
 *  ssl_BeginServerHandshake
67
 */
68
SECStatus
69
ssl_GatherRecord1stHandshake(sslSocket *ss)
70
0
{
71
0
    int rv;
72
0
73
0
    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
74
0
75
0
    ssl_GetRecvBufLock(ss);
76
0
77
0
    /* Wait for handshake to complete, or application data to arrive.  */
78
0
    rv = ssl3_GatherCompleteHandshake(ss, 0);
79
0
    SSL_TRC(10, ("%d: SSL[%d]: handshake gathering, rv=%d",
80
0
                 SSL_GETPID(), ss->fd, rv));
81
0
82
0
    ssl_ReleaseRecvBufLock(ss);
83
0
84
0
    if (rv <= 0) {
85
0
        if (rv == SECWouldBlock) {
86
0
            /* Progress is blocked waiting for callback completion.  */
87
0
            SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)",
88
0
                         SSL_GETPID(), ss->fd, ss->gs.remainder));
89
0
            return SECWouldBlock;
90
0
        }
91
0
        if (rv == 0) {
92
0
            /* EOF. Loser  */
93
0
            PORT_SetError(PR_END_OF_FILE_ERROR);
94
0
        }
95
0
        return SECFailure; /* rv is < 0 here. */
96
0
    }
97
0
98
0
    ss->handshake = NULL;
99
0
    return SECSuccess;
100
0
}
101
102
/* This function is called at the beginning of a handshake to ensure that at
103
 * least one SSL/TLS version is enabled. */
104
static SECStatus
105
ssl_CheckConfigSanity(sslSocket *ss)
106
0
{
107
0
    if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
108
0
        SSL_DBG(("%d: SSL[%d]: Can't handshake! all versions disabled.",
109
0
                 SSL_GETPID(), ss->fd));
110
0
        PORT_SetError(SSL_ERROR_SSL_DISABLED);
111
0
        return SECFailure;
112
0
    }
113
0
    return SECSuccess;
114
0
}
115
116
/* Sends out the initial client Hello message on the connection.
117
 * Acquires and releases the socket's xmitBufLock.
118
 */
119
SECStatus
120
ssl_BeginClientHandshake(sslSocket *ss)
121
0
{
122
0
    sslSessionID *sid = NULL;
123
0
    SECStatus rv;
124
0
125
0
    PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss));
126
0
127
0
    ss->sec.isServer = PR_FALSE;
128
0
129
0
    rv = ssl_CheckConfigSanity(ss);
130
0
    if (rv != SECSuccess)
131
0
        goto loser;
132
0
133
0
    /* Get peer name of server */
134
0
    rv = ssl_GetPeerInfo(ss);
135
0
    if (rv < 0) {
136
#ifdef HPUX11
137
        /*
138
         * On some HP-UX B.11.00 systems, getpeername() occasionally
139
         * fails with ENOTCONN after a successful completion of
140
         * non-blocking connect.  I found that if we do a write()
141
         * and then retry getpeername(), it will work.
142
         */
143
        if (PR_GetError() == PR_NOT_CONNECTED_ERROR) {
144
            char dummy;
145
            (void)PR_Write(ss->fd->lower, &dummy, 0);
146
            rv = ssl_GetPeerInfo(ss);
147
            if (rv < 0) {
148
                goto loser;
149
            }
150
        }
151
#else
152
        goto loser;
153
0
#endif
154
0
    }
155
0
156
0
    SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd));
157
0
158
0
    /* If there's an sid set from an external cache, use it. */
159
0
    if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) {
160
0
        sid = ss->sec.ci.sid;
161
0
        SSL_TRC(3, ("%d: SSL[%d]: using external token", SSL_GETPID(), ss->fd));
162
0
    } else if (!ss->opt.noCache) {
163
0
        /* Try to find server in our session-id cache */
164
0
        sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID,
165
0
                            ss->url);
166
0
    }
167
0
168
0
    if (sid) {
169
0
        if (sid->version >= ss->vrange.min && sid->version <= ss->vrange.max) {
170
0
            PORT_Assert(!ss->sec.localCert);
171
0
            ss->sec.localCert = CERT_DupCertificate(sid->localCert);
172
0
        } else {
173
0
            ssl_UncacheSessionID(ss);
174
0
            ssl_FreeSID(sid);
175
0
            sid = NULL;
176
0
        }
177
0
    }
178
0
    if (!sid) {
179
0
        sid = PORT_ZNew(sslSessionID);
180
0
        if (!sid) {
181
0
            goto loser;
182
0
        }
183
0
        sid->references = 1;
184
0
        sid->cached = never_cached;
185
0
        sid->addr = ss->sec.ci.peer;
186
0
        sid->port = ss->sec.ci.port;
187
0
        if (ss->peerID != NULL) {
188
0
            sid->peerID = PORT_Strdup(ss->peerID);
189
0
        }
190
0
        if (ss->url != NULL) {
191
0
            sid->urlSvrName = PORT_Strdup(ss->url);
192
0
        }
193
0
    }
194
0
    ss->sec.ci.sid = sid;
195
0
196
0
    PORT_Assert(sid != NULL);
197
0
198
0
    ss->gs.state = GS_INIT;
199
0
    ss->handshake = ssl_GatherRecord1stHandshake;
200
0
201
0
    /* ssl3_SendClientHello will override this if it succeeds. */
202
0
    ss->version = SSL_LIBRARY_VERSION_3_0;
203
0
204
0
    ssl_GetSSL3HandshakeLock(ss);
205
0
    ssl_GetXmitBufLock(ss);
206
0
    rv = ssl3_SendClientHello(ss, client_hello_initial);
207
0
    ssl_ReleaseXmitBufLock(ss);
208
0
    ssl_ReleaseSSL3HandshakeLock(ss);
209
0
210
0
    return rv;
211
0
212
0
loser:
213
0
    return SECFailure;
214
0
}
215
216
SECStatus
217
ssl_BeginServerHandshake(sslSocket *ss)
218
0
{
219
0
    SECStatus rv;
220
0
221
0
    ss->sec.isServer = PR_TRUE;
222
0
    ss->ssl3.hs.ws = wait_client_hello;
223
0
224
0
    rv = ssl_CheckConfigSanity(ss);
225
0
    if (rv != SECSuccess)
226
0
        goto loser;
227
0
228
0
    ss->handshake = ssl_GatherRecord1stHandshake;
229
0
    return SECSuccess;
230
0
231
0
loser:
232
0
    return SECFailure;
233
0
}
234
235
/* This function doesn't really belong in this file.
236
** It's here to keep AIX compilers from optimizing it away,
237
** and not including it in the DSO.
238
*/
239
240
#include "nss.h"
241
extern const char __nss_ssl_version[];
242
243
PRBool
244
NSSSSL_VersionCheck(const char *importedVersion)
245
0
{
246
0
#define NSS_VERSION_VARIABLE __nss_ssl_version
247
0
#include "verref.h"
248
0
249
0
    /*
250
0
     * This is the secret handshake algorithm.
251
0
     *
252
0
     * This release has a simple version compatibility
253
0
     * check algorithm.  This release is not backward
254
0
     * compatible with previous major releases.  It is
255
0
     * not compatible with future major, minor, or
256
0
     * patch releases.
257
0
     */
258
0
    return NSS_VersionCheck(importedVersion);
259
0
}
260
261
const char *
262
NSSSSL_GetVersion(void)
263
0
{
264
0
    return NSS_VERSION;
265
0
}