You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
4.6 KiB

/* Copyright (C) 2004-2007 Philippe Troin <phil@fifi.org>
* I hereby place this program in the public domain.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <security/pam_appl.h>
struct pam_closure {
const char *user;
const char *typed_passwd;
int verbose_p;
};
static int
pam_conversation (int nmsgs,
const struct pam_message **msg,
struct pam_response **resp,
void *closure)
{
int replies = 0;
struct pam_response *reply = 0;
struct pam_closure *c = (struct pam_closure *) closure;
reply = (struct pam_response *) calloc (nmsgs, sizeof (*reply));
if (!reply) return PAM_CONV_ERR;
for (replies = 0; replies < nmsgs; replies++)
{
switch (msg[replies]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = strdup (c->user); /* freed by PAM */
if (c->verbose_p)
fprintf (stderr, " PAM ECHO_ON(\"%s\") ==> \"%s\"\n",
msg[replies]->msg,
reply[replies].resp);
break;
case PAM_PROMPT_ECHO_OFF:
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = strdup (c->typed_passwd); /* freed by PAM */
if (c->verbose_p)
fprintf (stderr, " PAM ECHO_OFF(\"%s\") ==> password\n",
msg[replies]->msg);
break;
case PAM_TEXT_INFO:
/* ignore it... */
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = 0;
if (c->verbose_p)
fprintf (stderr, " PAM TEXT_INFO(\"%s\") ==> ignored\n",
msg[replies]->msg);
break;
case PAM_ERROR_MSG:
/* ignore it... */
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = 0;
if (c->verbose_p)
fprintf (stderr, " PAM ERROR_MSG(\"%s\") ==> ignored\n",
msg[replies]->msg);
break;
default:
/* Must be an error of some sort... */
free (reply);
if (c->verbose_p)
fprintf (stderr, " PAM unknown %d(\"%s\") ==> ignored\n",
msg[replies]->msg_style, msg[replies]->msg);
return PAM_CONV_ERR;
}
}
*resp = reply;
return PAM_SUCCESS;
}
int
pwvalid (const char* typed_user, const char *typed_passwd, int verbose_p)
{
const char *service = "pamauth";
pam_handle_t *pamh = 0;
int status = -1;
struct pam_conv pc;
struct pam_closure c;
c.user = typed_user;
c.typed_passwd = typed_passwd;
c.verbose_p = verbose_p;
pc.conv = &pam_conversation;
pc.appdata_ptr = (void *) &c;
/* Initialize PAM.
*/
status = pam_start (service, c.user, &pc, &pamh);
if (verbose_p)
fprintf (stderr, " pam_start (\"%s\", \"%s\", ...) ==> %d (%s)\n",
service, c.user,
status, pam_strerror (pamh, status));
if (status != PAM_SUCCESS) goto DONE;
{
const char *tty = "web";
status = pam_set_item (pamh, PAM_TTY, strdup(tty));
if (verbose_p)
fprintf (stderr, " pam_set_item (p, PAM_TTY, \"%s\") ==> %d (%s)\n",
tty, status, pam_strerror(pamh, status));
}
status = pam_set_item (pamh, PAM_RUSER, strdup(c.user));
if (verbose_p)
fprintf (stderr, " pam_set_item(p, PAM_RUSER, \"%s\") ==> %d (%s)\n",
c.user, status, pam_strerror(pamh, status));
if (status != PAM_SUCCESS) goto DONE;
pam_fail_delay(pamh, 1);
status = pam_authenticate (pamh, 0);
if (verbose_p)
fprintf (stderr, " pam_authenticate (...) ==> %d (%s)\n",
status, pam_strerror(pamh, status));
DONE:
if (pamh)
{
int status2 = pam_end (pamh, status);
pamh = 0;
if (verbose_p)
fprintf (stderr, " pam_end (...) ==> %d (%s)\n",
status2,
(status2 == PAM_SUCCESS ? "Success" : "Failure"));
}
return (status == PAM_SUCCESS ? 1 : 0);
}
int
main(int argc, char *argv[])
{
static const int bufsize = 1024;
char password[bufsize];
int passwordlen;
/**/
fprintf(stderr, "usage: " );
if (argc != 2)
{
fprintf(stderr, "usage: %s <login>\n", argv[0]);
return 1;
}
if (isatty(fileno(stdin)))
{
fprintf(stderr, "%s: cannot be used on a tty\n", argv[0]);
return 1;
}
fgets(password, bufsize, stdin);
passwordlen = strlen(password);
if (password[passwordlen-1] == '\n')
password[passwordlen-1] = 0;
return pwvalid(argv[1], password, 0) ? 0 : 1;
}

Powered by BW's shoe-string budget.