Module Process::UID
In: process.c

The Process::UID module contains a collection of module functions which can be used to portably get, set, and switch the current process‘s real, effective, and saved user IDs.

Methods

Public Class methods

Change the current process‘s real and effective user ID to that specified by integer. Returns the new user ID. Not available on all platforms.

   [Process.uid, Process.euid]          #=> [0, 0]
   Process::UID.change_privilege(31)    #=> 31
   [Process.uid, Process.euid]          #=> [31, 31]

[Source]

/*
 *  call-seq:
 *     Process::UID.change_privilege(integer)   => fixnum
 *
 *  Change the current process's real and effective user ID to that
 *  specified by _integer_. Returns the new user ID. Not
 *  available on all platforms.
 *
 *     [Process.uid, Process.euid]          #=> [0, 0]
 *     Process::UID.change_privilege(31)    #=> 31
 *     [Process.uid, Process.euid]          #=> [31, 31]
 */

static VALUE
p_uid_change_privilege(obj, id)
    VALUE obj, id;
{
    int uid;

    check_uid_switch();

    uid = NUM2INT(id);

    if (geteuid() == 0) { /* root-user */
#if defined(HAVE_SETRESUID)
        if (setresuid(uid, uid, uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
#elif defined(HAVE_SETUID)
        if (setuid(uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
        if (getuid() == uid) {
            if (SAVED_USER_ID == uid) {
                if (setreuid(-1, uid) < 0) rb_sys_fail(0);
            } else {
                if (uid == 0) { /* (r,e,s) == (root, root, x) */
                    if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
                    if (setreuid(SAVED_USER_ID, 0) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0; /* (r,e,s) == (x, root, root) */
                    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                } else {
                    if (setreuid(0, -1) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0;
                    if (setreuid(uid, uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                }
            }
        } else {
            if (setreuid(uid, uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        }
#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
        if (getuid() == uid) {
            if (SAVED_USER_ID == uid) {
                if (seteuid(uid) < 0) rb_sys_fail(0);
            } else {
                if (uid == 0) {
                    if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0;
                    if (setruid(0) < 0) rb_sys_fail(0);
                } else {
                    if (setruid(0) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = 0;
                    if (seteuid(uid) < 0) rb_sys_fail(0);
                    if (setruid(uid) < 0) rb_sys_fail(0);
                    SAVED_USER_ID = uid;
                }
            }
        } else {
            if (seteuid(uid) < 0) rb_sys_fail(0);
            if (setruid(uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        }
#else
        rb_notimplement();
#endif
    } else { /* unprivileged user */
#if defined(HAVE_SETRESUID)
        if (setresuid((getuid() == uid)? -1: uid,
                      (geteuid() == uid)? -1: uid,
                      (SAVED_USER_ID == uid)? -1: uid) < 0) rb_sys_fail(0);
        SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
        if (SAVED_USER_ID == uid) {
            if (setreuid((getuid() == uid)? -1: uid,
                         (geteuid() == uid)? -1: uid) < 0) rb_sys_fail(0);
        } else if (getuid() != uid) {
            if (setreuid(uid, (geteuid() == uid)? -1: uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        } else if (/* getuid() == uid && */ geteuid() != uid) {
            if (setreuid(geteuid(), uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
            if (setreuid(uid, -1) < 0) rb_sys_fail(0);
        } else { /* getuid() == uid && geteuid() == uid */
            if (setreuid(-1, SAVED_USER_ID) < 0) rb_sys_fail(0);
            if (setreuid(SAVED_USER_ID, uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
            if (setreuid(uid, -1) < 0) rb_sys_fail(0);
        }
#elif defined(HAVE_SETRUID) && defined(HAVE_SETEUID)
        if (SAVED_USER_ID == uid) {
            if (geteuid() != uid && seteuid(uid) < 0) rb_sys_fail(0);
            if (getuid() != uid && setruid(uid) < 0) rb_sys_fail(0);
        } else if (/* SAVED_USER_ID != uid && */ geteuid() == uid) {
            if (getuid() != uid) {
                if (setruid(uid) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
            } else {
                if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
                SAVED_USER_ID = uid;
                if (setruid(uid) < 0) rb_sys_fail(0);
            }
        } else if (/* geteuid() != uid && */ getuid() == uid) {
            if (seteuid(uid) < 0) rb_sys_fail(0);
            if (setruid(SAVED_USER_ID) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
            if (setruid(uid) < 0) rb_sys_fail(0);
        } else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_44BSD_SETUID
        if (getuid() == uid) {
            /* (r,e,s)==(uid,?,?) ==> (uid,uid,uid) */
            if (setuid(uid) < 0) rb_sys_fail(0);
            SAVED_USER_ID = uid;
        } else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_SETEUID
        if (getuid() == uid && SAVED_USER_ID == uid) {
            if (seteuid(uid) < 0) rb_sys_fail(0);
        } else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#elif defined HAVE_SETUID
        if (getuid() == uid && SAVED_USER_ID == uid) {
            if (setuid(uid) < 0) rb_sys_fail(0);
        } else {
            errno = EPERM;
            rb_sys_fail(0);
        }
#else
        rb_notimplement();
#endif
    }
    return INT2FIX(uid);
}

Returns the effective user ID for this process.

   Process.euid   #=> 501

[Source]

/*
 *  call-seq:
 *     Process.euid           => fixnum
 *     Process::UID.eid       => fixnum
 *     Process::Sys.geteuid   => fixnum
 *
 *  Returns the effective user ID for this process.
 *
 *     Process.euid   #=> 501
 */

static VALUE
proc_geteuid(obj)
    VALUE obj;
{
    int euid = geteuid();
    return INT2FIX(euid);
}

Set the effective user ID, and if possible, the saved user ID of the process to the given integer. Returns the new effective user ID. Not available on all platforms.

   [Process.uid, Process.euid]          #=> [0, 0]
   Process::UID.grant_privilege(31)     #=> 31
   [Process.uid, Process.euid]          #=> [0, 31]

[Source]

/*
 *  call-seq:
 *     Process::UID.grant_privilege(integer)   => fixnum
 *     Process::UID.eid= integer               => fixnum
 *
 *  Set the effective user ID, and if possible, the saved user ID of
 *  the process to the given _integer_. Returns the new
 *  effective user ID. Not available on all platforms.
 *
 *     [Process.uid, Process.euid]          #=> [0, 0]
 *     Process::UID.grant_privilege(31)     #=> 31
 *     [Process.uid, Process.euid]          #=> [0, 31]
 */

static VALUE
p_uid_grant_privilege(obj, id)
    VALUE obj, id;
{
    return rb_seteuid_core(NUM2INT(id));
}

Exchange real and effective user IDs and return the new effective user ID. Not available on all platforms.

   [Process.uid, Process.euid]   #=> [0, 31]
   Process::UID.re_exchange      #=> 0
   [Process.uid, Process.euid]   #=> [31, 0]

[Source]

/*
 *  call-seq:
 *     Process::UID.re_exchange   => fixnum
 *
 *  Exchange real and effective user IDs and return the new effective
 *  user ID. Not available on all platforms.
 *
 *     [Process.uid, Process.euid]   #=> [0, 31]
 *     Process::UID.re_exchange      #=> 0
 *     [Process.uid, Process.euid]   #=> [31, 0]
 */

static VALUE
p_uid_exchange(obj)
    VALUE obj;
{
    int uid, euid;

    check_uid_switch();

    uid = getuid();
    euid = geteuid();

#if defined(HAVE_SETRESUID) &&  !defined(__CHECKER__)
    if (setresuid(euid, uid, uid) < 0) rb_sys_fail(0);
    SAVED_USER_ID = uid;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
    if (setreuid(euid,uid) < 0) rb_sys_fail(0);
    SAVED_USER_ID = uid;
#else
    rb_notimplement();
#endif
    return INT2FIX(uid);
}

Returns true if the real and effective user IDs of a process may be exchanged on the current platform.

[Source]

/*
 *  call-seq:
 *     Process::UID.re_exchangeable?   => true or false
 *
 *  Returns +true+ if the real and effective user IDs of a
 *  process may be exchanged on the current platform.
 *
 */

static VALUE
p_uid_exchangeable()
{
#if defined(HAVE_SETRESUID) &&  !defined(__CHECKER__)
    return Qtrue;
#elif defined(HAVE_SETREUID) && !defined(OBSOLETE_SETREUID)
    return Qtrue;
#else
    return Qfalse;
#endif
}

Returns the (real) user ID of this process.

   Process.uid   #=> 501

[Source]

/*
 *  call-seq:
 *     Process.uid           => fixnum
 *     Process::UID.rid      => fixnum
 *     Process::Sys.getuid   => fixnum
 *
 *  Returns the (real) user ID of this process.
 *
 *     Process.uid   #=> 501
 */

static VALUE
proc_getuid(obj)
    VALUE obj;
{
    int uid = getuid();
    return INT2FIX(uid);
}

Returns true if the current platform has saved user ID functionality.

[Source]

/*
 *  call-seq:
 *     Process::UID.sid_available?   => true or false
 *
 *  Returns +true+ if the current platform has saved user
 *  ID functionality.
 *
 */

static VALUE
p_uid_have_saved_id()
{
#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS)
    return Qtrue;
#else
    return Qfalse;
#endif
}

Switch the effective and real user IDs of the current process. If a block is given, the user IDs will be switched back after the block is executed. Returns the new effective user ID if called without a block, and the return value of the block if one is given.

[Source]

/*
 *  call-seq:
 *     Process::UID.switch              => fixnum
 *     Process::UID.switch {|| block}   => object
 *
 *  Switch the effective and real user IDs of the current process. If
 *  a <em>block</em> is given, the user IDs will be switched back
 *  after the block is executed. Returns the new effective user ID if
 *  called without a block, and the return value of the block if one
 *  is given.
 *
 */

static VALUE
p_uid_switch(obj)
    VALUE obj;
{
    int uid, euid;

    check_uid_switch();

    uid = getuid();
    euid = geteuid();

    if (uid != euid) {
        proc_seteuid(obj, INT2FIX(uid));
        if (rb_block_given_p()) {
            under_uid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID);
        } else {
            return INT2FIX(euid);
        }
    } else if (euid != SAVED_USER_ID) {
        proc_seteuid(obj, INT2FIX(SAVED_USER_ID));
        if (rb_block_given_p()) {
            under_uid_switch = 1;
            return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid);
        } else {
            return INT2FIX(uid);
        }
    } else {
        errno = EPERM;
        rb_sys_fail(0);
    }

#else
static VALUE
p_uid_sw_ensure(obj)
    VALUE obj;
{
    under_uid_switch = 0;
    return p_uid_exchange(obj);
}

[Validate]