summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2008-12-21 03:02:54 +0100
committerDavid Sommerseth <dazo@users.sourceforge.net>2008-12-21 03:02:54 +0100
commitdd0c061770b90039e605e68a44327d968981c386 (patch)
treefc34c8dd0e5892c672c0bf6b3a96d41e47e599d7
parent33c16185e500e18dbf364dc183a2ce713448931f (diff)
downloadeurephia-dd0c061770b90039e605e68a44327d968981c386.tar.gz
eurephia-dd0c061770b90039e605e68a44327d968981c386.tar.xz
eurephia-dd0c061770b90039e605e68a44327d968981c386.zip
Moved the certfile parsing out from certificate.c into parse_certificate_files.c
Changed certinfo.[ch] to add cert.digest as well, and using this modified struct to handle the parse result after parsing the certfile.
-rw-r--r--common/certinfo.c2
-rw-r--r--common/certinfo.h1
-rw-r--r--eurephiadm/CMakeLists.txt2
-rw-r--r--eurephiadm/commands/certificates.c164
-rw-r--r--eurephiadm/parse_certificate_files.c192
-rw-r--r--eurephiadm/parse_certificate_files.h38
6 files changed, 250 insertions, 149 deletions
diff --git a/common/certinfo.c b/common/certinfo.c
index bb68a53..d3fccb2 100644
--- a/common/certinfo.c
+++ b/common/certinfo.c
@@ -80,6 +80,8 @@ void free_certinfo(certinfo *p) {
if( p == NULL )
return;
+ if( p->digest != NULL )
+ free(p->digest);
if( p->org != NULL )
free(p->org);
if( p->common_name != NULL )
diff --git a/common/certinfo.h b/common/certinfo.h
index d9496bd..ca6f659 100644
--- a/common/certinfo.h
+++ b/common/certinfo.h
@@ -22,6 +22,7 @@
#define __CERTINFO_H_
typedef struct _certinfo {
+ char *digest;
char *org;
char *common_name;
char *email;
diff --git a/eurephiadm/CMakeLists.txt b/eurephiadm/CMakeLists.txt
index d2ae8fd..e538a61 100644
--- a/eurephiadm/CMakeLists.txt
+++ b/eurephiadm/CMakeLists.txt
@@ -9,6 +9,7 @@ SET(efw_ipt_SRC
client_config.c
client_context.c
client_session.c
+ parse_certificate_files.c
commands/users.c
commands/certificates.c
commands/edit_config.c
@@ -19,6 +20,7 @@ SET(efw_ipt_SRC
../common/eurephia_xml.c
../common/passwd.c
../common/sha512.c
+ ../common/certinfo.c
../database/eurephiadb.c
)
diff --git a/eurephiadm/commands/certificates.c b/eurephiadm/commands/certificates.c
index e91dfb4..40e24d1 100644
--- a/eurephiadm/commands/certificates.c
+++ b/eurephiadm/commands/certificates.c
@@ -29,13 +29,6 @@
#include <errno.h>
#include <assert.h>
-#ifdef HAVE_OPENSSL
-#include <openssl/ssl.h>
-#include <openssl/pkcs12.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#endif
-
#ifdef HAVE_LIBXML2
#include <libxml/parser.h>
#include <libxml/tree.h>
@@ -52,10 +45,12 @@
#include <eurephia_admin_struct.h>
#include <eurephiadb_mapping.h>
#include <eurephiadb_driver.h>
+#include <certinfo.h>
#include "../argparser.h"
#include "../get_console_input.h"
#include "../field_print.h"
+#include "../parse_certificate_files.h"
void display_certs_help(int page) {
printf("Help page not implemented yet\n");
@@ -82,56 +77,6 @@ int help_Certificates2(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *
return 0;
}
-#ifdef HAVE_OPENSSL
-char *ExtractCertInfo(X509 *cert, const char *fieldname) {
- unsigned char *buf = (unsigned char *)1; // Needs to be 1 to avoid OpenSSL 0.9.6b bug
- char resbuf[2048];
- X509_NAME *name = NULL;
- X509_NAME_ENTRY *namentry = NULL;
- ASN1_STRING *asn1 = NULL;
- int nid, tmp = -1, pos = -1;
-
- //
- // Extract subject information
- //
-
- memset(&resbuf, 0, 2048);
-
- nid = OBJ_txt2nid(fieldname);
- name = X509_get_subject_name(cert);
-
- do {
- pos = tmp;
- tmp = X509_NAME_get_index_by_NID(name, nid, pos);
- } while ( tmp > -1 );
-
- if( pos == -1 ) {
- fprintf(stderr, "%s: Field '%s' not found\n", MODULE, fieldname);
- return NULL;
- }
-
- if( !(namentry = X509_NAME_get_entry(name, pos)) ) {
- fprintf(stderr, "%s: Failed to extract name entry from field '%s'\n", MODULE, fieldname);
- return NULL;
- }
-
- if( !(asn1 = X509_NAME_ENTRY_get_data(namentry)) ) {
- fprintf(stderr, "%s: Failed to extract data from name entry field '%s'\n", MODULE, fieldname);
- return NULL;
- }
-
- if( ASN1_STRING_to_UTF8(&buf, asn1) <= 0 ) {
- fprintf(stderr, "%s: Failed to convert ASN1 string to UTF-8 for '%s'\n", MODULE, fieldname);
- return NULL;
- }
-
- snprintf(resbuf, 2046, "%s", buf);
- OPENSSL_free(buf);
-
- return strdup_nullsafe(resbuf);
-}
-#endif
-
#define SHOWCERTS_FIREWALL 0x001
#define SHOWCERTS_DIGEST 0x002
@@ -276,7 +221,7 @@ int add_cert(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int a
};
certfile = NULL;
- certfile_format = 0;
+ certfile_format = CERTFILE_PEM; // Default file format when not specified
for( i = 1; i < argc ; i++ ) {
switch( eurephia_getopt(&i, argc, argv, addcertargs) ) {
case 'd': // Certificate depth
@@ -320,7 +265,7 @@ int add_cert(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int a
#ifdef HAVE_OPENSSL
case 'p': // Certfile is in PKCS#12 format
- certfile_format = 1;
+ certfile_format = CERTFILE_PKCS12;
break;
case 'f': // Load certificate info from a certificate file
@@ -373,100 +318,22 @@ int add_cert(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int a
#ifdef HAVE_OPENSSL
// If we have a certfile - open it and fetch the info we want
if( certfile != NULL ) {
- BIO *bio_err = NULL;
- PKCS12 *p12 = NULL;
- EVP_PKEY *pkey = NULL;
- X509 *cert = NULL;
- FILE *fp;
-
- /* Needed to convert X509 digest into hex string */
- unsigned char md_sha1[EVP_MAX_MD_SIZE];
- unsigned int mdlen;
-
- if( !bio_err ) {
- SSL_library_init();
- SSL_load_error_strings();
- bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
- }
-
- // Open file - according to defined format
- switch( certfile_format ) {
- case 0: // PEM/DER format
- fp = fopen(certfile, "r");
- if( !(cert = PEM_read_X509(fp, NULL, NULL, NULL)) ) {
- fprintf(stderr, "%s: Failed to open certificate file\n", MODULE);
- return 3;
- }
- fclose(fp);
- break;
-
- case 1: // PKCS#12 format
- fp = fopen(certfile, "r");
- p12 = d2i_PKCS12_fp(fp, NULL);
- fclose(fp);
- if( p12 == NULL ) {
- fprintf(stderr, "%s: Could not open PKCS#12 file\n", MODULE);
- return 3;
- }
- OpenSSL_add_all_ciphers();
-
- // First, try without password
- if( !PKCS12_parse(p12, "", &pkey, &cert, NULL) ) {
- char pwd[130];
-
- // If empty password failed, get password and try again
- memset(&pwd, 0, 130);
- if( get_console_input(pwd, 128, "PKCS12 password:", 1) < 0 ) {
- fprintf(stderr, "Could not retrieve password\n");
- }
- if( !PKCS12_parse(p12, pwd, &pkey, &cert, NULL) ) {
- PKCS12_free(p12); p12 = NULL;
- fprintf(stderr,
- "%s: Could not open PKCS#12 file - wrong password\n", MODULE);
- fprintf(stderr,
- "%s: %s\n", MODULE, ERR_error_string(ERR_get_error(), NULL));
- BIO_free(bio_err);
- return 3;
- }
- }
- EVP_PKEY_free(pkey); pkey = NULL;
- PKCS12_free(p12); p12 = NULL;
- break;
-
- default: // Unknown
- fprintf(stderr, "%s: Unknown certificate file format\n", MODULE);
- return 1;
+ certinfo *ci = NULL;
+ if( (ci = Cert_ParseFile(certfile, certfile_format)) == NULL ) {
+ fprintf(stderr, "%s: Failed to parse certificate file\n", MODULE);
+ rc = 1;
+ goto exit;
}
+ digest = strdup_nullsafe(ci->digest);
+ cname = strdup_nullsafe(ci->common_name);
+ org = strdup_nullsafe(ci->org);
+ email = strdup_nullsafe(ci->email);
+ free_certinfo(ci); ci = NULL;
-
- // extract SHA1 digest from certificate
- digest = (char *) malloc(66);
- memset(digest, 0, 66);
- if (X509_digest(cert, EVP_sha1(), md_sha1, &mdlen) && mdlen > 0) {
- static const char hexcodes[] = "0123456789ABCDEF";
- int j;
-
- for (j = 0; j < (int) mdlen; j++) {
- digest[j * 3] = hexcodes[(md_sha1[j] & 0xf0) >> 4U];
- digest[(j * 3) + 1] = hexcodes[(md_sha1[j] & 0x0f)];
- if (j + 1 != (int) mdlen) {
- digest[(j * 3) + 2] = ':';
- } else {
- digest[(j * 3) + 2] = '\0';
- }
- }
- }
-
- // Extract the subject information we want
- cname = ExtractCertInfo(cert, "CN");
- org = ExtractCertInfo(cert, "O");
- email = ExtractCertInfo(cert, "emailAddress");
-
- X509_free(cert);
- BIO_free(bio_err);
}
#endif
rc = register_certificate(ctx, depth, digest, cname, org, email);
+ exit:
free_nullsafe(digest);
free_nullsafe(cname);
free_nullsafe(org);
@@ -669,4 +536,3 @@ int cmd_Certificates(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cf
return rc;
}
-
diff --git a/eurephiadm/parse_certificate_files.c b/eurephiadm/parse_certificate_files.c
new file mode 100644
index 0000000..b2e5ca2
--- /dev/null
+++ b/eurephiadm/parse_certificate_files.c
@@ -0,0 +1,192 @@
+/* parse_certificate_files.c -- Parses PEM or PKCS12 formated cert. files
+ *
+ * GPLv2 - Copyright (C) 2008 David Sommerseth <dazo@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_OPENSSL
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <openssl/ssl.h>
+#include <openssl/pkcs12.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+#include <eurephia_nullsafe.h>
+#include <certinfo.h>
+
+#include "get_console_input.h"
+#define _PARSE_CERTFICIATE_FILES_C
+#include "parse_certificate_files.h"
+
+
+char *ExtractCertInfo(const char *module, X509 *cert, const char *fieldname) {
+ unsigned char *buf = (unsigned char *)1; // Needs to be 1 to avoid OpenSSL 0.9.6b bug
+ char resbuf[2050];
+ X509_NAME *name = NULL;
+ X509_NAME_ENTRY *namentry = NULL;
+ ASN1_STRING *asn1 = NULL;
+ int nid, tmp = -1, pos = -1;
+
+ //
+ // Extract subject information
+ //
+
+ memset(resbuf, 0, 2050);
+
+ nid = OBJ_txt2nid(fieldname);
+ name = X509_get_subject_name(cert);
+
+ do {
+ pos = tmp;
+ tmp = X509_NAME_get_index_by_NID(name, nid, pos);
+ } while ( tmp > -1 );
+
+ if( pos == -1 ) {
+ fprintf(stderr, "%s: Field '%s' not found\n", module, fieldname);
+ return 0;
+ }
+
+ if( !(namentry = X509_NAME_get_entry(name, pos)) ) {
+ fprintf(stderr, "%s: Failed to extract name entry from field '%s'\n", module, fieldname);
+ return 0;
+ }
+
+ if( !(asn1 = X509_NAME_ENTRY_get_data(namentry)) ) {
+ fprintf(stderr, "%s: Failed to extract data from name entry field '%s'\n", module, fieldname);
+ return 0;
+ }
+
+ if( ASN1_STRING_to_UTF8(&buf, asn1) <= 0 ) {
+ fprintf(stderr, "%s: Failed to convert ASN1 string to UTF-8 for '%s'\n", module, fieldname);
+ return 0;
+ }
+
+ snprintf(resbuf, 2048, "%s%c", buf, '\0');
+ OPENSSL_free(buf);
+
+ return strdup_nullsafe(resbuf);
+}
+
+
+certinfo *_Cert_ParseFile(const char *module, const char *certfile, int certfile_format) {
+ BIO *bio_err = NULL;
+ PKCS12 *p12 = NULL;
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ FILE *fp;
+ certinfo *ret = NULL;
+
+ /* Needed to convert X509 digest into hex string */
+ unsigned char md_sha1[EVP_MAX_MD_SIZE];
+ unsigned int mdlen;
+
+ if( !bio_err ) {
+ SSL_library_init();
+ SSL_load_error_strings();
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
+ }
+
+ // Open file - according to defined format
+ switch( certfile_format ) {
+ case CERTFILE_PEM: // PEM/DER format
+ fp = fopen(certfile, "r");
+ if( !(cert = PEM_read_X509(fp, NULL, NULL, NULL)) ) {
+ fprintf(stderr, "%s: Failed to open certificate file\n", module);
+ return NULL;
+ }
+ fclose(fp);
+ break;
+
+ case CERTFILE_PKCS12: // PKCS#12 format
+ fp = fopen(certfile, "r");
+ p12 = d2i_PKCS12_fp(fp, NULL);
+ fclose(fp);
+ if( p12 == NULL ) {
+ fprintf(stderr, "%s: Could not open PKCS#12 file\n", module);
+ return NULL;
+ }
+ OpenSSL_add_all_ciphers();
+
+ // First, try without password
+ if( !PKCS12_parse(p12, "", &pkey, &cert, NULL) ) {
+ char pwd[130];
+
+ // If empty password failed, get password and try again
+ memset(&pwd, 0, 130);
+ if( get_console_input(pwd, 128, "PKCS12 password:", 1) < 0 ) {
+ fprintf(stderr, "Could not retrieve password\n");
+ }
+ if( !PKCS12_parse(p12, pwd, &pkey, &cert, NULL) ) {
+ PKCS12_free(p12); p12 = NULL;
+ fprintf(stderr,
+ "%s: Could not open PKCS#12 file - wrong password\n", module);
+ fprintf(stderr,
+ "%s: %s\n", module, ERR_error_string(ERR_get_error(), NULL));
+ BIO_free(bio_err);
+ return NULL;
+ }
+ }
+ EVP_PKEY_free(pkey); pkey = NULL;
+ PKCS12_free(p12); p12 = NULL;
+ break;
+
+ default: // Unknown
+ fprintf(stderr, "%s: Unknown certificate file format\n", module);
+ return NULL;
+ }
+
+ ret = (certinfo *) malloc(sizeof(certinfo)+2);
+ assert( ret != NULL );
+ memset(ret, 0, sizeof(certinfo)+2);
+
+ ret->digest = (char *) malloc(66);
+ assert(ret != NULL);
+ memset(ret->digest, 0, 66);
+
+
+
+ // extract SHA1 digest from certificate
+ if (X509_digest(cert, EVP_sha1(), md_sha1, &mdlen) && mdlen > 0) {
+ static const char hexcodes[] = "0123456789ABCDEF";
+ int j;
+
+ for (j = 0; j < (int) mdlen; j++) {
+ ret->digest[j * 3] = hexcodes[(md_sha1[j] & 0xf0) >> 4U];
+ ret->digest[(j * 3) + 1] = hexcodes[(md_sha1[j] & 0x0f)];
+ if (j + 1 != (int) mdlen) {
+ ret->digest[(j * 3) + 2] = ':';
+ } else {
+ ret->digest[(j * 3) + 2] = '\0';
+ }
+ }
+ }
+
+ // Extract the subject information we want
+ ret->common_name = ExtractCertInfo(module, cert, "CN");
+ ret->org = ExtractCertInfo(module, cert, "O");
+ ret->email = ExtractCertInfo(module, cert, "emailAddress");
+
+ X509_free(cert);
+ BIO_free(bio_err);
+
+ return ret;
+}
+#endif
diff --git a/eurephiadm/parse_certificate_files.h b/eurephiadm/parse_certificate_files.h
new file mode 100644
index 0000000..03d66e4
--- /dev/null
+++ b/eurephiadm/parse_certificate_files.h
@@ -0,0 +1,38 @@
+/* parse_certificate_files.h --
+ *
+ * GPLv2 - Copyright (C) 2008 David Sommerseth <dazo@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PARSE_CERTIFICATE_FILES_H_
+# define PARSE_CERTIFICATE_FILES_H_
+
+#include <certinfo.h>
+
+#ifdef HAVE_OPENSSL
+#define CERTFILE_PEM 0x01
+#define CERTFILE_PKCS12 0x02
+
+#ifndef _PARSE_CERTFICIATE_FILES_C
+
+#define Cert_ParseFile(cfile,cformat) _Cert_ParseFile(MODULE, cfile, cformat)
+certinfo *_Cert_ParseFile(const char *module, const char *certfile, int certfile_format);
+
+#endif /* !_PARSE_CERTFICIATE_FILES_C */
+
+#endif /* HAVE OPENSSL */
+#endif /* !PARSE_CERTIFICATE_FILES_H_ */