| 1 |
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
|
| 2 |
index 4bbf622..0785b04 100644
|
| 3 |
--- a/src/knot/conf/conf.c
|
| 4 |
+++ b/src/knot/conf/conf.c
|
| 5 |
@@ -309,6 +309,10 @@ static int conf_process(conf_t *conf)
|
| 6 |
strncat(dest, dbext, strlen(dbext));
|
| 7 |
zone->ixfr_db = dest;
|
| 8 |
}
|
| 9 |
+
|
| 10 |
+ /* Update UID and GID. */
|
| 11 |
+ if (conf->uid < 0) conf->uid = getuid();
|
| 12 |
+ if (conf->gid < 0) conf->gid = getgid();
|
| 13 |
|
| 14 |
return ret;
|
| 15 |
}
|
| 16 |
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
|
| 17 |
index 97412dd..7f74bca 100644
|
| 18 |
--- a/src/knot/ctl/knotc_main.c
|
| 19 |
+++ b/src/knot/ctl/knotc_main.c
|
| 20 |
@@ -43,7 +43,8 @@ enum knotc_flag_t {
|
| 21 |
F_VERBOSE = 1 << 1,
|
| 22 |
F_WAIT = 1 << 2,
|
| 23 |
F_INTERACTIVE = 1 << 3,
|
| 24 |
- F_AUTO = 1 << 4
|
| 25 |
+ F_AUTO = 1 << 4,
|
| 26 |
+ F_UNPRIVILEGED= 1 << 5
|
| 27 |
};
|
| 28 |
|
| 29 |
static inline unsigned has_flag(unsigned flags, enum knotc_flag_t f) {
|
| 30 |
@@ -142,10 +143,15 @@ pid_t wait_cmd(pid_t proc, int *rc)
|
| 31 |
return proc;
|
| 32 |
}
|
| 33 |
|
| 34 |
-pid_t start_cmd(const char *argv[], int argc)
|
| 35 |
+pid_t start_cmd(const char *argv[], int argc, int flags)
|
| 36 |
{
|
| 37 |
pid_t chproc = fork();
|
| 38 |
if (chproc == 0) {
|
| 39 |
+
|
| 40 |
+ /* Alter privileges. */
|
| 41 |
+ if (flags & F_UNPRIVILEGED) {
|
| 42 |
+ proc_update_privileges(conf()->uid, conf()->gid);
|
| 43 |
+ }
|
| 44 |
|
| 45 |
/* Duplicate, it doesn't run from stack address anyway. */
|
| 46 |
char **args = malloc((argc + 1) * sizeof(char*));
|
| 47 |
@@ -180,7 +186,7 @@ pid_t start_cmd(const char *argv[], int argc)
|
| 48 |
int exec_cmd(const char *argv[], int argc)
|
| 49 |
{
|
| 50 |
int ret = 0;
|
| 51 |
- pid_t proc = start_cmd(argv, argc);
|
| 52 |
+ pid_t proc = start_cmd(argv, argc, 0);
|
| 53 |
wait_cmd(proc, &ret);
|
| 54 |
return ret;
|
| 55 |
}
|
| 56 |
@@ -291,17 +297,6 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
|
| 57 |
int valid_cmd = 0;
|
| 58 |
int rc = 0;
|
| 59 |
if (strcmp(action, "start") == 0) {
|
| 60 |
- // Check pidfile for w+
|
| 61 |
- FILE* chkf = fopen(pidfile, "w+");
|
| 62 |
- if (chkf == NULL) {
|
| 63 |
- log_server_error("PID file '%s' is not writeable, "
|
| 64 |
- "refusing to start\n", pidfile);
|
| 65 |
- return 1;
|
| 66 |
- } else {
|
| 67 |
- fclose(chkf);
|
| 68 |
- chkf = NULL;
|
| 69 |
- }
|
| 70 |
-
|
| 71 |
// Check PID
|
| 72 |
valid_cmd = 1;
|
| 73 |
// if (pid < 0 && pid == KNOT_ERANGE) {
|
| 74 |
@@ -604,7 +599,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
|
| 75 |
}
|
| 76 |
fflush(stdout);
|
| 77 |
fflush(stderr);
|
| 78 |
- pid_t zcpid = start_cmd(args, ac);
|
| 79 |
+ pid_t zcpid = start_cmd(args, ac, F_UNPRIVILEGED);
|
| 80 |
zctask_add(tasks, jobs, zcpid, zone);
|
| 81 |
++running;
|
| 82 |
}
|
| 83 |
@@ -722,7 +717,7 @@ int main(int argc, char **argv)
|
| 84 |
log_levels_add(LOGT_STDOUT, LOG_ANY,
|
| 85 |
LOG_MASK(LOG_INFO)|LOG_MASK(LOG_DEBUG));
|
| 86 |
}
|
| 87 |
-
|
| 88 |
+
|
| 89 |
// Fetch PID
|
| 90 |
char* pidfile = pid_filename();
|
| 91 |
if (!pidfile) {
|
| 92 |
diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c
|
| 93 |
index bb61804..8864cd0 100644
|
| 94 |
--- a/src/knot/ctl/process.c
|
| 95 |
+++ b/src/knot/ctl/process.c
|
| 96 |
@@ -21,6 +21,8 @@
|
| 97 |
#include <errno.h>
|
| 98 |
#include <string.h>
|
| 99 |
#include <signal.h>
|
| 100 |
+#include <grp.h>
|
| 101 |
+#include <unistd.h>
|
| 102 |
|
| 103 |
#include "knot/common.h"
|
| 104 |
#include "knot/ctl/process.h"
|
| 105 |
@@ -113,6 +115,7 @@ int pid_write(const char* fn)
|
| 106 |
int pid_remove(const char* fn)
|
| 107 |
{
|
| 108 |
if (unlink(fn) < 0) {
|
| 109 |
+ perror("unlink");
|
| 110 |
return KNOTD_EINVAL;
|
| 111 |
}
|
| 112 |
|
| 113 |
@@ -124,3 +127,45 @@ int pid_running(pid_t pid)
|
| 114 |
return kill(pid, 0) == 0;
|
| 115 |
}
|
| 116 |
|
| 117 |
+void proc_update_privileges(int uid, int gid)
|
| 118 |
+{
|
| 119 |
+#ifdef HAVE_SETGROUPS
|
| 120 |
+ /* Drop supplementary groups. */
|
| 121 |
+ if (uid != getuid() || gid != getgid()) {
|
| 122 |
+ if (setgroups(0, NULL) < 0) {
|
| 123 |
+ log_server_warning("Failed to drop supplementary groups"
|
| 124 |
+ " for uid '%d' (%s).\n",
|
| 125 |
+ getuid(), strerror(errno));
|
| 126 |
+ }
|
| 127 |
+ }
|
| 128 |
+#endif
|
| 129 |
+
|
| 130 |
+ /* Watch uid/gid. */
|
| 131 |
+ if (gid != getgid()) {
|
| 132 |
+ log_server_info("Changing group id to '%d'.\n", gid);
|
| 133 |
+ if (setregid(gid, gid) < 0) {
|
| 134 |
+ log_server_error("Failed to change gid to '%d'.\n",
|
| 135 |
+ gid);
|
| 136 |
+ }
|
| 137 |
+ }
|
| 138 |
+ if (uid != getuid()) {
|
| 139 |
+ log_server_info("Changing user id to '%d'.\n", uid);
|
| 140 |
+ if (setreuid(uid, uid) < 0) {
|
| 141 |
+ log_server_error("Failed to change uid to '%d'.\n",
|
| 142 |
+ uid);
|
| 143 |
+ }
|
| 144 |
+ }
|
| 145 |
+
|
| 146 |
+ /* Check storage writeability. */
|
| 147 |
+ char *lfile = strcdup(conf()->storage, "/knot.lock");
|
| 148 |
+ assert(lfile != NULL);
|
| 149 |
+ FILE* fp = fopen(lfile, "w");
|
| 150 |
+ if (fp == NULL) {
|
| 151 |
+ log_server_warning("Storage directory '%s' is not writeable.\n",
|
| 152 |
+ conf()->storage);
|
| 153 |
+ } else {
|
| 154 |
+ fclose(fp);
|
| 155 |
+ unlink(lfile);
|
| 156 |
+ }
|
| 157 |
+ free(lfile);
|
| 158 |
+}
|
| 159 |
diff --git a/src/knot/ctl/process.h b/src/knot/ctl/process.h
|
| 160 |
index d8f2f4c..a387add 100644
|
| 161 |
--- a/src/knot/ctl/process.h
|
| 162 |
+++ b/src/knot/ctl/process.h
|
| 163 |
@@ -83,6 +83,15 @@ int pid_remove(const char* fn);
|
| 164 |
*/
|
| 165 |
int pid_running(pid_t pid);
|
| 166 |
|
| 167 |
+/*!
|
| 168 |
+ * \brief Update process privileges to new UID/GID.
|
| 169 |
+ *
|
| 170 |
+ * \param uid New user ID.
|
| 171 |
+ * \param gid New group ID.
|
| 172 |
+ *
|
| 173 |
+ */
|
| 174 |
+void proc_update_privileges(int uid, int gid);
|
| 175 |
+
|
| 176 |
#endif // _KNOTD_PROCESS_H_
|
| 177 |
|
| 178 |
/*! @} */
|
| 179 |
diff --git a/src/knot/main.c b/src/knot/main.c
|
| 180 |
index 99ee1cf..a62230a 100644
|
| 181 |
--- a/src/knot/main.c
|
| 182 |
+++ b/src/knot/main.c
|
| 183 |
@@ -20,6 +20,7 @@
|
| 184 |
#include <unistd.h>
|
| 185 |
#include <getopt.h>
|
| 186 |
#include <limits.h>
|
| 187 |
+
|
| 188 |
#ifdef HAVE_CAP_NG_H
|
| 189 |
#include <cap-ng.h>
|
| 190 |
#endif /* HAVE_CAP_NG_H */
|
| 191 |
@@ -161,7 +162,6 @@ int main(int argc, char **argv)
|
| 192 |
conf_read_lock();
|
| 193 |
conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0);
|
| 194 |
conf_add_hook(conf(), CONF_ALL, server_conf_hook, server);
|
| 195 |
- conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
|
| 196 |
conf_read_unlock();
|
| 197 |
|
| 198 |
// Find implicit configuration file
|
| 199 |
@@ -242,21 +242,28 @@ int main(int argc, char **argv)
|
| 200 |
}
|
| 201 |
log_server_info("\n");
|
| 202 |
|
| 203 |
- // Create server instance
|
| 204 |
- char* pidfile = pid_filename();
|
| 205 |
+ /* Alter privileges. */
|
| 206 |
+ proc_update_privileges(conf()->uid, conf()->gid);
|
| 207 |
+
|
| 208 |
+ /* Load zones and add hook. */
|
| 209 |
+ zones_ns_conf_hook(conf(), server->nameserver);
|
| 210 |
+ conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
|
| 211 |
|
| 212 |
// Run server
|
| 213 |
int res = 0;
|
| 214 |
+ int has_pid = 0;
|
| 215 |
+ char* pidfile = pid_filename();
|
| 216 |
log_server_info("Starting server...\n");
|
| 217 |
if ((server_start(server)) == KNOTD_EOK) {
|
| 218 |
|
| 219 |
// Save PID
|
| 220 |
- int has_pid = 1;
|
| 221 |
+ has_pid = 1;
|
| 222 |
int rc = pid_write(pidfile);
|
| 223 |
if (rc < 0) {
|
| 224 |
has_pid = 0;
|
| 225 |
log_server_warning("Failed to create "
|
| 226 |
- "PID file '%s'.\n", pidfile);
|
| 227 |
+ "PID file '%s' (%s).\n",
|
| 228 |
+ pidfile, strerror(errno));
|
| 229 |
}
|
| 230 |
|
| 231 |
// Change directory if daemonized
|
| 232 |
@@ -370,7 +377,7 @@ int main(int argc, char **argv)
|
| 233 |
server_destroy(&server);
|
| 234 |
|
| 235 |
// Remove PID file
|
| 236 |
- if (pid_remove(pidfile) < 0) {
|
| 237 |
+ if (has_pid && pid_remove(pidfile) < 0) {
|
| 238 |
log_server_warning("Failed to remove PID file.\n");
|
| 239 |
}
|
| 240 |
|
| 241 |
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
|
| 242 |
index 5611a0c..5df7fe1 100644
|
| 243 |
--- a/src/knot/server/server.c
|
| 244 |
+++ b/src/knot/server/server.c
|
| 245 |
@@ -22,8 +22,6 @@
|
| 246 |
#include <errno.h>
|
| 247 |
#include <openssl/evp.h>
|
| 248 |
#include <assert.h>
|
| 249 |
-#include <grp.h>
|
| 250 |
-
|
| 251 |
|
| 252 |
#include "common/prng.h"
|
| 253 |
#include "knot/common.h"
|
| 254 |
@@ -743,51 +741,9 @@ int server_conf_hook(const struct conf_t *conf, void *data)
|
| 255 |
"configured interfaces.\n");
|
| 256 |
}
|
| 257 |
}
|
| 258 |
-
|
| 259 |
- /* Lock configuration. */
|
| 260 |
- conf_read_lock();
|
| 261 |
- int priv_failed = 0;
|
| 262 |
-
|
| 263 |
-#ifdef HAVE_SETGROUPS
|
| 264 |
- /* Drop supplementary groups. */
|
| 265 |
- if (conf->gid > -1 || conf->uid > -1) {
|
| 266 |
- ret = setgroups(0, NULL);
|
| 267 |
-
|
| 268 |
- /* Collect results. */
|
| 269 |
- if (ret < 0) {
|
| 270 |
- log_server_error("Failed to set supplementary groups "
|
| 271 |
- "for uid '%d' (%s).\n",
|
| 272 |
- getuid(), strerror(errno));
|
| 273 |
- priv_failed = 1;
|
| 274 |
- }
|
| 275 |
- }
|
| 276 |
-#endif
|
| 277 |
-
|
| 278 |
- /* Watch uid/gid. */
|
| 279 |
- if (conf->gid > -1 && conf->gid != getgid()) {
|
| 280 |
- log_server_info("Changing group id to '%d'.\n", conf->gid);
|
| 281 |
- if (setregid(conf->gid, conf->gid) < 0) {
|
| 282 |
- log_server_error("Failed to change gid to '%d'.\n",
|
| 283 |
- conf->gid);
|
| 284 |
- priv_failed = 1;
|
| 285 |
- }
|
| 286 |
- }
|
| 287 |
- if (conf->uid > -1 && conf->uid != getuid()) {
|
| 288 |
- log_server_info("Changing user id to '%d'.\n", conf->uid);
|
| 289 |
- if (setreuid(conf->uid, conf->uid) < 0) {
|
| 290 |
- log_server_error("Failed to change uid to '%d'.\n",
|
| 291 |
- conf->uid);
|
| 292 |
- priv_failed = 1;
|
| 293 |
- }
|
| 294 |
- }
|
| 295 |
-
|
| 296 |
- if (priv_failed) {
|
| 297 |
- ret = KNOTD_EACCES;
|
| 298 |
- }
|
| 299 |
|
| 300 |
/* Exit if the server is not running. */
|
| 301 |
if (ret != KNOTD_EOK || !(server->state & ServerRunning)) {
|
| 302 |
- conf_read_unlock();
|
| 303 |
return KNOTD_ENOTRUNNING;
|
| 304 |
}
|
| 305 |
|
| 306 |
@@ -807,9 +763,6 @@ int server_conf_hook(const struct conf_t *conf, void *data)
|
| 307 |
}
|
| 308 |
}
|
| 309 |
|
| 310 |
- /* Unlock config. */
|
| 311 |
- conf_read_unlock();
|
| 312 |
-
|
| 313 |
return ret;
|
| 314 |
}
|
| 315 |
|
| 316 |
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
|
| 317 |
index c4415d4..3c39004 100644
|
| 318 |
--- a/src/zcompile/zcompile.c
|
| 319 |
+++ b/src/zcompile/zcompile.c
|
| 320 |
@@ -570,7 +570,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
|
| 321 |
}
|
| 322 |
|
| 323 |
if (!knot_dname_is_fqdn(dname)) {
|
| 324 |
- fprintf(stderr, "Error: given zone origin is not FQDN.\n");
|
| 325 |
+ log_zone_error("Error: given zone origin is not FQDN.\n");
|
| 326 |
knot_dname_release(dname);
|
| 327 |
return KNOTDZCOMPILE_EINVAL;
|
| 328 |
}
|
| 329 |
@@ -660,8 +660,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
|
| 330 |
|
| 331 |
if (found_orphans != parser->rrsig_orphan_count) {
|
| 332 |
/*! \todo This might be desired behaviour. */
|
| 333 |
- fprintf(stderr,
|
| 334 |
- "There are unassigned RRSIGs in the zone!\n");
|
| 335 |
+ log_zone_error("There are unassigned RRSIGs in the zone!\n");
|
| 336 |
parser->errors++;
|
| 337 |
}
|
| 338 |
|