/*
 * 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 <stdio.h>
#include <axis2_util.h>
#include <openssl_rsa.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/bio.h>
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#include <oxs_buffer.h>
#include <oxs_error.h>
#include <openssl_pkcs12.h>
#include <openssl_x509.h>
#include <oxs_utility.h>

/*Usefull when we have BinarySecurityTokn*/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
openssl_x509_load_from_buffer(const axutil_env_t *env,
                              axis2_char_t *b64_encoded_buf,
                              X509 **cert)
{
    unsigned char *buff = NULL;
    BIO *mem = NULL;
    int ilen = 0;
    axis2_char_t *formatted_buf = NULL;
    axis2_char_t *buf_to_format = NULL;
    int decode_len = 0;
    int decoded_len = -1;

    /*We should remove new lines here.*/
    buf_to_format = (axis2_char_t*)axutil_strdup(env, b64_encoded_buf);
    if(buf_to_format)
    {
        formatted_buf = oxs_util_get_newline_removed_string(env,buf_to_format);
        AXIS2_FREE(env->allocator,buf_to_format);
        buf_to_format = NULL;
    }
    else
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT, "New line removed buffer creation failed.");
        return AXIS2_FAILURE;
    }

    decode_len = axutil_base64_decode_len(formatted_buf );
    buff = AXIS2_MALLOC(env->allocator, decode_len);
    ilen = axutil_strlen(formatted_buf);
    decoded_len = axutil_base64_decode_binary(buff, formatted_buf);

    AXIS2_FREE(env->allocator, formatted_buf);
    formatted_buf = NULL;

    if (decoded_len < 0)
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT, "axutil_base64_decode_binary failed");
        return AXIS2_FAILURE;
    }

    if ((mem = BIO_new_mem_buf(buff, ilen)) == NULL)
    {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT, "Cannot create a new memory buffer");
        return AXIS2_FAILURE;
    }

    *cert = d2i_X509_bio(mem, NULL);
    /*Free*/
    BIO_free(mem);
    mem = NULL;

    AXIS2_FREE(env->allocator, buff);
    buff = NULL;

    if (*cert == NULL){
        return AXIS2_FAILURE;
    }

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
openssl_x509_load_from_pem(const axutil_env_t *env,
                           axis2_char_t *filename,
                           X509 **cert)
{
    BIO *in = NULL;

    in = BIO_new_file(filename,"r");

    if (!in)
    {
        return AXIS2_FAILURE;
    }
    /*Read certificate*/
    PEM_read_bio_X509(in, cert, NULL, NULL);

    if (-1 == BIO_reset(in) ){
		BIO_free(in);
        return AXIS2_FAILURE;
    }

	if (-1 == BIO_free(in)  ){
        return AXIS2_FAILURE;
    }

    if(!*cert)
    {
        return AXIS2_FAILURE;
    }

    return AXIS2_SUCCESS;
}


