PAM-аутентификация для устаревшего приложения - PullRequest
8 голосов
/ 06 мая 2011

У меня есть устаревшее приложение, которое асинхронно получает запрос имени пользователя / пароля по сети.Поскольку у меня уже есть имя пользователя и пароль, которые хранятся в виде переменных, каков будет лучший способ аутентификации с помощью PAM в Linux (Debian 6)?

Я пытался написать свою собственную функцию диалога, но я неуверен, что лучший способ получить пароль в нем.Я подумал о том, чтобы сохранить его в appdata и сослаться на него из структуры pam_conv, но почти нет документации о том, как это сделать.

Есть ли более простой способ аутентификации пользователей без перерасхода функции разговора?Я также не могу успешно использовать pam_set_data, и я не уверен, что это даже уместно.

Вот что я делаю:

user = guiMessage->username;
pass = guiMessage->password;

pam_handle_t* pamh = NULL;
int           pam_ret;
struct pam_conv conv = {
  my_conv,
  NULL
};

pam_start("nxs_login", user, &conv, &pamh);
pam_ret = pam_authenticate(pamh, 0);

if (pam_ret == PAM_SUCCESS)
  permissions = 0xff;

pam_end(pamh, pam_ret);

И первые попытки использования функции разговора привелиin (пароль жестко запрограммирован для тестирования):

int 
my_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *data)
{
  struct pam_response *aresp;

  if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
    return (PAM_CONV_ERR);
  if ((aresp = (pam_response*)calloc(num_msg, sizeof *aresp)) == NULL)
    return (PAM_BUF_ERR);
  aresp[0].resp_retcode = 0;
  aresp[0].resp = strdup("mypassword");

  *resp = aresp;
  return (PAM_SUCCESS);
}

Любая помощь приветствуется.Спасибо!

Ответы [ 3 ]

14 голосов
/ 12 мая 2011

Я так и сделал. См. Комментарий, помеченный тремя звездочками.

#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <security/pam_appl.h>
#include <unistd.h>

// To build this:
// g++ test.cpp -lpam -o test

// if pam header files missing try:
// sudo apt install libpam0g-dev

struct pam_response *reply;

//function used to get user input
int function_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
{
  *resp = reply;
  return PAM_SUCCESS;
}

int main(int argc, char** argv)
{
  if(argc != 2) {
      fprintf(stderr, "Usage: check_user <username>\n");
      exit(1);
  }
  const char *username;
  username = argv[1];

  const struct pam_conv local_conversation = { function_conversation, NULL };
  pam_handle_t *local_auth_handle = NULL; // this gets set by pam_start

  int retval;

  // local_auth_handle gets set based on the service
  retval = pam_start("common-auth", username, &local_conversation, &local_auth_handle);

  if (retval != PAM_SUCCESS)
  {
    std::cout << "pam_start returned " << retval << std::endl;
    exit(retval);
  }

  reply = (struct pam_response *)malloc(sizeof(struct pam_response));

  // *** Get the password by any method, or maybe it was passed into this function.
  reply[0].resp = getpass("Password: ");
  reply[0].resp_retcode = 0;

  retval = pam_authenticate(local_auth_handle, 0);

  if (retval != PAM_SUCCESS)
  {
    if (retval == PAM_AUTH_ERR)
    {
      std::cout << "Authentication failure." << std::endl;
    }
    else
    {
      std::cout << "pam_authenticate returned " << retval << std::endl;
    }
    exit(retval);
  }

  std::cout << "Authenticated." << std::endl;

  retval = pam_end(local_auth_handle, retval);

  if (retval != PAM_SUCCESS)
  {
    std::cout << "pam_end returned " << retval << std::endl;
    exit(retval);
  }

  return retval;
}
2 голосов
/ 28 августа 2012

Способ передачи стандартной информации (такой как пароль) для PAM заключается в использовании переменных, установленных в дескрипторе pam с помощью pam_set_item (см. Справочную страницу для pam_set_item).

Вы можете установить все, что ваше приложение будетнужно использовать позже в pam_stack.Если вы хотите поместить пароль в стек pam_stack, вы сможете сделать это сразу после вызова pam_start (), установив переменную PAM_AUTHTOK в стек, как показано в псевдокоде ниже:

pam_handle_t* handle = NULL;
pam_start("common-auth", username, NULL, &handle);
pam_set_item( handle, PAM_AUTHTOK, password);

Это сделаетпароль, доступный в стеке для любого модуля, который хочет его использовать, но вы, как правило, должны указать модулю использовать его, установив стандартные параметры use_first_pass или try_first_pass в pam_configuration для службы (в данном случае / etc / pam.d / common-auth).

Стандартный модуль pam_unix поддерживает try_first_pass, поэтому было бы неплохо добавить это в конфигурацию pam в вашей системе (в конце строки для pam_unix).

После того, как вы сделаете это, любой вызов pam_authenticate () , который вызывается из службы общего аутентификации, должен просто подобрать пароль и пойти с ним.

Одна небольшая заметка оразница между use_first_pass и try_first_pass: они оба сообщают модулю (в данном случае pam_unix)попробовать пароль в pam_stack, но они отличаются по поведению, когда у них нет пароля / AUTHTOK.В пропущенном случае use_first_pass завершается неудачно, а try_first_pass позволяет модулю запрашивать пароль.

1 голос
/ 13 февраля 2018

Решение Fantius работало для меня, даже с правами суперпользователя.

Первоначально я выбрал решение Джона, так как оно было чище и использовало переменные PAM без функции диалога (на самом деле, в этом нет необходимости).для этого здесь), но это не работало и не будет работать.Как упоминал Адам Бадура в обеих публикациях, PAM имеет несколько внутренних проверок, чтобы предотвратить прямую установку PAM_AUTHTOK.

Решение Джона приведет к поведению, аналогичному тому, которое упоминается здесь , где любое значение паролябудет разрешено входить в систему (даже если вы объявите, но не определите переменную pam_conv).

Я бы также порекомендовал пользователям знать о расположении malloc, так как он, вероятно, будет отличаться в вашем приложении (помните, что приведенный выше код является скорее тестом / шаблоном, чем чем-либо еще).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...