summaryrefslogtreecommitdiff
path: root/libdigidoc/DigiDocCert.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdigidoc/DigiDocCert.c')
-rw-r--r--libdigidoc/DigiDocCert.c1981
1 files changed, 1981 insertions, 0 deletions
diff --git a/libdigidoc/DigiDocCert.c b/libdigidoc/DigiDocCert.c
new file mode 100644
index 0000000..3d248bd
--- /dev/null
+++ b/libdigidoc/DigiDocCert.c
@@ -0,0 +1,1981 @@
+//==================================================
+// FILE: DigiDocCert.c
+// PROJECT: Digi Doc
+// DESCRIPTION: Digi Doc functions for certificate handling
+// AUTHOR: Veiko Sinivee, S|E|B IT Partner Estonia
+//==================================================
+// Copyright (C) AS Sertifitseerimiskeskus
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+// GNU Lesser General Public Licence is available at
+// http://www.gnu.org/copyleft/lesser.html
+//==========< HISTORY >=============================
+// 09.09.2004 Veiko Sinivee
+// Creation
+//==================================================
+
+#include <libdigidoc/DigiDocDefs.h>
+#include <libdigidoc/DigiDocCert.h>
+#include <libdigidoc/DigiDocConvert.h>
+#include <libdigidoc/DigiDocLib.h>
+#include <libdigidoc/DigiDocError.h>
+#include <libdigidoc/DigiDocDebug.h>
+#include <libdigidoc/DigiDocMem.h>
+#include <libdigidoc/DigiDocOCSP.h>
+
+#include <openssl/sha.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/ocsp.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rand.h>
+#include <string.h>
+
+//==========< forward declarations >====================
+
+extern int createOCSPRequest(SignedDoc* pSigDoc, OCSP_REQUEST **req,
+ X509 *cert, X509 *pCA, byte* nonce, int nlen);
+extern int signOCSPRequestPKCS12(OCSP_REQUEST *req, const char* filename, const char* passwd);
+
+extern int verifyOCSPResponse(OCSP_RESPONSE* pResp,
+ const X509** caCerts, const char *CApath,
+ const X509* notCert);
+extern int hasUmlauts(const char* str);
+extern int checkNonceAndCertbyOCSP(OCSP_RESPONSE* resp, X509* cert, byte* nonce1, int nonceLen);
+
+
+//==========< utility functions >====================
+
+
+//--------------------------------------------------
+// Reads a certificate file
+// certfile - name of the certificate file
+//--------------------------------------------------
+EXP_OPTION int ReadCertificate(X509 **x509, const char *szCertfile)
+{
+ BIO *in;
+
+ RETURN_IF_NULL_PARAM(szCertfile);
+ if((in = BIO_new_file(szCertfile, "rb")) != NULL) {
+ *x509 = PEM_read_bio_X509(in, NULL, NULL, 0);
+ BIO_free(in);
+ if(!*x509) SET_LAST_ERROR_RETURN_CODE(ERR_NULL_CERT_POINTER);
+ } else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Reads a certificate file
+// certfile - name of the certificate file
+//--------------------------------------------------
+EXP_OPTION int ReadCertificateNoErr(X509 **x509, const char *szCertfile)
+{
+ BIO *in;
+
+ RETURN_IF_NULL_PARAM(szCertfile);
+ if((in = BIO_new_file(szCertfile, "rb")) != NULL) {
+ *x509 = PEM_read_bio_X509(in, NULL, NULL, 0);
+ BIO_free(in);
+ if(!*x509) return ERR_NULL_CERT_POINTER;
+ } else
+ return ERR_FILE_READ;
+ return ERR_OK;
+}
+
+
+//--------------------------------------------------
+// Reads a certificate from pkcs12 conteiner
+//--------------------------------------------------
+EXP_OPTION int ReadCertificateByPKCS12(X509 **x509, const char *pkcs12file, const char *passwd, EVP_PKEY **pkey)
+{
+ BIO *bio;
+ PKCS12 *p12;
+
+ //memset(debugBuf,0,sizeof(debugBuf));
+ RETURN_IF_NULL_PARAM(pkcs12file);
+ bio=BIO_new_file(pkcs12file, "rb");
+ RETURN_IF_NULL(bio);
+ p12 = d2i_PKCS12_bio(bio, NULL);
+ BIO_free(bio);
+ RETURN_IF_NOT(p12, ERR_OCSP_PKCS12_CONTAINER);
+ PKCS12_parse(p12, passwd, pkey, x509, NULL);
+ // Hack: clear PKCS12_parse error "ERROR: 185073780 - error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch
+ ERR_get_error();
+ PKCS12_free(p12);
+
+ RETURN_IF_NOT(*x509, ERR_OCSP_PKCS12_CONTAINER);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Reads certificates serial number
+// szSerial - buffer for serial number
+// nMaxLen - maximum serial number buffer length
+// certfile - name of the certificate file
+//--------------------------------------------------
+EXP_OPTION int GetCertSerialNumber(char *szSerial, int nMaxLen, const char *szCertfile)
+{
+ BIO *in;
+ X509 *x509;
+
+ RETURN_IF_NULL_PARAM(szSerial);
+ RETURN_IF_NULL_PARAM(szCertfile);
+ if((in = BIO_new_file(szCertfile, "rb")) != NULL) {
+ x509 = PEM_read_bio_X509(in, NULL, NULL, 0);
+ BIO_free(in);
+ RETURN_IF_NOT(x509, ERR_NULL_CERT_POINTER);
+ ReadCertSerialNumber(szSerial, nMaxLen, x509);
+ X509_free(x509);
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Reads certificates serial number
+// x509 - certificate object
+//--------------------------------------------------
+int ReadCertSerialNumber(char* szSerial, int nMaxLen, X509 *x509)
+{
+ ASN1_INTEGER *bs = NULL;
+ BIGNUM* bn;
+ char* str;
+ int err = ERR_OK;
+
+ RETURN_IF_NOT(x509, ERR_NULL_CERT_POINTER);
+ RETURN_IF_NOT(szSerial, ERR_NULL_POINTER);
+ bs = X509_get_serialNumber(x509);
+ RETURN_IF_NOT(bs, ERR_NULL_SER_NUM_POINTER);
+ bn = ASN1_INTEGER_to_BN(bs, NULL);
+ RETURN_IF_NOT(bn, ERR_NULL_SER_NUM_POINTER);
+ str = BN_bn2dec(bn);
+ RETURN_IF_NOT(str, ERR_NULL_SER_NUM_POINTER);
+ memset(szSerial, 0, nMaxLen);
+ strncpy(szSerial, str, nMaxLen -1);
+ if(strlen(str) > (unsigned int)nMaxLen) {
+ err = ERR_BUF_LEN;
+ SET_LAST_ERROR(ERR_BUF_LEN);
+ }
+ //AM 28.05.08 bn should be freed too
+ if(bn)
+ BN_free(bn);
+ OPENSSL_free(str);
+ checkErrors();
+ return err;
+}
+
+
+
+//--------------------------------------------------
+// Reads a public key file
+// certfile - name of the certificate file
+//--------------------------------------------------
+int ReadPublicKey(EVP_PKEY **PublicKey, const char *szCertfile)
+{
+ EVP_PKEY *pkey = NULL;
+ X509 *x509 = NULL;
+ int err = ERR_OK;
+
+ RETURN_IF_NULL_PARAM(szCertfile);
+ RETURN_IF_NULL_PARAM(PublicKey); // SVEN - ver 1.92 - crashbug fixed
+ if((err = ReadCertificate(&x509, szCertfile)) == ERR_OK) {
+ pkey = X509_extract_key(x509);
+ X509_free(x509);
+ RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER);
+ *PublicKey = pkey;
+ return ERR_OK;
+ } else
+ SET_LAST_ERROR_RETURN_CODE(err);
+}
+
+
+//--------------------------------------------------
+// Reads a public key file
+// certfile - name of the certificate file
+//--------------------------------------------------
+int GetPublicKey(EVP_PKEY **pubKey, const X509* x509)
+{
+ EVP_PKEY *pkey = NULL;
+
+ RETURN_IF_NULL_PARAM(x509);
+ // SET_LAST_ERROR_RETURN_IF_NOT(x509, ERR_NULL_CERT_POINTER, pkey);
+ // pkey = X509_extract_key((X509*)x509);
+ pkey = X509_get_pubkey((X509*)x509);
+ RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER);
+ *pubKey = pkey;
+ return ERR_OK;
+}
+
+
+//--------------------------------------------------
+// Callback routine for passing key password
+//--------------------------------------------------
+int pemkey_callback(char *buf, int size, int rwflag, void *userdata)
+{
+ RETURN_OBJ_IF_NULL(buf, 0);
+ RETURN_OBJ_IF_NULL(userdata, 0);
+ memset(buf, 0, size);
+ strncpy(buf, (char*)userdata, size);
+ return strlen(buf);
+}
+
+
+//--------------------------------------------------
+// Reads a private key file
+// keyfile - name of the private key file
+// passwd - key password (problems with encrypted passwwords!)
+// format - file format (PEM or DER)
+//--------------------------------------------------
+EXP_OPTION int ReadPrivateKey(EVP_PKEY **privKey, const char *keyfile, const char* passwd, int format)
+{
+ BIO *in;
+ EVP_PKEY *pkey = NULL;
+
+ RETURN_IF_NULL_PARAM(keyfile);
+ RETURN_IF_NULL_PARAM(passwd);
+ if((in = BIO_new_file(keyfile, "rb")) != NULL) {
+ switch(format) {
+ case FILE_FORMAT_ASN1:
+ pkey = d2i_PrivateKey_bio(in,NULL);
+ break;
+ case FILE_FORMAT_PEM:
+ PEM_read_bio_PrivateKey(in, &pkey, pemkey_callback, (void*)passwd);
+ break;
+ }
+ BIO_free(in);
+ RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER);
+ *privKey = pkey;
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Writes a private key file
+// keyfile - name of the private key file
+// passwd - key password (problems with encrypted passwwords!)
+// format - file format (PEM or DER)
+//--------------------------------------------------
+EXP_OPTION int WritePrivateKey(EVP_PKEY *privKey, const char *keyfile, const char* passwd, int format)
+{
+ BIO *out = NULL;
+ EVP_PKEY *pkey = privKey;
+
+ RETURN_IF_NULL_PARAM(privKey);
+ RETURN_IF_NULL_PARAM(keyfile);
+ if((out = BIO_new_file(keyfile, "wb")) != NULL) {
+ switch(format) {
+ case FILE_FORMAT_ASN1:
+ i2d_PUBKEY_bio(out, pkey);
+ break;
+ case FILE_FORMAT_PEM:
+ PEM_write_bio_PrivateKey(out, pkey, (passwd ? EVP_des_ede3_cbc() : NULL),
+ (unsigned char*)passwd, strlen(passwd), pemkey_callback, (void*)passwd) ;
+ break;
+ }
+ BIO_free(out);
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Writes a private key and cert to a PEM file
+// privKey - private key
+// pCert - certificate
+// keyfile - name of the private key file
+// passwd - key password (problems with encrypted passwwords!)
+//--------------------------------------------------
+EXP_OPTION int ddocWriteKeyAndCertPem(EVP_PKEY *privKey, X509* pCert,
+ const char *keyfile, const char* passwd)
+{
+ BIO *out = NULL;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(privKey);
+ RETURN_IF_NULL_PARAM(keyfile);
+ if((out = BIO_new_file(keyfile, "wb")) != NULL) {
+ PEM_write_bio_X509(out, pCert);
+ PEM_write_bio_PrivateKey(out, privKey, (passwd ? EVP_des_ede3_cbc() : NULL),
+ (unsigned char*)passwd, (passwd ? strlen(passwd) : 0), pemkey_callback, (void*)passwd);
+ BIO_free(out);
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE);
+ return ERR_OK;
+}
+
+
+
+//--------------------------------------------------
+// Reads an RSA private key file
+// keyfile - name of the private key file
+// passwd - key password (problems with encrypted passwwords!)
+// format - file format (PEM or DER)
+//--------------------------------------------------
+int ReadRSAPrivateKey(RSA **privKey, const char *keyfile, const char* passwd, int format)
+{
+
+ BIO *in = 0;
+ RSA *pkey = 0;
+
+ RETURN_IF_NULL_PARAM(keyfile);
+ RETURN_IF_NULL_PARAM(passwd);
+ if((in = BIO_new_file(keyfile, "rb")) != 0) {
+ switch(format) {
+ case FILE_FORMAT_ASN1:
+ pkey = d2i_RSAPrivateKey_bio(in,NULL);
+ break;
+ case FILE_FORMAT_PEM:
+ PEM_read_bio_RSAPrivateKey(in, &pkey, pemkey_callback, (void*)passwd);
+ break;
+ }
+ BIO_free(in);
+ RETURN_IF_NOT(pkey, ERR_NULL_KEY_POINTER);
+ *privKey = pkey;
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_READ);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Verifys a certificate by sending an OCSP_REQUEST object
+// to the notary server and checking the response.
+// Uses servers timestamps hash code as nonce value.
+// pCert - certificate to test
+// caCerts - responder CA certs chain
+// notaryCert - notarys cert search
+// proxyHost - proxy servers name
+// proxyPort - proxy servers port
+// notaryURL - notarys URL
+// ppResp - address to return OCSP response. Use NULL if
+// you don't want OCSP response to be returned
+// return 0 for OK, or error code
+//--------------------------------------------------
+EXP_OPTION int verifyCertificateByOCSP(X509* pCert, const X509** caCerts,
+ const X509* notaryCert, char* notaryURL,
+ char* proxyHost, char* proxyPort,
+ const char* pkcs12file, const char* pkcs12paswd,
+ OCSP_RESPONSE **ppResp)
+{
+ return verifyCertificateByOCSPWithIp(pCert, caCerts, notaryCert,
+ notaryURL, proxyHost, proxyPort, pkcs12file, pkcs12paswd, ppResp, 0);
+}
+
+//--------------------------------------------------
+// Verifys a certificate by sending an OCSP_REQUEST object
+// to the notary server and checking the response.
+// Uses servers timestamps hash code as nonce value.
+// pCert - certificate to test
+// caCerts - responder CA certs chain
+// notaryCert - notarys cert search
+// proxyHost - proxy servers name
+// proxyPort - proxy servers port
+// notaryURL - notarys URL
+// ppResp - address to return OCSP response. Use NULL if
+// you don't want OCSP response to be returned
+// return 0 for OK, or error code
+//--------------------------------------------------
+EXP_OPTION int verifyCertificateByOCSPWithIp(X509* pCert, const X509** caCerts,
+ const X509* notaryCert, char* notaryURL,
+ char* proxyHost, char* proxyPort,
+ const char* pkcs12file, const char* pkcs12paswd,
+ OCSP_RESPONSE **ppResp, unsigned long ip)
+
+{
+ OCSP_REQUEST *req = 0;
+ OCSP_RESPONSE *resp = 0;
+ int err = ERR_OK, l1, i;
+ byte nonce1[DIGEST_LEN+2];
+ time_t tNow;
+ X509* pCA = NULL;
+
+ RETURN_IF_NULL(pCert);
+ //RETURN_IF_NULL(notaryCert);
+ //RETURN_IF_NULL(caCerts);
+ RETURN_IF_NULL(notaryURL);
+
+ // mark as not found yet
+ if(ppResp)
+ *ppResp = 0;
+ time(&tNow);
+ l1 = sizeof(nonce1);
+ calculateDigest((const byte*)&tNow, sizeof(tNow), DIGEST_SHA1, nonce1, &l1);
+ // find lowest CA
+ for(i = 0; (caCerts != NULL) && (caCerts[i] != NULL); i++)
+ pCA = (X509*)caCerts[i];
+ err = createOCSPRequest(NULL, &req, pCert, pCA, nonce1, l1);
+ if(err == ERR_OK && pkcs12file)
+ err = signOCSPRequestPKCS12(req, pkcs12file, pkcs12paswd);
+ if(err == ERR_OK) {
+ //WriteOCSPRequest("test1.req", req);
+ err = sendOCSPRequest(&resp, req, notaryURL, proxyHost, proxyPort, ip);
+ //WriteOCSPResponse("test1.resp", resp);
+ //printf("sendOCSPRequest returned %d\n", err);
+ if(err == ERR_OK) {
+ if(caCerts && notaryCert) {
+ ddocDebug(1, "verifyCertificateByOCSPWithIp", "Verify OCSP resp with known CA certs");
+ // check the response signature
+ err = verifyOCSPResponse(resp, (const X509**)caCerts, NULL, notaryCert);
+ }
+ if(err == ERR_OK)
+ err = checkNonceAndCertbyOCSP(resp, pCert, nonce1, l1);
+ //WriteOCSPResponse("test1.resp", resp);
+ }
+ }
+ // free OCSP request, if allocated;
+ if (req)
+ OCSP_REQUEST_free(req);
+ // return OCSP response if required
+ if(ppResp)
+ *ppResp = resp;
+ else
+ OCSP_RESPONSE_free(resp);
+ return err;
+}
+
+//============================================================
+// Decodes binary (DER) cert data and returns a cert object
+// certData - binary (DER) cert data
+// certLen - cert data length
+//============================================================
+EXP_OPTION int ddocDecodeX509Data(X509 **ppX509, const byte* certData, int certLen)
+{
+ BIO* b1 = NULL;
+
+ // check input params
+ RETURN_IF_NULL_PARAM(certData);
+ RETURN_IF_NULL_PARAM(ppX509);
+ // mark as not read yet
+ *ppX509 = 0;
+ // create memory BIO on it
+ b1 = BIO_new_mem_buf((void*)certData, certLen);
+ RETURN_IF_NOT(b1, ERR_CERT_INVALID);
+ *ppX509 = d2i_X509_bio(b1, NULL);
+ ddocDebug(4, "ddocDecodeX509Data", "Decoding %d bytes DER data - cert %s", certLen, (*ppX509 ? "OK" : "ERROR"));
+ // cleanup
+ BIO_free(b1);
+ RETURN_IF_NOT(*ppX509, ERR_CERT_INVALID);
+ return ERR_OK;
+}
+
+//============================================================
+// Decodes base64 (PEM) cert data and returns a cert object
+// certData - base64 (PEM) cert data
+// certLen - cert data length
+//============================================================
+EXP_OPTION int ddocDecodeX509PEMData(X509 **ppX509, const char* certData, int certLen)
+{
+ byte* p1 = 0;
+ int l1 = 0, err = ERR_OK;
+
+ // check input params
+ RETURN_IF_NULL_PARAM(certData);
+ RETURN_IF_NULL_PARAM(ppX509);
+ // mark as not read yet
+ *ppX509 = 0;
+ // allocate memory for decoding
+ l1 = certLen; // should be enough as it shrinks
+ p1 = (byte*)malloc(l1);
+ RETURN_IF_BAD_ALLOC(p1);
+ memset(p1, 0, l1);
+ // decode base64 data
+ decode((const byte*)certData, certLen, p1, &l1);
+ // decode cert
+ err = ddocDecodeX509Data(ppX509, p1, l1);
+ ddocDebug(4, "ddocDecodeX509PEMData",
+ "Decoding %d bytes PEM data - cert %s", certLen, (*ppX509 ? "OK" : "ERROR"));
+ // cleanup
+ if(p1)
+ free(p1);
+ return err;
+}
+
+//============================================================
+// Checks if the cert is valid (between begin and end date)
+// cert - certificate object
+// tDate - date to check the cert
+//============================================================
+EXP_OPTION int isCertValid(X509* cert, time_t tDate)
+{
+ int err = ERR_OK;
+ ASN1_TIME *tm = 0;
+ time_t tStart, tEnd;
+
+ RETURN_IF_NULL_PARAM(cert);
+ tm = X509_get_notBefore(cert);
+ RETURN_IF_NULL(tm);
+ asn1time2time_t_local(tm, &tStart);
+ tm = X509_get_notAfter(cert);
+ RETURN_IF_NULL(tm);
+ asn1time2time_t_local(tm, &tEnd);
+ if(tDate < tStart || tDate > tEnd) {
+ err = ERR_CERT_INVALID;
+ SET_LAST_ERROR(err);
+ }
+ return err;
+}
+
+//============================================================
+// Retrieves the certificates first validity time as tim_t in GMT zone
+// pCert - certificate object
+// returns certificates first validity time as tim_t in GMT zone
+//============================================================
+EXP_OPTION time_t getCertNotBeforeTimeT(X509* pCert)
+{
+ time_t t1 = 0;
+ ASN1_TIME *tm = 0;
+
+ if(pCert) {
+ tm = X509_get_notBefore(pCert);
+ if(tm)
+ asn1time2time_t_local(tm, &t1);
+ }
+ return t1;
+}
+
+//============================================================
+// Retrieves the certificates last validity time as tim_t in GMT zone
+// pCert - certificate object
+// returns certificates last validity time as tim_t in GMT zone
+//============================================================
+EXP_OPTION time_t getCertNotAfterTimeT(X509* pCert)
+{
+ time_t t1 = 0;
+ ASN1_TIME *tm = 0;
+
+ if(pCert) {
+ tm = X509_get_notAfter(pCert);
+ if(tm)
+ asn1time2time_t_local(tm, &t1);
+ }
+ return t1;
+}
+
+//============================================================
+// Checks if the cert has been signed by this CA-cert
+// cert - certificate object
+// cafile - CA cert file
+//============================================================
+EXP_OPTION int isCertSignedBy(X509* cert, const char* cafile)
+{
+ int err = ERR_OK;
+ EVP_PKEY* pubkey = NULL; // SVEN - ver 1.92 - crashbug fixed
+
+ (void)ReadPublicKey(&pubkey, cafile);
+ RETURN_IF_NOT(pubkey, ERR_PUBKEY_READ);
+
+ err = X509_verify(cert, pubkey);
+ if(err == ERR_LIB_NONE)
+ err = ERR_OK;
+ else {
+ err = ERR_CERT_ISSUER;
+ SET_LAST_ERROR(err);
+ }
+ // checkErrors();
+ //332:error:0D0890A1:lib(13):func(137):reason(161):.\crypto\asn1\a_verify.c:141:
+ EVP_PKEY_free(pubkey);
+ return err;
+}
+
+//============================================================
+// Writes cert to file without the usual PEM headers
+// bout - output file
+// cert - certificate object
+// returns error code
+//============================================================
+int writeCertToXMLFile(BIO* bout, X509* cert)
+{
+ int l1, l2;
+ char *p1, *p2;
+
+ RETURN_IF_NULL_PARAM(bout);
+ RETURN_IF_NULL_PARAM(cert);
+ l1 = i2d_X509(cert, NULL);
+ p1 = (char*)malloc(l1+10);
+ RETURN_IF_BAD_ALLOC(p1);
+ p2 = p1;
+ i2d_X509(cert, (unsigned char**)&p2);
+ l2 = l1 * 2;
+ p2 = (char*)malloc(l2);
+ if (p2 == NULL) {
+ free(p1);
+ RETURN_IF_BAD_ALLOC(p2);
+ }
+ encode((const byte*)p1, l1, (byte*)p2, &l2);
+ BIO_puts(bout, p2);
+ free(p2);
+ free(p1);
+ return ERR_OK;
+}
+
+//============================================================
+// Converts the certificate to PEM form with or without headers
+// cert - certificate object
+// bHeaders - 1= with headers, 0=no headers
+// buf - output buffer newly allocated
+// returns error code
+//============================================================
+EXP_OPTION int getCertPEM(X509* cert, int bHeaders, char** buf)
+{
+ int l1, l2;
+ char *p1, *p2;
+
+ RETURN_IF_NULL_PARAM(buf);
+ RETURN_IF_NULL_PARAM(cert);
+ l1 = i2d_X509(cert, NULL);
+ p1 = (char*)malloc(l1+10);
+ RETURN_IF_BAD_ALLOC(p1);
+ p2 = p1;
+ i2d_X509(cert, (unsigned char**)&p2);
+ l2 = l1 * 2 + 200;
+ *buf = (char*)malloc(l2);
+ if(*buf == NULL) {
+ free(p1);
+ RETURN_IF_BAD_ALLOC(*buf);
+ }
+ memset(*buf, 0, l2);
+ if(bHeaders)
+ strncpy(*buf, "-----BEGIN CERTIFICATE-----\n", l2);
+ encode((const byte*)p1, l1, (byte*)strchr(*buf, 0), &l2);
+ l2 = l1 * 2 + 200 - strlen(*buf);
+ if(bHeaders)
+ strncat(*buf, "\n-----END CERTIFICATE-----", l2);
+ free(p1);
+ return ERR_OK;
+}
+
+
+
+//--------------------------------------------------
+// Returns the certificates validity first date
+// cert - certificate data
+// timestamp - timestamp buffer
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int getCertNotBefore(const SignedDoc* pSigDoc, X509* cert, char* timestamp, int len)
+{
+ int err = ERR_OK;
+ ASN1_TIME *tm = 0;
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(timestamp);
+
+ tm = X509_get_notBefore(cert);
+ RETURN_IF_NULL(tm);
+ err = asn1time2strYear(pSigDoc, tm, timestamp, 1900, len);
+
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Returns the certificates validity last date
+// cert - certificate data
+// timestamp - timestamp buffer
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int getCertNotAfter(const SignedDoc* pSigDoc, X509* cert, char* timestamp, int len)
+{
+ int err = ERR_OK;
+ ASN1_TIME *tm = 0;
+
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(timestamp);
+
+ tm = X509_get_notAfter(cert);
+ RETURN_IF_NULL(tm);
+ err = asn1time2strYear(pSigDoc, tm, timestamp, 1900, len);
+
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+
+//--------------------------------------------------
+// Saves the certificate in a file
+// cert - certificate data
+// szFileName - destination filename
+// nFormat - cert format
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int saveCert(X509* cert, const char* szFileName, int nFormat)
+{
+ // int err = ERR_OK;
+ BIO* b;
+
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(szFileName);
+
+ if((b = BIO_new_file(szFileName, "w")) != NULL) {
+ if(nFormat == FILE_FORMAT_PEM)
+ PEM_write_bio_X509(b, cert);
+ if(nFormat == FILE_FORMAT_ASN1)
+ i2d_X509_bio(b, cert);
+ BIO_free(b);
+ } else
+ SET_LAST_ERROR_RETURN_CODE(ERR_FILE_WRITE);
+ return ERR_OK;
+}
+
+// new functions for Win client
+
+EXP_OPTION void* decodeCert(const char* pemData)
+{
+ BIO* b1;
+ X509* x509;
+ int l1;
+
+ RETURN_OBJ_IF_NULL(pemData, NULL);
+ l1 = strlen(pemData);
+ b1 = BIO_new_mem_buf((void*)pemData, l1);
+ RETURN_OBJ_IF_NULL(b1, 0);
+ x509 = PEM_read_bio_X509(b1, NULL, NULL, 0);
+ if(!x509)
+ SET_LAST_ERROR(ERR_CERT_READ);
+ // checkErrors();
+ BIO_free(b1);
+ return x509;
+}
+
+
+
+
+//===========================================================
+// Encodes certificate from X509 to binary
+//===========================================================
+EXP_OPTION void encodeCert(const X509* x509, char * encodedCert, int* encodedCertLen)
+{
+ if(x509==NULL){
+ *encodedCertLen = 0;
+ return;
+ }
+ if(encodedCert==NULL){
+ *encodedCertLen = 0;
+ return;
+ }
+ *encodedCertLen = i2d_X509((X509*)x509, NULL);
+ i2d_X509((X509*)x509, (unsigned char**)&encodedCert);
+}
+
+//============================================================
+// Checks if the cert has been signed by this CA-cert
+// cert - certificate object
+// cafile - CA cert file
+//============================================================
+EXP_OPTION int isCertSignedByCERT(const X509* cert, const X509* caCert)
+{
+ int err = ERR_OK;
+ EVP_PKEY* pubkey;
+ DigiDocMemBuf mbuf1, mbuf2, mbuf3;
+
+ mbuf1.pMem = 0;
+ mbuf1.nLen = 0;
+ mbuf2.pMem = 0;
+ mbuf2.nLen = 0;
+ mbuf3.pMem = 0;
+ mbuf3.nLen = 0;
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(caCert);
+ err = ddocCertGetSubjectCN((X509*)caCert, &mbuf1);
+ err = ddocCertGetSubjectCN((X509*)cert, &mbuf2);
+ err = ddocCertGetIssuerCN((X509*)cert, &mbuf3);
+ ddocDebug(3, "isCertSignedByCERT",
+ "Issuer: %s, Subject: %s, Subjects-issuer: %s",
+ (const char*)mbuf1.pMem, (const char*)mbuf2.pMem,
+ (const char*)mbuf3.pMem);
+ ddocMemBuf_free(&mbuf1);
+ ddocMemBuf_free(&mbuf2);
+ ddocMemBuf_free(&mbuf3);
+ err = GetPublicKey(&pubkey, caCert);
+ if(err == ERR_OK) {
+ err = X509_verify((X509*)cert, pubkey);
+ ddocDebug(3, "isCertSignedByCERT", "verify: %d", err);
+ if(err == ERR_LIB_NONE)
+ err = ERR_OK;
+ else
+ err = ERR_CERT_ISSUER;
+ if(err != ERR_OK) {
+ ddocDebug(3, "isCertSignedByCERT", "Cert not issued by ca verify: %d", err);
+ checkErrors();
+ }
+ EVP_PKEY_free(pubkey);
+ }
+ else
+ err = ERR_PUBKEY_READ;
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+
+/*int utc2latin1(const char* data, int len, char* dest)
+{
+ int i, j;
+
+ for(i = j = 0; i < len; i++) {
+ if(data[i]) {
+ dest[j] = data[i];
+ j++;
+ }
+ }
+ dest[j] = 0;
+ return j;
+ }*/
+
+//--------------------------------------------------------
+// Checks if the desired key-usage bit is set on a given cert
+// pCert - certificate
+// nBit - flag index
+// return 1 if bit is set
+//--------------------------------------------------------
+EXP_OPTION int ddocCertCheckKeyUsage(X509 *pCert, int nBit)
+{
+ int crit = -1, extIdx = -1;
+ ASN1_BIT_STRING *keyUsage;
+
+ if(pCert && nBit >= 0 && nBit < 8) {
+ keyUsage = (ASN1_BIT_STRING *)X509_get_ext_d2i(pCert, NID_key_usage, &crit, &extIdx);
+ if(keyUsage) {
+ ddocDebug(3, "ddocCertCheckKeyUsage", "Bit: %d set: %d", nBit, ASN1_BIT_STRING_get_bit(keyUsage, nBit));
+ return ASN1_BIT_STRING_get_bit(keyUsage, nBit);
+ }
+ }
+ return 0;
+}
+
+
+//--------------------------------------------------------
+// Finds and copies a substring from source string that is
+// prefixed by szLabel and terminated by szTerminator
+// szSrc - source string
+// szLabel - prefix of searched string
+// szTerminator - terminator string
+// szDest - found string. Caller must free this mem.
+//--------------------------------------------------------
+int ddocCertCopySubstring(const char* szSrc, const char* szLabel, const char* szTerminator, char** szDest)
+{
+ ptrdiff_t l;
+ char *p1, *p2;
+
+ RETURN_IF_NULL_PARAM(szSrc);
+ RETURN_IF_NULL_PARAM(szLabel);
+ RETURN_IF_NULL_PARAM(szTerminator);
+ RETURN_IF_NULL_PARAM(szDest);
+ *szDest = 0; // mark as empty
+ p1 = strstr(szSrc, szLabel);
+ if(p1) {
+ p1 += strlen(szLabel);
+ p2 = strstr(p1, szTerminator);
+ if(!p2)
+ p2 = strchr(p1, 0);
+ if(p2 && p2 > p1) {
+ l = p2 - p1 + 1;
+ *szDest = (char*)malloc(l);
+ if(*szDest) {
+ memset(*szDest, 0, l);
+ strncpy(*szDest, p1, p2 - p1);
+ }
+ }
+ }
+ return ERR_OK;
+}
+
+EXP_OPTION int readCertPoliciesFromOU(X509* pX509, PolicyIdentifier** pPolicies, int* nPols)
+{
+ DigiDocMemBuf mbuf1;
+ int err = ERR_OK;
+ char *pUri, *pDesc, *pOid;
+ PolicyIdentifier *pTmp;
+
+ RETURN_IF_NULL_PARAM(pX509);
+ RETURN_IF_NULL_PARAM(pPolicies);
+ RETURN_IF_NULL_PARAM(nPols);
+ mbuf1.nLen = 0;
+ mbuf1.pMem = 0;
+ pUri = pDesc = pOid = 0;
+ err = ddocCertGetSubjectOrganizationUnit(pX509, &mbuf1);
+ if(!err && mbuf1.pMem) {
+ err = ddocCertCopySubstring((const char*)mbuf1.pMem, "SP Desc:", "\n", &pDesc);
+ if(!err) {
+ err = ddocCertCopySubstring((const char*)mbuf1.pMem, "SP URI:", "\n", &pUri);
+ if(!err) {
+ err = ddocCertCopySubstring((const char*)mbuf1.pMem, "SP OID:", "\n", &pOid);
+ if(!err && (pDesc || pUri || pOid)) {
+ pTmp = (PolicyIdentifier*)realloc(*pPolicies, sizeof(PolicyIdentifier) * ((*nPols) + 1));
+ if(pTmp) {
+ *pPolicies = pTmp;
+ pTmp = (*pPolicies) + (*nPols);
+ *nPols = (*nPols) + 1;
+ pTmp->szOID = (pOid ? strdup((const char*)pOid) : 0);
+ pTmp->szUserNotice = (pDesc ? strdup((const char*)pDesc) : 0);
+ pTmp->szCPS = (pUri ? strdup((const char*)pUri) : 0);
+ }
+ }
+ free(pOid);
+ }
+ free(pUri);
+ }
+ free(pDesc);
+ }
+ ddocMemBuf_free(&mbuf1);
+ return err;
+}
+
+//--------------------------------------------------
+// Reads certificates PolicyIdentifiers and returns
+// them in a newly allocated structure. Caller must
+// free this, regardless of function return status.
+// pX509 - certificate
+// pPolicies - returned PolicyIdentifiers array
+// nPols - number of returned policies
+//--------------------------------------------------
+EXP_OPTION int readCertPolicies(X509* pX509, PolicyIdentifier** pPolicies, int* nPols)
+{
+ char buf[512], *p;
+ int err = 0, i, k, j, pos, l;
+ PolicyIdentifier *pPol, *pTmp;
+
+ RETURN_IF_NULL_PARAM(pX509);
+ RETURN_IF_NULL_PARAM(pPolicies);
+ RETURN_IF_NULL_PARAM(nPols);
+ *pPolicies = NULL;
+ *nPols = 0;
+ // try read from certificates OU first
+ if(!err)
+ err = readCertPoliciesFromOU(pX509, pPolicies, nPols);
+ // read from usual place
+ pos = X509_get_ext_by_NID(pX509, NID_certificate_policies, -1);
+ if(pos >= 0) {
+ POLICYINFO *pol;
+ STACK_OF(POLICYINFO)* pPols;
+ STACK_OF(POLICYQUALINFO)* pQuals;
+ POLICYQUALINFO* pQual;
+ X509_EXTENSION* pExt = X509_get_ext(pX509, pos);
+ // X509V3_EXT_METHOD *method = X509V3_EXT_get(pExt);
+ //pPols = (STACK*)X509V3_EXT_d2i(pExt);
+ pPols = X509V3_EXT_d2i(pExt);
+ for(i = 0; i < sk_POLICYINFO_num(pPols); i++) {
+ pol = sk_POLICYINFO_value(pPols, i);
+ if(*pPolicies && *nPols) {
+ pTmp = (PolicyIdentifier*)realloc(*pPolicies, sizeof(PolicyIdentifier) * ((*nPols) + 1));
+ if (pTmp != NULL) {
+ *pPolicies = pTmp;
+ *nPols = (*nPols) + 1;
+ pPol = (*pPolicies) + ((*nPols) - 1);
+ } else
+ SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC);
+ } else {
+ pTmp = (PolicyIdentifier*)malloc(sizeof(PolicyIdentifier));
+ if (pTmp != NULL) {
+ *pPolicies = pTmp;
+ pPol = *pPolicies;
+ *nPols = 1;
+ } else
+ SET_LAST_ERROR_RETURN_CODE(ERR_BAD_ALLOC);
+ }
+ pPol->szCPS = pPol->szOID = pPol->szUserNotice = NULL;
+ // check
+ i2t_ASN1_OBJECT(buf, sizeof(buf), pol->policyid);
+ pPol->szOID = strdup(buf);
+ pQuals = pol->qualifiers;
+ for(k = 0; k < sk_POLICYQUALINFO_num(pQuals); k++) {
+ pQual = sk_POLICYQUALINFO_value(pQuals, k);
+ switch(OBJ_obj2nid(pQual->pqualid)) {
+ case NID_id_qt_cps:
+ pPol->szCPS = strdup((const char*)pQual->d.cpsuri->data);
+ // if strdup fails, szCPS will be NULL
+ break;
+ case NID_id_qt_unotice:
+ ddocDebug(4, "readCertPolicies", "Exptext: %d - \'%s\'",
+ pQual->d.usernotice->exptext->length, pQual->d.usernotice->exptext->data);
+ if(pQual->d.usernotice->exptext) {
+ if(pQual->d.usernotice->exptext->type == V_ASN1_UTF8STRING) {
+ pPol->szUserNotice = strdup((const char*)pQual->d.usernotice->exptext->data);
+ } else {
+ p = 0;
+ l = ASN1_STRING_to_UTF8((unsigned char**)&p, pQual->d.usernotice->exptext);
+ pPol->szUserNotice = strdup(p);
+ OPENSSL_free(p);
+ }
+ /*if(pQual->d.usernotice->exptext->data[0]) {
+ pPol->szUserNotice = strdup((const char*)pQual->d.usernotice->exptext->data);
+ } else {
+ utc2latin1((const char*)pQual->d.usernotice->exptext->data,
+ pQual->d.usernotice->exptext->length, buf);
+ pPol->szUserNotice = strdup(buf);
+ // if strdup fails, szUserNotice will be NULL
+ }*/
+ }
+ if(pQual->d.usernotice->noticeref) {
+ NOTICEREF *ref = pQual->d.usernotice->noticeref;
+ p = 0;
+ l = 0;
+ // calculate the memory required
+ l += strlen((const char*)ref->organization->data) + 1;
+ for(j = 0; j < sk_ASN1_INTEGER_num(ref->noticenos); j++) {
+ ASN1_INTEGER *num;
+ char *tmp;
+ num = sk_ASN1_INTEGER_value(ref->noticenos, j);
+ tmp = i2s_ASN1_INTEGER(NULL, num);
+ l += strlen(tmp) + 2;
+ OPENSSL_free(tmp);
+ }
+ // now alloc mem and copy data
+ l += 10; // alloc with a little extra
+ p = (char*)malloc(l);
+ if(p) {
+ memset(p, 0, l);
+ strncpy(p, (const char*)ref->organization->data, l);
+ strncat(p, " ", l - strlen(p));
+ for(j = 0; j < sk_ASN1_INTEGER_num(ref->noticenos); j++) {
+ ASN1_INTEGER *num;
+ char *tmp;
+ num = sk_ASN1_INTEGER_value(ref->noticenos, j);
+ if (j) strncat(p, ", ", l - strlen(p));
+ tmp = i2s_ASN1_INTEGER(NULL, num);
+ strncat(buf, tmp, sizeof(buf) - strlen(buf));
+ OPENSSL_free(tmp);
+ }
+ pPol->szUserNotice = p;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ sk_POLICYINFO_pop_free(pPols, POLICYINFO_free);
+ }
+ ddocDebug(4, "readCertPolicies", "End");
+ return err;
+}
+
+
+
+//--------------------------------------------------
+// Frees policy identifiers array
+// pPolicies - PolicyIdentifiers array
+// nPols - number of policies
+//--------------------------------------------------
+EXP_OPTION void PolicyIdentifiers_free(PolicyIdentifier* pPolicies, int nPols)
+{
+ int i;
+ for(i = 0; i < nPols; i++) {
+ free(pPolicies[i].szOID);
+ free(pPolicies[i].szCPS);
+ free(pPolicies[i].szUserNotice);
+ //free(pPolicies[i]);
+ }
+ free(pPolicies);
+}
+
+//--------------------------------------------------
+// Reads certificates extension value
+// pCert - certificate
+// pMemBuf - memory buffer to return data
+// nExt - extension code
+//--------------------------------------------------
+EXP_OPTION int readCertExtData(X509* pCert, DigiDocMemBuf* pMemBuf, int nExt, int nOff)
+{
+ int err = ERR_OK, pos;
+ X509_EXTENSION* pExt;
+/* char buf1[300];
+ int l1;*/
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+ pos = X509_get_ext_by_NID(pCert, nExt, -1);
+ if(pos >= 0) {
+ pExt = X509_get_ext(pCert, pos);
+ if(pExt && pExt->value && pExt->value->data) {
+ /* memset(buf1, 0, sizeof(buf1));
+ l1 = sizeof(buf1);
+ bin2hex(pExt->value->data, pExt->value->length, buf1, &l1);
+ ddocDebug(3, "readCertExtData", "Ext: %d len: %d data: %s", nExt, pExt->value->length, buf1);*/
+ if(pExt->value->length > 20 && nOff)
+ //ddocMemAssignData(pMemBuf, ((char*)pExt->value->data) + (pExt->value->length - 20), 20);
+ ddocMemAssignData(pMemBuf, ((char*)pExt->value->data) + nOff, 20);
+ else
+ ddocMemAssignData(pMemBuf, ((char*)pExt->value->data), pExt->value->length);
+ }
+ }
+ return err;
+}
+
+//--------------------------------------------------
+// Reads certificates authority key identifier
+// pCert - certificate
+// pMemBuf - memory buffer to return data
+//--------------------------------------------------
+EXP_OPTION int readAuthorityKeyIdentifier(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ int err = ERR_OK;
+ int crit = 0, l1;
+ char *p = 0;
+
+ AUTHORITY_KEYID *pAkid = X509_get_ext_d2i(pCert, NID_authority_key_identifier, &crit, NULL);
+ if(pAkid) {
+ l1 = i2d_ASN1_OCTET_STRING(pAkid->keyid, (unsigned char **)&p);
+ if(l1 > 20)
+ ddocMemAssignData(pMemBuf, p + (l1 - 20), 20);
+ else
+ ddocMemAssignData(pMemBuf, (char*)p, l1);
+ OPENSSL_free(p);
+ AUTHORITY_KEYID_free(pAkid);
+ }
+ return err;
+ //return readCertExtData(pCert, pMemBuf, NID_authority_key_identifier, 5);
+}
+
+//--------------------------------------------------
+// Reads certificates subject key identifier
+// pCert - certificate
+// pMemBuf - memory buffer to return data
+//--------------------------------------------------
+EXP_OPTION int readSubjectKeyIdentifier(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return readCertExtData(pCert, pMemBuf, NID_subject_key_identifier, 2);
+}
+
+
+//--------------------------------------------------
+// Checks if this is a company CPS policy
+// pPolicy - PolicyIdentifier to be checked
+//--------------------------------------------------
+EXP_OPTION int isCompanyCPSPolicy(PolicyIdentifier* pPolicy)
+{
+ //return (strstr(pPolicy->szCPS, "1.3.6.4.1.10015.7") != NULL);
+ if(pPolicy && pPolicy->szCPS)
+ return (strstr(pPolicy->szCPS, "1.3.6.1.4.1.10015.5") != NULL);
+ else
+ return 0;
+}
+
+
+//--------------------------------------------------
+// Returns the certificates sha1 hash.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertGetDigest(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ int err = ERR_OK;
+ unsigned int l1;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+ l1 = 30;
+ err = ddocMemSetLength(pMemBuf, l1);
+ X509_digest(pCert, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1);
+ pMemBuf->nLen = l1;
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates public key sha1 hash.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertGetPubkeyDigest(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ int err = ERR_OK;
+ unsigned int l1;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+ l1 = 30;
+ err = ddocMemSetLength(pMemBuf, l1);
+ X509_pubkey_digest(pCert, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1);
+ pMemBuf->nLen = l1;
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates subject name sha1 hash.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertGetSubjectNameDigest(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ int err = ERR_OK;
+ unsigned int l1;
+ X509_NAME *iname;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+ l1 = 30;
+ err = ddocMemSetLength(pMemBuf, l1);
+ iname = X509_get_subject_name(pCert);
+ X509_NAME_digest(iname, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1);
+ pMemBuf->nLen = l1;
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates issuer name sha1 hash.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertGetIssuerNameDigest(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ int err = ERR_OK;
+ unsigned int l1;
+ X509_NAME *iname;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+ l1 = 30;
+ err = ddocMemSetLength(pMemBuf, l1);
+ iname = X509_get_issuer_name(pCert);
+ X509_NAME_digest(iname, EVP_sha1(), (unsigned char*)pMemBuf->pMem, &l1);
+ pMemBuf->nLen = l1;
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates DN. Internal function.
+// Do not call directly, subject to change
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// bIssuer - 1=issuer, 0=subject
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertGetDN(X509* pCert, DigiDocMemBuf* pMemBuf, int bIssuer)
+{
+ int err = ERR_OK;
+ X509_NAME *pName = 0;
+ X509_NAME_ENTRY *pNe = 0;
+ int i, n, l, t, b = 0;
+ const char *s;
+ unsigned char* p;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+
+ // initialize
+ if(pMemBuf->pMem)
+ err = ddocMemBuf_free(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+
+ // iterate over name entries
+ if(bIssuer)
+ pName = X509_get_issuer_name(pCert);
+ else
+ pName = X509_get_subject_name(pCert);
+ RETURN_IF_NULL(pName)
+ for(i = 0; (err == ERR_OK) && (i < sk_X509_NAME_ENTRY_num(pName->entries)); i++) {
+ pNe = sk_X509_NAME_ENTRY_value(pName->entries, i);
+ n = OBJ_obj2nid(pNe->object);
+ s = OBJ_nid2sn(n);
+ t = pNe->value->type;
+ // mostly we find here:
+ // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING
+ // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8
+ // handle only the enry types we know
+ if(n != NID_undef && s != NULL) {
+ // convert to UTF8 only
+ p = 0;
+ if(t == V_ASN1_UTF8STRING) {
+ p = pNe->value->data;
+ l = pNe->value->length;
+ } else
+ l = ASN1_STRING_to_UTF8(&p, pNe->value);
+ ddocDebug(5, "ddocCertGetDN",
+ "NameEntry nid: %d type: %d len: %d item: %s value: \'%s\'",
+ n, t, l, s, (p ? (const char*)p : "NULL"));
+ // append separator if necessary
+ if(b)
+ err = ddocMemAppendData(pMemBuf, ",", -1); // RFC2253 must use ,
+ else
+ b = 1;
+ // print the entry
+ err = ddocMemAppendData(pMemBuf, s, -1);
+ err = ddocMemAppendData(pMemBuf, "=", -1);
+ err = ddocMemAppendData(pMemBuf, (const char*)p, l);
+ // cleanup
+ if(p && t != V_ASN1_UTF8STRING)
+ OPENSSL_free(p);
+ }
+ ddocDebug(5, "ddocCertGetDN", "Subject: \'%s\' len: %d",
+ (const char*)pMemBuf->pMem, pMemBuf->nLen);
+ } // for
+
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates issuer name.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetIssuerDN(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDN(pCert, pMemBuf, 1);
+}
+
+
+//--------------------------------------------------
+// Returns the certificates subject name.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectDN(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDN(pCert, pMemBuf, 0);
+}
+
+//--------------------------------------------------
+// Returns the certificates DN.
+// Do not call directly, subject to change
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// bIssuer - 1=issuer, 0=subject
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetDNFromName(X509_NAME* pName, DigiDocMemBuf* pMemBuf)
+{
+ int err = ERR_OK;
+ X509_NAME_ENTRY *pNe = 0;
+ int i, n, l, t, b = 0;
+ const char *s;
+ unsigned char* p;
+
+ RETURN_IF_NULL_PARAM(pMemBuf);
+
+ // initialize
+ if(pMemBuf->pMem)
+ err = ddocMemBuf_free(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+
+ for(i = 0; (err == ERR_OK) && (i < sk_X509_NAME_ENTRY_num(pName->entries)); i++) {
+ pNe = sk_X509_NAME_ENTRY_value(pName->entries, i);
+ n = OBJ_obj2nid(pNe->object);
+ s = OBJ_nid2sn(n);
+ t = pNe->value->type;
+ // mostly we find here:
+ // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING
+ // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8
+ // handle only the enry types we know
+ if(n != NID_undef && s != NULL) {
+ // convert to UTF8 only
+ p = 0;
+ if(t == V_ASN1_UTF8STRING) {
+ p = pNe->value->data;
+ l = pNe->value->length;
+ } else
+ l = ASN1_STRING_to_UTF8(&p, pNe->value);
+ ddocDebug(5, "ddocCertGetDN",
+ "NameEntry nid: %d type: %d len: %d item: %s value: \'%s\'",
+ n, t, l, s, (p ? (const char*)p : "NULL"));
+ // append separator if necessary
+ if(b)
+ err = ddocMemAppendData(pMemBuf, "/", -1);
+ else
+ b = 1;
+ // print the entry
+ err = ddocMemAppendData(pMemBuf, s, -1);
+ err = ddocMemAppendData(pMemBuf, "=", -1);
+ err = ddocMemAppendData(pMemBuf, (const char*)p, l);
+ // cleanup
+ if(p && t != V_ASN1_UTF8STRING)
+ OPENSSL_free(p);
+ }
+ ddocDebug(5, "ddocCertGetDN", "Subject: \'%s\' len: %d",
+ (const char*)pMemBuf->pMem, pMemBuf->nLen);
+ } // for
+
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates subject name and returns
+// the desired item from it.
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// nNid - cert name part NID
+// bIssuer - 1=from issuer DN, 0=from subject DN
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocCertGetDNPart(X509* pCert, DigiDocMemBuf* pMemBuf, int nNid, int bIssuer)
+{
+ int err = ERR_OK;
+ X509_NAME *pName = 0;
+ X509_NAME_ENTRY *pNe = 0;
+ int i, n, l, t, m, j;
+ const char *s;
+ unsigned char* p = 0;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+
+ // initialize
+ if(pMemBuf->pMem)
+ err = ddocMemBuf_free(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+
+ // iterate over name entries
+ if(bIssuer)
+ pName = X509_get_issuer_name(pCert);
+ else
+ pName = X509_get_subject_name(pCert);
+ for(i = 0; (err == ERR_OK) && (i < sk_X509_NAME_ENTRY_num(pName->entries)); i++) {
+ pNe = sk_X509_NAME_ENTRY_value(pName->entries, i);
+ n = OBJ_obj2nid(pNe->object);
+ s = OBJ_nid2sn(n);
+ t = pNe->value->type;
+ // mostly we find here:
+ // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING
+ // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8
+ // handle only the enry types we know
+ if(n == nNid && s != NULL) {
+ // convert to UTF8 only
+ if(t == V_ASN1_UTF8STRING) {
+ p = pNe->value->data;
+ l = pNe->value->length;
+ } else
+ l = ASN1_STRING_to_UTF8(&p, pNe->value);
+ // test for 0x0
+ m = (p ? strlen(p) : 0);
+ if(m < l && p) {
+ for(j = 0; j < l; j++)
+ if(p[j] == 0)
+ p[j] = ' ';
+ }
+ ddocDebug(5, "ddocCertGetDNPart",
+ "NameEntry type: %d len: %d item: %s value: \'%s\'",
+ t, l, s, (p ? (const char*)p : "NULL"));
+ if(pMemBuf->pMem && strlen(pMemBuf->pMem))
+ ddocMemAppendData(pMemBuf, "\n", -1);
+ err = ddocMemAppendData(pMemBuf, (const char*)p, l);
+ // cleanup
+ if(p && t != V_ASN1_UTF8STRING)
+ OPENSSL_free(p);
+ // continue search
+ }
+ } // for
+
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates subject CN
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectCN(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_commonName, 0);
+}
+
+
+//--------------------------------------------------
+// Returns the certificates issuer CN
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetIssuerCN(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_commonName, 1);
+}
+
+
+//--------------------------------------------------
+// Returns the certificates subject first name
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectFirstName(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_firstName, 0);
+}
+
+
+//--------------------------------------------------
+// Returns the certificates subject last name
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectLastName(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_lastName, 0);
+}
+
+
+//--------------------------------------------------
+// Returns the certificates subject personal code
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectPerCode(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_perCode, 0);
+}
+
+//--------------------------------------------------
+// Returns the certificates subject country code
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectCountryName(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_countryName, 0);
+}
+
+//--------------------------------------------------
+// Returns the certificates subject organization
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectOrganization(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_organization, 0);
+}
+
+//--------------------------------------------------
+// Returns the certificates subject organization unit
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int ddocCertGetSubjectOrganizationUnit(X509* pCert, DigiDocMemBuf* pMemBuf)
+{
+ return ddocCertGetDNPart(pCert, pMemBuf, NID_organizationUnit, 0);
+}
+
+//--------------------------------------------------
+// Returns the desired item from string rep of DN
+// sDn - certificate DN
+// sId - searched DN part
+// pMBuf - memory buffer object for storing result
+// returns error code or ERR_OK
+//--------------------------------------------------
+int ddocGetDNPartFromString(const char* sDn, const char* sId, DigiDocMemBuf* pMBuf)
+{
+ int err = ERR_OK, j, l;
+ char *p0 = 0, *p1 = 0;
+ char buf1[30];
+
+ RETURN_IF_NULL_PARAM(sDn);
+ RETURN_IF_NULL_PARAM(sId);
+ RETURN_IF_NULL_PARAM(pMBuf);
+ // initialize
+ if(pMBuf->pMem)
+ err = ddocMemBuf_free(pMBuf);
+ pMBuf->pMem = 0;
+ pMBuf->nLen = 0;
+ memset(buf1, 0, sizeof(buf1));
+ snprintf(buf1, sizeof(buf1)-1, "%s=", sId);
+ p0 = strstr(sDn, buf1);
+ if(p0) {
+ p0 += strlen(buf1);
+ p1 = strchr(p0, ',');
+ if(p1) {
+ while(p1 && *(p1-1) == '\\')
+ p1 = strchr(p1, ',');
+ if(p1 && *p1 == ',') p1--;
+ } else {
+ p1 = strchr(p0, '/');
+ if(p1) {
+ while(p1 && *(p1-1) == '\\')
+ p1 = strchr(p1, '/');
+ if(p1 && *p1 == '/') p1--;
+ } else
+ p1 = (char*)sDn + strlen(sDn);
+ }
+ //
+ if(p0 && p1 && (int)(p1 - p0) > 0) {
+ l = (int)(p1 - p0) + 1;
+ ddocMemAppendData(pMBuf, (const char*)p0, l);
+ ((char*)pMBuf->pMem)[l] = 0;
+ }
+ }
+ return err;
+}
+
+//AM 06.03.08
+//--------------------------------------------------
+// Returns the certificates DN. Internal function.
+// Do not call directly, subject to change
+// pCert - certificate data
+// pMemBuf - memory buffer object for storing DN
+// bIssuer - 1=issuer, 0=subject
+// returns error code or ERR_OK
+//--------------------------------------------------
+int bdocCertGetDN(X509* pCert, DigiDocMemBuf* pMemBuf, int bIssuer)
+{
+ int err = ERR_OK;
+ X509_NAME *pName = 0;
+ X509_NAME_ENTRY *pNe = 0;
+ int i, n, l, t, b = 0;
+ const char *s;
+ unsigned char* p;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(pMemBuf);
+
+ // initialize
+ if(pMemBuf->pMem)
+ err = ddocMemBuf_free(pMemBuf);
+ pMemBuf->pMem = 0;
+ pMemBuf->nLen = 0;
+
+ // iterate over name entries
+ if(bIssuer)
+ pName = X509_get_issuer_name(pCert);
+ else
+ pName = X509_get_subject_name(pCert);
+ for(i = 0; (err == ERR_OK) && (i < sk_X509_NAME_ENTRY_num(pName->entries)); i++) {
+ pNe = sk_X509_NAME_ENTRY_value(pName->entries, i);
+ n = OBJ_obj2nid(pNe->object);
+ s = OBJ_nid2sn(n);
+ t = pNe->value->type;
+ // mostly we find here:
+ // V_ASN1_PRINTABLESTRING, V_ASN1_TELETEXSTRING or V_ASN1_BMPSTRING
+ // that we convert to UTF, but V_ASN1_UTF8STRING allready is in UTF8
+ // handle only the enry types we know
+ if(n != NID_undef && s != NULL) {
+ // convert to UTF8 only
+ p = 0;
+ if(t == V_ASN1_UTF8STRING) {
+ p = pNe->value->data;
+ l = pNe->value->length;
+ } else
+ l = ASN1_STRING_to_UTF8(&p, pNe->value);
+ ddocDebug(5, "ddocCertGetDN",
+ "NameEntry nid: %d type: %d len: %d item: %s value: \'%s\'",
+ n, t, l, s, (p ? (const char*)p : "NULL"));
+ // append separator if necessary
+ if(b)
+ err = ddocMemAppendData(pMemBuf, ",", -1);
+ else
+ b = 1;
+ // print the entry
+ err = ddocMemAppendData(pMemBuf, s, -1);
+ err = ddocMemAppendData(pMemBuf, "=", -1);
+ err = ddocMemAppendData(pMemBuf, (const char*)p, l);
+ // cleanup
+ if(p && t != V_ASN1_UTF8STRING)
+ OPENSSL_free(p);
+ }
+ ddocDebug(5, "ddocCertGetDN", "Subject: \'%s\' len: %d",
+ (const char*)pMemBuf->pMem, pMemBuf->nLen);
+ } // for
+
+ return err;
+}
+
+//================< deprecated functions> =================================
+
+#ifdef WITH_DEPRECATED_FUNCTIONS
+
+//============================================================
+// Decodes base64 (PEM) cert data and returns a cert object
+// certData - base64 (PEM) cert data
+// certLen - cert data length
+//============================================================
+// FIXME : Ugly as hell...
+#pragma message ("Function decodeCertificateData may be removed from future releases. Please use function ddocDecodeX509PEMData() instead.")
+EXP_OPTION int decodeCertificateData(X509 **newX509, const byte* certData, int certLen)
+{
+ int l1, l2;
+ char *buf1;
+ BIO* b1 = NULL;
+ X509* x509 = NULL;
+
+ RETURN_IF_NULL_PARAM(certData);
+
+ l2 = certLen * 2;
+ buf1 = (char*)malloc(l2);
+ RETURN_IF_BAD_ALLOC(buf1);
+ memset(buf1, 0, l2);
+ strncpy(buf1, "-----BEGIN CERTIFICATE-----\r\n", l2);
+ l1 = l2 - strlen(buf1);
+ encode(certData, certLen, (byte*)strchr(buf1,0), &l1);
+ l1 = l2 - strlen(buf1);
+ strncat(buf1, "\n-----END CERTIFICATE-----", l1);
+ l1 = strlen(buf1);
+ b1 = BIO_new_mem_buf(buf1, l1);
+ if (!b1) {
+ free(buf1);
+ SET_LAST_ERROR_RETURN_CODE(ERR_NULL_POINTER);
+ }
+ x509 = PEM_read_bio_X509(b1, NULL, NULL, 0);
+ BIO_free(b1);
+ free(buf1);
+ RETURN_IF_NOT(x509, ERR_CERT_INVALID);
+
+ *newX509 = x509;
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Returns the certificates issuer name
+// cert - certificate data
+// buf - usser name buffer
+// buflen - pointer to buffer length (will be modified)
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int getCertIssuerName(X509* cert, char* buf, int* buflen)
+{
+ int l1;
+ char buf1[X509_NAME_BUF_LEN];
+
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(buf);
+ RETURN_IF_NULL_PARAM(buflen);
+
+ if(*buflen >= X509_NAME_LEN) {
+ l1 = sizeof(buf1);
+ memset(buf1,0,l1);
+ memset(buf, 0, *buflen);
+ X509_NAME_oneline(X509_get_issuer_name(cert), buf1, l1);
+ unicode2ascii(buf1, buf);
+ ddocDebug(5, "getCertIssuerName", "Issuer: \'%s\' -> \'%s\'", buf1, buf);
+ *buflen = strlen(buf);
+ } else
+ SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Returns the certificates subject name. This finction
+// is also used in the COM library
+// cert - certificate data
+// buf - user name buffer
+// buflen - pointer to buffer length (will be modified)
+// returns error code or ERR_OK
+//--------------------------------------------------
+#pragma message ("Function getCertSubjectName may be removed from future releases. Please use function ddocCertGetSubjectDN() instead.")
+EXP_OPTION int getCertSubjectName(X509* cert, char* buf, int* buflen)
+{
+ int err = ERR_OK;
+ DigiDocMemBuf mbuf;
+
+ mbuf.pMem = 0;
+ mbuf.nLen = 0;
+ err = ddocCertGetSubjectDN(cert, &mbuf);
+ if(err == ERR_OK) {
+ if(*buflen >= X509_NAME_LEN) {
+#ifdef WIN32
+ utf82oem((const char*)mbuf.pMem, buf, buflen);
+#else
+ utf82ascii((const char*)mbuf.pMem, buf, buflen);
+#endif
+ *buflen = strlen(buf);
+ } else
+ SET_LAST_ERROR(ERR_BUF_LEN);
+ ddocMemBuf_free(&mbuf);
+ }
+
+ return err;
+}
+
+//--------------------------------------------------
+// Returns the certificates subjects DN
+// cert - certificate data
+// buf - usser name buffer
+// buflen - pointer to buffer length (will be modified)
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int getCertSubjectDN(X509* cert, char* buf, int* buflen, int bUTF8)
+{
+ int l1;
+ char buf1[X509_NAME_BUF_LEN];
+
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(buf);
+ RETURN_IF_NULL_PARAM(buflen);
+ if(*buflen >= X509_NAME_LEN) {
+ l1 = sizeof(buf1);
+ memset(buf1, 0, l1);
+ memset(buf, 0, *buflen);
+ X509_NAME_oneline(X509_get_subject_name(cert), buf1, l1);
+ if (bUTF8) {
+ unicode2ascii(buf1, buf);
+ *buflen = strlen(buf);
+ } else {
+ ascii2utf8(buf1, buf, buflen);
+ }
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN);
+ return ERR_OK;
+}
+
+
+//--------------------------------------------------
+// Returns the certificates subjects name's CN part
+// cert - certificate data
+// buf - usser name buffer
+// buflen - pointer to buffer length (will be modified)
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int getCertSubjectCN(X509* cert, char* buf, int* buflen, int bUTF8)
+{
+ int l1, err = ERR_OK;
+ char buf1[X509_NAME_BUF_LEN], *p , *p2, buf2[X509_NAME_BUF_LEN];
+
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(buf);
+ RETURN_IF_NULL_PARAM(buflen);
+
+ if(*buflen >= X509_NAME_LEN) {
+ l1 = sizeof(buf1);
+ memset(buf1,0,l1);
+ memset(buf, 0, *buflen);
+ err = getCertSubjectName(cert, buf1, &l1);
+ if(bUTF8 && hasUmlauts(buf1)) {
+ //printf("Converting umlauts toi UTF8\n");
+ l1 = sizeof(buf2);
+ ascii2utf8(buf1, buf2, &l1);
+ strncpy(buf1, buf2, sizeof(buf1));
+ ddocDebug(4, "getCertSubjectCN", "Subject: \'%s\'", buf1);
+ }
+ /*if (!bUTF8) {
+ l1 = sizeof(buf2);
+ utf82ascii(buf1, buf2, &l1);
+ //strcpy(buf1, buf2);
+ }*/
+ //printf("SUBJECT: %s\n", buf1);
+ p = strstr(buf1, "CN=");
+ if(p) {
+ p += 3;
+ p2 = strchr(p, '/');
+ if(!p2)
+ p2 = p + strlen(p);
+ if(p2) {
+ strncpy(buf, p, p2-p);
+ buf[p2-p] = 0;
+ }
+ }
+ *buflen = strlen(buf);
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN);
+ return ERR_OK;
+}
+
+//--------------------------------------------------
+// Returns the certificates issuer name's CN part
+// cert - certificate data
+// buf - usser name buffer
+// buflen - pointer to buffer length (will be modified)
+// returns error code or ERR_OK
+//--------------------------------------------------
+EXP_OPTION int getCertIssuerCN(X509* cert, char* buf, int* buflen, int bUTF8)
+{
+ int l1;
+ char buf1[X509_NAME_BUF_LEN], *p , *p2, buf2[X509_NAME_BUF_LEN];
+
+ RETURN_IF_NULL_PARAM(cert);
+ RETURN_IF_NULL_PARAM(buf);
+ RETURN_IF_NULL_PARAM(buflen);
+
+ if(*buflen >= X509_NAME_LEN) {
+ l1 = sizeof(buf1);
+ memset(buf1,0,l1);
+ memset(buf, 0, *buflen);
+ X509_NAME_oneline(X509_get_issuer_name(cert), buf1, l1);
+ if (bUTF8) {
+ unicode2ascii(buf1, buf2);
+ } else {
+ l1 = sizeof(buf2);
+ ascii2utf8(buf1, buf2, &l1);
+ }
+ //printf("SUBJECT: %s\n", buf2);
+ p = strstr(buf2, "CN=");
+ if(p) {
+ p += 3;
+ p2 = strchr(p, '/');
+ if(!p2)
+ p2 = p + strlen(p);
+ if(p2) {
+ strncpy(buf, p, p2-p);
+ buf[p2-p] = 0;
+ }
+ }
+ *buflen = strlen(buf);
+ }
+ else
+ SET_LAST_ERROR_RETURN_CODE(ERR_BUF_LEN);
+ return ERR_OK;
+}
+
+// get cert owners id-code
+EXP_OPTION int getCertOwnerCode(const X509* pCert, char* buf, int len)
+{
+ int err, l1;
+ char buf1[500], *p;
+
+ RETURN_IF_NULL_PARAM(pCert);
+ RETURN_IF_NULL_PARAM(buf);
+ l1 = sizeof(buf1);
+ err = getCertSubjectName((void*)pCert, buf1, &l1);
+ if (err != ERR_OK) SET_LAST_ERROR_RETURN_CODE(err);
+ err = ERR_CERT_READ;
+ p = strstr(buf1, "CN=");
+ if (p) {
+ p = strchr(p, ',');
+ if(p) {
+ p = strchr(p+1, ',');
+ if(p) {
+ strncpy(buf, p+1, 1en);
+ buf[1en] = 0;
+ err = ERR_OK;
+ }
+ } else { // no comma -> no id-code !
+ buf[0] = 0;
+ // is this really an error ?
+ err = ERR_WRONG_CERT;
+ }
+ }
+ if (err != ERR_OK) SET_LAST_ERROR(err);
+ return err;
+}
+
+
+#endif // WITH_DEPRECATED_FUNCTIONS