commit 6b209c4

Emilia Smólska  ·  2026-07-26 09:21:17 +0000 UTC
parent 3a7962b
setusercontext
3 files changed,  +36, -16
+7, -2
 1@@ -16,10 +16,15 @@
 2 #define HAVE_PLEDGE
 3 #endif
 4 
 5-/* setclasscontext library function present */
 6+/* login_cap.h present */
 7 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
 8-#define HAVE_SETCLASSCONTEXT
 9+#define HAVE_LOGIN_CAP
10 #endif
11+#ifdef __has_include
12+#if __has_include(<login_cap.h>)
13+#define HAVE_LOGIN_CAP
14+#endif
15+#endif 
16 
17 /* for compilers without attribute support */
18 /* #define __attribute(_) */
+4, -4
 1@@ -9,7 +9,7 @@
 2 .Sh SYNOPSIS
 3 .Nm
 4 .Op Fl n
 5-#ifdef HAVE_SETCLASSCONTEXT
 6+#ifdef HAVE_LOGIN_CAP
 7 .Op Fl c Ar class
 8 #endif
 9 .Op Fl G Ar gid
10@@ -29,7 +29,7 @@ utility allows a user to run a command
11 if no command is specified
12 .Pc
13 with a different
14-#ifdef HAVE_SETCLASSCONTEXT
15+#ifdef HAVE_LOGIN_CAP
16 login class,
17 #endif
18 group id,
19@@ -41,7 +41,7 @@ write permission on
20 .Pa CHECKFILE .
21 The options are as follows:
22 .Bl -tag -width 8n
23-#ifdef HAVE_SETCLASSCONTEXT
24+#ifdef HAVE_LOGIN_CAP
25 .It Fl c Ar class
26 Specify a login class.
27 #endif
28@@ -92,7 +92,7 @@ authorized.
29 .Xr chroot 1 ,
30 #endif
31 .Xr doas 1 ,
32-#ifdef HAVE_SETCLASSCONTEXT
33+#ifdef HAVE_LOGIN_CAP
34 .Xr login 1 ,
35 #endif
36 .Xr su 1 ,
+25, -10
 1@@ -13,7 +13,7 @@
 2 #include "arg.h"
 3 #include "config"
 4 
 5-#ifdef HAVE_SETCLASSCONTEXT
 6+#ifdef HAVE_LOGIN_CAP
 7 #include <login_cap.h>
 8 #endif
 9 
10@@ -29,6 +29,7 @@ char *argv0;
11 __attribute((format(printf, 1, 2)))
12 static noreturn void	die(char *, ...);
13 static noreturn void	usage(void);
14+static void		dosetuid(uid_t, struct passwd *);
15 
16 int
17 main(int argc, char **argv)
18@@ -65,11 +66,10 @@ main(int argc, char **argv)
19 		die(CHECKFILESTR ": %s", strerror(errno));
20 
21 	if(argc <= 1 || argv[1][0] != '-')
22-		if(setuid(0) < 0)
23-			die("setuid 0: %s", strerror(errno));
24+		dosetuid(0, nil);
25 
26 	ARGBEGIN{
27-#ifdef HAVE_SETCLASSCONTEXT 
28+#ifdef HAVE_LOGIN_CAP 
29 	case 'c': {
30 		arg = EARGF(usage());
31 		if(setclasscontext(arg, LOGIN_SETALL) < 0)
32@@ -120,8 +120,7 @@ main(int argc, char **argv)
33 		uid = strtol(arg, &end, 10);
34 		if(arg[0] == '\0' || end[0] != '\0')
35 			usage();
36-		if(setuid(uid) < 0)
37-			die("setuid %u: %s", uid, strerror(errno));
38+		dosetuid(uid, nil);
39 		break;
40 	}
41 	case 'u': {
42@@ -131,8 +130,7 @@ main(int argc, char **argv)
43 		passwd = getpwnam(arg);
44 		if(!passwd)
45 			die("%s: No such user", arg);
46-		if(setuid(passwd->pw_uid) < 0)
47-			die("setuid %u: %s", passwd->pw_uid, strerror(errno));
48+		dosetuid(passwd->pw_uid, passwd);
49 		break;
50 	}
51 	default:
52@@ -172,13 +170,30 @@ static noreturn void
53 usage(void)
54 {
55 	fprintf(stderr, "usage: %s [-n]"
56-#if defined(HAVE_SETCLASSCONTEXT)
57+#ifdef HAVE_LOGIN_CAP
58 	    "[-c class] "
59 #endif
60 	    "[-G gid] [-g group] "
61-#if defined(WITH_CHROOT)
62+#ifdef WITH_CHROOT
63 	    "[-r dir] "
64 #endif
65 	    "[-U uid] [-u user]\n", argv0);
66 	exit(1);
67 }
68+
69+static void
70+dosetuid(uid_t uid, struct passwd *passwd)
71+{
72+#ifdef HAVE_LOGIN_CAP
73+	if(!passwd)
74+		passwd = getpwuid(uid);
75+	if(!passwd)
76+		die("%u: No such user id", uid);
77+	if(setusercontext(nil, passwd, uid, LOGIN_SETALL) < 0)
78+		die("setusercontext: %s", strerror(errno));
79+#else
80+	(void)passwd;
81+	if(setuid(uid) < 0)
82+		die("setuid %u: %s", uid, strerror(errno));
83+#endif
84+}