Use c app to call brew
This commit is contained in:
@@ -24,17 +24,6 @@ function ensureUserIsInAdminGroup() {
|
|||||||
dseditgroup -o edit -a "${username}" -t user admin
|
dseditgroup -o edit -a "${username}" -t user admin
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureUserCanRunPasswordlessSudo() {
|
|
||||||
local username=$1
|
|
||||||
local sudoersFile="/etc/sudoers.d/no-auth-sudo-for-${username}"
|
|
||||||
[[ -f ${sudoersFile} ]] && return
|
|
||||||
cat <<- SUDOERS > "${sudoersFile}"
|
|
||||||
Defaults:${username} !authenticate
|
|
||||||
SUDOERS
|
|
||||||
chown root:wheel "${sudoersFile}" || return 10
|
|
||||||
chmod u=rw,g=r,o= "${sudoersFile}" || return 20
|
|
||||||
}
|
|
||||||
|
|
||||||
function getFirstFreeRoleAccountID() {
|
function getFirstFreeRoleAccountID() {
|
||||||
local minUserID=450
|
local minUserID=450
|
||||||
local maxUserID=499
|
local maxUserID=499
|
||||||
@@ -96,33 +85,88 @@ function getHomebrewRepositoryPath() {
|
|||||||
|
|
||||||
function createBrewCallerScript() {
|
function createBrewCallerScript() {
|
||||||
ensureLocalBinFolder
|
ensureLocalBinFolder
|
||||||
local uname_machine=$(/usr/bin/uname -m)
|
|
||||||
local username=${homebrew_username}
|
local username=${homebrew_username}
|
||||||
local homebrewRepositoryPath="$(getHomebrewRepositoryPath)"
|
local homebrewRepositoryPath="$(getHomebrewRepositoryPath)"
|
||||||
local brewCallerPath="${homebrewRepositoryPath}/bin/brew-caller"
|
local brewCallerPath="${homebrewRepositoryPath}/bin/brew-caller"
|
||||||
local brewCallerSymlink="/usr/local/bin/brew"
|
local brewCallerSymlink="/usr/local/bin/brew"
|
||||||
[[ ${uname_machine} == "arm64" ]] && brewCallerPath="${brewCallerSymlink}"
|
|
||||||
[ -f "${brewCallerPath}" ] && rm "${brewCallerPath}"
|
[ -f "${brewCallerPath}" ] && rm "${brewCallerPath}"
|
||||||
cat <<- BREWCALLER > ${brewCallerPath}
|
cat <<- BREWCALLER | clang -x c -O2 -Wall -o "${brewCallerPath}" -
|
||||||
#!/usr/bin/env zsh
|
#include <unistd.h>
|
||||||
if [ "\$(id -un)" != "${username}" ]; then
|
#include <sys/types.h>
|
||||||
echo 'brew will be run as ${username} user.' >&2
|
#include <sys/stat.h>
|
||||||
sudo -E -u "${username}" "\$0" "\$@"
|
#include <pwd.h>
|
||||||
exit \$?
|
#include <grp.h>
|
||||||
fi
|
#include <stdlib.h>
|
||||||
export HOMEBREW_CACHE="${homebrew_cache}"
|
#include <stdio.h>
|
||||||
export HOMEBREW_LOGS="${homebrew_log}"
|
#include <string.h>
|
||||||
export HOMEBREW_CASK_OPTS="--no-quarantine \${HOMEBREW_CASK_OPTS}"
|
#include <errno.h>
|
||||||
export HOMEBREW_NO_AUTO_UPDATE=1
|
|
||||||
export HOMEBREW_NO_ANALYTICS=1
|
extern char **environ;
|
||||||
export HOMEBREW_NO_ANALYTICS_THIS_RUN=1
|
|
||||||
export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1
|
char *format_env(const char *env_name, const char *format) {
|
||||||
umask 002
|
if (!env_name || !format) return NULL;
|
||||||
"${homebrewRepositoryPath}/bin/brew" "\$@"
|
const char *value = getenv(env_name);
|
||||||
|
if (!value) return NULL;
|
||||||
|
int formatted_len = snprintf(NULL, 0, format, value);
|
||||||
|
if (formatted_len < 0) return NULL;
|
||||||
|
char *formatted_value = malloc(formatted_len + 1);
|
||||||
|
if (!formatted_value) return NULL;
|
||||||
|
snprintf(formatted_value, formatted_len + 1, format, value);
|
||||||
|
size_t result_len = strlen(env_name) + 1 + formatted_len;
|
||||||
|
char *result = malloc(result_len + 1);
|
||||||
|
if (!result) { free(formatted_value); return NULL; }
|
||||||
|
sprintf(result, "%s=%s", env_name, formatted_value);
|
||||||
|
free(formatted_value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HOMEBREW_USER "${username}"
|
||||||
|
#define HOMEBREW_DIR "${homebrewRepositoryPath}/bin"
|
||||||
|
#define BREW_PATH HOMEBREW_DIR "/brew"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
struct passwd *pw;
|
||||||
|
uid_t target_uid;
|
||||||
|
gid_t target_gid;
|
||||||
|
|
||||||
|
pw = getpwnam(HOMEBREW_USER);
|
||||||
|
if (!pw) { fprintf(stderr, "Error: user %s not found\n", HOMEBREW_USER); return 1; }
|
||||||
|
target_uid = pw->pw_uid;
|
||||||
|
target_gid = pw->pw_gid;
|
||||||
|
|
||||||
|
char *new_environ[] = {
|
||||||
|
"PATH=" HOMEBREW_DIR "/usr/bin:/bin",
|
||||||
|
"HOMEBREW_CACHE=${homebrew_cache}",
|
||||||
|
"HOMEBREW_LOGS=${homebrew_log}",
|
||||||
|
format_env("HOME", "%s"),
|
||||||
|
format_env("HOMEBREW_CASK_OPTS", "--no-quarantine %s"),
|
||||||
|
"HOMEBREW_NO_AUTO_UPDATE=1",
|
||||||
|
"HOMEBREW_NO_ANALYTICS=1",
|
||||||
|
"HOMEBREW_NO_ANALYTICS_THIS_RUN=1",
|
||||||
|
"HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (setegid(target_gid) != 0) { fprintf(stderr, "setegid(%d): %s\n", target_gid, strerror(errno)); return 1; }
|
||||||
|
|
||||||
|
if (seteuid(target_uid) != 0) { fprintf(stderr, "seteuid(%d): %s\n", target_uid, strerror(errno)); return 1; }
|
||||||
|
|
||||||
|
char **newargv = malloc((argc + 1) * sizeof(char *));
|
||||||
|
if (!newargv) { fprintf(stderr, "malloc failed for new argv\n"); return 1; }
|
||||||
|
|
||||||
|
newargv[0] = (char *)BREW_PATH;
|
||||||
|
for (int i = 1; i < argc; ++i) newargv[i] = argv[i];
|
||||||
|
newargv[argc] = NULL;
|
||||||
|
umask(0002);
|
||||||
|
|
||||||
|
execve(BREW_PATH, newargv, new_environ);
|
||||||
|
fprintf(stderr, "execv(%s) failed: %s\n", BREW_PATH, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
BREWCALLER
|
BREWCALLER
|
||||||
chown root:admin ${brewCallerPath}
|
chown root:admin ${brewCallerPath}
|
||||||
chmod ug+x,o-x ${brewCallerPath}
|
chmod 4550 ${brewCallerPath}
|
||||||
[[ ${uname_machine} == "arm64" ]] || ln -s "${brewCallerPath}" "${brewCallerSymlink}"
|
ln -s "${brewCallerPath}" "${brewCallerSymlink}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBrewPeriodicScript() {
|
function createBrewPeriodicScript() {
|
||||||
@@ -214,7 +258,6 @@ function configure_system() {
|
|||||||
lop -y h1 -- -i 'Install System Homebrew'
|
lop -y h1 -- -i 'Install System Homebrew'
|
||||||
createHomebrewUserIfNeccessary || return 10
|
createHomebrewUserIfNeccessary || return 10
|
||||||
indicateActivity 'Ensure Homebrew user is in admin group' ensureUserIsInAdminGroup ${homebrew_username} || return 11
|
indicateActivity 'Ensure Homebrew user is in admin group' ensureUserIsInAdminGroup ${homebrew_username} || return 11
|
||||||
indicateActivity 'Ensure Homebrew user can run passwordless sudo' ensureUserCanRunPasswordlessSudo ${homebrew_username} || return 12
|
|
||||||
ensureHomebrewCacheDirectory || return 13
|
ensureHomebrewCacheDirectory || return 13
|
||||||
ensureHomebrewLogDirectory || return 14
|
ensureHomebrewLogDirectory || return 14
|
||||||
indicateActivity 'Install Homebrew core' installHomebrewCore || return 15
|
indicateActivity 'Install Homebrew core' installHomebrewCore || return 15
|
||||||
|
|||||||
Reference in New Issue
Block a user