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) |