pam.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2010 Alexander Barton (alex@barton.de).
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. * Please read the file COPYING, README and AUTHORS for more information.
  10. */
  11. #include "portab.h"
  12. #ifdef PAM
  13. /**
  14. * @file
  15. * PAM User Authentification
  16. */
  17. #include "imp.h"
  18. #include <assert.h>
  19. #include "defines.h"
  20. #include "log.h"
  21. #include "conn.h"
  22. #include "client.h"
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #ifdef HAVE_SECURITY_PAM_APPL_H
  26. #include <security/pam_appl.h>
  27. #endif
  28. #ifdef HAVE_PAM_PAM_APPL_H
  29. #include <pam/pam_appl.h>
  30. #endif
  31. #include "exp.h"
  32. #include "pam.h"
  33. static char *password;
  34. /**
  35. * PAM "conversation function".
  36. * This is a callback function used by the PAM library to get the password.
  37. * Please see the PAM documentation for details :-)
  38. */
  39. static int
  40. password_conversation(int num_msg, const struct pam_message **msg,
  41. struct pam_response **resp, void *appdata_ptr) {
  42. LogDebug("PAM: conv(%d, %d, '%s', '%s')",
  43. num_msg, msg[0]->msg_style, msg[0]->msg, appdata_ptr);
  44. /* Can we deal with this request? */
  45. if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
  46. Log(LOG_ERR, "PAM: Unexpected PAM conversation '%d:%s'!",
  47. msg[0]->msg_style, msg[0]->msg);
  48. return PAM_CONV_ERR;
  49. }
  50. if (!appdata_ptr) {
  51. /* Sometimes appdata_ptr gets lost!? */
  52. appdata_ptr = password;
  53. }
  54. /* Duplicate password ("application data") for the PAM library */
  55. *resp = calloc(num_msg, sizeof(struct pam_response));
  56. if (!*resp) {
  57. Log(LOG_ERR, "PAM: Out of memory!");
  58. return PAM_CONV_ERR;
  59. }
  60. (*resp)[0].resp = strdup((char *)appdata_ptr);
  61. (*resp)[0].resp_retcode = 0;
  62. return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
  63. }
  64. /**
  65. * PAM "conversation" structure.
  66. */
  67. static struct pam_conv conv = {
  68. &password_conversation,
  69. NULL
  70. };
  71. /**
  72. * Authenticate a connectiong client using PAM.
  73. * @param Client The client to authenticate.
  74. * @return true when authentication succeeded, false otherwise.
  75. */
  76. GLOBAL bool
  77. PAM_Authenticate(CLIENT *Client) {
  78. pam_handle_t *pam;
  79. int retval = PAM_SUCCESS;
  80. LogDebug("PAM: Authenticate \"%s\" (%s) ...",
  81. Client_OrigUser(Client), Client_Mask(Client));
  82. /* Set supplied client password */
  83. if (password)
  84. free(password);
  85. password = strdup(Conn_Password(Client_Conn(Client)));
  86. conv.appdata_ptr = Conn_Password(Client_Conn(Client));
  87. /* Initialize PAM */
  88. retval = pam_start("ngircd", Client_OrigUser(Client), &conv, &pam);
  89. if (retval != PAM_SUCCESS) {
  90. Log(LOG_ERR, "PAM: Failed to create authenticator! (%d)", retval);
  91. return false;
  92. }
  93. pam_set_item(pam, PAM_RUSER, Client_User(Client));
  94. pam_set_item(pam, PAM_RHOST, Client_Hostname(Client));
  95. #if defined(HAVE_PAM_FAIL_DELAY) && !defined(NO_PAM_FAIL_DELAY)
  96. pam_fail_delay(pam, 0);
  97. #endif
  98. /* PAM authentication ... */
  99. retval = pam_authenticate(pam, 0);
  100. /* Success? */
  101. if (retval == PAM_SUCCESS)
  102. Log(LOG_INFO, "PAM: Authenticated \"%s\" (%s).",
  103. Client_OrigUser(Client), Client_Mask(Client));
  104. else
  105. Log(LOG_ERR, "PAM: Error on \"%s\" (%s): %s",
  106. Client_OrigUser(Client), Client_Mask(Client),
  107. pam_strerror(pam, retval));
  108. /* Free PAM structures */
  109. if (pam_end(pam, retval) != PAM_SUCCESS)
  110. Log(LOG_ERR, "PAM: Failed to release authenticator!");
  111. return (retval == PAM_SUCCESS);
  112. }
  113. #endif /* PAM */
  114. /* -eof- */