source: npl/system/pam_auth/pam_auth-2.0.c @ 105afb5

Last change on this file since 105afb5 was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100755
File size: 7.3 KB
Line 
1/*
2 * $Id: pam_auth-2.0.c 2685 2006-09-26 12:35:14Z edwin $
3 *
4 * PAM authenticator module for Squid.
5 * Copyright (C) 1999,2002 Henrik Nordstrom <hno@squid-cache.org>
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 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
20 *
21 * Install instructions:
22 *
23 * This program authenticates users against a PAM configured authentication
24 * service "squid". This allows you to authenticate Squid users to any
25 * authentication source for which you have a PAM module. Commonly available
26 * PAM modules includes "UNIX", RADIUS, Kerberos and SMB, but a lot of other
27 * PAM modules are available from various sources.
28 *
29 * Example PAM configuration for standard UNIX passwd authentication:
30 * /etc/pam.conf:
31 *  squid auth     required /lib/security/pam_unix.so.1
32 *  squid account  required /lib/security/pam_unix.so.1
33 *
34 * Note that some PAM modules (for example shadow password authentication)
35 * requires the program to be installed suid root to gain access to the
36 * user password database
37 *
38 * Change Log:
39 *
40 *   Version 2.0, 2002-01-07
41 *      One shot mode, command line options
42 *      man page
43 *
44 *   Version 1.3, 1999-12-10
45 *      Bugfix release 1.3 to work around Solaris 2.6
46 *      brokenness (not sending arguments to conversation
47 *      functions)
48 *
49 *   Version 1.2, internal release
50 *
51 *   Version 1.1, 1999-05-11
52 *      Initial version
53 *
54 * Compile this program with: gcc -o pam_auth pam_auth.c -lpam -ldl
55 */
56
57#include <stdio.h>
58#include <assert.h>
59#include <stdlib.h>
60#include <string.h>
61#include <signal.h>
62#include <time.h>
63#include <unistd.h>
64
65#include <security/pam_appl.h>
66
67#define BUFSIZE 8192
68
69
70/* The default PAM service name */
71#ifndef DEFAULT_SQUID_PAM_SERVICE
72#define DEFAULT_SQUID_PAM_SERVICE "squid"
73#endif
74
75/* The default TTL */
76#ifndef DEFAULT_SQUID_PAM_TTL
77#define DEFAULT_SQUID_PAM_TTL 60
78#endif
79
80static char *password = NULL;   /* Workaround for Solaris 2.6 brokenness */
81
82/*
83 * A simple "conversation" function returning the supplied password.
84 * Has a bit to much error control, but this is my first PAM application
85 * so I'd rather check everything than make any mistakes. The function
86 * expects a single converstation message of type PAM_PROMPT_ECHO_OFF.
87 */
88static int
89password_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
90{
91    if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
92        fprintf(stderr, "ERROR: Unexpected PAM converstaion '%d/%s'\n", msg[0]->msg_style, msg[0]->msg);
93        return PAM_CONV_ERR;
94    }
95    if (!appdata_ptr) {
96        /* Workaround for Solaris 2.6 where the PAM library is broken
97         * and does not pass appdata_ptr to the conversation routine
98         */
99        appdata_ptr = password;
100    }
101    if (!appdata_ptr) {
102        fprintf(stderr, "ERROR: No password available to password_converstation!\n");
103        return PAM_CONV_ERR;
104    }
105    *resp = calloc(num_msg, sizeof(struct pam_response));
106    if (!*resp) {
107        fprintf(stderr, "ERROR: Out of memory!\n");
108        return PAM_CONV_ERR;
109    }
110    (*resp)[0].resp = strdup((char *) appdata_ptr);
111    (*resp)[0].resp_retcode = 0;
112
113    return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
114}
115
116static struct pam_conv conv =
117{
118    &password_conversation,
119    NULL
120};
121
122static void usage(char *program)
123{
124    fprintf(stderr, "Usage: %s [options..]\n", program);
125    fprintf(stderr, " -n service_name\n");
126    fprintf(stderr, "           The PAM service name (default \"%s\")\n", DEFAULT_SQUID_PAM_SERVICE);
127    fprintf(stderr, " -t ttl    PAM connection ttl in seconds (default %d)\n", DEFAULT_SQUID_PAM_TTL);
128    fprintf(stderr, "           during this time the same connection will be reused\n");
129    fprintf(stderr, "           to authenticate all users\n");
130    fprintf(stderr, " -o        Do not perform account mgmt (account expiration etc)\n");
131    fprintf(stderr, " -1        Only one user authentication per PAM connection\n");
132}
133
134int
135main(int argc, char *argv[])
136{
137    pam_handle_t *pamh = NULL;
138    int retval = PAM_SUCCESS;
139    char *user;
140    /* char *password; */
141    char buf[BUFSIZE];
142    time_t pamh_created = 0;
143    int ttl = DEFAULT_SQUID_PAM_TTL;
144    char *service = DEFAULT_SQUID_PAM_SERVICE;
145    int no_acct_mgmt = 0;
146
147    /* make standard output line buffered */
148    setvbuf(stdout, NULL, _IOLBF, 0);
149
150    while (1) {
151        int ch = getopt(argc, argv, "1n:t:o");
152        switch (ch) {
153        case -1:
154                goto start;
155        case 'n':
156                service = optarg;
157                break;
158        case 't':
159                ttl = atoi(optarg);
160                break;
161        case '1':
162                ttl = 0;
163                break;
164        case 'o':
165                no_acct_mgmt = 1;
166                break;
167        default:
168                fprintf(stderr, "Unknown getopt value '%c'\n", ch);
169                usage(argv[0]);
170                exit(1);
171        }
172    }
173start:
174    if (optind < argc) {
175        fprintf(stderr, "Unknown option '%s'\n", argv[optind]);
176        usage(argv[0]);
177        exit(1);
178    }
179
180    while (fgets(buf, BUFSIZE, stdin)) {
181        user = buf;
182        password = strchr(buf, '\n');
183        if (!password) {
184            fprintf(stderr, "authenticator: Unexpected input '%s'\n", buf);
185            goto error;
186        }
187        *password = '\0';
188        password = strchr(buf, ' ');
189        if (!password) {
190            fprintf(stderr, "authenticator: Unexpected input '%s'\n", buf);
191            goto error;
192        }
193        *password++ = '\0';
194        conv.appdata_ptr = (char *) password;   /* from buf above. not allocated */
195
196        if (ttl == 0) {
197            /* Create PAM connection */
198            retval = pam_start(service, user, &conv, &pamh);
199            if (retval != PAM_SUCCESS) {
200                fprintf(stderr, "ERROR: failed to create PAM authenticator\n");
201                goto error;
202            }
203        } else if (!pamh || (time(NULL) - pamh_created) >= ttl || pamh_created > time(NULL)) {
204            /* Close previous PAM connection */
205            if (pamh) {
206                retval = pam_end(pamh, retval);
207                if (retval != PAM_SUCCESS) {
208                    fprintf(stderr, "WARNING: failed to release PAM authenticator\n");
209                }
210                pamh = NULL;
211            }
212            /* Initialize persistent PAM connection */
213            retval = pam_start(service, "squid@", &conv, &pamh);
214            if (retval != PAM_SUCCESS) {
215                fprintf(stderr, "ERROR: failed to create PAM authenticator\n");
216                goto error;
217            }
218            pamh_created = time(NULL);
219        }
220        retval = PAM_SUCCESS;
221        if (ttl != 0) {
222            if (retval == PAM_SUCCESS)
223                retval = pam_set_item(pamh, PAM_USER, user);
224            if (retval == PAM_SUCCESS)
225                retval = pam_set_item(pamh, PAM_CONV, &conv);
226        }
227        if (retval == PAM_SUCCESS)
228            retval = pam_authenticate(pamh, 0);
229        if (retval == PAM_SUCCESS && !no_acct_mgmt)
230            retval = pam_acct_mgmt(pamh, 0);
231        if (retval == PAM_SUCCESS) {
232            fprintf(stdout, "OK\n");
233        } else {
234error:
235            fprintf(stdout, "ERR\n");
236        }
237        if (ttl == 0) {
238            retval = pam_end(pamh, retval);
239            if (retval != PAM_SUCCESS) {
240                fprintf(stderr, "WARNING: failed to release PAM authenticator\n");
241            }
242            pamh = NULL;
243        }
244    }
245
246    if (pamh) {
247        retval = pam_end(pamh, retval);
248        if (retval != PAM_SUCCESS) {
249            pamh = NULL;
250            fprintf(stderr, "ERROR: failed to release PAM authenticator\n");
251        }
252    }
253    return 0;
254}
Note: See TracBrowser for help on using the repository browser.