blob: 6ffaccbbf3649ee98a6c98374183aba3c7e13b1a [file] [log] [blame]
/** @file
POSIX Capability related utilities.
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <unistd.h>
#include <sys/types.h>
#include "tscore/ink_mutex.h"
/// Generate a debug message with the current capabilities for the process.
extern void DebugCapabilities(const char *tag ///< Debug message tag.
);
/// Set capabilities to persist across change of user id.
/// @return true on success
extern bool PreserveCapabilities();
/// Initialize and restrict the capabilities of a thread.
/// @return true on success
extern bool RestrictCapabilities();
/** Open a file, elevating privilege only if needed.
@internal This is necessary because the CI machines run the regression tests
as a normal user, not as root, so attempts to get privilege fail even though
the @c open would succeed without elevation. So, try that first and ask for
elevation only on an explicit permission failure.
*/
extern int elevating_open(const char *path, unsigned int flags, unsigned int fperms);
/// Open a file, elevating privilege only if needed.
extern int elevating_open(const char *path, unsigned int flags);
/// Open a file, elevating privilege only if needed.
extern FILE *elevating_fopen(const char *path, const char *mode);
// chmod a file, elevating if necessary
extern int elevating_chmod(const char *path, int perm);
/// @c stat a file, elevating only if needed.
extern int elevating_stat(const char *path, struct stat *buff);
/** Control generate of core file on crash.
@a flag sets whether core files are enabled on crash.
@return true on success
*/
extern bool EnableCoreFile(bool flag ///< New enable state.
);
void EnableDeathSignal(int signum);
enum ImpersonationLevel {
IMPERSONATE_EFFECTIVE, // Set the effective credential set.
IMPERSONATE_PERMANENT // Set the real credential (permanently).
};
void ImpersonateUser(const char *user, ImpersonationLevel level);
void ImpersonateUserID(uid_t user, ImpersonationLevel level);
class ElevateAccess
{
public:
typedef enum {
FILE_PRIVILEGE = 0x1u, ///< Access filesystem objects with privilege
TRACE_PRIVILEGE = 0x2u, ///< Trace other processes with privilege
LOW_PORT_PRIVILEGE = 0x4u, ///< Bind to privilege ports.
OWNER_PRIVILEGE = 0x8u ///< Bypass permission checks on operations that normally require
/// filesystem UID & process UID to match
} privilege_level;
ElevateAccess(unsigned level = FILE_PRIVILEGE);
~ElevateAccess();
void elevate(unsigned level);
void demote();
private:
bool elevated = false;
uid_t saved_uid;
unsigned level;
/// Acquire the privileges marked in @a mask for this process.
void acquirePrivilege(unsigned priv_mask);
/// Restore the privilege set to the state before acquiring them.
void releasePrivilege();
#if !TS_USE_POSIX_CAP
static ink_mutex lock; // only one thread at a time can elevate
#else
void *cap_state; ///< Original capabilities state to restore.
#endif
};