Last active
May 25, 2018 14:40
-
-
Save bijanebrahimi/377cc92ffe2c016e061baaef74950399 to your computer and use it in GitHub Desktop.
Distinguished-Name validator in pure C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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