@ -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) |
@ -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); | |||||
} |
@ -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_ */ |
@ -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> |
@ -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); | |||||
} |
@ -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_ */ |
@ -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); | |||||
} |
@ -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_ */ |
@ -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); | |||||
} |
@ -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); | |||||
} |
@ -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_ */ |