/*
 *  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;
}
