vlmcsd/output.c
2015-11-29 17:30:52 +08:00

241 lines
6.0 KiB
C

#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif // _DEFAULT_SOURCE
#ifndef CONFIG
#define CONFIG "config.h"
#endif // CONFIG
#include CONFIG
#include "output.h"
#include "shared_globals.h"
#include "endian.h"
#include "helpers.h"
#ifndef NO_LOG
static void vlogger(const char *message, va_list args)
{
FILE *log;
#ifdef _NTSERVICE
if (!IsNTService && logstdout) log = stdout;
#else
if (logstdout) log = stdout;
#endif
else
{
if (fn_log == NULL) return;
#ifndef _WIN32
if (!strcmp(fn_log, "syslog"))
{
openlog("vlmcsd", LOG_CONS | LOG_PID, LOG_USER);
////PORTABILITY: vsyslog is not in Posix but virtually all Unixes have it
vsyslog(LOG_INFO, message, args);
closelog();
return;
}
#endif // _WIN32
log = fopen(fn_log, "a");
if ( !log ) return;
}
time_t now = time(0);
#ifdef USE_THREADS
char mbstr[2048];
#else
char mbstr[24];
#endif
strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", localtime(&now));
#ifndef USE_THREADS
fprintf(log, "%s: ", mbstr);
vfprintf(log, message, args);
fflush(log);
#else // USE_THREADS
// We write everything to a string before we really log inside the critical section
// so formatting the output can be concurrent
strcat(mbstr, ": ");
int len = strlen(mbstr);
vsnprintf(mbstr + len, sizeof(mbstr) - len, message, args);
lock_mutex(&logmutex);
fputs(mbstr, log);
fflush(log);
unlock_mutex(&logmutex);
#endif // USE_THREADS
if (log != stdout) fclose(log);
}
// Always sends to log output
int logger(const char *const fmt, ...)
{
va_list args;
va_start(args, fmt);
vlogger(fmt, args);
va_end(args);
return 0;
}
#endif //NO_LOG
// Output to stderr if it is available or to log otherwise (e.g. if running as daemon/service)
void printerrorf(const char *const fmt, ...)
{
va_list arglist;
va_start(arglist, fmt);
#ifndef NO_LOG
#ifdef _NTSERVICE
if (InetdMode || IsNTService)
#else // !_NTSERVICE
if (InetdMode)
#endif // NTSERVIICE
vlogger(fmt, arglist);
else
#endif //NO_LOG
{
vfprintf(stderr, fmt, arglist);
fflush(stderr);
}
va_end(arglist);
}
// Always output to stderr
int errorout(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
int i = vfprintf(stderr, fmt, args);
va_end(args);
fflush(stderr);
return i;
}
static const char *LicenseStatusText[] =
{
"Unlicensed", "Licensed", "OOB grace", "OOT grace", "Non-Genuine", "Notification", "Extended grace"
};
void uuid2StringLE(const GUID *const guid, char *const string)
{
sprintf(string,
#ifdef _WIN32
"%08x-%04x-%04x-%04x-%012I64x",
#else
"%08x-%04x-%04x-%04x-%012llx",
#endif
(unsigned int)LE32( guid->Data1 ),
(unsigned int)LE16( guid->Data2 ),
(unsigned int)LE16( guid->Data3 ),
(unsigned int)BE16( *(uint16_t*)guid->Data4 ),
(unsigned long long)BE64(*(uint64_t*)(guid->Data4)) & 0xffffffffffffLL
);
}
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
{
char guidBuffer[GUID_STRING_LENGTH + 1];
char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER];
const char *productName;
ProdListIndex_t index;
p("Protocol version : %u.%u\n", LE16(Request->MajorVer), LE16(Request->MinorVer));
p("Client is a virtual machine : %s\n", LE32(Request->VMInfo) ? "Yes" : "No");
p("Licensing status : %u (%s)\n", (uint32_t)LE32(Request->LicenseStatus), LE32(Request->LicenseStatus) < _countof(LicenseStatusText) ? LicenseStatusText[LE32(Request->LicenseStatus)] : "Unknown");
p("Remaining time (0 = forever) : %i minutes\n", (uint32_t)LE32(Request->BindingExpiration));
uuid2StringLE(&Request->AppID, guidBuffer);
productName = getProductNameLE(&Request->AppID, AppList, &index);
p("Application ID : %s (%s)\n", guidBuffer, productName);
uuid2StringLE(&Request->ActID, guidBuffer);
#ifndef NO_EXTENDED_PRODUCT_LIST
productName = getProductNameLE(&Request->ActID, ExtendedProductList, &index);
#else
productName = "Unknown";
#endif
p("Activation ID (Product) : %s (%s)\n", guidBuffer, productName);
uuid2StringLE(&Request->KMSID, guidBuffer);
#ifndef NO_BASIC_PRODUCT_LIST
productName = getProductNameLE(&Request->KMSID, ProductList, &index);
#else
productName = "Unknown";
#endif
p("Key Management Service ID : %s (%s)\n", guidBuffer, productName);
uuid2StringLE(&Request->CMID, guidBuffer);
p("Client machine ID : %s\n", guidBuffer);
uuid2StringLE(&Request->CMID_prev, guidBuffer);
p("Previous client machine ID : %s\n", guidBuffer);
char mbstr[64];
time_t st;
st = fileTimeToUnixTime(&Request->ClientTime);
strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
p("Client request timestamp (UTC) : %s\n", mbstr);
ucs2_to_utf8(Request->WorkstationName, WorkstationBuffer, WORKSTATION_NAME_BUFFER, sizeof(WorkstationBuffer));
p("Workstation name : %s\n", WorkstationBuffer);
p("N count policy (minimum clients): %u\n", (uint32_t)LE32(Request->N_Policy));
}
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p)
{
char guidBuffer[GUID_STRING_LENGTH + 1];
//SYSTEMTIME st;
p("Protocol version : %u.%u\n", (uint32_t)LE16(response->MajorVer), (uint32_t)LE16(response->MinorVer));
p("KMS host extended PID : %s\n", ePID);
if (LE16(response->MajorVer) > 5)
# ifndef _WIN32
p("KMS host Hardware ID : %016llX\n", (unsigned long long)BE64(*(uint64_t*)hwid));
# else // _WIN32
p("KMS host Hardware ID : %016I64X\n", (unsigned long long)BE64(*(uint64_t*)hwid));
# endif // WIN32
uuid2StringLE(&response->CMID, guidBuffer);
p("Client machine ID : %s\n", guidBuffer);
char mbstr[64];
time_t st;
st = fileTimeToUnixTime(&response->ClientTime);
strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
p("Client request timestamp (UTC) : %s\n", mbstr);
p("KMS host current active clients : %u\n", (uint32_t)LE32(response->Count));
p("Renewal interval policy : %u\n", (uint32_t)LE32(response->VLRenewalInterval));
p("Activation interval policy : %u\n", (uint32_t)LE32(response->VLActivationInterval));
}