85#if HAVE_SECURITY_PAM_APPL_H
86#include <security/pam_appl.h>
90#if !defined(DEFAULT_SQUID_PAM_SERVICE)
91#define DEFAULT_SQUID_PAM_SERVICE "squid"
95#if !defined(DEFAULT_SQUID_PAM_TTL)
96#define DEFAULT_SQUID_PAM_TTL 0
100static char *password =
nullptr;
104 struct pam_response **resp,
void *appdata_ptr);
113password_conversation(
int num_msg, PAM_CONV_FUNC_CONST_PARM
struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
115 if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
116 debug(
"ERROR: Unexpected PAM converstaion '%d/%s'\n", msg[0]->msg_style, msg[0]->msg);
124 appdata_ptr = password;
128 debug(
"ERROR: No password available to password_converstation!\n");
131 *resp =
static_cast<struct pam_response *
>(calloc(num_msg,
sizeof(
struct pam_response)));
133 debug(
"ERROR: Out of memory!\n");
136 (*resp)[0].resp =
xstrdup((
char *) appdata_ptr);
137 (*resp)[0].resp_retcode = 0;
139 return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
149 fprintf(stderr,
"Usage: %s [options..]\n", program);
150 fprintf(stderr,
" -n service_name\n");
153 fprintf(stderr,
" during this time the same connection will be reused\n");
154 fprintf(stderr,
" to authenticate all users\n");
155 fprintf(stderr,
" -o Do not perform account mgmt (account expiration etc)\n");
156 fprintf(stderr,
" -1 Only one user authentication per PAM connection\n");
157 fprintf(stderr,
" -r Detect and remove Negotiate/NTLM realm from username\n");
163 pam_handle_t *pamh =
nullptr;
164 int retval = PAM_SUCCESS;
168 time_t pamh_created = 0;
171 int no_acct_mgmt = 0;
175 setvbuf(stdout,
nullptr, _IOLBF, 0);
178 int ch =
getopt(argc, argv,
"1n:t:or");
198 fprintf(stderr,
"FATAL: Unknown getopt value '%c'\n", ch);
205 fprintf(stderr,
"FATAL: Unknown option '%s'\n", argv[
optind]);
212 password_buf = strchr(buf,
'\n');
214 debug(
"ERROR: %s: Unexpected input '%s'\n", argv[0], buf);
217 *password_buf =
'\0';
218 password_buf = strchr(buf,
' ');
220 debug(
"ERROR: %s: Unexpected input '%s'\n", argv[0], buf);
223 *password_buf =
'\0';
227 conv.appdata_ptr = (
char *) password_buf;
233 char * user_ptr = strchr(user,
'@');
234 if (user_ptr) *user_ptr = 0;
236 user_ptr = strchr(user,
'\\');
237 if (user_ptr) user = user_ptr + 1;
245 password = password_buf;
249 retval = pam_start(service, user, &
conv, &pamh);
250 if (retval != PAM_SUCCESS) {
251 debug(
"ERROR: failed to create PAM authenticator\n");
254 }
else if (!pamh || (time(
NULL) - pamh_created) >= ttl || pamh_created > time(
NULL)) {
257 retval = pam_end(pamh, retval);
258 if (retval != PAM_SUCCESS) {
259 debug(
"WARNING: failed to release PAM authenticator\n");
264 retval = pam_start(service,
"squid@", &
conv, &pamh);
265 if (retval != PAM_SUCCESS) {
266 debug(
"ERROR: failed to create PAM authenticator\n");
269 pamh_created = time(
NULL);
272 retval = PAM_SUCCESS;
274 retval = pam_set_item(pamh, PAM_USER, user);
275 if (retval == PAM_SUCCESS)
276 retval = pam_set_item(pamh, PAM_CONV, &
conv);
278 if (retval == PAM_SUCCESS)
279 retval = pam_authenticate(pamh, 0);
280 if (retval == PAM_SUCCESS && !no_acct_mgmt)
281 retval = pam_acct_mgmt(pamh, 0);
282 if (retval == PAM_SUCCESS) {
289 retval = PAM_SUCCESS;
290#if defined(PAM_AUTHTOK)
291 if (ttl != 0 && pamh) {
292 retval = pam_set_item(pamh, PAM_AUTHTOK,
nullptr);
295 if (pamh && (ttl == 0 || retval != PAM_SUCCESS)) {
296 retval = pam_end(pamh, retval);
297 if (retval != PAM_SUCCESS) {
298 debug(
"WARNING: failed to release PAM authenticator\n");
305 retval = pam_end(pamh, retval);
306 if (retval != PAM_SUCCESS) {
308 debug(
"ERROR: failed to release PAM authenticator\n");
void error(char *format,...)
#define HELPER_INPUT_BUFFER
int main(int argc, char *argv[])
static struct pam_conv conv
#define DEFAULT_SQUID_PAM_SERVICE
int password_conversation(int num_msg, PAM_CONV_FUNC_CONST_PARM struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
static void usage(char *program)
#define DEFAULT_SQUID_PAM_TTL
void debug(const char *format,...)
int getopt(int nargc, char *const *nargv, const char *ostr)
void rfc1738_unescape(char *url)