Line data Source code
1 : /*
2 : SSSD
3 :
4 : proxy_init.c
5 :
6 : Authors:
7 : Stephen Gallagher <sgallagh@redhat.com>
8 :
9 : Copyright (C) 2010 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "config.h"
26 :
27 : #include "util/sss_format.h"
28 : #include "providers/proxy/proxy.h"
29 :
30 : static int client_registration(struct sbus_request *dbus_req, void *data);
31 :
32 : static struct data_provider_iface proxy_methods = {
33 : { &data_provider_iface_meta, 0 },
34 : .RegisterService = client_registration,
35 : .pamHandler = NULL,
36 : .sudoHandler = NULL,
37 : .autofsHandler = NULL,
38 : .hostHandler = NULL,
39 : .getDomains = NULL,
40 : .getAccountInfo = NULL,
41 : };
42 :
43 : struct proxy_client {
44 : struct proxy_auth_ctx *proxy_auth_ctx;
45 : struct sbus_connection *conn;
46 : struct tevent_timer *timeout;
47 : bool initialized;
48 : };
49 :
50 0 : static int client_registration(struct sbus_request *dbus_req, void *data)
51 : {
52 0 : dbus_uint16_t version = DATA_PROVIDER_VERSION;
53 : struct sbus_connection *conn;
54 : struct proxy_client *proxy_cli;
55 : dbus_uint16_t cli_ver;
56 : uint32_t cli_id;
57 : int hret;
58 : hash_key_t key;
59 : hash_value_t value;
60 : struct tevent_req *req;
61 : struct proxy_child_ctx *child_ctx;
62 : struct pc_init_ctx *init_ctx;
63 : int ret;
64 :
65 0 : conn = dbus_req->conn;
66 0 : proxy_cli = talloc_get_type(data, struct proxy_client);
67 0 : if (!proxy_cli) {
68 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n");
69 0 : return EINVAL;
70 : }
71 :
72 : /* First thing, cancel the timeout */
73 0 : DEBUG(SSSDBG_CONF_SETTINGS,
74 : "Cancel proxy client ID timeout [%p]\n", proxy_cli->timeout);
75 0 : talloc_zfree(proxy_cli->timeout);
76 :
77 0 : if (!sbus_request_parse_or_finish(dbus_req,
78 : DBUS_TYPE_UINT16, &cli_ver,
79 : DBUS_TYPE_UINT32, &cli_id,
80 : DBUS_TYPE_INVALID)) {
81 0 : sbus_disconnect(conn);
82 0 : return EOK; /* handled */
83 : }
84 :
85 0 : DEBUG(SSSDBG_FUNC_DATA, "Proxy client [%"PRIu32"] connected\n", cli_id);
86 :
87 : /* Check the hash table */
88 0 : key.type = HASH_KEY_ULONG;
89 0 : key.ul = cli_id;
90 0 : if (!hash_has_key(proxy_cli->proxy_auth_ctx->request_table, &key)) {
91 0 : DEBUG(SSSDBG_CRIT_FAILURE,
92 : "Unknown child ID. Killing the connection\n");
93 0 : sbus_disconnect(proxy_cli->conn);
94 0 : return EIO;
95 : }
96 :
97 : /* reply that all is ok */
98 0 : ret = sbus_request_return_and_finish(dbus_req,
99 : DBUS_TYPE_UINT16, &version,
100 : DBUS_TYPE_INVALID);
101 0 : if (ret != EOK) {
102 0 : sbus_disconnect(conn);
103 0 : return ret;
104 : }
105 :
106 0 : hret = hash_lookup(proxy_cli->proxy_auth_ctx->request_table, &key, &value);
107 0 : if (hret != HASH_SUCCESS) {
108 0 : DEBUG(SSSDBG_CRIT_FAILURE,
109 : "Hash error [%d][%s]\n", hret, hash_error_string(hret));
110 0 : sbus_disconnect(conn);
111 : }
112 :
113 : /* Signal that the child is up and ready to receive the request */
114 0 : req = talloc_get_type(value.ptr, struct tevent_req);
115 0 : child_ctx = tevent_req_data(req, struct proxy_child_ctx);
116 :
117 0 : if (!child_ctx->running) {
118 : /* This should hopefully be impossible, but protect
119 : * against it anyway. If we're not marked running, then
120 : * the init_req will be NULL below and things will
121 : * break.
122 : */
123 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Client connection from a request "
124 : "that's not marked as running\n");
125 0 : return EIO;
126 : }
127 :
128 0 : init_ctx = tevent_req_data(child_ctx->init_req, struct pc_init_ctx);
129 0 : init_ctx->conn = conn;
130 0 : tevent_req_done(child_ctx->init_req);
131 0 : child_ctx->init_req = NULL;
132 :
133 0 : return EOK;
134 : }
135 :
136 0 : static void init_timeout(struct tevent_context *ev,
137 : struct tevent_timer *te,
138 : struct timeval t, void *ptr)
139 : {
140 : struct proxy_client *proxy_cli;
141 :
142 0 : DEBUG(SSSDBG_OP_FAILURE,
143 : "Client timed out before Identification [%p]!\n", te);
144 :
145 0 : proxy_cli = talloc_get_type(ptr, struct proxy_client);
146 :
147 0 : sbus_disconnect(proxy_cli->conn);
148 0 : talloc_zfree(proxy_cli);
149 :
150 : /* If we time out here, we will also time out to
151 : * pc_init_timeout(), so we'll finish the request
152 : * there.
153 : */
154 0 : }
155 :
156 0 : int proxy_client_init(struct sbus_connection *conn, void *data)
157 : {
158 : struct proxy_auth_ctx *proxy_auth_ctx;
159 : struct proxy_client *proxy_cli;
160 : struct timeval tv;
161 :
162 0 : proxy_auth_ctx = talloc_get_type(data, struct proxy_auth_ctx);
163 :
164 : /* hang off this memory to the connection so that when the connection
165 : * is freed we can potentially call a destructor */
166 :
167 0 : proxy_cli = talloc_zero(conn, struct proxy_client);
168 0 : if (!proxy_cli) {
169 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
170 0 : talloc_zfree(conn);
171 0 : return ENOMEM;
172 : }
173 0 : proxy_cli->proxy_auth_ctx = proxy_auth_ctx;
174 0 : proxy_cli->conn = conn;
175 0 : proxy_cli->initialized = false;
176 :
177 : /* 5 seconds should be plenty */
178 0 : tv = tevent_timeval_current_ofs(5, 0);
179 :
180 0 : proxy_cli->timeout = tevent_add_timer(proxy_auth_ctx->be->ev, proxy_cli,
181 : tv, init_timeout, proxy_cli);
182 0 : if (!proxy_cli->timeout) {
183 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
184 0 : talloc_zfree(conn);
185 0 : return ENOMEM;
186 : }
187 0 : DEBUG(SSSDBG_CONF_SETTINGS,
188 : "Set-up proxy client ID timeout [%p]\n", proxy_cli->timeout);
189 :
190 0 : return sbus_conn_register_iface(conn, &proxy_methods.vtable,
191 : DP_PATH, proxy_cli);
192 : }
|