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.

194 lines
5.6 KiB

  1. /*
  2. * Copyright (c) 2003-2007 Andrea Luzzardi <scox@sig11.org>
  3. *
  4. * This file is part of the pam_usb project. pam_usb is free software;
  5. * you can redistribute it and/or modify it under the terms of the GNU General
  6. * Public License version 2, as published by the Free Software Foundation.
  7. *
  8. * pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
  9. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  10. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  11. * details.
  12. *
  13. * You should have received a copy of the GNU General Public License along with
  14. * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  15. * Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. #include <sys/utsname.h>
  18. #include <string.h>
  19. #include <errno.h>
  20. #include "conf.h"
  21. #include "xpath.h"
  22. #include "log.h"
  23. static void pusb_conf_options_get_from(t_pusb_options *opts,
  24. const char *from,
  25. xmlDoc *doc)
  26. {
  27. pusb_xpath_get_string_from(doc, from, "option[@name='hostname']",
  28. opts->hostname, sizeof(opts->hostname));
  29. pusb_xpath_get_string_from(doc, from, "option[@name='system_pad_directory']",
  30. opts->system_pad_directory,
  31. sizeof(opts->system_pad_directory));
  32. pusb_xpath_get_string_from(doc, from, "option[@name='device_pad_directory']",
  33. opts->device_pad_directory,
  34. sizeof(opts->device_pad_directory));
  35. pusb_xpath_get_bool_from(doc, from, "option[@name='debug']",
  36. &(opts->debug));
  37. pusb_xpath_get_bool_from(doc, from, "option[@name='quiet']",
  38. &(opts->quiet));
  39. pusb_xpath_get_bool_from(doc, from, "option[@name='color_log']",
  40. &(opts->color_log));
  41. pusb_xpath_get_bool_from(doc, from, "option[@name='enable']",
  42. &(opts->enable));
  43. pusb_xpath_get_bool_from(doc, from, "option[@name='one_time_pad']",
  44. &(opts->one_time_pad));
  45. pusb_xpath_get_time_from(doc, from, "option[@name='pad_expiration']",
  46. &(opts->pad_expiration));
  47. pusb_xpath_get_time_from(doc, from, "option[@name='probe_timeout']",
  48. &(opts->probe_timeout));
  49. }
  50. static int pusb_conf_parse_options(t_pusb_options *opts,
  51. xmlDoc *doc,
  52. const char *user,
  53. const char *service)
  54. {
  55. char *xpath = NULL;
  56. size_t xpath_size;
  57. int i;
  58. struct s_opt_list opt_list[] = {
  59. { CONF_DEVICE_XPATH, opts->device.name },
  60. { CONF_USER_XPATH, (char *)user },
  61. { CONF_SERVICE_XPATH, (char *)service },
  62. { NULL, NULL }
  63. };
  64. pusb_conf_options_get_from(opts, "//configuration/defaults/", doc);
  65. for (i = 0; opt_list[i].name != NULL; ++i)
  66. {
  67. xpath_size = strlen(opt_list[i].name) + strlen(opt_list[i].value) + 1;
  68. if (!(xpath = malloc(xpath_size)))
  69. {
  70. log_error("malloc error\n");
  71. return (0);
  72. }
  73. memset(xpath, 0x00, xpath_size);
  74. snprintf(xpath, xpath_size, opt_list[i].name, opt_list[i].value, "");
  75. pusb_conf_options_get_from(opts, xpath, doc);
  76. free(xpath);
  77. }
  78. return (1);
  79. }
  80. static int pusb_conf_device_get_property(t_pusb_options *opts,
  81. xmlDoc *doc,
  82. const char *property,
  83. char *store,
  84. size_t size)
  85. {
  86. char *xpath = NULL;
  87. size_t xpath_len;
  88. int retval;
  89. xpath_len = strlen(CONF_DEVICE_XPATH) + strlen(opts->device.name) + \
  90. strlen(property) + 1;
  91. if (!(xpath = malloc(xpath_len)))
  92. {
  93. log_error("malloc error!\n");
  94. return (0);
  95. }
  96. memset(xpath, 0x00, xpath_len);
  97. snprintf(xpath, xpath_len, CONF_DEVICE_XPATH, opts->device.name,
  98. property);
  99. retval = pusb_xpath_get_string(doc, xpath, store, size);
  100. free(xpath);
  101. return (retval);
  102. }
  103. static int pusb_conf_parse_device(t_pusb_options *opts, xmlDoc *doc)
  104. {
  105. pusb_conf_device_get_property(opts, doc, "vendor", opts->device.vendor,
  106. sizeof(opts->device.vendor));
  107. pusb_conf_device_get_property(opts, doc, "model", opts->device.model,
  108. sizeof(opts->device.model));
  109. if (!pusb_conf_device_get_property(opts, doc, "serial", opts->device.serial,
  110. sizeof(opts->device.serial)))
  111. return (0);
  112. pusb_conf_device_get_property(opts, doc, "volume_uuid",
  113. opts->device.volume_uuid,
  114. sizeof(opts->device.volume_uuid));
  115. return (1);
  116. }
  117. int pusb_conf_init(t_pusb_options *opts)
  118. {
  119. struct utsname u;
  120. memset(opts, 0x00, sizeof(*opts));
  121. if (uname(&u) == -1)
  122. {
  123. log_error("uname: %s\n", strerror(errno));
  124. return (0);
  125. }
  126. strncpy(opts->hostname, u.nodename, sizeof(opts->hostname) - 1);
  127. if (strlen(u.nodename) > sizeof(opts->hostname))
  128. log_info("Hostname \"%s\" is too long, truncating to \"%s\".\n",
  129. u.nodename, opts->hostname);
  130. strcpy(opts->system_pad_directory, ".pamusb");
  131. strcpy(opts->device_pad_directory, ".pamusb");
  132. opts->probe_timeout = 10;
  133. opts->enable = 1;
  134. opts->debug = 0;
  135. opts->quiet = 0;
  136. opts->color_log = 1;
  137. opts->one_time_pad = 1;
  138. opts->pad_expiration = 3600;
  139. return (1);
  140. }
  141. int pusb_conf_parse(const char *file, t_pusb_options *opts,
  142. const char *user, const char *service)
  143. {
  144. xmlDoc *doc = NULL;
  145. int retval;
  146. char device_xpath[sizeof(CONF_USER_XPATH) + CONF_USER_MAXLEN + \
  147. sizeof("device")];
  148. log_debug("Parsing settings...\n",
  149. user, service);
  150. if (strlen(user) > CONF_USER_MAXLEN)
  151. {
  152. log_error("Username \"%s\" is too long (max: %d).\n", user,
  153. CONF_USER_MAXLEN);
  154. return (0);
  155. }
  156. if (!(doc = xmlReadFile(file, NULL, 0)))
  157. {
  158. log_error("Unable to parse \"%s\".\n", file);
  159. return (0);
  160. }
  161. snprintf(device_xpath, sizeof(device_xpath), CONF_USER_XPATH, user,
  162. "device");
  163. retval = pusb_xpath_get_string(doc,
  164. device_xpath,
  165. opts->device.name,
  166. sizeof(opts->device.name));
  167. if (!retval || !pusb_conf_parse_device(opts, doc))
  168. {
  169. log_error("No device configured for user \"%s\".\n", user);
  170. xmlFreeDoc(doc);
  171. xmlCleanupParser();
  172. return (0);
  173. }
  174. if (!pusb_conf_parse_options(opts, doc, user, service))
  175. {
  176. xmlFreeDoc(doc);
  177. xmlCleanupParser();
  178. return (0);
  179. }
  180. xmlFreeDoc(doc);
  181. xmlCleanupParser();
  182. return (1);
  183. }