/*
* util.c - routeup/tlsdated utility functions
* Copyright (c) 2012 The Chromium Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "config.h"
#include <grp.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#if !_PLAN9_SOURCE
#include <syslog.h>
#endif
#include <unistd.h>
#include "src/util.h"
/** helper function to print message and die */
void
die (const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(1);
}
/** helper function for 'verbose' output */
void
verb (const char *fmt, ...)
{
va_list ap;
if (! verbose) return;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#if !_PLAN9_SOURCE
void API logat(int isverbose, const char *fmt, ...)
{
if (isverbose && !verbose)
return;
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
va_start(ap, fmt);
vsyslog(LOG_INFO, fmt, ap);
va_end(ap);
}
#endif
void
drop_privs_to (const char *user, const char *group, const char **supp_groups)
{
#if !_PLAN9_SOURCE
uid_t uid;
gid_t gid;
struct passwd *pw;
struct group *gr;
/* TODO(garnold) Implement supplementary group support. */
if (supp_groups)
die ("Supplementary groups not supported\n");
if (0 != getuid ())
return; /* not running as root to begin with; should (!) be harmless to continue
without dropping to 'nobody' (setting time will fail in the end) */
pw = getpwnam(user);
gr = getgrnam(group);
if (NULL == pw)
die ("Failed to obtain UID for `%s'\n", user);
if (NULL == gr)
die ("Failed to obtain GID for `%s'\n", group);
uid = pw->pw_uid;
if (0 == uid)
die ("UID for `%s' is 0, refusing to run SSL\n", user);
gid = pw->pw_gid;
if (0 == gid || 0 == gr->gr_gid)
die ("GID for `%s' is 0, refusing to run SSL\n", user);
if (pw->pw_gid != gr->gr_gid)
die ("GID for `%s' is not `%s' as expected, refusing to run SSL\n",
user, group);
if (0 != initgroups((const char *)user, gr->gr_gid))
die ("Unable to initgroups for `%s' in group `%s' as expected\n",
user, group);
#ifdef HAVE_SETRESGID
if (0 != setresgid (gid, gid, gid))
die ("Failed to setresgid: %s\n", strerror (errno));
#else
if (0 != (setgid (gid) | setegid (gid)))
die ("Failed to setgid: %s\n", strerror (errno));
#endif
#ifdef HAVE_SETRESUID
if (0 != setresuid (uid, uid, uid))
die ("Failed to setresuid: %s\n", strerror (errno));
#else
if (0 != (setuid (uid) | seteuid (uid)))
die ("Failed to setuid: %s\n", strerror (errno));
#endif
#endif /* !_PLAN9_SOURCE */
}