AXIS2_EXTERN axis2_status_t AXIS2_CALL
openssl_x509_load_from_pkcs12(const axutil_env_t *env,
                              axis2_char_t *filename,
                              axis2_char_t *password,
                              X509 **cert,
                              EVP_PKEY **pkey,
                              STACK_OF(X509) **ca)
{
    PKCS12 *p12 = NULL;
    axis2_status_t status = AXIS2_FAILURE;

    /*Load*/
    status = openssl_pkcs12_load(env, filename, &p12);
    if(AXIS2_FAILURE == status){
        return AXIS2_FAILURE;
    }
    /*Parse*/
    status = openssl_pkcs12_parse(env, password, p12, pkey,
                                  cert,
                                  ca);
    if(AXIS2_FAILURE == status){
        return AXIS2_FAILURE;
    }
    /*Free*/
    status = openssl_pkcs12_free(env, p12);
    if(AXIS2_FAILURE == status){
        return AXIS2_FAILURE;
    }

    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
openssl_x509_load_certificate(const axutil_env_t *env,
                              openssl_x509_format_t format,
                              axis2_char_t *filename,
                              axis2_char_t *password,
                              X509 **cert)
{
    axis2_status_t status = AXIS2_FAILURE;

    if(OPENSSL_X509_FORMAT_PEM == format){
        /*Load from PEM*/
        status = openssl_x509_load_from_pem(env, filename, cert);
        if(AXIS2_FAILURE == status){
            return AXIS2_FAILURE;
        }
    }else if(OPENSSL_X509_FORMAT_PKCS12 == format){
        /*Load from PKCS12*/
        EVP_PKEY *pkey = NULL;
        STACK_OF(X509) *ca = NULL;
        status = openssl_x509_load_from_pkcs12(env, filename, password, cert, &pkey, &ca);
        if(AXIS2_FAILURE == status){
            return AXIS2_FAILURE;
        }
    }else if(OPENSSL_X509_FORMAT_DER == format){
        /*Load from DER*/

    }else{
        /*Unspported*/
    }
    return AXIS2_SUCCESS;
}


/*
 * Here we take data in btwn
 -----BEGIN CERTIFICATE-----
 -----END CERTIFICATE-----
 */

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
openssl_x509_get_cert_data(const axutil_env_t *env,
                           X509 *cert)
{
    axis2_char_t *unformatted = NULL;
    axis2_char_t *core_tail = NULL;
    axis2_char_t *core = NULL;
    axis2_char_t *res = NULL;
    axis2_char_t *buffer = NULL;

    unformatted = openssl_x509_get_info(env, OPENSSL_X509_INFO_DATA_CERT, cert);
    core_tail = axutil_strstr(unformatted, "\n");
    res = axutil_strstr(core_tail,"-----END");
    res[0] = '\0';
    core = (axis2_char_t*)axutil_strdup(env, core_tail);
    if(core)
    {
        buffer = oxs_util_get_newline_removed_string(env, core);
        AXIS2_FREE(env->allocator, core);
        AXIS2_FREE(env->allocator, unformatted);
        unformatted = NULL;
        core = NULL;
        return buffer;
    }else{
        return NULL;
    }
}


AXIS2_EXTERN int AXIS2_CALL
openssl_x509_get_serial(
    const axutil_env_t *env,
    X509 *cert)
{
    axis2_char_t *serial = NULL;
    int no = 0;
    
    /*WARN: Do not use the serial number without converting it to the integer.*/
    serial = (axis2_char_t*)i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert));
    if(serial)
    {
        no = atoi(serial);
        OPENSSL_free(serial);
        serial = NULL;
        return no;
    }
    else
    {
        return -1;
    }
}

AXIS2_EXTERN unsigned long AXIS2_CALL
openssl_x509_get_subject_name_hash(const axutil_env_t *env,
                                   X509 *cert)
{
    unsigned long l = 0;
    l=X509_subject_name_hash(cert);
    return l;
}

AXIS2_EXTERN axis2_status_t AXIS2_CALL
openssl_x509_get_pubkey(const axutil_env_t *env,
                        X509 *cert,
                        EVP_PKEY **pubkey)
{
    *pubkey = X509_get_pubkey(cert);
    return AXIS2_SUCCESS;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
openssl_x509_get_subject_key_identifier(const axutil_env_t *env,
                                        X509 *cert)
{
    X509_EXTENSION *ext;
    ASN1_OCTET_STRING *key_id = NULL;
    int index = 0;
    EVP_ENCODE_CTX ctx;
    int len, ret;
    char buf[1000];
    char output[100];
    axis2_char_t *ski = NULL;

    /*Get ext by ID*/
    index = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
    if (index < 0) {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT,
                  "The extenension index of NID_subject_key_identifier is not valid");
        return NULL;
    }
    /*Get the extension*/
    ext = X509_get_ext(cert, index);
    if (ext == NULL) {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT,
                  "The extension for NID_subject_key_identifier is NULL");
        return NULL;
    }
    /*Subject Key Identifier*/
    key_id = (ASN1_OCTET_STRING *)X509V3_EXT_d2i(ext);
    if (key_id == NULL) {
        oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT,
                  "The SubjectKeyIdentifier is NULL");
        return NULL;
    }
    memcpy(buf, key_id->data, key_id->length);
    buf[key_id->length] = 0;

    EVP_EncodeInit(&ctx);
    EVP_EncodeUpdate(&ctx, (unsigned char*)output, &len, (unsigned char*)buf, key_id->length);
    EVP_EncodeFinal(&ctx, (unsigned char*)(output+len), &ret);

    /*Free key_id*/
    M_ASN1_OCTET_STRING_free(key_id);
    key_id = NULL;

    ret += len;
    ski = axutil_strdup(env, output);
    return ski;
}

AXIS2_EXTERN axis2_char_t *AXIS2_CALL
openssl_x509_get_info(const axutil_env_t *env,
                      openssl_x509_info_type_t type,
                      X509 *cert)
{
    BIO *out = NULL;
    unsigned char *data= NULL;
    axis2_char_t *result = NULL;
    int n = 0;

    out = BIO_new(BIO_s_mem());
    if(OPENSSL_X509_INFO_SUBJECT==type){
        X509_NAME_print_ex(out, X509_get_subject_name(cert), 0, 0);
    }else if(OPENSSL_X509_INFO_ISSUER == type){
        X509_NAME_print_ex(out, X509_get_issuer_name(cert), 0, 0);
    }else if(OPENSSL_X509_INFO_VALID_FROM == type){
        ASN1_TIME_print(out, X509_get_notBefore(cert));
    }else if(OPENSSL_X509_INFO_VALID_TO == type){
        ASN1_TIME_print(out, X509_get_notAfter(cert));
    }else if(OPENSSL_X509_INFO_DATA_CERT == type){
        if(!PEM_write_bio_X509_AUX(out, cert)){
            return NULL;
        }
    }else if(OPENSSL_X509_INFO_FINGER == type){
        const EVP_MD *digest = NULL;
        unsigned char md[EVP_MAX_MD_SIZE];
        unsigned int _n = 0;

        digest = EVP_sha1();/*If we use EVP_md5(); here we can get the digest from md5. */
        if(X509_digest(cert,digest,md,&_n))
        {
            /*BIO_printf(out, "%s:", OBJ_nid2sn(EVP_MD_type(digest)));
            int j = 0;
            for (j=0; j<(int)_n; j++)
            {
                BIO_printf (out, "%02X",md[j]);
                if (j+1 != (int)_n) BIO_printf(out,":");
            }*/
            /*We need to base64 encode the digest value of the finger print*/
            axis2_char_t *encoded_str = NULL;
            
            encoded_str = AXIS2_MALLOC(env->allocator, axutil_base64_encode_len(_n));
            axutil_base64_encode(encoded_str, (char*)md, SHA_DIGEST_LENGTH);
            BIO_printf(out, "%s", encoded_str); 
			AXIS2_FREE(env->allocator, encoded_str);
        }
    }else if(OPENSSL_X509_INFO_SIGNATURE == type){
        int i = 0;
        unsigned char *s = NULL;

        n=cert->signature->length;
        s=cert->signature->data;
        for (i=0; i<n; i++)
        {
            if ( ((i%18) == 0) && (i!=0) ) BIO_printf(out,"\n");
            BIO_printf(out,"%02x%s",s[i], (((i+1)%18) == 0)?"":":");
        }

    }else if(OPENSSL_X509_INFO_VERSION == type){
        long l = 0.0;

        l = X509_get_version(cert);
        BIO_printf (out,"%lu (0x%lx)",l+1,l);
    }else if(OPENSSL_X509_INFO_PUBKEY == type){
        EVP_PKEY *pkey = NULL;

        pkey=X509_get_pubkey(cert);
        if (pkey != NULL)
        {
            if (pkey->type == EVP_PKEY_RSA){
                RSA_print(out,pkey->pkey.rsa,0);
            }else if (pkey->type == EVP_PKEY_DSA){
                DSA_print(out,pkey->pkey.dsa,0);
            }
            EVP_PKEY_free(pkey);
            pkey = NULL;
        }
    }else if(OPENSSL_X509_INFO_PUBKEY_ALGO == type){
        X509_CINF *ci = NULL;

        ci = cert->cert_info;
        i2a_ASN1_OBJECT(out, ci->key->algor->algorithm);
    }
    n = BIO_get_mem_data(out, &data);
    result = axutil_strndup( env, data, n);

    BIO_free(out);
    out = NULL;

    return result;
}

