]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libexec/lukemftpd/pamize.h
This commit was generated by cvs2svn to compensate for changes in r147078,
[FreeBSD/FreeBSD.git] / libexec / lukemftpd / pamize.h
1 /* $FreeBSD$ */
2
3
4 #ifdef USE_PAM
5 /*
6  * the following code is stolen from imap-uw PAM authentication module and
7  * login.c
8  */
9 #define COPY_STRING(s) (s ? strdup(s) : NULL)
10
11 struct cred_t {
12         const char *uname;              /* user name */
13         const char *pass;               /* password */
14 };
15 typedef struct cred_t cred_t;
16
17 static int
18 auth_conv(int num_msg, const struct pam_message **msg,
19           struct pam_response **resp, void *appdata)
20 {
21         int i;
22         cred_t *cred = (cred_t *) appdata;
23         struct pam_response *reply;
24
25         reply = calloc(num_msg, sizeof *reply);
26         if (reply == NULL)
27                 return PAM_BUF_ERR;
28
29         for (i = 0; i < num_msg; i++) {
30                 switch (msg[i]->msg_style) {
31                 case PAM_PROMPT_ECHO_ON:        /* assume want user name */
32                         reply[i].resp_retcode = PAM_SUCCESS;
33                         reply[i].resp = COPY_STRING(cred->uname);
34                         /* PAM frees resp. */
35                         break;
36                 case PAM_PROMPT_ECHO_OFF:       /* assume want password */
37                         reply[i].resp_retcode = PAM_SUCCESS;
38                         reply[i].resp = COPY_STRING(cred->pass);
39                         /* PAM frees resp. */
40                         break;
41                 case PAM_TEXT_INFO:
42                 case PAM_ERROR_MSG:
43                         reply[i].resp_retcode = PAM_SUCCESS;
44                         reply[i].resp = NULL;
45                         break;
46                 default:                        /* unknown message style */
47                         free(reply);
48                         return PAM_CONV_ERR;
49                 }
50         }
51
52         *resp = reply;
53         return PAM_SUCCESS;
54 }
55
56 /*
57  * Attempt to authenticate the user using PAM.  Returns 0 if the user is
58  * authenticated, or 1 if not authenticated.  If some sort of PAM system
59  * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
60  * function returns -1.  This can be used as an indication that we should
61  * fall back to a different authentication mechanism.
62  */
63 static int
64 auth_pam(struct passwd **ppw, const char *pass)
65 {
66         pam_handle_t *pamh = NULL;
67         const char *tmpl_user;
68         const void *item;
69         int rval;
70         int e;
71         cred_t auth_cred = { (*ppw)->pw_name, pass };
72         struct pam_conv conv = { &auth_conv, &auth_cred };
73
74         e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
75         if (e != PAM_SUCCESS) {
76                 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
77                 return -1;
78         }
79
80         e = pam_set_item(pamh, PAM_RHOST, remotehost);
81         if (e != PAM_SUCCESS) {
82                 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
83                         pam_strerror(pamh, e));
84                 return -1;
85         }
86
87         e = pam_authenticate(pamh, 0);
88         switch (e) {
89         case PAM_SUCCESS:
90                 /*
91                  * With PAM we support the concept of a "template"
92                  * user.  The user enters a login name which is
93                  * authenticated by PAM, usually via a remote service
94                  * such as RADIUS or TACACS+.  If authentication
95                  * succeeds, a different but related "template" name
96                  * is used for setting the credentials, shell, and
97                  * home directory.  The name the user enters need only
98                  * exist on the remote authentication server, but the
99                  * template name must be present in the local password
100                  * database.
101                  *
102                  * This is supported by two various mechanisms in the
103                  * individual modules.  However, from the application's
104                  * point of view, the template user is always passed
105                  * back as a changed value of the PAM_USER item.
106                  */
107                 if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
108                     PAM_SUCCESS) {
109                         tmpl_user = (const char *) item;
110                         if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
111                                 *ppw = getpwnam(tmpl_user);
112                 } else
113                         syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
114                             pam_strerror(pamh, e));
115                 rval = 0;
116                 break;
117
118         case PAM_AUTH_ERR:
119         case PAM_USER_UNKNOWN:
120         case PAM_MAXTRIES:
121                 rval = 1;
122                 break;
123
124         default:
125                 syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e));
126                 rval = -1;
127                 break;
128         }
129
130         if (rval == 0) {
131                 e = pam_acct_mgmt(pamh, 0);
132                 if (e == PAM_NEW_AUTHTOK_REQD) {
133                         e = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
134                         if (e != PAM_SUCCESS) {
135                                 syslog(LOG_ERR, "pam_chauthtok: %s",
136                                     pam_strerror(pamh, e));
137                                 rval = 1;
138                         }
139                 } else if (e != PAM_SUCCESS) {
140                         rval = 1;
141                 }
142         }
143
144         if (rval != 0) {
145                 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
146                         syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
147                 }
148                 pamh = NULL;
149         }
150         return rval;
151 }
152
153 #endif /* USE_PAM */