/*****************************************************************************
 *
 * File ..................: mbuseradd.c
 * Purpose ...............: setuid root version of useradd
 * Last modification date : 26-Jun-1999
 *
 *****************************************************************************
 * Copyright (C) 1997-1999
 *   
 * Michiel Broek		FIDO:		2:2801/16
 * Beekmansbos 10		Internet:	mbroek@ux123.pttnwb.nl
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * MBSE BBS is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with MBSE BBS; see the file COPYING.  If not, write to the Free
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *****************************************************************************/

#include "../include/libs.h"
#include "mbuseradd.h"




int execute(char *cmd, char *file, char *in, char *out, char *err)
{
	char	buf[512];
	char	*vector[16];
	int	i;
	int	pid, status, rc, sverr;

	sprintf(buf, "%s %s", cmd, file);

	i=0;
	vector[i++] = strtok(buf, " \t\n");
	while ((vector[i++] = strtok(NULL," \t\n")) && (i < 16));
	vector[15] = NULL;
	fflush(stdout);
	fflush(stderr);

	if ((pid = fork()) == 0) {
		if (in) {
			close(0);
			if (open(in, O_RDONLY) != 0) {
				perror("");
				printf("Reopen of stdin to %s failed", in);
				exit(-1);
			}
		}
		if (out) {
			close(1);
			if (open(out, O_WRONLY | O_APPEND | O_CREAT,0600) != 1) {
				perror("");
				printf("Reopen of stdout to %s failed", out);
				exit(-1);
			}
		}
		if (err) {
			close(2);
			if (open(err, O_WRONLY | O_APPEND | O_CREAT,0600) != 2) {
				perror("");
				printf("Reopen of stderr to %s failed", err);
				exit(-1);
			}
		}
		rc = execv(vector[0],vector);
		printf("Exec \"%s\" returned %d", vector[0], rc);
		exit(-1);
	}

	do {
		rc = wait(&status);
		sverr = errno;
	}
	while (((rc > 0) && (rc != pid)) || ((rc == -1) && (sverr == EINTR)));
	if (rc == -1)
	{
		printf("Wait returned %d, status %d,%d",
			rc,status>>8,status&0xff);
		return -1;
	}

	return status;
}



/*
 * Function will create the users name in the passwd file
 * Note that this function must run setuid root!
 */
int main(int argc, char *argv[])
{
	char		*PassEnt, *temp, *shell;
	int		i;
	struct passwd	*pwent;
	FILE		*fp;

	if (setuid(0) == -1 || setgid(1) == -1) {
		perror("");
		printf("FATAL: unable to setuid(root) or setgid(root)\n");
		printf("Make sure that this program is set to -rwsr-sr-x\n");
		printf("Owner must be root and group root\n");
		exit(1);
	}

	if (argc != 5)
		Help();

	PassEnt = calloc(256, sizeof(char));
	temp    = calloc(81, sizeof(char));
	shell   = calloc(81, sizeof(char));

	/*
	 * Build command to add user entry to the /etc/passwd and /etc/shadow
	 * files. We use the systems own useradd program.
	 */
	if ((access("/usr/bin/useradd", R_OK)) == 0)
		strcpy(temp, "/usr/bin/useradd");
	else if ((access("/bin/useradd", R_OK)) == 0)
		strcpy(temp, "/bin/useradd");
	else if ((access("/usr/sbin/useradd", R_OK)) == 0)
		strcpy(temp, "/usr/sbin/useradd");
	else if ((access("/sbin/useradd", R_OK)) == 0)
		strcpy(temp, "/sbin/useradd");
	else {
		printf("Can't find useradd");
		exit(1);
	}

	sprintf(shell, "%s/bin/mbsebbs", getenv("MBSE_ROOT"));

	sprintf(PassEnt, "%s -c \"%s\" -d %s/%s -g %s -s %s %s",
		temp, argv[3], argv[4], argv[2], argv[1], shell, argv[2]);
	fflush(stdout);
	fflush(stdin);

	if (system(PassEnt) != 0) {
		perror("Failed to create unix account");
		exit(1);
	} 

	if ((access("/bin/passwd", X_OK)) == 0)
		strcpy(temp, "/bin/passwd");
	else if ((access("/usr/bin/passwd", X_OK)) == 0)
		strcpy(temp, "/usr/bin/passwd");
	else {
		printf("Can't find passwd\n");
		exit(1);
	}

	/*
	 *  Let the user type a new password
	 */
	sprintf(PassEnt, " %s", argv[2]);
	fflush(stdout);
	fflush(stdin);
	i = execute(temp, PassEnt, (char *)"/dev/tty", (char *)"/dev/tty", (char *)"/dev/tty");

	if (i != 0) {
		printf("Unable to change password default\n");
		exit(2);
	}

	/*
	 * Now create directories and files for this user.
	 */
	if ((pwent = getpwnam((char *)"mbse")) == NULL) {
		perror("Can't get password entry for \"mbse\"");
		exit(2);
	}

	/*
	 *  Check bbs users home directory
	 */
	if ((access(argv[4], R_OK)) != 0) {
		if (mkdir(argv[4], 00770) != 0) {
			perror("");
			printf("Can't create %s\n", argv[4]);
			exit(2);
		} else {
			if (chown(argv[4], pwent->pw_uid, pwent->pw_gid) == -1) {
				perror("");
				printf("Unable to change ownership of %s\n", argv[4]);
			}
		}
	}

	sprintf(temp, "%s/%s", argv[4], argv[2]);
	if (mkdir(temp, 00770) != 0) {
		perror("");
		printf("Can't create %s\n", temp);
		exit(2);
	}
	chmod(temp, 0770);

	if ((chown(temp, pwent->pw_uid, pwent->pw_gid)) == -1) {
		perror("");
		printf("Unable to change ownership of %s\n", temp);
		exit(2);
	}

	sprintf(PassEnt, "%s/.hushlogin", temp);
	if ((fp = fopen(PassEnt, "w")) != NULL) 
		fclose(fp);
	else
		perror("Unable to create .hushlogin");

	free(shell);
	free(PassEnt);
	free(temp);

	/*
	 * Add username to /etc/ftpusers
	 */
	if ((fp = fopen("/etc/ftpusers", "a+")) != NULL) {
		fprintf(fp, "%s\n", argv[2]);
		fclose(fp);
		exit(0);
	} else
		exit(3);
}



void Help()
{
	printf("\nmbuseradd commandline:\n\n");
	printf("mbuseradd [gid] [name] [comment] [usersdir]\n");
	exit(1);
}


