
/* vim: set sw=4 sts=4 : */

/* Copyright (c) 2007-2008, David B. Cortarello
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *   * Neither the name of Kwort nor the names of its contributors may be used
 *     to endorse or promote products derived from this software without
 *     specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "config.h"
#include "errors.h"

int make_me_new(const char *username, const char *password, int chk_passwd);
char *get_real_name(const char *command);

static void re_su_error(int code)
{
	char **params;
	char *path = calloc(strlen(RE_SU_PLACE) + 7, sizeof(char));

	sprintf(path, "%s/re_su", RE_SU_PLACE);
	params = malloc(4 * sizeof(char *));
	params[0] = calloc(6, sizeof(char));
	sprintf(params[0], "ktsuss");
	params[1] = calloc(3, sizeof(char));
	sprintf(params[1], "-e");
	params[2] = calloc(3, sizeof(char));
	sprintf(params[2], "%d", code);
	params[3] = NULL;
	if (setuid(0))
		exit(1 + 0 * fprintf(stderr, "I'm not setuid\n"));
	execv(path, params);
	free(path);
	exit(1);
}

void say_help(char *str)
{
	printf("Usage: %s [OPTION] command [COMMAND ARGUMENTS]\n", str);
	printf("Run a command as another user\n\n");
	printf("OPTIONS:\n");
	printf("\t-v, --version        Gives ktsuss version info\n");
	printf("\t-u, --user USER      Runs the command as the given user\n");
	printf("\t-m, --message MESG   Change default message in ktsuss window\n");
	printf("\t-h, --help           Show this help\n");
	exit(1);
}

void say_about(void)
{
	printf("%s - Copyright (c) 2007-2008 David B. Cortarello\n\n", PACKAGE_STRING);
	printf("Please report comments, suggestions and bugs to:\n\t%s\n\n", PACKAGE_BUGREPORT);
	printf("Check for new versions at:\n\thttp://nomius.blogspot.com\n\n");
	exit(0);
}

int main(int argc, char **argv)
{
	struct passwd *pw;
	char *username = NULL;
	char *real_name = NULL;
	char *error = NULL;
	char *message = NULL;
	uid_t whoami;
	int u = 0, m = 0, i = 1;
	char *path = calloc(strlen(RE_SU_PLACE) + 7, sizeof(char));

	while (i < argc) {

		if (argv[i][0] != '-')
			break;

		if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
			say_help(argv[0]);

		if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v"))
			say_about();

		if (!strcmp(argv[i], "--user") || !strcmp(argv[i], "-u"))
			username = argv[i + 1], u = 1;

		if (!strcmp(argv[i], "--message") || !strcmp(argv[i], "-m"))
			message = argv[i + 1], m = 1;

		i += 2;
	}

	if (u && username == NULL)
		re_su_error(ERR_MISSING_USER_AND_COMMAND);
	if (m && message == NULL)
		re_su_error(ERR_MISSING_MESSAGE_AND_COMMAND);
	if (argv[i] == NULL)
		re_su_error(ERR_MISSING_COMMAND);

	whoami = getuid();
	if ((pw = getpwuid(whoami)) == NULL)
		exit(2 + 0 * fprintf(stderr, "Who you think you are? Houdini?\n"));

	if ((real_name = get_real_name(argv[i])) == NULL)
		re_su_error(ERR_COMMAND_NOT_FOUND);

	if (username && !strcmp(pw->pw_name, username)) {

		/* username was me so let's just run it and leave */
		if (execvp(real_name, &(argv[i])) == -1) {
			re_su_error(ERR_PERMISSION_DENIED);
			exit(1);
		}
		exit(0);
	}

	if (setuid(0))
		exit(1 + 0 * fprintf(stderr, "I'm not setuid\n"));

	sprintf(path, "%s/re_su", RE_SU_PLACE);
	execv(path, argv);
	free(path);
	return 0;
}
