/*****************************************************************************/ /* overseer.c The overseer is the certificate management activity executing in the detached process. It schedules the once-per-day certificate expiry management activity. The overseer.c module is considered the main module of wCME as an autonomous certificate management agent. Acme-client-portable has its own main.c module. COPYRIGHT --------- Copyright (C) 2017-2019 Mark G.Daniel This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version. http://www.gnu.org/licenses/gpl.txt VERSION HISTORY --------------- 24-JAN-2019 MGD v2.0.0, move to OpenBSD source 30-MAR-2018 MGD WCME_AGREEMENT logical name [.acme-client-portable-0_1_15]VMS.c timegm() code revised 15-OCT-2017 MGD wcme_socketpair() for building on earlier than VMS V8.2 23-JUL-2017 MGD http-01 standalone challenge server 09-JUL-2017 MGD initial release 23-APR-2017 MGD initial development */ /*****************************************************************************/ #define SOFTWAREVN "2.0.0" #define SOFTWARENM "WCME" #ifdef __ALPHA # define SOFTWAREID SOFTWARENM " AXP-" SOFTWAREVN #endif #ifdef __ia64 # define SOFTWAREID SOFTWARENM " IA64-" SOFTWAREVN #endif #ifdef __VAX # define SOFTWAREID SOFTWARENM " VAX-" SOFTWAREVN #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "certman.h" #include "overseer.h" #include "util.h" #include "acme-client/wcme_config.h" #include "wcme_tls_internal.h" #define FI_LI "OVERSEER", __LINE__ char *WcmeLogFileName; char SoftwareId [] = SOFTWAREID; char* doasprintf (char*, ...); /*****************************************************************************/ /* Called from [.acme-client]main.c when a detached process. Oversees the periodic certificate check and any required update. */ void OverseerProcess (int argc, char* argv[]) { static short PrevDay; int secs, status, NewLog, PerHour, PollSecs; ulong BinTime [2]; ushort NumTime [7]; char *cptr; /*********/ /* begin */ /*********/ UtilSetPrn ("overseer"); /* in case there's a detached process log being generated */ sys$gettim (&BinTime); sys$numtim (&NumTime, &BinTime); fprintf (stdout, "%%WCME-I-STARTUP, %04.04u-%02.02u-%02.02u-%02.02u:%02.02u:%02.02u\n\ %%WCME-I-VERSION, %s\n\ %%WCME-I-IMAGE, %s\n", NumTime[0], NumTime[1], NumTime[2], NumTime[3], NumTime[4], NumTime[5], OverseerVersion(), UtilImageName()); /* only intended for development purposes */ if (cptr = UtilTrnLnm ("WCME_OVERSEER_POLL", "LNM$SYSTEM", 0)) { PollSecs = atoi(cptr); if (PollSecs <= 0 || PollSecs > 3600) PollSecs = 60; } else PollSecs = 0; for (;;) { sys$gettim (&BinTime); sys$numtim (&NumTime, &BinTime); /* open the log */ NewLog = OverseerLog (NumTime[0], NumTime[1]); if (!PrevDay) vmsdbg ("%s starting %s", UtilUserName(), OverseerVersion()); else if (NewLog) vmsdbg ("%s running %s", UtilUserName(), OverseerVersion()); /* only intended for development purposes */ PerHour = (UtilTrnLnm ("WCME_OVERSEER_HOURLY", "LNM$SYSTEM", 0) != NULL); if ((PrevDay && PrevDay != NumTime[2]) || PerHour) { /* day has changed so perform certificate management */ vmsdbg ("certificate management"); CertManBegin (); /* reload the time in case of extended certificate activities */ sys$gettim (&BinTime); sys$numtim (&NumTime, &BinTime); } PrevDay = NumTime[2]; /* polls at twenty minutes after each hour */ secs = (3600 - (NumTime[4] * 60)) + (60 - NumTime[5]) + (19 * 60); /* close the log */ OverseerLog (0, 0); if (PollSecs) { PrevDay = -1; sleep (PollSecs); } else sleep (secs); } } /*****************************************************************************/ /* The log is maintained on a per-month basis. */ int OverseerLog ( int year, int month ) { int status; char *cptr, *lfname; FILE *fp; struct stat stat_buf; /*********/ /* begin */ /*********/ if (WcmeLogFileName) free (WcmeLogFileName); WcmeLogFileName = NULL; if (!year) { stderr = freopen ("/nl", "w", stderr); if (!stderr) exit (vaxc$errno); return (0); } lfname = doasprintf ("/wcme_root/log/overseer_%04.04d%02.02d.log", year, month); WcmeLogFileName = strdup(lfname); UtilSysPrv(); status = stat (lfname, &stat_buf); stderr = freopen (lfname, "a", stderr, "ctx=rec", "rfm=var", "rat=cr", "rop=rlk", "shr=get", "shr=put"); UtilMereMortal(); if (!stderr) exit (vaxc$errno); if (status) vmsdbg ("%s", (char*)UtilVmsName(lfname,-1)); free (lfname); return (status != 0); } /*****************************************************************************/ /* Ensure acme-client-portable warn/error output is captured. Called by the lib$spawn()ed and furk()ed [.acme-client-portable..]main.c Each subprocess needs an indepedent C-RTL std-I/O buffer to prevent mingling of the data (stderr) being written. Let the underlying RMS sort out the records. */ void OverseerSubprocessLog (char *lfname) { /*********/ /* begin */ /*********/ UtilSysPrv(); stderr = freopen (lfname, "a", stderr, "ctx=rec", "rfm=var", "rat=cr", "rop=rlk", "shr=get", "shr=put"); UtilMereMortal(); if (!stderr) exit (vaxc$errno); fprintf (stdout, "%s [main] %s\n", tstamp(NULL), OverseerVersion()); } /*****************************************************************************/ /* */ char* OverseerVersion () { static char *bptr; char *cptr, *sptr; /*********/ /* begin */ /*********/ if (bptr) return (bptr); bptr = doasprintf ("%s built %s %s LIBTLS %s %s", SoftwareId, __DATE__, __TIME__, WCME_LIBTLS_VERSION, OPENSSL_VERSION_TEXT); /* single spacing only thank you */ for (cptr = sptr = bptr; bptr && *cptr; cptr++) if (*cptr != ' ' || *(cptr+1) != ' ') *sptr++ = *cptr; *sptr = '\0'; return (bptr); } /*****************************************************************************/ /* */ void DisplayVersion () { fprintf (stdout, "%%WCME-I-VERSION, %s\n", OverseerVersion()); } /*****************************************************************************/