Commit 4ed65553 authored by Shawn Webb's avatar Shawn Webb
Browse files

Initial commit



This code hasn't been tested. My next step is to write Kyua-based unit
tests.
Signed-off-by: Shawn Webb's avatarShawn Webb <shawn.webb@hardenedbsd.org>
parents
SHLIB= lattutil
SHLIB_MAJOR= 0
SRCS= config.c
INCS= liblattutil.h
.PATH: ${.CURDIR}/src
.PATH: ${.CURDIR}/include
CFLAGS+= -I${.CURDIR}/include
CFLAGS+= -I/usr/local/include
LDFLAGS+= -L/usr/local/lib
LDADD+= -lucl
.if defined(PREFIX)
INCLUDEDIR= ${PREFIX}/include
LIBDIR= ${PREFIX}/lib
.endif
.include <bsd.lib.mk>
/*-
* Copyright (c) 2021 Shawn Webb <shawn.webb@hardenedbsd.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LIBLATTUTIL_H
#define _LIBLATTUTIL_H
#include <stdbool.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <ucl.h>
#define EXPORTED_SYM __attribute__((visibility("default")))
/*
* Though we export the underlying data structure, using the API is
* preferred over directly accessing the ABI.
*/
typedef struct _llconfig {
struct stat l_sb;
char *l_path;
int l_fd;
struct ucl_parser *l_parser;
const ucl_object_t *l_rootobj;
} lattutil_config_path_t;
/**
* Find a configuration file in a set of given paths
*
* This function iterates through the set of paths, looking for the
* passed-in configuration file name. If the configuration file is
* found, a UCL parser instance is created and the file is loaded by
* UCL.
*
* @param Set of paths
* @param Number of paths in set
* @param Configuration file name
* @return Pointer to struct that contains information about the
* config file on success, NULL on error.
*/
lattutil_config_path_t *lattutil_find_config(const char **, size_t, const char *,
int);
/**
* Free a given lattutil_config_path_t object
*
* In order to prevent UAF vulnerabilities, the structure is zeroed
* after all its members have been freed. Additionally, the pointer to
* the structure is set to NULL.
*
* @param A pointer to the to-be-freed object
*/
void lattutil_free_config_path(lattutil_config_path_t **);
/**
* Return the fully-qualified path of the config file
*
* @param A pointer to the lattutil_config_path_t object
* @return The path of the config file
*/
char *lattutil_config_path_path(lattutil_config_path_t *);
/**
* Return the file descriptor of the opened config
*
* @param A pointer to the lattutil_config_path_t object
* @return The file descriptor
*/
int lattutil_config_path_fd(lattutil_config_path_t *);
/**
* Look for a string-typed variable in a UCL configuration tree.
*
* @param UCL object root
* @param Path within the UCL object root
* @param Default value to set if path is not found
* @return The value if found, default value or zero-length string on
* error.
*/
char *lattutil_find_config_string(const ucl_object_t *, const char *,
const char *);
/**
* Look for an integer-typed variable in a UCL configuration tree.
*
* @param UCL object root
* @param Path within the UCL object root
* @param Default value to set if path is not found
* @return The value if found, default value if not
*/
int64_t find_config_int(const ucl_object_t *, const char *, int64_t);
#endif /* !_LIBLATTUTIL_H */
*
!.gitignore
/*-
* Copyright (c) 2021 Shawn Webb <shawn.webb@hardenedbsd.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "liblattutil.h"
EXPORTED_SYM
lattutil_config_path_t *
lattutil_find_config(const char **paths, size_t npaths,
const char *filename, int flags)
{
lattutil_config_path_t *res;
size_t i, sz;
res = calloc(1, sizeof(*res));
if (res == NULL) {
return (NULL);
}
res->l_fd = -1;
for (i = 0; i < npaths; i++) {
sz = strlen(paths[i]) + strlen(filename) + 3;
res->l_path = calloc(1, sz);
if (res->l_path == NULL) {
return (res);
}
snprintf(res->l_path, sz-1, "%s/%s", paths[i], filename);
res->l_fd = open(res->l_path, flags);
if (res->l_fd < 0) {
free(res->l_path);
res->l_path = NULL;
continue;
}
if (fstat(res->l_fd, &(res->l_sb))) {
close(res->l_fd);
free(res->l_path);
res->l_path = NULL;
continue;
}
res->l_parser = ucl_parser_new(UCL_PARSER_KEY_LOWERCASE);
if (res->l_parser == NULL) {
free(res->l_path);
close(res->l_fd);
free(res);
return (NULL);
}
if (!ucl_parser_add_fd(res->l_parser, res->l_fd)) {
close(res->l_fd);
free(res->l_path);
res->l_path = NULL;
ucl_parser_free(res->l_parser);
res->l_parser = NULL;
continue;
}
res->l_rootobj = ucl_parser_get_object(res->l_parser);
break;
}
if (i == npaths) {
lattutil_free_config_path(&res);
}
return (res);
}
EXPORTED_SYM
void
lattutil_free_config_path(lattutil_config_path_t **obj)
{
if (obj == NULL || *obj == NULL) {
return;
}
free((*obj)->l_path);
(*obj)->l_path = NULL;
if ((*obj)->l_parser != NULL) {
ucl_parser_free((*obj)->l_parser);
(*obj)->l_parser = NULL;
}
if ((*obj)->l_fd >= 0) {
close((*obj)->l_fd);
(*obj)->l_fd = -1;
}
memset(*obj, 0, sizeof(**obj)); /* Prevent UAF */
free(*obj);
*obj = NULL; /* Prevent UAF */
}
EXPORTED_SYM
char *
lattutil_config_path_path(lattutil_config_path_t *path)
{
if (path == NULL) {
return (NULL);
}
return (path->l_path);
}
EXPORTED_SYM
int
lattutil_config_path_fd(lattutil_config_path_t *path)
{
if (path == NULL) {
return (-1);
}
return (path->l_fd);
}
EXPORTED_SYM
char *
lattutil_find_config_string(const ucl_object_t *root, const char *path,
const char *def)
{
const ucl_object_t *obj;
obj = ucl_object_lookup_path(root, path);
if (obj == NULL) {
if (def != NULL) {
return (strdup(def));
}
return (strdup(""));
}
return (strdup(""));
}
EXPORTED_SYM
int64_t
lattutil_find_config_int(const ucl_object_t *root, const char *path, int64_t def)
{
const ucl_object_t *obj;
int64_t res;
res = def;
obj = ucl_object_lookup_path(root, path);
if (obj != NULL) {
res = ucl_object_toint(obj);
}
return (res);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment