C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
rsh.c File Reference

restricted shell to run bash as root More...

#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <syslog.h>
#include <termios.h>
#include <unistd.h>
Include dependency graph for rsh.c:

Go to the source code of this file.

Macros

#define _(String)
#define _GNU_SOURCE
#define bindtextdomain(Package, Directory)
#define HOST   "localhost"
#define MAXLEN   256
#define N_(String)
#define textdomain(Domain)

Functions

void ABEND (int e, char const *)
 Abnormal termination - print an error message and exit.
int main (int argc, char **argv)
 Main function for rsh.

Variables

bool F_VERBOSE = false

Detailed Description

restricted shell to run bash as root

Author
Bill Waller Copyright (c) 2025 MIT License billx.nosp@m.wall.nosp@m.er@gm.nosp@m.ail..nosp@m.com
Date
2026-02-09

Definition in file rsh.c.

Macro Definition Documentation

◆ _

#define _ ( String)
Value:
Definition cm.h:409

Definition at line 34 of file rsh.c.

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 10 of file rsh.c.

◆ bindtextdomain

#define bindtextdomain ( Package,
Directory )

Definition at line 37 of file rsh.c.

◆ HOST

#define HOST   "localhost"

Definition at line 40 of file rsh.c.

◆ MAXLEN

#define MAXLEN   256

Definition at line 42 of file rsh.c.

◆ N_

#define N_ ( String)
Value:

Definition at line 35 of file rsh.c.

◆ textdomain

#define textdomain ( Domain)

Definition at line 36 of file rsh.c.

Function Documentation

◆ ABEND()

void ABEND ( int e,
char const * s )

Abnormal termination - print an error message and exit.

Parameters
eError code
sError message

This function prints the provided error message along with the error code and its corresponding string representation, then exits the program with a failure status.

Definition at line 195 of file rsh.c.

195 {
196 fprintf(stderr, "%s: %d %s\n", s, e, strerror(e));
197 exit(EXIT_FAILURE);
198}

◆ main()

int main ( int argc,
char ** argv )

Main function for rsh.

Parameters
argcArgument count
argvArgument vector

If executed as 'rsh', this program sets the user ID and group ID to 0 (root) and then executes the user's default shell (or /usr/bin/bash if SHELL is not set) with the provided arguments. If no arguments are given, it runs the shell in interactive mode. To work properly, this program must be compiled and set with the setuid bit:

$ sudo -s
cc rsh.c -o rsh
sudo chown root:root rsh
sudo chmod 4755 rsh
exit

to verify proper operation:

$ rsh
$ whoami
root

Definition at line 88 of file rsh.c.

88 {
89 char *cargv[30];
90 char exec_cmd[MAXLEN] = "/usr/bin/bash";
91 char *p;
92 int c;
93 bool ssh_login = false;
94 int status;
95 pid_t pid;
96
97#ifdef RSH_PAM
98 pam_handle_t *pamh = NULL;
99 int retval;
100 char *username = getenv("USER");
101 if (username == NULL) {
102 syslog(LOG_ERR, "USER environment variable not set");
103 fprintf(stderr, "Error: USER environment variable not set\n");
104 return 1;
105 }
106 retval = pam_start("rsh-auth", username, &conv, &pamh);
107 if (retval != PAM_SUCCESS) {
108 syslog(LOG_ERR, _("PAM start failed: %s"), pam_strerror(pamh, retval));
109 fprintf(stderr, _("PAM start failed: %s\n"), pam_strerror(pamh, retval));
110 return 1;
111 }
112
113 // Authenticate the user using PAM. The configuration for this PAM service should
114 // be set to allow passwordless authentication, for example by using pam_permit.so.
115 // You can create a PAM configuration file named /etc/pam.d/pam_nopass with the
116 // following content:
117 //
118 // /etc/pam.d/pam_nopass:
119 // auth required pam_permit.so
120 //
121 //
122 retval = pam_authenticate(pamh, 0);
123 if (retval == PAM_SUCCESS) {
124 syslog(LOG_AUTH, _("Authentication succeeded for user '%s': %s"), username, pam_strerror(pamh, retval));
125 } else {
126 syslog(LOG_AUTH, _("Authentication failed for user '%s': %s"), username, pam_strerror(pamh, retval));
127 fprintf(stderr, _("Failure: Authentication failed: %s\n"), pam_strerror(pamh, retval));
128 }
129
130 // It's a wrap
131 pam_end(pamh, retval);
132
133 if (retval != PAM_SUCCESS) {
134 fprintf(stderr, _("PAM authentication failed: %s\n"), pam_strerror(pamh, retval));
135 exit(EXIT_FAILURE);
136 }
137
138#endif
139 if ((p = getenv("SHELL")))
140 strncpy(exec_cmd, p, MAXLEN - 1);
141 cargv[0] = strdup(exec_cmd);
142 c = 1;
143 if (argc > 0) {
144 for (int i = 1; i < argc; i++) {
145 if (strcmp(argv[i], "-i") == 0) {
146 cargv[c++] = strdup("-i");
147 } else if (strcmp(argv[i], "-D1") == 0 && ssh_login) {
148 fprintf(stderr, _("SSH authentication succeeded\n"));
149 } else {
150 cargv[c++] = strdup(argv[i]);
151 }
152 }
153 }
154 cargv[c] = nullptr;
155 pid = fork();
156 switch (pid) {
157 case -1:
158 ABEND(EXIT_FAILURE, _("fork() fatal error"));
159 break;
160 case 0: // Child
161 if (argv[0] && strstr(argv[0], "rsh")) {
162 if (setuid(0) || setgid(0))
163 ABEND(EXIT_FAILURE, _("setuid(0) fatal error"));
164 struct rlimit rl;
165 getrlimit(RLIMIT_FSIZE, &rl);
166 rl.rlim_cur = RLIM_INFINITY;
167 rl.rlim_max = RLIM_INFINITY;
168 setrlimit(RLIMIT_FSIZE, &rl);
169 }
170 execvp(exec_cmd, cargv);
171 ABEND(EXIT_FAILURE, _("execvp() fatal error"));
172 break;
173 default: // Parent
174 waitpid(pid, &status, 0);
175 for (int i = 0; i < c; i++)
176 free(cargv[i]);
177#ifdef F_VERBOSE
178 if (WIFEXITED(status)) {
179 rc = WEXITSTATUS(status);
180 if (rc != 0)
181 ABEND(rc, _("Child process exited"));
182 } else {
183 if (WIFSIGNALED(status)) {
184 rc = WTERMSIG(status);
185 ABEND(rc, _("Child process terminated by signal"));
186 } else
187 ABEND(EXIT_FAILURE, _("Child process terminated abnormally"));
188 }
189#endif
190 break;
191 }
192 exit(EXIT_SUCCESS);
193}
void ABEND(int e, char const *)
Abnormal termination - print an error message and exit.
Definition rsh.c:195
#define _(String)
Definition rsh.c:34
#define MAXLEN
Definition curskeys.c:15

References ABEND().

Here is the call graph for this function:

Variable Documentation

◆ F_VERBOSE

bool F_VERBOSE = false

Definition at line 48 of file rsh.c.