Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1895

Show
Ignore:
Timestamp:
02/19/08 12:27:22
Author:
fumanchu
Message:

Fix for #789 (Bug in DropPrivileges? plugin). Untested.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/restsrv/plugins.py

    r1854 r1895  
    103103 
    104104 
     105 
     106try: 
     107    import pwd, grp 
     108except ImportError: 
     109    pwd, grp = None, None 
     110 
     111 
    105112class DropPrivileges(SimplePlugin): 
    106     """Drop privileges. 
     113    """Drop privileges. uid/gid arguments not available on Windows. 
    107114     
    108115    Special thanks to Gavin Baker: http://antonym.org/node/100. 
    109116    """ 
    110117     
    111     def __init__(self, bus): 
     118    def __init__(self, bus, umask=None, uid=None, gid=None): 
    112119        SimplePlugin.__init__(self, bus) 
    113120        self.finalized = False 
    114      
    115     try: 
    116         import pwd, grp 
    117     except ImportError: 
    118         try: 
    119             os.umask 
    120         except AttributeError: 
    121             def start(self): 
    122                 """Drop privileges. Not implemented on this platform.""" 
    123                 raise NotImplementedError 
     121        self.uid = uid 
     122        self.gid = gid 
     123        self.umask = umask 
     124     
     125    def _get_uid(self): 
     126        return self._uid 
     127    def _set_uid(self, val): 
     128        if val is not None: 
     129            if pwd is None: 
     130                self.bus.log("pwd module not available; ignoring uid.") 
     131                val = None 
     132            elif isinstance(val, basestring): 
     133                val = pwd.getpwnam(val)[2] 
     134        self._uid = val 
     135    uid = property(_get_uid, _set_uid, doc="The uid under which to run.") 
     136     
     137    def _get_gid(self): 
     138        return self._gid 
     139    def _set_gid(self, val): 
     140        if val is not None: 
     141            if grp is None: 
     142                self.bus.log("grp module not available; ignoring gid.") 
     143                val = None 
     144            elif isinstance(val, basestring): 
     145                val = grp.getgrnam(val)[2] 
     146        self._gid = val 
     147    gid = property(_get_gid, _set_gid, doc="The gid under which to run.") 
     148     
     149    def _get_umask(self): 
     150        return self._umask 
     151    def _set_umask(self, val): 
     152        if val is not None: 
     153            try: 
     154                os.umask 
     155            except AttributeError: 
     156                self.bus.log("umask function not available; ignoring umask.") 
     157                val = None 
     158        self._umask = val 
     159    umask = property(_get_umask, _set_umask, doc="The umask under which to run.") 
     160     
     161    def start(self): 
     162        # uid/gid 
     163        def current_ids(): 
     164            """Return the current (uid, gid) if available.""" 
     165            name, group = None, None 
     166            if pwd: 
     167                name = pwd.getpwuid(os.getuid())[0] 
     168            if grp: 
     169                group = grp.getgrgid(os.getgid())[0] 
     170            return name, group 
     171         
     172        if self.finalized: 
     173            if not (self.uid is None and self.gid is None): 
     174                self.bus.log('Already running as uid: %r gid: %r' % 
     175                             current_ids()) 
    124176        else: 
    125             umask = None 
    126              
    127             def start(self): 
    128                 """Drop privileges. Windows version (umask only).""" 
    129                 if self.finalized: 
    130                     self.bus.log('umask already set to: %03o' % umask) 
    131                 else: 
    132                     if umask is None: 
    133                         self.bus.log('umask not set') 
    134                     else: 
    135                         old_umask = os.umask(umask) 
    136                         self.bus.log('umask old: %03o, new: %03o' % 
    137                                      (old_umask, umask)) 
    138                     self.finalized = True 
    139     else: 
    140         uid = None 
    141         gid = None 
    142         umask = None 
    143          
    144         def start(self): 
    145             """Drop privileges. UNIX version (uid, gid, and umask).""" 
    146             if uid is None and gid is None: 
     177            if self.uid is None and self.gid is None: 
    147178                self.bus.log('uid/gid not set') 
    148179            else: 
    149                 if uid is None: 
    150                     uid = None 
    151                 elif isinstance(uid, basestring): 
    152                     uid = pwd.getpwnam(uid)[2] 
    153                 else: 
    154                     uid = uid 
    155                  
    156                 if gid is None: 
    157                     gid = None 
    158                 elif isinstance(gid, basestring): 
    159                     gid = grp.getgrnam(gid)[2] 
    160                 else: 
    161                     gid = gid 
    162                  
    163                 def names(): 
    164                     name = pwd.getpwuid(os.getuid())[0] 
    165                     group = grp.getgrgid(os.getgid())[0] 
    166                     return name, group 
    167                  
    168                 if self.finalized: 
    169                     self.bus.log('Already running as: %r/%r' % names()) 
    170                 else: 
    171                     self.bus.log('Started as %r/%r' % names()) 
    172                     if gid is not None: 
    173                         os.setgid(gid) 
    174                     if uid is not None: 
    175                         os.setuid(uid) 
    176                     self.bus.log('Running as %r/%r' % names()) 
    177              
    178             if self.finalized: 
    179                 self.bus.log('umask already set to: %03o' % umask) 
     180                self.bus.log('Started as uid: %r gid: %r' % current_ids()) 
     181                if self.gid is not None: 
     182                    os.setgid(gid) 
     183                if self.uid is not None: 
     184                    os.setuid(uid) 
     185                self.bus.log('Running as uid: %r gid: %r' % current_ids()) 
     186         
     187        # umask 
     188        if self.finalized: 
     189            if self.umask is not None: 
     190                self.bus.log('umask already set to: %03o' % self.umask) 
     191        else: 
     192            if self.umask is None: 
     193                self.bus.log('umask not set') 
    180194            else: 
    181                 if umask is None: 
    182                     self.bus.log('umask not set') 
    183                 else: 
    184                     old_umask = os.umask(umask) 
    185                     self.bus.log('umask old: %03o, new: %03o' % 
    186                                  (old_umask, umask)) 
    187                 self.finalized = True 
     195                old_umask = os.umask(self.umask) 
     196                self.bus.log('umask old: %03o, new: %03o' % 
     197                             (old_umask, self.umask)) 
     198         
     199        self.finalized = True 
    188200    start.priority = 75 
    189201 
     
    197209     
    198210    When this component finishes, the process is completely decoupled from 
    199     the parent environment.  Please note that when this component is used, 
    200     the return code from the parent process will always be 0, even if a 
    201     startup error occured, unless that error was during the daemonizing process.  
    202     If you use this plugin to Daemonize, don't use the return code as an accurate 
    203     indication of whether the process fully started.  In fact, that return code 
    204     only indicates if the process succesfully finished the first fork. 
     211    the parent environment. Please note that when this component is used, 
     212    the return code from the parent process will still be 0 if a startup 
     213    error occurs in the forked children. Errors in the initial daemonizing 
     214    process still return proper exit codes. Therefore, if you use this 
     215    plugin to daemonize, don't use the return code as an accurate indicator 
     216    of whether the process fully started. In fact, that return code only 
     217    indicates if the process succesfully finished the first fork. 
    205218    """ 
    206219     
     
    269282        se = open(self.stderr, "a+", 0) 
    270283 
    271         # os.dup2(fd,fd2) will close fd2 if necessary (so we don't explicitly close 
    272         # stdin,stdout,stderr): 
    273         # http://docs.python.org/lib/os-fd-ops.html  
     284        # os.dup2(fd, fd2) will close fd2 if necessary, 
     285        # so we don't explicitly close stdin/out/err. 
     286        # See http://docs.python.org/lib/os-fd-ops.html 
    274287        os.dup2(si.fileno(), sys.stdin.fileno()) 
    275288        os.dup2(so.fileno(), sys.stdout.fileno()) 

Hosted by WebFaction

Log in as guest/cpguest to create tickets