Всем привет.
Имеется следующий код:
#include <errno.h>
#include <libgen.h>
#include <malloc.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <termio.h>
#include <security/pam_appl.h>
#include <sys/types.h>
#include <pwd.h>
static int ctl_c; /* was the conversation interrupted? */
static void interrupt(int x) {
ctl_c = 1;
}
static char *getinput(int noecho) {
struct termio tty;
unsigned short tty_flags;
char input[PAM_MAX_RESP_SIZE];
int c;
int i = 0;
void (*sig)(int);
ctl_c = 0;
sig = signal(SIGINT, interrupt);
if (noecho) {
(void) ioctl(fileno(stdin), TCGETA, &tty);
tty_flags = tty.c_lflag;
tty.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
(void) ioctl(fileno(stdin), TCSETAF, &tty);
}
flockfile(stdin);
while (ctl_c == 0 && (c = getchar_unlocked()) != '\n' && c != '\r' && c != EOF) {
if (i < PAM_MAX_RESP_SIZE) {
input[i++] = (char) c;
}
}
funlockfile(stdin);
input[i] = '\0';
if (noecho) {
tty.c_lflag = tty_flags;
(void) ioctl(fileno(stdin), TCSETAW, &tty);
(void) fputc('\n', stdout);
}
(void) signal(SIGINT, sig);
if (ctl_c == 1) {
(void) kill(getpid(), SIGINT);
}
return (strdup(input));
}
static void free_resp(int num_msg, struct pam_response *pr) {
int i;
struct pam_response *r = pr;
if (pr == NULL)
return;
for (i = 0; i < num_msg; i++, r++) {
if (r->resp) {
bzero(r->resp, strlen(r->resp));
free(r->resp);
r->resp = NULL;
}
}
free(pr);
}
int pam_tty_conv(int num_msg, const pam_message **mess, pam_response **resp, void *my_data) {
struct pam_message *m = (struct pam_message*)*mess;
struct pam_response *r;
int i;
if (num_msg <= 0 || num_msg >= PAM_MAX_NUM_MSG) {
(void) fprintf(stderr, "bad number of messages %d <= 0 || >= %d\n", num_msg, PAM_MAX_NUM_MSG);
*resp = NULL;
return (PAM_CONV_ERR);
}
if ((*resp = r = (struct pam_response*)calloc(num_msg, sizeof(struct pam_response))) == NULL) {
return (PAM_BUF_ERR);
}
errno = 0;
for (i = 0; i < num_msg; i++) {
int echo_off;
if (m->msg == NULL) {
(void) fprintf(stderr, "message[%d]: %d/NULL\n", i, m->msg_style);
goto err;
}
r->resp = NULL;
r->resp_retcode = 0;
echo_off = 0;
switch (m->msg_style) {
case PAM_PROMPT_ECHO_OFF:
echo_off = 1;
case PAM_PROMPT_ECHO_ON:
(void) fputs(m->msg, stdout);
r->resp = strdup("password");
break;
case PAM_ERROR_MSG:
(void) fputs(m->msg, stderr);
(void) fputc('\n', stderr);
break;
case PAM_TEXT_INFO:
(void) fputs(m->msg, stdout);
(void) fputc('\n', stdout);
break;
default:
(void) fprintf(stderr, "message[%d]: unknown type %d/val=\"%s\"\n", i, m->msg_style, m->msg);
goto err;
}
if (errno == EINTR) {
goto err;
}
m++;
r++;
}
return (PAM_SUCCESS);
err:
free_resp(i, r);
*resp = NULL;
return (PAM_CONV_ERR);
}
/* Disable keyboard interrupts (Ctrl-C, Ctrl-Z, Ctrl-\) */
static void
disable_kbd_signals(void) {
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGTSTP, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
}
/* Terminate current user session, i.e., logout */
static void
logout() {
pid_t pgroup = getpgrp();
(void) signal(SIGTERM, SIG_IGN);
(void) fprintf(stderr, "Sorry, your session can't be restored.\n");
(void) fprintf(stderr, "Press return to terminate this session.\n");
(void) getchar();
(void) kill(-pgroup, SIGTERM);
(void) sleep(2);
(void) kill(-pgroup, SIGKILL);
exit(-1);
}
int main(int argc, char *argv[]) {
struct pam_conv conv = {pam_tty_conv, NULL};
pam_handle_t *pamh;
struct passwd *pw;
int err;
disable_kbd_signals();
if ((pw = getpwuid(getuid())) == NULL) {
(void) fprintf(stderr, "plock: Can't get username: %s\n", strerror(errno));
exit(1);
}
err = pam_start("system-auth", pw->pw_name, &conv, &pamh);
if (err != PAM_SUCCESS) {
(void) fprintf(stderr, "plock: pam_start failed: %s\n", pam_strerror(pamh, err));
exit(1);
}
do {
(void) fprintf(stderr, "Terminal locked for %s. ", pw->pw_name);
err = pam_authenticate(pamh, 0);
if (err == PAM_USER_UNKNOWN) {
logout();
} else if (err != PAM_SUCCESS) {
(void) fprintf(stderr, "Invalid password.\n");
}
} while (err != PAM_SUCCESS);
switch (err = pam_acct_mgmt(pamh, 0)) {
case PAM_SUCCESS:
break;
case PAM_USER_UNKNOWN:
case PAM_ACCT_EXPIRED:
logout();
break;
case PAM_NEW_AUTHTOK_REQD:
do {
err = pam_chauthtok(pamh, 0);
} while (err == PAM_AUTHTOK_ERR);
if (err != PAM_SUCCESS) {
logout();
}
break;
default:
logout();
}
if ((err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
logout();
}
if ((err = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
logout();
}
if ((err = pam_close_session(pamh, 0)) != PAM_SUCCESS) {
logout();
}
if ((err = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) {
logout();
}
if (pam_setcred(pamh, PAM_REFRESH_CRED) != PAM_SUCCESS) {
logout();
}
(void) pam_end(pamh, 0);
return (0);
}
Суть этой небольшой программки - проверка аутентификации - правильно ли введен пароль для пользователя который запускает программку.
На Астра и RedOS - данный код работает прекрасно.
Но, на ALT он постоянно падает с ошибкой pam_tcb(system-auth:auth): Authentication failed for user from user(uid=500)
Единственные мои подозрения это на схему tcb.
Возможно на ALT необходимо использовать что-то особенное?
Машина ALT 9.2 - была специально создана, чтобы проверить этот кусочек кода на работоспособность.