pam_ftp.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * pam_ftp module
  3. *
  4. * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
  5. */
  6. #define PLEASE_ENTER_PASSWORD "Password required for %s."
  7. #define GUEST_LOGIN_PROMPT "Guest login ok, " \
  8. "send your complete e-mail address as password."
  9. /* the following is a password that "can't be correct" */
  10. #define BLOCK_PASSWORD "\177BAD PASSWPRD\177"
  11. #include "config.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15. #include <syslog.h>
  16. #include <stdarg.h>
  17. #include <string.h>
  18. #include <security/pam_modules.h>
  19. #include <security/_pam_macros.h>
  20. #include <security/pam_ext.h>
  21. #include "pam_inline.h"
  22. /* argument parsing */
  23. #define PAM_DEBUG_ARG 01
  24. #define PAM_IGNORE_EMAIL 02
  25. #define PAM_NO_ANON 04
  26. static int
  27. _pam_parse(pam_handle_t *pamh, int argc, const char **argv, const char **users)
  28. {
  29. int ctrl=0;
  30. /* step through arguments */
  31. for (ctrl=0; argc-- > 0; ++argv) {
  32. const char *str;
  33. /* generic options */
  34. if (!strcmp(*argv,"debug"))
  35. ctrl |= PAM_DEBUG_ARG;
  36. else if (!strcmp(*argv,"ignore"))
  37. ctrl |= PAM_IGNORE_EMAIL;
  38. else if ((str = pam_str_skip_prefix(*argv, "users=")) != NULL)
  39. *users = str;
  40. else
  41. pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
  42. }
  43. return ctrl;
  44. }
  45. /*
  46. * check if name is in list or default list. place users name in *_user
  47. * return 1 if listed 0 if not.
  48. */
  49. static int lookup(const char *name, const char *list, char **_user)
  50. {
  51. int anon = 0;
  52. if (list && *list) {
  53. const char *l;
  54. char *list_copy, *x;
  55. char *sptr = NULL;
  56. list_copy = strdup(list);
  57. x = list_copy;
  58. while (list_copy && (l = strtok_r(x, ",", &sptr))) {
  59. x = NULL;
  60. if (!strcmp(name, l)) {
  61. *_user = list_copy;
  62. anon = 1;
  63. break;
  64. }
  65. }
  66. if (*_user != list_copy) {
  67. free(list_copy);
  68. }
  69. } else {
  70. #define MAX_L 2
  71. static const char *l[MAX_L] = { "ftp", "anonymous" };
  72. int i;
  73. for (i=0; i<MAX_L; ++i) {
  74. if (!strcmp(l[i], name)) {
  75. *_user = strdup(l[0]);
  76. anon = 1;
  77. break;
  78. }
  79. }
  80. }
  81. return anon;
  82. }
  83. /* --- authentication management functions (only) --- */
  84. int
  85. pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
  86. int argc, const char **argv)
  87. {
  88. int retval, anon=0, ctrl;
  89. const char *user;
  90. char *anon_user = NULL;
  91. const char *users = NULL;
  92. /*
  93. * this module checks if the user name is ftp or anonymous. If
  94. * this is the case, it can set the PAM_RUSER to the entered email
  95. * address and SUCCEEDS, otherwise it FAILS.
  96. */
  97. ctrl = _pam_parse(pamh, argc, argv, &users);
  98. retval = pam_get_user(pamh, &user, NULL);
  99. if (retval != PAM_SUCCESS) {
  100. pam_syslog(pamh, LOG_NOTICE, "cannot determine user name: %s",
  101. pam_strerror(pamh, retval));
  102. return PAM_USER_UNKNOWN;
  103. }
  104. if (!(ctrl & PAM_NO_ANON)) {
  105. anon = lookup(user, users, &anon_user);
  106. }
  107. if (anon) {
  108. retval = pam_set_item(pamh, PAM_USER, (const void *)anon_user);
  109. if (retval != PAM_SUCCESS || anon_user == NULL) {
  110. pam_syslog(pamh, LOG_ERR, "user resetting failed");
  111. free(anon_user);
  112. return PAM_USER_UNKNOWN;
  113. }
  114. free(anon_user);
  115. }
  116. /*
  117. * OK. we require an email address for user or the user's password.
  118. * - build conversation and get their input.
  119. */
  120. {
  121. char *resp = NULL;
  122. const char *token;
  123. if (!anon)
  124. retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
  125. PLEASE_ENTER_PASSWORD, user);
  126. else
  127. retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
  128. GUEST_LOGIN_PROMPT);
  129. if (retval != PAM_SUCCESS) {
  130. _pam_overwrite (resp);
  131. _pam_drop (resp);
  132. return ((retval == PAM_CONV_AGAIN)
  133. ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
  134. }
  135. if (anon) {
  136. /* XXX: Some effort should be made to verify this email address! */
  137. if (!(ctrl & PAM_IGNORE_EMAIL)) {
  138. char *sptr = NULL;
  139. token = strtok_r(resp, "@", &sptr);
  140. retval = pam_set_item(pamh, PAM_RUSER, token);
  141. if ((token) && (retval == PAM_SUCCESS)) {
  142. token = strtok_r(NULL, "@", &sptr);
  143. retval = pam_set_item(pamh, PAM_RHOST, token);
  144. }
  145. }
  146. /* we are happy to grant anonymous access to the user */
  147. retval = PAM_SUCCESS;
  148. } else {
  149. /*
  150. * we have a password so set AUTHTOK
  151. */
  152. pam_set_item(pamh, PAM_AUTHTOK, resp);
  153. /*
  154. * this module failed, but the next one might succeed with
  155. * this password.
  156. */
  157. retval = PAM_AUTH_ERR;
  158. }
  159. /* clean up */
  160. _pam_overwrite(resp);
  161. _pam_drop(resp);
  162. /* success or failure */
  163. return retval;
  164. }
  165. }
  166. int
  167. pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
  168. int argc UNUSED, const char **argv UNUSED)
  169. {
  170. return PAM_IGNORE;
  171. }
  172. /* end of module definition */