new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / remoted / main.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All right 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 "remoted.h"
12
13 /* Prototypes */
14 static void help_remoted(void) __attribute__((noreturn));
15
16
17 /* Print help statement */
18 static void help_remoted()
19 {
20     print_header();
21     print_out("  %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
22     print_out("    -V          Version and license message");
23     print_out("    -h          This help message");
24     print_out("    -d          Execute in debug mode. This parameter");
25     print_out("                can be specified multiple times");
26     print_out("                to increase the debug level.");
27     print_out("    -t          Test configuration");
28     print_out("    -f          Run in foreground");
29     print_out("    -u <user>   User to run as (default: %s)", REMUSER);
30     print_out("    -g <group>  Group to run as (default: %s)", GROUPGLOBAL);
31     print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
32     print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
33     print_out(" ");
34     exit(1);
35 }
36
37 int main(int argc, char **argv)
38 {
39     int i = 0, c = 0;
40     uid_t uid;
41     gid_t gid;
42     int debug_level = 0;
43     int test_config = 0, run_foreground = 0;
44
45     const char *cfg = DEFAULTCPATH;
46     const char *dir = DEFAULTDIR;
47     const char *user = REMUSER;
48     const char *group = GROUPGLOBAL;
49
50     /* Set the name */
51     OS_SetName(ARGV0);
52
53     while ((c = getopt(argc, argv, "Vdthfu:g:c:D:")) != -1) {
54         switch (c) {
55             case 'V':
56                 print_version();
57                 break;
58             case 'h':
59                 help_remoted();
60                 break;
61             case 'd':
62                 nowDebug();
63                 debug_level = 1;
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 't':
81                 test_config = 1;
82                 break;
83             case 'c':
84                 if (!optarg) {
85                     ErrorExit("%s: -c need an argument", ARGV0);
86                 }
87                 cfg = optarg;
88                 break;
89             case 'D':
90                 if (!optarg) {
91                     ErrorExit("%s: -D needs an argument", ARGV0);
92                 }
93                 dir = optarg;
94                 break;
95             default:
96                 help_remoted();
97                 break;
98         }
99     }
100
101     /* Check current debug_level
102      * Command line setting takes precedence
103      */
104     if (debug_level == 0) {
105         /* Get debug level */
106         debug_level = getDefine_Int("remoted", "debug", 0, 2);
107         while (debug_level != 0) {
108             nowDebug();
109             debug_level--;
110         }
111     }
112
113     debug1(STARTED_MSG, ARGV0);
114
115     /* Return 0 if not configured */
116     if (RemotedConfig(cfg, &logr) < 0) {
117         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
118     }
119
120     /* Exit if test_config is set */
121     if (test_config) {
122         exit(0);
123     }
124
125     if (logr.conn == NULL) {
126         /* Not configured */
127         exit(0);
128     }
129
130     /* Don't exit when client.keys empty (if set) */
131     if (getDefine_Int("remoted", "pass_empty_keyfile", 0, 1)) {
132         OS_PassEmptyKeyfile();
133     }
134
135
136     /* Check if the user and group given are valid */
137     uid = Privsep_GetUser(user);
138     gid = Privsep_GetGroup(group);
139     if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
140         ErrorExit(USER_ERROR, ARGV0, user, group);
141     }
142
143     /* Setup random */
144     srandom_init();
145
146     /* pid before going daemon */
147     i = getpid();
148
149     if (!run_foreground) {
150         nowDaemon();
151         goDaemon();
152     }
153
154     /* Set new group */
155     if (Privsep_SetGroup(gid) < 0) {
156         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
157     }
158
159     /* chroot */
160     if (Privsep_Chroot(dir) < 0) {
161         ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
162     }
163     nowChroot();
164
165     /* Start the signal manipulation */
166     StartSIG(ARGV0);
167
168     random();
169
170     /* Start up message */
171     verbose(STARTUP_MSG, ARGV0, (int)getpid());
172
173     /* Really start the program */
174     i = 0;
175     while (logr.conn[i] != 0) {
176         /* Fork for each connection handler */
177         if (fork() == 0) {
178             /* On the child */
179             debug1("%s: DEBUG: Forking remoted: '%d'.", ARGV0, i);
180             HandleRemote(i, uid);
181         } else {
182             i++;
183             continue;
184         }
185     }
186
187     return (0);
188 }
189