Posts tagged ‘c’

Validating names in SSL certificates using OpenSSL (0.9.8)

Recently I’ve battled with OpenSSL at work. One thing I needed to do was add name validation to a program that previously hasn’t had it. In an attempt to avoid obvious mistakes I went looking for existing examples for how to do it. I came across some code from Secure Programming.com, it can be found in the code from the book in “/spc-1.1/chapter10/8-unix.c”. Just too bad only a part of the code actually works as advertised. On top of that the working part uses old functions which remain in the API only for backwards compatibility.

In trying to fix up that code I wrote the following little example code for extracting CN and subjectAltName:

#include <stdlib.h>
#include <stdio.h>
 
#include <openssl/pem.h>
#include <openssl/x509v3.h>
 
void getCN( X509 * );
void getSubjectAltName( X509 * );
 
int
main( int argc, char **argv )
{
    FILE *fpem;
    X509 *cert;
 
    if( !( fpem = fopen( argv[1], "r" ))) {
        fprintf( stderr, "Couldn't open the PEM file: %s\n", argv[1] );
        return( EXIT_FAILURE );
    }
 
    if( !( cert = PEM_read_X509( fpem, NULL, NULL, NULL ))) {
        fclose( fpem );
        fprintf( stderr, "Failed to read the PEM file: %s\n", argv[1] );
        return( EXIT_FAILURE );
    }
 
    getCN( cert );
    getSubjectAltName( cert );
 
    fclose( fpem );
    return( EXIT_SUCCESS );
}
 
void
getCN( X509 *cert )
{
    printf( "## %s\n", __PRETTY_FUNCTION__ );
 
    X509_NAME *subjName;
    int idx;
 
    if( !( subjName = X509_get_subject_name( cert )))
        fprintf( stderr, "X509_get_subject_name failed" );
 
    idx = X509_NAME_get_index_by_NID( subjName, NID_commonName, -1 );
    X509_NAME_ENTRY *entry = X509_NAME_get_entry( subjName, idx );
    ASN1_STRING *entryData = X509_NAME_ENTRY_get_data( entry );
    unsigned char *utf8;
    int length = ASN1_STRING_to_UTF8( &utf8, entryData );
    printf( "CN value: %s\n", utf8 );
    printf( "CN length: %d\n", length );
    OPENSSL_free( utf8 );
 
    return;
}
 
void getSubjectAltName( X509 *cert )
{
    printf( "## %s\n", __PRETTY_FUNCTION__ );
 
    GENERAL_NAMES *sANs;
 
    if( !( sANs = X509_get_ext_d2i( cert, NID_subject_alt_name, 0, 0 ))) {
        printf( "No subjectAltName extension\n" );
        return;
    }
 
    int i, numAN = sk_GENERAL_NAME_num( sANs );
    printf( "subjectAltName entries: %d\n", numAN );
    for( i = 0; i < numAN; ++i ) {
        GENERAL_NAME *sAN = sk_GENERAL_NAME_value( sANs, i );
        // we only care about DNS entries
        if( GEN_DNS == sAN->type ) {
            unsigned char *dns;
            ASN1_STRING_to_UTF8( &dns, sAN->d.dNSName );
            printf( "subjectAltName DNS: %s\n", dns );
            OPENSSL_free( dns );
        }
    }
 
    return;
}

Based on this I should be able to finish the patch I’ve been working on.

ctypes and flexible (zero-length) arrays

Dear lazyweb, I’ve been racking my brain trying to get information out of the following C struct in a nice way when using ctypes:

struct Foo
{
    unsigned int length;
    char name[];
};

I wrote a little C function to get instance of the struct easily into python:

struct Foo *
put_name(char *name)
{
    struct Foo *foo = malloc(sizeof(struct Foo) + strlen(name));
    foo->length = strlen(name);
    memcpy(foo->name, name, foo->length);
    return(foo);
}

Now, how do I actually get the full contents of Foo.name in python? The only way I could think of that actually works is to create a dummy-struct type in order to get the length out and then use it to dynamically create a new sub-class of ctypes.Structure, then create an instance based on the address of what was returned. I think the following shows it pretty clearly:

class FOO(Structure):
    _fields_ = [('length', c_uint), ('name', c_char * 0)]
 
liblib = cdll.LoadLibrary('./_build/liblib.so')
c_put_name = liblib.put_name
c_put_name.argtypes = [c_char_p]
c_put_name.restype = POINTER(FOO)
 
def put_name(str):
    f = c_put_name(str)
    K = type('FOO%s' % f.contents.length, (Structure,),
                        {'_fields_' : [('length', c_uint), ('name', c_char * f.contents.length)]})
    return K.from_address(addressof(f.contents))

I still think there ought to be some other way that ‘feels’ nicer. I mean the use of “short arrays” (declared as here with [], or zero size as supported by GCC, or the more portable array of size one) seems to be common enough to warrant some support from ctypes, right?

Any suggestions for improvements?

Banging my head against sparse files

Lately I’ve had use for sparse files to solve a problem. Simple, yes. Use lseek and write (or read). Even better, at least in this case, use pwrite and pread. Should be simple, right? Yes, should be.

I was banging my head against code equivalent to the following for quite a few hours:

#define _XOPEN_SOURCE 500
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

char buf[1024];

int
main(int argc, char **argv)
{
    int n;
    off_t off;

    for(n = 0; n < 1024; n++) {
        buf[n] = 'a';
    }

    int fd1;

    if(-1 == (fd1 = open("file1", O_WRONLY | O_CREAT, 0666)))
        error(EXIT_FAILURE, errno, "open (test1)");
    off = 0x80000000;
    printf("size: %d\n", sizeof(off));
    if(pwrite(fd1, buf, 1024, off) != 1024)
        error(EXIT_FAILURE, errno, "pwrite (%lli)", off);

    return(0);
}

Can you spot the problem?

Well, I can tell you it doesn’t work. off_t becomes 64-bit due to the #define _FILE_OFFSET_BITS 64 so the off variable isn’t negative in my code. Somehow however it becomes negative on the way into pwrite, and without a single compiler or linker error at that!

Have you spot the problem yet?

Here’s the correctly working code:

#define _XOPEN_SOURCE 500
#define _FILE_OFFSET_BITS 64
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

char buf[1024];

int
main(int argc, char **argv)
{
    int n;
    off_t off;

    for(n = 0; n < 1024; n++) {
        buf[n] = 'a';
    }

    int fd1;

    if(-1 == (fd1 = open("file1", O_WRONLY | O_CREAT, 0666)))
        error(EXIT_FAILURE, errno, "open (test1)");
    off = 0x80000000;
    printf("size: %d\n", sizeof(off));
    if(pwrite(fd1, buf, 1024, off) != 1024)
        error(EXIT_FAILURE, errno, "pwrite (%lli)", off);

    return(0);
}

Don’t see any difference? Look at the list of included files!

Let me just say the C and I aren’t on speaking terms at the moment!