Annotation of ircnowd/src/ngircd/pam.c, Revision 1.1.1.1
1.1 tomglok 1: /*
2: * ngIRCd -- The Next Generation IRC Daemon
3: * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
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:
12: #include "portab.h"
13:
14: #ifdef PAM
15:
16: /**
17: * @file
18: * PAM User Authentication
19: */
20:
21: #include <assert.h>
22: #include <stdlib.h>
23: #include <string.h>
24: #ifdef HAVE_SECURITY_PAM_APPL_H
25: # include <security/pam_appl.h>
26: #endif
27: #ifdef HAVE_PAM_PAM_APPL_H
28: # include <pam/pam_appl.h>
29: #endif
30:
31: #include "defines.h"
32: #include "log.h"
33: #include "conn.h"
34: #include "client.h"
35: #include "conf.h"
36:
37: #include "pam.h"
38:
39: static char *password;
40:
41: /**
42: * PAM "conversation function".
43: * This is a callback function used by the PAM library to get the password.
44: * Please see the PAM documentation for details :-)
45: */
46: static int
47: password_conversation(int num_msg, const struct pam_message **msg,
48: struct pam_response **resp, void *appdata_ptr) {
49: LogDebug("PAM: conv(%d, %d, '%s', '%s')",
50: num_msg, msg[0]->msg_style, msg[0]->msg, appdata_ptr);
51:
52: /* Can we deal with this request? */
53: if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
54: Log(LOG_ERR, "PAM: Unexpected PAM conversation '%d:%s'!",
55: msg[0]->msg_style, msg[0]->msg);
56: return PAM_CONV_ERR;
57: }
58:
59: if (!appdata_ptr) {
60: /* Sometimes appdata_ptr gets lost!? */
61: appdata_ptr = password;
62: }
63:
64: /* Duplicate password ("application data") for the PAM library */
65: *resp = calloc(num_msg, sizeof(struct pam_response));
66: if (!*resp) {
67: Log(LOG_ERR, "PAM: Out of memory!");
68: return PAM_CONV_ERR;
69: }
70:
71: (*resp)[0].resp = strdup((char *)appdata_ptr);
72: (*resp)[0].resp_retcode = 0;
73:
74: return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
75: }
76:
77: /**
78: * PAM "conversation" structure.
79: */
80: static struct pam_conv conv = {
81: &password_conversation,
82: NULL
83: };
84:
85: /**
86: * Authenticate a connecting client using PAM.
87: * @param Client The client to authenticate.
88: * @return true when authentication succeeded, false otherwise.
89: */
90: GLOBAL bool
91: PAM_Authenticate(CLIENT *Client) {
92: pam_handle_t *pam;
93: int retval = PAM_SUCCESS;
94:
95: LogDebug("PAM: Authenticate \"%s\" (%s) ...",
96: Client_OrigUser(Client), Client_Mask(Client));
97:
98: /* Set supplied client password */
99: if (password)
100: free(password);
101: password = strdup(Conn_Password(Client_Conn(Client)));
102: conv.appdata_ptr = Conn_Password(Client_Conn(Client));
103:
104: /* Initialize PAM */
105: retval = pam_start(Conf_PAMServiceName, Client_OrigUser(Client), &conv, &pam);
106: if (retval != PAM_SUCCESS) {
107: Log(LOG_ERR, "PAM: Failed to create authenticator! (%d)", retval);
108: return false;
109: }
110:
111: pam_set_item(pam, PAM_RUSER, Client_User(Client));
112: pam_set_item(pam, PAM_RHOST, Client_Hostname(Client));
113: #if defined(HAVE_PAM_FAIL_DELAY) && !defined(NO_PAM_FAIL_DELAY)
114: pam_fail_delay(pam, 0);
115: #endif
116:
117: /* PAM authentication ... */
118: retval = pam_authenticate(pam, 0);
119:
120: /* Success? */
121: if (retval == PAM_SUCCESS)
122: Log(LOG_INFO, "PAM: Authenticated \"%s\" (%s).",
123: Client_OrigUser(Client), Client_Mask(Client));
124: else
125: Log(LOG_ERR, "PAM: Error on \"%s\" (%s): %s",
126: Client_OrigUser(Client), Client_Mask(Client),
127: pam_strerror(pam, retval));
128:
129: /* Free PAM structures */
130: if (pam_end(pam, retval) != PAM_SUCCESS)
131: Log(LOG_ERR, "PAM: Failed to release authenticator!");
132:
133: return (retval == PAM_SUCCESS);
134: }
135:
136: #endif /* PAM */
137:
138: /* -eof- */
CVSweb