Skip to content

Instantly share code, notes, and snippets.

@vjt
Created August 26, 2009 15:51
Show Gist options
  • Save vjt/175596 to your computer and use it in GitHub Desktop.
Save vjt/175596 to your computer and use it in GitHub Desktop.
.*.sw?
verify-cn
all:
gcc -Wall -Werror -static -s verify-cn.c -o verify-cn
install:
install -o root -g openvpn -m 510 verify-cn /etc/openvpn/empty/verify-cn
clean:
rm -f verify-cn
/**
* Quick & dirty verify-cn software for OpenVPN tls-verify directive
* that checks CNs agains a flat text file. CNs are separated by new
* line characters, maximum line lenghth is 256 characters. Example:
*
* 0/C=IT/ST=RM/L=Rome/O=Some_org/OU=VPN/CN=voyager.nirvana.local/[email protected]
*
* The leading 0 is the certificate depth in the certification chain.
*
* This source can be statically compiled and placed into an OpenVPN
* chroot, without worrying about bash or libraries. The only file
* that needs to be present is the CN flat-file, and if you want
* to syslog, also create a "dev" directory and place a syslog socket
* inside it (on Linux, by adding a -a /path/to/chroot/dev/log command
* line option to syslogd.
*
* 2009-2010 [email protected] - Released in the Public Domain
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
#include <limits.h>
#define MAXLINELEN 256
#define CNFILE "users.txt"
#define SYSLOG_IDENT "verify-cn"
extern int errno;
char *chomp (char *str)
{
int len = strlen (str) - 1;
if (str[len] == '\n')
str[len] = '\0';
return str;
}
int parse_depth (char *s)
{
int ret = 0;
char *endptr = NULL;
if (*s == '\0')
return -1;
ret = strtoul (s, &endptr, 10);
if (*endptr != '\0' || errno == ERANGE)
return -1;
return ret;
}
char *parse_cn (int depth, char *cn)
{
// depth decimal cn \0
int len = (depth / 10 + 1) + strlen (cn) + 1;
char *ret = malloc (len);
memset (ret, 0x0, len);
snprintf (ret, len, "%d%s", depth, cn);
return ret;
}
#define ERR_IF( condition, message ) do { \
if (condition) { syslog (LOG_ERR, message); goto error; } \
} while (0)
int main (int argc, char **argv)
{
int depth;
char *cn;
FILE *users;
char *user = calloc (MAXLINELEN, sizeof (char));
// Open syslog connection
openlog (SYSLOG_IDENT, LOG_PID|LOG_NDELAY, LOG_AUTH);
// Check arguments
ERR_IF (argc < 3, "Wrong number of arguments");
// Parse arguments
depth = parse_depth (argv[1]);
ERR_IF (depth < 0, "Invalid depth");
cn = parse_cn (depth, argv[2]);
// Open user database
users = fopen (CNFILE, "r");
ERR_IF (!users, "Cannot open users file: %m");
// Check the passed cn against the db
while (fgets (user, MAXLINELEN-1, users))
{
if (strncmp (chomp (user), cn, MAXLINELEN) == 0)
{
syslog (LOG_WARNING, "Authorized CN %s", cn);
return EXIT_SUCCESS;
}
}
syslog (LOG_WARNING, "Failed authorization of CN %s", cn);
error:
return EXIT_FAILURE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment