Browse Source

Simple engine using HAL, XML parser, test application.

master
Andrea Luzzardi 17 years ago
parent
commit
bbb7a5d53d
11 changed files with 770 additions and 0 deletions
  1. +17
    -0
      pam_usb/src/Makefile
  2. +169
    -0
      pam_usb/src/conf.c
  3. +53
    -0
      pam_usb/src/conf.h
  4. +42
    -0
      pam_usb/src/conf.xml
  5. +159
    -0
      pam_usb/src/hal.c
  6. +23
    -0
      pam_usb/src/hal.h
  7. +47
    -0
      pam_usb/src/log.c
  8. +25
    -0
      pam_usb/src/log.h
  9. +54
    -0
      pam_usb/src/test.c
  10. +152
    -0
      pam_usb/src/xpath.c
  11. +29
    -0
      pam_usb/src/xpath.h

+ 17
- 0
pam_usb/src/Makefile View File

@ -0,0 +1,17 @@
SRC = test.c \
conf.c \
log.c \
xpath.c \
hal.c
OBJ = $(SRC:.c=.o)
NAME = test
CC = gcc
CFLAGS = -Wall `pkg-config --cflags hal` `pkg-config --cflags libxml-2.0`
LDFLAGS = `pkg-config --libs hal` `pkg-config --libs libxml-2.0`
all : $(NAME)
$(NAME) : $(OBJ)
$(CC) -o $(NAME) $(LDFLAGS) $(OBJ)
clean :
rm -f $(OBJ)

+ 169
- 0
pam_usb/src/conf.c View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "conf.h"
#include "xpath.h"
#include "log.h"
static void pusb_conf_options_get_from(t_pusb_options *opts,
const char *from,
xmlDoc *doc)
{
pusb_xpath_get_string_from(doc, from, "option[@name='hostname']",
opts->hostname, sizeof(opts->hostname));
pusb_xpath_get_bool_from(doc, from, "option[@name='debug']",
&(opts->debug));
pusb_xpath_get_bool_from(doc, from, "option[@name='enable']",
&(opts->enable));
pusb_xpath_get_bool_from(doc, from, "option[@name='try_otp']",
&(opts->try_otp));
pusb_xpath_get_bool_from(doc, from, "option[@name='enforce_otp']",
&(opts->enforce_otp));
}
static int pusb_conf_parse_options(t_pusb_options *opts,
xmlDoc *doc,
const char *user,
const char *service)
{
char *xpath = NULL;
size_t xpath_size;
int i;
struct s_opt_list opt_list[] = {
{ CONF_DEVICE_XPATH, opts->device.name },
{ CONF_USER_XPATH, (char *)user },
{ CONF_SERVICE_XPATH, (char *)service },
{ NULL, NULL }
};
pusb_conf_options_get_from(opts, "//configuration/defaults/", doc);
for (i = 0; opt_list[i].name != NULL; ++i)
{
xpath_size = strlen(opt_list[i].name) + strlen(opt_list[i].value) + 1;
if (!(xpath = malloc(xpath_size)))
{
log_error("malloc error\n");
return (0);
}
memset(xpath, 0x00, xpath_size);
snprintf(xpath, xpath_size, opt_list[i].name, opt_list[i].value, "");
pusb_conf_options_get_from(opts, xpath, doc);
free(xpath);
}
return (1);
}
static int pusb_conf_device_get_property(t_pusb_options *opts,
xmlDoc *doc,
const char *property,
char *store,
size_t size)
{
char *xpath = NULL;
size_t xpath_len;
int retval;
xpath_len = strlen(CONF_DEVICE_XPATH) + strlen(opts->device.name) + \
strlen(property) + 1;
if (!(xpath = malloc(xpath_len)))
{
log_error("malloc error!\n");
return (0);
}
memset(xpath, 0x00, xpath_len);
snprintf(xpath, xpath_len, CONF_DEVICE_XPATH, opts->device.name,
property);
retval = pusb_xpath_get_string(doc, xpath, store, size);
free(xpath);
return (retval);
}
static int pusb_conf_parse_device(t_pusb_options *opts, xmlDoc *doc)
{
log_debug("Parsing settings...\n");
if (!pusb_conf_device_get_property(opts, doc, "vendor", opts->device.vendor,
sizeof(opts->device.vendor)))
return (0);
if (!pusb_conf_device_get_property(opts, doc, "model", opts->device.model,
sizeof(opts->device.model)))
return (0);
if (!pusb_conf_device_get_property(opts, doc, "serial", opts->device.serial,
sizeof(opts->device.serial)))
return (0);
return (1);
}
int pusb_conf_init(t_pusb_options *opts)
{
memset(opts, 0x00, sizeof(*opts));
if (gethostname(opts->hostname, sizeof(opts->hostname)) == -1)
{
log_error("gethostname: %s\n", strerror(errno));
return (0);
}
opts->enable = 1;
opts->try_otp = 1;
opts->enforce_otp = 0;
opts->debug = 0;
return (1);
}
int pusb_conf_parse(const char *file, t_pusb_options *opts,
const char *user, const char *service)
{
xmlDoc *doc = NULL;
int retval;
char device_xpath[sizeof(CONF_USER_XPATH) + CONF_USER_MAXLEN + \
sizeof("device")];
if (strlen(user) > CONF_USER_MAXLEN)
{
log_error("Username \"%s\" is too long (max: %d)\n", user,
CONF_USER_MAXLEN);
return (0);
}
if (!(doc = xmlReadFile(file, NULL, 0)))
{
log_error("Unable to parse \"%s\"\n", file);
return (0);
}
snprintf(device_xpath, sizeof(device_xpath), CONF_USER_XPATH, user,
"device");
retval = pusb_xpath_get_string(doc,
device_xpath,
opts->device.name,
sizeof(opts->device.name));
if (!retval || !pusb_conf_parse_device(opts, doc))
{
log_error("No device found for user \"%s\"\n", user);
xmlFreeDoc(doc);
xmlCleanupParser();
return (0);
}
if (!pusb_conf_parse_options(opts, doc, user, service))
{
xmlFreeDoc(doc);
xmlCleanupParser();
return (0);
}
xmlFreeDoc(doc);
xmlCleanupParser();
return (1);
}

