Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Started work on running Fossil as different OS user per Flint user |
|---|---|
| Timelines: | family | ancestors | descendants | both | setuid-fossil |
| Files: | files | file ages | folders |
| SHA1: |
91893d0dc39ba9f1efa44037f0685572 |
| User & Date: | rkeene 2019-01-07 22:40:17.093 |
Context
|
2019-01-07
| ||
| 23:07 | Ensure User ID is sane before calling fossil check-in: 0874801b3e user: rkeene tags: setuid-fossil | |
| 22:40 | Started work on running Fossil as different OS user per Flint user check-in: 91893d0dc3 user: rkeene tags: setuid-fossil | |
|
2017-03-16
| ||
| 16:32 | Fixed missing semicolons check-in: f6600ad1a1 user: rkeene tags: trunk | |
Changes
Added .fossil-settings/ignore-glob.
> > | 1 2 | scripts/fossil-as-user/suid-fossil scripts/fossil-as-user/lib/* |
Added scripts/fossil-as-user/Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | CRYSTAL_PATH := /opt/appfs/rkeene.org/crystal/platform/latest CRYSTAL := $(CRYSTAL_PATH)/bin/crystal SHARDS := $(CRYSTAL_PATH)/bin/shards DEBUG_OR_RELEASE := --debug all: suid-fossil lib: shard.lock rm -rf lib $(SHARDS) install shard.lock: shard.yml suid-fossil: suid-fossil.cr lib $(CRYSTAL) build $(DEBUG_OR_RELEASE) -o suid-fossil suid-fossil.cr clean: rm -f suid-fossil distclean: clean rm -rf lib mrproper: distclean rm -f shard.lock $(MAKE) lib rm -rf lib .PHONY: all clean distclean .SUFFIXES: |
Added scripts/fossil-as-user/shard.lock.
> > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 |
version: 1.0
shards:
db:
github: crystal-lang/crystal-db
version: 0.5.1
sqlite3:
github: crystal-lang/crystal-sqlite3
version: 0.10.0
|
Added scripts/fossil-as-user/shard.yml.
> > > > > | 1 2 3 4 5 |
name: fossil-as-user
version: 1
dependencies:
sqlite3:
github: crystal-lang/crystal-sqlite3
|
Added scripts/fossil-as-user/suid-fossil.cr.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
#! /opt/appfs/rkeene.org/crystal/platform/latest/bin/crystal
require "sqlite3"
require "ini"
# User-specified constants
## UID offset when mapping Flint user IDs to OS user IDs
UID_OFFSET = 1024 * 1024
##
FLINT_ROOT = "/home/chiselapp/chisel"
# Import the C functions for setuid/setgid
lib C
fun setuid(uid : Int32) : Int32
fun setgid(gid : Int32) : Int32
end
# Usage information
def print_help
print("Usage: suid-fossil <fossil-args...>\n")
end
# Convert a UserID or a Username to the other via the DB
def userid_from_db(userdb : String, username : String) : Int32
userid = nil
DB.open "sqlite3://#{userdb}" {|db|
userid = db.query_one "SELECT id FROM users WHERE username = ? LIMIT 1", username, as: {Int32}
}
if userid.nil?
raise "User Name could not be found"
end
userid
end
def username_from_db(userdb : String, userid : Int32) : String
username = nil
DB.open "sqlite3://#{userdb}" {|db|
username = db.query_one "SELECT username FROM users WHERE id = ? LIMIT 1", userid, as: {String}
}
if username.nil?
raise "User ID could not be found"
end
username
end
# Find the Flint DB given a path to the Flint root
def find_db(root : String) : String
dbconfig_file = File.join(root, "config", "sqlite.cnf")
dbconfig_text = File.read(dbconfig_file)
dbconfig = INI.parse(dbconfig_text)
dbfile = dbconfig["config"]["database"]
dbfile = File.expand_path(dbfile, File.join(root, "db"))
dbfile
end
# Find a Flint User ID from an OS File
def userid_from_file(file : String) : Int32
info = File.info(file)
Int32.new(info.owner - UID_OFFSET)
end
# Run Fossil, wrapped as a Flint UserName/UserID
def suid_fossil(username : String, userid : Int32, fossil_args : Array, fossil_command = "fossil")
# Compute OS UID from Flint User ID
uid = userid + UID_OFFSET
# Create Fossil home directory
home = "/tmp/suid-fossil/#{userid}"
if !Dir.exists?(home)
Dir.mkdir(home, 0o700)
File.chown(home, uid, uid)
end
ENV["HOME"] = home
# Set OS UID/GID
## Opportunistic -- if it fails, we do not care
C.setgid(uid)
uidcheck = C.setuid(uid)
if (uidcheck != 0)
raise "Unable to switch to UID #{uid}"
end
# If possible, update environment with usernames
ENV["USER"] = username
ENV["USERNAME"] = username
Process.exec(fossil_command, fossil_args)
raise "Failed to run Fossil"
end
# -------------------------------
# MAIN
# -------------------------------
fossil_args = ARGV
flint_root = ENV.fetch("FLINT_ROOT", FLINT_ROOT)
userid = ENV["FLINT_USERID"]?
username = ENV["FLINT_USERNAME"]?
# Find DB if possible
userdb = ENV["FLINT_USERDB"]?
if userdb.nil?
if !flint_root.nil?
userdb = find_db(flint_root)
end
end
# Find User ID
## Check to see if this is a CGI call, if so
## we take the user ID from the filename
if userid.nil?
if ENV.has_key?("GATEWAY_INTERFACE")
userid = userid_from_file(ARGV[0])
end
end
if userid.nil?
if username.nil?
raise "Unhandled -- must specify one of FLINT_USERNAME or FLINT_USERID"
end
if userdb.nil?
raise "Unhandled -- must specify FLINT_USERDB or FLINT_ROOT"
end
userid = userid_from_db(userdb, username)
else
userid = userid.to_i32()
end
# Find User Name
if username.nil?
if userdb.nil?
raise "Unhandled -- must specify FLINT_USERDB or FLINT_ROOT"
end
username = username_from_db(userdb, userid)
end
# Run Fossil
suid_fossil(username, userid, fossil_args)
|