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 26 extern const char* __progname; 27 const char* kProgramName = __progname; 28 29 const uint32 kRetries = 3; 30 31 32 static void 33 usage() 34 { 35 fprintf(stderr, "usage: %s [-pl] [-c command] [username]\n", kProgramName); 36 exit(1); 37 } 38 39 40 int 41 main(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