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
|
/*
* Process identity: max25-bcprd runs unprivileged; init drops from root.
*/
#define _GNU_SOURCE
#include "bcpr/bcpr_runas.h"
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int bcpr_runas_refuse_root(int dry_run)
{
if (geteuid() == 0 && !dry_run) {
fprintf(stderr,
"max25-bcprd: refusing to run as root — use max25-bcprd-init "
"(setuid) for live SER12\n");
return -1;
}
return 0;
}
int bcpr_runas_drop(const bcpr_config_t *cfg)
{
struct passwd *pw;
struct group *gr = NULL;
gid_t gid;
uid_t uid;
const char *name;
if (!cfg || !cfg->run_user[0]) {
fprintf(stderr, "max25-bcpr: [max25-bcpr] user= required for daemon\n");
return -1;
}
if (geteuid() != 0) {
fprintf(stderr, "max25-bcpr: privilege drop requires euid=0\n");
return -1;
}
pw = getpwnam(cfg->run_user);
if (!pw) {
fprintf(stderr, "max25-bcpr: unknown user=%s\n", cfg->run_user);
return -1;
}
uid = pw->pw_uid;
gid = pw->pw_gid;
name = pw->pw_name;
if (cfg->run_group[0]) {
gr = getgrnam(cfg->run_group);
if (!gr) {
fprintf(stderr, "max25-bcpr: unknown group=%s\n", cfg->run_group);
return -1;
}
gid = gr->gr_gid;
}
if (initgroups(name, gid) != 0) {
fprintf(stderr, "max25-bcpr: initgroups(%s) failed: %s\n", name,
strerror(errno));
return -1;
}
if (setgid(gid) != 0) {
fprintf(stderr, "max25-bcpr: setgid failed: %s\n", strerror(errno));
return -1;
}
if (setuid(uid) != 0) {
fprintf(stderr, "max25-bcpr: setuid failed: %s\n", strerror(errno));
return -1;
}
if (setuid(0) == 0) {
fprintf(stderr, "max25-bcpr: privilege drop incomplete\n");
return -1;
}
fprintf(stderr, "max25-bcpr: running as uid=%u gid=%u (%s)\n",
(unsigned)uid, (unsigned)gid, name);
return 0;
}
|