• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_cap.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003     A brief file description
00004 
00005     @section license License
00006 
00007     Licensed to the Apache Software Foundation (ASF) under one
00008     or more contributor license agreements.  See the NOTICE file
00009     distributed with this work for additional information
00010     regarding copyright ownership.  The ASF licenses this file
00011     to you under the Apache License, Version 2.0 (the
00012     "License"); you may not use this file except in compliance
00013     with the License.  You may obtain a copy of the License at
00014 
00015     http://www.apache.org/licenses/LICENSE-2.0
00016 
00017     Unless required by applicable law or agreed to in writing, software
00018     distributed under the License is distributed on an "AS IS" BASIS,
00019     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020     See the License for the specific language governing permissions and
00021     limitations under the License.
00022 */
00023 
00024 # include "ink_config.h"
00025 # include "Diags.h"
00026 # include "ink_cap.h"
00027 # include "ink_thread.h"
00028 
00029 # if TS_USE_POSIX_CAP
00030 #   include <sys/capability.h>
00031 #   include <sys/prctl.h>
00032 # endif
00033 
00034 # if !TS_USE_POSIX_CAP
00035 ink_mutex ElevateAccess::lock = INK_MUTEX_INIT;
00036 #endif
00037 
00038 void
00039 DebugCapabilities(char const* tag) {
00040   if (is_debug_tag_set(tag)) {
00041 #   if TS_USE_POSIX_CAP
00042       cap_t caps = cap_get_proc();
00043       char* caps_text = cap_to_text(caps, 0);
00044 #   endif
00045 
00046 #     if TS_USE_POSIX_CAP
00047     Debug(tag, "uid=%u, gid=%u, euid=%u, egid=%u, caps %s core=%s thread=0x%llx",
00048           static_cast<unsigned int>(getuid()),
00049           static_cast<unsigned int>(getgid()),
00050           static_cast<unsigned int>(geteuid()),
00051           static_cast<unsigned int>(getegid()),
00052           caps_text,
00053           prctl(PR_GET_DUMPABLE) != 1 ? "disabled" : "enabled",
00054           (unsigned long long)pthread_self() );
00055     cap_free(caps_text);
00056     cap_free(caps);
00057 #else
00058     Debug(tag, "uid=%u, gid=%u, euid=%u, egid=%u",
00059           static_cast<unsigned int>(getuid()),
00060           static_cast<unsigned int>(getgid()),
00061           static_cast<unsigned int>(geteuid()),
00062           static_cast<unsigned int>(getegid()) );
00063 #endif
00064   }
00065 }
00066 
00067 int
00068 PreserveCapabilities() {
00069   int zret = 0;
00070 # if TS_USE_POSIX_CAP
00071     zret = prctl(PR_SET_KEEPCAPS, 1);
00072 # endif
00073   Debug("proxy_priv", "[PreserveCapabilities] zret : %d\n", zret);
00074   return zret;
00075 }
00076 
00077 // Adjust the capabilities to only those needed.
00078 int
00079 RestrictCapabilities() {
00080   int zret = 0; // return value.
00081 # if TS_USE_POSIX_CAP
00082     cap_t caps = cap_init(); // start with nothing.
00083     // Capabilities we need.
00084     cap_value_t perm_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_IPC_LOCK, CAP_DAC_OVERRIDE};
00085     static int const PERM_CAP_COUNT = sizeof(perm_list)/sizeof(*perm_list);
00086     cap_value_t eff_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_IPC_LOCK};
00087     static int const EFF_CAP_COUNT = sizeof(eff_list)/sizeof(*eff_list);
00088 
00089     cap_set_flag(caps, CAP_PERMITTED, PERM_CAP_COUNT, perm_list, CAP_SET);
00090     cap_set_flag(caps, CAP_EFFECTIVE, EFF_CAP_COUNT, eff_list, CAP_SET);
00091     zret = cap_set_proc(caps);
00092     cap_free(caps);
00093 #  endif
00094   Debug("proxy_priv", "[RestrictCapabilities] zret : %d\n", zret);
00095   return zret;
00096 }
00097 
00098 int
00099 EnableCoreFile(bool flag) {
00100   int zret = 0;
00101 # if defined(linux)
00102     int state = flag ? 1 : 0;
00103     if (0 > (zret = prctl(PR_SET_DUMPABLE, state, 0, 0, 0))) {
00104       Warning("Unable to set PR_DUMPABLE : %s", strerror(errno));
00105     } else if (state != prctl(PR_GET_DUMPABLE)) {
00106       zret = ENOSYS; // best guess
00107       Warning("Call to set PR_DUMPABLE was ineffective");
00108     }
00109 # endif  // linux check
00110   Debug("proxy_priv", "[EnableCoreFile] zret : %d\n", zret);
00111   return zret;
00112 }
00113 
00114 #if TS_USE_POSIX_CAP
00115 /** Control file access privileges to bypass DAC.
00116     @parm state Use @c true to enable elevated privileges,
00117     @c false to disable.
00118     @return @c true if successful, @c false otherwise.
00119 
00120     @internal After some pondering I decided that the file access
00121     privilege was worth the effort of restricting. Unlike the network
00122     privileges this can protect a host system from programming errors
00123     by not (usually) permitting such errors to access arbitrary
00124     files. This is particularly true since none of the config files
00125     current enable this feature so it's not actually called. Still,
00126     best to program defensively and have it available.
00127  */
00128 bool
00129 elevateFileAccess(bool state)
00130 {
00131   Debug("proxy_priv", "[elevateFileAccess] state : %d\n", state);
00132 
00133   bool zret = false; // return value.
00134   cap_t cap_state = cap_get_proc(); // current capabilities
00135   // Make a list of the capabilities we changed.
00136   cap_value_t cap_list[] = { CAP_DAC_OVERRIDE };
00137   static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
00138 
00139   cap_set_flag(cap_state, CAP_EFFECTIVE, CAP_COUNT, cap_list, state ? CAP_SET : CAP_CLEAR);
00140   zret = (0 == cap_set_proc(cap_state));
00141   cap_free(cap_state);
00142   Debug("proxy_priv", "[elevateFileAccess] zret : %d\n", zret);
00143   return zret;
00144 }
00145 #else
00146 //  bool removeRootPriv()
00147 //
00148 //    - Returns true on success
00149 //      and false on failure
00150 bool
00151 removeRootPriv(uid_t euid)
00152 {
00153   if (seteuid(euid) < 0) {
00154     Debug("proxy_priv", "[removeRootPriv] seteuid failed : %s\n", strerror(errno));
00155     return false;
00156   }
00157 
00158   Debug("proxy_priv", "[removeRootPriv] removed root privileges.  Euid is %d\n", euid);
00159   return true;
00160 }
00161 
00162 //  bool restoreRootPriv()
00163 //
00164 //    - Returns true on success
00165 //      and false on failure
00166 bool
00167 restoreRootPriv(uid_t *old_euid)
00168 {
00169   if (old_euid)
00170     *old_euid = geteuid();
00171   if (seteuid(0) < 0) {
00172     Debug("proxy_priv", "[restoreRootPriv] seteuid root failed : %s\n", strerror(errno));
00173     return false;
00174   }
00175 
00176   Debug("proxy_priv", "[restoreRootPriv] restored root privileges.  Euid is %d\n", 0);
00177 
00178   return true;
00179 }
00180 #endif

Generated by  doxygen 1.7.1