hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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()!;