AXIS2_EXTERN axis2_char_t * AXIS2_CALL
openssl_x509_get_common_name(
	const axutil_env_t *env,
	X509 *cert)
{
	X509_NAME *subject = NULL;
	int pos = -1;
	X509_NAME_ENTRY *entry = NULL;
	ASN1_STRING *entry_str;
	BIO *out = NULL;
	unsigned char *data= NULL;
	axis2_char_t *result = NULL;
	int n = 0;
	
	out = BIO_new(BIO_s_mem());
	subject = X509_get_subject_name(cert);
	pos = X509_NAME_get_index_by_NID(subject, NID_commonName, -1);
	
	if(pos < 0)
	{
		oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT,
		                  "No Common Name in given X509 Certificate!");
		return NULL;
	}
	
	if (X509_NAME_get_index_by_NID(subject, NID_commonName, pos) >= 0)
	{
		/* Handling multiple common names. */
	}	

	if ((entry = X509_NAME_get_entry(subject, pos)) == 0)
	{
		oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT,
				  "Error occured during when retrieving common name from X509_NAME!");
		return NULL;		   
	}
	
	if ((entry_str = X509_NAME_ENTRY_get_data(entry)) == 0)
	{
		oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_DEFAULT,
						  "Error occured during when retrieving common name from X509_NAME_ENTRY!");
		return NULL;
	}
	
	ASN1_TIME_print(out, entry_str);
	n = BIO_get_mem_data(out, &data);
	result = axutil_strndup( env, data, n);

	BIO_free(out);
	out = NULL;
	
	return result;
}

AXIS2_EXTERN void  AXIS2_CALL
openssl_x509_print(const axutil_env_t *env,
                   X509 *cert)
{
    printf("\n*************START PRINTING*****************\n");
    printf("OPENSSL_X509_INFO_SUBJECT : %s\n", openssl_x509_get_info(env, OPENSSL_X509_INFO_SUBJECT,cert));
    printf("OPENSSL_X509_INFO_ISSUER : %s\n", openssl_x509_get_info(env,OPENSSL_X509_INFO_ISSUER ,cert));
    printf("OPENSSL_X509_INFO_VALID_FROM : %s\n", openssl_x509_get_info(env, OPENSSL_X509_INFO_VALID_FROM,cert));
    printf("OPENSSL_X509_INFO_VALID_TO : %s\n", openssl_x509_get_info(env,OPENSSL_X509_INFO_VALID_TO ,cert));
    printf("OPENSSL_X509_INFO_FINGER : %s\n", openssl_x509_get_info(env,OPENSSL_X509_INFO_FINGER ,cert));
    printf("OPENSSL_X509_INFO_SIGNATURE : %s\n", openssl_x509_get_info(env, OPENSSL_X509_INFO_SIGNATURE,cert));
    printf("OPENSSL_X509_INFO_VERSION : %s\n", openssl_x509_get_info(env,OPENSSL_X509_INFO_VERSION ,cert));
    printf("OPENSSL_X509_INFO_PUBKEY : %s\n", openssl_x509_get_info(env,OPENSSL_X509_INFO_PUBKEY ,cert));
    printf("OPENSSL_X509_INFO_PUBKEY_ALGO : %s\n", openssl_x509_get_info(env,OPENSSL_X509_INFO_PUBKEY_ALGO ,cert));
    printf("SERIAL : %u\n", openssl_x509_get_serial(env,cert));
    printf("PUBKEY : %s\n", openssl_x509_get_cert_data(env,cert));

    printf("\n*************END PRINTING********************\n");


}
