X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fservice.c;h=0594149d96e79798697daecf13daaabf57fece8f;hb=48718834d4fb6c411ff5b00b86662a3dee3ac6cc;hp=99a364f15cb3e52881546a131c03a7292f91c3cc;hpb=4a789496f1b7a453c247b99994839e759155e7b9;p=oweals%2Fgnunet.git diff --git a/src/util/service.c b/src/util/service.c index 99a364f15..0594149d9 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -429,11 +429,6 @@ struct GNUNET_SERVICE_Context */ struct GNUNET_SERVER_Handle *server; - /** - * Scheduler for the server. - */ - struct GNUNET_SCHEDULER_Handle *sched; - /** * NULL-terminated array of addresses to bind to, NULL if we got pre-bound * listen sockets. @@ -516,6 +511,18 @@ struct GNUNET_SERVICE_Context */ int require_found; + /** + * Do we require a matching UID for UNIX domain socket + * connections? + */ + int match_uid; + + /** + * Do we require a matching GID for UNIX domain socket + * connections? + */ + int match_gid; + /** * Our options. */ @@ -584,9 +591,18 @@ static const struct GNUNET_SERVER_MessageHandler defhandlers[] = { /** * Check if access to the service is allowed from the given address. + * + * @param cls closure + * @param uc credentials, if available, otherwise NULL + * @param addr address + * @param addrlen length of address + * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR + * for unknown address family (will be denied). */ static int -check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen) +check_access (void *cls, + const struct GNUNET_CONNECTION_Credentials *uc, + const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_SERVICE_Context *sctx = cls; const struct sockaddr_in *i4; @@ -614,8 +630,23 @@ check_access (void *cls, const struct sockaddr *addr, socklen_t addrlen) (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr))); break; case AF_UNIX: - /* FIXME: support checking UID/GID in the future... */ ret = GNUNET_OK; /* always OK for now */ + if ( (sctx->match_uid == GNUNET_YES) || + (sctx->match_gid == GNUNET_YES) ) + ret = GNUNET_NO; + if ( (uc != NULL) && + ( (sctx->match_uid != GNUNET_YES) || + (uc->uid == geteuid()) || + (uc->uid == getuid()) ) && + ( (sctx->match_gid != GNUNET_YES) || + (uc->gid == getegid()) || + (uc->gid == getgid())) ) + ret = GNUNET_YES; + else + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Access denied to UID %d / GID %d\n"), + (uc == NULL) ? -1 : uc->uid, + (uc == NULL) ? -1 : uc->gid); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -865,13 +896,23 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, if (GNUNET_CONFIGURATION_have_value (cfg, serviceName, "UNIXPATH")) { - GNUNET_break (GNUNET_OK == + GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, serviceName, "UNIXPATH", &unixpath)); /* probe UNIX support */ + struct sockaddr_un s_un; + if (strlen(unixpath) >= sizeof(s_un.sun_path)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("UNIXPATH `%s' too long, maximum length is %llu\n"),unixpath, sizeof(s_un.sun_path)); + GNUNET_free_non_null (hostname); + GNUNET_free (unixpath); + return GNUNET_SYSERR; + } + desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); if (NULL == desc) { @@ -917,6 +958,7 @@ GNUNET_SERVICE_get_server_addresses (const char *serviceName, saddrlens = GNUNET_malloc (2 * sizeof (socklen_t)); add_unixpath (saddrs, saddrlens, unixpath); GNUNET_free_non_null (unixpath); + GNUNET_free_non_null(hostname); *addrs = saddrs; *addr_lens = saddrlens; return 1; @@ -1093,11 +1135,13 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) { struct GNUNET_TIME_Relative idleout; int tolerant; +#ifndef MINGW const char *lpid; unsigned int pid; const char *nfds; unsigned int cnt; int flags; +#endif if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->serviceName, "TIMEOUT")) @@ -1143,7 +1187,9 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) (getpid () == (pid_t) pid) && (NULL != (nfds = getenv ("LISTEN_FDS"))) && (1 == sscanf (nfds, "%u", &cnt)) && - (cnt > 0) ) + (cnt > 0) && + (cnt < FD_SETSIZE) && + (cnt + 4 < FD_SETSIZE) ) { sctx->lsocks = GNUNET_malloc (sizeof(struct GNUNET_NETWORK_Handle*) * (cnt+1)); while (0 < cnt--) @@ -1177,7 +1223,12 @@ setup_service (struct GNUNET_SERVICE_Context *sctx) &sctx->addrlens)) ) return GNUNET_SYSERR; sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES; - + sctx->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, + sctx->serviceName, + "UNIX_MATCH_UID"); + sctx->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, + sctx->serviceName, + "UNIX_MATCH_GID"); process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM"); process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM"); process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6"); @@ -1285,16 +1336,13 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_SERVICE_Context *sctx = cls; unsigned int i; - sctx->sched = tc->sched; if (sctx->lsocks != NULL) - sctx->server = GNUNET_SERVER_create_with_sockets (tc->sched, - &check_access, + sctx->server = GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks, sctx->timeout, sctx->require_found); else - sctx->server = GNUNET_SERVER_create (tc->sched, - &check_access, + sctx->server = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens, @@ -1320,8 +1368,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { /* install a task that will kill the server process if the scheduler ever gets a shutdown signal */ - GNUNET_SCHEDULER_add_delayed (tc->sched, - GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, sctx->server); } sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers)); @@ -1349,7 +1396,7 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) i++; } } - sctx->task (sctx->task_cls, tc->sched, sctx->server, sctx->cfg); + sctx->task (sctx->task_cls, sctx->server, sctx->cfg); } @@ -1413,10 +1460,12 @@ detach_terminal (struct GNUNET_SERVICE_Context *sctx) return GNUNET_SYSERR; /* set stdin/stdout to /dev/null */ if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0)) - { + { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2"); + (void) CLOSE (nullfd); return GNUNET_SYSERR; } + (void) CLOSE (nullfd); /* Detach from controlling terminal */ pid = setsid (); if (pid == -1) @@ -1543,6 +1592,7 @@ GNUNET_SERVICE_run (int argc, sctx.ret = GNUNET_OK; sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL; sctx.task = task; + sctx.task_cls = task_cls; sctx.serviceName = serviceName; sctx.cfg = cfg = GNUNET_CONFIGURATION_create (); /* setup subsystems */ @@ -1604,13 +1654,11 @@ shutdown: * initialized system. * * @param serviceName our service name - * @param sched scheduler to use * @param cfg configuration to use * @return NULL on error, service handle */ struct GNUNET_SERVICE_Context * GNUNET_SERVICE_start (const char *serviceName, - struct GNUNET_SCHEDULER_Handle *sched, const struct GNUNET_CONFIGURATION_Handle *cfg) { int i; @@ -1622,7 +1670,6 @@ GNUNET_SERVICE_start (const char *serviceName, sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL; sctx->serviceName = serviceName; sctx->cfg = cfg; - sctx->sched = sched; /* setup subsystems */ if (GNUNET_OK != setup_service (sctx)) @@ -1631,14 +1678,12 @@ GNUNET_SERVICE_start (const char *serviceName, return NULL; } if (sctx->lsocks != NULL) - sctx->server = GNUNET_SERVER_create_with_sockets (sched, - &check_access, + sctx->server = GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks, sctx->timeout, sctx->require_found); else - sctx->server = GNUNET_SERVER_create (sched, - &check_access, + sctx->server = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens,