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 "agentd.h"
12 #include "os_net/os_net.h"
13 
14 #ifndef WIN32
15 #include "os_dns/os_dns.h"
16 #endif //WIN32
17 
18 struct imsgbuf server_ibuf;
19 
20 /* Start the agent daemon */
AgentdStart(const char * dir,int uid,int gid,const char * user,const char * group)21 void AgentdStart(const char *dir, int uid, int gid, const char *user, const char *group)
22 {
23     int rc = 0;
24     int maxfd = 0;
25     fd_set fdset;
26     struct timeval fdtimeout;
27 
28     available_server = 0;
29 
30     /* Initial random numbers must happen before chroot */
31     srandom_init();
32 
33     merror("going daemon");
34     /* Going Daemon */
35     if (!run_foreground) {
36         nowDaemon();
37         goDaemon();
38     }
39 
40 #ifndef WIN32
41     merror("starting imsg stuff");
42     /* Prepare for os_dns */
43     struct imsgbuf osdns_ibuf;
44     //struct imsgbuf osdns_ibuf;
45     int imsg_fds[2];
46     merror("Creating socketpair()");
47     if ((socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, imsg_fds)) == -1) {
48         ErrorExit("%s: ERROR: Could not create socket pair.", ARGV0);
49     }
50     if (setnonblock(imsg_fds[0]) < 0) {
51         ErrorExit("%s: ERROR: Could not set imsg_fds[0] to nonblock", ARGV0);
52     }
53     if (setnonblock(imsg_fds[1]) < 0) {
54         ErrorExit("%s: ERROR: Could not set imsg_fds[1] to nonblock", ARGV0);
55     }
56 
57     /* Fork os_dns process */
58     switch(fork()) {
59         case -1:
60             ErrorExit("%s: ERROR: Cannot fork() os_dns process", ARGV0);
61         case 0:
62             close(imsg_fds[0]);
63 	    merror("os_dns imsg_init()");
64             imsg_init(&osdns_ibuf, imsg_fds[1]);
65             exit(osdns(&osdns_ibuf, ARGV0));
66     }
67 
68     /* Setup imsg for the rest of agentd */
69     close(imsg_fds[1]);
70     //imsg_init(&agt->ibuf, imsg_fds[1]);
71     merror("agentd imsg_init()");
72     imsg_init(&server_ibuf, imsg_fds[0]);
73 
74 #endif  //WIN32
75 
76     /* Set group ID */
77     if (Privsep_SetGroup(gid) < 0) {
78         ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
79     }
80 
81     /* chroot */
82     if (Privsep_Chroot(dir) < 0) {
83         ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
84     }
85     nowChroot();
86 
87     if (Privsep_SetUser(uid) < 0) {
88         ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
89     }
90 
91     /* Create the queue and read from it. Exit if fails. */
92     if ((agt->m_queue = StartMQ(DEFAULTQUEUE, READ)) < 0) {
93         ErrorExit(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno));
94     }
95 
96     maxfd = agt->m_queue;
97     agt->sock = -1;
98 
99     /* Create PID file */
100     if (CreatePID(ARGV0, getpid()) < 0) {
101         merror(PID_ERROR, ARGV0);
102     }
103 
104     /* Read private keys  */
105     verbose(ENC_READ, ARGV0);
106 
107     OS_ReadKeys(&keys);
108     OS_StartCounter(&keys);
109 
110     os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id,
111                         agt->profile);
112 
113     /* Start up message */
114     verbose(STARTUP_MSG, ARGV0, (int)getpid());
115 
116     random();
117 
118     /* Connect UDP */
119     rc = 0;
120     while (rc < agt->rip_id) {
121         verbose("%s: INFO: Server %d: %s", ARGV0, rc+1, agt->rip[rc]);
122         rc++;
123     }
124 
125     /* Try to connect to the server */
126     if (!connect_server(0)) {
127         ErrorExit(UNABLE_CONN, ARGV0);
128     }
129 
130     /* Set max fd for select */
131     if (agt->sock > maxfd) {
132         maxfd = agt->sock;
133     }
134 
135     /* Connect to the execd queue */
136     if (agt->execdq == 0) {
137         if ((agt->execdq = StartMQ(EXECQUEUE, WRITE)) < 0) {
138             merror("%s: INFO: Unable to connect to the active response "
139                    "queue (disabled).", ARGV0);
140             agt->execdq = -1;
141         }
142     }
143 
144     /* Try to connect to server */
145     os_setwait();
146 
147     start_agent(1);
148 
149     os_delwait();
150 
151     /* Send integrity message for agent configs */
152     intcheck_file(OSSECCONF, dir);
153     intcheck_file(OSSEC_DEFINES, dir);
154 
155     /* Send first notification */
156 #ifdef WIN32
157     run_notify();
158 #else
159     run_notify();
160 #endif //WIN32
161 
162     /* Maxfd must be higher socket +1 */
163     maxfd++;
164 
165     /* Monitor loop */
166     while (1) {
167         /* Monitor all available sockets from here */
168         FD_ZERO(&fdset);
169         FD_SET(agt->sock, &fdset);
170         FD_SET(agt->m_queue, &fdset);
171 
172         fdtimeout.tv_sec = 1;
173         fdtimeout.tv_usec = 0;
174 
175         /* Continuously send notifications */
176 #ifdef WIN32
177         run_notify();
178 #else
179         run_notify();
180 #endif //WIN32
181 
182         /* Wait with a timeout for any descriptor */
183         rc = select(maxfd, &fdset, NULL, NULL, &fdtimeout);
184         if (rc == -1) {
185             ErrorExit(SELECT_ERROR, ARGV0, errno, strerror(errno));
186         } else if (rc == 0) {
187             continue;
188         }
189 
190         /* For the receiver */
191         if (FD_ISSET(agt->sock, &fdset)) {
192             receive_msg();
193         }
194 
195         /* For the forwarder */
196         if (FD_ISSET(agt->m_queue, &fdset)) {
197 #ifdef WIN32
198             EventForward();
199 #else
200             EventForward();
201 #endif
202         }
203     }
204 }
205 
206