[#15357] Regexp literal and Regexp.new() — TAKAHASHI Masayoshi <maki@...>

高橋征義です。

14 messages 2001/12/05
[#15358] Regexp in UTF-8 (Re: Regexp literal and Regexp.new()) — TAKAHASHI Masayoshi <maki@...> 2001/12/05

高橋征義です。むーん、問題のありかが違ったかも。

[#15435] Time#utcoff — Tanaka Akira <akr@...17n.org>

In article <hvosnahj702.fsf@coulee.a02.aist.go.jp>,

20 messages 2001/12/13
[#15436] Re: Time#utcoff — matz@... (Yukihiro Matsumoto) 2001/12/14

まつもと ゆきひろです

[#15505] ERb — m_seki@...

74 messages 2001/12/20
[#15560] Re: ERb — Tanaka Akira <akr@...17n.org> 2001/12/27

In article <20011220114249J.seki@mr.nasu.toshiba.co.jp>,

[#15879] Re: ERb — m_seki@... 2002/02/12

[#15884] Re: ERb — Tanaka Akira <akr@...17n.org> 2002/02/14

In article <m3eljr5o9m.wl@edwin.mva.biglobe.ne.jp>,

[#15885] Re: ERb — m_seki@... 2002/02/14

[#15886] Re: ERb — m_seki@... 2002/02/14

[#15887] Re: ERb — TAKAHASHI Masayoshi <maki@...> 2002/02/14

高橋征義です。

[#15888] Re: ERb — m_seki@... 2002/02/14

[#15896] Re: ERb — Tanaka Akira <akr@...17n.org> 2002/02/15

In article <20020215085405G.seki@mr.nasu.toshiba.co.jp>,

[#15898] Re: ERb — m_seki@... 2002/02/15

[#15900] Re: ERb — TADA Tadashi <sho@...> 2002/02/16

ただただしです。

[#15901] Re: ERb — m_seki@... 2002/02/16

[#15906] Re: ERb — matz@... (Yukihiro Matsumoto) 2002/02/17

まつもと ゆきひろです

[#15909] 1.6 の寿命 (Re: Re: ERb) — Koji Arai <JCA02266@...> 2002/02/17

新井です。

[#15507] fileutils (2) — Minero Aoki <aamine@...>

あおきです。

30 messages 2001/12/20
[#15512] Re: fileutils (2) — TAKAHASHI Masayoshi <maki@...> 2001/12/20

高橋征義です。

[#15513] Re: fileutils (2) — Minero Aoki <aamine@...> 2001/12/21

あおきです。

[#15515] Re: fileutils (2) — TAKAHASHI Masayoshi <maki@...> 2001/12/21

高橋征義です。結論は最後に。

[#15516] Re: fileutils (2) — Minero Aoki <aamine@...> 2001/12/21

あおきです。

[#15533] Re: fileutils (2) — TAKAHASHI Masayoshi <maki@...> 2001/12/22

高橋征義です。

[#15536] Re: fileutils (2) — Minero Aoki <aamine@...> 2001/12/24

あおきです。

[#15540] Re: fileutils (2) — TAKAHASHI Masayoshi <maki@...> 2001/12/24

高橋征義です。

[#15545] Re: fileutils (2) — Minero Aoki <aamine@...> 2001/12/24

あおきです。

[#15557] Re: fileutils (2) — TAKAHASHI Masayoshi <maki@...> 2001/12/26

高橋征義です。

[#15567] Re: fileutils (2) — Minero Aoki <aamine@...> 2001/12/27

あおきです。

[#15573] [patch] resolv.rb for win32 platform — Tietew <tietew-ml-ruby-dev@...>

Tietew です。

22 messages 2001/12/28

[ruby-dev:15372] new methods to treat uid/gid

From: nagai@...
Date: 2001-12-06 06:35:18 UTC
List: ruby-dev #15372
永井@知能.九工大です.

色々と忙しかったり風邪でダウンしてたりで遅くなりました.
Process モジュールにおけるユーザ ID / グループ ID の操作関連の
新しいメソッド群の試験実装です.
よかったら,試して意見をください.

まず,実装しているメソッドは次の通りです.

============================================================

uid/gid 操作のために実装するメソッド

Process.uid
Process.euid

Process.uid=
Process.euid=

Process.swap_uid

Process.switch_uauth() { ... }

-------------------

Process.gid
Process.egid

Process.gid=
Process.egid=

Process.swap_gid

Process.switch_gauth() { ... }

============================================================

で,各メソッドの仕様は以下のようになっています.

============================================================

Process.uid=(id) [Process.gid=(id)]

  仕様 : 実/実効/保存ユーザ ID のすべてを変更して,
         他のユーザとしての権限を放棄する.
         成功時は id を返す.
         完全放棄できない場合(一部ユーザ ID の変更ができない場合)は
         例外を発生する.
         例外の発生時に,このメソッドを呼び出す前の各ユーザ ID の値が
         保存されているかどうかは保証されない.

  注意 : 以前の Process.uid= とは互換性がないことに注意.
         setreuid(id,-1) によって実装されていたものを用いていたケースは,
         例えば次のように書き換える必要があるだろう.

           Process.swap_uid   ;# (r,e,s) == (u1,u2,??) ==> (u2,u1,??)
           Process.euid = id  ;# (u2,u1,??) ==> (u2,id,??)
           Process.swap_uid   ;# (u2,id,??) ==> (id,u2,??)

------------------------------------------------------------

Process.euid=(id) [Process.egid=(id)]

  仕様 : 実効ユーザ ID を変更する.
         成功時は id を返す.
         保存ユーザ ID の変化は,Process.swap_uid が定義されているかで決まる.
         定義されない環境では,保存ユーザ ID は変化しない.
         定義されている環境では,id が実ユーザ ID と異なる値に設定された場合,
         保存ユーザ ID は新しい実効ユーザ ID の値に設定される.
         設定できない場合は例外を発生する.

------------------------------------------------------------

Process.swap_uid() [Process.swap_gid()]

  仕様 : 実ユーザ ID と実効ユーザ ID とを入れ換える.
         保存ユーザ ID は新しい実効ユーザ ID と同じになる.
         設定できない場合は例外を発生する.
         戻り値としては,新しい実効ユーザ ID を返す.

  注意 : setresuid か setreuid を持たない環境には設定されない.

------------------------------------------------------------

Process.switch_uauth() { ... } [Process.switch_gauth() { ... }]

  仕様 : ユーザ権限を(一時的に)変更する.
         その際に実ユーザ ID が変化するかは,環境依存のため,保証されない.
         実/実効/保存ユーザ ID が二つのユーザ権限を移行できる状態でなければ
         例外を発生する.
         ブロックが与えられたならば,権限を移行してそのブロックを実行した後,
         元の権限に復帰する.
         ブロック内でユーザ ID が変更されるなどの理由で,
         元の権限に復帰できない場合,例外を発生する.
         ブロックが与えられない場合の戻り値は元に戻せる(変更できる) ID 値,
         ブロックが与えられた場合の戻り値はブロックの値を返す.

============================================================

ただ,環境に対して個別対応せざるをえない問題が少しあります.

上記仕様とするためには,保存ユーザ ID が存在し,
かつ,setreuid が存在する環境では,
その setreuid は保存ユーザ ID を変化させるものでなければなりません.
もし,変化させないものであった場合には
その setreuid の使用を無効化する必要があります.
とりあえず今のところ,OpenBSD 環境だけがそうらしいということで,
その場合のみは setreuid を使わないようにしています.

# 手元には OpenBSD 環境はありません.

また,保存ユーザ ID が存在するかどうかは,
setresuid が存在するか,seteuid が存在するか,
_POSIX_SAVED_IDS が真であるかのいずれかで判断しています.
そのため,これらに該当しないにも関わらず
保存ユーザ ID を持つ環境に対しては個別対応が必要です.
といっても,上の setreuid の問題よりは軽微で,
Process.switch_uauth において,
保存ユーザ ID を使った権限変更が選択されず,
実/実効ユーザ ID の交換による方法が選択されてしまうという点です.

保存ユーザ ID に影響しない setreuid の環境かどうかは
次のソースをコンパイルして,root 権限で実行してみてください.
もし FAIL を出さずに最後まで行くようなら,
保存ユーザ ID に影響しない setreuid の環境ではないかと思われます.

============================================================
#include <stdio.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

int main()
{
  int uid, euid, suid;

  uid = getuid();
  euid = geteuid();
  suid = euid;
  printf("initial status : (%d, %d, %d)\n", uid, euid, suid);

  printf(" --> (%d, 5) ; ", uid);
  if (setreuid(-1,5) < 0) {
    printf("FAIL!!\n");
    exit (0);
  }
  uid = getuid();
  euid = geteuid();
  printf("(%d, %d, ?)\n", uid, euid);

  printf(" --> (%d, %d) ; ", euid, uid);
  if (setreuid(euid,uid) < 0) {
    printf("FAIL!!\n");
    exit (0);
  }
  uid = getuid();
  euid = geteuid();
  suid = euid;
  printf("(%d, %d, %d)\n", uid, euid, suid);

  printf(" --> (%d, 7) ; ", uid);
  if (setreuid(-1,7) < 0) {
    printf("FAIL!!\n");
    exit (0);
  }
  uid = getuid();
  euid = geteuid();
  printf("(%d, %d, ?)\n", uid, euid);

  printf(" --> (%d, %d) ; ", euid, uid);
  if (setreuid(euid,uid) < 0) {
    printf("FAIL!!\n");
    exit (0);
  }
  uid = getuid();
  euid = geteuid();
  suid = euid;
  printf("(%d, %d, %d)\n", uid, euid, suid);

  printf(" --> (%d, %d) ; ", uid, uid);
  if (setreuid(-1,uid) < 0) {
    printf("FAIL!!\n");
    exit (0);
  }
  uid = getuid();
  euid = geteuid();
  printf("(%d, %d, %d)\n", uid, euid, suid);

  printf(" --> (%d, %d) ; ", uid, suid);
  if (setreuid(-1,suid) < 0) {
    printf("FAIL!!\n");
  }
  uid = getuid();
  euid = geteuid();
  printf("(%d, %d, %d)\n", uid, euid, suid);

  return 0;
}
============================================================

# これに限らず,テストプログラムで条件確認をしようとすると
# root 権限が必要になる点が頭のいたいところです.

で,以下がパッチです.
============================================================
Index: configure.in
===================================================================
RCS file: /src/ruby/configure.in,v
retrieving revision 1.103
diff -u -r1.103 configure.in
--- configure.in	2001/12/03 09:38:35	1.103
+++ configure.in	2001/12/06 06:30:23
@@ -297,8 +297,8 @@
 		 isinf isnan finite hypot)
 AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall chroot\
 	      truncate chsize times utimes fcntl lockf lstat symlink readlink\
-	      setitimer setruid seteuid setreuid setresuid setproctitle\
-	      setrgid setegid setregid setresgid pause lchown lchmod\
+	      setitimer setuid setruid seteuid setreuid setresuid setproctitle\
+	      setgid setrgid setegid setregid setresgid pause lchown lchmod\
 	      getpgrp setpgrp getpgid setpgid getgroups getpriority getrlimit\
 	      dlopen sigprocmask sigaction _setjmp setsid telldir seekdir fchmod)
 AC_STRUCT_TIMEZONE
Index: process.c
===================================================================
RCS file: /src/ruby/process.c,v
retrieving revision 1.43
diff -u -r1.43 process.c
--- process.c	2001/11/21 15:41:26	1.43
+++ process.c	2001/12/06 06:30:24
@@ -1111,29 +1111,134 @@
     return INT2FIX(uid);
 }
 
+static int SAVED_USER_ID;
+
 static VALUE
 proc_setuid(obj, id)
     VALUE obj, id;
 {
+    extern int errno;
     int uid;
 
     uid = NUM2INT(id);
-#if defined(HAVE_SETRESUID) &&  !defined(__CHECKER__)
-    if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0);
+
+    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
-    if (setreuid(uid, -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETRUID
-    if (setruid(uid) < 0) rb_sys_fail(0);
-#else
-    {
-	if (geteuid() == uid) {
-	    if (setuid(uid) < 0) rb_sys_fail(0);
+      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 {
-	    rb_notimplement();
+      } 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
+      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_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);
 }
 
@@ -1145,29 +1250,134 @@
     return INT2FIX(gid);
 }
 
+static int SAVED_GROUP_ID;
+
 static VALUE
 proc_setgid(obj, id)
     VALUE obj, id;
 {
+    extern int errno;
     int gid;
 
     gid = NUM2INT(id);
-#if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
-    if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0);
+
+    if (getegid() == 0) { /* root-group */
+#if defined(HAVE_SETRESGID)
+      if (setresgid(gid, gid, gid) < 0) rb_sys_fail(0);
+      SAVED_GROUP_ID = gid;
+#elif defined HAVE_SETGID
+      if (setgid(gid) < 0) rb_sys_fail(0);
+      SAVED_GROUP_ID = gid;
 #elif defined HAVE_SETREGID
-    if (setregid(gid, -1) < 0) rb_sys_fail(0);
-#elif defined HAS_SETRGID
-    if (setrgid((GIDTYPE)gid) < 0) rb_sys_fail(0);
-#else
-    {
-	if (getegid() == gid) {
-	    if (setgid(gid) < 0) rb_sys_fail(0);
+      if (getgid() == gid) {
+	if (SAVED_GROUP_ID == gid) {
+	  if (setregid(-1, gid) < 0) rb_sys_fail(0);
+	} else {
+	  if (gid == 0) { /* (r,e,s) == (root, root, x) */
+	    if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+	    if (setregid(SAVED_GROUP_ID, 0) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = 0; /* (r,e,s) == (x, root, root) */
+	    if (setregid(gid, gid) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = gid;
+	  } else {
+	    if (setregid(0, -1) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = 0;
+	    if (setregid(gid, gid) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = gid;
+	  }
 	}
-	else {
-	    rb_notimplement();
+      } else {
+	if (setregid(gid, gid) < 0) rb_sys_fail(0);
+	SAVED_GROUP_ID = gid;
+      }
+#elif defined HAVE_SETRGID && defined HAVE_SETEGID
+      if (getgid() == gid) {
+	if (SAVED_GROUP_ID == gid) {
+	  if (setegid(gid) < 0) rb_sys_fail(0);
+	} else {
+	  if (gid == 0) {
+	    if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = 0;
+	    if (setrgid(0) < 0) rb_sys_fail(0);
+	  } else {
+	    if (setrgid(0) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = 0;
+	    if (setegid(gid) < 0) rb_sys_fail(0);
+	    if (setrgid(gid) < 0) rb_sys_fail(0);
+	    SAVED_GROUP_ID = gid;
+	  }
 	}
-    }
+      } else {
+	if (setegid(gid) < 0) rb_sys_fail(0);
+	if (setrgid(gid) < 0) rb_sys_fail(0);
+	SAVED_GROUP_ID = gid;
+      }
+#else
+      rb_notimplement();
+#endif
+    } else { /* unprivileged group */
+#if defined(HAVE_SETRESGID)
+      if (setresgid((getgid() == gid)? -1: gid, 
+		    (getegid() == gid)? -1: gid, 
+		    (SAVED_GROUP_ID == gid)? -1: gid) < 0) rb_sys_fail(0);
+      SAVED_GROUP_ID = gid;
+#elif defined HAVE_SETREGID
+      if (SAVED_GROUP_ID == gid) {
+	if (setregid((getgid() == gid)? -1: gid, 
+		     (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
+      } else if (getgid() != gid) {
+	if (setregid(gid, (getegid() == gid)? -1: gid) < 0) rb_sys_fail(0);
+	SAVED_GROUP_ID = gid;
+      } else if (/* getgid() == gid && */ getegid() != gid) {
+	if (setregid(getegid(), gid) < 0) rb_sys_fail(0);
+	SAVED_GROUP_ID = gid;
+	if (setregid(gid, -1) < 0) rb_sys_fail(0);
+      } else { /* getgid() == gid && getegid() == gid */
+	if (setregid(-1, SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+	if (setregid(SAVED_GROUP_ID, gid) < 0) rb_sys_fail(0);
+	SAVED_GROUP_ID = gid;
+	if (setregid(gid, -1) < 0) rb_sys_fail(0);
+      }
+#elif defined HAVE_SETRGID && defined HAVE_SETEGID
+      if (SAVED_GROUP_ID == gid) {
+	if (getegid() != gid && setegid(gid) < 0) rb_sys_fail(0);
+	if (getgid() != gid && setrgid(gid) < 0) rb_sys_fail(0);
+      } else if (/* SAVED_GROUP_ID != gid && */ getegid() == gid) {
+	if (getgid() != gid) {
+	  if (setrgid(gid) < 0) rb_sys_fail(0);
+	  SAVED_GROUP_ID = gid;
+	} else {
+	  if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+	  SAVED_GROUP_ID = gid;
+	  if (setrgid(gid) < 0) rb_sys_fail(0);
+	}
+      } else if (/* getegid() != gid && */ getgid() == gid) {
+	if (setegid(gid) < 0) rb_sys_fail(0);
+	if (setrgid(SAVED_GROUP_ID) < 0) rb_sys_fail(0);
+	SAVED_GROUP_ID = gid;
+	if (setrgid(gid) < 0) rb_sys_fail(0);
+      } else {
+	errno = EPERM;
+	rb_sys_fail(0);
+      }
+#elif defined HAVE_SETEGID
+      if (getgid() == gid && SAVED_GROUP_ID == gid) {
+	if (setegid(gid) < 0) rb_sys_fail(0);
+      } else {
+	errno = EPERM;
+	rb_sys_fail(0);
+      }
+#elif defined HAVE_SETGID
+      if (getgid() == gid && SAVED_GROUP_ID == gid) {
+	if (setgid(gid) < 0) rb_sys_fail(0);
+      } else {
+	errno = EPERM;
+	rb_sys_fail(0);
+      }
+#else
+      rb_notimplement();
 #endif
+    }
     return INT2FIX(gid);
 }
 
@@ -1180,25 +1390,43 @@
 }
 
 static VALUE
-proc_seteuid(obj, euid)
-    VALUE obj, euid;
+rb_seteuid_core(euid)
+    int euid;
 {
+    int uid;
+
+    uid = getuid();
+
 #if defined(HAVE_SETRESUID) && !defined(__CHECKER__)
-    if (setresuid(-1, NUM2INT(euid), -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREUID
-    if (setreuid(-1, NUM2INT(euid)) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETEUID
-    if (seteuid(NUM2INT(euid)) < 0) rb_sys_fail(0);
-#else
-    euid = NUM2INT(euid);
-    if (euid == getuid()) {
-	if (setuid(euid) < 0) rb_sys_fail(0);
+    if (uid != euid) {
+      if (setresuid(-1,euid,euid) < 0) rb_sys_fail(0);
+      SAVED_USER_ID = euid;
+    } else {
+      if (setresuid(-1,euid,-1) < 0) rb_sys_fail(0);
     }
-    else {
-	rb_notimplement();
+#elif defined HAVE_SETREUID && !defined(__OpenBSD__)
+    if (setreuid(-1, euid) < 0) rb_sys_fail(0);
+    if (uid != euid) {
+      if (setreuid(euid,uid) < 0) rb_sys_fail(0);
+      if (setreuid(uid,euid) < 0) rb_sys_fail(0);
+      SAVED_USER_ID = euid;
     }
+#elif defined HAVE_SETEUID
+    if (seteuid(euid) < 0) rb_sys_fail(0);
+#elif defined HAVE_SETUID
+    if (geteuid() == 0) rb_sys_fail(0);
+    if (setuid(euid) < 0) rb_sys_fail(0);
+#else
+    rb_notimplement();
 #endif
-    return euid;
+    return INT2FIX(euid);
+}
+
+static VALUE
+proc_seteuid(obj, id)
+    VALUE obj, id;
+{
+  return rb_seteuid_core(NUM2INT(id));
 }
 
 static VALUE
@@ -1210,26 +1438,171 @@
 }
 
 static VALUE
-proc_setegid(obj, egid)
-    VALUE obj, egid;
+rb_setegid_core(egid)
+    int egid;
 {
-    rb_secure(2);
+    int gid;
+
+    gid = getgid();
+
 #if defined(HAVE_SETRESGID) && !defined(__CHECKER__)
-    if (setresgid(-1, NUM2INT(egid), -1) < 0) rb_sys_fail(0);
-#elif defined HAVE_SETREGID
-    if (setregid(-1, NUM2INT(egid)) < 0) rb_sys_fail(0);
+    if (gid != egid) {
+      if (setresgid(-1,egid,egid) < 0) rb_sys_fail(0);
+      SAVED_GROUP_ID = egid;
+    } else {
+      if (setresgid(-1,egid,-1) < 0) rb_sys_fail(0);
+    }
+#elif defined HAVE_SETREGID && !defined(__OpenBSD__)
+    if (setregid(-1, egid) < 0) rb_sys_fail(0);
+    if (gid != egid) {
+      if (setregid(egid,gid) < 0) rb_sys_fail(0);
+      if (setregid(gid,egid) < 0) rb_sys_fail(0);
+      SAVED_GROUP_ID = egid;
+    }
 #elif defined HAVE_SETEGID
-    if (setegid(NUM2INT(egid)) < 0) rb_sys_fail(0);
+    if (setegid(egid) < 0) rb_sys_fail(0);
+#elif defined HAVE_SETGID
+    if (getegid() == 0) rb_sys_fail(0);
+    if (setgid(egid) < 0) rb_sys_fail(0);
 #else
-    egid = NUM2INT(egid);
-    if (egid == getgid()) {
-	if (setgid(egid) < 0) rb_sys_fail(0);
+    rb_notimplement();
+#endif
+    return INT2FIX(egid);
+}
+
+static VALUE
+proc_setegid(obj, id)
+    VALUE obj, id;
+{
+  return rb_setegid_core(NUM2INT(id));
+}
+
+static VALUE
+proc_swap_uid(obj)
+    VALUE obj;
+{
+    int uid, euid;
+
+    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(__OpenBSD__)
+    if (setreuid(euid,uid) < 0) rb_sys_fail(0);
+    SAVED_USER_ID = uid;
+#else
+    rb_notimplement();
+#endif
+    return INT2FIX(uid);
+}
+
+static VALUE
+proc_swap_gid(obj)
+    VALUE obj;
+{
+    int gid, egid;
+
+    gid = getgid();
+    egid = getegid();
+
+#if defined(HAVE_SETRESGID) &&  !defined(__CHECKER__)
+    if (setresgid(egid, gid, gid) < 0) rb_sys_fail(0);
+    SAVED_GROUP_ID = gid;
+#elif defined HAVE_SETREGID && !defined(__OpenBSD__)
+    if (setregid(egid,gid) < 0) rb_sys_fail(0);
+    SAVED_GROUP_ID = gid;
+#else
+    rb_notimplement();
+#endif
+    return INT2FIX(gid);
+}
+
+static VALUE
+proc_switch_uauth(obj)
+    VALUE obj;
+{
+    extern int errno;
+    int uid, euid;
+
+    uid = getuid();
+    euid = geteuid();
+
+#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || _POSIX_SAVED_IDS
+    if (uid != euid) {
+      proc_seteuid(obj, INT2FIX(uid));
+      if (rb_block_given_p()) {
+	return rb_ensure(rb_yield, Qnil, rb_seteuid_core, 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()) {
+	return rb_ensure(rb_yield, Qnil, rb_seteuid_core, euid);
+      } else {
+	return INT2FIX(uid);
+      }
+    } else {
+      errno = EPERM;
+      rb_sys_fail(0);
+    }
+#else
+    if (uid == euid) {
+      errno = EPERM;
+      rb_sys_fail(0);
+    }
+    proc_swap_uid(obj);
+    if (rb_block_given_p()) {
+      return rb_ensure(rb_yield, Qnil, proc_swap_uid, obj);
+    } else {
+      return INT2FIX(euid);
+    }
+#endif
+}
+
+static VALUE
+proc_switch_gauth(obj)
+    VALUE obj;
+{
+    extern int errno;
+    int gid, egid;
+
+    gid = getgid();
+    egid = getegid();
+
+#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || _POSIX_SAVED_IDS
+    if (gid != egid) {
+      proc_setegid(obj, INT2FIX(gid));
+      if (rb_block_given_p()) {
+	return rb_ensure(rb_yield, Qnil, proc_setegid, INT2FIX(SAVED_GROUP_ID));
+      } else {
+	return INT2FIX(egid);
+      }
+    } else if (egid != SAVED_GROUP_ID) {
+      proc_setegid(obj, INT2FIX(SAVED_GROUP_ID));
+      if (rb_block_given_p()) {
+	return rb_ensure(rb_yield, Qnil, proc_setegid, INT2FIX(egid));
+      } else {
+	return INT2FIX(gid);
+      }
+    } else {
+      errno = EPERM;
+      rb_sys_fail(0);
+    }
+#else
+    if (gid == egid) {
+      errno = EPERM;
+      rb_sys_fail(0);
     }
-    else {
-	rb_notimplement();
+    proc_swap_gid(obj);
+    if (rb_block_given_p()) {
+      return rb_ensure(rb_yield, Qnil, proc_swap_gid, obj);
+    } else {
+      return INT2FIX(egid);
     }
 #endif
-    return egid;
 }
 
 VALUE
@@ -1333,6 +1706,8 @@
     rb_define_const(rb_mProcess, "PRIO_USER", INT2FIX(PRIO_USER));
 #endif
 
+    SAVED_USER_ID = geteuid();
+    SAVED_GROUP_ID = getegid();
     rb_define_module_function(rb_mProcess, "uid", proc_getuid, 0);
     rb_define_module_function(rb_mProcess, "uid=", proc_setuid, 1);
     rb_define_module_function(rb_mProcess, "gid", proc_getgid, 0);
@@ -1341,6 +1716,14 @@
     rb_define_module_function(rb_mProcess, "euid=", proc_seteuid, 1);
     rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
     rb_define_module_function(rb_mProcess, "egid=", proc_setegid, 1);
+#if defined(HAVE_SETRESUID) || (defined(HAVE_SETREUID) && !defined(__OpenBSD__))
+    rb_define_module_function(rb_mProcess, "swap_uid", proc_swap_uid, 0);
+#endif
+#if defined(HAVE_SETRESGID) || (defined(HAVE_SETREGID) && !defined(__OpenBSD__))
+    rb_define_module_function(rb_mProcess, "swap_gid", proc_swap_gid, 0);
+#endif
+    rb_define_module_function(rb_mProcess, "switch_uauth", proc_switch_uauth, 0);
+    rb_define_module_function(rb_mProcess, "switch_gauth", proc_switch_gauth, 0);
 
     rb_define_module_function(rb_mProcess, "times", rb_proc_times, 0);
 
============================================================
-- 
                                         永井 秀利 (九工大 知能情報)
                                             nagai@ai.kyutech.ac.jp

In This Thread

Prev Next