On Thu, Nov 02, 2000 at 06:07:05PM -0500, Laszlo Vecsey wrote:
> I'm having trouble getting scp to transfer files from one machine to
> another when invoked from a user other than the one that has the keys,
> even though I'm switching into the correct account by setting the
> effective uid.
>
> It seems ssh is doing an additional check to get the real uid, ignorning
> the effective uid.
>
> I've tried setting the HOME, USER, LOGNAME environment variables and
> additionally I set the wrapper script with chmod g+s so that it uses the
> correct user.
>
> I'm trying this on SunOS 5.7 with OpenSSH 2.2.0p1. I wasn't able to even
> set the script setuid root and then 'su - user' to the correct user from
> the script -- it prompts for a password.
>
> Whats the right way to do this?
>
> The intent here is to drop files to a remote machine using non-root
> accounts, and doing so on the sending machine from an account
> thats different from the accounts set up for the specific task of
> doing the drop transfer.
A week ago I wrote a very short setuid-root C program to do this. The
trick is to assume you're being forked from a setuid-whoever process and
use /proc to look at the *parent's* effective uid, and then set the real
uid to that effective uid before invoking ssh.
I've attached the source. I'd appreciate if anybody can tell me if they
can think of any security holes in it.
- Dave Dykstra
/*
* When parent process is running as effective user different than the
* real user (that is, if it is a setuid-program), then set the real
* uid to that user and run ssh. Without this wrapper, ssh will not
* allow being run from a setuid program.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/procfs.h>
#include <fcntl.h>
#ifndef SSHPATH
#define SSHPATH "/opt/ssh/bin/ssh"
#endif
int main(int ac, char **av)
{
struct prcred prcred;
char *me = av[0];
int fd;
char procnamebuf[sizeof("/proc/NNNNNNNNNNNN")];
sprintf(procnamebuf, "/proc/%d", getppid());
if ((fd = open(procnamebuf, O_RDONLY)) == -1) {
perror(procnamebuf);
exit(1);
}
if (ioctl(fd, PIOCCRED, &prcred) == -1) {
perror("PIOCCRED failed");
exit(1);
}
close(fd);
if (setuid(prcred.pr_euid) == -1) {
perror("setuid");
exit(1);
}
av[0] = SSHPATH;
execv(SSHPATH, av);
fprintf(stderr, "%s: error on execv of %s\n", me, SSHPATH);
return 1;
}