Line data Source code
1 : /*
2 : SSSD
3 :
4 : PAC Responder
5 :
6 : Copyright (C) Sumit Bose <sbose@redhat.com> 2011
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 <stdio.h>
23 : #include <unistd.h>
24 : #include <fcntl.h>
25 : #include <sys/types.h>
26 : #include <sys/stat.h>
27 : #include <sys/socket.h>
28 : #include <sys/un.h>
29 : #include <string.h>
30 : #include <sys/time.h>
31 : #include <errno.h>
32 : #include <popt.h>
33 : #include <dbus/dbus.h>
34 :
35 : #include "util/util.h"
36 : #include "responder/pac/pacsrv.h"
37 : #include "db/sysdb.h"
38 : #include "confdb/confdb.h"
39 : #include "sbus/sssd_dbus.h"
40 : #include "responder/common/responder_packet.h"
41 : #include "responder/common/responder.h"
42 : #include "providers/data_provider.h"
43 : #include "monitor/monitor_interfaces.h"
44 : #include "sbus/sbus_client.h"
45 : #include "util/util_sss_idmap.h"
46 :
47 : #define SSS_PAC_PIPE_NAME "pac"
48 : #define DEFAULT_PAC_FD_LIMIT 8192
49 : #define DEFAULT_ALLOWED_UIDS "0"
50 :
51 : struct mon_cli_iface monitor_pac_methods = {
52 : { &mon_cli_iface_meta, 0 },
53 : .ping = monitor_common_pong,
54 : .resInit = monitor_common_res_init,
55 : .shutDown = NULL,
56 : .goOffline = NULL,
57 : .resetOffline = NULL,
58 : .rotateLogs = responder_logrotate,
59 : .clearMemcache = NULL,
60 : .clearEnumCache = NULL,
61 : .sysbusReconnect = NULL,
62 : };
63 :
64 : static struct data_provider_iface pac_dp_methods = {
65 : { &data_provider_iface_meta, 0 },
66 : .RegisterService = NULL,
67 : .pamHandler = NULL,
68 : .sudoHandler = NULL,
69 : .autofsHandler = NULL,
70 : .hostHandler = NULL,
71 : .getDomains = NULL,
72 : .getAccountInfo = NULL,
73 : };
74 :
75 : /* TODO: check if this can be made generic for all responders */
76 0 : static void pac_dp_reconnect_init(struct sbus_connection *conn,
77 : int status, void *pvt)
78 : {
79 0 : struct be_conn *be_conn = talloc_get_type(pvt, struct be_conn);
80 : int ret;
81 :
82 : /* Did we reconnect successfully? */
83 0 : if (status == SBUS_RECONNECT_SUCCESS) {
84 0 : DEBUG(SSSDBG_OP_FAILURE, "Reconnected to the Data Provider.\n");
85 :
86 : /* Identify ourselves to the data provider */
87 0 : ret = dp_common_send_id(be_conn->conn,
88 : DATA_PROVIDER_VERSION,
89 : "PAC");
90 : /* all fine */
91 0 : if (ret == EOK) {
92 0 : handle_requests_after_reconnect(be_conn->rctx);
93 0 : return;
94 : }
95 : }
96 :
97 : /* Failed to reconnect */
98 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Could not reconnect to %s provider.\n",
99 : be_conn->domain->name);
100 :
101 : /* FIXME: kill the frontend and let the monitor restart it ? */
102 : /* nss_shutdown(rctx); */
103 : }
104 :
105 0 : int pac_process_init(TALLOC_CTX *mem_ctx,
106 : struct tevent_context *ev,
107 : struct confdb_ctx *cdb)
108 : {
109 : struct resp_ctx *rctx;
110 : struct sss_cmd_table *pac_cmds;
111 : struct be_conn *iter;
112 : struct pac_ctx *pac_ctx;
113 : int ret, max_retries;
114 : enum idmap_error_code err;
115 : int fd_limit;
116 : char *uid_str;
117 :
118 0 : pac_cmds = get_pac_cmds();
119 :
120 0 : ret = sss_process_init(mem_ctx, ev, cdb,
121 : pac_cmds,
122 : SSS_PAC_SOCKET_NAME, -1, NULL, -1,
123 : CONFDB_PAC_CONF_ENTRY,
124 : PAC_SBUS_SERVICE_NAME,
125 : PAC_SBUS_SERVICE_VERSION,
126 : &monitor_pac_methods,
127 : "PAC", &pac_dp_methods.vtable,
128 : &rctx);
129 0 : if (ret != EOK) {
130 0 : DEBUG(SSSDBG_FATAL_FAILURE, "sss_process_init() failed\n");
131 0 : return ret;
132 : }
133 :
134 0 : pac_ctx = talloc_zero(rctx, struct pac_ctx);
135 0 : if (!pac_ctx) {
136 0 : DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing pac_ctx\n");
137 0 : ret = ENOMEM;
138 0 : goto fail;
139 : }
140 :
141 0 : pac_ctx->rctx = rctx;
142 0 : pac_ctx->rctx->pvt_ctx = pac_ctx;
143 :
144 :
145 0 : ret = confdb_get_string(pac_ctx->rctx->cdb, pac_ctx->rctx,
146 : CONFDB_PAC_CONF_ENTRY, CONFDB_SERVICE_ALLOWED_UIDS,
147 : DEFAULT_ALLOWED_UIDS, &uid_str);
148 0 : if (ret != EOK) {
149 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get allowed UIDs.\n");
150 0 : goto fail;
151 : }
152 :
153 0 : ret = csv_string_to_uid_array(pac_ctx->rctx, uid_str, true,
154 0 : &pac_ctx->rctx->allowed_uids_count,
155 0 : &pac_ctx->rctx->allowed_uids);
156 0 : talloc_free(uid_str);
157 0 : if (ret != EOK) {
158 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n");
159 0 : goto fail;
160 : }
161 :
162 : /* Enable automatic reconnection to the Data Provider */
163 0 : ret = confdb_get_int(pac_ctx->rctx->cdb,
164 : CONFDB_PAC_CONF_ENTRY,
165 : CONFDB_SERVICE_RECON_RETRIES,
166 : 3, &max_retries);
167 0 : if (ret != EOK) {
168 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set up automatic reconnection\n");
169 0 : goto fail;
170 : }
171 :
172 0 : for (iter = pac_ctx->rctx->be_conns; iter; iter = iter->next) {
173 0 : sbus_reconnect_init(iter->conn, max_retries,
174 : pac_dp_reconnect_init, iter);
175 : }
176 :
177 0 : err = sss_idmap_init(sss_idmap_talloc, pac_ctx, sss_idmap_talloc_free,
178 : &pac_ctx->idmap_ctx);
179 0 : if (err != IDMAP_SUCCESS) {
180 0 : DEBUG(SSSDBG_FATAL_FAILURE, "sss_idmap_init failed.\n");
181 0 : ret = EFAULT;
182 0 : goto fail;
183 : }
184 :
185 : /* Set up file descriptor limits */
186 0 : ret = confdb_get_int(pac_ctx->rctx->cdb,
187 : CONFDB_PAC_CONF_ENTRY,
188 : CONFDB_SERVICE_FD_LIMIT,
189 : DEFAULT_PAC_FD_LIMIT,
190 : &fd_limit);
191 0 : if (ret != EOK) {
192 0 : DEBUG(SSSDBG_FATAL_FAILURE,
193 : "Failed to set up file descriptor limit\n");
194 0 : goto fail;
195 : }
196 0 : responder_set_fd_limit(fd_limit);
197 :
198 0 : ret = schedule_get_domains_task(rctx, rctx->ev, rctx, NULL);
199 0 : if (ret != EOK) {
200 0 : DEBUG(SSSDBG_FATAL_FAILURE, "schedule_get_domains_tasks failed.\n");
201 0 : goto fail;
202 : }
203 :
204 0 : DEBUG(SSSDBG_TRACE_FUNC, "PAC Initialization complete\n");
205 :
206 0 : return EOK;
207 :
208 : fail:
209 0 : talloc_free(rctx);
210 0 : return ret;
211 : }
212 :
213 0 : int main(int argc, const char *argv[])
214 : {
215 : int opt;
216 : poptContext pc;
217 : struct main_context *main_ctx;
218 : int ret;
219 : uid_t uid;
220 : gid_t gid;
221 :
222 0 : struct poptOption long_options[] = {
223 : POPT_AUTOHELP
224 0 : SSSD_MAIN_OPTS
225 0 : SSSD_SERVER_OPTS(uid, gid)
226 : POPT_TABLEEND
227 : };
228 :
229 : /* Set debug level to invalid value so we can decide if -d 0 was used. */
230 0 : debug_level = SSSDBG_INVALID;
231 :
232 0 : umask(DFL_RSP_UMASK);
233 :
234 0 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
235 0 : while((opt = poptGetNextOpt(pc)) != -1) {
236 : switch(opt) {
237 : default:
238 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
239 : poptBadOption(pc, 0), poptStrerror(opt));
240 0 : poptPrintUsage(pc, stderr, 0);
241 0 : return 1;
242 : }
243 : }
244 :
245 0 : poptFreeContext(pc);
246 :
247 0 : DEBUG_INIT(debug_level);
248 :
249 : /* set up things like debug, signals, daemonization, etc... */
250 0 : debug_log_file = "sssd_pac";
251 :
252 0 : ret = server_setup("sssd[pac]", 0, uid, gid,
253 : CONFDB_PAC_CONF_ENTRY, &main_ctx);
254 0 : if (ret != EOK) return 2;
255 :
256 0 : ret = die_if_parent_died();
257 0 : if (ret != EOK) {
258 : /* This is not fatal, don't return */
259 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set up to exit when parent process does\n");
260 : }
261 :
262 0 : ret = pac_process_init(main_ctx,
263 0 : main_ctx->event_ctx,
264 0 : main_ctx->confdb_ctx);
265 0 : if (ret != EOK) return 3;
266 :
267 : /* loop on main */
268 0 : server_loop(main_ctx);
269 :
270 0 : return 0;
271 : }
|