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.

222 lines
6.1 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  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 <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <pwd.h>
  25. #include <time.h>
  26. #include <libhal-storage.h>
  27. #include "conf.h"
  28. #include "log.h"
  29. #include "volume.h"
  30. #include "pad.h"
  31. static FILE *pusb_pad_open_device(t_pusb_options *opts,
  32. LibHalVolume *volume,
  33. const char *user,
  34. const char *mode)
  35. {
  36. FILE *f;
  37. char path[PATH_MAX];
  38. const char *mnt_point;
  39. struct stat sb;
  40. mnt_point = (char *)libhal_volume_get_mount_point(volume);
  41. if (!mnt_point)
  42. return (NULL);
  43. memset(path, 0x00, PATH_MAX);
  44. snprintf(path, PATH_MAX, "%s/%s", mnt_point, opts->device_pad_directory);
  45. if (stat(path, &sb) != 0)
  46. {
  47. log_debug("Directory %s does not exist, creating one.\n", path);
  48. if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
  49. {
  50. log_debug("Unable to create directory %s: %s\n", path,
  51. strerror(errno));
  52. return (NULL);
  53. }
  54. memset(path, 0x00, PATH_MAX);
  55. }
  56. snprintf(path, PATH_MAX, "%s/%s/%s.%s.pad", mnt_point,
  57. opts->device_pad_directory, user, opts->hostname);
  58. f = fopen(path, mode);
  59. if (!f)
  60. {
  61. log_debug("Cannot open device file: %s\n", strerror(errno));
  62. return (NULL);
  63. }
  64. return (f);
  65. }
  66. static FILE *pusb_pad_open_system(t_pusb_options *opts,
  67. const char *user,
  68. const char *mode)
  69. {
  70. FILE *f;
  71. char path[PATH_MAX];
  72. struct passwd *user_ent = NULL;
  73. struct stat sb;
  74. if (!(user_ent = getpwnam(user)) || !(user_ent->pw_dir))
  75. {
  76. log_error("Unable to retrieve informations for user \"%s\": %s\n",
  77. strerror(errno));
  78. return (0);
  79. }
  80. memset(path, 0x00, PATH_MAX);
  81. snprintf(path, PATH_MAX, "%s/%s", user_ent->pw_dir,
  82. opts->system_pad_directory);
  83. if (stat(path, &sb) != 0)
  84. {
  85. log_debug("Directory %s does not exist, creating one.\n", path);
  86. if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
  87. {
  88. log_debug("Unable to create directory %s: %s\n", path,
  89. strerror(errno));
  90. return (NULL);
  91. }
  92. chown(path, user_ent->pw_uid, user_ent->pw_gid);
  93. chmod(path, S_IRUSR | S_IWUSR | S_IXUSR);
  94. }
  95. memset(path, 0x00, PATH_MAX);
  96. snprintf(path, PATH_MAX, "%s/%s/%s.pad", user_ent->pw_dir,
  97. opts->system_pad_directory, opts->device.name);
  98. f = fopen(path, mode);
  99. if (!f)
  100. {
  101. log_debug("Cannot open system file: %s\n", strerror(errno));
  102. return (NULL);
  103. }
  104. return (f);
  105. }
  106. static int pusb_pad_protect(const char *user, int fd)
  107. {
  108. struct passwd *user_ent = NULL;
  109. log_debug("Protecting pad file...\n");
  110. if (!(user_ent = getpwnam(user)))
  111. {
  112. log_error("Unable to retrieve informations for user \"%s\": %s\n",
  113. strerror(errno));
  114. return (0);
  115. }
  116. if (fchown(fd, user_ent->pw_uid, user_ent->pw_gid) == -1)
  117. {
  118. log_error("Unable to change owner of the pad: %s\n",
  119. strerror(errno));
  120. return (0);
  121. }
  122. if (fchmod(fd, S_IRUSR | S_IWUSR) == -1)
  123. {
  124. log_error("Unable to change mode of the pad: %s\n",
  125. strerror(errno));
  126. return (0);
  127. }
  128. return (1);
  129. }
  130. static void pusb_pad_update(t_pusb_options *opts,
  131. LibHalVolume *volume,
  132. const char *user)
  133. {
  134. FILE *f_device = NULL;
  135. FILE *f_system = NULL;
  136. char magic[1024];
  137. int i;
  138. if (!(f_device = pusb_pad_open_device(opts, volume, user, "w+")))
  139. {
  140. log_error("Unable to update pads.\n");
  141. return ;
  142. }
  143. pusb_pad_protect(user, fileno(f_device));
  144. if (!(f_system = pusb_pad_open_system(opts, user, "w+")))
  145. {
  146. log_error("Unable to update pads.\n");
  147. fclose(f_device);
  148. return ;
  149. }
  150. pusb_pad_protect(user, fileno(f_system));
  151. log_debug("Generating %d bytes unique pad...\n", sizeof(magic));
  152. srand(getpid() * time(NULL));
  153. for (i = 0; i < sizeof(magic); ++i)
  154. magic[i] = (char)rand();
  155. log_debug("Writing pad to the device...\n");
  156. fwrite(magic, sizeof(char), sizeof(magic), f_system);
  157. log_debug("Writing pad to the system...\n");
  158. fwrite(magic, sizeof(char), sizeof(magic), f_device);
  159. log_debug("Synchronizing filesystems...\n");
  160. fclose(f_system);
  161. fclose(f_device);
  162. sync();
  163. log_debug("One time pads updated.\n");
  164. }
  165. static int pusb_pad_compare(t_pusb_options *opts, LibHalVolume *volume,
  166. const char *user)
  167. {
  168. FILE *f_device = NULL;
  169. FILE *f_system = NULL;
  170. char magic_device[1024];
  171. char magic_system[1024];
  172. int retval;
  173. if (!(f_system = pusb_pad_open_system(opts, user, "r")))
  174. return (1);
  175. if (!(f_device = pusb_pad_open_device(opts, volume, user, "r")))
  176. {
  177. fclose(f_system);
  178. return (0);
  179. }
  180. log_debug("Loading device pad...\n");
  181. fread(magic_device, sizeof(char), sizeof(magic_device), f_device);
  182. log_debug("Loading system pad...\n");
  183. fread(magic_system, sizeof(char), sizeof(magic_system), f_system);
  184. retval = memcmp(magic_system, magic_device, sizeof(magic_system));
  185. fclose(f_system);
  186. fclose(f_device);
  187. if (!retval)
  188. log_debug("Pad match.\n");
  189. return (retval == 0);
  190. }
  191. int pusb_pad_check(t_pusb_options *opts, LibHalContext *ctx,
  192. const char *user)
  193. {
  194. LibHalVolume *volume = NULL;
  195. int retval;
  196. volume = pusb_volume_get(opts, ctx);
  197. if (!volume)
  198. return (0);
  199. retval = pusb_pad_compare(opts, volume, user);
  200. if (retval)
  201. {
  202. log_info("Verification match, updating one time pads...\n");
  203. pusb_pad_update(opts, volume, user);
  204. }
  205. else
  206. log_error("Pad checking failed !\n");
  207. pusb_volume_destroy(volume);
  208. return (retval);
  209. }