Main function for rsh.
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:
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
114
115
116
117
118
119
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
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:
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:
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.