LINUX.ORG.RU

Аутотентификация с использованием PAM

 , , ,


0

2

День добрый, Необходимо внедрить в ПО следующий функционал: Аутотентификация в программе одного из системных пользователей по логину и паролю (используя PAM). Проблема следующая: аутотентифицируется только тот пользователь, от имени которого запущена программа.

При авторизации любого пользователя, отличного от владельца терминала, с которого запускается программа, pam_strerror возвращает ошибку: «Сбой при проверке подлинности»

Инструментарий С++ и QT4.7

class MainWindow : public QMainWindow
{
    Q_OBJECT
   ...
public:
    QString pcode;
   ...
private:
    QString currUser;
    bool authenticated;
   ...
private slots:
    void doAutenticate ();
 ...
};

int converse(int n, const struct pam_message **msg,
    struct pam_response **resp, void *data);

Процедура аутотентификации:

void MainWindow::doAutenticate()
{
    authenticated = false;
    loginDialog dialog(this);
    if (dialog.exec())
    {
        char * user = (char*)dialog.getLogin().toAscii().data();
        pcode = dialog.getPassword();
        static pam_handle_t *pamh;
        struct pam_conv pamc = { converse, this };
 //       pcode = "";
        char hostname[MAXHOSTNAMELEN];
        char *ruser;
        int retcode = 0;
        pam_start("su", user, &pamc, &pamh);
        gethostname(hostname, sizeof(hostname));
        if ((retcode = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
        {
            qDebug() << "pam_set_item hostname failed. " << QString::fromLocal8Bit(pam_strerror(pamh, retcode));
        }
        else
        {
           ruser = getlogin();
           if ((retcode = pam_set_item(pamh, PAM_RUSER, ruser)) != PAM_SUCCESS)
            {
                qDebug() << "pam_set_item remote user failed. " << QString::fromLocal8Bit(pam_strerror(pamh, retcode));
            }
            if ((retcode = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
            {
                qDebug() << "pam_authenticate failed. " << QString::fromLocal8Bit(pam_strerror(pamh, retcode));
            }
            else
            {
                authenticated = true;
                qDebug() << "Authenticated !!!!";
            }
        }
    }
    else
    {
        authenticated = false;
    }
    updateUser();
}

Функция converse:

int converse(int n, const struct pam_message **msg, struct pam_response **resp, void *data)
{
    MainWindow* ob = static_cast<MainWindow*>(data);
    QString strp = ob->pcode;
    QByteArray ba = strp.toLatin1();
    char *pcodec = ba.data();
    struct pam_response *aresp;
    char buf[PAM_MAX_RESP_SIZE];
    int i;

    aresp = new pam_response;

    if (n <= 0 || n > PAM_MAX_NUM_MSG)
        return (PAM_CONV_ERR);
    for (i = 0; i < n; ++i) {
        aresp[i].resp_retcode = 0;
        aresp[i].resp = NULL;
        switch (msg[i]->msg_style) {
        case PAM_PROMPT_ECHO_OFF:
            aresp[i].resp = strdup(pcodec);
            if (aresp[i].resp == NULL)
                goto fail;
            break;
        case PAM_PROMPT_ECHO_ON:
            fputs(msg[i]->msg, stderr);
            if (fgets(buf, sizeof buf, stdin) == NULL)
                goto fail;
            aresp[i].resp = strdup(buf);
            if (aresp[i].resp == NULL)
                goto fail;
            break;
        case PAM_ERROR_MSG:
            fputs(msg[i]->msg, stderr);
            if (strlen(msg[i]->msg) > 0 &&
                msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
                fputc('\n', stderr);
            break;
        case PAM_TEXT_INFO:
            fputs(msg[i]->msg, stdout);
            if (strlen(msg[i]->msg) > 0 &&
                msg[i]->msg[strlen(msg[i]->msg) - 1] != '\n')
                fputc('\n', stdout);
            break;
        default:
            goto fail;
        }
    }
    *resp = aresp;
    return (PAM_SUCCESS);
 fail:
        for (i = 0; i < n; ++i) {
                if (aresp[i].resp != NULL) {
                        memset(aresp[i].resp, 0, strlen(aresp[i].resp));
                        free(aresp[i].resp);
                }
        }
        memset(aresp, 0, n * sizeof *aresp);
    *resp = NULL;
    return (PAM_CONV_ERR);
}

Заранее спасибо за помощь.



Последнее исправление: INZER (всего исправлений: 1)

Проблема следующая: аутотентифицируется только тот пользователь, от имени которого запущена программа.

Ну а чего ты ожидал то? Правов то нет, секьюрити :]

vasily_pupkin ★★★★★
()
Ответ на: комментарий от vasily_pupkin

Понятно что с секюрностью что то. Если запускать из рутового терминала то все ок :) По сути мне необходимо чтобы PAM проверял есть ли пользователь с заданым логином и паролем в системе. Это возможно? Или придется программу от рута запускать?

INZER
() автор топика
Ответ на: комментарий от INZER

Ну как бы для того, что бы аутентифицировать пользователя, приложению нужно считать его пароль. PAM - набор библиотек, без сервера аутентификации. Текущий пользователь может аутентифицировать себя благодаря suid хелперу unix_chkpwd. Можно написать свой/пофиксить unix_chkpwd. Корректнее запускать сервис от суперпользователя.

vasily_pupkin ★★★★★
()
Ответ на: комментарий от INZER

По сути мне необходимо чтобы PAM проверял есть ли пользователь с заданым логином и паролем в системе. Это возможно? Или придется программу от рута запускать?

сделай отдельный бинарь, который будет это делать, и повесь на него suid

ananas ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.