+ 53
- 0
pam_usb/src/conf.h View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PUSB_CONF_H_
# define PUSB_CONF_H_
# define CONF_DEVICE_XPATH "//configuration/devices/device[@id='%s']/%s"
# define CONF_USER_XPATH "//configuration/users/user[@id='%s']/%s"
# define CONF_SERVICE_XPATH "//configuration/services/service[@id='%s']/%s"
# define CONF_USER_MAXLEN 32
typedef struct pusb_device
{
char name[32];
char vendor[32];
char model[32];
char serial[64];
} t_pusb_device;
typedef struct pusb_options
{
int enable;
int try_otp;
int enforce_otp;
int debug;
char hostname[32];
t_pusb_device device;
} t_pusb_options;
struct s_opt_list
{
char *name;
char *value;
};
int pusb_conf_init(t_pusb_options *opts);
int pusb_conf_parse(const char *file, t_pusb_options *opts,
const char *user, const char *service);
#endif /* !PUSB_CONF_H_ */

+ 42
- 0
pam_usb/src/conf.xml View File

@ -0,0 +1,42 @@
<configuration>
<defaults>
<option name="hostname">foobar</option>
<option name="debug">true</option>
<option name="try_otp">true</option>
<option name="enforce_otp">false</option>
</defaults>
<devices>
<device id="foobar">
<vendor>SanDisk Corp.</vendor>
<model>Cruzer Titanium</model>
<serial>SNDKB882652FC4A03701</serial>
</device>
</devices>
<users>
<user id="scox">
<device>foobar</device>
</user>
<user id="root">
<device>foobar</device>
<option name="enforce_otp">true</option>
</user>
</users>
<services>
<!-- Disable pam_usb for sshd (nonsense) -->
<service id="ssh">
<option name="enable">false</option>
</service>
<!-- Speed up 'login' authentication by disabling one time pads.
This setting will not affect user 'root' as he/she is
enforcing one time pads (enforce_otp).
-->
<service id="login">
<option name="try_otp">false</option>
</service>
</services>
</configuration>

+ 159
- 0
pam_usb/src/hal.c View File

