creds.ha (6191B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 // Unix credentials types & functions; ref credentials(7) 4 5 use errors; 6 use rt; 7 8 // Process ID. 9 export type pid = rt::pid_t; 10 11 // User ID. 12 export type uid = rt::uid_t; 13 14 // Group ID. 15 export type gid = rt::gid_t; 16 17 // Returns the current process user ID. 18 export fn getuid() uid = { 19 let uid = 0u, euid = 0u, suid = 0u; 20 rt::getresuid(&uid, &euid, &suid) as void; 21 return uid; 22 }; 23 24 // Returns the current process effective user ID. 25 export fn geteuid() uid = { 26 let uid = 0u, euid = 0u, suid = 0u; 27 rt::getresuid(&uid, &euid, &suid) as void; 28 return euid; 29 }; 30 31 // Returns the current process group ID. 32 export fn getgid() gid = { 33 let gid = 0u, egid = 0u, sgid = 0u; 34 rt::getresgid(&gid, &egid, &sgid) as void; 35 return gid; 36 }; 37 38 // Returns the current process effective group ID. 39 export fn getegid() gid = { 40 let gid = 0u, egid = 0u, sgid = 0u; 41 rt::getresgid(&gid, &egid, &sgid) as void; 42 return egid; 43 }; 44 45 // Sets the caller's user ID to the specified value. This generally requires 46 // elevated permissions from the calling process. 47 // 48 // If the system returns an error, this function will abort the program. Failing 49 // to handle errors from setuid is a grave security issue in your program, and 50 // therefore we require this function to succeed. If you need to handle the 51 // error case gracefully, call the appropriate syscall wrapper in [[rt::]] 52 // yourself, and take extreme care to handle errors correctly. 53 export fn setuid(uid: uid) void = rt::setresuid(uid, -1i: uint, -1i: uint)!; 54 55 // Sets the caller's effective user ID to the specified value. This generally 56 // requires elevated permissions from the calling process. 57 // 58 // If the system returns an error, this function will abort the program. Failing 59 // to handle errors from seteuid is a grave security issue in your program, and 60 // therefore we require this function to succeed. If you need to handle the 61 // error case gracefully, call the appropriate syscall wrapper in [[rt::]] 62 // yourself, and take extreme care to handle errors correctly. 63 export fn seteuid(uid: uid) void = rt::setresuid(-1i: uint, uid, -1i: uint)!; 64 65 // Sets the caller's group ID to the specified value. This generally requires 66 // elevated permissions from the calling process. 67 // 68 // If the system returns an error, this function will abort the program. Failing 69 // to handle errors from setuid is a grave security issue in your program, and 70 // therefore we require this function to succeed. If you need to handle the 71 // error case gracefully, call the appropriate syscall wrapper in [[rt::]] 72 // yourself, and take extreme care to handle errors correctly. 73 export fn setgid(gid: gid) void = rt::setresgid(gid, -1i: uint, -1i: uint)!; 74 75 // Sets the caller's effective group ID to the specified value. This generally 76 // requires elevated permissions from the calling process. 77 // 78 // If the system returns an error, this function will abort the program. Failing 79 // to handle errors from setegid is a grave security issue in your program, and 80 // therefore we require this function to succeed. If you need to handle the 81 // error case gracefully, call the appropriate syscall wrapper in [[rt::]] 82 // yourself, and take extreme care to handle errors correctly. 83 export fn setegid(gid: gid) void = rt::setresgid(-1i: uint, gid, -1i: uint)!; 84 85 // Returns a list of supplementary group IDs for the current process. The 86 // returned slice is statically allocated. 87 export fn getgroups() []gid = { 88 static let gids: [rt::NGROUPS_MAX]rt::gid_t = [0...]; 89 const n = rt::getgroups(gids)!; 90 return gids[..n]: []gid; 91 }; 92 93 // Sets the list of supplementary group IDs which apply to the current process. 94 // This generally requires elevated permissions. 95 // 96 // If the system returns an error, this function will abort the program. Failing 97 // to handle errors from setgroups is a grave security issue in your program, 98 // and therefore we require this function to succeed. If you need to handle the 99 // error case gracefully, call the appropriate syscall wrapper in [[rt::]] 100 // yourself, and take extreme care to handle errors correctly. 101 export fn setgroups(gids: []gid) void = rt::setgroups(gids: []rt::gid_t)!; 102 103 // Returns the current process ID. 104 export fn getpid() pid = rt::getpid(); 105 106 // Returns the parent process ID. 107 export fn getppid() pid = rt::getppid(); 108 109 // Returns the current process group ID. 110 export fn getpgrp() pid = rt::getpgrp(); 111 112 // Returns the process group associated with the given pid. 113 export fn getpgid(pid: pid) (pid | errors::noentry) = { 114 match (rt::getpgid(pid)) { 115 case let pid: rt::pid_t => 116 return pid; 117 case let err: rt::errno => 118 assert(err == rt::ESRCH, "Unexpected getpgid return value"); 119 return errors::noentry; 120 }; 121 }; 122 123 // Sets the process group ID of the specified process. This function is 124 // error-prone; see the notes in the POSIX specification for its many caveats. 125 export fn setpgid(targ: pid, pgid: pid) (void | errors::error) = { 126 match (rt::setpgid(targ, pgid)) { 127 case let err: rt::errno => 128 return errors::errno(err); 129 case void => 130 return; 131 }; 132 }; 133 134 // Returns the current process's session ID. 135 export fn getsid() pid = rt::getsid(0)!; 136 137 // Returns the session ID associated with the given process. 138 export fn getpsid(pid: pid) (pid | errors::noentry | errors::noaccess) = { 139 match (rt::getsid(pid)) { 140 case let pid: rt::pid_t => 141 return pid; 142 case let err: rt::errno => 143 assert(err == rt::ESRCH, "Unexpected getsid return value"); 144 return errors::noentry; 145 }; 146 }; 147 148 // Creates a new session and sets the current process to the session leader. 149 // A new process group is also created with its process group ID equal to the 150 // pid of the current process, and the current process is made the process group 151 // leader. 152 // 153 // Upon return, the new session will have no controlling terminal. To establish 154 // one, the caller must open a terminal file with [[fs::flag::CTTY]]; this 155 // opt-in approach differs from the Unix norm where O_NOCTTY is required to 156 // opt-out of establishing a controlling terminal. 157 // 158 // The current process cannot be a process group leader; this is a programmer 159 // error and will cause a runtime assertion failure. 160 export fn setsid() void = rt::setsid()!;