Make server-side SSL work. Put common code in common.c.

This commit is contained in:
nicolson%netscape.com 2001-02-15 05:46:33 +00:00
Родитель 418c168bd1
Коммит 60d1142a0d
9 изменённых файлов: 1129 добавлений и 320 удалений

Просмотреть файл

@ -0,0 +1,258 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include <nspr.h>
#include <jni.h>
#include <ssl.h>
#include <sslerr.h>
#include <pk11func.h>
#include <keyhi.h>
#include <jssutil.h>
#include <jss_exceptions.h>
#include <java_ids.h>
#include <pk11util.h>
#include "jssl.h"
JNIEXPORT jbyteArray JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_socketCreate
(JNIEnv *env, jobject self)
{
return JSSL_socketCreate(env, self, NULL, NULL);
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_socketBind
(JNIEnv *env, jobject self, jbyteArray addrBA, jint port)
{
JSSL_socketBind(env, self, addrBA, port);
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_socketListen
(JNIEnv *env, jobject self, jint backlog)
{
JSSL_SocketData *sock;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
if( PR_Listen(sock->fd, backlog) != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Failed to set listen backlog on socket");
goto finish;
}
finish:
}
JNIEXPORT jbyteArray JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_socketAccept
(JNIEnv *env, jobject self, jobject newSock, jint timeout)
{
JSSL_SocketData *sock;
PRNetAddr addr;
PRFileDesc *newFD=NULL;
PRIntervalTime ivtimeout;
JSSL_SocketData *newSD=NULL;
jbyteArray sdArray = NULL;
SECStatus status;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
ivtimeout = (timeout > 0) ? PR_MillisecondsToInterval(timeout)
: PR_INTERVAL_NO_TIMEOUT;
for(;;) {
newFD = PR_Accept(sock->fd, &addr, ivtimeout);
if( newFD != NULL ) {
/* success! */
break;
} else {
switch( PR_GetError() ) {
case PR_PENDING_INTERRUPT_ERROR:
case PR_IO_PENDING_ERROR:
break; /* out of the switch and loop again */
default:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Failed to accept new connection");
goto finish;
}
}
}
newSD = JSSL_CreateSocketData(env, newSock, newFD);
newFD = NULL;
if( newSD == NULL ) {
goto finish;
}
/* setup the handshake callback */
status = SSL_HandshakeCallback(newSD->fd, JSSL_HandshakeCallback,
newSD);
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install handshake callback");
}
/* pass the pointer back to Java */
sdArray = JSS_ptrToByteArray(env, (void*) newSD);
if( sdArray == NULL ) {
/* exception was thrown */
goto finish;
}
finish:
if( (*env)->ExceptionOccurred(env) != NULL ) {
if( newSD != NULL ) {
JSSL_DestroySocketData(env, newSD);
}
if( newFD != NULL ) {
PR_Close(newFD);
}
}
return sdArray;
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_clearSessionCache(
JNIEnv *env, jclass clazz)
{
SSL_ClearSessionCache();
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_socketClose(JNIEnv *env, jobject self)
{
JSSL_socketClose(env, self);
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_configServerSessionIDCache(
JNIEnv *env, jclass myClass, jint maxEntries, jint ssl2Timeout,
jint ssl3Timeout, jstring nameString)
{
const char* dirName = NULL;
SECStatus status;
if (nameString != NULL) {
dirName = (*env)->GetStringUTFChars(env, nameString, NULL);
}
status = SSL_ConfigServerSessionIDCache(
maxEntries, ssl2Timeout, ssl3Timeout, dirName);
if (status != SECSuccess) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Failed to configure server session ID cache");
goto finish;
}
finish:
if(dirName != NULL) {
(*env)->ReleaseStringUTFChars(env, nameString, dirName);
}
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCertNickname(
JNIEnv *env, jobject self, jstring nicknameStr)
{
JSSL_SocketData *sock;
const char *nickname=NULL;
CERTCertificate* cert=NULL;
SECKEYPrivateKey* privKey=NULL;
SECStatus status;
if(nicknameStr == NULL) {
goto finish;
}
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
nickname = (*env)->GetStringUTFChars(env, nicknameStr, NULL);
if( nickname == NULL ) goto finish;
cert = PK11_FindCertFromNickname((char *)nickname, NULL); /* CONST */
if (cert != NULL) {
privKey = PK11_FindKeyByAnyCert(cert, NULL);
if (privKey != NULL) {
status = SSL_ConfigSecureServer(sock->fd, cert, privKey, kt_rsa);
if( status != SECSuccess) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Failed to configure secure server certificate and key");
goto finish;
}
} else {
JSS_throwMsg(env, SOCKET_EXCEPTION, "Failed to locate private key");
goto finish;
}
} else {
JSS_throwMsg(env, SOCKET_EXCEPTION, "Failed to locate private key");
goto finish;
}
finish:
if(privKey!=NULL) {
SECKEY_DestroyPrivateKey(privKey);
}
if(cert!=NULL) {
CERT_DestroyCertificate(cert);
}
if( nickname != NULL ) {
(*env)->ReleaseStringUTFChars(env, nicknameStr, nickname);
}
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_setNeedClientAuthNoExpiryCheck(
JNIEnv *env, jobject self, jboolean b)
{
JSSL_setNeedClientAuthNoExpiryCheck(env, self, b);
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLServerSocket_setNeedClientAuth(
JNIEnv *env, jobject self, jboolean b)
{
JSSL_SocketData *sock;
SECStatus status;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
status = SSL_OptionSet(sock->fd, SSL_REQUEST_CERTIFICATE, b);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "Failed to set socket option");
goto finish;
}
finish:
}

Просмотреть файл

@ -0,0 +1,138 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
package org.mozilla.jss.ssl;
import java.net.InetAddress;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class SSLServerSocket {
private static final int DEFAULT_BACKLOG = 50;
public SSLServerSocket(int port) throws IOException {
this(port, DEFAULT_BACKLOG, null);
}
public SSLServerSocket(int port, int backlog) throws IOException {
this(port, backlog, null);
}
public SSLServerSocket(int port, int backlog, InetAddress bindAddr)
throws IOException
{
// Dance the dance of fools. The superclass doesn't have a default
// constructor, so we have to trick it here. This is an example
// of WHY WE SHOULDN'T BE EXTENDING SERVERSOCKET.
//super(0);
//super.close();
// create the socket
sockProxy = new SocketProxy( socketCreate() );
// bind it to the local address and port
if( bindAddr == null ) {
bindAddr = anyLocalAddr;
}
socketBind(bindAddr.getAddress(), port);
socketListen(backlog);
}
private SocketProxy sockProxy;
private boolean handshakeAsClient=false;
private native byte[] socketCreate() throws SocketException;
private native void socketBind(byte[] addrBA, int port)
throws SocketException;
private native void socketListen(int backlog) throws SocketException;
private static InetAddress anyLocalAddr;
static {
try {
anyLocalAddr = InetAddress.getByName("0.0.0.0");
} catch (java.net.UnknownHostException e) { }
}
public Socket accept() throws IOException {
SSLSocket s = new SSLSocket();
s.setSockProxy( new SocketProxy( socketAccept(s, timeout) ) );
return s;
}
private int timeout;
public void setSoTimeout(int timeout) {
this.timeout = timeout;
}
public int getSoTimeout() {
return timeout;
}
private native byte[] socketAccept(SSLSocket s, int timeout)
throws SocketException;
public static native void clearSessionCache();
protected void finalize() throws Throwable {
close();
}
public void close() throws IOException {
if( sockProxy != null ) {
socketClose();
sockProxy = null;
}
}
private native void socketClose() throws IOException;
// This directory is used as the default for the Session ID cache
private final static String UNIX_TEMP_DIR = "/tmp";
private final static String WINDOWS_TEMP_DIR = "\\temp";
public static native void configServerSessionIDCache(int maxSidEntries,
int ssl2EntryTimeout, int ssl3EntryTimeout, String cacheFileDirectory);
public native void setServerCertNickname(String nickname)
throws SocketException;
public native void setNeedClientAuth(boolean b) throws SocketException;
public native void setNeedClientAuthNoExpiryCheck(boolean b)
throws SocketException;
}

Просмотреть файл

@ -42,94 +42,20 @@
#include <pk11util.h>
#include "jssl.h"
#ifdef JDK1_2
/* JDK 1.2 and higher provide weak references in JNI. */
#define NEW_WEAK_GLOBAL_REF(env, obj) \
((*env)->NewWeakGlobalRef((env), (obj)))
#define DELETE_WEAK_GLOBAL_REF(env, obj) \
((*env)->DeleteWeakGlobalRef((env), (obj)))
#else
/* JDK 1.1 doesn't have weak references, so we'll have to use regular ones */
#define NEW_WEAK_GLOBAL_REF(env, obj) \
((*env)->NewGlobalRef((env), (obj)))
#define DELETE_WEAK_GLOBAL_REF(env, obj) \
((*env)->DeleteGlobalRef((env), (obj)))
#endif
static PRStatus
JSS_SSL_getSockData(JNIEnv *env, jobject sockObject, JSSL_SocketData **sd);
SECStatus
JSSL_JavaCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer);
void
JSSL_HandshakeCallback(PRFileDesc *fd, void *arg);
int
JSSL_DefaultCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer);
int
JSSL_CallCertSelectionCallback( void * arg,
PRFileDesc * fd,
CERTDistNames * caNames,
CERTCertificate ** pRetCert,
SECKEYPrivateKey ** pRetKey);
static void
DestroyJSSL_SocketData(JNIEnv *env, JSSL_SocketData *sd)
{
PR_ASSERT(sd != NULL);
if( sd->fd != NULL ) {
PR_Close(sd->fd);
}
if( sd->socketObject != NULL ) {
DELETE_WEAK_GLOBAL_REF(env, sd->socketObject );
}
if( sd->certApprovalCallback != NULL ) {
(*env)->DeleteGlobalRef(env, sd->certApprovalCallback);
}
if( sd->clientCertSelectionCallback != NULL ) {
(*env)->DeleteGlobalRef(env, sd->clientCertSelectionCallback);
}
PR_Free(sd);
}
/*
* These must match up with the constants defined in SSLSocket.java.
*/
static PRInt32 enums[] = {
SSL_ENABLE_SSL2, /* 0 */
SSL_ENABLE_SSL3, /* 1 */
PR_SockOpt_NoDelay, /* 2 */
PR_SockOpt_Keepalive, /* 3 */
PR_SHUTDOWN_RCV, /* 4 */
PR_SHUTDOWN_SEND, /* 5 */
0
};
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_setSSLOption(JNIEnv *env, jobject self,
jint joption, jboolean on)
jint joption, jint on)
{
SECStatus status;
JSSL_SocketData *sock;
/* get my fd */
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
/* set the option */
status = SSL_OptionSet(sock->fd, enums[joption], on);
status = SSL_OptionSet(sock->fd, JSSL_enums[joption], on);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "SSL_OptionSet failed");
goto finish;
@ -141,12 +67,12 @@ finish:
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_setSSLDefaultOption(JNIEnv *env,
jclass clazz, jint joption, jboolean on)
jclass clazz, jint joption, jint on)
{
SECStatus status;
/* set the option */
status = SSL_OptionSetDefault(enums[joption], on);
status = SSL_OptionSetDefault(JSSL_enums[joption], on);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "SSL_OptionSet failed");
goto finish;
@ -163,7 +89,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_forceHandshake(JNIEnv *env, jobject self)
int rv;
/* get my fd */
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) goto finish;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) goto finish;
/* do the work */
rv = SSL_ForceHandshake(sock->fd);
@ -188,7 +114,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_setSoLInger(JNIEnv *env, jobject self,
PRStatus status;
JSSL_SocketData *sock;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -216,7 +142,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_getTcpNoDelay(JNIEnv *env, jobject self)
JSSL_SocketData *sock;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -240,7 +166,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_setTcpNoDelay(JNIEnv *env, jobject self,
PRStatus status;
JSSL_SocketData *sock;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -264,7 +190,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_getSendBufferSize(JNIEnv *env, jobject self)
JSSL_SocketData *sock;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -288,7 +214,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_setSendBufferSize(JNIEnv *env, jobject self,
PRStatus status;
JSSL_SocketData *sock;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -312,7 +238,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_getKeepAlive(JNIEnv *env, jobject self)
JSSL_SocketData *sock;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -336,7 +262,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_getReceiveBufferSize(
JSSL_SocketData *sock;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -360,7 +286,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_setReceiveBufferSize(
PRStatus status;
JSSL_SocketData *sock;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -385,7 +311,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_setKeepAlive(JNIEnv *env, jobject self,
PRStatus status;
JSSL_SocketData *sock;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -410,7 +336,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_getSoLinger(JNIEnv *env, jobject self)
jint retval;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -441,7 +367,7 @@ getSockAddr(JNIEnv *env, jobject self, PRNetAddr *addr, LocalOrPeer localOrPeer)
PRStatus status;
/* get my fd */
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
return;
}
@ -497,147 +423,15 @@ Java_org_mozilla_jss_ssl_SSLSocket_getPort(JNIEnv *env,
return addr.inet.port;
}
static PRStatus
JSS_SSL_getSockData(JNIEnv *env, jobject sockObject, JSSL_SocketData **sd)
{
PR_ASSERT(env!=NULL && sockObject!=NULL && sd!=NULL);
return JSS_getPtrFromProxyOwner(env, sockObject, SSLSOCKET_PROXY_FIELD,
SSLSOCKET_PROXY_SIG, (void**)sd);
}
JNIEXPORT jbyteArray JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_socketCreate
(JNIEnv *env, jobject self, jobject certApprovalCallback,
jobject clientCertSelectionCallback)
{
jbyteArray sdArray = NULL;
JSSL_SocketData *sockdata = NULL;
PRStatus status;
/* make a JSSL_SocketData structure */
sockdata = PR_Malloc( sizeof(JSSL_SocketData) );
sockdata->fd = NULL;
sockdata->socketObject = NULL;
sockdata->certApprovalCallback = NULL;
sockdata->clientCertSelectionCallback = NULL;
/* create a TCP socket */
sockdata->fd = PR_NewTCPSocket();
if( sockdata->fd == NULL ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "PR_NewTCPSocket() returned NULL");
goto finish;
}
/* enable SSL on the socket */
sockdata->fd = SSL_ImportFD(NULL, sockdata->fd);
if( sockdata->fd == NULL ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "SSL_ImportFD() returned NULL");
goto finish;
}
status = SSL_OptionSet(sockdata->fd, SSL_SECURITY, PR_TRUE);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to enable SSL security on socket");
goto finish;
}
/*
* Make a global ref to the socket. Since it is a weak reference, it will
* get garbage collected if this is the only reference that remains.
* We do this so that sockets will get closed when they go out of scope
* in the Java layer.
*/
sockdata->socketObject = NEW_WEAK_GLOBAL_REF(env, self);
if( sockdata->socketObject == NULL ) goto finish;
/* setup the handshake callback */
status = SSL_HandshakeCallback(sockdata->fd, JSSL_HandshakeCallback,
sockdata);
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install handshake callback");
}
/* setup the cert authentication callback */
if( certApprovalCallback != NULL ) {
/* create global reference to the callback object */
sockdata->certApprovalCallback =
(*env)->NewGlobalRef(env, certApprovalCallback);
if( sockdata->certApprovalCallback == NULL ) goto finish;
/* install the Java callback */
status = SSL_AuthCertificateHook(
sockdata->fd, JSSL_JavaCertAuthCallback,
(void*) sockdata->certApprovalCallback);
} else {
/* install the default callback */
status = SSL_AuthCertificateHook(
sockdata->fd, JSSL_DefaultCertAuthCallback, NULL);
}
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install certificate authentication callback");
goto finish;
}
/* setup the client cert selection callback */
if( clientCertSelectionCallback != NULL ) {
/* create a new global ref */
sockdata->clientCertSelectionCallback =
(*env)->NewGlobalRef(env, clientCertSelectionCallback);
if(sockdata->clientCertSelectionCallback == NULL) goto finish;
/* install the Java callback */
status = SSL_GetClientAuthDataHook(
sockdata->fd, JSSL_CallCertSelectionCallback,
(void*) sockdata->clientCertSelectionCallback);
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install client certificate selection callback");
goto finish;
}
}
/* pass the pointer back to Java */
sdArray = JSS_ptrToByteArray(env, (void*) sockdata);
if( sdArray == NULL ) {
/* exception was thrown */
goto finish;
}
finish:
if( (*env)->ExceptionOccurred(env) != NULL ) {
if( sockdata != NULL ) {
DestroyJSSL_SocketData(env, sockdata);
}
} else {
PR_ASSERT( sdArray != NULL );
}
return sdArray;
return JSSL_socketCreate(env, self, certApprovalCallback,
clientCertSelectionCallback);
}
#if 0
static void
throwMsgPRErr(JNIEnv *env, char* exceptionClassName, char* msg)
{
PRErrorCode errcode;
char *errstr;
int len;
len = strlen(msg) + 26;
errstr = (char*) PR_Malloc(len);
errcode = PR_GetError();
snprintf(errstr, len, "%s (error code %d)", msg, errcode);
JSS_throwMsg(env, exceptionClassName, errstr);
PR_Free(errstr);
}
#endif
/*
* This function assumes 4-byte IP addresses. It will need to be tweaked
* for IPv6.
@ -650,74 +444,13 @@ JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_socketBind
(JNIEnv *env, jobject self, jbyteArray addrBA, jint port)
{
JSSL_SocketData *sock;
PRNetAddr addr;
jbyte *addrBAelems = NULL;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) {
/* exception was thrown */
goto finish;
}
/*
* setup the PRNetAddr structure
*/
addr.inet.family = AF_INET;
addr.inet.port = port;
PR_ASSERT(sizeof(addr.inet.ip) == 4);
PR_ASSERT( (*env)->GetArrayLength(env, addrBA) == 4);
addrBAelems = (*env)->GetByteArrayElements(env, addrBA, NULL);
if( addrBAelems == NULL ) {
ASSERT_OUTOFMEM(env);
goto finish;
}
memcpy(&addr.inet.ip, addrBAelems, 4);
/* do the bind() call */
status = PR_Bind(sock->fd, &addr);
if( status != PR_SUCCESS ) {
PRErrorCode err = PR_GetError();
switch( err ) {
case PR_ADDRESS_NOT_AVAILABLE_ERROR:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Binding exception: address not available");
break;
case PR_ADDRESS_IN_USE_ERROR:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Binding exception: address in use");
break;
default:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Binding exception");
break;
}
goto finish;
}
finish:
if( addrBAelems != NULL ) {
(*env)->ReleaseByteArrayElements(env, addrBA, addrBAelems, JNI_ABORT);
}
JSSL_socketBind(env, self, addrBA, port);
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_socketClose(JNIEnv *env, jobject self)
{
JSSL_SocketData *sock;
printf("***\nClosing socket\n***\n");
/* get the FD */
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) {
/* exception was thrown */
goto finish;
}
/* destroy the FD and any supporting data */
DestroyJSSL_SocketData(env, sock);
finish:
JSSL_socketClose(env, self);
}
JNIEXPORT void JNICALL
@ -731,7 +464,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_socketConnect
int stat;
const char *hostnameStr=NULL;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) {
/* exception was thrown */
goto finish;
}
@ -802,7 +535,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_getStatus
jobject serialNumObj = NULL;
/* get the fd */
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) {
/* exception was thrown */
goto finish;
}
@ -923,7 +656,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_socketRead(JNIEnv *env, jobject self,
jint nread;
/* get the socket */
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -982,7 +715,7 @@ Java_com_netscape_jss_ssl_SSLSocketImpl_socketAvailable(
jint available;
JSSL_SocketData *sock;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -1013,7 +746,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_socketWrite(JNIEnv *env, jobject self,
goto finish;
}
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) {
goto finish;
}
@ -1064,9 +797,9 @@ Java_org_mozilla_jss_ssl_SSLSocket_shutdownNative(
JSSL_SocketData *sock;
PRStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
status = PR_Shutdown(sock->fd, enums[how]);
status = PR_Shutdown(sock->fd, JSSL_enums[how]);
if( status != PR_SUCCESS) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "Failed to shutdown socket");
goto finish;
@ -1081,7 +814,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_invalidateSession(JNIEnv *env, jobject self)
JSSL_SocketData *sock;
SECStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
status = SSL_InvalidateSession(sock->fd);
if(status != SECSuccess) {
@ -1099,7 +832,7 @@ Java_org_mozilla_jss_ssl_SSLSocket_redoHandshake(
JSSL_SocketData *sock;
SECStatus status;
if( JSS_SSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
status = SSL_ReHandshake(sock->fd, flushCache);
if(status != SECSuccess) {
@ -1109,3 +842,66 @@ Java_org_mozilla_jss_ssl_SSLSocket_redoHandshake(
finish:
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_resetHandshake(
JNIEnv *env, jobject self, jboolean asClient)
{
JSSL_SocketData *sock;
SECStatus status;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
status = SSL_ResetHandshake(sock->fd, !asClient);
if(status != SECSuccess) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "Failed to redo handshake");
goto finish;
}
finish:
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_setClientCertNicknameNative(
JNIEnv *env, jobject self, jstring nickStr)
{
JSSL_SocketData *sock;
const char *nick=NULL;
SECStatus status;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
/*
* Store the nickname in the SocketData.
*/
nick = (*env)->GetStringUTFChars(env, nickStr, NULL);
if( nick == NULL ) goto finish;
if( sock->clientCertNickname != NULL ) {
PR_Free(sock->clientCertNickname);
}
sock->clientCertNickname = PL_strdup(nick);
/*
* Install the callback.
*/
status = SSL_GetClientAuthDataHook(sock->fd, JSSL_GetClientAuthData,
(void*)sock);
if(status != SECSuccess) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to set client auth data hook");
goto finish;
}
finish:
if( nick != NULL ) {
(*env)->ReleaseStringUTFChars(env, nickStr, nick);
}
}
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_setNeedClientAuthNoExpiryCheck(
JNIEnv *env, jobject self, jboolean b)
{
JSSL_setNeedClientAuthNoExpiryCheck(env, self, b);
}

Просмотреть файл

@ -34,7 +34,9 @@
package org.mozilla.jss.ssl;
import java.net.*;
import java.net.SocketException;
import java.io.*;
import java.io.IOException;
import java.util.LinkedList;
import java.util.ListIterator;
@ -46,6 +48,14 @@ public class SSLSocket extends java.net.Socket {
SSLSocket() throws IOException {
}
/**
* Should only be called by SSLServerSocket after a successful
* accept().
*/
void setSockProxy(SocketProxy sp) {
sockProxy = sp;
}
public SSLSocket(String host, int port)
throws UnknownHostException, IOException
{
@ -194,7 +204,6 @@ public class SSLSocket extends java.net.Socket {
return new SSLOutputStream(this);
}
public native void setTcpNoDelay(boolean on) throws SocketException;
public native boolean getTcpNoDelay() throws SocketException;
@ -292,14 +301,66 @@ public class SSLSocket extends java.net.Socket {
setSSLDefaultOption(SSL_ENABLE_SSL3, enable);
}
public void requireClientAuth(boolean require, boolean onRedo)
throws SocketException
{
setSSLOption(SSL_REQUIRE_CERTIFICATE, require ? (onRedo ? 1 : 2) : 0);
}
public void requireClientAuthDefault(boolean require, boolean onRedo)
throws SocketException
{
setSSLDefaultOption(SSL_REQUIRE_CERTIFICATE,
require ? (onRedo ? 1 : 2) : 0);
}
public native void forceHandshake() throws SocketException;
public void setUseClientMode(boolean b) {
handshakeAsClient = b;
}
public boolean getUseClientMode() {
return handshakeAsClient;
}
public void resetHandshake() throws SocketException {
resetHandshakeNative(handshakeAsClient);
}
private native void resetHandshakeNative(boolean asClient)
throws SocketException;
public native SSLSecurityStatus getStatus() throws SocketException;
public void setClientCertNickname(String nick) throws SocketException {
if( nick != null && nick.length() > 0 ) {
setClientCertNicknameNative(nick);
}
}
public native void setClientCertNicknameNative(String nick)
throws SocketException;
public void setNeedClientAuth(boolean b) throws SocketException {
setSSLOption(SSL_REQUEST_CERTIFICATE, b);
}
public native void setNeedClientAuthNoExpiryCheck(boolean b)
throws SocketException;
public void useCache(boolean b) throws SocketException {
setSSLOption(SSL_NO_CACHE, !b);
}
public void useCacheDefault(boolean b) throws SocketException {
setSSLDefaultOption(SSL_NO_CACHE, !b);
}
private InetAddress inetAddress;
private int port;
private SocketProxy sockProxy;
private boolean open = false;
private boolean handshakeAsClient=true;
/**
* Enums. These must match the enums table in SSLSocket.c. This is
@ -312,6 +373,9 @@ public class SSLSocket extends java.net.Socket {
private static final int SO_KEEPALIVE = 3;
private static final int PR_SHUTDOWN_RCV = 4;
private static final int PR_SHUTDOWN_SEND = 5;
private static final int SSL_REQUIRE_CERTIFICATE = 6;
private static final int SSL_REQUEST_CERTIFICATE = 7;
private static final int SSL_NO_CACHE = 8;
/**
* SO_TIMEOUT timeout in millis. I don't know why we have to keep it here
@ -319,9 +383,19 @@ public class SSLSocket extends java.net.Socket {
*/
private int timeout;
private native void setSSLOption(int option, boolean on)
private void setSSLOption(int option, boolean on)
throws SocketException
{
setSSLOption(option, on ? 1 : 0);
}
private native void setSSLOption(int option, int on)
throws SocketException;
private static native void setSSLDefaultOption(int option, boolean on)
private static void setSSLDefaultOption(int option, boolean on)
throws SocketException
{
setSSLDefaultOption(option, on ? 1 : 0);
}
private static native void setSSLDefaultOption(int option, int on)
throws SocketException;
private native byte[] socketCreate(
@ -424,20 +498,3 @@ public class SSLSocket extends java.net.Socket {
}
class SocketProxy extends org.mozilla.jss.util.NativeProxy {
public SocketProxy(byte[] pointer) {
super(pointer);
}
/**
* Theoretically, we don't need to do anything, since SSLSocket should
* call close() when it finalizes. When a socket is closed all its
* resources are freed, and there's nothing left to release.
*/
protected void releaseNativeResources() { }
protected void finalize() throws Throwable {
super.finalize();
}
}

Просмотреть файл

@ -0,0 +1,52 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
package org.mozilla.jss.ssl;
class SocketProxy extends org.mozilla.jss.util.NativeProxy {
public SocketProxy(byte[] pointer) {
super(pointer);
}
/**
* Theoretically, we don't need to do anything, since SSLSocket should
* call close() when it finalizes. When a socket is closed all its
* resources are freed, and there's nothing left to release.
*/
protected void releaseNativeResources() { }
protected void finalize() throws Throwable {
super.finalize();
}
}

Просмотреть файл

@ -607,3 +607,94 @@ finish:
return retval;
}
PR_IMPLEMENT( int )
JSSL_GetClientAuthData( void * arg,
PRFileDesc * fd,
CERTDistNames * caNames,
CERTCertificate ** pRetCert,
SECKEYPrivateKey ** pRetKey)
{
CERTCertificate * cert;
SECKEYPrivateKey * privkey;
JSSL_SocketData * sock;
SECStatus rv = SECFailure;
PR_ASSERT(arg != NULL);
sock = (JSSL_SocketData*) arg;
if (sock->clientCertNickname) {
cert = PK11_FindCertFromNickname(sock->clientCertNickname,
NULL /*pinarg*/);
if ( cert ) {
privkey = PK11_FindKeyByAnyCert(cert, NULL /*pinarg*/);
if ( privkey ) {
rv = SECSuccess;
} else {
CERT_DestroyCertificate(cert);
}
}
}
if (rv == SECSuccess) {
*pRetCert = cert;
*pRetKey = privkey;
}
return rv;
}
/*
* Callback from SSL for checking a (possibly) expired
* certificate the peer presents.
*/
PR_IMPLEMENT( int )
JSSL_ConfirmExpiredPeerCert(void *arg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer)
{
char* hostname;
SECStatus rv=SECFailure;
SECCertUsage certUsage;
CERTCertificate* peerCert=NULL;
int64 notAfter, notBefore;
certUsage = isServer ? certUsageSSLClient : certUsageSSLServer;
peerCert = SSL_PeerCertificate(fd);
if (peerCert) {
rv = CERT_GetCertTimes(peerCert, &notBefore, &notAfter);
if (rv != SECSuccess) goto finish;
/*
* Verify the certificate based on it's expiry date. This should
* always succeed, if the cert is trusted. It doesn't care if
* the cert has expired.
*/
rv = CERT_VerifyCert(CERT_GetDefaultCertDB(), peerCert,
checkSig, certUsage,
notAfter, NULL /*pinarg*/,
NULL /* log */);
}
if ( rv != SECSuccess ) goto finish;
if( ! isServer ) {
/* This is the client side of an SSL connection.
* Now check the name field in the cert against the desired hostname.
* NB: This is our only defense against Man-In-The-Middle (MITM) attacks!
*/
if( peerCert == NULL ) {
rv = SECFailure;
} else {
hostname = SSL_RevealURL(fd); /* really is a hostname, not a URL */
if (hostname && hostname[0]) {
rv = CERT_VerifyCertName(peerCert, hostname);
} else {
rv = SECFailure;
}
}
}
finish:
if (peerCert!=NULL) CERT_DestroyCertificate(peerCert);
return (int)rv;
}

Просмотреть файл

@ -0,0 +1,329 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include <nspr.h>
#include <jni.h>
#include <ssl.h>
#include <sslerr.h>
#include <jssutil.h>
#include <jss_exceptions.h>
#include <java_ids.h>
#include <pk11util.h>
#include "jssl.h"
/*
* This is done for regular sockets that we connect() and server sockets,
* but not for sockets that come from accept.
*/
jbyteArray
JSSL_socketCreate(JNIEnv *env, jobject self,
jobject certApprovalCallback, jobject clientCertSelectionCallback)
{
jbyteArray sdArray = NULL;
JSSL_SocketData *sockdata;
PRStatus status;
PRFileDesc *newFD;
/* create a TCP socket */
newFD = PR_NewTCPSocket();
if( newFD == NULL ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "PR_NewTCPSocket() returned NULL");
goto finish;
}
sockdata = JSSL_CreateSocketData(env, self, newFD);
if( sockdata == NULL ) {
goto finish;
}
/* enable SSL on the socket */
sockdata->fd = SSL_ImportFD(NULL, sockdata->fd);
if( sockdata->fd == NULL ) {
JSS_throwMsg(env, SOCKET_EXCEPTION, "SSL_ImportFD() returned NULL");
goto finish;
}
status = SSL_OptionSet(sockdata->fd, SSL_SECURITY, PR_TRUE);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to enable SSL security on socket");
goto finish;
}
/* setup the handshake callback */
status = SSL_HandshakeCallback(sockdata->fd, JSSL_HandshakeCallback,
sockdata);
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install handshake callback");
}
/* setup the cert authentication callback */
if( certApprovalCallback != NULL ) {
/* create global reference to the callback object */
sockdata->certApprovalCallback =
(*env)->NewGlobalRef(env, certApprovalCallback);
if( sockdata->certApprovalCallback == NULL ) goto finish;
/* install the Java callback */
status = SSL_AuthCertificateHook(
sockdata->fd, JSSL_JavaCertAuthCallback,
(void*) sockdata->certApprovalCallback);
} else {
/* install the default callback */
status = SSL_AuthCertificateHook(
sockdata->fd, JSSL_DefaultCertAuthCallback, NULL);
}
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install certificate authentication callback");
goto finish;
}
/* setup the client cert selection callback */
if( clientCertSelectionCallback != NULL ) {
/* create a new global ref */
sockdata->clientCertSelectionCallback =
(*env)->NewGlobalRef(env, clientCertSelectionCallback);
if(sockdata->clientCertSelectionCallback == NULL) goto finish;
/* install the Java callback */
status = SSL_GetClientAuthDataHook(
sockdata->fd, JSSL_CallCertSelectionCallback,
(void*) sockdata->clientCertSelectionCallback);
if( status != PR_SUCCESS ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Unable to install client certificate selection callback");
goto finish;
}
}
/* pass the pointer back to Java */
sdArray = JSS_ptrToByteArray(env, (void*) sockdata);
if( sdArray == NULL ) {
/* exception was thrown */
goto finish;
}
finish:
if( (*env)->ExceptionOccurred(env) != NULL ) {
if( sockdata != NULL ) {
JSSL_DestroySocketData(env, sockdata);
}
} else {
PR_ASSERT( sdArray != NULL );
}
return sdArray;
}
JSSL_SocketData*
JSSL_CreateSocketData(JNIEnv *env, jobject sockObj, PRFileDesc* newFD)
{
JSSL_SocketData *sockdata = NULL;
/* make a JSSL_SocketData structure */
sockdata = PR_Malloc( sizeof(JSSL_SocketData) );
sockdata->fd = NULL;
sockdata->socketObject = NULL;
sockdata->certApprovalCallback = NULL;
sockdata->clientCertSelectionCallback = NULL;
sockdata->clientCertNickname = NULL;
sockdata->fd = newFD;
/*
* Make a global ref to the socket. Since it is a weak reference, it will
* get garbage collected if this is the only reference that remains.
* We do this so that sockets will get closed when they go out of scope
* in the Java layer.
*/
sockdata->socketObject = NEW_WEAK_GLOBAL_REF(env, sockObj);
if( sockdata->socketObject == NULL ) goto finish;
finish:
if( (*env)->ExceptionOccurred(env) != NULL ) {
if( sockdata != NULL ) {
JSSL_DestroySocketData(env, sockdata);
sockdata = NULL;
} else {
PR_ASSERT( sockdata != NULL );
}
}
return sockdata;
}
void
JSSL_DestroySocketData(JNIEnv *env, JSSL_SocketData *sd)
{
PR_ASSERT(sd != NULL);
if( sd->fd != NULL ) {
PR_Close(sd->fd);
}
if( sd->socketObject != NULL ) {
DELETE_WEAK_GLOBAL_REF(env, sd->socketObject );
}
if( sd->certApprovalCallback != NULL ) {
(*env)->DeleteGlobalRef(env, sd->certApprovalCallback);
}
if( sd->clientCertSelectionCallback != NULL ) {
(*env)->DeleteGlobalRef(env, sd->clientCertSelectionCallback);
}
if( sd->clientCertNickname != NULL ) {
PR_Free(sd->clientCertNickname);
}
PR_Free(sd);
}
/*
* These must match up with the constants defined in SSLSocket.java.
*/
PRInt32 JSSL_enums[] = {
SSL_ENABLE_SSL2, /* 0 */
SSL_ENABLE_SSL3, /* 1 */
PR_SockOpt_NoDelay, /* 2 */
PR_SockOpt_Keepalive, /* 3 */
PR_SHUTDOWN_RCV, /* 4 */
PR_SHUTDOWN_SEND, /* 5 */
SSL_REQUIRE_CERTIFICATE, /* 6 */
SSL_REQUEST_CERTIFICATE, /* 7 */
SSL_NO_CACHE, /* 8 */
0
};
void
JSSL_socketBind(JNIEnv *env, jobject self, jbyteArray addrBA, jint port)
{
JSSL_SocketData *sock;
PRNetAddr addr;
jbyte *addrBAelems = NULL;
PRStatus status;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) {
/* exception was thrown */
goto finish;
}
/*
* setup the PRNetAddr structure
*/
addr.inet.family = AF_INET;
addr.inet.port = htons(port);
PR_ASSERT(sizeof(addr.inet.ip) == 4);
PR_ASSERT( (*env)->GetArrayLength(env, addrBA) == 4);
addrBAelems = (*env)->GetByteArrayElements(env, addrBA, NULL);
if( addrBAelems == NULL ) {
ASSERT_OUTOFMEM(env);
goto finish;
}
memcpy(&addr.inet.ip, addrBAelems, 4);
/* do the bind() call */
status = PR_Bind(sock->fd, &addr);
if( status != PR_SUCCESS ) {
PRErrorCode err = PR_GetError();
switch( err ) {
case PR_ADDRESS_NOT_AVAILABLE_ERROR:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Binding exception: address not available");
break;
case PR_ADDRESS_IN_USE_ERROR:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Binding exception: address in use");
break;
default:
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Binding exception");
break;
}
goto finish;
}
finish:
if( addrBAelems != NULL ) {
(*env)->ReleaseByteArrayElements(env, addrBA, addrBAelems, JNI_ABORT);
}
}
void
JSSL_socketClose(JNIEnv *env, jobject self)
{
JSSL_SocketData *sock;
/* get the FD */
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) {
/* exception was thrown */
goto finish;
}
/* destroy the FD and any supporting data */
JSSL_DestroySocketData(env, sock);
finish:
}
void
JSSL_setNeedClientAuthNoExpiryCheck(JNIEnv *env, jobject self, jboolean b)
{
JSSL_SocketData *sock;
SECStatus status;
if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) goto finish;
/*
* Set the option on the socket
*/
status = SSL_OptionSet(sock->fd, SSL_REQUEST_CERTIFICATE, b);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Failed to set REQUEST_CERTIFICATE option on socket");
goto finish;
}
if(b) {
/*
* Set the callback function
*/
status = SSL_AuthCertificateHook(sock->fd,
JSSL_ConfirmExpiredPeerCert, NULL /*cx*/);
if( status != SECSuccess ) {
JSS_throwMsg(env, SOCKET_EXCEPTION,
"Failed to set certificate authentication callback");
goto finish;
}
}
finish:
}

