15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/* 25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle 35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2008, Google Inc. 45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2011, RTFM, Inc. 55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without 75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met: 85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer. 115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * this list of conditions and the following disclaimer in the documentation 135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * and/or other materials provided with the distribution. 145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 3. The name of the author may not be used to endorse or promote products 155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * derived from this software without specific prior written permission. 165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * 175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */ 285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <vector> 305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if HAVE_CONFIG_H 325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "config.h" 335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // HAVE_CONFIG_H 345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#if HAVE_NSS_SSL_H 365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/nssstreamadapter.h" 385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "keyhi.h" 405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "nspr.h" 415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "nss.h" 425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "pk11pub.h" 435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "secerr.h" 445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef NSS_SSL_RELATIVE_PATH 465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "ssl.h" 475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "sslerr.h" 485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "sslproto.h" 495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "net/third_party/nss/ssl/ssl.h" 515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "net/third_party/nss/ssl/sslerr.h" 525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "net/third_party/nss/ssl/sslproto.h" 535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/nssidentity.h" 565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/thread.h" 575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace talk_base { 595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPRDescIdentity NSSStreamAdapter::nspr_layer_identity = PR_INVALID_IO_LAYER; 615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define UNIMPLEMENTED \ 635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); \ 645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) \ 655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << "Call to unimplemented function "<< __FUNCTION__; ASSERT(false) 665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef SRTP_AES128_CM_HMAC_SHA1_80 685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#define HAVE_DTLS_SRTP 695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef HAVE_DTLS_SRTP 725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// SRTP cipher suite table 735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct SrtpCipherMapEntry { 745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const char* external_name; 755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRUint16 cipher_id; 765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// This isn't elegant, but it's better than an external reference 795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const SrtpCipherMapEntry kSrtpCipherMap[] = { 805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org {"AES_CM_128_HMAC_SHA1_80", SRTP_AES128_CM_HMAC_SHA1_80 }, 815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org {"AES_CM_128_HMAC_SHA1_32", SRTP_AES128_CM_HMAC_SHA1_32 }, 825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org {NULL, 0} 835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Implementation of NSPR methods 885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamClose(PRFileDesc *socket) { 895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Noop 905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_SUCCESS; 915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamRead(PRFileDesc *socket, void *buf, PRInt32 length) { 945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret); 955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t read; 965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int error; 975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamResult result = stream->Read(buf, length, &read, &error); 985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result == SR_SUCCESS) { 995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return read; 1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result == SR_EOS) { 1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result == SR_BLOCK) { 1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_SetError(PR_UNKNOWN_ERROR, error); 1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamWrite(PRFileDesc *socket, const void *buf, 1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 length) { 1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret); 1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t written; 1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int error; 1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamResult result = stream->Write(buf, length, &written, &error); 1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result == SR_SUCCESS) { 1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return written; 1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (result == SR_BLOCK) { 1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << 1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org "NSSStreamAdapter: write to underlying transport would block"; 1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_SetError(PR_WOULD_BLOCK_ERROR, 0); 1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Write error"; 1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_SetError(PR_UNKNOWN_ERROR, error); 1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamAvailable(PRFileDesc *socket) { 1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPRInt64 StreamAvailable64(PRFileDesc *socket) { 1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamSync(PRFileDesc *socket) { 1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PROffset32 StreamSeek(PRFileDesc *socket, PROffset32 offset, 1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRSeekWhence how) { 1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PROffset64 StreamSeek64(PRFileDesc *socket, PROffset64 offset, 1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRSeekWhence how) { 1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamFileInfo(PRFileDesc *socket, PRFileInfo *info) { 1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamFileInfo64(PRFileDesc *socket, PRFileInfo64 *info) { 1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamWritev(PRFileDesc *socket, const PRIOVec *iov, 1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 iov_size, PRIntervalTime timeout) { 1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamConnect(PRFileDesc *socket, const PRNetAddr *addr, 1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRIntervalTime timeout) { 1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRFileDesc *StreamAccept(PRFileDesc *sd, PRNetAddr *addr, 1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRIntervalTime timeout) { 1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return NULL; 1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamBind(PRFileDesc *socket, const PRNetAddr *addr) { 1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamListen(PRFileDesc *socket, PRIntn depth) { 1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamShutdown(PRFileDesc *socket, PRIntn how) { 2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Note: this is always nonblocking and ignores the timeout. 2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// TODO(ekr@rtfm.com): In future verify that the socket is 2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// actually in non-blocking mode. 2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// This function does not support peek. 2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamRecv(PRFileDesc *socket, void *buf, PRInt32 amount, 2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRIntn flags, PRIntervalTime to) { 2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(flags == 0); 2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (flags != 0) { 2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return StreamRead(socket, buf, amount); 2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Note: this is always nonblocking and assumes a zero timeout. 2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// This function does not support peek. 2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamSend(PRFileDesc *socket, const void *buf, 2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 amount, PRIntn flags, 2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRIntervalTime to) { 2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(flags == 0); 2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return StreamWrite(socket, buf, amount); 2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamRecvfrom(PRFileDesc *socket, void *buf, 2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 amount, PRIntn flags, 2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRNetAddr *addr, PRIntervalTime to) { 2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamSendto(PRFileDesc *socket, const void *buf, 2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 amount, PRIntn flags, 2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PRNetAddr *addr, PRIntervalTime to) { 2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt16 StreamPoll(PRFileDesc *socket, PRInt16 in_flags, 2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt16 *out_flags) { 2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRNetAddr **raddr, 2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org void *buf, PRInt32 amount, PRIntervalTime t) { 2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamTransmitFile(PRFileDesc *sd, PRFileDesc *socket, 2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const void *headers, PRInt32 hlen, 2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRTransmitFileFlags flags, PRIntervalTime t) { 2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamGetPeerName(PRFileDesc *socket, PRNetAddr *addr) { 2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(ekr@rtfm.com): Modify to return unique names for each channel 2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // somehow, as opposed to always the same static address. The current 2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // implementation messes up the session cache, which is why it's off 2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // elsewhere 2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr->inet.family = PR_AF_INET; 2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr->inet.port = 0; 2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org addr->inet.ip = 0; 2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_SUCCESS; 2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamGetSockName(PRFileDesc *socket, PRNetAddr *addr) { 2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamGetSockOption(PRFileDesc *socket, PRSocketOptionData *opt) { 2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (opt->option) { 2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case PR_SockOpt_Nonblocking: 2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org opt->value.non_blocking = PR_TRUE; 2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_SUCCESS; 2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Imitate setting socket options. These are mostly noops. 2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamSetSockOption(PRFileDesc *socket, 2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const PRSocketOptionData *opt) { 3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (opt->option) { 3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case PR_SockOpt_Nonblocking: 3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_SUCCESS; 3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case PR_SockOpt_NoDelay: 3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_SUCCESS; 3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRInt32 StreamSendfile(PRFileDesc *out, PRSendFileData *in, 3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRTransmitFileFlags flags, PRIntervalTime to) { 3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRStatus StreamConnectContinue(PRFileDesc *socket, PRInt16 flags) { 3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return PR_FAILURE; 3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic PRIntn StreamReserved(PRFileDesc *socket) { 3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic const struct PRIOMethods nss_methods = { 3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_DESC_LAYERED, 3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamClose, 3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamRead, 3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamWrite, 3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamAvailable, 3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamAvailable64, 3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSync, 3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSeek, 3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSeek64, 3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamFileInfo, 3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamFileInfo64, 3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamWritev, 3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamConnect, 3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamAccept, 3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamBind, 3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamListen, 3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamShutdown, 3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamRecv, 3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSend, 3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamRecvfrom, 3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSendto, 3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamPoll, 3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamAcceptRead, 3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamTransmitFile, 3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamGetSockName, 3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamGetPeerName, 3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamReserved, 3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamReserved, 3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamGetSockOption, 3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSetSockOption, 3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamSendfile, 3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamConnectContinue, 3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamReserved, 3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamReserved, 3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamReserved, 3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamReserved 3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgNSSStreamAdapter::NSSStreamAdapter(StreamInterface *stream) 3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org : SSLStreamAdapterHelper(stream), 3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssl_fd_(NULL), 3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org cert_ok_(false) { 3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::Init() { 3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (nspr_layer_identity == PR_INVALID_IO_LAYER) { 3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org nspr_layer_identity = PR_GetUniqueIdentity("nssstreamadapter"); 3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRFileDesc *pr_fd = PR_CreateIOLayerStub(nspr_layer_identity, &nss_methods); 3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!pr_fd) 3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org pr_fd->secret = reinterpret_cast<PRFilePrivate *>(stream()); 3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRFileDesc *ssl_fd; 3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ssl_mode_ == SSL_MODE_DTLS) { 3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssl_fd = DTLS_ImportFD(NULL, pr_fd); 3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssl_fd = SSL_ImportFD(NULL, pr_fd); 3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(ssl_fd != NULL); // This should never happen 3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!ssl_fd) { 3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_Close(pr_fd); 3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv; 3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Turn on security. 3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_SECURITY, PR_TRUE); 3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Error enabling security on SSL Socket"; 4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disable SSLv2. 4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SSL2, PR_FALSE); 4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Error disabling SSL2"; 4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disable caching. 4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(ekr@rtfm.com): restore this when I have the caching 4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // identity set. 4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE); 4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Error disabling cache"; 4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disable session tickets. 4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); 4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Error enabling tickets"; 4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disable renegotiation. 4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, 4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SSL_RENEGOTIATE_NEVER); 4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Error disabling renegotiation"; 4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Disable false start. 4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE); 4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Error disabling false start"; 4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssl_fd_ = ssl_fd; 4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgNSSStreamAdapter::~NSSStreamAdapter() { 4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ssl_fd_) 4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_Close(ssl_fd_); 4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}; 4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint NSSStreamAdapter::BeginSSL() { 4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv; 4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!Init()) { 4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("Init", -1, false); 4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(state_ == SSL_CONNECTING); 4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The underlying stream has been opened. If we are in peer-to-peer mode 4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // then a peer certificate must have been specified by now. 4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(!ssl_server_name_.empty() || 4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org peer_certificate_.get() != NULL || 4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org !peer_certificate_digest_algorithm_.empty()); 4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "BeginSSL: " 4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << (!ssl_server_name_.empty() ? ssl_server_name_ : 4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org "with peer"); 4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (role_ == SSL_CLIENT) { 4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "BeginSSL: as client"; 4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_GetClientAuthDataHook(ssl_fd_, GetClientAuthDataHook, 4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this); 4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "BeginSSL: as server"; 4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSSIdentity *identity; 4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (identity_.get()) { 4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org identity = static_cast<NSSIdentity *>(identity_.get()); 4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Can't be an SSL server without an identity"; 4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_ConfigSecureServer(ssl_fd_, identity->certificate().certificate(), 4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org identity->keypair()->privkey(), 4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org kt_rsa); 4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Insist on a certificate from the client 4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE); 5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_OptionSet(ssl_fd_, SSL_REQUIRE_CERTIFICATE, PR_TRUE); 5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Set the version range. 5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SSLVersionRange vrange; 5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org vrange.min = (ssl_mode_ == SSL_MODE_DTLS) ? 5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SSL_LIBRARY_VERSION_TLS_1_1 : 5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SSL_LIBRARY_VERSION_TLS_1_0; 5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org vrange.max = SSL_LIBRARY_VERSION_TLS_1_1; 5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_VersionRangeSet(ssl_fd_, &vrange); 5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // SRTP 5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef HAVE_DTLS_SRTP 5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!srtp_ciphers_.empty()) { 5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_SetSRTPCiphers(ssl_fd_, &srtp_ciphers_[0], srtp_ciphers_.size()); 5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Certificate validation 5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this); 5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Now start the handshake 5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = SSL_ResetHandshake(ssl_fd_, role_ == SSL_SERVER ? PR_TRUE : PR_FALSE); 5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", -1, false); 5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return ContinueSSL(); 5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint NSSStreamAdapter::ContinueSSL() { 5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "ContinueSSL"; 5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(state_ == SSL_CONNECTING); 5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Clear the DTLS timer 5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT); 5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv = SSL_ForceHandshake(ssl_fd_); 5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv == SECSuccess) { 5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Handshake complete"; 5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(cert_ok_); 5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!cert_ok_) { 5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("ContinueSSL", -1, true); 5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = SSL_CONNECTED; 5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamAdapterInterface::OnEvent(stream(), SE_OPEN|SE_READ|SE_WRITE, 0); 5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 err = PR_GetError(); 5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (err) { 5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_ERROR_RX_MALFORMED_HANDSHAKE: 5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ssl_mode_ != SSL_MODE_DTLS) { 5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("ContinueSSL", -1, true); 5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Malformed DTLS message. Ignoring."; 5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Fall through 5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case PR_WOULD_BLOCK_ERROR: 5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Would have blocked"; 5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ssl_mode_ == SSL_MODE_DTLS) { 5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRIntervalTime timeout; 5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv = DTLS_GetHandshakeTimeout(ssl_fd_, &timeout); 5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv == SECSuccess) { 5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Timeout is " << timeout << " ms"; 5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Thread::Current()->PostDelayed(PR_IntervalToMilliseconds(timeout), 5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org this, MSG_DTLS_TIMEOUT, 0); 5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return 0; 6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Error " << err; 6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("ContinueSSL", -1, true); 6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return -1; 6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid NSSStreamAdapter::Cleanup() { 6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_ != SSL_ERROR) { 6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = SSL_CLOSED; 6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ssl_fd_) { 6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PR_Close(ssl_fd_); 6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ssl_fd_ = NULL; 6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org identity_.reset(); 6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org peer_certificate_.reset(); 6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT); 6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgStreamResult NSSStreamAdapter::Read(void* data, size_t data_len, 6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t* read, int* error) { 6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // SSL_CONNECTED sanity check. 6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (state_) { 6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_NONE: 6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_WAIT: 6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_CONNECTING: 6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_BLOCK; 6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_CONNECTED: 6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_CLOSED: 6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_EOS; 6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_ERROR: 6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (error) 6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *error = ssl_error_code_; 6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_ERROR; 6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 rv = PR_Read(ssl_fd_, data, data_len); 6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv == 0) { 6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_EOS; 6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Error 6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv < 0) { 6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 err = PR_GetError(); 6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (err) { 6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case PR_WOULD_BLOCK_ERROR: 6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_BLOCK; 6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("Read", -1, false); 6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *error = err; // libjingle semantics are that this is impl-specific 6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_ERROR; 6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Success 6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *read = rv; 6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_SUCCESS; 6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgStreamResult NSSStreamAdapter::Write(const void* data, size_t data_len, 6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t* written, int* error) { 6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // SSL_CONNECTED sanity check. 6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (state_) { 6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_NONE: 6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_WAIT: 6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_CONNECTING: 6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_BLOCK; 6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_CONNECTED: 6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_ERROR: 6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case SSL_CLOSED: 6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (error) 6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *error = ssl_error_code_; 6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_ERROR; 6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 rv = PR_Write(ssl_fd_, data, data_len); 6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Error 6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv < 0) { 6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRInt32 err = PR_GetError(); 6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org switch (err) { 7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org case PR_WOULD_BLOCK_ERROR: 7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_BLOCK; 7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org default: 7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("Write", -1, false); 7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *error = err; // libjingle semantics are that this is impl-specific 7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_ERROR; 7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Success 7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *written = rv; 7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SR_SUCCESS; 7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid NSSStreamAdapter::OnEvent(StreamInterface* stream, int events, 7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int err) { 7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int events_to_signal = 0; 7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org int signal_error = 0; 7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(stream == this->stream()); 7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((events & SE_OPEN)) { 7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::OnEvent SE_OPEN"; 7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_ != SSL_WAIT) { 7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(state_ == SSL_NONE); 7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events_to_signal |= SE_OPEN; 7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org state_ = SSL_CONNECTING; 7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (int err = BeginSSL()) { 7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("BeginSSL", err, true); 7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((events & (SE_READ|SE_WRITE))) { 7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::OnEvent" 7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << ((events & SE_READ) ? " SE_READ" : "") 7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org << ((events & SE_WRITE) ? " SE_WRITE" : ""); 7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_ == SSL_NONE) { 7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events_to_signal |= events & (SE_READ|SE_WRITE); 7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (state_ == SSL_CONNECTING) { 7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (int err = ContinueSSL()) { 7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Error("ContinueSSL", err, true); 7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return; 7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (state_ == SSL_CONNECTED) { 7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events & SE_WRITE) { 7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << " -- onStreamWriteable"; 7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events_to_signal |= SE_WRITE; 7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events & SE_READ) { 7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << " -- onStreamReadable"; 7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events_to_signal |= SE_READ; 7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if ((events & SE_CLOSE)) { 7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::OnEvent(SE_CLOSE, " << err << ")"; 7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Cleanup(); 7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org events_to_signal |= SE_CLOSE; 7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // SE_CLOSE is the only event that uses the final parameter to OnEvent(). 7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(signal_error == 0); 7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org signal_error = err; 7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (events_to_signal) 7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamAdapterInterface::OnEvent(stream, events_to_signal, signal_error); 7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid NSSStreamAdapter::OnMessage(Message* msg) { 7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Process our own messages and then pass others to the superclass 7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (MSG_DTLS_TIMEOUT == msg->message_id) { 7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "DTLS timeout expired"; 7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ContinueSSL(); 7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org StreamInterface::OnMessage(msg); 7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Certificate verification callback. Called to check any certificate 7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSECStatus NSSStreamAdapter::AuthCertificateHook(void *arg, 7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRFileDesc *fd, 7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRBool checksig, 7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRBool isServer) { 7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "NSSStreamAdapter::AuthCertificateHook"; 7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSSCertificate peer_cert(SSL_PeerCertificate(fd)); 7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool ok = false; 7855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(ekr@rtfm.com): Should we be enforcing self-signed like 7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // the OpenSSL version? 7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (stream->peer_certificate_.get()) { 7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Checking against specified certificate"; 7925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 7935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The peer certificate was specified 7945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (reinterpret_cast<NSSCertificate *>(stream->peer_certificate_.get())-> 7955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Equals(&peer_cert)) { 7965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Accepted peer certificate"; 7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ok = true; 7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else if (!stream->peer_certificate_digest_algorithm_.empty()) { 8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Checking against specified digest"; 8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // The peer certificate digest was specified 8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org unsigned char digest[64]; // Maximum size 8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::size_t digest_length; 8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!peer_cert.ComputeDigest( 8065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org stream->peer_certificate_digest_algorithm_, 8075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org digest, sizeof(digest), &digest_length)) { 8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Digest computation failed"; 8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org Buffer computed_digest(digest, digest_length); 8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (computed_digest == stream->peer_certificate_digest_value_) { 8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Accepted peer certificate"; 8135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ok = true; 8145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } else { 8175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Other modes, but we haven't implemented yet 8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // TODO(ekr@rtfm.com): Implement real certificate validation 8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org UNIMPLEMENTED; 8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (ok) { 8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org stream->cert_ok_ = true; 82459a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org 82559a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org // Record the peer's certificate chain. 82659a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org CERTCertList* cert_list = SSL_PeerCertificateChain(fd); 82759a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org ASSERT(cert_list != NULL); 82859a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org 82959a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org stream->peer_certificate_.reset(new NSSCertificate(cert_list)); 83059a1e5569576b61b7ae1f0d7fe72c958c940e156wu@webrtc.org CERT_DestroyCertList(cert_list); 8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SECSuccess; 8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!ok && stream->ignore_bad_cert()) { 8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; 8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org stream->cert_ok_ = true; 8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SECSuccess; 8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); 8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SECFailure; 8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSECStatus NSSStreamAdapter::GetClientAuthDataHook(void *arg, PRFileDesc *fd, 8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CERTDistNames *caNames, 8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org CERTCertificate **pRetCert, 8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECKEYPrivateKey **pRetKey) { 8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_INFO) << "Client cert requested"; 8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg); 8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!stream->identity_.get()) { 8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "No identity available"; 8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SECFailure; 8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSSIdentity *identity = static_cast<NSSIdentity *>(stream->identity_.get()); 8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Destroyed internally by NSS 8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *pRetCert = CERT_DupCertificate(identity->certificate().certificate()); 8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *pRetKey = SECKEY_CopyPrivateKey(identity->keypair()->privkey()); 8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return SECSuccess; 8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// RFC 5705 Key Exporter 8665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label, 8675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const uint8* context, 8685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t context_len, 8695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool use_context, 8705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org uint8* result, 8715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org size_t result_len) { 8725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_, 8735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org label.c_str(), label.size(), 8745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org use_context, 8755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org context, context_len, 8765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org result, result_len); 8775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return rv == SECSuccess; 8795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 8805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::SetDtlsSrtpCiphers( 8825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org const std::vector<std::string>& ciphers) { 8835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef HAVE_DTLS_SRTP 8845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org std::vector<PRUint16> internal_ciphers; 8855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_ != SSL_NONE) 8865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 8875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 8885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (std::vector<std::string>::const_iterator cipher = ciphers.begin(); 8895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org cipher != ciphers.end(); ++cipher) { 8905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org bool found = false; 8915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; entry->cipher_id; 8925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ++entry) { 8935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (*cipher == entry->external_name) { 8945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org found = true; 8955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org internal_ciphers.push_back(entry->cipher_id); 8965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org break; 8975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 8995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!found) { 9015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Could not find cipher: " << *cipher; 9025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (internal_ciphers.empty()) 9075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org srtp_ciphers_ = internal_ciphers; 9105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 9125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 9135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 9155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::GetDtlsSrtpCipher(std::string* cipher) { 9185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef HAVE_DTLS_SRTP 9195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(state_ == SSL_CONNECTED); 9205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (state_ != SSL_CONNECTED) 9215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PRUint16 selected_cipher; 9245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, &selected_cipher); 9265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv == SECFailure) 9275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; 9305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org entry->cipher_id; ++entry) { 9315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (selected_cipher == entry->cipher_id) { 9325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *cipher = entry->external_name; 9335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 9345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(false); // This should never happen 9385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 9395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSContext::initialized; 9445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgNSSContext *NSSContext::global_nss_context; 9455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Static initialization and shutdown 9475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgNSSContext *NSSContext::Instance() { 9485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!global_nss_context) { 9495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSSContext *new_ctx = new NSSContext(); 9505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!(new_ctx->slot_ = PK11_GetInternalSlot())) { 9525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org delete new_ctx; 9535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org goto fail; 9545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org global_nss_context = new_ctx; 9575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org fail: 9605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return global_nss_context; 9615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSContext::InitializeSSL(VerificationCallback callback) { 9665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org ASSERT(!callback); 9675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (!initialized) { 9695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org SECStatus rv; 9705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org rv = NSS_NoDB_Init(NULL); 9725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org if (rv != SECSuccess) { 9735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org LOG(LS_ERROR) << "Couldn't initialize NSS error=" << 9745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org PORT_GetError(); 9755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 9765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org NSS_SetDomesticPolicy(); 9795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org initialized = true; 9815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org } 9825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 9845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSContext::InitializeSSLThread() { 9875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Not needed 9885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 9895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSContext::CleanupSSL() { 9925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org // Not needed 9935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 9945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 9965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::HaveDtls() { 9975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 9985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 9995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::HaveDtlsSrtp() { 10015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#ifdef HAVE_DTLS_SRTP 10025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 10035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#else 10045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return false; 10055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif 10065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool NSSStreamAdapter::HaveExporter() { 10095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org return true; 10105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} 10115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org} // namespace talk_base 10135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org 10145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#endif // HAVE_NSS_SSL_H 1015