View Javadoc

1   //========================================================================
2   //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
3   //------------------------------------------------------------------------
4   //Licensed under the Apache License, Version 2.0 (the "License");
5   //you may not use this file except in compliance with the License.
6   //You may obtain a copy of the License at 
7   //http://www.apache.org/licenses/LICENSE-2.0
8   //Unless required by applicable law or agreed to in writing, software
9   //distributed under the License is distributed on an "AS IS" BASIS,
10  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  //See the License for the specific language governing permissions and
12  //limitations under the License.
13  //========================================================================
14  
15  package org.mortbay.setuid;
16  
17  import org.mortbay.jetty.Connector;
18  import org.mortbay.jetty.Server;
19  import org.mortbay.log.Log;
20  
21  /**
22   * This extension of {@link Server} will make a JNI call to set the unix UID.
23   *
24   * This can be used to start the server as root so that privileged ports may
25   * be accessed and then switch to a non-root user for security.
26   * Depending on the value of {@link #setStartServerAsPrivileged(boolean)}, either the
27   * server will be started and then the UID set; or the {@link Server#getConnectors()} will be 
28   * opened with a call to {@link Connector#open()}, the UID set and then the server is started.
29   * The later is the default and avoids any webapplication code being run as a privileged user,
30   * but will not work if the application code also needs to open privileged ports.
31   *
32   *<p>
33   * The configured umask is set before the server is started and the configured
34   * uid is set after the server is started.
35   * </p>
36   * @author gregw
37   *
38   */
39  public class SetUIDServer extends Server
40  {
41      private int _uid=0;
42      private int _gid=0;
43      private int _umask=0;
44      private boolean _startServerAsPrivileged;
45      private RLimit _rlimitNoFiles = null;
46      
47      public void setUsername(String username)
48      {
49          Passwd passwd = SetUID.getpwnam(username);
50          _uid = passwd.getPwUid();
51      }
52      
53      public String getUsername()
54      {
55          Passwd passwd = SetUID.getpwuid(_uid);
56          return passwd.getPwName();
57      }
58      
59      public void setGroupname(String groupname)
60      {
61          Group group = SetUID.getgrnam(groupname);
62          _gid = group.getGrGid();
63      }
64      
65      public String getGroupname()
66      {
67          Group group = SetUID.getgrgid(_gid);
68          return group.getGrName();
69      }
70  
71  
72      public int getUmask ()
73      {
74          return _umask;
75      }
76  
77      public void setUmask(int umask)
78      {
79          _umask=umask;
80      }
81      
82      public int getUid()
83      {
84          return _uid;
85      }
86  
87      public void setUid(int uid)
88      {
89          _uid=uid;
90      }
91      
92      public void setGid(int gid)
93      {
94          _gid=gid;
95      }
96      
97      public int getGid()
98      {
99          return _gid;
100     }
101 
102     public void setRLimitNoFiles(RLimit rlimit)
103     {
104         _rlimitNoFiles = rlimit;
105     }
106     
107     public RLimit getRLimitNoFiles ()
108     {
109         return _rlimitNoFiles;
110     }
111     
112     protected void doStart() throws Exception
113     {
114         if (_umask!=0)
115         {
116             Log.info("Setting umask=0"+Integer.toString(_umask,8));
117             SetUID.setumask(_umask);
118         }
119         
120         if (_rlimitNoFiles != null)
121         {
122             Log.info("Current "+SetUID.getrlimitnofiles());
123             int success = SetUID.setrlimitnofiles(_rlimitNoFiles);
124             if (success < 0)
125                 Log.warn("Failed to set rlimit_nofiles, returned status "+success);
126             Log.info("Set "+SetUID.getrlimitnofiles());
127         }
128         
129         if (_startServerAsPrivileged)
130         {
131             super.doStart();
132             if (_gid!=0)
133             {
134                 Log.info("Setting GID="+_gid);
135                 SetUID.setgid(_gid);
136             }
137             if (_uid!=0)
138             {
139                 Log.info("Setting UID="+_uid);
140                 SetUID.setuid(_uid);
141             }
142         }
143         else
144         {
145             Connector[] connectors = getConnectors();
146             for (int i=0;connectors!=null && i<connectors.length;i++)
147                 connectors[i].open();
148             if (_gid!=0)
149             {
150                 Log.info("Setting GID="+_gid);
151                 SetUID.setgid(_gid);
152             }
153             if (_uid!=0)
154             {
155                 Log.info("Setting UID="+_uid);
156                 SetUID.setuid(_uid);
157             }
158             super.doStart();
159         }
160     }
161 
162     /* ------------------------------------------------------------ */
163     /**
164      * @return the startServerAsPrivileged 
165      */
166     public boolean isStartServerAsPrivileged()
167     {
168         return _startServerAsPrivileged;
169     }
170 
171     /* ------------------------------------------------------------ */
172     /**
173      * @see {@link Connector#open()}
174      * @param startServerAsPrivileged if true, the server is started and then the process UID is switched. If false, the connectors are opened, the UID is switched and then the server is started.
175      */
176     public void setStartServerAsPrivileged(boolean startContextsAsPrivileged)
177     {
178         _startServerAsPrivileged=startContextsAsPrivileged;
179     }
180     
181 }