From: Brian Candler on
> Regardless, there isn't then a good workaround for what I need? :/

There almost certainly is one for Mac, but I'm not a Mac user.

sudo doesn't require any user input if you configure it correctly (i.e.
with suitable use of NOPASSWD flag in the sudoers file).

Many Ubuntu GUI apps prompt for a password when they need to escalate to
root privileges (e.g. update-manager). I don't know what that framework
they use as I've never had to use it myself.

Anyway, the way that ruby checks setuid is to test for real uid !=
effective uid (grep for "forbid_setid" in the ruby source). So a simple
C program which is setuid root and which sets real id to effective id is
all you need.

$ cat myrunner.c
// gcc -Wall -o myrunner myrunner.c
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (setgid(getegid()) < 0) { perror("setgid"); return 1; }
if (setuid(geteuid()) < 0) { perror("setuid"); return 1; }
execl("/usr/bin/ruby","ruby","/home/candlerb/myscript.rb",NULL);
return 1;
}

$ gcc -Wall -o myrunner myrunner.c
$ sudo chown 0:0 myrunner
$ sudo chmod 4755 myrunner
$ cat myscript.rb
p $SAFE
$ ./myrunner
0

Note that I have intentionally hard-coded the name of the script to run,
and the path to the ruby interpreter, into the wrapper. You don't want
people being able to run arbitrary code as root. A better wrapper would
also reset the environment (man execle)

HTH,

Brian.
--
Posted via http://www.ruby-forum.com/.

From: Brian Candler on
BTW, here's exactly what happens (ruby.c):

static void
init_ids()
{
uid = (int)getuid();
euid = (int)geteuid();
gid = (int)getgid();
egid = (int)getegid();
#ifdef VMS
uid |= gid << 16;
euid |= egid << 16;
#endif
if (uid && (euid != uid || egid != gid)) {
rb_set_safe_level(1);
}
}

That is: if the real uid is not root, and either the effective uid
different to the real uid or the effective gid is different to the real
gid, then set $SAFE to 1.

But notice that $SAFE level 1 only means "Ruby disallows the use of
tainted data by potentially dangerous operations". So maybe what you
should do is go with the flow, and carefully validate and untaint all
data which comes from external sources. Maybe ruby pcap will work if you
do this.

See http://www.ruby-doc.org/docs/ProgrammingRuby/html/taint.html for
more info.
--
Posted via http://www.ruby-forum.com/.

From: Caleb Clausen on
On 4/6/10, Rick Ashton <expiation(a)devils.com> wrote:
> That's what I'm saying. You need to escalate the current user's privs
> using sudo. You can't have root privs without escalation (ie. log in as
> root) in Ubuntu or OS X since the root account is disabled as it uses
> the sudo paradigm.

Although (logging in to) the root account is disabled _by_default_ on
Ubuntu, you can certainly enable it. I believe the same is true of the
mac, tho it's been a while since I really used a mac. Just because
they try to shove sudo down your throat doesn't mean you have to
swallow it.

From: Joel VanderWerf on
Brian Candler wrote:
> sudo works fine in Ubuntu. Even if you run from the live CD, you can do
> "sudo bash" to get a root shell.

or "sudo -i":

-i [command]
The -i (simulate initial login) option runs the shell
specified in the passwd(5) entry of the target user as a
login shell. This means that login-specific resource files
such as .profile or .login will be read by the shell. If a
command is specified, it is passed to the shell for
execution. Otherwise, an interactive shell is executed.
sudo attempts to change to that user's home directory
before running the shell. It also initializes the
environment, leaving DISPLAY and TERM unchanged, setting
HOME, SHELL, USER, LOGNAME, and PATH, as well as the
contents of /etc/environment on Linux and AIX systems. All
other environment variables are removed.

When setting up an ubuntu system, I always used to set up a root
password (just "sudo passwd root" IIRC), until I found out about the -i
option. Now I just use that instead.

From: Rick Ashton on
Thanks for all the helpful responses guys :)

Brian Candler wrote:
> Note that I have intentionally hard-coded the name of the script to run,
> and the path to the ruby interpreter, into the wrapper.

I can't hard-code the path this way. By design, a Mac app bundle should
be able to live anywhere, not just under a particular path, so I can't
do this. Will just have to live with the security implication then. Of
course, in the case of the example you provide, there's nothing stopping
someone / something from modifying / replacing
/home/candlerb/myscript.rb anyways, right?

> So maybe what you
> should do is go with the flow, and carefully validate and untaint all
> data which comes from external sources.

You are totally right! :) Because the SecurityError had come from inside
of open_live in the pcap library, and gave no reference to anything of
mine, I had assumed something in that library was getting some tainted
input. I had forgotten the fact that I had modified my program to get
the network interface based on the currently active interface (which
changes dynamically in OS X). This was then part of what got passed to
open_live and I overlooked that. Dope! Untainting the network interface
string fixed that.

Solved! Thanks for the help :)
--
Posted via http://www.ruby-forum.com/.