Deleted Added
sdiff udiff text old ( 41228 ) new ( 42917 )
full compact
1/*-
2 * Copyright 1998 Juniper Networks, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/lib/libpam/modules/pam_tacplus/pam_tacplus.c 41228 1998-11-18 01:44:37Z jdp $
27 */
28
29#include <sys/param.h>
30
31#include <pwd.h>
32#include <stdlib.h>
33#include <string.h>
34#include <syslog.h>
35#include <taclib.h>
36#include <unistd.h>
37
38#define PAM_SM_AUTH
39#include <security/pam_modules.h>
40
41#include "pam_mod_misc.h"
42
43/* Option names, including the "=" sign. */
44#define OPT_CONF "conf="
45#define OPT_TMPL "template_user="
46
47typedef int (*set_func)(struct tac_handle *, const char *);
48
49static int do_item(pam_handle_t *, struct tac_handle *, int,
50 set_func, const char *);
51static char *get_msg(struct tac_handle *);
52static int set_msg(struct tac_handle *, const char *);
53
54static int
55do_item(pam_handle_t *pamh, struct tac_handle *tach, int item,
56 set_func func, const char *funcname)
57{
58 int retval;
59 const void *value;
60
61 if ((retval = pam_get_item(pamh, item, &value)) != PAM_SUCCESS)
62 return retval;
63 if (value != NULL && (*func)(tach, (const char *)value) == -1) {
64 syslog(LOG_CRIT, "%s: %s", funcname, tac_strerror(tach));
65 tac_close(tach);
66 return PAM_SERVICE_ERR;
67 }
68 return PAM_SUCCESS;
69}
70
71static char *
72get_msg(struct tac_handle *tach)
73{
74 char *msg;
75
76 if ((msg = tac_get_msg(tach)) == NULL) {
77 syslog(LOG_CRIT, "tac_get_msg: %s", tac_strerror(tach));
78 tac_close(tach);
79 return NULL;
80 }
81 return msg;
82}
83
84static int
85set_msg(struct tac_handle *tach, const char *msg)
86{
87 if (tac_set_msg(tach, msg) == -1) {
88 syslog(LOG_CRIT, "tac_set_msg: %s", tac_strerror(tach));
89 tac_close(tach);
90 return -1;
91 }
92 return 0;
93}
94
95PAM_EXTERN int
96pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
97 const char **argv)
98{
99 int retval;
100 struct tac_handle *tach;
101 const char *conf_file = NULL;
102 const char *template_user = NULL;
103 int options = 0;
104 int i;
105
106 for (i = 0; i < argc; i++) {
107 size_t len;
108
109 pam_std_option(&options, argv[i]);
110 if (strncmp(argv[i], OPT_CONF, (len = strlen(OPT_CONF))) == 0)
111 conf_file = argv[i] + len;
112 else if (strncmp(argv[i], OPT_TMPL,
113 (len = strlen(OPT_TMPL))) == 0)
114 template_user = argv[i] + len;
115 }
116
117 if ((tach = tac_open()) == NULL) {
118 syslog(LOG_CRIT, "tac_open failed");
119 return PAM_SERVICE_ERR;
120 }
121 if (tac_config(tach, conf_file) == -1) {
122 syslog(LOG_ALERT, "tac_config: %s", tac_strerror(tach));
123 tac_close(tach);
124 return PAM_SERVICE_ERR;
125 }
126 if (tac_create_authen(tach, TAC_AUTHEN_LOGIN, TAC_AUTHEN_TYPE_ASCII,
127 TAC_AUTHEN_SVC_LOGIN) == -1) {
128 syslog(LOG_CRIT, "tac_create_authen: %s", tac_strerror(tach));
129 tac_close(tach);
130 return PAM_SERVICE_ERR;
131 }
132 if ((retval = do_item(pamh, tach, PAM_USER,
133 tac_set_user, "tac_set_user")) != PAM_SUCCESS)
134 return retval;
135 if ((retval = do_item(pamh, tach, PAM_TTY,
136 tac_set_port, "tac_set_port")) != PAM_SUCCESS)
137 return retval;
138 if ((retval = do_item(pamh, tach, PAM_RHOST,
139 tac_set_rem_addr, "tac_set_rem_addr")) != PAM_SUCCESS)
140 return retval;
141 for ( ; ; ) {
142 char *srvr_msg;
143 size_t msg_len;
144 const char *user_msg;
145 char *data_msg;
146 int sflags;
147 int status;
148 int echo;
149
150 if ((sflags = tac_send_authen(tach)) == -1) {
151 syslog(LOG_CRIT, "tac_send_authen: %s",
152 tac_strerror(tach));
153 tac_close(tach);
154 return PAM_AUTHINFO_UNAVAIL;
155 }
156 status = TAC_AUTHEN_STATUS(sflags);
157 echo = TAC_AUTHEN_NOECHO(sflags) ? 0 : PAM_OPT_ECHO_PASS;
158 switch (status) {
159
160 case TAC_AUTHEN_STATUS_PASS:
161 tac_close(tach);
162 if (template_user != NULL) {
163 const void *item;
164 const char *user;
165
166 /*
167 * If the given user name doesn't exist in
168 * the local password database, change it
169 * to the value given in the "template_user"
170 * option.
171 */
172 retval = pam_get_item(pamh, PAM_USER, &item);
173 if (retval != PAM_SUCCESS)
174 return retval;
175 user = (const char *)item;
176 if (getpwnam(user) == NULL)
177 pam_set_item(pamh, PAM_USER,
178 template_user);
179 }
180 return PAM_SUCCESS;
181
182 case TAC_AUTHEN_STATUS_FAIL:
183 tac_close(tach);
184 return PAM_AUTH_ERR;
185
186 case TAC_AUTHEN_STATUS_GETUSER:
187 case TAC_AUTHEN_STATUS_GETPASS:
188 if ((srvr_msg = get_msg(tach)) == NULL)
189 return PAM_SERVICE_ERR;
190 if (status == TAC_AUTHEN_STATUS_GETUSER)
191 retval = pam_get_user(pamh, &user_msg,
192 srvr_msg[0] != '\0' ? srvr_msg : NULL);
193 else if (status == TAC_AUTHEN_STATUS_GETPASS)
194 retval = pam_get_pass(pamh, &user_msg,
195 srvr_msg[0] != '\0' ? srvr_msg :
196 "Password:", options | echo);
197 free(srvr_msg);
198 if (retval != PAM_SUCCESS) {
199 /* XXX - send a TACACS+ abort packet */
200 tac_close(tach);
201 return retval;
202 }
203 if (set_msg(tach, user_msg) == -1)
204 return PAM_SERVICE_ERR;
205 break;
206
207 case TAC_AUTHEN_STATUS_GETDATA:
208 if ((srvr_msg = get_msg(tach)) == NULL)
209 return PAM_SERVICE_ERR;
210 retval = pam_prompt(pamh,
211 (options|echo) & PAM_OPT_ECHO_PASS ?
212 PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF,
213 srvr_msg[0] != '\0' ? srvr_msg : "Data:",
214 &data_msg);
215 free(srvr_msg);
216 if (retval != PAM_SUCCESS) {
217 /* XXX - send a TACACS+ abort packet */
218 tac_close(tach);
219 return retval;
220 }
221 retval = set_msg(tach, data_msg);
222 memset(data_msg, 0, strlen(data_msg));
223 free(data_msg);
224 if (retval == -1)
225 return PAM_SERVICE_ERR;
226 break;
227
228 case TAC_AUTHEN_STATUS_ERROR:
229 srvr_msg = (char *)tac_get_data(tach, &msg_len);
230 if (srvr_msg != NULL && msg_len != 0) {
231 syslog(LOG_CRIT, "tac_send_authen:"
232 " server detected error: %s", srvr_msg);
233 free(srvr_msg);
234 } else
235 syslog(LOG_CRIT,
236 "tac_send_authen: server detected error");
237 tac_close(tach);
238 return PAM_AUTHINFO_UNAVAIL;
239 break;
240
241 case TAC_AUTHEN_STATUS_RESTART:
242 case TAC_AUTHEN_STATUS_FOLLOW:
243 default:
244 syslog(LOG_CRIT,
245 "tac_send_authen: unexpected status %#x", status);
246 tac_close(tach);
247 return PAM_AUTHINFO_UNAVAIL;
248 }
249 }
250}
251
252PAM_EXTERN int
253pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
254{
255 return PAM_SUCCESS;
256}