Skip to content

Instantly share code, notes, and snippets.

@bijanebrahimi
Last active May 25, 2018 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bijanebrahimi/377cc92ffe2c016e061baaef74950399 to your computer and use it in GitHub Desktop.
Save bijanebrahimi/377cc92ffe2c016e061baaef74950399 to your computer and use it in GitHub Desktop.
Distinguished-Name validator in pure C
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define PARSER_KEY 0x001
#define PARSER_VALUE 0x002
#define PARSER_ESC 0x004
#define PARSER_SPACE 0x008
#define KEY_DC ((0x4443))
#define KEY_CN ((0x434e))
#define KEY_OU ((0x4f55))
#define KEY_O ((0x4f))
#define KEY_STREET ((0x535452454554))
#define KEY_ST ((0x5354))
#define KEY_L ((0x4c))
#define KEY_C ((0x43))
#define KEY_UID ((0x554944))
char *dn_validator(char *str, const char **err);
int
main(int argc, char **argv)
{
char *p, *dn;
const char *err = NULL;
if (argc != 2) {
fprintf(stderr, "Usage: %s \"DistinguishedName\"\n", argv[0]);
return -1;
}
if ((dn = strdup(argv[1])) == NULL) {
return -1;
}
if ((p = dn_validator(argv[1], &err))) {
fprintf(stderr, "%s: '%s'\n", err, p);
return -1;
}
free(dn);
return 0;
}
char *
dn_validator(char *str, const char **err)
{
char *key = NULL, *value = NULL, *p;
u_char parser = PARSER_KEY;
u_int64_t key_magic = 0;
p = str;
while (1) {
if (parser & PARSER_KEY) {
if (!key) {
key = p;
value = NULL;
}
if (*p != '=')
key_magic = (key_magic << 8 | toupper(*p));
} else if ((parser & PARSER_VALUE) && !value) {
if (*p == ' ' || *p == '#') {
*err = "Invalid character";
return p;
}
value = p;
}
if (parser & PARSER_ESC && *p == ',')
goto escaped;
switch(*p) {
case 0x3d: // equal sign
if (!key || value || parser & PARSER_ESC) {
*err = "Invalid character";
return p;
}
*p = '\0';
parser = PARSER_VALUE;
break;
case 0x00: // EOL
case 0x2c: // separator comma
if (!key || !value) {
*err = (!key)? "Missing Key": "Missing Value";
return p;
}
if (parser & (PARSER_ESC | PARSER_SPACE)) {
*err = "Invalid character";
return p;
}
switch (key_magic) {
case KEY_DC:
case KEY_CN:
case KEY_OU:
case KEY_O:
case KEY_STREET:
case KEY_ST:
case KEY_L:
case KEY_C:
case KEY_UID:
break;
case 0x00:
*err = "Missing Key";
return p;
default:
*err = "Invalid key";
return key;
}
parser = PARSER_KEY;
key = value = NULL;
key_magic = 0;
if (*p == '\0')
goto done;
*p = '\0';
break;
case 0x5c: // backslash
if (!(parser & PARSER_ESC)) {
parser |= PARSER_ESC;
break;
}
case 0x0a: // CR
case 0x0d: // LF
case 0x22: // "
case 0x27: // '
case 0x2b: // +
case 0x2f: // slash
case 0x3b: // ;
case 0x3c: // <
case 0x3e: // >
if (!(parser & PARSER_ESC)) {
*err = "Invalid character";
return p;
}
case 0x20 ... 0x21:
case 0x23 ... 0x26:
case 0x28 ... 0x2a:
case 0x2d ... 0x2e:
case 0x30 ... 0x3a:
case 0x3f ... 0x5b:
case 0x5d ... 0x7e:
if (*p == ' ' && !(parser & PARSER_ESC))
parser |= PARSER_SPACE;
else
parser &= ~PARSER_SPACE;
if (*p == '\\' && !(parser & PARSER_ESC))
parser = PARSER_ESC;
else if (parser & PARSER_ESC) /* ASCII escaped */
escaped:
parser &= ~PARSER_ESC;
break;
default:
*err = "Invalid character";
return p;
}
p++;
}
done:
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment