2011-07-22 11 views
4

Linux UIDの操作をやや混乱させないように、そしてmanページが乱雑であるため、Groovyの少しのコードで少し時間を費やしました。結果はTestCaseであり、setuid、seteuid、setfsuid、setreuid、setresuid呼び出しのフードの下で何が起こるかを示します。返されたエラーコードの詳細は考慮されませんでした。Linuxは、擬似コードで実際に保存されたファイルシステムのUID操作

質問は基本的には:私は何かを逃したのですか?現実と実効UIDとの違いについては

/** 
* This is some Groovy code to explain Linux privilege handling 
* The manipulable data structure is "PermVector", and it is manipulated through a 
* TestCase. 
*/ 

class PermissionTestCase extends GroovyTestCase { 

    class PermVector { 

    int ruid // real UID; affects the permissions for sending signals 
    int euid // effective UID; affects file creation and access 
    int suid // saved UID 
    int fsuid // filesystem UID; access control to the file system for NFS in Linux 

    /** 
    * The permission vector of a process that is created from a parent process 
    * having the given parent_euid, with its executable file having the given 
    * exe_suid_bit and being owned by the given exe_uid 
    */ 

    PermVector(Map params) { 
     ruid = params.parent_euid // is this right?? 
     euid = params.parent_euid 
     suid = params.exe_suid_bit ? params.exe_uid : params.parent_euid 
     fsuid = params.parent_euid // is this right?? 
    } 

    /** 
    * What does it mean for a process to be "privileged"? 
    */ 

    def isPrivileged() { 
     return euid == 0 
    } 

    /** 
    * Helper 
    */ 

    private def euid_part(int new_euid) { 
     if (isPrivileged() || 
      (new_euid == ruid || new_euid == euid || new_euid == suid)) { 
      return new_euid 
     } 
     else { 
      throw new IllegalStateException("Nixed euid ${euid} to ${new_euid}") 
     } 
    } 

    /** 
    * Helper 
    */ 

    private def ruid_part(int new_ruid) { 
     if (isPrivileged() || (new_ruid == ruid || new_ruid == euid)) { 
      return new_ruid 
     } 
     else { 
      throw new IllegalStateException("Nixed ruid ${ruid} to ${new_ruid}") 
     } 
    } 

    /** 
    * Helper 
    */ 

    private def suid_part(int new_suid) { 
     if (isPrivileged() || 
      (new_suid == ruid || new_suid == euid || new_suid == suid)) { 
      return new_suid 
     } 
     else { 
      throw new IllegalStateException("Nixed suid ${suid} to ${new_suid}") 
     } 
    } 

    /** 
    * Helper 
    */ 

    private def ruid_part_for_setresuid(int new_ruid) { 
     if (isPrivileged() || 
      (new_ruid == ruid || new_ruid == euid || new_ruid == suid)) { 
      return new_ruid 
     } 
     else { 
      throw new IllegalStateException("Nixed ruid ${ruid} to ${new_ruid}") 
     } 
    } 

    /** 
    * Behaviour of SETREUID(2) 
    */ 

    def setreuid(int new_ruid, int new_euid) { 
     int next_euid = euid_part(new_euid) 
     int next_ruid = ruid_part(new_ruid) 
     if (next_euid != euid || next_ruid != ruid) { 
      suid = next_euid 
     } 
     euid = next_euid 
     ruid = next_ruid 
     fsuid = next_euid 
    } 

    /** 
    * Behaviour of SETEUID(2) 
    */ 

    def seteuid(int new_euid) { 
     if (isPrivileged()) { 
      euid = new_euid 
      fsuid = new_euid 
     } 
     else { 
      if (new_euid == ruid || new_euid == euid || new_euid == suid) { 
       euid = new_euid 
       fsuid = new_euid 
       // glibc 2.1 and later do not change the suid! 
      } 
      else { 
       throw new IllegalStateException("Nixed euid ${euid} to ${new_euid}") 
      } 
     } 
    } 

    /** 
    * Behaviour of SETUID(2) 
    */ 

    def setuid(int new_euid) { 
     if (isPrivileged()) { 
      euid = new_euid 
      ruid = new_euid 
      suid = new_euid 
      fsuid = new_euid 
     } 
     else { 
      if (new_euid == ruid || new_euid == suid) { 
       euid = new_euid 
       fsuid = new_euid 
      } 
      else { 
       throw new IllegalStateException("Nixed euid ${euid} to ${new_euid}") 
      } 
     } 
    } 

