Hardware authentication for Linux using ordinary USB Flash Drives.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

257 lines
5.7 KiB

/*
* Copyright (c) 2003-2007 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., 51 Franklin
* Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <libxml/xpath.h>
#include <ctype.h>
#include <string.h>
#include "mem.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);
}
static int pusb_xpath_strip_string(char *dest, const char *src,
size_t size)
{
int first_char = -1;
int last_char = -1;
int i;
for (i = 0; src[i]; ++i)
{
if (isspace(src[i]))
continue ;
if (first_char == -1)
first_char = i;
last_char = i;
}
if (first_char == -1 || last_char == -1)
return (0);
if ((last_char - first_char) > (size - 1))
{
log_error("Device name is too long: %s", src);
return (0);
}
memset(dest, 0x0, size);
strncpy(dest, &(src[first_char]), last_char - first_char + 1);
return (1);
}
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 (!result_string)
{
xmlXPathFreeObject(result);
log_debug("Empty value for %s\n", path);
return (0);
}
if (!pusb_xpath_strip_string(value, (const char *)result_string, 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);
}
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;
xpath = xmalloc(xpath_size);
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);
xfree(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;
xpath = xmalloc(xpath_size);
memset(xpath, 0x00, xpath_size);
snprintf(xpath, xpath_size, "%s%s", base, path);
retval = pusb_xpath_get_bool(doc, xpath, value);
xfree(xpath);
return (retval);
}
int pusb_xpath_get_time(xmlDocPtr doc, const char *path, time_t *value)
{
char ret[64];
char *last;
int coef;
if (!pusb_xpath_get_string(doc, path, ret, sizeof(ret)))
return (0);
last = &(ret[strlen(ret) - 1]);
coef = 1;
if (*last == 's')
coef = 1;
else if (*last == 'm')
coef = 60;
else if (*last == 'h')
coef = 3600;
else if (*last == 'd')
coef = 3600 * 24;
else
if (!isdigit(*last))
{
log_debug("Expecting a time modifier, got %c\n", *last);
return (0);
}
if (!isdigit(*last))
*last = '\0';
*value = atoi(ret) * coef;
return (0);
}
int pusb_xpath_get_time_from(xmlDocPtr doc,
const char *base,
const char *path,
time_t *value)
{
char *xpath = NULL;
size_t xpath_size;
int retval;
xpath_size = strlen(base) + strlen(path) + 1;
xpath = xmalloc(xpath_size);
memset(xpath, 0x00, xpath_size);
snprintf(xpath, xpath_size, "%s%s", base, path);
retval = pusb_xpath_get_time(doc, xpath, value);
xfree(xpath);
return (retval);
}
int pusb_xpath_get_int(xmlDocPtr doc, const char *path, int *value)
{
char ret[64];
if (!pusb_xpath_get_string(doc, path, ret, sizeof(ret)))
return (0);
*value = atoi(ret);
return (1);
}
int pusb_xpath_get_int_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;
xpath = xmalloc(xpath_size);
memset(xpath, 0x00, xpath_size);
snprintf(xpath, xpath_size, "%s%s", base, path);
retval = pusb_xpath_get_int(doc, xpath, value);
xfree(xpath);
return (retval);
}