1/*
2 * Copyright 2017, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 *		Augustin Cavalier <waddlesplash>
8 */
9
10
11#include <SupportDefs.h>
12
13#include <errno.h>
14#include <pwd.h>
15#include <signal.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <syslog.h>
20#include <termios.h>
21#include <unistd.h>
22
23#include "multiuser_utils.h"
24
25
26extern const char* __progname;
27const char* kProgramName = __progname;
28
29const uint32 kRetries = 3;
30
31
32static void
33usage()
34{
35	fprintf(stderr, "usage: %s [-pl] [-c command] [username]\n", kProgramName);
36	exit(1);
37}
38
39
40int
41main(int argc, char *argv[])
42{
43	bool loginShell = false;
44	const char* command = NULL;
45
46	char c;
47	while ((c = getopt(argc, argv, "c:l")) != -1) {
48		switch (c) {
49			case 'l':
50				loginShell = true;
51				break;
52
53			case 'c':
54				command = optarg;
55				break;
56
57			default:
58				usage();
59				break;
60		}
61	}
62
63	argc -= optind;
64	argv += optind;
65
66	const char* user = NULL;
67	if (argc > 0)
68		user = argv[0];
69
70	if (user == NULL)
71		user = "user";
72		// aka 'root' on Haiku
73
74	// login
75
76	openlog(kProgramName, 0, LOG_AUTH);
77
78	status_t status = B_ERROR;
79	struct passwd* passwd = NULL;
80
81	status = authenticate_user("password: ", user, &passwd, NULL,
82		kRetries, false);
83
84	if (status < B_OK || !passwd) {
85		if (passwd != NULL)
86			syslog(LOG_NOTICE, "su failed for \"%s\"", passwd->pw_name);
87		else
88			syslog(LOG_NOTICE, "su attempt for non-existent user \"%s\"", user);
89		exit(1);
90	}
91
92	// setup environment for the user
93
94	status = setup_environment(passwd, true, false);
95	if (status < B_OK) {
96		// refused login
97		fprintf(stderr, "%s: Refused login. Setting up environment failed: %s\n",
98			kProgramName, strerror(status));
99		syslog(LOG_NOTICE, "su refused for \"%s\"", passwd->pw_name);
100		exit(1);
101	}
102
103	syslog(LOG_INFO, "su as \"%s\"", passwd->pw_name);
104
105	// start shell
106	const char* args[] = {getenv("SHELL"), NULL, NULL, NULL, NULL};
107	int nextarg = 1;
108	if (loginShell) {
109		args[nextarg++] = "-login";
110	}
111	if (command != NULL) {
112		args[nextarg++] = "-c";
113		args[nextarg++] = command;
114	}
115
116	execv(args[0], (char **)args);
117
118	// try default shell
119	args[0] = "/bin/sh";
120	execv(args[0], (char **)args);
121
122	fprintf(stderr, "%s: starting the shell failed: %s", kProgramName,
123		strerror(errno));
124
125	return 1;
126}
127
128