]> granicus.if.org Git - linux-pam/blob - modules/pam_ftp/pam_ftp.c
revert preceding patch; under discussion, no consensus
[linux-pam] / modules / pam_ftp / pam_ftp.c
1 /* pam_ftp module */
2
3 /*
4  * $Id$
5  *
6  * Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
7  *
8  */
9
10 #define PLEASE_ENTER_PASSWORD "Password required for %s."
11 #define GUEST_LOGIN_PROMPT "Guest login ok, " \
12 "send your complete e-mail address as password."
13
14 /* the following is a password that "can't be correct" */
15 #define BLOCK_PASSWORD "\177BAD PASSWPRD\177"
16
17 #include "config.h"
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <syslog.h>
23 #include <stdarg.h>
24 #include <string.h>
25
26 /*
27  * here, we make a definition for the externally accessible function
28  * in this file (this definition is required for static a module
29  * but strongly encouraged generally) it is used to instruct the
30  * modules include file to define the function prototypes.
31  */
32
33 #define PAM_SM_AUTH
34
35 #include <security/pam_modules.h>
36 #include <security/_pam_macros.h>
37 #include <security/pam_ext.h>
38
39 /* argument parsing */
40
41 #define PAM_DEBUG_ARG       01
42 #define PAM_IGNORE_EMAIL    02
43 #define PAM_NO_ANON         04
44
45 static int
46 _pam_parse(pam_handle_t *pamh, int argc, const char **argv, const char **users)
47 {
48     int ctrl=0;
49
50     /* step through arguments */
51     for (ctrl=0; argc-- > 0; ++argv) {
52
53         /* generic options */
54
55         if (!strcmp(*argv,"debug"))
56             ctrl |= PAM_DEBUG_ARG;
57         else if (!strncmp(*argv,"users=",6)) {
58             *users = 6 + *argv;
59         } else if (!strcmp(*argv,"ignore")) {
60             ctrl |= PAM_IGNORE_EMAIL;
61         } else {
62             pam_syslog(pamh, LOG_ERR, "unknown option: %s", *argv);
63         }
64     }
65
66     return ctrl;
67 }
68
69 /*
70  * check if name is in list or default list. place users name in *_user
71  * return 1 if listed 0 if not.
72  */
73
74 static int lookup(const char *name, const char *list, const char **_user)
75 {
76     int anon = 0;
77
78     *_user = name;                 /* this is the default */
79     if (list && *list) {
80         const char *l;
81         char *list_copy, *x;
82         char *sptr = NULL;
83
84         list_copy = x_strdup(list);
85         x = list_copy;
86         while (list_copy && (l = strtok_r(x, ",", &sptr))) {
87             x = NULL;
88             if (!strcmp(name, l)) {
89                 *_user = list;
90                 anon = 1;
91             }
92         }
93         _pam_overwrite(list_copy);
94         _pam_drop(list_copy);
95     } else {
96 #define MAX_L 2
97         static const char *l[MAX_L] = { "ftp", "anonymous" };
98         int i;
99
100         for (i=0; i<MAX_L; ++i) {
101             if (!strcmp(l[i], name)) {
102                 *_user = l[0];
103                 anon = 1;
104                 break;
105             }
106         }
107     }
108
109     return anon;
110 }
111
112 /* --- authentication management functions (only) --- */
113
114 PAM_EXTERN int
115 pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
116                      int argc, const char **argv)
117 {
118     int retval, anon=0, ctrl;
119     const char *user;
120     const char *users = NULL;
121
122     /*
123      * this module checks if the user name is ftp or annonymous. If
124      * this is the case, it can set the PAM_RUSER to the entered email
125      * address and SUCCEEDS, otherwise it FAILS.
126      */
127
128     ctrl = _pam_parse(pamh, argc, argv, &users);
129
130     retval = pam_get_user(pamh, &user, NULL);
131     if (retval != PAM_SUCCESS || user == NULL) {
132         pam_syslog(pamh, LOG_ERR, "no user specified");
133         return PAM_USER_UNKNOWN;
134     }
135
136     if (!(ctrl & PAM_NO_ANON)) {
137         anon = lookup(user, users, &user);
138     }
139
140     if (anon) {
141         retval = pam_set_item(pamh, PAM_USER, (const void *)user);
142         if (retval != PAM_SUCCESS || user == NULL) {
143             pam_syslog(pamh, LOG_ERR, "user resetting failed");
144             return PAM_USER_UNKNOWN;
145         }
146     }
147
148     /*
149      * OK. we require an email address for user or the user's password.
150      * - build conversation and get their input.
151      */
152
153     {
154         char *resp = NULL;
155         const char *token;
156
157         if (!anon)
158           retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
159                                PLEASE_ENTER_PASSWORD, user);
160         else
161           retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
162                                GUEST_LOGIN_PROMPT);
163
164         if (retval != PAM_SUCCESS) {
165             _pam_overwrite (resp);
166             _pam_drop (resp);
167             return ((retval == PAM_CONV_AGAIN)
168                     ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
169         }
170
171         if (anon) {
172           /* XXX: Some effort should be made to verify this email address! */
173
174             if (!(ctrl & PAM_IGNORE_EMAIL)) {
175                 char *sptr = NULL;
176                 token = strtok_r(resp, "@", &sptr);
177                 retval = pam_set_item(pamh, PAM_RUSER, token);
178
179                 if ((token) && (retval == PAM_SUCCESS)) {
180                     token = strtok_r(NULL, "@", &sptr);
181                     retval = pam_set_item(pamh, PAM_RHOST, token);
182                 }
183             }
184
185             /* we are happy to grant annonymous access to the user */
186             retval = PAM_SUCCESS;
187
188         } else {
189             /*
190              * we have a password so set AUTHTOK
191              */
192
193             pam_set_item(pamh, PAM_AUTHTOK, resp);
194
195             /*
196              * this module failed, but the next one might succeed with
197              * this password.
198              */
199
200             retval = PAM_AUTH_ERR;
201         }
202
203         /* clean up */
204         _pam_overwrite(resp);
205         _pam_drop(resp);
206
207         /* success or failure */
208
209         return retval;
210     }
211 }
212
213 PAM_EXTERN int
214 pam_sm_setcred (pam_handle_t *pamh UNUSED, int flags UNUSED,
215                 int argc UNUSED, const char **argv UNUSED)
216 {
217      return PAM_IGNORE;
218 }
219
220
221 #ifdef PAM_STATIC
222
223 /* static module data */
224
225 struct pam_module _pam_ftp_modstruct = {
226      "pam_ftp",
227      pam_sm_authenticate,
228      pam_sm_setcred,
229      NULL,
230      NULL,
231      NULL,
232      NULL,
233 };
234
235 #endif
236
237 /* end of module definition */