Line data Source code
1 : /*
2 : SSSD
3 :
4 : NSS Responder - Data Provider Interfaces
5 :
6 : Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include <sys/time.h>
23 : #include <time.h>
24 :
25 : #include <talloc.h>
26 : #include <security/pam_modules.h>
27 :
28 : #include "util/util.h"
29 : #include "responder/common/responder_packet.h"
30 : #include "providers/data_provider.h"
31 : #include "sbus/sbus_client.h"
32 : #include "responder/pam/pamsrv.h"
33 :
34 0 : static void pam_dp_process_reply(DBusPendingCall *pending, void *ptr)
35 : {
36 : DBusError dbus_error;
37 : DBusMessage* msg;
38 : int ret;
39 : int type;
40 0 : struct pam_auth_req *preq = NULL;
41 : struct pam_auth_dp_req *pdp_req;
42 :
43 0 : pdp_req = talloc_get_type(ptr, struct pam_auth_dp_req);
44 0 : preq = pdp_req->preq;
45 0 : talloc_free(pdp_req);
46 :
47 0 : dbus_error_init(&dbus_error);
48 0 : msg = dbus_pending_call_steal_reply(pending);
49 :
50 : /* Check if the client still exists. If not, simply free all the resources
51 : * and quit */
52 0 : if (preq == NULL) {
53 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Client already disconnected\n");
54 0 : dbus_pending_call_unref(pending);
55 0 : dbus_message_unref(msg);
56 0 : return;
57 : }
58 :
59 : /* Sanity-check of message validity */
60 0 : if (msg == NULL) {
61 0 : DEBUG(SSSDBG_FATAL_FAILURE,
62 : "Severe error. A reply callback was called but no reply was"
63 : "received and no timeout occurred\n");
64 0 : preq->pd->pam_status = PAM_SYSTEM_ERR;
65 0 : goto done;
66 : }
67 :
68 0 : type = dbus_message_get_type(msg);
69 0 : switch (type) {
70 : case DBUS_MESSAGE_TYPE_METHOD_RETURN:
71 0 : ret = dp_unpack_pam_response(msg, preq->pd, &dbus_error);
72 0 : if (!ret) {
73 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to parse reply.\n");
74 0 : preq->pd->pam_status = PAM_SYSTEM_ERR;
75 0 : goto done;
76 : }
77 0 : DEBUG(SSSDBG_FUNC_DATA,
78 : "received: [%d (%s)][%s]\n", preq->pd->pam_status,
79 : pam_strerror(NULL, preq->pd->pam_status),
80 : preq->pd->domain);
81 0 : break;
82 : case DBUS_MESSAGE_TYPE_ERROR:
83 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Reply error.\n");
84 0 : preq->pd->pam_status = PAM_SYSTEM_ERR;
85 0 : break;
86 : default:
87 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Default... what now?.\n");
88 0 : preq->pd->pam_status = PAM_SYSTEM_ERR;
89 : }
90 :
91 :
92 : done:
93 0 : dbus_pending_call_unref(pending);
94 0 : dbus_message_unref(msg);
95 0 : preq->callback(preq);
96 : }
97 :
98 0 : static int pdp_req_destructor(struct pam_auth_dp_req *pdp_req)
99 : {
100 0 : if (pdp_req && pdp_req->preq) {
101 : /* If there is still a client waiting, reset the
102 : * spy */
103 0 : pdp_req->preq->dpreq_spy = NULL;
104 : }
105 0 : return 0;
106 : }
107 :
108 0 : int pam_dp_send_req(struct pam_auth_req *preq, int timeout)
109 : {
110 0 : struct pam_data *pd = preq->pd;
111 : struct be_conn *be_conn;
112 : DBusMessage *msg;
113 : dbus_bool_t ret;
114 : int res;
115 : struct pam_auth_dp_req *pdp_req;
116 :
117 : /* double check dp_ctx has actually been initialized.
118 : * in some pathological cases it may happen that nss starts up before
119 : * dp connection code is actually able to establish a connection.
120 : */
121 0 : res = sss_dp_get_domain_conn(preq->cctx->rctx,
122 0 : preq->domain->conn_name, &be_conn);
123 0 : if (res != EOK) {
124 0 : DEBUG(SSSDBG_CRIT_FAILURE,
125 : "The Data Provider connection for %s is not available!"
126 : " This maybe a bug, it shouldn't happen!\n",
127 : preq->domain->conn_name);
128 0 : return EIO;
129 : }
130 :
131 0 : msg = dbus_message_new_method_call(NULL,
132 : DP_PATH,
133 : DATA_PROVIDER_IFACE,
134 : DATA_PROVIDER_IFACE_PAMHANDLER);
135 0 : if (msg == NULL) {
136 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
137 0 : return ENOMEM;
138 : }
139 :
140 :
141 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Sending request with the following data:\n");
142 0 : DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
143 :
144 0 : ret = dp_pack_pam_request(msg, pd);
145 0 : if (!ret) {
146 0 : DEBUG(SSSDBG_CRIT_FAILURE,"Failed to build message\n");
147 0 : return EIO;
148 : }
149 :
150 0 : pdp_req = talloc(preq->cctx->rctx, struct pam_auth_dp_req);
151 0 : if (pdp_req == NULL) {
152 0 : return ENOMEM;
153 : }
154 0 : pdp_req->preq = preq;
155 0 : preq->dpreq_spy = pdp_req;
156 0 : talloc_set_destructor(pdp_req, pdp_req_destructor);
157 :
158 0 : res = sbus_conn_send(be_conn->conn, msg,
159 : timeout, pam_dp_process_reply,
160 : pdp_req, NULL);
161 0 : dbus_message_unref(msg);
162 0 : return res;
163 : }
164 :
|