Records

Records are the fundamental unit used to store additional data attached to a certificate (e.g. roles, grants, user data, etc.) Records are key / value pairs. The key and value are both optional, and may contain either string or binary data.

Records are organised by section. Each section begins with a 'section header' record, which must use a NULL-terminated string containing the name of the section as its key.

Section names beginning with an underscore are reserved for internal use by the library.

If a section name is prefixed by '$', then all records in that section (including the section header) must be signed. Certificates containing a NOSIGN record in such a section will not validate.

API

ec_record_create()

ec_record_t *ec_record_create(uint16_t flags, char *key, unsigned char *data, uint16_t data_len);

Create a new record. Returns a pointer to the new record, or NULL on failure. key must be a NULL-terminated string.

Records created with ec_record_create() must be freed using ec_record_destroy() once they are no longer required, unless they are attached to a certificate. All records attached to a certificate are automatically freed when the certificate is destroyed.

flags is used to set additional metadata on the record, according to the following table:

#include <ec.h>
...
ec_record_t *r = ec_record_create(EC_RECORD_NOSIGN | EC_RECORD_DCOPY, "my_key", my_data,
    my_data_length);
if(r == NULL) {
    //failed to create record
}
...

ec_record_bin()

ec_record_t *ec_record_bin(uint16_t flags, unsigned char *key, uint8_t key_len, unsigned char *data, uint16_t data_len);

Identical to ec_record_create(), except using a binary key.

ec_record_str()

ec_record_t *ec_record_str(uint16_t flags, char *key, char *data);

Identical to ec_record_create(), except data is a NULL-terminated string.

ec_record_destroy()

void ec_record_destroy(ec_record_t *r);

Destroy a record. If EC_RECORD_KFREE / EC_RECORD_DFREE are set, then also free the record's key / data respectively.

#include <ec.h>
...
ec_record_destroy(r);
...

ec_record_add()

ec_record_t *ec_record_add(ec_cert_t *c, char *section, ec_record_t *r);

Add a record to a certificate. Returns r on success, NULL otherwise.

The record will be added to the section referred to by section, and the section will be created if it does not already exist. If EC_RECORD_SECTION is set, then section will be ignored and the record will be treated as a section header.

#include <ec.h>
...
if(ec_record_add(c, "my_section", my_record) == NULL) {
    //failed to add record
}
...

ec_record_remove()

ec_record_t *ec_record_remove(ec_cert_t *c, ec_record_t *r);

Remove a record from a certificate, if present. Always returns r.

#include <ec.h>
...
ec_record_remove(c, r);
...

ec_record_remove_section()

void ec_record_remove_section(ec_cert_t *c, char *section, ec_freefn_t freefn);

Remove an entire section and all its child records from a certificate, if present.

If freefn is provided, it will be run once for each removed record, after that record is removed. If freefn is NULL, then nothing will be run on the removed records, and you should destroy them manually if they are no longer required.

#include <ec.h>
...
ec_record_remove_section(c, "mySection", (ec_freefn_t)ec_record_destroy);
...

ec_record_match()

ec_record_t *ec_record_match(ec_record_t *start, char *section, uint16_t flags, char *key, unsigned char *data, uint16_t data_len);

Find the first matching record in a record list. key must be a NULL-terminated string. All provided flags must be present in a record for it to match. section must be defined unless searching for a section header, in which case it should be NULL.

#include <ec.h>
...
ec_record_t *list = ec_cert_records(c);
ec_record_t *r = ec_record_match(list, "my_section", EC_RECORD_NOSIGN,
    "my_record", NULL, 0);
if(r != NULL) {
    //found a matching record
}
...

ec_record_match_bin()

ec_record_t *ec_record_match_bin(ec_record_t *start, char *section, uint16_t flags, unsigned char *key, uint8_t key_len, unsigned char *data, uint16_t data_len);

Identical to ec_record_match(), except using a binary key.

ec_record_match_str()

ec_record_t *ec_record_match_str(ec_record_t *start, char *section, uint16_t flags, char *key, char *data);

Identical to ec_record_match(), except data is a NULL-terminated string.

ec_record_next()

ec_record_t *ec_record_next(ec_record_t *start, int filter);

Get the next matching record in the same section. The next record that matches start is returned, or NULL if no matching record is found.

filter specifies which aspects of a record must match, according to the following table:

#include <ec.h>
...
ec_record_t *next = ec_record_next(r, EC_MATCH_FLAGS | EC_MATCH_KEY);
if(next !== NULL) {
    //found a matching record
}
...

ec_record_set()

ec_record_t *ec_record_set(ec_cert_t *c, char *section, uint16_t flags, char *key, char *data);

Identical to ec_record_add(c, section, ec_record_str(flags, key, data));

ec_record_get()

char *ec_record_get(ec_record_t *start, char *section, uint16_t flags, char *key);

Get the NULL-terminated data field from a matching record. Returns NULL if not found, or if the data field is not NULL-terminated.

#include <ec.h>
...
ec_record_t *list = ec_cert_records(c);
char *s = ec_record_get(list, "my_section", EC_RECORD_NOSIGN, "my_record");
if(s != NULL) {
    //found a valid matching string
}
...

ec_record_section()

char *ec_record_section(ec_record_t *r);

Get the name for the section to which the record belongs. Returns the section name if present, or NULL if the record is not associated with a section, or is a section header.

#include <ec.h>
...
char *section_name = ec_record_section(r);
if(section_name != NULL) {
    //record has a valid section name
}
...

ec_record_section_flags()

void ec_record_section_flags(ec_cert_t *c, char *section, uint16_t flags);

Bulk-set additional flags for an entire section, if the section exists.

#include <ec.h>
...
ec_record_section_flags(c, "mySection", EC_CERT_NOSIGN);
...

ec_record_data()

unsigned char *ec_record_data(ec_record_t *r);

Get a pointer to a record's data buffer. Returns NULL if r is NULL.

#include <ec.h>
...
unsigned char *buf = ec_record_data(r);
...

ec_record_buf()

unsigned char *ec_record_buf(ec_cert_t *c, char *section, char *key, size_t length, uint16_t flags);

Quickly get or create a record-backed buffer of at least length bytes. Returns NULL on error.

If the record already exists, but the buffer is smaller than length, or some of the flags are unset, this is considered an error. Otherwise, the existing record is used as-is without alteration, and the data buffer is returned.

If the record does not exist, then a new record is created with a zero-initialised buffer of the desired length, and flags will be added to the default.

#include <ec.h>
...
unsigned char *buf = ec_record_buf(c, "mySection", "myRecord", 500, EC_RECORD_NOSIGN);
if(buf != NULL) {
    //successfully created a 500-byte buffer
}
...

Last updated