blob: 99e30621f4ebdaf6264b7eefb7cc67ae5cb23d9f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sslSession.h"
#include <stdio.h>
#include "jni.h"
#include "hysock.h"
#include "openssl/bio.h"
#include "openssl/ssl.h"
#include "openssl/err.h"
#include "cipherList.h"
JNIEXPORT jlong JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSessionImpl_initialiseSession
(JNIEnv *env, jobject object, jlong jssl)
{
SSL *ssl = jlong2addr(SSL, jssl);
return addr2jlong(SSL_get_session(ssl));
}
char* getSpecName(const char *cipherName, char *openSSLNames[], char *specNames[], int mappedNamesCount) {
int i;
for (i=0; i<mappedNamesCount; i++) {
if (!strcmp(cipherName, openSSLNames[i])) {
return specNames[i];
}
}
return NULL;
}
JNIEXPORT jstring JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSessionImpl_getCipherNameImpl
(JNIEnv *env, jobject object, jlong jssl) {
SSL *ssl = jlong2addr(SSL, jssl);
const char *cipherName = SSL_get_cipher(ssl);
char *protocol = SSL_get_cipher_version(ssl);
char *specName = NULL;
char *finalName;
if (!strcmp(protocol, "TLSv1/SSLv3")) {
// We're in either TLS or SSLv3, now find the spec name
specName = getSpecName(cipherName, getTLSv1OpenSSLNames(), getTLSv1SpecNames(), TLSv1_CIPHER_COUNT);
if (specName) {
protocol = "TLSv1";
} else {
// Not in the TLS list, now search the SSL list
// TODO: Lists are likely to be the same - can this case ever occur?
specName = getSpecName(cipherName, getSSLv3OpenSSLNames(), getSSLv3SpecNames(), SSLv3_CIPHER_COUNT);
protocol = "SSLv3";
}
} else if (!strcmp(protocol, "(NONE)")) {
// Handshake not completed yet - return NULL protocol/cipher
return (*env)->NewStringUTF(env, "NONE:SSL_NULL_WITH_NULL_NULL");
} else {
// SSLv2 case - protocol will already be "SSLv2", so no need to set it
specName = getSpecName(cipherName, getSSLv2OpenSSLNames(), getSSLv2SpecNames(), SSLv2_CIPHER_COUNT);
}
// finalName is "protocol:specName\0"
// protocol length is always 5, so allocate strlen(specName) + 5 + 1 for the colon + 1 for the terminator
finalName = malloc(strlen(specName)+7);
strcpy(finalName, protocol);
strcat(finalName, ":");
strcat(finalName, specName);
return (*env)->NewStringUTF(env, finalName);
}
JNIEXPORT jlong JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSessionImpl_getCreationTimeImpl
(JNIEnv *env, jobject object, jlong jsession) {
SSL_SESSION *session = jlong2addr(SSL_SESSION, jsession);
return (jlong)SSL_SESSION_get_time(session)*1000;
}
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_xnet_provider_jsse_SSLSessionImpl_getPeerCertificatesImpl
(JNIEnv *env, jobject object, jlong jssl) {
SSL *ssl = jlong2addr(SSL, jssl);
STACK_OF(X509) *certs;
int certCount, i;
jobjectArray jcerts;
jclass byteArrayClass;
// Get the chain of peer certificates from OpenSSL
certs = SSL_get_peer_cert_chain(ssl);
if (!certs) {
return NULL;
}
// Get the number of certificates in the chain
certCount = sk_num(&certs->stack);
if (!certCount) {
return NULL;
}
// Allocate an array of jbyte arrays to contain the peer certs
byteArrayClass = (*env)->FindClass(env, "[B");
jcerts = (*env)->NewObjectArray(env, certCount, byteArrayClass, NULL);
for (i=0; i<certCount; i++) {
unsigned char *certBuffer = NULL;
jbyteArray jcertBuffer;
// OpenSSL will automatically allocate the buffer for us because certBuffer is NULL
int len = i2d_X509(sk_value(&certs->stack, i), &certBuffer);
// Allocate a jbyte array for the certificate data and copy it over
jcertBuffer = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(env, jcertBuffer, 0, len, (jbyte*)certBuffer);
(*env)->SetObjectArrayElement(env, jcerts, i, jcertBuffer);
}
return jcerts;
}