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