#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "conf.h"
#include "ipsec_num.h"
#include "isakmp_fld.h"
#include "libcrypto.h"
#include "log.h"
#include "x509.h"
static int x509_check_subjectaltname (u_char *, u_int, X509 *);
u_int32_t file_sz;
#if 0
static u_int8_t *
open_file (char *name)
{
int fd;
struct stat st;
u_int8_t *addr;
if (stat (name, &st) == -1)
log_fatal ("stat (\"%s\", &st)", name);
file_sz = st.st_size;
fd = open (name, O_RDONLY);
if (fd == -1)
log_fatal ("open (\"%s\", O_RDONLY)", name);
addr = mmap (0, file_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
fd, 0);
if (addr == MAP_FAILED)
log_fatal ("mmap (0, %d, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,"
"%d, 0)", file_sz, fd);
close (fd);
return addr;
}
#endif
static int
x509_check_subjectaltname (u_char *id, u_int id_len, X509 *scert)
{
const u_int8_t *altname;
u_int32_t altlen;
int type, idtype, ret;
type = x509_cert_subjectaltname (scert, &altname, &altlen);
if (!type)
{
log_print ("x509_check_subjectaltname: can't access subjectAltName");
return 0;
}
idtype = id[0];
id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
ret = 0;
switch (idtype)
{
case IPSEC_ID_IPV4_ADDR:
if (type == X509v3_IP_ADDR)
ret = 1;
break;
case IPSEC_ID_FQDN:
if (type == X509v3_DNS_NAME)
ret = 1;
break;
case IPSEC_ID_USER_FQDN:
if (type == X509v3_RFC_NAME)
ret = 1;
break;
default:
ret = 0;
break;
}
if (!ret)
{
LOG_DBG ((LOG_CRYPTO, 50,
"x509_check_subjectaltname: "
"our ID type (%d) does not match X509 cert ID type (%d)",
idtype, type));
return 0;
}
if (altlen != id_len || memcmp (altname, id, id_len) != 0)
{
LOG_DBG ((LOG_CRYPTO, 50,
"x509_check_subjectaltname: "
"our ID does not match X509 cert ID"));
return 0;
}
return 1;
}
int
main (int argc, char *argv[])
{
RSA *pub_key, *priv_key;
X509 *cert;
BIO *certfile, *keyfile;
EVP_PKEY *pkey_pub;
u_char ipaddr[6];
struct in_addr saddr;
char enc[256], dec[256];
u_int8_t idpayload[8];
int err, len;
if (argc < 3 || argc > 4)
{
fprintf (stderr, "usage: x509test private-key certificate ip-address\n");
exit (1);
}
printf ("Reading private key %s\n", argv[1]);
keyfile = BIO_new (BIO_s_file ());
if (BIO_read_filename (keyfile, argv[1]) == -1)
{
perror ("read");
exit (1);
}
#if SSLEAY_VERSION_NUMBER >= 0x00904100L
priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL, NULL);
#else
priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL);
#endif
BIO_free (keyfile);
if (priv_key == NULL)
{
printf("PEM_read_bio_RSAPrivateKey () failed\n");
exit (1);
}
printf ("Reading ssleay created certificate %s\n", argv[2]);
certfile = BIO_new (BIO_s_file ());
if (BIO_read_filename (certfile, argv[2]) == -1)
{
perror ("read");
exit (1);
}
#if SSLEAY_VERSION_NUMBER >= 0x00904100L
cert = PEM_read_bio_X509 (certfile, NULL, NULL, NULL);
#else
cert = PEM_read_bio_X509 (certfile, NULL, NULL);
#endif
BIO_free (certfile);
if (cert == NULL)
{
printf("PEM_read_bio_X509 () failed\n");
exit (1);
}
pkey_pub = X509_get_pubkey (cert);
pub_key = EVP_PKEY_get0_RSA (pkey_pub);
if (pub_key == NULL)
{
exit (1);
}
printf ("Testing RSA keys: ");
err = 0;
strlcpy (dec, "Eine kleine Testmeldung", 256);
if ((len = RSA_private_encrypt (strlen (dec), dec, enc, priv_key,
RSA_PKCS1_PADDING)) == -1)
printf ("SIGN FAILED ");
else
err = RSA_public_decrypt (len, enc, dec, pub_key, RSA_PKCS1_PADDING);
if (err == -1 || strcmp (dec, "Eine kleine Testmeldung"))
printf ("SIGN/VERIFY FAILED");
else
printf ("OKAY");
printf ("\n");
printf ("Validate SIGNED: ");
err = X509_verify (cert, pkey_pub);
printf ("X509 verify: %d ", err);
if (err == -1)
printf ("FAILED ");
else
printf ("OKAY ");
printf ("\n");
if (argc == 4)
{
printf ("Verifying extension: ");
if (inet_aton (argv[3], &saddr) == 0)
{
printf ("inet_aton () failed\n");
exit (1);
}
saddr.s_addr = htonl (saddr.s_addr);
ipaddr[0] = 0x87;
ipaddr[1] = 0x04;
ipaddr[2] = saddr.s_addr >> 24;
ipaddr[3] = (saddr.s_addr >> 16) & 0xff;
ipaddr[4] = (saddr.s_addr >> 8) & 0xff;
ipaddr[5] = saddr.s_addr & 0xff;
bzero (idpayload, sizeof idpayload);
idpayload[0] = IPSEC_ID_IPV4_ADDR;
bcopy (ipaddr + 2, idpayload + 4, 4);
if (!x509_check_subjectaltname (idpayload, sizeof idpayload, cert))
printf("FAILED ");
else
printf("OKAY ");
printf ("\n");
}
return 1;
}