Line data Source code
1 : /*
2 : SSSD
3 :
4 : Common Responder methods
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 "config.h"
23 :
24 : #include <stdio.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 "util/strtonum.h"
37 : #include "db/sysdb.h"
38 : #include "confdb/confdb.h"
39 : #include "sbus/sssd_dbus.h"
40 : #include "responder/common/responder.h"
41 : #include "responder/common/responder_packet.h"
42 : #include "providers/data_provider.h"
43 : #include "monitor/monitor_interfaces.h"
44 : #include "sbus/sbus_client.h"
45 : #include "util/util_creds.h"
46 :
47 0 : static errno_t set_close_on_exec(int fd)
48 : {
49 : int v;
50 : int ferr;
51 : errno_t error;
52 :
53 : /* Get the current flags for this file descriptor */
54 0 : v = fcntl(fd, F_GETFD, 0);
55 :
56 0 : errno = 0;
57 : /* Set the close-on-exec flags on this fd */
58 0 : ferr = fcntl(fd, F_SETFD, v | FD_CLOEXEC);
59 0 : if (ferr < 0) {
60 0 : error = errno;
61 0 : DEBUG(SSSDBG_FATAL_FAILURE,
62 : "Unable to set fd close-on-exec: [%d][%s]\n",
63 : error, strerror(error));
64 0 : return error;
65 : }
66 0 : return EOK;
67 : }
68 :
69 0 : static void client_close_fn(struct tevent_context *ev,
70 : struct tevent_fd *fde, int fd,
71 : void *ptr)
72 : {
73 : errno_t ret;
74 0 : struct cli_ctx *ctx = talloc_get_type(ptr, struct cli_ctx);
75 :
76 0 : if ((ctx->cfd > 0) && close(ctx->cfd) < 0) {
77 0 : ret = errno;
78 0 : DEBUG(SSSDBG_CRIT_FAILURE,
79 : "Failed to close fd [%d]: [%s]\n",
80 : ctx->cfd, strerror(ret));
81 : }
82 :
83 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
84 : "Terminated client [%p][%d]\n",
85 : ctx, ctx->cfd);
86 :
87 0 : ctx->cfd = -1;
88 0 : }
89 :
90 0 : static errno_t get_client_cred(struct cli_ctx *cctx)
91 : {
92 : SEC_CTX secctx;
93 : int ret;
94 :
95 0 : cctx->creds = talloc(cctx, struct cli_creds);
96 0 : if (!cctx->creds) return ENOMEM;
97 :
98 : #ifdef HAVE_UCRED
99 0 : socklen_t client_cred_len = sizeof(struct ucred);
100 :
101 0 : cctx->creds->ucred.uid = -1;
102 0 : cctx->creds->ucred.gid = -1;
103 0 : cctx->creds->ucred.pid = -1;
104 :
105 0 : ret = getsockopt(cctx->cfd, SOL_SOCKET, SO_PEERCRED, &cctx->creds->ucred,
106 : &client_cred_len);
107 0 : if (ret != EOK) {
108 0 : ret = errno;
109 0 : DEBUG(SSSDBG_CRIT_FAILURE,
110 : "getsock failed [%d][%s].\n", ret, strerror(ret));
111 0 : return ret;
112 : }
113 0 : if (client_cred_len != sizeof(struct ucred)) {
114 0 : DEBUG(SSSDBG_CRIT_FAILURE,
115 : "getsockopt returned unexpected message size.\n");
116 0 : return ENOMSG;
117 : }
118 :
119 0 : DEBUG(SSSDBG_TRACE_ALL,
120 : "Client creds: euid[%d] egid[%d] pid[%d].\n",
121 : cctx->creds->ucred.uid, cctx->creds->ucred.gid,
122 : cctx->creds->ucred.pid);
123 : #endif
124 :
125 0 : ret = SELINUX_getpeercon(cctx->cfd, &secctx);
126 0 : if (ret != 0) {
127 0 : DEBUG(SSSDBG_CRIT_FAILURE,
128 : "SELINUX_getpeercon failed [%d][%s].\n", ret, strerror(ret));
129 : /* This is not fatal, as SELinux may simply be disabled */
130 0 : ret = EOK;
131 : } else {
132 0 : cctx->creds->selinux_ctx = SELINUX_context_new(secctx);
133 0 : SELINUX_freecon(secctx);
134 : }
135 :
136 0 : return ret;
137 : }
138 :
139 40 : uid_t client_euid(struct cli_creds *creds)
140 : {
141 40 : if (!creds) return -1;
142 0 : return cli_creds_get_uid(creds);
143 : }
144 :
145 8 : errno_t check_allowed_uids(uid_t uid, size_t allowed_uids_count,
146 : uid_t *allowed_uids)
147 : {
148 : size_t c;
149 :
150 8 : if (allowed_uids == NULL) {
151 1 : return EINVAL;
152 : }
153 :
154 14 : for (c = 0; c < allowed_uids_count; c++) {
155 12 : if (uid == allowed_uids[c]) {
156 5 : return EOK;
157 : }
158 : }
159 :
160 2 : return EACCES;
161 : }
162 :
163 12 : errno_t csv_string_to_uid_array(TALLOC_CTX *mem_ctx, const char *csv_string,
164 : bool allow_sss_loop,
165 : size_t *_uid_count, uid_t **_uids)
166 : {
167 : int ret;
168 : size_t c;
169 12 : char **list = NULL;
170 : int list_size;
171 12 : uid_t *uids = NULL;
172 : char *endptr;
173 :
174 12 : ret = split_on_separator(mem_ctx, csv_string, ',', true, false,
175 : &list, &list_size);
176 12 : if (ret != EOK) {
177 2 : DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed [%d][%s].\n",
178 : ret, strerror(ret));
179 2 : goto done;
180 : }
181 :
182 10 : uids = talloc_array(mem_ctx, uint32_t, list_size);
183 10 : if (uids == NULL) {
184 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
185 0 : ret = ENOMEM;
186 0 : goto done;
187 : }
188 :
189 10 : if (allow_sss_loop) {
190 10 : ret = unsetenv("_SSS_LOOPS");
191 10 : if (ret != EOK) {
192 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to unset _SSS_LOOPS, getpwnam "
193 : "might not find sssd users.\n");
194 : }
195 : }
196 :
197 37 : for (c = 0; c < list_size; c++) {
198 31 : errno = 0;
199 31 : if (*list[c] == '\0') {
200 1 : DEBUG(SSSDBG_OP_FAILURE, "Empty list item.\n");
201 1 : ret = EINVAL;
202 1 : goto done;
203 : }
204 :
205 30 : uids[c] = strtouint32(list[c], &endptr, 10);
206 30 : if (errno != 0 || *endptr != '\0') {
207 4 : ret = errno;
208 4 : if (ret == ERANGE) {
209 2 : DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is out of range.\n",
210 : list[c]);
211 2 : goto done;
212 : }
213 :
214 2 : ret = sss_user_by_name_or_uid(list[c], &uids[c], NULL);
215 2 : if (ret != EOK) {
216 1 : DEBUG(SSSDBG_OP_FAILURE, "List item [%s] is neither a valid "
217 : "UID nor a user name which could be "
218 : "resolved by getpwnam().\n", list[c]);
219 1 : sss_log(SSS_LOG_WARNING, "List item [%s] is neither a valid "
220 : "UID nor a user name which could be "
221 1 : "resolved by getpwnam().\n", list[c]);
222 1 : goto done;
223 : }
224 : }
225 : }
226 :
227 6 : *_uid_count = list_size;
228 6 : *_uids = uids;
229 :
230 6 : ret = EOK;
231 :
232 : done:
233 12 : if(setenv("_SSS_LOOPS", "NO", 0) != 0) {
234 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to set _SSS_LOOPS.\n");
235 : }
236 12 : talloc_free(list);
237 12 : if (ret != EOK) {
238 6 : talloc_free(uids);
239 : }
240 :
241 12 : return ret;
242 : }
243 :
244 :
245 0 : static void client_send(struct cli_ctx *cctx)
246 : {
247 : int ret;
248 :
249 0 : ret = sss_packet_send(cctx->creq->out, cctx->cfd);
250 0 : if (ret == EAGAIN) {
251 : /* not all data was sent, loop again */
252 0 : return;
253 : }
254 0 : if (ret != EOK) {
255 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n");
256 0 : talloc_free(cctx);
257 0 : return;
258 : }
259 :
260 : /* ok all sent */
261 0 : TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
262 0 : TEVENT_FD_READABLE(cctx->cfde);
263 0 : talloc_free(cctx->creq);
264 0 : cctx->creq = NULL;
265 0 : return;
266 : }
267 :
268 0 : static int client_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds)
269 : {
270 : enum sss_cli_command cmd;
271 :
272 0 : cmd = sss_packet_get_cmd(cctx->creq->in);
273 0 : return sss_cmd_execute(cctx, cmd, sss_cmds);
274 : }
275 :
276 0 : static void client_recv(struct cli_ctx *cctx)
277 : {
278 : int ret;
279 :
280 0 : if (!cctx->creq) {
281 0 : cctx->creq = talloc_zero(cctx, struct cli_request);
282 0 : if (!cctx->creq) {
283 0 : DEBUG(SSSDBG_FATAL_FAILURE,
284 : "Failed to alloc request, aborting client!\n");
285 0 : talloc_free(cctx);
286 0 : return;
287 : }
288 : }
289 :
290 0 : if (!cctx->creq->in) {
291 0 : ret = sss_packet_new(cctx->creq, SSS_PACKET_MAX_RECV_SIZE,
292 0 : 0, &cctx->creq->in);
293 0 : if (ret != EOK) {
294 0 : DEBUG(SSSDBG_FATAL_FAILURE,
295 : "Failed to alloc request, aborting client!\n");
296 0 : talloc_free(cctx);
297 0 : return;
298 : }
299 : }
300 :
301 0 : ret = sss_packet_recv(cctx->creq->in, cctx->cfd);
302 0 : switch (ret) {
303 : case EOK:
304 : /* do not read anymore */
305 0 : TEVENT_FD_NOT_READABLE(cctx->cfde);
306 : /* execute command */
307 0 : ret = client_cmd_execute(cctx, cctx->rctx->sss_cmds);
308 0 : if (ret != EOK) {
309 0 : DEBUG(SSSDBG_FATAL_FAILURE,
310 : "Failed to execute request, aborting client!\n");
311 0 : talloc_free(cctx);
312 : }
313 : /* past this point cctx can be freed at any time by callbacks
314 : * in case of error, do not use it */
315 0 : return;
316 :
317 : case EAGAIN:
318 : /* need to read still some data, loop again */
319 0 : break;
320 :
321 : case EINVAL:
322 0 : DEBUG(SSSDBG_TRACE_FUNC,
323 : "Invalid data from client, closing connection!\n");
324 0 : talloc_free(cctx);
325 0 : break;
326 :
327 : case ENODATA:
328 0 : DEBUG(SSSDBG_FUNC_DATA, "Client disconnected!\n");
329 0 : talloc_free(cctx);
330 0 : break;
331 :
332 : default:
333 0 : DEBUG(SSSDBG_TRACE_FUNC, "Failed to read request, aborting client!\n");
334 0 : talloc_free(cctx);
335 : }
336 :
337 0 : return;
338 : }
339 :
340 : static errno_t reset_idle_timer(struct cli_ctx *cctx);
341 :
342 0 : static void client_fd_handler(struct tevent_context *ev,
343 : struct tevent_fd *fde,
344 : uint16_t flags, void *ptr)
345 : {
346 : errno_t ret;
347 0 : struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx);
348 :
349 : /* Always reset the idle timer on any activity */
350 0 : ret = reset_idle_timer(cctx);
351 0 : if (ret != EOK) {
352 0 : DEBUG(SSSDBG_CRIT_FAILURE,
353 : "Could not create idle timer for client. "
354 : "This connection may not auto-terminate\n");
355 : /* Non-fatal, continue */
356 : }
357 :
358 0 : if (flags & TEVENT_FD_READ) {
359 0 : client_recv(cctx);
360 0 : return;
361 : }
362 0 : if (flags & TEVENT_FD_WRITE) {
363 0 : client_send(cctx);
364 0 : return;
365 : }
366 : }
367 :
368 : struct accept_fd_ctx {
369 : struct resp_ctx *rctx;
370 : bool is_private;
371 : };
372 :
373 : static void idle_handler(struct tevent_context *ev,
374 : struct tevent_timer *te,
375 : struct timeval current_time,
376 : void *data);
377 :
378 0 : static void accept_fd_handler(struct tevent_context *ev,
379 : struct tevent_fd *fde,
380 : uint16_t flags, void *ptr)
381 : {
382 : /* accept and attach new event handler */
383 0 : struct accept_fd_ctx *accept_ctx =
384 : talloc_get_type(ptr, struct accept_fd_ctx);
385 0 : struct resp_ctx *rctx = accept_ctx->rctx;
386 : struct cli_ctx *cctx;
387 : socklen_t len;
388 : struct stat stat_buf;
389 : int ret;
390 0 : int fd = accept_ctx->is_private ? rctx->priv_lfd : rctx->lfd;
391 : int client_fd;
392 :
393 0 : if (accept_ctx->is_private) {
394 0 : ret = stat(rctx->priv_sock_name, &stat_buf);
395 0 : if (ret == -1) {
396 0 : DEBUG(SSSDBG_CRIT_FAILURE,
397 : "stat on privileged pipe failed: [%d][%s].\n", errno,
398 : strerror(errno));
399 0 : return;
400 : }
401 :
402 0 : if ( ! (stat_buf.st_uid == 0 && stat_buf.st_gid == 0 &&
403 0 : (stat_buf.st_mode&(S_IFSOCK|S_IRUSR|S_IWUSR)) == stat_buf.st_mode)) {
404 0 : DEBUG(SSSDBG_CRIT_FAILURE,
405 : "privileged pipe has an illegal status.\n");
406 : /* TODO: what is the best response to this condition? Terminate? */
407 0 : return;
408 : }
409 : }
410 :
411 0 : cctx = talloc_zero(rctx, struct cli_ctx);
412 0 : if (!cctx) {
413 : struct sockaddr_un addr;
414 0 : DEBUG(SSSDBG_FATAL_FAILURE,
415 : "Out of memory trying to setup client context%s!\n",
416 : accept_ctx->is_private ? " on privileged pipe": "");
417 : /* accept and close to signal the client we have a problem */
418 0 : memset(&addr, 0, sizeof(addr));
419 0 : len = sizeof(addr);
420 0 : client_fd = accept(fd, (struct sockaddr *)&addr, &len);
421 0 : if (client_fd == -1) {
422 0 : return;
423 : }
424 0 : close(client_fd);
425 0 : return;
426 : }
427 :
428 0 : len = sizeof(cctx->addr);
429 0 : cctx->cfd = accept(fd, (struct sockaddr *)&cctx->addr, &len);
430 0 : if (cctx->cfd == -1) {
431 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Accept failed [%s]\n", strerror(errno));
432 0 : talloc_free(cctx);
433 0 : return;
434 : }
435 :
436 0 : cctx->priv = accept_ctx->is_private;
437 :
438 0 : ret = get_client_cred(cctx);
439 0 : if (ret != EOK) {
440 0 : DEBUG(SSSDBG_OP_FAILURE, "get_client_cred failed, "
441 : "client cred may not be available.\n");
442 : }
443 :
444 0 : if (rctx->allowed_uids_count != 0) {
445 0 : if (client_euid(cctx->creds) == -1) {
446 0 : DEBUG(SSSDBG_CRIT_FAILURE, "allowed_uids configured, " \
447 : "but platform does not support " \
448 : "reading peer credential from the " \
449 : "socket. Access denied.\n");
450 0 : close(cctx->cfd);
451 0 : talloc_free(cctx);
452 0 : return;
453 : }
454 :
455 0 : ret = check_allowed_uids(client_euid(cctx->creds), rctx->allowed_uids_count,
456 : rctx->allowed_uids);
457 0 : if (ret != EOK) {
458 0 : if (ret == EACCES) {
459 0 : DEBUG(SSSDBG_CRIT_FAILURE,
460 : "Access denied for uid [%"SPRIuid"].\n",
461 : client_euid(cctx->creds));
462 : } else {
463 0 : DEBUG(SSSDBG_OP_FAILURE, "check_allowed_uids failed.\n");
464 : }
465 0 : close(cctx->cfd);
466 0 : talloc_free(cctx);
467 0 : return;
468 : }
469 : }
470 :
471 0 : cctx->cfde = tevent_add_fd(ev, cctx, cctx->cfd,
472 : TEVENT_FD_READ, client_fd_handler, cctx);
473 0 : if (!cctx->cfde) {
474 0 : close(cctx->cfd);
475 0 : talloc_free(cctx);
476 0 : DEBUG(SSSDBG_OP_FAILURE,
477 : "Failed to queue client handler%s\n",
478 : accept_ctx->is_private ? " on privileged pipe" : "");
479 0 : return;
480 : }
481 0 : tevent_fd_set_close_fn(cctx->cfde, client_close_fn);
482 :
483 0 : cctx->ev = ev;
484 0 : cctx->rctx = rctx;
485 :
486 : /* Set up the idle timer */
487 0 : ret = reset_idle_timer(cctx);
488 0 : if (ret != EOK) {
489 0 : DEBUG(SSSDBG_CRIT_FAILURE,
490 : "Could not create idle timer for client. "
491 : "This connection may not auto-terminate\n");
492 : /* Non-fatal, continue */
493 : }
494 :
495 0 : DEBUG(SSSDBG_TRACE_FUNC,
496 : "Client connected%s!\n",
497 : accept_ctx->is_private ? " to privileged pipe" : "");
498 :
499 0 : return;
500 : }
501 :
502 0 : static errno_t reset_idle_timer(struct cli_ctx *cctx)
503 : {
504 0 : struct timeval tv =
505 0 : tevent_timeval_current_ofs(cctx->rctx->client_idle_timeout, 0);
506 :
507 0 : talloc_zfree(cctx->idle);
508 :
509 0 : cctx->idle = tevent_add_timer(cctx->ev, cctx, tv, idle_handler, cctx);
510 0 : if (!cctx->idle) return ENOMEM;
511 :
512 0 : DEBUG(SSSDBG_TRACE_ALL,
513 : "Idle timer re-set for client [%p][%d]\n",
514 : cctx, cctx->cfd);
515 :
516 0 : return EOK;
517 : }
518 :
519 0 : static void idle_handler(struct tevent_context *ev,
520 : struct tevent_timer *te,
521 : struct timeval current_time,
522 : void *data)
523 : {
524 : /* This connection is idle. Terminate it */
525 0 : struct cli_ctx *cctx =
526 : talloc_get_type(data, struct cli_ctx);
527 :
528 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
529 : "Terminating idle client [%p][%d]\n",
530 : cctx, cctx->cfd);
531 :
532 : /* The cli_ctx destructor will handle the rest */
533 0 : talloc_free(cctx);
534 0 : }
535 :
536 0 : static int sss_dp_init(struct resp_ctx *rctx,
537 : struct sbus_vtable *dp_intf,
538 : const char *cli_name,
539 : struct sss_domain_info *domain)
540 : {
541 : struct be_conn *be_conn;
542 : int ret;
543 :
544 0 : be_conn = talloc_zero(rctx, struct be_conn);
545 0 : if (!be_conn) return ENOMEM;
546 :
547 0 : be_conn->cli_name = cli_name;
548 0 : be_conn->domain = domain;
549 0 : be_conn->rctx = rctx;
550 :
551 : /* Set up SBUS connection to the monitor */
552 0 : ret = dp_get_sbus_address(be_conn, &be_conn->sbus_address, domain->name);
553 0 : if (ret != EOK) {
554 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Could not locate DP address.\n");
555 0 : return ret;
556 : }
557 0 : ret = sbus_client_init(rctx, rctx->ev,
558 0 : be_conn->sbus_address,
559 : &be_conn->conn);
560 0 : if (ret != EOK) {
561 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to connect to monitor services.\n");
562 0 : return ret;
563 : }
564 :
565 0 : ret = sbus_conn_register_iface(be_conn->conn, dp_intf, DP_PATH, rctx);
566 0 : if (ret != EOK) {
567 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to export data provider.\n");
568 0 : return ret;
569 : }
570 :
571 0 : DLIST_ADD_END(rctx->be_conns, be_conn, struct be_conn *);
572 :
573 : /* Identify ourselves to the DP */
574 0 : ret = rdp_register_client(be_conn, cli_name);
575 0 : if (ret != EOK) {
576 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to identify to the DP!\n");
577 0 : return ret;
578 : }
579 :
580 0 : return EOK;
581 : }
582 :
583 0 : int create_pipe_fd(const char *sock_name, int *_fd, mode_t umaskval)
584 : {
585 : struct sockaddr_un addr;
586 : mode_t orig_umaskval;
587 : errno_t ret;
588 : int fd;
589 :
590 0 : fd = socket(AF_UNIX, SOCK_STREAM, 0);
591 0 : if (fd == -1) {
592 0 : return EIO;
593 : }
594 :
595 0 : orig_umaskval = umask(umaskval);
596 :
597 0 : ret = sss_fd_nonblocking(fd);
598 0 : if (ret != EOK) {
599 0 : goto done;
600 : }
601 :
602 0 : ret = set_close_on_exec(fd);
603 0 : if (ret != EOK) {
604 0 : goto done;
605 : }
606 :
607 0 : memset(&addr, 0, sizeof(addr));
608 0 : addr.sun_family = AF_UNIX;
609 0 : strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path) - 1);
610 0 : addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
611 :
612 : /* make sure we have no old sockets around */
613 0 : ret = unlink(sock_name);
614 0 : if (ret != 0 && errno != ENOENT) {
615 0 : ret = errno;
616 0 : DEBUG(SSSDBG_MINOR_FAILURE,
617 : "Cannot remove old socket (errno=%d), bind might fail!\n", ret);
618 : }
619 :
620 0 : if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
621 0 : DEBUG(SSSDBG_FATAL_FAILURE,
622 : "Unable to bind on socket '%s'\n", sock_name);
623 0 : ret = EIO;
624 0 : goto done;
625 : }
626 0 : if (listen(fd, 10) == -1) {
627 0 : DEBUG(SSSDBG_FATAL_FAILURE,
628 : "Unable to listen on socket '%s'\n", sock_name);
629 0 : ret = EIO;
630 0 : goto done;
631 : }
632 :
633 0 : ret = EOK;
634 :
635 : done:
636 : /* restore previous umask value */
637 0 : umask(orig_umaskval);
638 0 : if (ret == EOK) {
639 0 : *_fd = fd;
640 : } else {
641 0 : close(fd);
642 : }
643 0 : return ret;
644 : }
645 :
646 : /* create a unix socket and listen to it */
647 0 : static int set_unix_socket(struct resp_ctx *rctx)
648 : {
649 : errno_t ret;
650 : struct accept_fd_ctx *accept_ctx;
651 :
652 : /* for future use */
653 : #if 0
654 : char *default_pipe;
655 : int ret;
656 :
657 : default_pipe = talloc_asprintf(rctx, "%s/%s", PIPE_PATH,
658 : rctx->sss_pipe_name);
659 : if (!default_pipe) {
660 : return ENOMEM;
661 : }
662 :
663 : ret = confdb_get_string(rctx->cdb, rctx,
664 : rctx->confdb_socket_path, "unixSocket",
665 : default_pipe, &rctx->sock_name);
666 : if (ret != EOK) {
667 : talloc_free(default_pipe);
668 : return ret;
669 : }
670 : talloc_free(default_pipe);
671 :
672 : default_pipe = talloc_asprintf(rctx, "%s/private/%s", PIPE_PATH,
673 : rctx->sss_pipe_name);
674 : if (!default_pipe) {
675 : return ENOMEM;
676 : }
677 :
678 : ret = confdb_get_string(rctx->cdb, rctx,
679 : rctx->confdb_socket_path, "privUnixSocket",
680 : default_pipe, &rctx->priv_sock_name);
681 : if (ret != EOK) {
682 : talloc_free(default_pipe);
683 : return ret;
684 : }
685 : talloc_free(default_pipe);
686 : #endif
687 :
688 0 : if (rctx->sock_name != NULL ) {
689 : /* Set the umask so that permissions are set right on the socket.
690 : * It must be readable and writable by anybody on the system. */
691 0 : if (rctx->lfd == -1) {
692 0 : ret = create_pipe_fd(rctx->sock_name, &rctx->lfd, SCKT_RSP_UMASK);
693 0 : if (ret != EOK) {
694 0 : return ret;
695 : }
696 : }
697 :
698 0 : accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
699 0 : if(!accept_ctx) goto failed;
700 0 : accept_ctx->rctx = rctx;
701 0 : accept_ctx->is_private = false;
702 :
703 0 : rctx->lfde = tevent_add_fd(rctx->ev, rctx, rctx->lfd,
704 : TEVENT_FD_READ, accept_fd_handler,
705 : accept_ctx);
706 0 : if (!rctx->lfde) {
707 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to queue handler on pipe\n");
708 0 : goto failed;
709 : }
710 : }
711 :
712 0 : if (rctx->priv_sock_name != NULL ) {
713 : /* create privileged pipe */
714 0 : if (rctx->priv_lfd == -1) {
715 0 : ret = create_pipe_fd(rctx->priv_sock_name, &rctx->priv_lfd,
716 : DFL_RSP_UMASK);
717 0 : if (ret != EOK) {
718 0 : goto failed;
719 : }
720 : }
721 :
722 0 : accept_ctx = talloc_zero(rctx, struct accept_fd_ctx);
723 0 : if(!accept_ctx) goto failed;
724 0 : accept_ctx->rctx = rctx;
725 0 : accept_ctx->is_private = true;
726 :
727 0 : rctx->priv_lfde = tevent_add_fd(rctx->ev, rctx, rctx->priv_lfd,
728 : TEVENT_FD_READ, accept_fd_handler,
729 : accept_ctx);
730 0 : if (!rctx->priv_lfde) {
731 0 : DEBUG(SSSDBG_FATAL_FAILURE,
732 : "Failed to queue handler on privileged pipe\n");
733 0 : goto failed;
734 : }
735 : }
736 :
737 0 : return EOK;
738 :
739 : failed:
740 0 : close(rctx->lfd);
741 0 : close(rctx->priv_lfd);
742 0 : return EIO;
743 : }
744 :
745 0 : static int sss_responder_ctx_destructor(void *ptr)
746 : {
747 0 : struct resp_ctx *rctx = talloc_get_type(ptr, struct resp_ctx);
748 :
749 : /* mark that we are shutting down the responder, so it is propagated
750 : * into underlying contexts that are freed right before rctx */
751 0 : DEBUG(SSSDBG_TRACE_FUNC, "Responder is being shut down\n");
752 0 : rctx->shutting_down = true;
753 :
754 0 : return 0;
755 : }
756 :
757 0 : static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
758 : struct confdb_ctx *cdb,
759 : struct sss_nc_ctx **ncache)
760 : {
761 : uint32_t neg_timeout;
762 : uint32_t locals_timeout;
763 : int tmp_value;
764 : int ret;
765 :
766 : /* neg_timeout */
767 0 : ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
768 : CONFDB_NSS_ENTRY_NEG_TIMEOUT,
769 : 15, &tmp_value);
770 0 : if (ret != EOK) {
771 0 : DEBUG(SSSDBG_FATAL_FAILURE,
772 : "Fatal failure of setup negative cache timeout.\n");
773 0 : ret = ENOENT;
774 0 : goto done;
775 : }
776 :
777 0 : if (tmp_value < 0) {
778 0 : ret = EINVAL;
779 0 : goto done;
780 : }
781 :
782 0 : neg_timeout = tmp_value;
783 0 : ret = EOK;
784 :
785 : /* local_timeout */
786 0 : ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
787 : CONFDB_RESPONDER_LOCAL_NEG_TIMEOUT,
788 : 0, &tmp_value);
789 0 : if (ret != EOK) {
790 0 : DEBUG(SSSDBG_FATAL_FAILURE,
791 : "Fatal failure of setup negative cache timeout.\n");
792 0 : ret = ENOENT;
793 0 : goto done;
794 : }
795 :
796 0 : if (tmp_value < 0) {
797 0 : ret = EINVAL;
798 0 : goto done;
799 : }
800 :
801 0 : locals_timeout = tmp_value;
802 0 : ret = EOK;
803 :
804 : /* negative cache init */
805 0 : ret = sss_ncache_init(mem_ctx, neg_timeout, locals_timeout, ncache);
806 0 : if (ret != EOK) {
807 0 : DEBUG(SSSDBG_FATAL_FAILURE,
808 : "Fatal failure of initializing negative cache.\n");
809 0 : goto done;
810 : }
811 :
812 0 : ret = EOK;
813 :
814 : done:
815 0 : return ret;
816 : }
817 :
818 0 : int sss_process_init(TALLOC_CTX *mem_ctx,
819 : struct tevent_context *ev,
820 : struct confdb_ctx *cdb,
821 : struct sss_cmd_table sss_cmds[],
822 : const char *sss_pipe_name,
823 : int pipe_fd,
824 : const char *sss_priv_pipe_name,
825 : int priv_pipe_fd,
826 : const char *confdb_service_path,
827 : const char *svc_name,
828 : uint16_t svc_version,
829 : struct mon_cli_iface *monitor_intf,
830 : const char *cli_name,
831 : struct sbus_vtable *dp_intf,
832 : struct resp_ctx **responder_ctx)
833 : {
834 : struct resp_ctx *rctx;
835 : struct sss_domain_info *dom;
836 : int ret;
837 0 : char *tmp = NULL;
838 :
839 0 : rctx = talloc_zero(mem_ctx, struct resp_ctx);
840 0 : if (!rctx) {
841 0 : DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing resp_ctx\n");
842 0 : return ENOMEM;
843 : }
844 0 : rctx->ev = ev;
845 0 : rctx->cdb = cdb;
846 0 : rctx->sss_cmds = sss_cmds;
847 0 : rctx->sock_name = sss_pipe_name;
848 0 : rctx->priv_sock_name = sss_priv_pipe_name;
849 0 : rctx->lfd = pipe_fd;
850 0 : rctx->priv_lfd = priv_pipe_fd;
851 0 : rctx->confdb_service_path = confdb_service_path;
852 0 : rctx->shutting_down = false;
853 :
854 0 : talloc_set_destructor((TALLOC_CTX*)rctx, sss_responder_ctx_destructor);
855 :
856 0 : ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
857 : CONFDB_RESPONDER_CLI_IDLE_TIMEOUT,
858 : CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT,
859 : &rctx->client_idle_timeout);
860 0 : if (ret != EOK) {
861 0 : DEBUG(SSSDBG_OP_FAILURE,
862 : "Cannot get the client idle timeout [%d]: %s\n",
863 : ret, strerror(ret));
864 0 : goto fail;
865 : }
866 :
867 : /* Ensure that the client timeout is at least ten seconds */
868 0 : if (rctx->client_idle_timeout < 10) {
869 0 : rctx->client_idle_timeout = 10;
870 : }
871 :
872 0 : ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path,
873 : CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT,
874 : GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout);
875 0 : if (ret != EOK) {
876 0 : DEBUG(SSSDBG_OP_FAILURE,
877 : "Cannnot get the default domain timeout [%d]: %s\n",
878 : ret, strerror(ret));
879 0 : goto fail;
880 : }
881 :
882 0 : if (rctx->domains_timeout < 0) {
883 0 : DEBUG(SSSDBG_CONF_SETTINGS, "timeout can't be set to negative value, setting default\n");
884 0 : rctx->domains_timeout = GET_DOMAINS_DEFAULT_TIMEOUT;
885 : }
886 :
887 0 : ret = confdb_get_domains(rctx->cdb, &rctx->domains);
888 0 : if (ret != EOK) {
889 0 : DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up domain map\n");
890 0 : goto fail;
891 : }
892 :
893 0 : ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
894 : CONFDB_MONITOR_DEFAULT_DOMAIN, NULL,
895 : &rctx->default_domain);
896 0 : if (ret != EOK) {
897 0 : DEBUG(SSSDBG_OP_FAILURE,
898 : "Cannnot get the default domain [%d]: %s\n",
899 : ret, strerror(ret));
900 0 : goto fail;
901 : }
902 :
903 0 : ret = confdb_get_string(rctx->cdb, rctx, CONFDB_MONITOR_CONF_ENTRY,
904 : CONFDB_MONITOR_OVERRIDE_SPACE, NULL,
905 : &tmp);
906 0 : if (ret != EOK) {
907 0 : DEBUG(SSSDBG_OP_FAILURE,
908 : "Cannnot get the space substitution character [%d]: %s\n",
909 : ret, strerror(ret));
910 0 : goto fail;
911 : }
912 :
913 0 : if (tmp != NULL) {
914 0 : if (strlen(tmp) > 1) {
915 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Option %s is longer than 1 character "
916 : "only the first character %c will be used\n",
917 : CONFDB_MONITOR_OVERRIDE_SPACE, tmp[0]);
918 : }
919 :
920 0 : rctx->override_space = tmp[0];
921 : }
922 :
923 0 : ret = sss_monitor_init(rctx, rctx->ev, monitor_intf,
924 : svc_name, svc_version, rctx,
925 : &rctx->mon_conn);
926 0 : if (ret != EOK) {
927 0 : DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up message bus\n");
928 0 : goto fail;
929 : }
930 :
931 0 : for (dom = rctx->domains; dom; dom = get_next_domain(dom, 0)) {
932 0 : ret = sss_names_init(rctx->cdb, rctx->cdb, dom->name, &dom->names);
933 0 : if (ret != EOK) {
934 0 : DEBUG(SSSDBG_FATAL_FAILURE,
935 : "fatal error initializing regex data for domain: %s\n",
936 : dom->name);
937 0 : goto fail;
938 : }
939 :
940 : /* skip local domain, it doesn't have a backend */
941 0 : if (strcasecmp(dom->provider, "local") == 0) {
942 0 : continue;
943 : }
944 :
945 0 : ret = sss_dp_init(rctx, dp_intf, cli_name, dom);
946 0 : if (ret != EOK) {
947 0 : DEBUG(SSSDBG_FATAL_FAILURE,
948 : "fatal error setting up backend connector\n");
949 0 : goto fail;
950 : }
951 : }
952 :
953 0 : ret = sysdb_init(rctx, rctx->domains, false);
954 0 : if (ret != EOK) {
955 0 : SYSDB_VERSION_ERROR_DAEMON(ret);
956 0 : DEBUG(SSSDBG_FATAL_FAILURE,
957 : "fatal error initializing sysdb connection\n");
958 0 : goto fail;
959 : }
960 :
961 : /* after all initializations we are ready to listen on our socket */
962 0 : ret = set_unix_socket(rctx);
963 0 : if (ret != EOK) {
964 0 : DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing socket\n");
965 0 : goto fail;
966 : }
967 :
968 : /* Create DP request table */
969 0 : ret = sss_hash_create(rctx, 30, &rctx->dp_request_table);
970 0 : if (ret != EOK) {
971 0 : DEBUG(SSSDBG_FATAL_FAILURE,
972 : "Could not create hash table for the request queue\n");
973 0 : goto fail;
974 : }
975 :
976 0 : ret = responder_init_ncache(rctx, rctx->cdb, &rctx->ncache);
977 0 : if (ret != EOK) {
978 0 : DEBUG(SSSDBG_CRIT_FAILURE, "fatal error initializing negcache\n");
979 0 : goto fail;
980 : }
981 :
982 0 : DEBUG(SSSDBG_TRACE_FUNC, "Responder Initialization complete\n");
983 :
984 0 : *responder_ctx = rctx;
985 0 : return EOK;
986 :
987 : fail:
988 0 : talloc_free(rctx);
989 0 : return ret;
990 : }
991 :
992 3 : int sss_dp_get_domain_conn(struct resp_ctx *rctx, const char *domain,
993 : struct be_conn **_conn)
994 : {
995 : struct be_conn *iter;
996 :
997 3 : if (!rctx->be_conns) return ENOENT;
998 :
999 0 : for (iter = rctx->be_conns; iter; iter = iter->next) {
1000 0 : if (strcasecmp(domain, iter->domain->name) == 0) break;
1001 : }
1002 :
1003 0 : if (!iter) return ENOENT;
1004 :
1005 0 : *_conn = iter;
1006 :
1007 0 : return EOK;
1008 : }
1009 :
1010 : struct sss_domain_info *
1011 71 : responder_get_domain(struct resp_ctx *rctx, const char *name)
1012 : {
1013 : struct sss_domain_info *dom;
1014 71 : struct sss_domain_info *ret_dom = NULL;
1015 :
1016 164 : for (dom = rctx->domains; dom;
1017 22 : dom = get_next_domain(dom, SSS_GND_DESCEND)) {
1018 87 : if (sss_domain_get_state(dom) == DOM_DISABLED) {
1019 0 : continue;
1020 : }
1021 :
1022 109 : if (strcasecmp(dom->name, name) == 0 ||
1023 22 : (dom->flat_name != NULL &&
1024 0 : strcasecmp(dom->flat_name, name) == 0)) {
1025 65 : ret_dom = dom;
1026 65 : break;
1027 : }
1028 : }
1029 :
1030 71 : if (!ret_dom) {
1031 6 : DEBUG(SSSDBG_OP_FAILURE, "Unknown domain [%s]\n", name);
1032 : }
1033 :
1034 71 : return ret_dom;
1035 : }
1036 :
1037 4 : errno_t responder_get_domain_by_id(struct resp_ctx *rctx, const char *id,
1038 : struct sss_domain_info **_ret_dom)
1039 : {
1040 : struct sss_domain_info *dom;
1041 4 : struct sss_domain_info *ret_dom = NULL;
1042 : size_t id_len;
1043 : size_t dom_id_len;
1044 : int ret;
1045 :
1046 4 : if (id == NULL || _ret_dom == NULL) {
1047 0 : return EINVAL;
1048 : }
1049 :
1050 4 : id_len = strlen(id);
1051 :
1052 8 : for (dom = rctx->domains; dom;
1053 0 : dom = get_next_domain(dom, SSS_GND_DESCEND)) {
1054 8 : if (sss_domain_get_state(dom) == DOM_DISABLED ||
1055 4 : dom->domain_id == NULL) {
1056 0 : continue;
1057 : }
1058 :
1059 4 : dom_id_len = strlen(dom->domain_id);
1060 8 : if ((id_len >= dom_id_len) &&
1061 4 : strncasecmp(dom->domain_id, id, dom_id_len) == 0) {
1062 4 : if (IS_SUBDOMAIN(dom) &&
1063 0 : ((time(NULL) - dom->parent->subdomains_last_checked.tv_sec) >
1064 0 : rctx->domains_timeout)) {
1065 0 : DEBUG(SSSDBG_TRACE_FUNC, "Domain entry with id [%s] " \
1066 : "is expired.\n", id);
1067 0 : ret = EAGAIN;
1068 0 : goto done;
1069 : }
1070 4 : ret_dom = dom;
1071 4 : break;
1072 : }
1073 : }
1074 :
1075 4 : if (ret_dom == NULL) {
1076 0 : DEBUG(SSSDBG_OP_FAILURE, "Unknown domain id [%s], checking for "
1077 : "possible subdomains!\n", id);
1078 0 : ret = ENOENT;
1079 : } else {
1080 4 : *_ret_dom = ret_dom;
1081 4 : ret = EOK;
1082 : }
1083 :
1084 : done:
1085 4 : return ret;
1086 : }
1087 :
1088 0 : int responder_logrotate(struct sbus_request *dbus_req, void *data)
1089 : {
1090 : errno_t ret;
1091 0 : struct resp_ctx *rctx = talloc_get_type(data, struct resp_ctx);
1092 :
1093 0 : ret = server_common_rotate_logs(rctx->cdb, rctx->confdb_service_path);
1094 0 : if (ret != EOK) return ret;
1095 :
1096 0 : return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
1097 : }
1098 :
1099 0 : void responder_set_fd_limit(rlim_t fd_limit)
1100 : {
1101 : struct rlimit current_limit, new_limit;
1102 : int limret;
1103 :
1104 : /* First, let's see if we have permission to just set
1105 : * the value as-is.
1106 : */
1107 0 : new_limit.rlim_cur = fd_limit;
1108 0 : new_limit.rlim_max = fd_limit;
1109 0 : limret = setrlimit(RLIMIT_NOFILE, &new_limit);
1110 0 : if (limret == 0) {
1111 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1112 : "Maximum file descriptors set to [%"SPRIrlim"]\n",
1113 : new_limit.rlim_cur);
1114 0 : return;
1115 : }
1116 :
1117 : /* We couldn't set the soft and hard limits to this
1118 : * value. Let's see how high we CAN set it.
1119 : */
1120 :
1121 : /* Determine the maximum hard limit */
1122 0 : limret = getrlimit(RLIMIT_NOFILE, ¤t_limit);
1123 0 : if (limret == 0) {
1124 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
1125 : "Current fd limit: [%"SPRIrlim"]\n",
1126 : current_limit.rlim_cur);
1127 : /* Choose the lesser of the requested and the hard limit */
1128 0 : if (current_limit.rlim_max < fd_limit) {
1129 0 : new_limit.rlim_cur = current_limit.rlim_max;
1130 : } else {
1131 0 : new_limit.rlim_cur = fd_limit;
1132 : }
1133 0 : new_limit.rlim_max = current_limit.rlim_max;
1134 :
1135 0 : limret = setrlimit(RLIMIT_NOFILE, &new_limit);
1136 0 : if (limret == 0) {
1137 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1138 : "Maximum file descriptors set to [%"SPRIrlim"]\n",
1139 : new_limit.rlim_cur);
1140 : } else {
1141 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1142 : "Could not set new fd limits. Proceeding with "
1143 : "[%"SPRIrlim"]\n", current_limit.rlim_cur);
1144 : }
1145 : } else {
1146 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1147 : "Could not determine fd limits. "
1148 : "Proceeding with system values\n");
1149 : }
1150 : }
|