2011-07-22 20 views
4

我花了一些時間在Groovy中的一些代碼上,使Linux UID操作對自己的混淆更少一些,因爲手冊頁很雜亂。結果就是一個TestCase,它是爲了顯示setuid,seteuid,setfsuid,setreuid和setresuid調用引發的情況。沒有考慮關於返回的錯誤代碼的細節(或不)。Linux有效的,真實的,保存的,僞代碼中的文件系統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

對於真實和有效的UID之間的差別,例如讀取this - 這是UNIX的UID的關鍵概念。你可以例如有一個設置了UID位集的進程,如果普通用戶運行它,他將擁有根的有效UID(例如),但真正的UID仍然是他的UID。在你明白這個例子後,它會變得更加清晰......

相關問題