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 "agentlessd.h"
12 #include "config/config.h"
13 
14 /* Prototypes */
15 static void help_agentlessd(void) __attribute__((noreturn));
16 
17 
18 /* Print help statement */
help_agentlessd()19 static void help_agentlessd()
20 {
21     print_header();
22     print_out("  %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
23     print_out("    -V          Version and license message");
24     print_out("    -h          This help message");
25     print_out("    -d          Execute in debug mode. This parameter");
26     print_out("                can be specified multiple times");
27     print_out("                to increase the debug level.");
28     print_out("    -t          Test configuration");
29     print_out("    -f          Run in foreground");
30     print_out("    -u <user>   User to run as (default: %s)", USER);
31     print_out("    -g <group>  Group to run as (default: %s)", GROUPGLOBAL);
32     print_out("    -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
33     print_out("    -D <dir>    Directory to chroot into (default: %s)", DEFAULTDIR);
34     print_out(" ");
35     exit(1);
36 }
37 
main(int argc,char ** argv)38 int main(int argc, char **argv)
39 {
40     int c, test_config = 0, run_foreground = 0;
41     uid_t uid;
42     gid_t gid;
43     const char *dir  = DEFAULTDIR;
44     const char *user = USER;
45     const char *group = GROUPGLOBAL;
46     const char *cfg = DEFAULTCPATH;
47 
48     /* Set the name */
49     OS_SetName(ARGV0);
50 
51     while ((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1) {
52         switch (c) {
53             case 'V':
54                 print_version();
55                 break;
56             case 'h':
57                 help_agentlessd();
58                 break;
59             case 'd':
60                 nowDebug();
61                 break;
62             case 'f':
63                 run_foreground = 1;
64                 break;
65             case 'u':
66                 if (!optarg) {
67                     ErrorExit("%s: -u needs an argument", ARGV0);
68                 }
69                 user = optarg;
70                 break;
71             case 'g':
72                 if (!optarg) {
73                     ErrorExit("%s: -g needs an argument", ARGV0);
74                 }
75                 group = optarg;
76                 break;
77             case 'D':
78                 if (!optarg) {
79                     ErrorExit("%s: -D needs an argument", ARGV0);
80                 }
81                 dir = optarg;
82                 break;
83             case 'c':
84                 if (!optarg) {
85                     ErrorExit("%s: -c needs an argument", ARGV0);
86                 }
87                 cfg = optarg;
88                 break;
89             case 't':
90                 test_config = 1;
91                 break;
92             default:
93                 help_agentlessd();
94                 break;
95         }
96     }
97 
98     /* Start daemon */
99     debug1(STARTED_MSG, ARGV0);
100 
101     /* Check if the user/group given are valid */
102     uid = Privsep_GetUser(user);
103     gid = Privsep_GetGroup(group);
104     if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
105         ErrorExit(USER_ERROR, ARGV0, user, group);
106     }
107 
108     /* Read config */
109     c = 0;
110     c |= CAGENTLESS;
111     lessdc.entries = NULL;
112     lessdc.queue = 0;
113 
114     if (ReadConfig(c, cfg, &lessdc, NULL) < 0) {
115         ErrorExit(XML_INV_AGENTLESS, ARGV0);
116     }
117 
118     /* Exit here if test config is set */
119     if (test_config) {
120         exit(0);
121     }
122 
123     /* Continue in daemon mode */
124     if (!run_foreground) {
125         nowDaemon();
126         goDaemonLight();
127     }
128 
129     if (chdir(dir) == -1) {
130         ErrorExit(CHDIR_ERROR, ARGV0, dir, errno, strerror(errno));
131     }
132 
133     /* Exit if not configured */
134     if (!lessdc.entries) {
135         verbose("%s: INFO: Not configured. Exiting.", ARGV0);
136         exit(0);
137     }
138 
139     /* Privilege separation */
140     if (Privsep_SetGroup(gid) < 0) {
141         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
142     }
143 
144     /* Change user */
145     if (Privsep_SetUser(uid) < 0) {
146         ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
147     }
148 
149     debug1(CHROOT_MSG, ARGV0, dir);
150     debug1(PRIVSEP_MSG, ARGV0, user);
151 
152     /* Signal manipulation */
153     StartSIG(ARGV0);
154 
155     /* Create PID files */
156     if (CreatePID(ARGV0, getpid()) < 0) {
157         ErrorExit(PID_ERROR, ARGV0);
158     }
159 
160     /* Start up message */
161     verbose(STARTUP_MSG, ARGV0, (int)getpid());
162 
163     /* The real daemon now */
164     Agentlessd();
165 }
166 
167