Просмотреть файл

@ -39,7 +39,83 @@ struct JSSL_SocketData {
jobject socketObject; /* weak global ref */
jobject certApprovalCallback; /* global ref */
jobject clientCertSelectionCallback; /* global ref */
char *clientCertNickname;
};
typedef struct JSSL_SocketData JSSL_SocketData;
SECStatus
JSSL_JavaCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer);
void
JSSL_HandshakeCallback(PRFileDesc *fd, void *arg);
int
JSSL_DefaultCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer);
int
JSSL_CallCertSelectionCallback( void * arg,
PRFileDesc * fd,
CERTDistNames * caNames,
CERTCertificate ** pRetCert,
SECKEYPrivateKey ** pRetKey);
int
JSSL_ConfirmExpiredPeerCert(void *arg, PRFileDesc *fd, PRBool checkSig,
PRBool isServer);
int
JSSL_GetClientAuthData( void * arg,
PRFileDesc * fd,
CERTDistNames * caNames,
CERTCertificate ** pRetCert,
SECKEYPrivateKey ** pRetKey);
#ifdef JDK1_2
/* JDK 1.2 and higher provide weak references in JNI. */
#define NEW_WEAK_GLOBAL_REF(env, obj) \
((*env)->NewWeakGlobalRef((env), (obj)))
#define DELETE_WEAK_GLOBAL_REF(env, obj) \
((*env)->DeleteWeakGlobalRef((env), (obj)))
#else
/* JDK 1.1 doesn't have weak references, so we'll have to use regular ones */
#define NEW_WEAK_GLOBAL_REF(env, obj) \
((*env)->NewGlobalRef((env), (obj)))
#define DELETE_WEAK_GLOBAL_REF(env, obj) \
((*env)->DeleteGlobalRef((env), (obj)))
#endif
#define JSSL_getSockData(env, sockObject, sdptr) \
JSS_getPtrFromProxyOwner(env, sockObject, SSLSOCKET_PROXY_FIELD, \
SSLSOCKET_PROXY_SIG, (void**)sdptr)
void
JSSL_DestroySocketData(JNIEnv *env, JSSL_SocketData *sd);
extern PRInt32 JSSL_enums[];
void
JSSL_socketBind(JNIEnv *env, jobject self, jbyteArray addrBA, jint port);
void
JSSL_socketClose(JNIEnv *env, jobject self);
jbyteArray
JSSL_socketCreate(JNIEnv *env, jobject self,
jobject certApprovalCallback, jobject clientCertSelectionCallback);
JSSL_SocketData*
JSSL_CreateSocketData(JNIEnv *env, jobject sockObj, PRFileDesc* newFD);
void
JSSL_setNeedClientAuthNoExpiryCheck(JNIEnv *env, jobject self, jboolean b);
#endif

