"Fossies" - the Fresh Open Source Software Archive

Member "monit-5.28.0/src/util.c" (28 Mar 2021, 83210 Bytes) of package /linux/privat/monit-5.28.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "util.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.27.2_vs_5.28.0.

    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_STDARG_H
   32 #include <stdarg.h>
   33 #endif
   34 
   35 #ifdef HAVE_ERRNO_H
   36 #include <errno.h>
   37 #endif
   38 
   39 #ifdef HAVE_CTYPE_H
   40 #include <ctype.h>
   41 #endif
   42 
   43 #ifdef HAVE_SIGNAL_H
   44 #include <signal.h>
   45 #endif
   46 
   47 #ifdef HAVE_STDLIB_H
   48 #include <stdlib.h>
   49 #endif
   50 
   51 #ifdef HAVE_SYS_SOCKET_H
   52 #include <sys/socket.h>
   53 #endif
   54 
   55 #ifdef HAVE_FCNTL_H
   56 #include <fcntl.h>
   57 #endif
   58 
   59 #ifdef HAVE_UNISTD_H
   60 #include <unistd.h>
   61 #endif
   62 
   63 #ifdef HAVE_STRING_H
   64 #include <string.h>
   65 #endif
   66 
   67 #ifdef HAVE_STRINGS_H
   68 #include <strings.h>
   69 #endif
   70 
   71 #ifdef HAVE_SYS_TYPES_H
   72 #include <sys/types.h>
   73 #endif
   74 
   75 #ifdef HAVE_NETDB_H
   76 #include <netdb.h>
   77 #endif
   78 
   79 #ifdef HAVE_SYS_STAT_H
   80 #include <sys/stat.h>
   81 #endif
   82 
   83 #ifdef HAVE_CRYPT_H
   84 #include <crypt.h>
   85 #endif
   86 
   87 #ifdef HAVE_NETINET_IN_H
   88 #include <netinet/in.h>
   89 #endif
   90 
   91 #ifdef HAVE_ARPA_INET_H
   92 #include <arpa/inet.h>
   93 #endif
   94 
   95 #ifdef HAVE_PAM_PAM_APPL_H
   96 #include <pam/pam_appl.h>
   97 #endif
   98 
   99 #ifdef HAVE_SECURITY_PAM_APPL_H
  100 #include <security/pam_appl.h>
  101 #endif
  102 
  103 #ifdef HAVE_PWD_H
  104 #include <pwd.h>
  105 #endif
  106 
  107 #ifdef HAVE_GRP_H
  108 #include <grp.h>
  109 #endif
  110 
  111 #include "monit.h"
  112 #include "engine.h"
  113 #include "md5.h"
  114 #include "md5_crypt.h"
  115 #include "sha1.h"
  116 #include "base64.h"
  117 #include "alert.h"
  118 #include "ProcessTree.h"
  119 #include "event.h"
  120 #include "state.h"
  121 #include "protocol.h"
  122 #include "checksum.h"
  123 
  124 // libmonit
  125 #include "io/File.h"
  126 #include "util/Convert.h"
  127 #include "system/Time.h"
  128 #include "exceptions/AssertException.h"
  129 #include "exceptions/IOException.h"
  130 
  131 
  132 struct ad_user {
  133         const char *login;
  134         const char *passwd;
  135 };
  136 
  137 
  138 /* Unsafe URL characters: [00-1F, 7F-FF] <>\"#%}{|\\^[] ` */
  139 static const unsigned char urlunsafe[256] = {
  140         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  141         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  142         1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  143         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
  144         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  145         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
  146         1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  147         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
  148         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  149         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  150         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  151         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  152         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  153         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  154         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  155         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  156 };
  157 
  158 
  159 /* Unsafe URL characters for parameter value: [00-1F, 7F-FF] ?=&/<>\"#%}{|\\^[] ` */
  160 static const unsigned char urlunsafeparameter[256] = {
  161         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  162         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  163         1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
  164         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
  165         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  166         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
  167         1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  168         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1,
  169         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  170         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  171         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  172         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  173         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  174         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  175         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  176         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
  177 };
  178 
  179 
  180 static const unsigned char b2x[][256] = {
  181         "00", "01", "02", "03", "04", "05", "06", "07",
  182         "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
  183         "10", "11", "12", "13", "14", "15", "16", "17",
  184         "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
  185         "20", "21", "22", "23", "24", "25", "26", "27",
  186         "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
  187         "30", "31", "32", "33", "34", "35", "36", "37",
  188         "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
  189         "40", "41", "42", "43", "44", "45", "46", "47",
  190         "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
  191         "50", "51", "52", "53", "54", "55", "56", "57",
  192         "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
  193         "60", "61", "62", "63", "64", "65", "66", "67",
  194         "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
  195         "70", "71", "72", "73", "74", "75", "76", "77",
  196         "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
  197         "80", "81", "82", "83", "84", "85", "86", "87",
  198         "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
  199         "90", "91", "92", "93", "94", "95", "96", "97",
  200         "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
  201         "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
  202         "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
  203         "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
  204         "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
  205         "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7",
  206         "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
  207         "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
  208         "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
  209         "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7",
  210         "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
  211         "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7",
  212         "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
  213 };
  214 
  215 
  216 /**
  217  *  General purpose utility methods.
  218  *
  219  *  @file
  220  */
  221 
  222 
  223 /* ----------------------------------------------------------------- Private */
  224 
  225 
  226 /**
  227  * Returns the value of the parameter if defined or the String "(not
  228  * defined)"
  229  */
  230 static const char *is_str_defined(const char *s) {
  231         return((s && *s) ? s : "(not defined)");
  232 }
  233 
  234 
  235 /**
  236  * Convert a hex char to a char
  237  */
  238 static char _x2c(char *hex) {
  239         register char digit;
  240         digit = ((hex[0] >= 'A') ? ((hex[0] & 0xdf) - 'A')+10 : (hex[0] - '0'));
  241         digit *= 16;
  242         digit += (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A')+10 : (hex[1] - '0'));
  243         return(digit);
  244 }
  245 
  246 
  247 /**
  248  * Print registered events list
  249  */
  250 static void printevents(unsigned int events) {
  251         if (events == Event_Null) {
  252                 printf("No events");
  253         } else if (events == Event_All) {
  254                 printf("All events");
  255         } else {
  256                 if (IS_EVENT_SET(events, Event_Action))
  257                         printf("Action ");
  258                 if (IS_EVENT_SET(events, Event_ByteIn))
  259                         printf("ByteIn ");
  260                 if (IS_EVENT_SET(events, Event_ByteOut))
  261                         printf("ByteOut ");
  262                 if (IS_EVENT_SET(events, Event_Checksum))
  263                         printf("Checksum ");
  264                 if (IS_EVENT_SET(events, Event_Connection))
  265                         printf("Connection ");
  266                 if (IS_EVENT_SET(events, Event_Content))
  267                         printf("Content ");
  268                 if (IS_EVENT_SET(events, Event_Data))
  269                         printf("Data ");
  270                 if (IS_EVENT_SET(events, Event_Exec))
  271                         printf("Exec ");
  272                 if (IS_EVENT_SET(events, Event_Exist))
  273                         printf("Exist ");
  274                 if (IS_EVENT_SET(events, Event_FsFlag))
  275                         printf("Fsflags ");
  276                 if (IS_EVENT_SET(events, Event_Gid))
  277                         printf("Gid ");
  278                 if (IS_EVENT_SET(events, Event_Icmp))
  279                         printf("Icmp ");
  280                 if (IS_EVENT_SET(events, Event_Instance))
  281                         printf("Instance ");
  282                 if (IS_EVENT_SET(events, Event_Invalid))
  283                         printf("Invalid ");
  284                 if (IS_EVENT_SET(events, Event_Link))
  285                         printf("Link ");
  286                 if (IS_EVENT_SET(events, Event_NonExist))
  287                         printf("Nonexist ");
  288                 if (IS_EVENT_SET(events, Event_PacketIn))
  289                         printf("PacketIn ");
  290                 if (IS_EVENT_SET(events, Event_PacketOut))
  291                         printf("PacketOut ");
  292                 if (IS_EVENT_SET(events, Event_Permission))
  293                         printf("Permission ");
  294                 if (IS_EVENT_SET(events, Event_Pid))
  295                         printf("PID ");
  296                 if (IS_EVENT_SET(events, Event_PPid))
  297                         printf("PPID ");
  298                 if (IS_EVENT_SET(events, Event_Resource))
  299                         printf("Resource ");
  300                 if (IS_EVENT_SET(events, Event_Saturation))
  301                         printf("Saturation ");
  302                 if (IS_EVENT_SET(events, Event_Size))
  303                         printf("Size ");
  304                 if (IS_EVENT_SET(events, Event_Speed))
  305                         printf("Speed ");
  306                 if (IS_EVENT_SET(events, Event_Status))
  307                         printf("Status ");
  308                 if (IS_EVENT_SET(events, Event_Timeout))
  309                         printf("Timeout ");
  310                 if (IS_EVENT_SET(events, Event_Timestamp))
  311                         printf("Timestamp ");
  312                 if (IS_EVENT_SET(events, Event_Uid))
  313                         printf("Uid ");
  314                 if (IS_EVENT_SET(events, Event_Uptime))
  315                         printf("Uptime ");
  316 
  317         }
  318         printf("\n");
  319 }
  320 
  321 
  322 #ifdef HAVE_LIBPAM
  323 /**
  324  * PAM conversation
  325  */
  326 #if defined(SOLARIS) || defined(AIX)
  327 static int PAMquery(int num_msg, struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
  328 #else
  329 static int PAMquery(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
  330 #endif
  331         int i;
  332         struct ad_user *user = (struct ad_user *)appdata_ptr;
  333         struct pam_response *response;
  334 
  335         /* Sanity checking */
  336         if (! msg || ! resp || ! user )
  337                 return PAM_CONV_ERR;
  338 
  339         response = CALLOC(sizeof(struct pam_response), num_msg);
  340 
  341         for (i = 0; i < num_msg; i++) {
  342                 response[i].resp = NULL;
  343                 response[i].resp_retcode = 0;
  344 
  345                 switch ((*(msg[i])).msg_style) {
  346                         case PAM_PROMPT_ECHO_ON:
  347                                 /* Store the login as the response. This likely never gets called, since login was on pam_start() */
  348                                 response[i].resp = appdata_ptr ? Str_dup(user->login) : NULL;
  349                                 break;
  350 
  351                         case PAM_PROMPT_ECHO_OFF:
  352                                 /* Store the password as the response */
  353                                 response[i].resp = appdata_ptr ? Str_dup(user->passwd) : NULL;
  354                                 break;
  355 
  356                         case PAM_TEXT_INFO:
  357                         case PAM_ERROR_MSG:
  358                                 /* Shouldn't happen since we have PAM_SILENT set. If it happens anyway, ignore it. */
  359                                 break;
  360 
  361                         default:
  362                                 /* Something strange... */
  363                                 FREE(response);
  364                                 return PAM_CONV_ERR;
  365                 }
  366         }
  367         /* On success, return the response structure */
  368         *resp = response;
  369         return PAM_SUCCESS;
  370 }
  371 
  372 
  373 /**
  374  * Validate login/passwd via PAM service "monit"
  375  */
  376 static bool PAMcheckPasswd(const char *login, const char *passwd) {
  377         int rv;
  378         pam_handle_t *pamh = NULL;
  379         struct ad_user user_info = {
  380                 login,
  381                 passwd
  382         };
  383         struct pam_conv conv = {
  384                 PAMquery,
  385                 &user_info
  386         };
  387 
  388         if ((rv = pam_start("monit", login, &conv, &pamh) != PAM_SUCCESS)) {
  389                 DEBUG("PAM authentication start failed -- %d\n", rv);
  390                 return false;
  391         }
  392 
  393         rv = pam_authenticate(pamh, PAM_SILENT);
  394 
  395         if (pam_end(pamh, rv) != PAM_SUCCESS)
  396                 pamh = NULL;
  397 
  398         return rv == PAM_SUCCESS ? true : false;
  399 }
  400 
  401 
  402 /**
  403  * Check whether the user is member of allowed groups
  404  */
  405 static Auth_T PAMcheckUserGroup(const char *uname) {
  406         Auth_T c = Run.httpd.credentials;
  407         struct passwd *pwd = NULL;
  408         struct group  *grp = NULL;
  409 
  410         ASSERT(uname);
  411 
  412         if (! (pwd = getpwnam(uname)))
  413                 return NULL;
  414 
  415         if (! (grp = getgrgid(pwd->pw_gid)))
  416                 return NULL;
  417 
  418         while (c) {
  419                 if (c->groupname) {
  420                         struct group *sgrp = NULL;
  421 
  422                         /* check for primary group match */
  423                         if (IS(c->groupname, grp->gr_name))
  424                                 return c;
  425 
  426                         /* check secondary groups match */
  427                         if ((sgrp = getgrnam(c->groupname))) {
  428                                 char **g = NULL;
  429 
  430                                 for (g = sgrp->gr_mem; *g; g++)
  431                                         if (IS(*g, uname))
  432                                                 return c;
  433                         }
  434                 }
  435                 c = c->next;
  436         }
  437         return NULL;
  438 }
  439 #endif
  440 
  441 
  442 /* ------------------------------------------------------------------ Public */
  443 
  444 
  445 char *Util_replaceString(char **src, const char *old, const char *new) {
  446         ASSERT(src);
  447         ASSERT(*src);
  448         ASSERT(old);
  449         ASSERT(new);
  450 
  451         int i = Util_countWords(*src, old);
  452         if (i) {
  453                 size_t l = strlen(old);
  454                 size_t d = strlen(new) - l;
  455                 if (d > 0) {
  456                         d *= i;
  457                 } else {
  458                         d = 0;
  459                 }
  460                 char *buf = CALLOC(sizeof(char), strlen(*src) + d + 1);
  461                 char *p;
  462                 char *q = *src;
  463                 *buf = 0;
  464                 while ((p = strstr(q, old))) {
  465                         *p = 0;
  466                         strcat(buf, q);
  467                         strcat(buf, new);
  468                         p += l;
  469                         q = p;
  470                 }
  471                 strcat(buf, q);
  472                 FREE(*src);
  473                 *src = buf;
  474         }
  475         return *src;
  476 }
  477 
  478 
  479 int Util_countWords(char *s, const char *word) {
  480         int i = 0;
  481         char *p = s;
  482 
  483         ASSERT(s && word);
  484 
  485         while ((p = strstr(p, word))) { i++;  p++; }
  486         return i;
  487 }
  488 
  489 
  490 void Util_handleEscapes(char *buf) {
  491         int editpos;
  492         int insertpos;
  493 
  494         ASSERT(buf);
  495 
  496         for (editpos = insertpos = 0; *(buf + editpos) != '\0'; editpos++, insertpos++) {
  497                 if (*(buf + editpos) == '\\' ) {
  498                         switch (*(buf + editpos + 1)) {
  499                                 case 'n':
  500                                         *(buf + insertpos) = '\n';
  501                                         editpos++;
  502                                         break;
  503 
  504                                 case 't':
  505                                         *(buf + insertpos) = '\t';
  506                                         editpos++;
  507                                         break;
  508 
  509                                 case 'r':
  510                                         *(buf + insertpos) = '\r';
  511                                         editpos++;
  512                                         break;
  513 
  514                                 case ' ':
  515                                         *(buf + insertpos) = ' ';
  516                                         editpos++;
  517                                         break;
  518 
  519                                 case '0':
  520                                         if (*(buf + editpos+2) == 'x') {
  521                                                 if ((*(buf + editpos + 3) == '0' && *(buf + editpos + 4) == '0')) {
  522                                                         /* Don't swap \0x00 with 0 to avoid truncating the string.
  523                                                          Currently the only place where we support sending of 0 bytes
  524                                                          is in check_generic(). The \0x00 -> 0 byte swap is performed
  525                                                          there and in-place.
  526                                                          */
  527                                                         *(buf + insertpos) = *(buf+editpos);
  528                                                 } else {
  529                                                         *(buf + insertpos) = _x2c(&buf[editpos + 3]);
  530                                                         editpos += 4;
  531                                                 }
  532                                         }
  533                                         break;
  534 
  535                                 case '\\':
  536                                         *(buf + insertpos) = '\\';
  537                                         editpos++;
  538                                         break;
  539 
  540                                 default:
  541                                         *(buf + insertpos) = *(buf + editpos);
  542 
  543                         }
  544 
  545                 } else {
  546                         *(buf + insertpos) = *(buf + editpos);
  547                 }
  548 
  549         }
  550         *(buf + insertpos) = '\0';
  551 }
  552 
  553 
  554 int Util_handle0Escapes(char *buf) {
  555         int editpos;
  556         int insertpos;
  557 
  558         ASSERT(buf);
  559 
  560         for (editpos = insertpos = 0; *(buf + editpos) != '\0'; editpos++, insertpos++) {
  561                 if (*(buf + editpos) == '\\' ) {
  562                         switch (*(buf + editpos + 1)) {
  563                                 case '0':
  564                                         if (*(buf + editpos + 2) == 'x') {
  565                                                 *(buf + insertpos) = _x2c(&buf[editpos+3]);
  566                                                 editpos += 4;
  567                                         }
  568                                         break;
  569 
  570                                 default:
  571                                         *(buf + insertpos) = *(buf + editpos);
  572 
  573                         }
  574 
  575                 } else {
  576                         *(buf + insertpos) = *(buf + editpos);
  577                 }
  578         }
  579         *(buf + insertpos) = '\0';
  580         return insertpos;
  581 }
  582 
  583 
  584 Service_T Util_getService(const char *name) {
  585         ASSERT(name);
  586         for (Service_T s = servicelist; s; s = s->next)
  587                 if (IS(s->name, name))
  588                         return s;
  589         return NULL;
  590 }
  591 
  592 
  593 int Util_getNumberOfServices() {
  594         int i = 0;
  595         Service_T s;
  596         for (s = servicelist; s; s = s->next)
  597                 i += 1;
  598         return i;
  599 }
  600 
  601 
  602 bool Util_existService(const char *name) {
  603         ASSERT(name);
  604         return Util_getService(name) ? true : false;
  605 }
  606 
  607 
  608 void Util_printRunList() {
  609         char buf[10];
  610         printf("Runtime constants:\n");
  611         printf(" %-18s = %s\n", "Control file", is_str_defined(Run.files.control));
  612         printf(" %-18s = %s\n", "Log file", is_str_defined(Run.files.log));
  613         printf(" %-18s = %s\n", "Pid file", is_str_defined(Run.files.pid));
  614         printf(" %-18s = %s\n", "Id file", is_str_defined(Run.files.id));
  615         printf(" %-18s = %s\n", "State file", is_str_defined(Run.files.state));
  616         printf(" %-18s = %s\n", "Debug", Run.debug ? "True" : "False");
  617         printf(" %-18s = %s\n", "Log", (Run.flags & Run_Log) ? "True" : "False");
  618         printf(" %-18s = %s\n", "Use syslog", (Run.flags & Run_UseSyslog) ? "True" : "False");
  619         printf(" %-18s = %s\n", "Is Daemon", (Run.flags & Run_Daemon) ? "True" : "False");
  620         printf(" %-18s = %s\n", "Use process engine", (Run.flags & Run_ProcessEngineEnabled) ? "True" : "False");
  621         printf(" %-18s = {\n", "Limits");
  622         printf(" %-18s =   programOutput:     %s\n", " ", Convert_bytes2str(Run.limits.programOutput, buf));
  623         printf(" %-18s =   sendExpectBuffer:  %s\n", " ", Convert_bytes2str(Run.limits.sendExpectBuffer, buf));
  624         printf(" %-18s =   fileContentBuffer: %s\n", " ", Convert_bytes2str(Run.limits.fileContentBuffer, buf));
  625         printf(" %-18s =   httpContentBuffer: %s\n", " ", Convert_bytes2str(Run.limits.httpContentBuffer, buf));
  626         printf(" %-18s =   networkTimeout:    %s\n", " ", Convert_time2str(Run.limits.networkTimeout, (char[11]){}));
  627         printf(" %-18s =   programTimeout:    %s\n", " ", Convert_time2str(Run.limits.programTimeout, (char[11]){}));
  628         printf(" %-18s =   stopTimeout:       %s\n", " ", Convert_time2str(Run.limits.stopTimeout, (char[11]){}));
  629         printf(" %-18s =   startTimeout:      %s\n", " ", Convert_time2str(Run.limits.startTimeout, (char[11]){}));
  630         printf(" %-18s =   restartTimeout:    %s\n", " ", Convert_time2str(Run.limits.restartTimeout, (char[11]){}));
  631         printf(" %-18s = }\n", " ");
  632         printf(" %-18s = %s\n", "On reboot", onrebootnames[Run.onreboot]);
  633         printf(" %-18s = %d seconds with start delay %d seconds\n", "Poll time", Run.polltime, Run.startdelay);
  634 
  635         if (Run.eventlist_dir) {
  636                 char slots[STRLEN];
  637 
  638                 if (Run.eventlist_slots < 0)
  639                         snprintf(slots, STRLEN, "unlimited");
  640                 else
  641                         snprintf(slots, STRLEN, "%d", Run.eventlist_slots);
  642 
  643                 printf(" %-18s = base directory %s with %s slots\n",
  644                        "Event queue", Run.eventlist_dir, slots);
  645         }
  646 #ifdef HAVE_OPENSSL
  647         {
  648                 const char *options = Ssl_printOptions(&(Run.ssl), (char[STRLEN]){}, STRLEN);
  649                 if (options && *options)
  650                         printf(" %-18s = %s\n", "SSL options", options);
  651         }
  652 #endif
  653         if (Run.mmonits) {
  654                 Mmonit_T c;
  655                 printf(" %-18s = ", "M/Monit(s)");
  656                 for (c = Run.mmonits; c; c = c->next) {
  657                         printf("%s with timeout %s", c->url->url, Convert_time2str(c->timeout, (char[11]){}));
  658 #ifdef HAVE_OPENSSL
  659                         if (c->ssl.flags) {
  660                                 printf(" using TLS");
  661                                 const char *options = Ssl_printOptions(&c->ssl, (char[STRLEN]){}, STRLEN);
  662                                 if (options && *options)
  663                                         printf(" with options {%s}", options);
  664                                 if (c->ssl.checksum)
  665                                         printf(" and certificate checksum %s equal to '%s'", checksumnames[c->ssl.checksumType], c->ssl.checksum);
  666                         }
  667 #endif
  668                         if (Run.flags & Run_MmonitCredentials && c->url->user)
  669                                 printf(" with credentials");
  670                         if (c->next)
  671                                printf(",\n                    = ");
  672                 }
  673                 printf("\n");
  674         }
  675 
  676         if (Run.mailservers) {
  677                 MailServer_T mta;
  678                 printf(" %-18s = ", "Mail server(s)");
  679                 for (mta = Run.mailservers; mta; mta = mta->next) {
  680                         printf("%s:%d", mta->host, mta->port);
  681 #ifdef HAVE_OPENSSL
  682                         if (mta->ssl.flags) {
  683                                 printf(" using TLS");
  684                                 const char *options = Ssl_printOptions(&mta->ssl, (char[STRLEN]){}, STRLEN);
  685                                 if (options && *options)
  686                                         printf(" with options {%s}", options);
  687                                 if (mta->ssl.checksum)
  688                                         printf(" and certificate checksum %s equal to '%s'", checksumnames[mta->ssl.checksumType], mta->ssl.checksum);
  689                         }
  690 #endif
  691                         if (mta->next)
  692                                 printf(", ");
  693                 }
  694                 printf(" with timeout %s", Convert_time2str(Run.mailserver_timeout, (char[11]){}));
  695                 if (Run.mail_hostname)
  696                         printf(" using '%s' as my hostname", Run.mail_hostname);
  697                 printf("\n");
  698         }
  699 
  700         if (Run.MailFormat.from) {
  701                 if (Run.MailFormat.from->name)
  702                         printf(" %-18s = %s <%s>\n", "Mail from", Run.MailFormat.from->name, Run.MailFormat.from->address);
  703                 else
  704                         printf(" %-18s = %s\n", "Mail from", Run.MailFormat.from->address);
  705         }
  706         if (Run.MailFormat.replyto) {
  707                 if (Run.MailFormat.replyto->name)
  708                         printf(" %-18s = %s <%s>\n", "Mail reply to", Run.MailFormat.replyto->name, Run.MailFormat.replyto->address);
  709                 else
  710                         printf(" %-18s = %s\n", "Mail reply to", Run.MailFormat.replyto->address);
  711         }
  712         if (Run.MailFormat.subject)
  713                 printf(" %-18s = %s\n", "Mail subject", Run.MailFormat.subject);
  714         if (Run.MailFormat.message)
  715                 printf(" %-18s = %-.20s..(truncated)\n", "Mail message", Run.MailFormat.message);
  716 
  717         printf(" %-18s = %s\n", "Start monit httpd", (Run.httpd.flags & Httpd_Net || Run.httpd.flags & Httpd_Unix) ? "True" : "False");
  718 
  719         if (Run.httpd.flags & Httpd_Net || Run.httpd.flags & Httpd_Unix) {
  720                 if (Run.httpd.flags & Httpd_Net) {
  721                         printf(" %-18s = %s\n", "httpd bind address", Run.httpd.socket.net.address ? Run.httpd.socket.net.address : "Any/All");
  722                         printf(" %-18s = %d\n", "httpd portnumber", Run.httpd.socket.net.port);
  723 #ifdef HAVE_OPENSSL
  724                         const char *options = Ssl_printOptions(&(Run.httpd.socket.net.ssl), (char[STRLEN]){}, STRLEN);
  725                         if (options && *options)
  726                                 printf(" %-18s = %s\n", "httpd encryption", options);
  727 #endif
  728                 }
  729                 if (Run.httpd.flags & Httpd_Unix)
  730                         printf(" %-18s = %s\n", "httpd unix socket", Run.httpd.socket.unix.path);
  731                 printf(" %-18s = %s\n", "httpd signature", Run.httpd.flags & Httpd_Signature ? "Enabled" : "Disabled");
  732                 printf(" %-18s = %s\n", "httpd auth. style",
  733                        Run.httpd.credentials && Engine_hasAllow() ? "Basic Authentication and Host/Net allow list" : Run.httpd.credentials ? "Basic Authentication" : Engine_hasAllow() ? "Host/Net allow list" : "No authentication!");
  734 
  735         }
  736 
  737         {
  738                 for (Mail_T list = Run.maillist; list; list = list->next) {
  739                         printf(" %-18s = %s\n", "Alert mail to", is_str_defined(list->to));
  740                         printf("   %-16s = ", "Alert on");
  741                         printevents(list->events);
  742                         if (list->reminder)
  743                                 printf("   %-16s = %u cycles\n", "Alert reminder", list->reminder);
  744                 }
  745         }
  746 
  747         printf("\n");
  748 }
  749 
  750 
  751 void Util_printService(Service_T s) {
  752         ASSERT(s);
  753 
  754         bool sgheader = false;
  755         char buffer[STRLEN];
  756         StringBuffer_T buf = StringBuffer_create(STRLEN);
  757 
  758         printf("%-21s = %s\n", StringBuffer_toString(StringBuffer_append(buf, "%s Name", servicetypes[s->type])), s->name);
  759 
  760         for (ServiceGroup_T o = servicegrouplist; o; o = o->next) {
  761                 for (list_t m = o->members->head; m; m = m->next) {
  762                         if (m->e == s) {
  763                                 if (! sgheader) {
  764                                         printf(" %-20s = %s", "Group", o->name);
  765                                         sgheader = true;
  766                                 } else {
  767                                         printf(", %s", o->name);
  768                                 }
  769                         }
  770                 }
  771         }
  772         if (sgheader)
  773                 printf("\n");
  774 
  775         if (s->type == Service_Process) {
  776                 if (s->matchlist)
  777                         printf(" %-20s = %s\n", "Match", s->path);
  778                 else
  779                         printf(" %-20s = %s\n", "Pid file", s->path);
  780         } else if (s->type == Service_Host) {
  781                 printf(" %-20s = %s\n", "Address", s->path);
  782         } else if (s->type == Service_Net) {
  783                 printf(" %-20s = %s\n", "Interface", s->path);
  784         } else if (s->type != Service_System) {
  785                 printf(" %-20s = %s\n", "Path", s->path);
  786         }
  787         printf(" %-20s = %s\n", "Monitoring mode", modenames[s->mode]);
  788         printf(" %-20s = %s\n", "On reboot", onrebootnames[s->onreboot]);
  789         if (s->start) {
  790                 printf(" %-20s = '%s'", "Start program", Util_commandDescription(s->start, (char[STRLEN]){}));
  791                 if (s->start->has_uid)
  792                         printf(" as uid %d", s->start->uid);
  793                 if (s->start->has_gid)
  794                         printf(" as gid %d", s->start->gid);
  795                 printf(" timeout %s", Convert_time2str(s->start->timeout, (char[11]){}));
  796                 printf("\n");
  797         }
  798         if (s->stop) {
  799                 printf(" %-20s = '%s'", "Stop program", Util_commandDescription(s->stop, (char[STRLEN]){}));
  800                 if (s->stop->has_uid)
  801                         printf(" as uid %d", s->stop->uid);
  802                 if (s->stop->has_gid)
  803                         printf(" as gid %d", s->stop->gid);
  804                 printf(" timeout %s", Convert_time2str(s->stop->timeout, (char[11]){}));
  805                 printf("\n");
  806         }
  807         if (s->restart) {
  808                 printf(" %-20s = '%s'", "Restart program", Util_commandDescription(s->restart, (char[STRLEN]){}));
  809                 if (s->restart->has_uid)
  810                         printf(" as uid %d", s->restart->uid);
  811                 if (s->restart->has_gid)
  812                         printf(" as gid %d", s->restart->gid);
  813                 printf(" timeout %s", Convert_time2str(s->restart->timeout, (char[11]){}));
  814                 printf("\n");
  815         }
  816 
  817         for (NonExist_T o = s->nonexistlist; o; o = o->next) {
  818                 StringBuffer_clear(buf);
  819                 printf(" %-20s = %s\n", "Existence", StringBuffer_toString(Util_printRule(false, buf, o->action, "if does not exist")));
  820         }
  821 
  822         for (Exist_T o = s->existlist; o; o = o->next) {
  823                 StringBuffer_clear(buf);
  824                 printf(" %-20s = %s\n", "Non-Existence", StringBuffer_toString(Util_printRule(false, buf, o->action, "if exist")));
  825         }
  826 
  827         for (Dependant_T o = s->dependantlist; o; o = o->next)
  828                 if (o->dependant != NULL)
  829                         printf(" %-20s = %s\n", "Depends on Service", o->dependant);
  830 
  831         for (Pid_T o = s->pidlist; o; o = o->next) {
  832                 StringBuffer_clear(buf);
  833                 printf(" %-20s = %s\n", "Pid", StringBuffer_toString(Util_printRule(false, buf, o->action, "if changed")));
  834         }
  835 
  836         for (Pid_T o = s->ppidlist; o; o = o->next) {
  837                 StringBuffer_clear(buf);
  838                 printf(" %-20s = %s\n", "PPid", StringBuffer_toString(Util_printRule(false, buf, o->action, "if changed")));
  839         }
  840 
  841         for (FsFlag_T o = s->fsflaglist; o; o = o->next) {
  842                 StringBuffer_clear(buf);
  843                 printf(" %-20s = %s\n", "Filesystem flags", StringBuffer_toString(Util_printRule(false, buf, o->action, "if changed")));
  844         }
  845 
  846         if (s->type == Service_Program) {
  847                 printf(" %-20s = ", "Program timeout");
  848                 printf("terminate the program if not finished within %s\n", Convert_time2str(s->program->timeout, (char[11]){}));
  849                 for (Status_T o = s->statuslist; o; o = o->next) {
  850                         StringBuffer_clear(buf);
  851                         if (o->operator == Operator_Changed)
  852                                 printf(" %-20s = %s\n", "Status", StringBuffer_toString(Util_printRule(false, buf, o->action, "if exit value changed")));
  853                         else
  854                                 printf(" %-20s = %s\n", "Status", StringBuffer_toString(Util_printRule(false, buf, o->action, "if exit value %s %d", operatorshortnames[o->operator], o->return_value)));
  855                 }
  856         }
  857 
  858         if (s->checksum && s->checksum->action) {
  859                 StringBuffer_clear(buf);
  860                 printf(" %-20s = %s\n", "Checksum",
  861                        s->checksum->test_changes
  862                        ?
  863                        StringBuffer_toString(Util_printRule(false, buf, s->checksum->action, "if changed %s", checksumnames[s->checksum->type]))
  864                        :
  865                        StringBuffer_toString(Util_printRule(false, buf, s->checksum->action, "if failed %s(%s)", s->checksum->hash, checksumnames[s->checksum->type]))
  866                        );
  867         }
  868 
  869         if (s->perm && s->perm->action) {
  870                 StringBuffer_clear(buf);
  871                 printf(" %-20s = %s\n", "Permission",
  872                        s->perm->test_changes
  873                        ?
  874                        StringBuffer_toString(Util_printRule(false, buf, s->perm->action, "if changed"))
  875                        :
  876                        StringBuffer_toString(Util_printRule(false, buf, s->perm->action, "if failed %04o", s->perm->perm))
  877                        );
  878         }
  879 
  880         if (s->uid && s->uid->action) {
  881                 StringBuffer_clear(buf);
  882                 printf(" %-20s = %s\n", "UID", StringBuffer_toString(Util_printRule(false, buf, s->uid->action, "if failed %d", s->uid->uid)));
  883         }
  884 
  885         if (s->euid && s->euid->action) {
  886                 StringBuffer_clear(buf);
  887                 printf(" %-20s = %s\n", "EUID", StringBuffer_toString(Util_printRule(false, buf, s->euid->action, "if failed %d", s->euid->uid)));
  888         }
  889 
  890         for (SecurityAttribute_T o = s->secattrlist; o; o = o->next) {
  891                 StringBuffer_clear(buf);
  892                 printf(" %-20s = %s\n", "Security attribute", StringBuffer_toString(Util_printRule(false, buf, o->action, "if failed %s", o->attribute)));
  893         }
  894 
  895         for (Filedescriptors_T o = s->filedescriptorslist; o; o = o->next) {
  896                 StringBuffer_clear(buf);
  897                 if (o->total) {
  898                         printf(" %-20s = %s\n", "Total filedescriptors", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld", operatornames[o->operator], o->limit_absolute)));
  899                 } else {
  900                         if (o->limit_absolute > -1)
  901                                 printf(" %-20s = %s\n", "Filedescriptors", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld", operatornames[o->operator], o->limit_absolute)));
  902                         else
  903                                 printf(" %-20s = %s\n", "Filedescriptors", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit_percent)));
  904                 }
  905         }
  906 
  907         if (s->gid && s->gid->action) {
  908                 StringBuffer_clear(buf);
  909                 printf(" %-20s = %s\n", "GID", StringBuffer_toString(Util_printRule(false, buf, s->gid->action, "if failed %d", s->gid->gid)));
  910         }
  911 
  912         for (Icmp_T o = s->icmplist; o; o = o->next) {
  913                 StringBuffer_clear(buf);
  914                 StringBuffer_T buf2 = StringBuffer_create(64);
  915                 StringBuffer_append(buf2, "if %s count %d size %d with timeout %s", o->check_invers ? "succeeded" : "failed", o->count, o->size, Convert_time2str(o->timeout, (char[11]){}));
  916                 if (o->responsetime.limit > -1.)
  917                         StringBuffer_append(buf2, " and responsetime %s %s", operatornames[o->responsetime.operator], Convert_time2str(o->responsetime.limit, (char[11]){}));
  918                 if (o->outgoing.ip)
  919                         StringBuffer_append(buf2, " via address %s",  o->outgoing.ip);
  920                 switch (o->family) {
  921                         case Socket_Ip4:
  922                                 printf(" %-20s = %s\n", "Ping4", StringBuffer_toString(Util_printRule(o->check_invers, buf, o->action, "%s", StringBuffer_toString(buf2))));
  923                                 break;
  924                         case Socket_Ip6:
  925                                 printf(" %-20s = %s\n", "Ping6", StringBuffer_toString(Util_printRule(o->check_invers, buf, o->action, "%s", StringBuffer_toString(buf2))));
  926                                 break;
  927                         default:
  928                                 printf(" %-20s = %s\n", "Ping", StringBuffer_toString(Util_printRule(o->check_invers, buf, o->action, "%s", StringBuffer_toString(buf2))));
  929                                 break;
  930                 }
  931                 StringBuffer_free(&buf2);
  932         }
  933 
  934         for (Port_T o = s->portlist; o; o = o->next) {
  935                 StringBuffer_clear(buf);
  936                 StringBuffer_T buf2 = StringBuffer_create(64);
  937                 StringBuffer_append(buf2, "if %s [%s]:%d%s",
  938                         o->check_invers ? "succeeded" : "failed", o->hostname, o->target.net.port, Util_portRequestDescription(o));
  939                 if (o->outgoing.ip)
  940                         StringBuffer_append(buf2, " via address %s", o->outgoing.ip);
  941                 StringBuffer_append(buf2, " type %s/%s protocol %s with timeout %s",
  942                         Util_portTypeDescription(o), Util_portIpDescription(o), o->protocol->name, Convert_time2str(o->timeout, (char[11]){}));
  943                 if (o->retry > 1)
  944                         StringBuffer_append(buf2, " and retry %d times", o->retry);
  945                 if (o->responsetime.limit > -1.)
  946                         StringBuffer_append(buf2, " and responsetime %s %s", operatornames[o->responsetime.operator], Convert_time2str(o->responsetime.limit, (char[11]){}));
  947 #ifdef HAVE_OPENSSL
  948                 if (o->target.net.ssl.options.flags) {
  949                         StringBuffer_append(buf2, " using TLS");
  950                         const char *options = Ssl_printOptions(&o->target.net.ssl.options, (char[STRLEN]){}, STRLEN);
  951                         if (options && *options)
  952                                 StringBuffer_append(buf2, " with options {%s}", options);
  953                         if (o->target.net.ssl.certificate.minimumDays > 0)
  954                                 StringBuffer_append(buf2, " and certificate valid for at least %d days", o->target.net.ssl.certificate.minimumDays);
  955                         if (o->target.net.ssl.options.checksum)
  956                                 StringBuffer_append(buf2, " and certificate checksum %s equal to '%s'", checksumnames[o->target.net.ssl.options.checksumType], o->target.net.ssl.options.checksum);
  957                 }
  958 #endif
  959                 printf(" %-20s = %s\n", "Port", StringBuffer_toString(Util_printRule(o->check_invers, buf, o->action, "%s", StringBuffer_toString(buf2))));
  960                 StringBuffer_free(&buf2);
  961         }
  962 
  963         for (Port_T o = s->socketlist; o; o = o->next) {
  964                 StringBuffer_clear(buf);
  965                 StringBuffer_T buf2 = StringBuffer_create(64);
  966                 StringBuffer_append(buf2, "if %s %s type %s protocol %s with timeout %s", o->check_invers ? "succeeded" : "failed", o->target.unix.pathname, Util_portTypeDescription(o), o->protocol->name, Convert_time2str(o->timeout, (char[11]){}));
  967                 if (o->retry > 1)
  968                         StringBuffer_append(buf2, " and retry %d times", o->retry);
  969                 if (o->responsetime.limit > -1.)
  970                         StringBuffer_append(buf2, " and responsetime %s %s", operatornames[o->responsetime.operator], Convert_time2str(o->responsetime.limit, (char[11]){}));
  971                 printf(" %-20s = %s\n", "Unix Socket", StringBuffer_toString(Util_printRule(o->check_invers, buf, o->action, "%s", StringBuffer_toString(buf2))));
  972         }
  973 
  974         for (Timestamp_T o = s->timestamplist; o; o = o->next) {
  975                 StringBuffer_clear(buf);
  976                 printf(" %-20s = %s\n", timestampnames[o->type],
  977                        o->test_changes
  978                        ?
  979                        StringBuffer_toString(Util_printRule(false, buf, o->action, "if changed"))
  980                        :
  981                        StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s", operatornames[o->operator], Convert_time2str(o->time * 1000., (char[11]){})))
  982                        );
  983         }
  984 
  985         for (Size_T o = s->sizelist; o; o = o->next) {
  986                 StringBuffer_clear(buf);
  987                 printf(" %-20s = %s\n", "Size",
  988                        o->test_changes
  989                        ?
  990                        StringBuffer_toString(Util_printRule(false, buf, o->action, "if changed"))
  991                        :
  992                        StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %llu byte(s)", operatornames[o->operator], o->size))
  993                        );
  994         }
  995 
  996         for (LinkStatus_T o = s->linkstatuslist; o; o = o->next) {
  997                 StringBuffer_clear(buf);
  998                 printf(" %-20s = %s\n", "Link status", StringBuffer_toString(Util_printRule(o->check_invers, buf, o->action, "if %s", o->check_invers ? "up" : "down")));
  999         }
 1000 
 1001         for (LinkSpeed_T o = s->linkspeedlist; o; o = o->next) {
 1002                 StringBuffer_clear(buf);
 1003                 printf(" %-20s = %s\n", "Link capacity", StringBuffer_toString(Util_printRule(false, buf, o->action, "if changed")));
 1004         }
 1005 
 1006         for (LinkSaturation_T o = s->linksaturationlist; o; o = o->next) {
 1007                 StringBuffer_clear(buf);
 1008                 printf(" %-20s = %s\n", "Link utilization", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit)));
 1009         }
 1010 
 1011         for (Bandwidth_T o = s->uploadbyteslist; o; o = o->next) {
 1012                 StringBuffer_clear(buf);
 1013                 if (o->range == Time_Second) {
 1014                         printf(" %-20s = %s\n", "Upload bytes", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s/s", operatornames[o->operator], Convert_bytes2str(o->limit, buffer))));
 1015                 } else {
 1016                         printf(" %-20s = %s\n", "Total upload bytes", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s in last %d %s(s)", operatornames[o->operator], Convert_bytes2str(o->limit, buffer), o->rangecount, Util_timestr(o->range))));
 1017                 }
 1018         }
 1019 
 1020         for (Bandwidth_T o = s->uploadpacketslist; o; o = o->next) {
 1021                 StringBuffer_clear(buf);
 1022                 if (o->range == Time_Second) {
 1023                         printf(" %-20s = %s\n", "Upload packets", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld packets/s", operatornames[o->operator], o->limit)));
 1024                 } else {
 1025                         printf(" %-20s = %s\n", "Total upload packets", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld packets in last %d %s(s)", operatornames[o->operator], o->limit, o->rangecount, Util_timestr(o->range))));
 1026                 }
 1027         }
 1028 
 1029         for (Bandwidth_T o = s->downloadbyteslist; o; o = o->next) {
 1030                 StringBuffer_clear(buf);
 1031                 if (o->range == Time_Second) {
 1032                         printf(" %-20s = %s\n", "Download bytes", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s/s", operatornames[o->operator], Convert_bytes2str(o->limit, buffer))));
 1033                 } else {
 1034                         printf(" %-20s = %s\n", "Total download bytes", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s in last %d %s(s)", operatornames[o->operator], Convert_bytes2str(o->limit, buffer), o->rangecount, Util_timestr(o->range))));
 1035                 }
 1036         }
 1037 
 1038         for (Bandwidth_T o = s->downloadpacketslist; o; o = o->next) {
 1039                 StringBuffer_clear(buf);
 1040                 if (o->range == Time_Second) {
 1041                         printf(" %-20s = %s\n", "Download packets", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld packets/s", operatornames[o->operator], o->limit)));
 1042                 } else {
 1043                         printf(" %-20s = %s\n", "Total downl. packets", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld packets in last %d %s(s)", operatornames[o->operator], o->limit, o->rangecount, Util_timestr(o->range))));
 1044                 }
 1045         }
 1046 
 1047         for (Uptime_T o = s->uptimelist; o; o = o->next) {
 1048                 StringBuffer_clear(buf);
 1049                 printf(" %-20s = %s\n", "Uptime", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %llu second(s)", operatornames[o->operator], o->uptime)));
 1050         }
 1051 
 1052         if (s->type != Service_Process) {
 1053                 for (Match_T o = s->matchignorelist; o; o = o->next) {
 1054                         StringBuffer_clear(buf);
 1055                         printf(" %-20s = %s\n", "Ignore content", StringBuffer_toString(Util_printRule(false, buf, o->action, "if content %s \"%s\"", o->not ? "!=" : "=", o->match_string)));
 1056                 }
 1057                 for (Match_T o = s->matchlist; o; o = o->next) {
 1058                         StringBuffer_clear(buf);
 1059                         printf(" %-20s = %s\n", "Content", StringBuffer_toString(Util_printRule(false, buf, o->action, "if content %s \"%s\"", o->not ? "!=" : "=", o->match_string)));
 1060                 }
 1061         }
 1062 
 1063         for (FileSystem_T o = s->filesystemlist; o; o = o->next) {
 1064                 StringBuffer_clear(buf);
 1065                 if (o->resource == Resource_Inode) {
 1066                         printf(" %-20s = %s\n", "Inodes usage limit",
 1067                                o->limit_absolute > -1
 1068                                ?
 1069                                StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld", operatornames[o->operator], o->limit_absolute))
 1070                                :
 1071                                StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit_percent))
 1072                                );
 1073                 } else if (o->resource == Resource_InodeFree) {
 1074                         printf(" %-20s = %s\n", "Inodes free limit",
 1075                                o->limit_absolute > -1
 1076                                ?
 1077                                StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %lld", operatornames[o->operator], o->limit_absolute))
 1078                                :
 1079                                StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit_percent))
 1080                                );
 1081                 } else if (o->resource == Resource_Space) {
 1082                         if (o->limit_absolute > -1) {
 1083                                 printf(" %-20s = %s\n", "Space usage limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s", operatornames[o->operator], Convert_bytes2str(o->limit_absolute, buffer))));
 1084                         } else {
 1085                                printf(" %-20s = %s\n", "Space usage limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit_percent)));
 1086                         }
 1087                 } else if (o->resource == Resource_SpaceFree) {
 1088                         if (o->limit_absolute > -1) {
 1089                                 printf(" %-20s = %s\n", "Space free limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s", operatornames[o->operator], Convert_bytes2str(o->limit_absolute, buffer))));
 1090                         } else {
 1091                                printf(" %-20s = %s\n", "Space free limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit_percent)));
 1092                         }
 1093                 } else if (o->resource == Resource_ReadBytes) {
 1094                         printf(" %-20s = %s\n", "Read limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if read %s %s/s", operatornames[o->operator], Convert_bytes2str(o->limit_absolute, (char[10]){}))));
 1095                 } else if (o->resource == Resource_ReadOperations) {
 1096                         printf(" %-20s = %s\n", "Read limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if read %s %llu operations/s", operatornames[o->operator], o->limit_absolute)));
 1097                 } else if (o->resource == Resource_WriteBytes) {
 1098                         printf(" %-20s = %s\n", "Write limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if write %s %s/s", operatornames[o->operator], Convert_bytes2str(o->limit_absolute, (char[10]){}))));
 1099                 } else if (o->resource == Resource_WriteOperations) {
 1100                         printf(" %-20s = %s\n", "Write limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if write %s %llu operations/s", operatornames[o->operator], o->limit_absolute)));
 1101                 } else if (o->resource == Resource_ServiceTime) {
 1102                         printf(" %-20s = %s\n", "Service time limit", StringBuffer_toString(Util_printRule(false, buf, o->action, "if service time %s %s/operation", operatornames[o->operator], Convert_time2str(o->limit_absolute, (char[11]){}))));
 1103                 }
 1104         }
 1105 
 1106         for (Resource_T o = s->resourcelist; o; o = o->next) {
 1107                 StringBuffer_clear(buf);
 1108                 switch (o->resource_id) {
 1109                         case Resource_CpuPercent:
 1110                                 printf(" %-20s = ", "CPU usage limit");
 1111                                 break;
 1112 
 1113                         case Resource_CpuPercentTotal:
 1114                                 printf(" %-20s = ", "CPU usage limit (incl. children)");
 1115                                 break;
 1116 
 1117                         case Resource_CpuUser:
 1118                                 printf(" %-20s = ", "CPU user limit");
 1119                                 break;
 1120 
 1121                         case Resource_CpuSystem:
 1122                                 printf(" %-20s = ", "CPU system limit");
 1123                                 break;
 1124 
 1125                         case Resource_CpuWait:
 1126                                 printf(" %-20s = ", "CPU I/O wait limit");
 1127                                 break;
 1128 
 1129                         case Resource_CpuNice:
 1130                                 printf(" %-20s = ", "CPU nice limit");
 1131                                 break;
 1132 
 1133                         case Resource_CpuHardIRQ:
 1134                                 printf(" %-20s = ", "CPU hardware IRQ limit");
 1135                                 break;
 1136 
 1137                         case Resource_CpuSoftIRQ:
 1138                                 printf(" %-20s = ", "CPU software IRQ limit");
 1139                                 break;
 1140 
 1141                         case Resource_CpuSteal:
 1142                                 printf(" %-20s = ", "CPU steal limit");
 1143                                 break;
 1144 
 1145                         case Resource_CpuGuest:
 1146                                 printf(" %-20s = ", "CPU guest limit");
 1147                                 break;
 1148 
 1149                         case Resource_CpuGuestNice:
 1150                                 printf(" %-20s = ", "CPU guest nice limit");
 1151                                 break;
 1152 
 1153                         case Resource_MemoryPercent:
 1154                                 printf(" %-20s = ", "Memory usage limit");
 1155                                 break;
 1156 
 1157                         case Resource_MemoryKbyte:
 1158                                 printf(" %-20s = ", "Memory amount limit");
 1159                                 break;
 1160 
 1161                         case Resource_SwapPercent:
 1162                                 printf(" %-20s = ", "Swap usage limit");
 1163                                 break;
 1164 
 1165                         case Resource_SwapKbyte:
 1166                                 printf(" %-20s = ", "Swap amount limit");
 1167                                 break;
 1168 
 1169                         case Resource_LoadAverage1m:
 1170                                 printf(" %-20s = ", "Load avg (1m)");
 1171                                 break;
 1172 
 1173                         case Resource_LoadAverage5m:
 1174                                 printf(" %-20s = ", "Load avg (5m)");
 1175                                 break;
 1176 
 1177                         case Resource_LoadAverage15m:
 1178                                 printf(" %-20s = ", "Load avg (15m)");
 1179                                 break;
 1180 
 1181                         case Resource_LoadAveragePerCore1m:
 1182                                 printf(" %-20s = ", "Load avg/core (1m)");
 1183                                 break;
 1184 
 1185                         case Resource_LoadAveragePerCore5m:
 1186                                 printf(" %-20s = ", "Load avg/core (5m)");
 1187                                 break;
 1188 
 1189                         case Resource_LoadAveragePerCore15m:
 1190                                 printf(" %-20s = ", "Load avg/core (15m)");
 1191                                 break;
 1192 
 1193                         case Resource_Threads:
 1194                                 printf(" %-20s = ", "Threads");
 1195                                 break;
 1196 
 1197                         case Resource_Children:
 1198                                 printf(" %-20s = ", "Children");
 1199                                 break;
 1200 
 1201                         case Resource_MemoryKbyteTotal:
 1202                                 printf(" %-20s = ", "Memory amount limit (incl. children)");
 1203                                 break;
 1204 
 1205                         case Resource_MemoryPercentTotal:
 1206                                 printf(" %-20s = ", "Memory usage limit (incl. children)");
 1207                                 break;
 1208 
 1209                         case Resource_ReadBytes:
 1210                                 printf(" %-20s = ", "Read limit");
 1211                                 break;
 1212 
 1213                         case Resource_ReadBytesPhysical:
 1214                                 printf(" %-20s = ", "Disk read limit");
 1215                                 break;
 1216 
 1217                         case Resource_ReadOperations:
 1218                                 printf(" %-20s = ", "Disk read limit");
 1219                                 break;
 1220 
 1221                         case Resource_WriteBytes:
 1222                                 printf(" %-20s = ", "Write limit");
 1223                                 break;
 1224 
 1225                         case Resource_WriteBytesPhysical:
 1226                                 printf(" %-20s = ", "Disk write limit");
 1227                                 break;
 1228 
 1229                         case Resource_WriteOperations:
 1230                                 printf(" %-20s = ", "Disk write limit");
 1231                                 break;
 1232 
 1233                         default:
 1234                                 break;
 1235                 }
 1236                 switch (o->resource_id) {
 1237                         case Resource_CpuPercent:
 1238                         case Resource_CpuPercentTotal:
 1239                         case Resource_MemoryPercentTotal:
 1240                         case Resource_CpuUser:
 1241                         case Resource_CpuSystem:
 1242                         case Resource_CpuWait:
 1243                         case Resource_CpuNice:
 1244                         case Resource_CpuHardIRQ:
 1245                         case Resource_CpuSoftIRQ:
 1246                         case Resource_CpuSteal:
 1247                         case Resource_CpuGuest:
 1248                         case Resource_CpuGuestNice:
 1249                         case Resource_MemoryPercent:
 1250                         case Resource_SwapPercent:
 1251                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f%%", operatornames[o->operator], o->limit)));
 1252                                 break;
 1253 
 1254                         case Resource_MemoryKbyte:
 1255                         case Resource_SwapKbyte:
 1256                         case Resource_MemoryKbyteTotal:
 1257                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s", operatornames[o->operator], Convert_bytes2str(o->limit, buffer))));
 1258                                 break;
 1259 
 1260                         case Resource_LoadAverage1m:
 1261                         case Resource_LoadAverage5m:
 1262                         case Resource_LoadAverage15m:
 1263                         case Resource_LoadAveragePerCore1m:
 1264                         case Resource_LoadAveragePerCore5m:
 1265                         case Resource_LoadAveragePerCore15m:
 1266                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.1f", operatornames[o->operator], o->limit)));
 1267                                 break;
 1268 
 1269                         case Resource_Threads:
 1270                         case Resource_Children:
 1271                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.0f", operatornames[o->operator], o->limit)));
 1272                                 break;
 1273 
 1274                         case Resource_ReadBytes:
 1275                         case Resource_WriteBytes:
 1276                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s/s", operatornames[o->operator], Convert_bytes2str(o->limit, (char[10]){}))));
 1277                                 break;
 1278 
 1279                         case Resource_ReadBytesPhysical:
 1280                         case Resource_WriteBytesPhysical:
 1281                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %s/s", operatornames[o->operator], Convert_bytes2str(o->limit, (char[10]){}))));
 1282                                 break;
 1283 
 1284                         case Resource_ReadOperations:
 1285                         case Resource_WriteOperations:
 1286                                 printf("%s", StringBuffer_toString(Util_printRule(false, buf, o->action, "if %s %.0f operations/s", operatornames[o->operator], o->limit)));
 1287                                 break;
 1288 
 1289                         default:
 1290                                 break;
 1291                 }
 1292                 printf("\n");
 1293         }
 1294 
 1295         if (s->every.type == Every_SkipCycles)
 1296                 printf(" %-20s = Check service every %d cycles\n", "Every", s->every.spec.cycle.number);
 1297         else if (s->every.type == Every_Cron)
 1298                 printf(" %-20s = Check service every %s\n", "Every", s->every.spec.cron);
 1299         else if (s->every.type == Every_NotInCron)
 1300                 printf(" %-20s = Don't check service every %s\n", "Every", s->every.spec.cron);
 1301 
 1302         for (ActionRate_T o = s->actionratelist; o; o = o->next) {
 1303                 StringBuffer_clear(buf);
 1304                 printf(" %-20s = If restarted %d times within %d cycle(s) then %s\n", "Timeout", o->count, o->cycle, StringBuffer_toString(Util_printAction(o->action->failed, buf)));
 1305         }
 1306 
 1307         for (Mail_T o = s->maillist; o; o = o->next) {
 1308                 printf(" %-20s = %s\n", "Alert mail to", is_str_defined(o->to));
 1309                 printf("   %-18s = ", "Alert on");
 1310                 printevents(o->events);
 1311                 if (o->reminder)
 1312                         printf("   %-18s = %u cycles\n", "Alert reminder", o->reminder);
 1313         }
 1314 
 1315         printf("\n");
 1316 
 1317         StringBuffer_free(&buf);
 1318 }
 1319 
 1320 
 1321 void Util_printServiceList() {
 1322         Service_T s;
 1323         char ruler[STRLEN];
 1324 
 1325         printf("The service list contains the following entries:\n\n");
 1326 
 1327         for (s = servicelist_conf; s; s = s->next_conf)
 1328                 Util_printService(s);
 1329 
 1330         memset(ruler, '-', STRLEN);
 1331         printf("%-.79s\n", ruler);
 1332 }
 1333 
 1334 
 1335 char *Util_getToken(MD_T token) {
 1336         md5_context_t ctx;
 1337         char buf[STRLEN] = {};
 1338         MD_T digest;
 1339         System_random(buf, sizeof(buf));
 1340         md5_init(&ctx);
 1341         md5_append(&ctx, (const md5_byte_t *)buf, STRLEN - 1);
 1342         md5_finish(&ctx, (md5_byte_t *)digest);
 1343         Checksum_digest2Bytes((unsigned char *)digest, 16, token);
 1344         return token;
 1345 }
 1346 
 1347 
 1348 char *Util_monitId(char *idfile) {
 1349         ASSERT(idfile);
 1350         FILE *file = NULL;
 1351         if (! File_exist(idfile)) {
 1352                 // Generate the unique id
 1353                 file = fopen(idfile, "w");
 1354                 if (! file) {
 1355                         Log_error("Error opening the idfile '%s' -- %s\n", idfile, STRERROR);
 1356                         return NULL;
 1357                 }
 1358                 fprintf(file, "%s", Util_getToken(Run.id));
 1359                 Log_info(" New Monit id: %s\n Stored in '%s'\n", Run.id, idfile);
 1360         } else {
 1361                 if (! File_isFile(idfile)) {
 1362                         Log_error("idfile '%s' is not a regular file\n", idfile);
 1363                         return NULL;
 1364                 }
 1365                 if ((file = fopen(idfile,"r")) == (FILE *)NULL) {
 1366                         Log_error("Error opening the idfile '%s' -- %s\n", idfile, STRERROR);
 1367                         return NULL;
 1368                 }
 1369                 if (fscanf(file, "%64s", Run.id) != 1) {
 1370                         Log_error("Error reading id from file '%s'\n", idfile);
 1371                         if (fclose(file))
 1372                                 Log_error("Error closing file '%s' -- %s\n", idfile, STRERROR);
 1373                         return NULL;
 1374                 }
 1375         }
 1376         if (fclose(file))
 1377                 Log_error("Error closing file '%s' -- %s\n", idfile, STRERROR);
 1378 
 1379         return Run.id;
 1380 }
 1381 
 1382 
 1383 pid_t Util_getPid(char *pidfile) {
 1384         FILE *file = NULL;
 1385         int pid = -1;
 1386 
 1387         ASSERT(pidfile);
 1388 
 1389         if (! File_exist(pidfile)) {
 1390                 DEBUG("pidfile '%s' does not exist\n", pidfile);
 1391                 return 0;
 1392         }
 1393         if (! File_isFile(pidfile)) {
 1394                 DEBUG("pidfile '%s' is not a regular file\n", pidfile);
 1395                 return 0;
 1396         }
 1397         if ((file = fopen(pidfile,"r")) == (FILE *)NULL) {
 1398                 DEBUG("Error opening the pidfile '%s' -- %s\n", pidfile, STRERROR);
 1399                 return 0;
 1400         }
 1401         if (fscanf(file, "%d", &pid) != 1) {
 1402                 DEBUG("Error reading pid from file '%s'\n", pidfile);
 1403                 if (fclose(file))
 1404                         DEBUG("Error closing file '%s' -- %s\n", pidfile, STRERROR);
 1405                 return 0;
 1406         }
 1407         if (fclose(file))
 1408                 DEBUG("Error closing file '%s' -- %s\n", pidfile, STRERROR);
 1409 
 1410         if (pid < 0)
 1411                 return(0);
 1412 
 1413         return (pid_t)pid;
 1414 
 1415 }
 1416 
 1417 
 1418 bool Util_isurlsafe(const char *url) {
 1419         ASSERT(url && *url);
 1420         for (int i = 0; url[i]; i++)
 1421                 if (urlunsafe[(unsigned char)url[i]])
 1422                         return false;
 1423         return true;
 1424 }
 1425 
 1426 
 1427 char *Util_urlEncode(char *string, bool isParameterValue) {
 1428         char *escaped = NULL;
 1429         if (string) {
 1430                 char *p;
 1431                 int i, n;
 1432                 const unsigned char *unsafe = isParameterValue ? urlunsafeparameter : urlunsafe;
 1433                 for (n = i = 0; string[i]; i++)
 1434                         if (unsafe[(unsigned char)(string[i])])
 1435                                 n += 2;
 1436                 p = escaped = ALLOC(i + n + 1);
 1437                 for (; *string; string++, p++) {
 1438                         if (unsafe[(unsigned char)(*p = *string)]) {
 1439                                 *p++ = '%';
 1440                                 *p++ = b2x[(unsigned char)(*string)][0];
 1441                                 *p = b2x[(unsigned char)(*string)][1];
 1442                         }
 1443                 }
 1444                 *p = 0;
 1445         }
 1446         return escaped;
 1447 }
 1448 
 1449 
 1450 char *Util_urlDecode(char *url) {
 1451         if (url && *url) {
 1452                 register int x, y;
 1453                 for (x = 0, y = 0; url[y]; x++, y++) {
 1454                         if (url[y] == '+') {
 1455                                 url[x] = ' ';
 1456                         } else if (url[y] == '%') {
 1457                                 if (! url[y + 1] || ! url[y + 2])
 1458                                         break;
 1459                                 url[x] = _x2c(url + y + 1);
 1460                                 y += 2;
 1461                         } else {
 1462                                 url[x] = url[y];
 1463                         }
 1464                 }
 1465                 url[x] = 0;
 1466         }
 1467         return url;
 1468 }
 1469 
 1470 
 1471 char *Util_getBasicAuthHeader(char *username, char *password) {
 1472         char *auth, *b64;
 1473         char  buf[STRLEN];
 1474 
 1475         if (! username)
 1476                 return NULL;
 1477 
 1478         snprintf(buf, STRLEN, "%s:%s", username, password ? password : "");
 1479         if (! (b64 = encode_base64(strlen(buf), (unsigned char *)buf)) ) {
 1480                 Log_error("Failed to base64 encode authentication header\n");
 1481                 return NULL;
 1482         }
 1483         auth = CALLOC(sizeof(char), STRLEN + 1);
 1484         snprintf(auth, STRLEN, "Authorization: Basic %s\r\n", b64);
 1485         FREE(b64);
 1486         return auth;
 1487 }
 1488 
 1489 
 1490 void Util_redirectStdFds() {
 1491         for (int i = 0; i < 3; i++) {
 1492                 if (close(i) == -1 || open("/dev/null", O_RDWR) != i) {
 1493                         Log_error("Cannot reopen standard file descriptor (%d) -- %s\n", i, STRERROR);
 1494                 }
 1495         }
 1496 }
 1497 
 1498 
 1499 void Util_closeFds() {
 1500         for (int i = 3, descriptors = System_getDescriptorsGuarded(); i < descriptors; i++) {
 1501                 close(i);
 1502         }
 1503         errno = 0;
 1504 }
 1505 
 1506 
 1507 Auth_T Util_getUserCredentials(char *uname) {
 1508         /* check allowed user names */
 1509         for (Auth_T c = Run.httpd.credentials; c; c = c->next)
 1510                 if (c->uname && IS(c->uname, uname))
 1511                         return c;
 1512 
 1513 #ifdef HAVE_LIBPAM
 1514         /* check allowed group names */
 1515         return(PAMcheckUserGroup(uname));
 1516 #else
 1517         return NULL;
 1518 #endif
 1519 }
 1520 
 1521 
 1522 bool Util_checkCredentials(char *uname, char *outside) {
 1523         Auth_T c = Util_getUserCredentials(uname);
 1524         char outside_crypt[STRLEN];
 1525         if (c == NULL)
 1526                 return false;
 1527         switch (c->digesttype) {
 1528                 case Digest_Cleartext:
 1529                         outside_crypt[sizeof(outside_crypt) - 1] = 0;
 1530                         strncpy(outside_crypt, outside, sizeof(outside_crypt) - 1);
 1531                         break;
 1532                 case Digest_Md5:
 1533                 {
 1534                         char id[STRLEN];
 1535                         char salt[STRLEN];
 1536                         char *temp;
 1537                         /* A password looks like this,
 1538                          *   $id$salt$digest
 1539                          * the '$' around the id are still part of the id.
 1540                          */
 1541                         id[sizeof(id) - 1] = 0;
 1542                         strncpy(id, c->passwd, sizeof(id) - 1);
 1543                         if (! (temp = strchr(id + 1, '$'))) {
 1544                                 Log_error("Password not in MD5 format.\n");
 1545                                 return false;
 1546                         }
 1547                         temp += 1;
 1548                         *temp = '\0';
 1549                         salt[sizeof(salt) - 1] = 0;
 1550                         strncpy(salt, c->passwd + strlen(id), sizeof(salt) - 1);
 1551                         if (! (temp = strchr(salt, '$'))) {
 1552                                 Log_error("Password not in MD5 format.\n");
 1553                                 return false;
 1554                         }
 1555                         *temp = '\0';
 1556                         if (md5_crypt(outside, id, salt, outside_crypt, sizeof(outside_crypt)) == NULL) {
 1557                                 Log_error("Cannot generate MD5 digest error.\n");
 1558                                 return false;
 1559                         }
 1560                         break;
 1561                 }
 1562                 case Digest_Crypt:
 1563                 {
 1564                         char salt[3];
 1565                         char *temp;
 1566                         snprintf(salt, 3, "%c%c", c->passwd[0], c->passwd[1]);
 1567                         temp = crypt(outside, salt);
 1568                         outside_crypt[sizeof(outside_crypt) - 1] = 0;
 1569                         strncpy(outside_crypt, temp, sizeof(outside_crypt) - 1);
 1570                         break;
 1571                 }
 1572 #ifdef HAVE_LIBPAM
 1573                 case Digest_Pam:
 1574                         return PAMcheckPasswd(uname, outside);
 1575                         break;
 1576 #endif
 1577                 default:
 1578                         Log_error("Unknown password digestion method.\n");
 1579                         return false;
 1580         }
 1581         if (Str_compareConstantTime(outside_crypt, c->passwd) == 0)
 1582                 return true;
 1583         return false;
 1584 }
 1585 
 1586 
 1587 static void _resetIOStatistics(IOStatistics_T S) {
 1588         Statistics_reset(&(S->operations));
 1589         Statistics_reset(&(S->bytes));
 1590 }
 1591 
 1592 
 1593 void Util_resetInfo(Service_T s) {
 1594         switch (s->type) {
 1595                 case Service_Filesystem:
 1596                         s->inf.filesystem->f_bsize = 0LL;
 1597                         s->inf.filesystem->f_blocks = 0LL;
 1598                         s->inf.filesystem->f_blocksfree = 0LL;
 1599                         s->inf.filesystem->f_blocksfreetotal = 0LL;
 1600                         s->inf.filesystem->f_blocksused = 0LL;
 1601                         s->inf.filesystem->f_files = 0LL;
 1602                         s->inf.filesystem->f_filesfree = 0LL;
 1603                         s->inf.filesystem->f_filesused = 0LL;
 1604                         s->inf.filesystem->inode_percent = 0.;
 1605                         s->inf.filesystem->space_percent = 0.;
 1606                         s->inf.filesystem->flagsChanged = false;
 1607                         *(s->inf.filesystem->flags) = 0;
 1608                         s->inf.filesystem->mode = -1;
 1609                         s->inf.filesystem->uid = -1;
 1610                         s->inf.filesystem->gid = -1;
 1611                         _resetIOStatistics(&(s->inf.filesystem->read));
 1612                         _resetIOStatistics(&(s->inf.filesystem->write));
 1613                         Statistics_reset(&(s->inf.filesystem->time.read));
 1614                         Statistics_reset(&(s->inf.filesystem->time.write));
 1615                         Statistics_reset(&(s->inf.filesystem->time.wait));
 1616                         Statistics_reset(&(s->inf.filesystem->time.run));
 1617                         break;
 1618                 case Service_File:
 1619                         s->inf.file->size  = -1;
 1620                         s->inf.file->readpos = 0;
 1621                         s->inf.file->inode = 0;
 1622                         s->inf.file->inode_prev = 0;
 1623                         s->inf.file->mode = -1;
 1624                         s->inf.file->uid = -1;
 1625                         s->inf.file->gid = -1;
 1626                         s->inf.file->timestamp.access = 0;
 1627                         s->inf.file->timestamp.change = 0;
 1628                         s->inf.file->timestamp.modify = 0;
 1629                         *s->inf.file->cs_sum = 0;
 1630                         break;
 1631                 case Service_Directory:
 1632                         s->inf.directory->mode = -1;
 1633                         s->inf.directory->uid = -1;
 1634                         s->inf.directory->gid = -1;
 1635                         s->inf.directory->timestamp.access = 0;
 1636                         s->inf.directory->timestamp.change = 0;
 1637                         s->inf.directory->timestamp.modify = 0;
 1638                         break;
 1639                 case Service_Fifo:
 1640                         s->inf.fifo->mode = -1;
 1641                         s->inf.fifo->uid = -1;
 1642                         s->inf.fifo->gid = -1;
 1643                         s->inf.fifo->timestamp.access = 0;
 1644                         s->inf.fifo->timestamp.change = 0;
 1645                         s->inf.fifo->timestamp.modify = 0;
 1646                         break;
 1647                 case Service_Process:
 1648                         s->inf.process->_pid = -1;
 1649                         s->inf.process->_ppid = -1;
 1650                         s->inf.process->pid = -1;
 1651                         s->inf.process->ppid = -1;
 1652                         s->inf.process->uid = -1;
 1653                         s->inf.process->euid = -1;
 1654                         s->inf.process->gid = -1;
 1655                         s->inf.process->zombie = false;
 1656                         s->inf.process->threads = -1;
 1657                         s->inf.process->children = -1;
 1658                         s->inf.process->mem = 0ULL;
 1659                         s->inf.process->total_mem = 0ULL;
 1660                         s->inf.process->mem_percent = -1.;
 1661                         s->inf.process->total_mem_percent = -1.;
 1662                         s->inf.process->cpu_percent = -1.;
 1663                         s->inf.process->total_cpu_percent = -1.;
 1664                         s->inf.process->uptime = -1;
 1665                         s->inf.process->filedescriptors.open = -1LL;
 1666                         s->inf.process->filedescriptors.openTotal = -1LL;
 1667                         *(s->inf.process->secattr) = 0;
 1668                         _resetIOStatistics(&(s->inf.process->read));
 1669                         _resetIOStatistics(&(s->inf.process->write));
 1670                         break;
 1671                 case Service_Net:
 1672                         if (s->inf.net->stats)
 1673                                 Link_reset(s->inf.net->stats);
 1674                         break;
 1675                 default:
 1676                         break;
 1677         }
 1678 }
 1679 
 1680 
 1681 bool Util_hasServiceStatus(Service_T s) {
 1682         return((s->monitor & Monitor_Yes) && ! (s->error & Event_NonExist) && ! (s->error & Event_Data));
 1683 }
 1684 
 1685 
 1686 char *Util_getHTTPHostHeader(Socket_T s, char *hostBuf, int len) {
 1687         int port = Socket_getRemotePort(s);
 1688         const char *host = Socket_getRemoteHost(s);
 1689         bool ipv6 = Str_sub(host, ":") ? true : false;
 1690         if (port == 80 || port == 443)
 1691                 snprintf(hostBuf, len, "%s%s%s", ipv6 ? "[" : "", host, ipv6 ? "]" : "");
 1692         else
 1693                 snprintf(hostBuf, len, "%s%s%s:%d", ipv6 ? "[" : "", host, ipv6 ? "]" : "", port);
 1694         return hostBuf;
 1695 }
 1696 
 1697 
 1698 bool Util_evalQExpression(Operator_Type operator, long long left, long long right) {
 1699         switch (operator) {
 1700                 case Operator_Greater:
 1701                         if (left > right)
 1702                                 return true;
 1703                         break;
 1704                 case Operator_GreaterOrEqual:
 1705                         if (left >= right)
 1706                                 return true;
 1707                         break;
 1708                 case Operator_Less:
 1709                         if (left < right)
 1710                                 return true;
 1711                         break;
 1712                 case Operator_LessOrEqual:
 1713                         if (left <= right)
 1714                                 return true;
 1715                         break;
 1716                 case Operator_Equal:
 1717                         if (left == right)
 1718                                 return true;
 1719                         break;
 1720                 case Operator_NotEqual:
 1721                 case Operator_Changed:
 1722                         if (left != right)
 1723                                 return true;
 1724                         break;
 1725                 default:
 1726                         Log_error("Unknown comparison operator\n");
 1727                         return false;
 1728         }
 1729         return false;
 1730 }
 1731 
 1732 
 1733 bool Util_evalDoubleQExpression(Operator_Type operator, double left, double right) {
 1734         switch (operator) {
 1735                 case Operator_Greater:
 1736                         if (left > right)
 1737                                 return true;
 1738                         break;
 1739                 case Operator_GreaterOrEqual:
 1740                         if (left >= right)
 1741                                 return true;
 1742                         break;
 1743                 case Operator_Less:
 1744                         if (left < right)
 1745                                 return true;
 1746                         break;
 1747                 case Operator_LessOrEqual:
 1748                         if (left <= right)
 1749                                 return true;
 1750                         break;
 1751                 case Operator_Equal:
 1752                         if (left == right)
 1753                                 return true;
 1754                         break;
 1755                 case Operator_NotEqual:
 1756                 case Operator_Changed:
 1757                         if (left != right)
 1758                                 return true;
 1759                         break;
 1760                 default:
 1761                         Log_error("Unknown comparison operator\n");
 1762                         return false;
 1763         }
 1764         return false;
 1765 }
 1766 
 1767 
 1768 void Util_monitorSet(Service_T s) {
 1769         ASSERT(s);
 1770         if (s->monitor == Monitor_Not) {
 1771                 s->monitor = Monitor_Init;
 1772                 DEBUG("'%s' monitoring enabled\n", s->name);
 1773                 State_dirty();
 1774         }
 1775 }
 1776 
 1777 
 1778 void Util_monitorUnset(Service_T s) {
 1779         ASSERT(s);
 1780         if (s->monitor != Monitor_Not) {
 1781                 s->monitor = Monitor_Not;
 1782                 DEBUG("'%s' monitoring disabled\n", s->name);
 1783         }
 1784         s->nstart = 0;
 1785         s->ncycle = 0;
 1786         if (s->every.type == Every_SkipCycles)
 1787                 s->every.spec.cycle.counter = 0;
 1788         s->error = Event_Null;
 1789         if (s->eventlist)
 1790                 gc_event(&s->eventlist);
 1791         Util_resetInfo(s);
 1792         State_dirty();
 1793 }
 1794 
 1795 
 1796 int Util_getAction(const char *action) {
 1797         int i = 1; /* the Action_Ignored has index 0 => we will start on next item */
 1798 
 1799         ASSERT(action);
 1800 
 1801         while (strlen(actionnames[i])) {
 1802                 if (IS(action, actionnames[i]))
 1803                         return i;
 1804                 i++;
 1805         }
 1806         /* the action was not found */
 1807         return Action_Ignored;
 1808 }
 1809 
 1810 
 1811 StringBuffer_T Util_printAction(Action_T A, StringBuffer_T buf) {
 1812         StringBuffer_append(buf, "%s", actionnames[A->id]);
 1813         if (A->id == Action_Exec) {
 1814                 command_t C = A->exec;
 1815                 for (int i = 0; C->arg[i]; i++)
 1816                         StringBuffer_append(buf, "%s%s", i ? " " : " '", C->arg[i]);
 1817                 StringBuffer_append(buf, "'");
 1818                 if (C->has_uid)
 1819                         StringBuffer_append(buf, " as uid %d", C->uid);
 1820                 if (C->has_gid)
 1821                         StringBuffer_append(buf, " as gid %d", C->gid);
 1822                 if (C->timeout)
 1823                         StringBuffer_append(buf, " timeout %d cycle(s)", C->timeout);
 1824                 if (A->repeat)
 1825                         StringBuffer_append(buf, " repeat every %d cycle(s)", A->repeat);
 1826         }
 1827         return buf;
 1828 }
 1829 
 1830 
 1831 StringBuffer_T Util_printEventratio(Action_T action, StringBuffer_T buf) {
 1832         if (action->cycles > 1) {
 1833                 if (action->count == action->cycles)
 1834                         StringBuffer_append(buf, "for %d cycles ", action->cycles);
 1835                 else
 1836                         StringBuffer_append(buf, "for %d times within %d cycles ", action->count, action->cycles);
 1837         }
 1838         return buf;
 1839 }
 1840 
 1841 
 1842 StringBuffer_T Util_printRule(bool inverse, StringBuffer_T buf, EventAction_T action, const char *rule, ...) {
 1843         ASSERT(buf);
 1844         ASSERT(action);
 1845         ASSERT(rule);
 1846         // Variable part
 1847         va_list ap;
 1848         va_start(ap, rule);
 1849         StringBuffer_vappend(buf, rule, ap);
 1850         va_end(ap);
 1851         // Constant part (failure action)
 1852         StringBuffer_append(buf, " ");
 1853         Util_printEventratio(action->failed, buf);
 1854         StringBuffer_append(buf, "then ");
 1855         Util_printAction(action->failed, buf);
 1856         // Print the success part only if it's non default action (alert is implicit => skipped for simpler output)
 1857         if (action->succeeded->id != Action_Ignored && action->succeeded->id != Action_Alert) {
 1858                 StringBuffer_append(buf, " else if ");
 1859                 StringBuffer_append(buf, inverse ? "failed " : "succeeded ");
 1860                 Util_printEventratio(action->succeeded, buf);
 1861                 StringBuffer_append(buf, "then ");
 1862                 Util_printAction(action->succeeded, buf);
 1863         }
 1864         return buf;
 1865 }
 1866 
 1867 
 1868 const char *Util_portIpDescription(Port_T p) {
 1869         switch (p->family) {
 1870                 case Socket_Ip:
 1871                         return "IP";
 1872                 case Socket_Ip4:
 1873                         return "IPv4";
 1874                 case Socket_Ip6:
 1875                         return "IPv6";
 1876                 default:
 1877                         return "UNKNOWN";
 1878         }
 1879 }
 1880 
 1881 
 1882 const char *Util_portTypeDescription(Port_T p) {
 1883         switch (p->type) {
 1884                 case Socket_Tcp:
 1885                         return "TCP";
 1886                 case Socket_Udp:
 1887                         return "UDP";
 1888                 default:
 1889                         return "UNKNOWN";
 1890         }
 1891 }
 1892 
 1893 
 1894 const char *Util_portRequestDescription(Port_T p) {
 1895         const char *request = "";
 1896         if (p->protocol->check == check_http && p->parameters.http.request)
 1897                 request = p->parameters.http.request;
 1898         else if (p->protocol->check == check_websocket && p->parameters.websocket.request)
 1899                 request = p->parameters.websocket.request;
 1900         return request;
 1901 }
 1902 
 1903 
 1904 char *Util_portDescription(Port_T p, char *buf, int bufsize) {
 1905         if (p->family == Socket_Ip || p->family == Socket_Ip4 || p->family == Socket_Ip6) {
 1906                 snprintf(buf, bufsize, "[%s]:%d%s [%s/%s%s]", p->hostname, p->target.net.port, Util_portRequestDescription(p), Util_portTypeDescription(p), Util_portIpDescription(p), p->target.net.ssl.options.flags ? " TLS" : "");
 1907         } else if (p->family == Socket_Unix) {
 1908                 snprintf(buf, bufsize, "%s", p->target.unix.pathname);
 1909         } else {
 1910                 *buf = 0;
 1911         }
 1912         return buf;
 1913 }
 1914 
 1915 
 1916 char *Util_commandDescription(command_t command, char s[STRLEN]) {
 1917         ASSERT(s);
 1918         ASSERT(command);
 1919         int len = 0;
 1920         for (int i = 0; command->arg[i] && len < STRLEN - 1; i++) {
 1921                 len += snprintf(s + len, STRLEN - len, "%s%s", i ? " " : "", command->arg[i]);
 1922         }
 1923         if (len >= STRLEN - 1)
 1924                 snprintf(s + STRLEN - 3 - 1, 4, "...");
 1925         return s;
 1926 }
 1927 
 1928 
 1929 const char *Util_timestr(int time) {
 1930         int i = 0;
 1931         struct mytimetable {
 1932                 int id;
 1933                 const char *description;
 1934         } tt[]= {
 1935                 {Time_Second, "second"},
 1936                 {Time_Minute, "minute"},
 1937                 {Time_Hour,   "hour"},
 1938                 {Time_Day,    "day"},
 1939                 {Time_Month,  "month"},
 1940                 {0}
 1941         };
 1942         do {
 1943                 if (time == tt[i].id)
 1944                         return tt[i].description;
 1945         } while (tt[++i].description);
 1946         return NULL;
 1947 }
 1948