# $Id$ # # Copyright (C) 2013--2014 Dragon Research Labs ("DRL") # Portions copyright (C) 2011--2012 Internet Systems Consortium ("ISC") # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notices and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND DRL AND ISC DISCLAIM ALL # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR # ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA # OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. """ Common Django ORM field classes. Many of these are complex ASN.1 DER objects stored as binaray data, since the only sane text representation would just be the Base64 encoding of the DER and thus would add no value. """ import logging from django.db import models import rpki.x509 import rpki.sundial logger = logging.getLogger(__name__) class EnumField(models.PositiveSmallIntegerField): """ An enumeration type that uses strings in Python and small integers in SQL. """ description = "An enumeration type" def __init__(self, *args, **kwargs): if isinstance(kwargs.get("choices"), (tuple, list)) and isinstance(kwargs["choices"][0], (str, unicode)): kwargs["choices"] = tuple(enumerate(kwargs["choices"], 1)) # Might need something here to handle string-valued default parameter models.PositiveSmallIntegerField.__init__(self, *args, **kwargs) self.enum_i2s = dict(self.flatchoices) self.enum_s2i = dict((v, k) for k, v in self.flatchoices) def from_db_value(self, value, expression, connection, context): return self.enum_i2s.get(value, value) def to_python(self, value): value = super(EnumField, self).to_python(value) return self.enum_i2s.get(value, value) def get_prep_value(self, value): return self.enum_s2i.get(value, value) class SundialField(models.DateTimeField): """ A field type for our customized datetime objects. """ description = "A datetime type using our customized datetime objects" def from_db_value(self, value, expression, connection, context): return self.to_python(value) def to_python(self, value): if isinstance(value, rpki.sundial.pydatetime.datetime): return rpki.sundial.datetime.from_datetime( models.DateTimeField.to_python(self, value)) else: return value def get_prep_value(self, value): if isinstance(value, rpki.sundial.datetime): return value.to_datetime() else: return value class BlobField(models.Field): """ Old BLOB field type, predating Django's BinaryField type. Do not use, this is only here for backwards compatabilty during migrations. """ description = "Raw BLOB type without ASN.1 encoding/decoding" def __init__(self, *args, **kwargs): self.blob_type = kwargs.pop("blob_type", None) kwargs["serialize"] = False kwargs["blank"] = True kwargs["default"] = None models.Field.__init__(self, *args, **kwargs) def deconstruct(self): name, path, args, kwargs = super(BlobField, self).deconstruct() del kwargs["serialize"] del kwargs["blank"] del kwargs["default"] return name, path, args, kwargs def db_type(self, connection): if self.blob_type is not None: return self.blob_type elif connection.settings_dict['ENGINE'] == "django.db.backends.mysql": return "LONGBLOB" elif connection.settings_dict['ENGINE'] == "django.db.backends.posgresql": return "bytea" else: return "BLOB" # For reasons which now escape me, I had a few fields in the old # hand-coded SQL which used MySQL type BINARY(20) to hold SKIs. # Presumably this was so that I could then use those SKIs in indexes # and searches, but apparently I never got around to that part. # # SKIs probably would be better stored as hex strings anyway, so not # bothering with a separate binary type model for this. Deal with # this if and when it ever becomes an issue. # DERField used to be a subclass of BlobField. Try changing it to be # a subclass of BinaryField instead, leave BlobField (for now) for # backwards compatability during migrations, class DERField(models.BinaryField): """ Field class for DER objects, with automatic translation between ASN.1 and Python types. This is an abstract class, concrete field classes are derived from it. """ rpki_type = rpki.x509.DER_object def __init__(self, *args, **kwargs): kwargs["blank"] = True kwargs["default"] = None super(DERField, self).__init__(*args, **kwargs) def deconstruct(self): name, path, args, kwargs = super(DERField, self).deconstruct() del kwargs["blank"] del kwargs["default"] return name, path, args, kwargs def from_db_value(self, value, expression, connection, context): if value is not None: value = self.rpki_type(DER = str(value)) return value def to_python(self, value): value = super(DERField, self).to_python(value) if value is not None and not isinstance(value, self.rpki_type): value = self.rpki_type(DER = str(value)) return value def get_prep_value(self, value): if value is not None: value = value.get_DER() return super(DERField, self).get_prep_value(value) class CertificateField(DERField): description = "X.509 certificate" rpki_type = rpki.x509.X509 class RSAPrivateKeyField(DERField): description = "RSA keypair" rpki_type = rpki.x509.RSA KeyField = RSAPrivateKeyField class PublicKeyField(DERField): description = "RSA keypair" rpki_type = rpki.x509.PublicKey class CRLField(DERField): description = "Certificate Revocation List" rpki_type = rpki.x509.CRL class PKCS10Field(DERField): description = "PKCS #10 certificate request" rpki_type = rpki.x509.PKCS10 class ManifestField(DERField): description = "RPKI Manifest" rpki_type = rpki.x509.SignedManifest class ROAField(DERField): description = "ROA" rpki_type = rpki.x509.ROA class GhostbusterField(DERField): description = "Ghostbuster Record" rpki_type = rpki.x509.Ghostbuster '>112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
/* serv.cpp - Minimal ssleay server for Unix
30.9.1996, Sampo Kellomaki <sampo@iki.fi> */
/* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b
Simplified to be even more minimal
12/98 - 4/99 Wade Scholine <wades@mail.cybg.com> */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <openssl/rsa.h> /* SSLeay stuff */
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* define HOME to be dir for key and cert files... */
#define HOME "./"
/* Make these what you want for cert & key files */
#define CERTF HOME "foo-cert.pem"
#define KEYF HOME "foo-cert.pem"
#define CHK_NULL(x) if ((x)==NULL) exit (1)
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); }
void main ()
{
int err;
int listen_sd;
int sd;
struct sockaddr_in sa_serv;
struct sockaddr_in sa_cli;
size_t client_len;
SSL_CTX* ctx;
SSL* ssl;
X509* client_cert;
char* str;
char buf [4096];
SSL_METHOD *meth;
/* SSL preliminaries. We keep the certificate and key with the context. */
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
meth = SSLv23_server_method();
ctx = SSL_CTX_new (meth);
if (!ctx) {
ERR_print_errors_fp(stderr);
exit(2);
}
if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(3);
}
if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(4);
}
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr,"Private key does not match the certificate public key\n");
exit(5);
}
/* ----------------------------------------------- */
/* Prepare TCP socket for receiving connections */
listen_sd = socket (AF_INET, SOCK_STREAM, 0); CHK_ERR(listen_sd, "socket");
memset (&sa_serv, '\0', sizeof(sa_serv));
sa_serv.sin_family = AF_INET;
sa_serv.sin_addr.s_addr = INADDR_ANY;
sa_serv.sin_port = htons (1111); /* Server Port number */
err = bind(listen_sd, (struct sockaddr*) &sa_serv,
sizeof (sa_serv)); CHK_ERR(err, "bind");
/* Receive a TCP connection. */
err = listen (listen_sd, 5); CHK_ERR(err, "listen");
client_len = sizeof(sa_cli);
sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
CHK_ERR(sd, "accept");
close (listen_sd);
printf ("Connection from %lx, port %x\n",
sa_cli.sin_addr.s_addr, sa_cli.sin_port);
/* ----------------------------------------------- */
/* TCP connection is ready. Do server side SSL. */
ssl = SSL_new (ctx); CHK_NULL(ssl);
SSL_set_fd (ssl, sd);
err = SSL_accept (ssl); CHK_SSL(err);
/* Get the cipher - opt */
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
/* Get client's certificate (note: beware of dynamic allocation) - opt */
client_cert = SSL_get_peer_certificate (ssl);
if (client_cert != NULL) {
printf ("Client certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t subject: %s\n", str);
OPENSSL_free (str);
str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0);
CHK_NULL(str);
printf ("\t issuer: %s\n", str);
OPENSSL_free (str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
X509_free (client_cert);
} else
printf ("Client does not have certificate.\n");
/* DATA EXCHANGE - Receive message and send reply. */
err = SSL_read (ssl, buf, sizeof(buf) - 1); CHK_SSL(err);
buf[err] = '\0';
printf ("Got %d chars:'%s'\n", err, buf);
err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); CHK_SSL(err);
/* Clean up. */
close (sd);
SSL_free (ssl);
SSL_CTX_free (ctx);
}
/* EOF - serv.cpp */