    /** 
    * Behaviour of SETFSUID(2) 
    */ 

    def setfsuid(int new_fsuid) { 
     if (isPrivileged()) { 
      fsuid = new_fsuid 
     } 
     else { 
      if (new_fsuid == ruid || new_fsuid == euid || 
       new_fsuid == suid || new_fsuid == fsuid) { 
       fsuid = new_fsuid 
      } 
      else { 
       throw new IllegalStateException("Nixed fsuid ${fsuid} to ${new_fsuid}") 
      } 
     } 
    } 

    /** 
    * Behaviour of SETRESUID(2) 
    */ 

    def setresuid(int new_ruid, int new_euid, int new_suid) { 
     int next_ruid = new_ruid==-1 ? ruid : ruid_part_for_setresuid(new_ruid) 
     int next_euid = new_euid==-1 ? euid : euid_part(new_euid) 
     int next_suid = new_suid==-1 ? suid : suid_part(new_suid) 
     ruid = next_ruid 
     euid = next_euid 
     suid = next_suid 
     fsuid = next_euid 
    } 

    /** 
    * Printing 
    */ 

    String toString() { 
     return "[ruid:${ruid}, euid:${euid}, suid:${suid}, fsuid:${fsuid}]" 
    } 
} 


/** 
* Use case: drop privileges for good 
*/ 

void testDropPrivilegesFromRoot() { 
    PermVector pv = 
     new PermVector(parent_euid : 0, exe_suid_bit : false, exe_uid : 500)   
    System.out << "Dropping privileges from ${pv} using setuid(1000) .... " 
    pv.setuid(1000) 
    System.out << "now at ${pv}\n" 
    assertEquals(1000, pv.ruid) 
    assertEquals(1000, pv.euid) 
    assertEquals(1000, pv.suid) 
    assertEquals(1000, pv.fsuid) 

} 

/** 
* Use case: elevate privileges, do some work, then drop privileges again 
*/ 

void testElevatePrivilegesTemporarily() { 
    PermVector pv = 
     new PermVector(parent_euid : 500, exe_suid_bit : true, exe_uid : 0) 
    System.out << "Elevating privileges from ${pv} using setreuid(500,0) .... " 
    pv.setreuid(500,0)   
    System.out << "now at ${pv}, doing privileged work .... " 
    assertEquals(500, pv.ruid) 
    assertEquals(0, pv.euid) 
    assertEquals(0, pv.suid) 
    assertEquals(0, pv.fsuid) 
    System.out << "dropping back .... "   
    pv.setuid(500) 
    System.out << "now at ${pv}\n" 
    assertEquals(500, pv.ruid) 
    assertEquals(500, pv.euid) 
    assertEquals(500, pv.suid) 
    assertEquals(500, pv.fsuid) 

} 

/** 
* Use case: drop privileges, do some work, then elevate privileges again 
*/ 

void testDropPrivilegesTemporarily() { 
    PermVector pv = 
     new PermVector(parent_euid : 0, exe_suid_bit : false, exe_uid : 500) 
    System.out << "Dropping privileges from ${pv} using setreuid(0,500) .... " 
    pv.setreuid(0, 500) 
    System.out << "now at ${pv} ... doing unprivileged work safely .... " 
    assertEquals(0, pv.ruid) 
    assertEquals(500, pv.euid) 
    assertEquals(500, pv.suid) 
    assertEquals(500, pv.fsuid) 
    System.out << "elevating .... " 
    pv.setuid(0) 
    System.out << "back at ${pv}\n" 
    assertEquals(0, pv.ruid) 
    assertEquals(0, pv.euid) 
    assertEquals(500, pv.suid) 
    assertEquals(0, pv.fsuid) 

    } 
} 
+0

これは私にとっては良いテストのようですが、プログラミング言語のタグを含めると、あなたの質問に目を向けるでしょう。多くのユーザーは、「自分たちの」タグセットだけを見ます。 Groovyでテストを書いている間に、Unixの内部について最もよく知っている人はcプログラマですので、Groovyでタグ付けしてもそれ以上の応答が得られない場合はC(言語)に変更してください。確かに適切なタグ「unix-programming」もあります。がんばろう! – shellter

答えて

5

、たとえばthisために読んで - これは、UNIXのUIDの重要な概念です。たとえば、設定されたUIDビットが設定されたプロセスがあり、通常のユーザーがそれを実行する場合、彼は実効UID(たとえばroot)を持ちますが、実際のUIDは引き続きUIDになります。この例を理解すると、より明確になります...

関連する問題