1 /*
2  * Copyright (C) Tildeslash Ltd. All rights reserved.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Affero General Public License version 3.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU Affero General Public License
13  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
14  *
15  * In addition, as a special exception, the copyright holders give
16  * permission to link the code of portions of this program with the
17  * OpenSSL library under certain conditions as described in each
18  * individual source file, and distribute linked combinations
19  * including the two.
20  *
21  * You must obey the GNU Affero General Public License in all respects
22  * for all of the code used other than OpenSSL.
23  */
24 
25 #include "config.h"
26 
27 #ifdef HAVE_STDIO_H
28 #include <stdio.h>
29 #endif
30 
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 
35 #ifdef HAVE_ERRNO_H
36 #include <errno.h>
37 #endif
38 
39 #ifdef HAVE_STRING_H
40 #include <string.h>
41 #endif
42 
43 #ifdef HAVE_STRINGS_H
44 #include <strings.h>
45 #endif
46 
47 #ifdef HAVE_SYS_TYPES_H
48 #include <sys/types.h>
49 #endif
50 
51 #ifdef HAVE_SYS_STAT_H
52 #include <sys/stat.h>
53 #endif
54 
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58 
59 #ifdef HAVE_FCNTL_H
60 #include <fcntl.h>
61 #endif
62 
63 #ifdef HAVE_DIRENT_H
64 #include <dirent.h>
65 #endif
66 
67 #include "monit.h"
68 #include "engine.h"
69 
70 // libmonit
71 #include "io/File.h"
72 
73 /**
74  *  Utilities for managing files used by monit.
75  *
76  *  @file
77  */
78 
79 
80 /* ------------------------------------------------------------------ Public */
81 
82 
file_init()83 void file_init() {
84         char pidfile[STRLEN];
85         char buf[STRLEN];
86         /* Check if the pidfile was already set during configfile parsing */
87         if (Run.files.pid == NULL) {
88                 /* Set the location of this programs pidfile */
89                 if (! getuid()) {
90                         snprintf(pidfile, STRLEN, "%s/%s", MYPIDDIR, MYPIDFILE);
91                 } else {
92                         snprintf(pidfile, STRLEN, "%s/.%s", Run.Env.home, MYPIDFILE);
93                 }
94                 Run.files.pid = Str_dup(pidfile);
95         }
96         /* Set the location of monit's id file */
97         if (Run.files.id == NULL) {
98                 snprintf(buf, STRLEN, "%s/.%s", Run.Env.home, MYIDFILE);
99                 Run.files.id = Str_dup(buf);
100         }
101         Util_monitId(Run.files.id);
102         /* Set the location of monit's state file */
103         if (Run.files.state == NULL) {
104                 snprintf(buf, STRLEN, "%s/.%s", Run.Env.home, MYSTATEFILE);
105                 Run.files.state = Str_dup(buf);
106         }
107 }
108 
109 
file_finalize()110 void file_finalize() {
111         Engine_cleanup();
112         unlink(Run.files.pid);
113 }
114 
115 
file_findControlFile()116 char *file_findControlFile() {
117         char *rcfile = CALLOC(sizeof(char), STRLEN + 1);
118         snprintf(rcfile, STRLEN, "%s/.%s", Run.Env.home, MONITRC);
119         if (File_exist(rcfile)) {
120                 return rcfile;
121         }
122         snprintf(rcfile, STRLEN, "/etc/%s", MONITRC);
123         if (File_exist(rcfile)) {
124                 return rcfile;
125         }
126         snprintf(rcfile, STRLEN, "%s/%s", SYSCONFDIR, MONITRC);
127         if (File_exist(rcfile)) {
128                 return rcfile;
129         }
130         snprintf(rcfile, STRLEN, "/usr/local/etc/%s", MONITRC);
131         if (File_exist(rcfile)) {
132                 return rcfile;
133         }
134         if (File_exist(MONITRC)) {
135                 snprintf(rcfile, STRLEN, "%s/%s", Run.Env.cwd, MONITRC);
136                 return rcfile;
137         }
138         Log_error("Cannot find the Monit control file at ~/.%s, /etc/%s, %s/%s, /usr/local/etc/%s or at ./%s \n", MONITRC, MONITRC, SYSCONFDIR, MONITRC, MONITRC, MONITRC);
139         exit(1);
140 }
141 
142 
file_createPidFile(const char * pidfile)143 bool file_createPidFile(const char *pidfile) {
144         ASSERT(pidfile);
145         unlink(pidfile);
146         FILE *F = fopen(pidfile, "w");
147         if (! F) {
148                 Log_error("Error opening pidfile '%s' for writing -- %s\n", pidfile, STRERROR);
149                 return false;
150         }
151         fprintf(F, "%d\n", (int)getpid());
152         fclose(F);
153         return true;
154 }
155 
156 
file_checkStat(const char * filename,const char * description,mode_t permmask)157 bool file_checkStat(const char *filename, const char *description, mode_t permmask) {
158         ASSERT(filename);
159         ASSERT(description);
160         errno = 0;
161         struct stat buf;
162         if (stat(filename, &buf) < 0) {
163                 Log_error("Cannot stat the %s '%s' -- %s\n", description, filename, STRERROR);
164                 return false;
165         }
166         if (! S_ISREG(buf.st_mode)) {
167                 Log_error("The %s '%s' is not a regular file.\n", description,  filename);
168                 return false;
169         }
170         if (buf.st_uid != geteuid())  {
171                 Log_error("The %s '%s' must be owned by you.\n", description, filename);
172                 return false;
173         }
174         if ((buf.st_mode & 0777) & ~permmask) {
175                 Log_error("The %s '%s' permission 0%o is wrong, maximum 0%o allowed\n", description, filename, buf.st_mode & 0777, permmask & 0777);
176                 return false;
177         }
178         return true;
179 }
180 
181 
file_checkQueueDirectory(const char * path)182 bool file_checkQueueDirectory(const char *path) {
183         if (mkdir(path, 0700) < 0 && errno != EEXIST) {
184                 Log_error("Cannot create the event queue directory '%s' -- %s\n", path, STRERROR);
185                 return false;
186         }
187         return true;
188 }
189 
190 
file_checkQueueLimit(const char * path,int limit)191 bool file_checkQueueLimit(const char *path, int limit) {
192         if (limit >= 0) {
193                 DIR *dir = opendir(path);
194                 if (! dir) {
195                         Log_error("Cannot open the event queue directory '%s' -- %s\n", path, STRERROR);
196                         return false;
197                 }
198                 int used = 0;
199                 struct dirent *de = NULL;
200                 while ((de = readdir(dir)) ) {
201                         char buf[PATH_MAX];
202                         snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
203                         if (File_isFile(buf) && ++used > limit) {
204                                 Log_error("Event queue is full\n");
205                                 closedir(dir);
206                                 return false;
207                         }
208                 }
209                 closedir(dir);
210         }
211         return true;
212 }
213 
214 
file_writeQueue(FILE * file,const void * data,size_t size)215 bool file_writeQueue(FILE *file, const void *data, size_t size) {
216         ASSERT(file);
217         /* write size */
218         size_t rv = fwrite(&size, 1, sizeof(size_t), file);
219         if (rv != sizeof(size_t)) {
220                 if (feof(file) || ferror(file))
221                         Log_error("Queued event file: unable to write event size -- %s\n", feof(file) ? "end of file" : "stream error");
222                 else
223                         Log_error("Queued event file: unable to write event size -- read returned %lu bytes\n", (unsigned long)rv);
224                 return false;
225         }
226         /* write data if any */
227         if (size > 0) {
228                 if ((rv = fwrite(data, 1, size, file)) != size) {
229                         if (feof(file) || ferror(file))
230                                 Log_error("Queued event file: unable to write event size -- %s\n", feof(file) ? "end of file" : "stream error");
231                         else
232                                 Log_error("Queued event file: unable to write event size -- read returned %lu bytes\n", (unsigned long)rv);
233                         return false;
234                 }
235         }
236         return true;
237 }
238 
239 
file_readQueue(FILE * file,size_t * size)240 void *file_readQueue(FILE *file, size_t *size) {
241         ASSERT(file);
242         /* read size */
243         size_t rv = fread(size, 1, sizeof(size_t), file);
244         if (rv != sizeof(size_t)) {
245                 if (feof(file) || ferror(file))
246                         Log_error("Queued event file: unable to read event size -- %s\n", feof(file) ? "end of file" : "stream error");
247                 else
248                         Log_error("Queued event file: unable to read event size -- read returned %lu bytes\n", (unsigned long)rv);
249                 return NULL;
250         }
251         /* read data if any (allow 1MB at maximum to prevent enormous memory allocation) */
252         void *data = NULL;
253         if (*size > 0 && *size < 1048576) {
254                 data = CALLOC(1, *size);
255                 if ((rv = fread(data, 1, *size, file)) != *size) {
256                         FREE(data);
257                         if (feof(file) || ferror(file))
258                                 Log_error("Queued event file: unable to read event data -- %s\n", feof(file) ? "end of file" : "stream error");
259                         else
260                                 Log_error("Queued event file: unable to read event data -- read returned %lu bytes\n", (unsigned long)rv);
261                         return NULL;
262                 }
263         }
264         return data;
265 }
266 
267 
file_readProc(char * buf,int buf_size,const char * name,int pid,int * bytes_read)268 bool file_readProc(char *buf, int buf_size, const char *name, int pid, int *bytes_read) {
269         ASSERT(buf);
270         ASSERT(name);
271 
272         char filename[STRLEN];
273         if (pid < 0)
274                 snprintf(filename, sizeof(filename), "/proc/%s", name);
275         else
276                 snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, name);
277 
278         int fd = open(filename, O_RDONLY);
279         if (fd < 0) {
280                 if (Run.debug >= 2)
281                         DEBUG("Cannot open proc file '%s' -- %s\n", filename, STRERROR);
282                 return false;
283         }
284 
285         bool rv = false;
286         int bytes = (int)read(fd, buf, buf_size - 1);
287         if (bytes >= 0) {
288                 if (bytes_read)
289                         *bytes_read = bytes;
290                 buf[bytes] = 0;
291                 rv = true;
292         } else {
293                 *buf = 0;
294                 DEBUG("Cannot read proc file '%s' -- %s\n", filename, STRERROR);
295         }
296 
297         if (close(fd) < 0)
298                 Log_error("Failed to close proc file '%s' -- %s\n", filename, STRERROR);
299 
300         return rv;
301 }
302 
303