/* * Copyright (c) 2002, 2003, 2004 BalaBit IT Ltd, Budapest, Hungary * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * Note that this permission is granted for only version 2 of the GPL. * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "affile.h" #include "driver.h" #include "messages.h" #include "macros.h" #include "misc.h" #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <time.h> #include <stdlib.h> #include <stdio.h> #if !HAVE_O_LARGEFILE #define O_LARGEFILE 0 #endif #if 0/*start dongshu*/ static gboolean affile_open_file(gchar *name, int flags, int uid, int gid, int mode, int dir_uid, int dir_gid, int dir_mode, int create_dirs, int *fd) { if (strstr(name, "../") || strstr(name, "/..")) { msg_error("Spurious path, logfile not created", evt_tag_str("path", name), NULL); return FALSE; } *fd = open(name, flags, mode); if (create_dirs && *fd == -1 && errno == ENOENT) { /* directory does not exist */ char *p = name + 1; p = strchr(p, '/'); while (p) { struct stat st; *p = 0; if (stat(name, &st) == 0) { if (!S_ISDIR(st.st_mode)) return FALSE; } else if (errno == ENOENT) { if (mkdir(name, dir_mode) == -1) return 0; if (dir_uid != -1 || dir_gid != -1) chown(name, dir_uid, dir_gid); if (dir_mode != -1) /* CID 13888 (#1 of 1): Argument cannot be negative , no problem*/ /* CID 10351 (#1 of 1): Unchecked return value from library no problem*/ chmod(name, dir_mode); } *p = '/'; p = strchr(p + 1, '/'); } *fd = open(name, flags, mode); } if (*fd != -1) { g_fd_set_cloexec(*fd, TRUE); if (uid != -1) fchown(*fd, uid, -1); if (gid != -1) fchown(*fd, -1, gid); if (mode != -1) fchmod(*fd, mode); } return *fd != -1; }
static void afsocket_sd_accept(gpointer s) { AFSocketSourceDriver *self = (AFSocketSourceDriver *) s; GSockAddr *peer_addr; gchar buf1[256], buf2[256]; gint new_fd; gboolean res; int accepts = 0; while (accepts < MAX_ACCEPTS_AT_A_TIME) { GIOStatus status; status = g_accept(self->fd, &new_fd, &peer_addr); if (status == G_IO_STATUS_AGAIN) { /* no more connections to accept */ break; } else if (status != G_IO_STATUS_NORMAL) { msg_error("Error accepting new connection", evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); return; } g_fd_set_nonblock(new_fd, TRUE); g_fd_set_cloexec(new_fd, TRUE); res = afsocket_sd_process_connection(self, peer_addr, self->bind_addr, new_fd); if (res) { if (peer_addr->sa.sa_family != AF_UNIX) msg_notice("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); else msg_verbose("Syslog connection accepted", evt_tag_int("fd", new_fd), evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)), evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)), NULL); } else { close(new_fd); } g_sockaddr_unref(peer_addr); accepts++; } return; }
static gboolean afprogram_sd_init(LogPipe *s) { AFProgramSourceDriver *self = (AFProgramSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; if (!log_src_driver_init_method(s)) return FALSE; if (cfg) log_reader_options_init(&self->reader_options, cfg, self->super.super.group); msg_verbose("Starting source program", evt_tag_str("cmdline", self->process_info.cmdline->str)); if (!afprogram_popen(&self->process_info, G_IO_IN, &fd)) return FALSE; /* parent */ child_manager_register(self->process_info.pid, afprogram_sd_exit, log_pipe_ref(&self->super.super.super), (GDestroyNotify) log_pipe_unref); g_fd_set_nonblock(fd, TRUE); g_fd_set_cloexec(fd, TRUE); if (!self->reader) { LogTransport *transport; transport = log_transport_pipe_new(fd); self->reader = log_reader_new(s->cfg); log_reader_reopen(self->reader, log_proto_text_server_new(transport, &self->reader_options.proto_options.super), poll_fd_events_new(fd)); log_reader_set_options(self->reader, s, &self->reader_options, STATS_LEVEL0, SCS_PROGRAM, self->super.super.id, self->process_info.cmdline->str); } log_pipe_append((LogPipe *) self->reader, &self->super.super.super); if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing program source, closing fd", evt_tag_int("fd", fd)); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); return FALSE; } return TRUE; }
static inline void _set_fd_permission(FilePermOptions *perm_opts, int fd) { if (fd != -1) { g_fd_set_cloexec(fd, TRUE); g_process_cap_modify(CAP_CHOWN, TRUE); g_process_cap_modify(CAP_FOWNER, TRUE); if (perm_opts) file_perm_options_apply_fd(perm_opts, fd); } }
static gboolean _create_store(PersistState *self) { self->fd = open(self->temp_filename, O_RDWR | O_CREAT | O_TRUNC, 0600); if (self->fd < 0) { msg_error("Error creating persistent state file", evt_tag_str("filename", self->temp_filename), evt_tag_errno("error", errno), NULL); return FALSE; } g_fd_set_cloexec(self->fd, TRUE); self->current_key_block = offsetof(PersistFileHeader, initial_key_store); self->current_key_ofs = 0; self->current_key_size = sizeof((((PersistFileHeader *) NULL))->initial_key_store); return _grow_store(self, PERSIST_FILE_INITIAL_SIZE); }
gboolean transport_mapper_open_socket(TransportMapper *self, SocketOptions *socket_options, GSockAddr *bind_addr, AFSocketDirection dir, int *fd) { gint sock; sock = socket(self->address_family, self->sock_type, self->sock_proto); if (sock < 0) { msg_error("Error creating socket", evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); goto error; } g_fd_set_nonblock(sock, TRUE); g_fd_set_cloexec(sock, TRUE); if (!transport_mapper_privileged_bind(sock, bind_addr)) { gchar buf[256]; msg_error("Error binding socket", evt_tag_str("addr", g_sockaddr_format(bind_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); goto error_close; } if (!socket_options_setup_socket(socket_options, sock, bind_addr, dir)) goto error_close; *fd = sock; return TRUE; error_close: close(sock); error: *fd = -1; return FALSE; }
static gboolean afsocket_open_socket(GSockAddr *bind_addr, int stream_or_dgram, int *fd) { gint sock; if (stream_or_dgram) sock = socket(bind_addr->sa.sa_family, SOCK_STREAM, 0); else sock = socket(bind_addr->sa.sa_family, SOCK_DGRAM, 0); if (sock != -1) { cap_t saved_caps; g_fd_set_nonblock(sock, TRUE); g_fd_set_cloexec(sock, TRUE); saved_caps = g_process_cap_save(); g_process_cap_modify(CAP_NET_BIND_SERVICE, TRUE); g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE); if (g_bind(sock, bind_addr) != G_IO_STATUS_NORMAL) { gchar buf[256]; g_process_cap_restore(saved_caps); msg_error("Error binding socket", evt_tag_str("addr", g_sockaddr_format(bind_addr, buf, sizeof(buf), GSA_FULL)), evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); close(sock); return FALSE; } g_process_cap_restore(saved_caps); *fd = sock; return TRUE; } else { msg_error("Error creating socket", evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); return FALSE; } }
static void afstreams_init_door(int hook_type G_GNUC_UNUSED, gpointer user_data) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) user_data; struct stat st; gint fd; if (stat(self->door_filename->str, &st) == -1) { /* file does not exist, create it */ fd = creat(self->door_filename->str, 0666); if (fd == -1) { msg_error("Error creating syslog door file", evt_tag_str(EVT_TAG_FILENAME, self->door_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); close(fd); return; } } fdetach(self->door_filename->str); self->door_fd = door_create(afstreams_sd_door_server_proc, NULL, 0); if (self->door_fd == -1) { msg_error("Error creating syslog door", evt_tag_str(EVT_TAG_FILENAME, self->door_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); return; } g_fd_set_cloexec(self->door_fd, TRUE); if (fattach(self->door_fd, self->door_filename->str) == -1) { msg_error("Error attaching syslog door", evt_tag_str(EVT_TAG_FILENAME, self->door_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno), NULL); close(self->door_fd); self->door_fd = -1; return; } }
static gboolean afstreams_sd_init(LogPipe *s) { AFStreamsSourceDriver *self = (AFStreamsSourceDriver *) s; GlobalConfig *cfg = log_pipe_get_config(s); gint fd; if (!log_src_driver_init_method(s)) return FALSE; log_reader_options_init(&self->reader_options, cfg, self->super.super.group); fd = open(self->dev_filename->str, O_RDONLY | O_NOCTTY | O_NONBLOCK); if (fd != -1) { struct strioctl ioc; g_fd_set_cloexec(fd, TRUE); memset(&ioc, 0, sizeof(ioc)); ioc.ic_cmd = I_CONSLOG; if (ioctl(fd, I_STR, &ioc) < 0) { msg_error("Error in ioctl(I_STR, I_CONSLOG)", evt_tag_str(EVT_TAG_FILENAME, self->dev_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); close(fd); return FALSE; } g_fd_set_nonblock(fd, TRUE); self->reader = log_reader_new(cfg); log_reader_reopen(self->reader, log_proto_dgram_server_new(log_transport_streams_new(fd), &self->reader_options.proto_options.super), poll_fd_events_new(fd)); log_reader_set_options(self->reader, s, &self->reader_options, STATS_LEVEL1, SCS_SUN_STREAMS, self->super.super.id, self->dev_filename->str); log_pipe_append((LogPipe *) self->reader, s); if (self->door_filename) { /* door creation is deferred, because it creates threads which is * not inherited through forks, and syslog-ng forks during * startup, but _after_ the configuration was initialized */ register_application_hook(AH_POST_DAEMONIZED, afstreams_init_door, self); } if (!log_pipe_init((LogPipe *) self->reader)) { msg_error("Error initializing log_reader, closing fd", evt_tag_int("fd", fd)); log_pipe_unref((LogPipe *) self->reader); self->reader = NULL; close(fd); return FALSE; } } else { msg_error("Error opening syslog device", evt_tag_str(EVT_TAG_FILENAME, self->dev_filename->str), evt_tag_errno(EVT_TAG_OSERROR, errno)); return FALSE; } return TRUE; }
static gboolean affile_open_file(gchar *name, int flags, int uid, int gid, int mode, int dir_uid, int dir_gid, int dir_mode, int create_dirs, int *fd, int switch_enable) { int sw_fd; if (strstr(name, "../") || strstr(name, "/..")) { msg_error("Spurious path, logfile not created", evt_tag_str("path", name), NULL); return FALSE; } if (switch_enable == 0){ *fd = open(name, flags, mode); } else{ affile_open_switch_file(name, flags, mode, &sw_fd, fd); } if (create_dirs && *fd == -1 && errno == ENOENT) /*如果指定目录不存在则创建*/ { /* directory does not exist */ char *p = name + 1; p = strchr(p, '/'); while (p) { struct stat st; *p = 0; if (stat(name, &st) == 0) { if (!S_ISDIR(st.st_mode)) return FALSE; } else if (errno == ENOENT) { if (mkdir(name, dir_mode) == -1) return 0; if (dir_uid != -1 || dir_gid != -1) chown(name, dir_uid, dir_gid); if (dir_mode != -1) chmod(name, dir_mode); } *p = '/'; p = strchr(p + 1, '/'); } if (switch_enable == 0){ *fd = open(name, flags, mode); } else{ affile_open_switch_file(name, flags, mode, &sw_fd, fd); } } if (*fd != -1) { g_fd_set_cloexec(*fd, TRUE); if (uid != -1) fchown(*fd, uid, -1); if (gid != -1) fchown(*fd, -1, gid); if (mode != -1) fchmod(*fd, mode); } if(switch_enable != 0){ g_fd_set_cloexec(sw_fd, TRUE); if (uid != -1) fchown(sw_fd, uid, -1); if (gid != -1) fchown(sw_fd, -1, gid); if (mode != -1) fchmod(sw_fd, mode); close(sw_fd); } return *fd != -1; }
static gboolean affile_open_file(gchar *name, gint flags, gint uid, gint gid, gint mode, gint dir_uid, gint dir_gid, gint dir_mode, gboolean create_dirs, gboolean privileged, gboolean is_pipe, gint *fd) { cap_t saved_caps; struct stat st; if (strstr(name, "../") || strstr(name, "/..")) { msg_error("Spurious path, logfile not created", evt_tag_str("path", name), NULL); return FALSE; } if (create_dirs && !create_containing_directory(name, dir_uid, dir_gid, dir_mode)) return FALSE; saved_caps = g_process_cap_save(); if (privileged) { g_process_cap_modify(CAP_DAC_READ_SEARCH, TRUE); g_process_cap_modify(CAP_SYS_ADMIN, TRUE); } *fd = -1; if (stat(name, &st) >= 0) { if (is_pipe && !S_ISFIFO(st.st_mode)) { msg_warning("WARNING: you are using the pipe driver, underlying file is not a FIFO, it should be used by file()", evt_tag_str("filename", name), NULL); } else if (!is_pipe && S_ISFIFO(st.st_mode)) { msg_warning("WARNING: you are using the file driver, underlying file is a FIFO, it should be used by pipe()", evt_tag_str("filename", name), NULL); } } *fd = open(name, flags, mode); if (is_pipe && *fd < 0 && errno == ENOENT) { if (mkfifo(name, 0666) >= 0) *fd = open(name, flags, 0666); } if (*fd != -1) { g_fd_set_cloexec(*fd, TRUE); g_process_cap_modify(CAP_CHOWN, TRUE); g_process_cap_modify(CAP_FOWNER, TRUE); if (uid >= 0) fchown(*fd, (uid_t) uid, -1); if (gid >= 0) fchown(*fd, -1, (gid_t) gid); if (mode >= 0) fchmod(*fd, (mode_t) mode); } g_process_cap_restore(saved_caps); msg_trace("affile_open_file", evt_tag_str("path", name), evt_tag_int("fd",*fd), NULL); return *fd != -1; }
static gboolean afunix_sd_acquire_named_socket(AFSocketSourceDriver *s, gint *result_fd, const gchar *filename) { AFUnixSourceDriver *self = (AFUnixSourceDriver *) s; gint fd, fds; *result_fd = -1; fd = -1; fds = sd_listen_fds(0); if (fds == 0) return TRUE; msg_debug("Systemd socket activation", evt_tag_int("systemd-sockets", fds), evt_tag_str("systemd-listen-pid", getenv("LISTEN_PID")), evt_tag_str("systemd-listen-fds", getenv("LISTEN_FDS")), NULL); if (fds < 0) { msg_error("Failed to acquire systemd sockets, incorrectly set LISTEN_FDS environment variable?", NULL); return FALSE; } else if (fds > 0) { for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; fd++) { /* check if any type is available */ if (sd_is_socket_unix(fd, 0, -1, filename, 0)) { /* check if it matches our idea of the socket type */ if (sd_is_socket_unix(fd, self->super.transport_mapper->sock_type, -1, filename, 0)) { *result_fd = fd; break; } else { msg_error("The systemd supplied UNIX domain socket is of a different type, check the configured driver and the matching systemd unit file", evt_tag_str("filename", filename), evt_tag_int("systemd-sock-fd", fd), evt_tag_str("expecting", self->super.transport_mapper->sock_type == SOCK_STREAM ? "unix-stream()" : "unix-dgram()"), NULL); return FALSE; } } else { /* systemd passed an fd we didn't really care about. This is * not an error, but might be worth mentioning it at the debug * level. */ msg_debug("Ignoring systemd supplied fd as it is not a UNIX domain socket", evt_tag_str("filename", filename), evt_tag_int("systemd-sock-fd", fd), NULL); } } } if (*result_fd != -1) { g_fd_set_nonblock(*result_fd, TRUE); g_fd_set_cloexec(*result_fd, TRUE); msg_verbose("Acquired systemd socket", evt_tag_str("filename", filename), evt_tag_int("systemd-sock-fd", *result_fd), NULL); return TRUE; } return TRUE; }