-/* $OpenBSD: spamd-setup.c,v 1.48 2016/01/04 09:15:24 mestre Exp $ */
+/* $OpenBSD: spamd-setup.c,v 1.49 2017/07/07 00:09:14 djm Exp $ */
/*
* Copyright (c) 2003 Bob Beck. All rights reserved.
#include <arpa/inet.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PATH_PFCTL "/sbin/pfctl"
#define PATH_SPAMD_CONF "/etc/mail/spamd.conf"
#define SPAMD_ARG_MAX 256 /* max # of args to an exec */
+#define SPAMD_USER "_spamd"
struct cidr {
u_int32_t addr;
void cidr2range(struct cidr, u_int32_t *, u_int32_t *);
char *atop(u_int32_t);
int parse_netblock(char *, struct bl *, struct bl *, int);
-int open_child(char *, char **);
+int open_child(char *, char **, int);
int fileget(char *);
int open_file(char *, char *);
char *fix_quoted_colons(char *);
int getlist(char **, char *, struct blacklist *, struct blacklist *);
__dead void usage(void);
+uid_t spamd_uid;
+gid_t spamd_gid;
int debug;
int dryrun;
int greyonly = 1;
return (1);
}
+void
+drop_privileges(void)
+{
+ if (setgroups(1, &spamd_gid) != 0)
+ err(1, "setgroups %ld", (long)spamd_gid);
+ if (setresgid(spamd_gid, spamd_gid, spamd_gid) != 0)
+ err(1, "setresgid %ld", (long)spamd_gid);
+ if (setresuid(spamd_uid, spamd_uid, spamd_uid) != 0)
+ err(1, "setresuid %ld", (long)spamd_uid);
+}
+
int
-open_child(char *file, char **argv)
+open_child(char *file, char **argv, int drop_privs)
{
int pdes[2];
dup2(pdes[1], STDOUT_FILENO);
close(pdes[1]);
}
+ if (drop_privs)
+ drop_privileges();
+ closefrom(STDERR_FILENO + 1);
execvp(file, argv);
_exit(1);
}
if (debug)
fprintf(stderr, "Getting %s\n", url);
- return (open_child(PATH_FTP, argv));
+ return (open_child(PATH_FTP, argv, 1));
}
int
ap++;
}
*ap = NULL;
- i = open_child(argv[0], argv);
+ i = open_child(argv[0], argv, 0);
oerrno = errno;
free(argv);
errno = oerrno;
dup2(pdes[0], STDIN_FILENO);
close(pdes[0]);
}
+ closefrom(STDERR_FILENO + 1);
execvp(PATH_PFCTL, argv);
_exit(1);
}
struct blacklist *blists;
struct servent *ent;
int daemonize = 0, ch;
+ struct passwd *pw;
while ((ch = getopt(argc, argv, "bdDn")) != -1) {
switch (ch) {
if (argc != 0)
usage();
- if (pledge("stdio rpath inet proc exec", NULL) == -1)
+ if ((pw = getpwnam(SPAMD_USER)) == NULL)
+ errx(1, "cannot find user %s", SPAMD_USER);
+ spamd_uid = pw->pw_uid;
+ spamd_gid = pw->pw_gid;
+
+ if (pledge("stdio rpath inet proc exec id", NULL) == -1)
err(1, "pledge");
if (daemonize)
daemon(0, 0);
+ else if (chdir("/") != 0)
+ err(1, "chdir(\"/\")");
if ((ent = getservbyname("spamd-cfg", "tcp")) == NULL)
errx(1, "cannot find service \"spamd-cfg\" in /etc/services");