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