Commit 86e64407 authored by Bernard Quatermass's avatar Bernard Quatermass

Initial Commit of clica V2

parents
#CFLAGS=-I../mplib1/
#LDFLAGS=-L../mplib1/lib -lmplib1 -lidn
CFLAGS=-I/usr/include/nss3 -I/usr/include/nspr4 -g
LDFLAGS=-lidn -lnssutil3 -lnss3 -lsmime3 -ltalloc -lmplib1 -lsqlite3
#OBJ_FILES=clica.o util.o inifile.o
OBJ_CORE_FILES=util.o clica_db.o sub_proc.o clica_nss.o clica_nss_extns.o clica_idn.o clica_file.o
OBJ_FILES=clica.o ${OBJ_CORE_FILES}
all: clica
clica: ${OBJ_FILES}
clean::
@rm -rf clica ${OBJ_FILES} debugfiles.list debuglinks.list debugsources.list
testK2::
@rm -rf K2/
./clica --initialise --directory K2 --domain example.com --password password
testK2idn::
@rm -rf K2/
./clica --initialise --directory K2 --domain éxample.com --password password
This diff is collapsed.
/***************************************************************************************
* *
* clica.h
*
* main config structure
*
* *
***************************************************************************************/
#ifndef CLICA_CLICA_H
#define CLICA_CLICA_H
#define CLICA_DIR_MODE 0700
#define CLICA_FILE_MODE 0600
/* config structure
*
*/
#define CLICA_DIR_CA "CA"
#define CLICA_DIR_BLANK "BLANK"
#define CLICA_DIR_TRUST "TRUST"
#define CLICA_DB_CLICA_LEVEL "CLICA.level"
#define CLICA_DB_CLICA_SIGNER "CLICA.signer"
#define CLICA_DB_CLICA_OCSP_SIGNER "CLICA.ocsp_signer"
#define CLICA_DB_CLICA_OCSP_URL "CLICA.ocsp_url"
#define CLICA_DB_CLICA_CRL_SIGNER "CLICA.crl_signer"
#define CLICA_DB_CLICA_CRL_URL "CLICA.crl_url"
#define CLICA_DB_CLICA_ALGORITHM "CLICA.algorithm"
#define CLICA_DB_CA_NAME "CA.name"
#define CLICA_DB_CA_SUBJECT "CA.subject"
#define CLICA_DB_CA_DOMAIN_NAME "CA.domain_name"
#define CLICA_DB_CA_BITS "CA.bits"
#define CLICA_DB_CA_DN "CA.DN"
#define CLICA_DB_CA_SERVER_CA_DN "CA.SERVER_CA_DN"
#define CLICA_DB_CA_CLIENT_CA_DN "CA.CLIENT_CA_DN"
#define CLICA_DB_CA_USER_CA_DN "CA.USER_CA_DN"
#define CLICA_TRUST_CA "CTu,Cu,Cu"
#define CLICA_TRUST_SUBCA "CTu,Cu,Cu"
#define CLICA_TRUST_SERVER "u,u,u"
#define CLICA_TRUST_CLIENT "u,u,u"
#define CLICA_TRUST_USER "u,u,u"
enum clica_cmds {
CLICA_CMD_NONE = 0,
CLICA_CMD_INIT,
CLICA_CMD_SERVER_CERT,
CLICA_CMD_CLIENT_CERT,
CLICA_CMD_USER_CERT,
};
enum clica_cert_usage {
CLICA_CERT_USAGE_UNK = 0,
CLICA_CERT_USAGE_CA,
CLICA_CERT_USAGE_SUBCA,
CLICA_CERT_USAGE_OCSP,
CLICA_CERT_USAGE_CRL,
CLICA_CERT_USAGE_SERVER,
CLICA_CERT_USAGE_CLIENT,
CLICA_CERT_USAGE_USER,
};
/***************************************************************************************
* *
typedefs
* *
***************************************************************************************/
/***************************************************************************************
* *
Primary configuration structure
* *
holds parsed command line args
* *
unless explicitely noted all storage pointed to
has been alloced
* *
***************************************************************************************/
struct config
{
/* start with arg-line provided values */
int got_cmd; /* number of commands, >1 is an error */
int cmd;
int cmd_needs_password;
char *clica_dir;
char *server_cert_name;
char *client_cert_name;
char *user_cert_name;
char *alternates;
char *provided_csr;
char *provided_password;
char *provided_pwdfile;
char *provided_domain_name;
char *provided_ocsp_url;
char *provided_crl;
char *provided_algo;
char *provided_ou;
char *provided_serial;
int provided_bits;
int provided_months;
int no_sub_sign;
dl_List_t provided_noise_files;
int verbose;
/* derived, located and frustrated */
char *main_ca_dir;
char *cfgfile_name;
char *cfg_db_name;
void *dbh;
char *blank_dir;
char *trust_dir;
char *ou_dir_name;
char *store_pwdfile;
struct clica_dir *cd_ca_h;
struct clica_dir *cd_blank_h;
struct clica_dir *cd_trust_h;
char *ca_dn;
char *ocsp_dn;
char *crl_dn;
char *server_sub_ca_dn;
char *server_ca_pem;
char *client_sub_ca_dn;
char *client_ca_pem;
char *user_sub_ca_dn;
char *user_ca_pem;
struct clica_dir *cd_end_entity_h;
/* keep track of when for serialnumber data */
PRTime last_serno;
dl_List_t raw_alts;
dl_List_t dns_alts;
dl_List_t email_alts;
dl_List_t all_dirs;
};
/***************************************************************************************
* *
details of each directory
* *
we hold all details about a particular directory here.
path
* *
***************************************************************************************/
struct clica_dir
{
dl_Node_t cd_Node;
char *relname;
char *dirname;
char *pwdfile;
char *password;
int currently_open;
int valid;
char *slotname;
/* these are filenames where the pem versions of the stages of a create will be stored */
/* if multiple certs are being created remember to copy the files, or change the name */
char *key_pem;
char *req_pem;
char *cert_pem;
char *cert_name;
char *trusts;
};
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
#endif
This diff is collapsed.
/***************************************************************************************
* *
clica_db.h
interface to sqlite database with defaults
* *
***************************************************************************************/
#ifndef CLICA_DB_H
#define CLICA_DB_H
extern void *
open_clica_db( const char *filename, int create );
extern void *
close_clica_db( void *t );
extern int
sync_clica_db( void *t );
extern int
fetch_clica_db_opt( void *t, const char *name, char **rv );
extern int
set_clica_db_opt( void *t, const char *name, const char *val );
extern int
set_clica_db_opt_int( void *t, const char *name, int val );
extern int
fetch_clica_db_opt_int( void *t, const char *name, int *val );
extern int
may_fetch_clica_db_opt( void *t, const char *name, char **rv );
extern int
may_fetch_clica_db_opt_int( void *t, const char *name, int *val, int unset );
extern int
dump_clica_db( void *t, FILE *fp );
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
#endif
/***************************************************************************************
* *
* clica_file.c
* *
* conversion of data to/from plain files
* *
***************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <nss.h>
#include "clica_file.h"
/***************************************************************************************
* *
structures & defines
* *
***************************************************************************************/
/***************************************************************************************
* *
functions follow
* *
***************************************************************************************/
int
dump_der_to_file_as_pem( const char *filename, SECItem *der, const char *hdr, const char *trlr )
{
FILE *fh;
int rv=0;
if ( filename == NULL || ! *filename )
{
/* NOP, return OK */
rv = 1;
}
else
if ( (fh = fopen(filename,"w")) != NULL)
{
fprintf( fh, "%s\n%s\n%s\n",
(hdr) ? hdr : "-- BEGIN UNKNOWN TYPE --",
BTOA_DataToAscii(der->data, der->len),
(trlr) ? trlr : "-- BEGIN UNKNOWN TYPE --"
);
fclose(fh);
rv = 1;
}
return rv;
}
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
/***************************************************************************************
* *
* TODO.h
* *
* description
* *
***************************************************************************************/
#ifndef CLICA_TODO_H
#define CLICA_TODO_H
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
#endif
/***************************************************************************************
* *
* clica_idn.c
* *
* IDN suport routines
* *
***************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <idna.h>
/***************************************************************************************
* *
structures & defines
* *
***************************************************************************************/
/***************************************************************************************
* *
functions follow
* *
***************************************************************************************/
char *
clica_idna_if_different( const char *raw )
{
char *cp=NULL;
if (idna_to_ascii_8z(raw, &cp, 0)==IDNA_SUCCESS)
{
/* so we converted, but is it different ? */
if ( strcmp( raw, cp ) == 0 )
{
free(cp);
cp = NULL;
/* but if we were passed the punycode we need to try the other way */
if (idna_to_unicode_8z8z(raw, &cp, 0)==IDNA_SUCCESS)
{
if ( strcmp( raw, cp ) == 0 )
{
idn_free(cp);
cp = NULL;
}
}
}
}else
{
cp = NULL;
}
return cp;
}
int
clica_idna_ascii_and_uni( const char *raw, char **ascii, char **uni )
{
int rv = 0;
/* both returns */
*ascii = NULL;
*uni = NULL;
if ( (idna_to_ascii_8z(raw, ascii, 0)==IDNA_SUCCESS)
&& (idna_to_ascii_8z(*ascii, uni, 0)==IDNA_SUCCESS)
)
{
rv=1;
}
return rv;
}
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
/***************************************************************************************
* *
* clica_idn.h
* *
* IDN support routines
* *
***************************************************************************************/
#ifndef CLICA_TODO_H
#define CLICA_TODO_H
/* return the punycode (or unicode) version if input is an IDN and the other form is different */
extern char *
clica_idna_if_different( const char *raw );
/* return the ascii and unicode versions, should do a decent sanitise job */
extern int
clica_idna_ascii_and_uni( const char *raw, char **ascii, char **uni );
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
#endif
This diff is collapsed.
/***************************************************************************************
* *
* clica_nss.h
* *
* NSS interaction routines
* *
***************************************************************************************/
#ifndef CLICA_NSS_H
#define CLICA_NSS_H
extern void
clica_nss_init( void );
extern void
clica_nss_shutdown( void );
extern int
create_new_nss_db( struct config *config, struct clica_dir *cdh );
extern int
create_private_key( struct config *config, struct clica_dir *cdh, int size );
extern int
create_ca_cert( struct config *config, struct clica_dir *cdh, int size );
extern int
create_sub_ca_cert( struct config *config, struct clica_dir *cdh,
const char *signer,
PRTime serno,
const char *subject,
int path_length,
int size,
const char *pemname
);
extern int
create_end_entity_cert( struct config *config,
struct clica_dir *signer_cdh,
const char *signer,
struct clica_dir *ee_cdh,
const char *ee_subject,
int cct,
int size,
PRTime serno,
dl_List_t *alts_list,
const char *csrfile,
const char *pemname,
const char *trusts
);
extern int
import_pem( struct config *config, struct clica_dir *cdh, const char *filename, const char *dn, const char *trusts );
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
#endif
This diff is collapsed.
/***************************************************************************************
* *
* clica_nss_extns.h
* *
* Deal with the extensions for each type of cert
* *
***************************************************************************************/
#ifndef CLICA_NSS_EXTNS_H
#define CLICA_NSS_EXTNS_H
struct clica_key_info {
KeyType keytype;
SECOidTag algtag;
SECKEYPublicKey *pubkey;
SECKEYPrivateKey *privKey;
PK11RSAGenParams rsaparams;
SECKEYPQGParams *dsaparams;
int publicExponent;
/* will also need forms of hash */
SECItem keyID; /* which will be of SHA1_LENGTH */
};
#if 0
enum clica_cert_usage {
ccu_unk = 0,
ccu_ca,
ccu_subca,
ccu_ocsp,
ccu_crl,
ccu_server,
ccu_client,
ccu_user
};
#endif
struct clica_cert_extn {
dl_Node_t cce_Node;
SECOidTag extnOIDTag;
SECItem bsv;
PRBool is_crit;
unsigned char e_value;
};
struct clica_cert_extn_list {
dl_List_t cce_List;
int cce_use;
};
enum certutilExtns {
ext_keyUsage = 0,
ext_basicConstraint,
ext_authorityKeyID,
ext_CRLDistPts,
ext_NSCertType,
ext_extKeyUsage,
ext_authInfoAcc,
ext_subjInfoAcc,
ext_certPolicies,
ext_policyMappings,
ext_policyConstr,
ext_inhibitAnyPolicy,
ext_subjectKeyID,
ext_nameConstraints,
ext_End
};
typedef struct ExtensionEntryStr {
PRBool activated;
const char *arg;
} ExtensionEntry;
typedef ExtensionEntry certutilExtnList[ext_End];
SECStatus
cce_addextnsfortype(struct config *config,
struct clica_dir *cdh,
struct clica_key_info *ckip,
int ccu,
int path_length,
CERTCertificate *cert,
CERTCertificateRequest *certReq,
void *extHandle,
SECItem *authKID,
SECItem *subjKID,
const char *emailAddrs, const char *dnsNames
);
/***************************************************************************************
* *
End of File
* *
* vi: aw ai sw=4 *
***************************************************************************************/
#endif
/*
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <getopt.h>
#include <errno.h>
#include <talloc.h>
#include <mplib1/dl_list.h>
#include "util.h"
#include "sub_proc.h"
/***************************************************************************************
* *
sub-proc control
since there is no notion of independent operation on individual cert DBs we
need to delegate operation to sub processes.
we use these primitive by default so we can hook up a feedback path for
non-returncode data
* *
***************************************************************************************/
static struct sub_proc *
sub_proc_alloc( const char *subname )
{
struct sub_proc *sp;
if( ( sp = talloc_zero( NULL, struct sub_proc ) )
&& ( sp->subname = talloc_strdup( sp, (subname) ? subname : "" ) )
)
{
dl_Init_Node( &sp->sb_Node, sp->subname, sp );
}
else
{
talloc_free( sp );
}
return sp;
}
void
sub_proc_free( struct sub_proc *sp )
{
talloc_free( sp );
return;
}
struct sub_proc *
sub_proc_start( const char *subname )
{
struct sub_proc *sp;
pid_t sub_pid;
if ( sp = sub_proc_alloc( subname ))
{
fflush(stdout);
fflush(stderr); /* not strictly needed, but wth */
sub_pid = fork();
if (sub_pid < 0)
{
diefmt( 9, "Unable to for for sub-process %s\n", (subname) ? subname : "" );
}else
if (sub_pid > 0)
{
sp->sub_pid = sub_pid;
}
}
return sp;
}
void
sub_proc_return( struct sub_proc *sp, int rc )
{
if (sp->sub_pid == (pid_t)0)
{
/* might need to flush feedback */
exit(rc);
}
return; /* doesn't get here unless someone got something wrong */
}
int
sub_proc_wait( struct sub_proc *sp )
{
if (sp->sub_pid == (pid_t)0)
return 0; /* we're the subproc */
if (sp->complete)
return 0; /* already done */
wait( sp->sub_pid, &sp->status, 0 );