/*
 * Copyright (c) 2003, 2005 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: runas.c,v 1.3 2005/04/10 23:57:02 ca Exp $")

#include "sm/stdio.h"
#include "sm/types.h"
#include "sm/error.h"
#include "sm/pwd.h"
#include "sm/string.h"
#include "sm/sysexits.h"

static void
usage(char *prg)
{
	fprintf(stderr, "Usage: %s user command [args]\n", prg);
	fprintf(stderr,
		"%s can only be executed by root and must not be set-user-ID\n",
		prg);
	exit(EX_USAGE);
	/* NOTREACHED */
}

/*
**  RUNAS -- Wrapper to run some program as a specific user.
*/

int
main(int argc, char *argv[], char *envp[])
{
	uid_t realuid, effuid, newuid;
	gid_t newgid;
	char *prg, *cmd, *user;
	struct passwd *pw;

	prg = argv[0];
	if (argc < 3)
		usage(prg);
	realuid = getuid();
	if (realuid != 0)
		usage(prg);
	effuid = geteuid();
	if (effuid != realuid)
		usage(prg);
	user = argv[1];
	cmd = argv[2];
	argv += 2;
	argc -= 2;

	pw = getpwnam(user);
	if (pw == NULL)
	{
		fprintf(stderr, "%s: user '%s' not found\n", prg, user);
		return EX_UNAVAILABLE;
	}
	newuid = pw->pw_uid;
	newgid = pw->pw_gid;
	if (setgid(newgid) < 0)
	{
		fprintf(stderr, "%s: setgid(%ld) failed: %s\n", prg,
			(long) newgid, strerror(errno));
		return errno;
	}
	if (setuid(newuid) < 0)
	{
		fprintf(stderr, "%s: setuid(%ld) failed: %s\n", prg,
			(long) newuid, strerror(errno));
		return errno;
	}

	if (execve(cmd, argv, envp) < 0)
	{
		fprintf(stderr, "%s: cannot exec(%s): %s\n", prg,
			cmd, strerror(errno));
		exit(EX_UNAVAILABLE);
	}

	/* NOTREACHED */
	exit(EX_OSERR);
}


syntax highlighted by Code2HTML, v. 0.9.1