@ -0,0 +1,159 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <dbus/dbus.h>
#include <libhal.h>
#include "conf.h"
#include "log.h"
static DBusConnection *pusb_hal_dbus_connect(void)
{
DBusConnection *dbus = NULL;
DBusError error;
dbus_error_init(&error);
if (!(dbus = dbus_bus_get(DBUS_BUS_SYSTEM, &error)))
{
log_error("Cannot connect to system bus: %s\n",
error.message);
dbus_error_free(&error);
return (NULL);
}
return (dbus);
}
static void pusb_hal_dbus_disconnect(DBusConnection *dbus)
{
dbus_connection_close(dbus);
dbus_connection_unref(dbus);
dbus_shutdown();
}
static LibHalContext *pusb_hal_init(DBusConnection *dbus)
{
DBusError error;
LibHalContext *ctx = NULL;
dbus_error_init(&error);
if (!(ctx = libhal_ctx_new()))
{
log_error("Failed to create a HAL context\n");
return (NULL);
}
if (!libhal_ctx_set_dbus_connection(ctx, dbus))
{
log_error("Failed to attach dbus connection to hal\n");
libhal_ctx_free(ctx);
return (NULL);
}
if (!libhal_ctx_init(ctx, &error))
{
log_error("libhal_ctx_init: %s\n", error.name, error.message);
libhal_ctx_free(ctx);
return (NULL);
}
return (ctx);
}
static int pusb_hal_verify_model(LibHalContext *ctx,
t_pusb_options *opts,
const char *udi)
{
DBusError error;
char *data;
int i;
struct s_opt_list check_list[] = {
{ "usb_device.vendor", opts->device.vendor },
{ "info.product", opts->device.model },
{ NULL, NULL }
};
log_debug("Verifying model...\n");
dbus_error_init(&error);
for (i = 0; check_list[i].name; ++i)
{
data = libhal_device_get_property_string(ctx, udi,
check_list[i].name,
&error);
if (!data)
{
log_error("Cannot retrieve device %s: %s\n",
check_list[i].name,
error.message);
dbus_error_free(&error);
return (0);
}
if (strcmp(data, check_list[i].value) != 0)
{
log_error("[KO]\t%s -> %s\n", check_list[i].name, data);
libhal_free_string(data);
return (0);
}
log_debug("[OK]\t%s -> %s \n", check_list[i].name, data);
libhal_free_string(data);
}
return (1);
}
static int pusb_hal_find_device(LibHalContext *ctx,
t_pusb_options *opts)
{
DBusError error;
char **devices;
int n_devices;
int retval = 0;
dbus_error_init(&error);
if (!(devices = libhal_manager_find_device_string_match(ctx,
"usb_device.serial",
opts->device.serial,
&n_devices,
&error)))
{
log_error("Unable to find device \"%s\": %s\n", opts->device.name,
error.message);
dbus_error_free(&error);
return (0);
}
if (n_devices > 0)
{
log_debug("Device \"%s\" connected (S/N: %s)\n", opts->device.name,
opts->device.serial);
retval = pusb_hal_verify_model(ctx, opts, devices[0]);
}
else
log_error("Device \"%s\" not connected\n", opts->device.name);
libhal_free_string_array(devices);
return (retval);
}
int pusb_hal_device_check(t_pusb_options *opts)
{
DBusConnection *dbus;
LibHalContext *ctx;
int retval;
if (!(dbus = pusb_hal_dbus_connect()))
return (0);
if (!(ctx = pusb_hal_init(dbus)))
return (0);
retval = pusb_hal_find_device(ctx, opts);
pusb_hal_dbus_disconnect(dbus);
libhal_ctx_free(ctx);
return (retval);
}

+ 23
- 0
pam_usb/src/hal.h View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef HAL_H_
# define HAL_H_
int pusb_hal_device_check(t_pusb_options *opts);
#endif /* !HAL_H_ */

