new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_csyslogd / main.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All rights reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation.
8  */
9
10 #include "csyslogd.h"
11
12 /* Prototypes */
13 static void help_csyslogd(void) __attribute__((noreturn));
14
15
16 /* Print help statement */
17 static void help_csyslogd()
18 {
19     print_header();
20     print_out("  %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
21     print_out("    -V          Version and license message");
22     print_out("    -h          This help message");
23     print_out("    -d          Execute in debug mode. This parameter");
24     print_out("                can be specified multiple times");
25     print_out("                to increase the debug level.");
26     print_out("    -t          Test configuration");
27     print_out("    -f          Run in foreground");
28     print_out("    -u <user>   User to run as (default: %s)", MAILUSER);
29     print_out("    -g <group>  Group to run as (default: %s)", GROUPGLOBAL);
30     print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
31     print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
32     print_out(" ");
33     exit(1);
34 }
35
36 int main(int argc, char **argv)
37 {
38     int c, test_config = 0, run_foreground = 0;
39     uid_t uid;
40     gid_t gid;
41
42     /* Use MAILUSER (read only) */
43     const char *dir  = DEFAULTDIR;
44     const char *user = MAILUSER;
45     const char *group = GROUPGLOBAL;
46     const char *cfg = DEFAULTCPATH;
47
48     /* Database Structure */
49     SyslogConfig **syslog_config;
50
51     /* Set the name */
52     OS_SetName(ARGV0);
53
54     while ((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1) {
55         switch (c) {
56             case 'V':
57                 print_version();
58                 break;
59             case 'h':
60                 help_csyslogd();
61                 break;
62             case 'd':
63                 nowDebug();
64                 break;
65             case 'f':
66                 run_foreground = 1;
67                 break;
68             case 'u':
69                 if (!optarg) {
70                     ErrorExit("%s: -u needs an argument", ARGV0);
71                 }
72                 user = optarg;
73                 break;
74             case 'g':
75                 if (!optarg) {
76                     ErrorExit("%s: -g needs an argument", ARGV0);
77                 }
78                 group = optarg;
79                 break;
80             case 'D':
81                 if (!optarg) {
82                     ErrorExit("%s: -D needs an argument", ARGV0);
83                 }
84                 dir = optarg;
85                 break;
86             case 'c':
87                 if (!optarg) {
88                     ErrorExit("%s: -c needs an argument", ARGV0);
89                 }
90                 cfg = optarg;
91                 break;
92             case 't':
93                 test_config = 1;
94                 break;
95             default:
96                 help_csyslogd();
97                 break;
98         }
99     }
100
101     /* Start daemon */
102     debug1(STARTED_MSG, ARGV0);
103
104     /* Check if the user/group given are valid */
105     uid = Privsep_GetUser(user);
106     gid = Privsep_GetGroup(group);
107     if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
108         ErrorExit(USER_ERROR, ARGV0, user, group);
109     }
110
111     /* Read configuration */
112     syslog_config = OS_ReadSyslogConf(test_config, cfg);
113
114     /* Get server hostname */
115     memset(__shost, '\0', 512);
116     if (gethostname(__shost, 512 - 1) != 0) {
117         ErrorExit("%s: ERROR: gethostname() failed", ARGV0);
118     } else {
119         /* Save the full hostname */
120         memcpy(__shost_long, __shost, 512);
121
122         char *ltmp;
123
124         /* Remove domain part if available */
125         ltmp = strchr(__shost, '.');
126         if (ltmp) {
127             *ltmp = '\0';
128         }
129     }
130
131     /* Exit here if test config is set */
132     if (test_config) {
133         exit(0);
134     }
135
136     if (!run_foreground) {
137         /* Going on daemon mode */
138         nowDaemon();
139         goDaemon();
140     }
141
142     /* Not configured */
143     if (!syslog_config || !syslog_config[0]) {
144         verbose("%s: INFO: Remote syslog server not configured. "
145                 "Clean exit.", ARGV0);
146         exit(0);
147     }
148
149     /* Privilege separation */
150     if (Privsep_SetGroup(gid) < 0) {
151         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
152     }
153
154     /* chroot */
155     if (Privsep_Chroot(dir) < 0) {
156         ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
157     }
158
159     /* Now in chroot */
160     nowChroot();
161
162     /* Change user */
163     if (Privsep_SetUser(uid) < 0) {
164         ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
165     }
166
167     /* Basic start up completed */
168     debug1(CHROOT_MSG, ARGV0, dir);
169     debug1(PRIVSEP_MSG, ARGV0, user);
170
171     /* Signal manipulation */
172     StartSIG(ARGV0);
173
174     /* Create PID files */
175     if (CreatePID(ARGV0, getpid()) < 0) {
176         ErrorExit(PID_ERROR, ARGV0);
177     }
178
179     /* Start up message */
180     verbose(STARTUP_MSG, ARGV0, (int)getpid());
181
182     /* The real daemon now */
183     OS_CSyslogD(syslog_config);
184 }
185