Beispiel #1
0
void SetPolicyServer(EvalContext *ctx, const char *new_policy_server)
{
    if (new_policy_server)
    {
        snprintf(POLICY_SERVER, CF_MAX_IP_LEN, "%s", new_policy_server);
        ScopeNewSpecial(ctx, "sys", "policy_hub", new_policy_server, DATA_TYPE_STRING);
    }
    else
    {
        POLICY_SERVER[0] = '\0';
        ScopeNewSpecial(ctx, "sys", "policy_hub", "undefined", DATA_TYPE_STRING);
    }

    // Get the timestamp on policy update
    struct stat sb;
    {
        char cf_promises_validated_filename[CF_MAXVARSIZE];
        snprintf(cf_promises_validated_filename, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR);
        MapName(cf_promises_validated_filename);

        if ((stat(cf_promises_validated_filename, &sb)) != 0)
        {
            return;
        }
    }
    
    char timebuf[26];
    cf_strtimestamp_local(sb.st_mtime, timebuf);
    
    ScopeNewSpecial(ctx, "sys", "last_policy_update", timebuf, DATA_TYPE_STRING);
}
Beispiel #2
0
static bool ShowHost(const char *hostkey, const char *address, bool incoming,
                     const KeyHostSeen *quality, void *ctx)
{
    int *count = ctx;
    char timebuf[26];

    char hostname[CF_BUFSIZE];
    strlcpy(hostname, IPString2Hostname(address), CF_BUFSIZE);

    (*count)++;
    printf("%-10.10s %-17.17s %-25.25s %-26.26s %-s\n", incoming ? "Incoming" : "Outgoing",
           address, hostname, cf_strtimestamp_local(quality->lastseen, timebuf), hostkey);

    return true;
}
Beispiel #3
0
bool ShowHost(const char *hostkey, const char *address, bool incoming,
                     const KeyHostSeen *quality, void *ctx)
{
    int *count = ctx;
    char timebuf[26];

    char hostname[MAXHOSTNAMELEN];
    int ret = IPString2Hostname(hostname, address, sizeof(hostname));

    (*count)++;
    printf("%-10.10s %-17.17s %-25.25s %-26.26s %-s\n",
           incoming ? "Incoming" : "Outgoing",
           address, (ret != -1) ? hostname : "-",
           cf_strtimestamp_local(quality->lastseen, timebuf), hostkey);

    return true;
}
Beispiel #4
0
void UpdateLastPolicyUpdateTime(EvalContext *ctx)
{
    // Get the timestamp on policy update
    struct stat sb;
    {
        char cf_promises_validated_filename[CF_MAXVARSIZE];
        snprintf(cf_promises_validated_filename, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR);
        MapName(cf_promises_validated_filename);

        if ((stat(cf_promises_validated_filename, &sb)) != 0)
        {
            return;
        }
    }
    
    char timebuf[26];
    cf_strtimestamp_local(sb.st_mtime, timebuf);
    
    EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "last_policy_update", timebuf, DATA_TYPE_STRING, "source=agent");
}
Beispiel #5
0
/**
 * @brief Writes a file with a contained timestamp to mark a policy file as validated
 * @return True if successful.
 */
static bool WritePolicyValidatedFile(const GenericAgentConfig *config)
{
    char filename[CF_MAXVARSIZE];

    if (MINUSF)
    {
        snprintf(filename, CF_MAXVARSIZE, "%s/state/validated_%s", CFWORKDIR, CanonifyName(config->original_input_file));
        MapName(filename);
    }
    else
    {
        snprintf(filename, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR);
        MapName(filename);
    }

    if (!MakeParentDirectory(filename, true))
    {
        Log(LOG_LEVEL_ERR, "While writing policy validated marker file '%s', could not create directory (MakeParentDirectory: %s)", filename, GetErrorStr());
        return false;
    }

    int fd = creat(filename, 0600);
    if (fd == -1)
    {
        Log(LOG_LEVEL_ERR, "While writing policy validated marker file '%s', could not create file (creat: %s)", filename, GetErrorStr());
        return false;
    }

    FILE *fp = fdopen(fd, "w");
    time_t now = time(NULL);

    char timebuf[26];

    fprintf(fp, "%s", cf_strtimestamp_local(now, timebuf));
    fclose(fp);

    return true;
}
Beispiel #6
0
void RemoteSysLog(int log_priority, const char *log_string)
{
    int sd, rfc3164_len = 1024;
    char message[CF_BUFSIZE];
    time_t now = time(NULL);
    int pri = log_priority | FACILITY;

#if defined(HAVE_GETADDRINFO)
    int err;
    struct addrinfo query, *response, *ap;
    char strport[CF_MAXVARSIZE];

    snprintf(strport, CF_MAXVARSIZE - 1, "%u", (unsigned) SYSLOG_PORT);
    memset(&query, 0, sizeof(struct addrinfo));
    query.ai_family = AF_UNSPEC;
    query.ai_socktype = SOCK_DGRAM;

    if ((err = getaddrinfo(SYSLOG_HOST, strport, &query, &response)) != 0)
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Unable to find syslog_host or service: (%s/%s) %s", SYSLOG_HOST, strport,
              gai_strerror(err));
        return;
    }

    for (ap = response; ap != NULL; ap = ap->ai_next)
    {
        CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Connect to syslog %s = %s on port %s\n", SYSLOG_HOST, sockaddr_ntop(ap->ai_addr),
              strport);

        if ((sd = socket(ap->ai_family, ap->ai_socktype, IPPROTO_UDP)) == -1)
        {
            CfOut(OUTPUT_LEVEL_INFORM, "socket", "Couldn't open a socket");
            continue;
        }
        else
        {
            char timebuffer[26];

            snprintf(message, rfc3164_len, "<%u>%.15s %s %s", pri, cf_strtimestamp_local(now, timebuffer) + 4, VFQNAME,
                     log_string);
            if (sendto(sd, message, strlen(message), 0, ap->ai_addr, ap->ai_addrlen) == -1)
            {
                CfOut(OUTPUT_LEVEL_VERBOSE, "sendto", " -> Couldn't send \"%s\" to syslog server \"%s\"\n", message, SYSLOG_HOST);
            }
            else
            {
                CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Syslog message: \"%s\" to server \"%s\"\n", message, SYSLOG_HOST);
            }
            close(sd);
            return;
        }
    }

#else
    struct sockaddr_in addr;
    char timebuffer[26];

    sockaddr_pton(AF_INET, SYSLOG_HOST, &addr);
    addr.sin_port = htons(SYSLOG_PORT);

    if ((sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "sendto", " !! Unable to send syslog datagram");
        return;
    }

    snprintf(message, rfc3164_len, "<%u>%.15s %s %s", pri, cf_strtimestamp_local(now, timebuffer) + 4, VFQNAME,
             log_string);

    if (sendto(sd, message, strlen(message), 0, (struct sockaddr *) &addr, sizeof(addr)) == -1)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "sendto", " !! Unable to send syslog datagram");
        return;
    }

    CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> Syslog message: \"%s\" to server %s\n", message, SYSLOG_HOST);
    close(sd);
#endif
}
Beispiel #7
0
void LocalExec(const ExecConfig *config)
{
    FILE *pp;
    char line[CF_BUFSIZE], line_escaped[sizeof(line) * 2], filename[CF_BUFSIZE], *sp;
    char cmd[CF_BUFSIZE], esc_command[CF_BUFSIZE];
    int print, count = 0;
    void *thread_name;
    time_t starttime = time(NULL);
    char starttime_str[64];
    FILE *fp;
    char canonified_fq_name[CF_BUFSIZE];

    thread_name = ThreadUniqueName();

    cf_strtimestamp_local(starttime, starttime_str);

    CfOut(cf_verbose, "", "------------------------------------------------------------------\n\n");
    CfOut(cf_verbose, "", "  LocalExec(%sscheduled) at %s\n", config->scheduled_run ? "" : "not ", starttime_str);
    CfOut(cf_verbose, "", "------------------------------------------------------------------\n");

/* Need to make sure we have LD_LIBRARY_PATH here or children will die  */

    if (strlen(config->exec_command) > 0)
    {
        strncpy(cmd, config->exec_command, CF_BUFSIZE - 1);

        if (!strstr(cmd, "-Dfrom_cfexecd"))
        {
            strcat(cmd, " -Dfrom_cfexecd");
        }
    }
    else
    {
        ConstructFailsafeCommand(config->scheduled_run, cmd);
    }

    strncpy(esc_command, MapName(cmd), CF_BUFSIZE - 1);

    snprintf(line, CF_BUFSIZE - 1, "_%jd_%s", (intmax_t) starttime, CanonifyName(cf_ctime(&starttime)));

    strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE);
    CanonifyNameInPlace(canonified_fq_name);

    snprintf(filename, CF_BUFSIZE - 1, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name);
    MapName(filename);

/* What if no more processes? Could sacrifice and exec() - but we need a sentinel */

    if ((fp = fopen(filename, "w")) == NULL)
    {
        CfOut(cf_error, "fopen", "!! Couldn't open \"%s\" - aborting exec\n", filename);
        return;
    }

#if !defined(__MINGW32__)
/*
 * Don't inherit this file descriptor on fork/exec
 */

    if (fileno(fp) != -1)
    {
        fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
    }
#endif

    CfOut(cf_verbose, "", " -> Command => %s\n", cmd);

    if ((pp = cf_popen_sh(esc_command, "r")) == NULL)
    {
        CfOut(cf_error, "cf_popen", "!! Couldn't open pipe to command \"%s\"\n", cmd);
        fclose(fp);
        return;
    }

    CfOut(cf_verbose, "", " -> Command is executing...%s\n", esc_command);

    while (!feof(pp))
    {
        if(!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE)))
        {
            char errmsg[CF_MAXVARSIZE];
            snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it",
                     config->agent_expireafter);

            CfOut(cf_error, "", "%s", errmsg);
            fprintf(fp, "%s\n", errmsg);
            count++;

            pid_t pid_agent;

            if(PipeToPid(&pid_agent, pp))
            {
                ProcessSignalTerminate(pid_agent);
            }
            else
            {
                CfOut(cf_error, "", "!! Could not get PID of agent");
            }

            break;
        }

        {
            ssize_t num_read = CfReadLine(line, CF_BUFSIZE, pp);
            if (num_read == -1)
            {
                FatalError("Cannot continue on CfReadLine error");
            }
            else if (num_read == 0)
            {
                break;
            }
        }

        if(!CfReadLine(line, CF_BUFSIZE, pp))
        {
            break;
        }

        if (ferror(pp))
        {
            fflush(pp);
            break;
        }

        print = false;

        for (sp = line; *sp != '\0'; sp++)
        {
            if (!isspace((int) *sp))
            {
                print = true;
                break;
            }
        }

        if (print)
        {
            // we must escape print format chars (%) from output

            ReplaceStr(line, line_escaped, sizeof(line_escaped), "%", "%%");

            fprintf(fp, "%s\n", line_escaped);
            count++;

            /* If we can't send mail, log to syslog */

            if (strlen(config->mail_to_address) == 0)
            {
                strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped));
                if ((strchr(line_escaped, '\n')) == NULL)
                {
                    line_escaped[sizeof(line_escaped) - 2] = '\n';
                }

                CfOut(cf_inform, "", "%s", line_escaped);
            }

            line[0] = '\0';
            line_escaped[0] = '\0';
        }
    }

    cf_pclose(pp);
    CfDebug("Closing fp\n");
    fclose(fp);

    CfOut(cf_verbose, "", " -> Command is complete\n");

    if (count)
    {
        CfOut(cf_verbose, "", " -> Mailing result\n");
        MailResult(config, filename);
    }
    else
    {
        CfOut(cf_verbose, "", " -> No output\n");
        unlink(filename);
    }
}
Beispiel #8
0
static bool IsReadReady(int fd, int timeout_sec)
{
    fd_set  rset;
    FD_ZERO(&rset);
    FD_SET(fd, &rset);

    struct timeval tv = {
        .tv_sec = timeout_sec,
        .tv_usec = 0,
    };

    int ret = select(fd + 1, &rset, NULL, NULL, &tv);

    if(ret < 0)
    {
        Log(LOG_LEVEL_ERR, "IsReadReady: Failed checking for data. (select: %s)", GetErrorStr());
        return false;
    }

    if(FD_ISSET(fd, &rset))
    {
        return true;
    }

    if(ret == 0)  // timeout
    {
        return false;
    }

    // can we get here?
    Log(LOG_LEVEL_ERR, "IsReadReady: Unknown outcome (ret > 0 but our only fd is not set). (select: %s)", GetErrorStr());

    return false;
}
#if defined(__hpux) && defined(__GNUC__)
#pragma GCC diagnostic warning "-Wstrict-aliasing"
#endif

#endif  /* __MINGW32__ */

void LocalExec(const ExecConfig *config)
{
    time_t starttime = time(NULL);

    void *thread_name = ThreadUniqueName();

    {
        char starttime_str[64];
        cf_strtimestamp_local(starttime, starttime_str);

        if (LEGACY_OUTPUT)
        {
            Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------");
            Log(LOG_LEVEL_VERBOSE, "  LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str);
            Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------");
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str);
        }
    }

/* Need to make sure we have LD_LIBRARY_PATH here or children will die  */

    char cmd[CF_BUFSIZE];
    if (strlen(config->exec_command) > 0)
    {
        strncpy(cmd, config->exec_command, CF_BUFSIZE - 1);

        if (!strstr(cmd, "-Dfrom_cfexecd"))
        {
            strcat(cmd, " -Dfrom_cfexecd");
        }
    }
    else
    {
        ConstructFailsafeCommand(config->scheduled_run, cmd);
    }

    char esc_command[CF_BUFSIZE];
    strncpy(esc_command, MapName(cmd), CF_BUFSIZE - 1);

    char line[CF_BUFSIZE];
    snprintf(line, CF_BUFSIZE - 1, "_%jd_%s", (intmax_t) starttime, CanonifyName(ctime(&starttime)));

    char filename[CF_BUFSIZE];
    {
        char canonified_fq_name[CF_BUFSIZE];

        strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE);
        CanonifyNameInPlace(canonified_fq_name);


        snprintf(filename, CF_BUFSIZE - 1, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name);
        MapName(filename);
    }


/* What if no more processes? Could sacrifice and exec() - but we need a sentinel */

    FILE *fp = fopen(filename, "w");
    if (!fp)
    {
        Log(LOG_LEVEL_ERR, "Couldn't open '%s' - aborting exec. (fopen: %s)", filename, GetErrorStr());
        return;
    }

#if !defined(__MINGW32__)
/*
 * Don't inherit this file descriptor on fork/exec
 */

    if (fileno(fp) != -1)
    {
        fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
    }
#endif

    Log(LOG_LEVEL_VERBOSE, "Command => %s", cmd);

    FILE *pp = cf_popen_sh(esc_command, "r");
    if (!pp)
    {
        Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", cmd, GetErrorStr());
        fclose(fp);
        return;
    }

    Log(LOG_LEVEL_VERBOSE, "Command is executing...%s", esc_command);

    int count = 0;
    for (;;)
    {
        if(!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE)))
        {
            char errmsg[CF_MAXVARSIZE];
            snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it",
                     config->agent_expireafter);

            Log(LOG_LEVEL_ERR, "%s", errmsg);
            fprintf(fp, "%s\n", errmsg);
            count++;

            pid_t pid_agent;

            if(PipeToPid(&pid_agent, pp))
            {
                ProcessSignalTerminate(pid_agent);
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Could not get PID of agent");
            }

            break;
        }

        ssize_t res = CfReadLine(line, CF_BUFSIZE, pp);

        if (res == 0)
        {
            break;
        }

        if (res == -1)
        {
            Log(LOG_LEVEL_ERR, "Unable to read output from command '%s'. (cfread: %s)", cmd, GetErrorStr());
            cf_pclose(pp);
            return;
        }

        bool print = false;

        for (const char *sp = line; *sp != '\0'; sp++)
        {
            if (!isspace((int) *sp))
            {
                print = true;
                break;
            }
        }

        if (print)
        {
            char line_escaped[sizeof(line) * 2];

            // we must escape print format chars (%) from output

            ReplaceStr(line, line_escaped, sizeof(line_escaped), "%", "%%");

            fprintf(fp, "%s\n", line_escaped);
            count++;

            /* If we can't send mail, log to syslog */

            if (strlen(config->mail_to_address) == 0)
            {
                strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped));
                if ((strchr(line_escaped, '\n')) == NULL)
                {
                    line_escaped[sizeof(line_escaped) - 2] = '\n';
                }

                Log(LOG_LEVEL_INFO, "%s", line_escaped);
            }

            line[0] = '\0';
            line_escaped[0] = '\0';
        }
    }

    cf_pclose(pp);
    Log(LOG_LEVEL_DEBUG, "Closing fp");
    fclose(fp);

    Log(LOG_LEVEL_VERBOSE, "Command is complete");

    if (count)
    {
        Log(LOG_LEVEL_VERBOSE, "Mailing result");
        MailResult(config, filename);
    }
    else
    {
        Log(LOG_LEVEL_VERBOSE, "No output");
        unlink(filename);
    }
}
Beispiel #9
0
void RemoteSysLog(int log_priority, const char *log_string)
{
    int sd, rfc3164_len = 1024;
    char message[CF_BUFSIZE];
    time_t now = time(NULL);
    int pri = log_priority | FACILITY;

    int err;
    struct addrinfo query, *response, *ap;
    char strport[CF_MAXVARSIZE];

    snprintf(strport, CF_MAXVARSIZE - 1, "%u", (unsigned) SYSLOG_PORT);
    memset(&query, 0, sizeof(query));
    query.ai_family = AF_UNSPEC;
    query.ai_socktype = SOCK_DGRAM;

    if ((err = getaddrinfo(SYSLOG_HOST, strport, &query, &response)) != 0)
    {
        Log(LOG_LEVEL_INFO,
              "Unable to find syslog_host or service: (%s/%s) %s",
              SYSLOG_HOST, strport, gai_strerror(err));
        return;
    }

    for (ap = response; ap != NULL; ap = ap->ai_next)
    {
        /* No DNS lookup, just convert IP address to string. */
        char txtaddr[CF_MAX_IP_LEN] = "";
        getnameinfo(ap->ai_addr, ap->ai_addrlen,
                    txtaddr, sizeof(txtaddr),
                    NULL, 0, NI_NUMERICHOST);
        Log(LOG_LEVEL_VERBOSE,
            "Connect to syslog '%s' = '%s' on port '%s'",
              SYSLOG_HOST, txtaddr, strport);

        if ((sd = socket(ap->ai_family, ap->ai_socktype, IPPROTO_UDP)) == -1)
        {
            Log(LOG_LEVEL_INFO, "Couldn't open a socket. (socket: %s)", GetErrorStr());
            continue;
        }
        else
        {
            char timebuffer[26];

            snprintf(message, rfc3164_len, "<%u>%.15s %s %s",
                     pri, cf_strtimestamp_local(now, timebuffer) + 4,
                     VFQNAME, log_string);
            err = sendto(sd, message, strlen(message),
                         0, ap->ai_addr, ap->ai_addrlen);
            if (err == -1)
            {
                Log(LOG_LEVEL_VERBOSE, "Couldn't send '%s' to syslog server '%s'. (sendto: %s)",
                      message, SYSLOG_HOST, GetErrorStr());
            }
            else
            {
                Log(LOG_LEVEL_VERBOSE, "Syslog message: '%s' to server '%s'", message, SYSLOG_HOST);
            }
            close(sd);
        }
    }

    freeaddrinfo(response);
}
Beispiel #10
0
void SetPolicyServer(char *name)
/*
 * If name contains a string, it's written to file,
 * if not, name is filled with the contents of file.
 */
{
    char file[CF_BUFSIZE];
    FILE *fout, *fin;
    char fileContents[CF_MAXVARSIZE] = { 0 };

    snprintf(file, CF_BUFSIZE - 1, "%s/policy_server.dat", CFWORKDIR);
    MapName(file);

    if ((fin = fopen(file, "r")) != NULL)
    {
        fscanf(fin, "%1023s", fileContents);
        fclose(fin);
    }

    // update file if different and we know what to put there

    if ((NULL_OR_EMPTY(name)) && (!NULL_OR_EMPTY(fileContents)))
    {
        snprintf(name, CF_MAXVARSIZE, "%s", fileContents);
    }
    else if ((!NULL_OR_EMPTY(name)) && (strcmp(name, fileContents) != 0))
    {
        if ((fout = fopen(file, "w")) == NULL)
        {
            CfOut(cf_error, "fopen", "Unable to write policy server file! (%s)", file);
            return;
        }

        fprintf(fout, "%s", name);
        fclose(fout);
    }

    if (NULL_OR_EMPTY(name))
    {
        // avoids "Scalar item in servers => {  } in rvalue is out of bounds ..."
        // when NovaBase is checked with unprivileged (not bootstrapped) cf-promises
        NewScalar("sys", "policy_hub", "undefined", cf_str);
    }
    else
    {
        NewScalar("sys", "policy_hub", name, cf_str);
    }

// Get the timestamp on policy update

    snprintf(file, CF_MAXVARSIZE, "%s/masterfiles/cf_promises_validated", CFWORKDIR);
    MapName(file);

    struct stat sb;

    if ((cfstat(file, &sb)) != 0)
    {
        return;
    }

    char timebuf[26];
    cf_strtimestamp_local(sb.st_mtime, timebuf);

    NewScalar("sys", "last_policy_update", timebuf, cf_str);
}
Beispiel #11
0
void UpdateLastSeen() // This function is temporarily or permanently deprecated

{ double lsea = LASTSEENEXPIREAFTER;
  int intermittency = false,qsize,ksize;
  struct CfKeyHostSeen q,newq; 
  double lastseen,delta2;
  void *stored;
  CF_DB *dbp = NULL,*dbpent = NULL;
  CF_DBC *dbcp;
  char name[CF_BUFSIZE],*key;
  struct Rlist *rp;
  struct CfKeyBinding *kp;
  time_t now = time(NULL);
  static time_t then;
  
if (now < then + 300 && then > 0 && then <= now + 300)
   {
   // Rate limiter
   return;
   }

then = now;

CfOut(cf_verbose,""," -> Writing last-seen observations");

ThreadLock(cft_server_keyseen);

if (SERVER_KEYSEEN == NULL)
   {
   ThreadUnlock(cft_server_keyseen);
   CfOut(cf_verbose,""," -> Keyring is empty");
   return;
   }

if (BooleanControl("control_agent",CFA_CONTROLBODY[cfa_intermittency].lval))
   {
   CfOut(cf_inform,""," -> Recording intermittency");
   intermittency = true;
   }

snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE);
MapName(name);

if (!OpenDB(name,&dbp))
   {
   ThreadUnlock(cft_server_keyseen);
   return;
   }

/* First scan for hosts that have moved address and purge their records so that
   the database always has a 1:1 relationship between keyhash and IP address    */

if (!NewDBCursor(dbp,&dbcp))
   {
   ThreadUnlock(cft_server_keyseen);
   CfOut(cf_inform,""," !! Unable to scan class db");
   return;
   }

while(NextDB(dbp,dbcp,&key,&ksize,&stored,&qsize))
   {
   memcpy(&q,stored,sizeof(q));

   lastseen = (double)now - q.Q.q;

   if (lastseen > lsea)
      {
      CfOut(cf_verbose,""," -> Last-seen record for %s expired after %.1lf > %.1lf hours\n",key,lastseen/3600,lsea/3600);
      DeleteDB(dbp,key);
      }

   for (rp = SERVER_KEYSEEN; rp !=  NULL; rp=rp->next)
      {
      kp = (struct CfKeyBinding *) rp->item;
      
      if ((strcmp(q.address,kp->address) == 0) && (strcmp(key+1,kp->name+1) != 0))
         {
         CfOut(cf_verbose,""," ! Deleting %s's address (%s=%d) as this host %s seems to have moved elsewhere (%s=5d)",key,kp->address,strlen(kp->address),kp->name,q.address,strlen(q.address));
         DeleteDB(dbp,key);
         }
      }

   }

DeleteDBCursor(dbp,dbcp);

/* Now perform updates with the latest data */

for (rp = SERVER_KEYSEEN; rp !=  NULL; rp=rp->next)
   {
   kp = (struct CfKeyBinding *) rp->item;

   now = kp->timestamp;
   
   if (intermittency)
      {
      /* Open special file for peer entropy record - INRIA intermittency */
      snprintf(name,CF_BUFSIZE-1,"%s/lastseen/%s.%s",CFWORKDIR,CF_LASTDB_FILE,kp->name);
      MapName(name);
      
      if (!OpenDB(name,&dbpent))
         {
         continue;
         }
      }
   
   if (ReadDB(dbp,kp->name,&q,sizeof(q)))
      {
      lastseen = (double)now - q.Q.q;
      
      if (q.Q.q <= 0)
         {
         lastseen = 300;
         q.Q.expect = 0;
         q.Q.var = 0;
         }
      
      newq.Q.q = (double)now;
      newq.Q.expect = GAverage(lastseen,q.Q.expect,0.4);
      delta2 = (lastseen - q.Q.expect)*(lastseen - q.Q.expect);
      newq.Q.var = GAverage(delta2,q.Q.var,0.4);
      strncpy(newq.address,kp->address,CF_ADDRSIZE-1);
      }
   else
      {
      lastseen = 0.0;
      newq.Q.q = (double)now;
      newq.Q.expect = 0.0;
      newq.Q.var = 0.0;
      strncpy(newq.address,kp->address,CF_ADDRSIZE-1);
      }
   
   if (lastseen > lsea)
      {
      CfOut(cf_verbose,""," -> Last-seen record for %s expired after %.1lf > %.1lf hours\n",kp->name,lastseen/3600,lsea/3600);
      DeleteDB(dbp,kp->name);
      }
   else
      {
      char timebuf[26];
      CfOut(cf_verbose,""," -> Last saw %s (alias %s) at %s (noexpiry %.1lf <= %.1lf)\n",kp->name,kp->address,cf_strtimestamp_local(now,timebuf),lastseen/3600,lsea/3600);

      WriteDB(dbp,kp->name,&newq,sizeof(newq));
      
      if (intermittency)
         {
         WriteDB(dbpent,GenTimeKey(now),&newq,sizeof(newq));
         }
      }
   
   if (intermittency && dbpent)
      {
      CloseDB(dbpent);
      }
   }

ThreadUnlock(cft_server_keyseen);
}
Beispiel #12
0
void RemoteSysLog(int log_priority, const char *log_string)
{
    time_t now = time(NULL);

    struct addrinfo query = { 0 }, *response = NULL;
    char strport[PRINTSIZE(unsigned)];
    xsnprintf(strport, sizeof(strport), "%u", (unsigned) SYSLOG_PORT);

    query.ai_family = AF_UNSPEC;
    query.ai_socktype = SOCK_DGRAM;

    int err = getaddrinfo(SYSLOG_HOST, strport, &query, &response);
    if (err != 0)
    {
        Log(LOG_LEVEL_INFO,
            "Unable to find syslog_host or service: (%s/%s) %s",
            SYSLOG_HOST, strport, gai_strerror(err));
        if (response != NULL)
        {
            freeaddrinfo(response);
        }
        return;
    }

    for (const struct addrinfo *ap = response; ap != NULL; ap = ap->ai_next)
    {
        /* No DNS lookup, just convert IP address to string. */
        char txtaddr[CF_MAX_IP_LEN] = "";
        getnameinfo(ap->ai_addr, ap->ai_addrlen,
                    txtaddr, sizeof(txtaddr),
                    NULL, 0, NI_NUMERICHOST);
        Log(LOG_LEVEL_VERBOSE,
            "Connect to syslog '%s' = '%s' on port '%s'",
            SYSLOG_HOST, txtaddr, strport);

        int sd = socket(ap->ai_family, ap->ai_socktype, IPPROTO_UDP);
        if (sd == -1)
        {
            Log(LOG_LEVEL_INFO, "Couldn't open a socket. (socket: %s)", GetErrorStr());
            continue;
        }
        else
        {
            const size_t rfc3164_len = 1024;
            char message[rfc3164_len];
            char timebuffer[26];
            pid_t pid = getpid();

            snprintf(message, sizeof(message), "<%i>%.15s %s %s[%d]: %s",
                     log_priority | SYSLOG_FACILITY,
                     cf_strtimestamp_local(now, timebuffer) + 4,
                     VFQNAME, VPREFIX, pid, log_string);
            err = sendto(sd, message, strlen(message),
                         0, ap->ai_addr, ap->ai_addrlen);
            if (err == -1)
            {
                Log(LOG_LEVEL_VERBOSE, "Couldn't send '%s' to syslog server '%s'. (sendto: %s)",
                    message, SYSLOG_HOST, GetErrorStr());
            }
            else
            {
                Log(LOG_LEVEL_VERBOSE, "Syslog message: '%s' to server '%s'", message, SYSLOG_HOST);
            }
            close(sd);
        }
    }

    freeaddrinfo(response);
}
Beispiel #13
0
static void UpdateLastSawHost(char *rkey, char *ipaddress)
{
    CF_DB *dbp = NULL;
    KeyHostSeen q, newq;
    double lastseen, delta2;
    time_t now = time(NULL);
    char timebuf[26];


    if (!OpenDB(&dbp, dbid_lastseen))
    {
        CfOut(cf_inform, "", " !! Unable to open last seen db");
        return;
    }

    if (ReadDB(dbp, rkey, &q, sizeof(q)))
    {
        lastseen = (double) now - q.Q.q;

        if (q.Q.q <= 0)
        {
            lastseen = 300;
            q.Q = QDefinite(0.0);
        }

        newq.Q.q = (double) now;
        newq.Q.dq = newq.Q.q - q.Q.q;
        newq.Q.expect = GAverage(lastseen, q.Q.expect, 0.4);
        delta2 = (lastseen - q.Q.expect) * (lastseen - q.Q.expect);
        newq.Q.var = GAverage(delta2, q.Q.var, 0.4);
        strncpy(newq.address, ipaddress, CF_ADDRSIZE - 1);
    }
    else
    {
        lastseen = 0.0;
        newq.Q.q = (double) now;
        newq.Q.dq = 0;
        newq.Q.expect = 0.0;
        newq.Q.var = 0.0;
        strncpy(newq.address, ipaddress, CF_ADDRSIZE - 1);
    }

    if (strcmp(rkey + 1, PUBKEY_DIGEST) == 0)
    {
        Item *ip;
        int match = false;

        for (ip = IPADDRESSES; ip != NULL; ip = ip->next)
        {
            if (strcmp(VIPADDRESS, ip->name) == 0)
            {
                match = true;
                break;
            }
            if (strcmp(ipaddress, ip->name) == 0)
            {
                match = true;
                break;
            }
        }

        if (!match)
        {
            CfOut(cf_verbose, "", " ! Not updating last seen, as this appears to be a host with a duplicate key");
            CloseDB(dbp);

            return;
        }
    }

    CfOut(cf_verbose, "", " -> Last saw %s (alias %s) at %s\n", rkey, ipaddress, cf_strtimestamp_local(now, timebuf));

    PurgeMultipleIPReferences(dbp, rkey, ipaddress);

    WriteDB(dbp, rkey, &newq, sizeof(newq));

    CloseDB(dbp);
}
Beispiel #14
0
char *cf_ctime(const time_t *timep)
{
    static char buf[26];

    return cf_strtimestamp_local(*timep, buf);
}