+ 47
- 0
pam_usb/src/log.c View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdarg.h>
#include "log.h"
void log_debug(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
void log_error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
void log_verbose(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}

+ 25
- 0
pam_usb/src/log.h View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef LOG_H_
# define LOG_H_
void log_debug(const char *fmt, ...);
void log_error(const char *fmt, ...);
void log_verbose(const char *fmt, ...);
#endif /* !LOG_H_ */

+ 54
- 0
pam_usb/src/test.c View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include "conf.h"
#include "hal.h"
#include "log.h"
static void pusb_dump_conf(t_pusb_options *opts)
{
printf("\nConfiguration dump:\n");
printf("enable:\t\t%d\n", opts->enable);
printf("try_otp:\t%d\n", opts->try_otp);
printf("enforce_otp:\t%d\n", opts->enforce_otp);
printf("debug:\t\t%d\n", opts->debug);
printf("hostname:\t%s\n", opts->hostname);
}
int main(int argc, char **argv)
{
t_pusb_options opts;
if (argc < 3)
{
printf("Usage: %s <username> <service>\n", argv[0]);
return (1);
}
pusb_conf_init(&opts);
if (!pusb_conf_parse("conf.xml", &opts, argv[1], argv[2]))
return (0);
pusb_dump_conf(&opts);
if (!opts.enable)
{
printf("not enabled, exiting\n");
return (0);
}
printf("\n");
printf ("Access %s.\n", pusb_hal_device_check(&opts) ? "granted" : "denied");
return (0);
}

+ 152
- 0
pam_usb/src/xpath.c View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <libxml/xpath.h>
#include <string.h>
#include "xpath.h"
#include "log.h"
static xmlXPathObject *pusb_xpath_match(xmlDocPtr doc, const char *path)
{
xmlXPathContext *context = NULL;
xmlXPathObject *result = NULL;
context = xmlXPathNewContext(doc);
if (context == NULL)
{
log_error("Unable to create XML context\n");
return (NULL);
}
result = xmlXPathEvalExpression((xmlChar *)path, context);
xmlXPathFreeContext(context);
if (result == NULL)
{
log_error("Error in xmlXPathEvalExpression\n");
return (NULL);
}
if (xmlXPathNodeSetIsEmpty(result->nodesetval))
{
xmlXPathFreeObject(result);
return (NULL);
}
return (result);
}
int pusb_xpath_get_string(xmlDocPtr doc, const char *path,
char *value, size_t size)
{
xmlXPathObject *result = NULL;
xmlNode *node = NULL;
xmlChar *result_string = NULL;
if (!(result = pusb_xpath_match(doc, path)))
return (0);
if (result->nodesetval->nodeNr > 1)
{
xmlXPathFreeObject(result);
log_debug("Syntax error: %s: more than one record found\n", path);
return (0);
}
node = result->nodesetval->nodeTab[0]->xmlChildrenNode;
result_string = xmlNodeListGetString(doc, node, 1);
if (strlen((const char *)result_string) + 1 > size)
{
xmlFree(result_string);
xmlXPathFreeObject(result);
log_debug("Result for %s (%s) is too long (max: %d)\n",
path, (const char *)result_string, size);
return (0);
}
memset(value, '\0', size);
strncpy(value, (const char *)result_string, size);
xmlFree(result_string);
xmlXPathFreeObject(result);
return (1);
}
int pusb_xpath_get_string_from(xmlDocPtr doc,
const char *base,
const char *path,
char *value, size_t size)
{
char *xpath = NULL;
size_t xpath_size;
int retval;
xpath_size = strlen(base) + strlen(path) + 1;
if (!(xpath = malloc(xpath_size)))
{
log_error("malloc error !\n");
return (0);
}
memset(xpath, 0x00, xpath_size);
snprintf(xpath, xpath_size, "%s%s", base, path);
retval = pusb_xpath_get_string(doc, xpath, value, size);
if (retval)
log_debug("%s%s -> %s\n", base, path, value);
free(xpath);
return (retval);
}
int pusb_xpath_get_bool(xmlDocPtr doc, const char *path, int *value)
{
char ret[6]; /* strlen("false") + 1 */
if (!pusb_xpath_get_string(doc, path, ret, sizeof(ret)))
return (0);
if (!strcmp(ret, "true"))
{
*value = 1;
return (1);
}
if (!strcmp(ret, "false"))
{
*value = 0;
return (1);
}
log_debug("Expecting a boolean, got %s\n", ret);
return (0);
}
int pusb_xpath_get_bool_from(xmlDocPtr doc,
const char *base,
const char *path,
int *value)
{
char *xpath = NULL;
size_t xpath_size;
int retval;
xpath_size = strlen(base) + strlen(path) + 1;
if (!(xpath = malloc(xpath_size)))
{
log_error("malloc error!\n");
return (0);
}
memset(xpath, 0x00, xpath_size);
snprintf(xpath, xpath_size, "%s%s", base, path);
retval = pusb_xpath_get_bool(doc, xpath, value);
free(xpath);
if (retval)
log_debug("%s%s -> %s\n", base, path, *value ? "true" : "false");
return (retval);
}

+ 29
- 0
pam_usb/src/xpath.h View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2003-2006 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
* Public License version 2, as published by the Free Software Foundation.
*
* pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef PUSB_XPATH_H_
# define PUSB_XPATH_H_
# include <libxml/parser.h>
int pusb_xpath_get_string(xmlDocPtr doc, const char *path, char *value,
size_t size);
int pusb_xpath_get_bool(xmlDocPtr doc, const char *path, int *value);
int pusb_xpath_get_string_from(xmlDocPtr doc, const char *base,
const char *path, char *value, size_t size);
int pusb_xpath_get_bool_from(xmlDocPtr doc, const char *base, const char *path,
int *value);
#endif /* !PUSB_XPATH_H_ */

Loading…
Cancel
Save