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

External Aliases

grant_privilege -> eid=

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]