new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_dbd / 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 "shared.h"
11 #include "dbd.h"
12
13 #ifndef ARGV0
14 #define ARGV0 "ossec-dbd"
15 #endif
16
17 /* Prototypes */
18 static void print_db_info(void);
19 static void help_dbd(void) __attribute__((noreturn));
20
21
22 /* Print information regarding enabled databases */
23 static void print_db_info()
24 {
25 #ifdef MYSQL_DATABASE_ENABLED
26     print_out("    Compiled with MySQL support");
27 #endif
28
29 #ifdef PGSQL_DATABASE_ENABLED
30     print_out("    Compiled with PostgreSQL support");
31 #endif
32
33 #if !defined(MYSQL_DATABASE_ENABLED) && !defined(PGSQL_DATABASE_ENABLED)
34     print_out("    Compiled without any database support");
35 #endif
36 }
37
38 /* Print help statement */
39 static void help_dbd()
40 {
41     print_header();
42     print_out("  %s: -[Vhdtfv] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
43     print_out("    -V          Version and license message");
44     print_out("    -h          This help message");
45     print_out("    -d          Execute in debug mode. This parameter");
46     print_out("                can be specified multiple times");
47     print_out("                to increase the debug level.");
48     print_out("    -t          Test configuration");
49     print_out("    -f          Run in foreground");
50     print_out("    -u <user>   User to run as (default: %s)", MAILUSER);
51     print_out("    -g <group>  Group to run as (default: %s)", GROUPGLOBAL);
52     print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
53     print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
54     print_out(" ");
55     print_out("  Database Support:");
56     print_db_info();
57     print_out(" ");
58     exit(1);
59 }
60
61 int main(int argc, char **argv)
62 {
63     int c, test_config = 0, run_foreground = 0;
64     uid_t uid;
65     gid_t gid;
66     unsigned int d;
67
68     /* Use MAILUSER (read only) */
69     const char *dir  = DEFAULTDIR;
70     const char *user = MAILUSER;
71     const char *group = GROUPGLOBAL;
72     const char *cfg = DEFAULTCPATH;
73
74     /* Database Structure */
75     DBConfig db_config;
76     db_config.error_count = 0;
77
78     /* Set the name */
79     OS_SetName(ARGV0);
80
81     while ((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1) {
82         switch (c) {
83             case 'V':
84                 print_version();
85                 break;
86             case 'h':
87                 help_dbd();
88                 break;
89             case 'd':
90                 nowDebug();
91                 break;
92             case 'f':
93                 run_foreground = 1;
94                 break;
95             case 'u':
96                 if (!optarg) {
97                     ErrorExit("%s: -u needs an argument", ARGV0);
98                 }
99                 user = optarg;
100                 break;
101             case 'g':
102                 if (!optarg) {
103                     ErrorExit("%s: -g needs an argument", ARGV0);
104                 }
105                 group = optarg;
106                 break;
107             case 'D':
108                 if (!optarg) {
109                     ErrorExit("%s: -D needs an argument", ARGV0);
110                 }
111                 dir = optarg;
112                 break;
113             case 'c':
114                 if (!optarg) {
115                     ErrorExit("%s: -c needs an argument", ARGV0);
116                 }
117                 cfg = optarg;
118                 break;
119             case 't':
120                 test_config = 1;
121                 break;
122             default:
123                 help_dbd();
124                 break;
125         }
126     }
127
128     /* Start daemon */
129     debug1(STARTED_MSG, ARGV0);
130
131     /* Check if the user/group given are valid */
132     uid = Privsep_GetUser(user);
133     gid = Privsep_GetGroup(group);
134     if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
135         ErrorExit(USER_ERROR, ARGV0, user, group);
136     }
137
138     /* Read configuration */
139     if ((c = OS_ReadDBConf(test_config, cfg, &db_config)) < 0) {
140         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
141     }
142
143     /* Exit here if test config is set */
144     if (test_config) {
145         exit(0);
146     }
147
148     if (!run_foreground) {
149         /* Going on daemon mode */
150         nowDaemon();
151         goDaemon();
152     }
153
154     /* Not configured */
155     if (c == 0) {
156         verbose("%s: Database not configured. Clean exit.", ARGV0);
157         exit(0);
158     }
159
160     /* Maybe disable this debug? */
161     debug1("%s: DEBUG: Connecting to '%s', using '%s', '%s', '%s', %d,'%s'.",
162            ARGV0,
163            db_config.host != NULL ? db_config.host : "NoHost",
164            db_config.user != NULL ? db_config.user : "NoUser",
165            db_config.pass != NULL ? db_config.pass : "NoPass",
166            db_config.db != NULL ? db_config.db : "NoDB",
167            db_config.port,
168            db_config.sock != NULL ? db_config.sock : "NoSock");
169
170     /* Set config pointer */
171     osdb_setconfig(&db_config);
172
173     /* Get maximum reconnect attempts */
174     db_config.maxreconnect = (unsigned int) getDefine_Int("dbd",
175                              "reconnect_attempts", 1, 9999);
176
177     /* Connect to the database */
178     d = 0;
179     while (d <= (db_config.maxreconnect * 10)) {
180         db_config.conn = osdb_connect(db_config.host, db_config.user,
181                                       db_config.pass, db_config.db,
182                                       db_config.port, db_config.sock);
183
184         /* If we are able to reconnect, keep going */
185         if (db_config.conn) {
186             break;
187         }
188
189         d++;
190         sleep(d * 60);
191
192     }
193
194     /* If after the maxreconnect attempts, it still didn't work, exit here */
195     if (!db_config.conn) {
196         merror(DB_CONFIGERR, ARGV0);
197         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
198     }
199
200     /* We must notify that we connected -- easy debugging */
201     verbose("%s: Connected to database '%s' at '%s'.",
202             ARGV0, db_config.db, db_config.host);
203
204     /* Privilege separation */
205     if (Privsep_SetGroup(gid) < 0) {
206         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
207     }
208
209     /* chroot */
210     if (Privsep_Chroot(dir) < 0) {
211         ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
212     }
213
214     /* Now in chroot */
215     nowChroot();
216
217     /* Insert server info into the db */
218     db_config.server_id = OS_Server_ReadInsertDB(&db_config);
219     if (db_config.server_id <= 0) {
220         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
221     }
222
223     /* Read rules and insert into the db */
224     if (OS_InsertRulesDB(&db_config) < 0) {
225         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
226     }
227
228     /* Change user */
229     if (Privsep_SetUser(uid) < 0) {
230         ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
231     }
232
233     /* Basic start up completed */
234     debug1(CHROOT_MSG, ARGV0, dir);
235     debug1(PRIVSEP_MSG, ARGV0, user);
236
237     /* Signal manipulation */
238     StartSIG(ARGV0);
239
240     /* Create PID files */
241     if (CreatePID(ARGV0, getpid()) < 0) {
242         ErrorExit(PID_ERROR, ARGV0);
243     }
244
245     /* Start up message */
246     verbose(STARTUP_MSG, ARGV0, (int)getpid());
247
248     /* The real daemon now */
249     OS_DBD(&db_config);
250 }
251