Просмотреть файл

@ -44,9 +44,12 @@ PACKAGE = org/mozilla/jss/ssl
JNI_GEN = org.mozilla.jss.ssl.SSLSocket \
$(NULL)
JSRCS = SSLHandshakeCompletedEvent.java \
JSRCS = \
SocketProxy.java \
SSLHandshakeCompletedEvent.java \
SSLSecurityStatus.java \
SSLHandshakeCompletedListener.java \
SSLServerSocket.java \
SSLSocket.java \
SSLInputStream.java \
SSLOutputStream.java \
@ -55,7 +58,9 @@ JSRCS = SSLHandshakeCompletedEvent.java \
SSLClientCertificateSelectionCallback.java \
$(NULL)
PRIVATE_JSRCS = SSLClient.java \
PRIVATE_JSRCS = \
SSLClient.java \
SSLServer.java \
TestCertApprovalCallback.java \
TestClientCertificateSelectionCallback.java \
$(NULL)
@ -69,6 +74,7 @@ PRIVATE_JSRCS = SSLClient.java \
CLASSES = SSLHandshakeCompletedEvent \
SSLSecurityStatus \
SSLHandshakeCompletedListener \
SSLServerSocket \
SSLSocket \
PrintOutputStreamWriter \
SSLCallbackNotifier \
@ -76,7 +82,11 @@ CLASSES = SSLHandshakeCompletedEvent \
SSLClientCertificateSelectionCallback \
$(NULL)
#PRIVATE_CLASSES = SSLServer \
PRIVATE_CLASSES = \
SSLServer \
SSLClient \
$(NULL)
#SSLClient \
#ServerHandshakeCB \
#ClientHandshakeCB \
@ -84,6 +94,8 @@ CLASSES = SSLHandshakeCompletedEvent \
CSRCS = SSLSocket.c \
callbacks.c \
SSLServerSocket.c \
common.c \
$(NULL)
LIBRARY_NAME = jssssl