/* Demonstration of how to implement a 30 day limited trial application * * (c) 2007 by Lazarus Internet Development * Written by Clay Dowling * * $Id: 30-day-demo.c 16 2005-08-17 23:30:15Z $ */ #include #include #include #include #include #include #include #include "registration.h" #include "serial.h" #include "config.h" #include "regsanity.h" #include "md5.h" #define ONEDAY 86400 #define TRIALDAYS 30 const char *CONFIGFILE = "trialreg.conf"; const char *SECRET = "30 Day Trial"; const char* getmd5(const char*); void getregistration(); void checkregistration(); /* Make these global because all portions of the app need to know about this */ int g_trialdays = -1; int g_valid = 0; int main(int argc, char** argv) { const char* regmd5 = NULL; g_trialdays = TRIALDAYS + 1; regmd5 = getmd5("registration.dll"); if (strcmp(regmd5, REGISTRATION_MD5) != 0) { fputs("Registration DLL failed sanity check.\n", stderr); fprintf(stderr, "Actual MD5: %s\nTarget MD5: %s\n", regmd5, REGISTRATION_MD5); return EXIT_FAILURE; } checkregistration(); if (g_trialdays >= 0 && g_trialdays <= TRIALDAYS) printf("You have %d days remaining in this trial.\n", g_trialdays); if (g_trialdays < 0) printf("This trial copy has expired.\n"); if (g_valid) puts("This copy is valid."); else puts("*** INVALID COPY ***"); return EXIT_SUCCESS; } const char* getmd5(const char* filename) { FILE* in; char* buffer; md5_state_t pms; md5_byte_t digest[16]; static char key[33]; int i; struct stat sb; char *pos; if (stat(filename, &sb)) { perror(filename); return NULL; } buffer = (char*)calloc(1, sb.st_size + 1); memset(key, 0, 33); in = fopen(filename, "rb"); fread((void*)buffer, 1, sb.st_size, in); fclose(in); md5_init(&pms); md5_append(&pms, (const md5_byte_t *)buffer, sb.st_size); md5_finish(&pms, digest); pos = key; for (i=0; i < 16; ++i) { sprintf(pos, "%2.2x", digest[i]); pos += 2; } return key; } void cleanstring(char* victim) { char *work; int i=0; int j=0; if (victim == NULL) return; work = (char*)calloc(1, strlen(victim) + 1); for (i=0; victim[i]; ++i) if (!isspace(victim[i])) work[j++] = victim[i]; for (i=0; work[i]; ++i) victim[i] = work[i]; victim[i] = 0; } void getregistration() { char serial[33]; char key[33]; FILE *cfile; memset(serial, 0, 33); memset(key, 0, 33); printf("Enter serial number (ENTER for 30 day trial): "); fgets(serial, 33, stdin); cleanstring(serial); if (serial[0] != 0) { printf("Enter registration key: "); fgets(key, 33, stdin); cleanstring(key); } else { serial_t ser; char* regkey; time_t now; int backdate = 0; printf("Days to backdate the installation: "); scanf("%d", &backdate); ser = serial_create(2); now = time(0); serial_set_int(ser, 0, 0); /* Customer ID of 0 indicates a trial */ serial_set_date(ser, 1, now - (backdate * ONEDAY)); /* Date application was first run */ strncpy(serial, serial_encode(ser), 32); regkey = gen_key(serial, SECRET); strncpy(key, key_as_string(regkey), 32); free(regkey); } cfile = fopen(CONFIGFILE, "w"); if (!cfile) { perror(CONFIGFILE); return; } fprintf(cfile, "serial = %s\n", serial); fprintf(cfile, "key = %s\n", key); fclose(cfile); return; } void checkregistration() { FILE* cfile; serial_t ser; cfile = fopen(CONFIGFILE, "r"); if (cfile) { config_t config; char* regkey = NULL; char* regserial = NULL; config = config_read(cfile); fclose(cfile); regserial = config_get_string(config, "serial"); regkey = config_get_string(config, "key"); ser = serial_decode(regserial); if (regserial && regkey && isregistered(regserial, regkey, SECRET)) g_valid = 1; /* This is a trial version. Check g_valid to ensure that somebody hasn't been * manually updating the registration file */ if (serial_get_int(ser, 0) == 0 && g_valid == 1) { time_t now; time_t regdate; now = time(0); regdate = serial_get_date(ser, 1); g_trialdays = TRIALDAYS - ((now - regdate) / ONEDAY); if (g_trialdays < 0) g_valid = 0; } config_destroy(config); serial_destroy(ser); } else getregistration(); }