]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/basic_auth/PAM/pam_auth.c
Updated copyright
[thirdparty/squid.git] / helpers / basic_auth / PAM / pam_auth.c
1 /*
2 * $Id: pam_auth.c,v 1.2 2001/01/12 00:37:29 wessels Exp $
3 *
4 * PAM authenticator module for Squid.
5 * Copyright (C) 1999 Henrik Nordstrom <hno@hem.passagen.se>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * SQUID Web Proxy Cache http://www.squid-cache.org/
20 * ----------------------------------------------------------
21 *
22 * Squid is the result of efforts by numerous individuals from
23 * the Internet community; see the CONTRIBUTORS file for full
24 * details. Many organizations have provided support for Squid's
25 * development; see the SPONSORS file for full details. Squid is
26 * Copyrighted (C) 2001 by the Regents of the University of
27 * California; see the COPYRIGHT file for full details. Squid
28 * incorporates software developed and/or copyrighted by other
29 * sources; see the CREDITS file for full details.
30 *
31 * This program is free software; you can redistribute it and/or modify
32 * it under the terms of the GNU General Public License as published by
33 * the Free Software Foundation; either version 2 of the License, or
34 * (at your option) any later version.
35 *
36 * This program is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with this program; if not, write to the Free Software
43 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
44 *
45 * Install instructions:
46 *
47 * This program authenticates users against a PAM configured authentication
48 * service "squid". This allows you to authenticate Squid users to any
49 * authentication source for which you have a PAM module. Commonly available
50 * PAM modules includes "UNIX", RADIUS, Kerberos and SMB, but a lot of other
51 * PAM modules are available from various sources.
52 *
53 * Example PAM configuration for standard UNIX passwd authentication:
54 * /etc/pam.conf:
55 * squid auth required /lib/security/pam_unix.so.1
56 * squid account required /lib/security/pam_unix.so.1
57 *
58 * Note that some PAM modules (for example shadow password authentication)
59 * requires the program to be installed suid root, or PAM will not allow
60 * it to authenticate other users than it runs as (this is a security
61 * limitation of PAM to avoid automated probing of passwords).
62 *
63 * Compile this program with: gcc -o pam_auth pam_auth.c -lpam -ldl
64 *
65 */
66
67 #include <stdio.h>
68 #include <assert.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <signal.h>
72 #include <time.h>
73
74 #include <security/pam_appl.h>
75
76 #define BUFSIZE 8192
77
78
79 /* The default PAM service name */
80 #ifndef SQUID_PAM_SERVICE
81 #define SQUID_PAM_SERVICE "squid"
82 #endif
83
84 /* How often to reinitialize PAM, in seconds. Undefined = never, 0=always */
85 /* #define PAM_CONNECTION_TTL 60 */
86
87 static int reset_pam = 1; /* Set to one if it is time to reset PAM processing */
88
89 static char *password = NULL; /* Workaround for Solaris 2.6 brokenness */
90
91 /*
92 * A simple "conversation" function returning the supplied password.
93 * Has a bit to much error control, but this is my first PAM application
94 * so I'd rather check everything than make any mistakes. The function
95 * expects a single converstation message of type PAM_PROMPT_ECHO_OFF.
96 */
97 static int
98 password_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
99 {
100 if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
101 fprintf(stderr, "ERROR: Unexpected PAM converstaion '%d/%s'\n", msg[0]->msg_style, msg[0]->msg);
102 return PAM_CONV_ERR;
103 }
104 if (!appdata_ptr) {
105 /* Workaround for Solaris 2.6 where the PAM library is broken
106 * and does not pass appdata_ptr to the conversation routine
107 */
108 appdata_ptr = password;
109 }
110 if (!appdata_ptr) {
111 fprintf(stderr, "ERROR: No password available to password_converstation!\n");
112 return PAM_CONV_ERR;
113 }
114 *resp = calloc(num_msg, sizeof(struct pam_response));
115 if (!*resp) {
116 fprintf(stderr, "ERROR: Out of memory!\n");
117 return PAM_CONV_ERR;
118 }
119 (*resp)[0].resp = strdup((char *) appdata_ptr);
120 (*resp)[0].resp_retcode = 0;
121
122 return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
123 }
124
125 static struct pam_conv conv =
126 {
127 &password_conversation,
128 NULL
129 };
130
131 void
132 signal_received(int sig)
133 {
134 reset_pam = 1;
135 signal(sig, signal_received);
136 }
137
138 int
139 main(int argc, char *argv[])
140 {
141 pam_handle_t *pamh = NULL;
142 int retval;
143 char *user;
144 /* char *password; */
145 char buf[BUFSIZE];
146 time_t pamh_created = 0;
147
148 signal(SIGHUP, signal_received);
149
150 /* make standard output line buffered */
151 setvbuf(stdout, NULL, _IOLBF, 0);
152
153 while (retval = PAM_SUCCESS, fgets(buf, BUFSIZE, stdin)) {
154 user = buf;
155 password = strchr(buf, '\n');
156 if (!password) {
157 fprintf(stderr, "authenticator: Unexpected input '%s'\n", buf);
158 fprintf(stdout, "ERR\n");
159 continue;
160 }
161 *password = '\0';
162 password = strchr(buf, ' ');
163 if (!password) {
164 fprintf(stderr, "authenticator: Unexpected input '%s'\n", buf);
165 fprintf(stdout, "ERR\n");
166 continue;
167 }
168 *password++ = '\0';
169 conv.appdata_ptr = (char *) password; /* from buf above. not allocated */
170 #ifdef PAM_CONNECTION_TTL
171 if (pamh_created + PAM_CONNECTION_TTL >= time(NULL))
172 reset_pam = 1;
173 #endif
174 if (reset_pam && pamh) {
175 /* Close previous PAM connection */
176 retval = pam_end(pamh, retval);
177 if (retval != PAM_SUCCESS) {
178 fprintf(stderr, "ERROR: failed to release PAM authenticator\n");
179 }
180 pamh = NULL;
181 }
182 if (!pamh) {
183 /* Initialize PAM connection */
184 retval = pam_start(SQUID_PAM_SERVICE, "squid@", &conv, &pamh);
185 if (retval != PAM_SUCCESS) {
186 fprintf(stderr, "ERROR: failed to create PAM authenticator\n");
187 }
188 reset_pam = 0;
189 pamh_created = time(NULL);
190 }
191 if (retval == PAM_SUCCESS)
192 retval = pam_set_item(pamh, PAM_USER, user);
193 if (retval == PAM_SUCCESS)
194 retval = pam_set_item(pamh, PAM_CONV, &conv);
195 if (retval == PAM_SUCCESS)
196 retval = pam_authenticate(pamh, 0);
197 if (retval == PAM_SUCCESS)
198 retval = pam_acct_mgmt(pamh, 0);
199 if (retval == PAM_SUCCESS) {
200 fprintf(stdout, "OK\n");
201 } else {
202 fprintf(stdout, "ERR\n");
203 }
204 }
205
206 if (pamh) {
207 retval = pam_end(pamh, retval);
208 if (retval != PAM_SUCCESS) {
209 pamh = NULL;
210 fprintf(stderr, "ERROR: failed to release PAM authenticator\n");
211 }
212 }
213 return (retval == PAM_SUCCESS ? 0 : 1); /* indicate success */
214 }