License.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 $Header$
00004 
00005 */
00006 
00007 #include <stdio.h>
00008 #include <sys/types.h>
00009 #include <sys/ioctl.h>
00010 #include <sys/time.h>
00011 #include <net/if.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <unistd.h>
00015 
00016 #include "Endian.h"
00017 #include "Error.h"
00018 #include "Connection.h"
00019 
00020 #include "License.h"
00021 
00022 // Public methods.
00023 
00024 // Check license with specified MAC.
00025 int License::check(const String &license)
00026 {
00027   char decodedLicense[LICENSE_LIMIT_SIZE];
00028   int res;
00029 
00030   if (FAILED(res = decode(decodedLicense, CSTRING(license), license.length())) < 0)
00031     return ERROR_BACKTRACE(res);
00032 
00033   if (crc(decodedLicense, LICENSE_MAC_ADDRESS_SIZE) != decodedLicense[LICENSE_MAC_ADDRESS_SIZE])
00034     return ERROR(MSG_LICENSE_INVALID);
00035 
00036   if (crc(decodedLicense + LICENSE_MAC_ADDRESS_SIZE + 1, sizeof(_expirationTime)) !=
00037       *(decodedLicense + LICENSE_MAC_ADDRESS_SIZE + 1 + sizeof(_expirationTime)))
00038     return ERROR(MSG_LICENSE_INVALID);
00039 
00040   _expirationTime = SWAP32_IF_BE(*((time_t *)(decodedLicense + LICENSE_MAC_ADDRESS_SIZE + 1)));
00041   if (_expirationTime != (time_t)LICENSE_MAGIC_TIME && _expirationTime <= time(NULL))
00042     return ERROR(MSG_LICENSE_INVALID);
00043 
00044   decodedLicense[LICENSE_MAC_ADDRESS_SIZE] = '\0';
00045   _mac = decodedLicense;
00046 
00047   return OK;
00048 }
00049 
00050 int License::check()
00051 {
00052   FILE *f;
00053   char license[LICENSE_LIMIT_SIZE];
00054   char decodedLicense[LICENSE_LIMIT_SIZE];
00055   String macAddr;
00056   int res;
00057 
00058   if (!(f = fopen(LICENSE_FILE_PATH, "r")))
00059     return ERROR(MSG_FILE_CANNOT_OPEN, LICENSE_FILE_PATH, strerror(errno));
00060 
00061   fgets((char *)license, sizeof(license) - 1, f);
00062 
00063   if (fclose(f) != 0)
00064     return ERROR(MSG_FILE_CANNOT_CLOSE, LICENSE_FILE_PATH, strerror(errno));
00065 
00066   if (FAILED(res = decode(decodedLicense, license, strlen(license))))
00067     return ERROR_BACKTRACE(res);
00068 
00069   if (FAILED(res = mac(macAddr)))
00070     return ERROR_BACKTRACE(res);
00071 
00072   if (macAddr == LICENSE_MAGIC_MAC)
00073     return OK;
00074 
00075   if (memcmp(CSTRING(macAddr.substr(0, LICENSE_MAC_ADDRESS_SIZE)), decodedLicense, LICENSE_MAC_ADDRESS_SIZE))
00076     return ERROR(MSG_LICENSE_INVALID);
00077 
00078   if (FAILED(res = check(license)))
00079     return ERROR_BACKTRACE(res);
00080 
00081   return OK;
00082 }
00083 
00084 int License::checkWithMsg()
00085 {
00086   int res;
00087 
00088   if (FAILED(res = check())) {
00089     sleep(LICENSE_MSG_DELAY);
00090     fprintf(stderr, LICENSE_MSG);
00091     return ERROR_BACKTRACE(res);
00092   }
00093   return OK;
00094 }
00095 
00096 String License::mac() const
00097 {
00098   return _mac;
00099 }
00100 
00101 time_t License::expirationTime() const
00102 {
00103   return _expirationTime;
00104 }
00105 
00106 int License::generate(const String &macAddr, const time_t expirationTime, String &license)
00107 {
00108   char clearLicense[LICENSE_LIMIT_SIZE];
00109   char encodedLicense[LICENSE_LIMIT_SIZE];
00110   time_t et;
00111   int res;
00112 
00113 #ifdef DEBUG_MODE
00114   if (FAILED(res = test()))
00115     return ERROR_BACKTRACE(res);
00116 #endif
00117 
00118   if (macAddr.empty()) {
00119     String macAddr;
00120 
00121     if (FAILED(res = mac(macAddr)))
00122       return ERROR_BACKTRACE(res);
00123     memcpy(clearLicense, CSTRING(macAddr), LICENSE_MAC_ADDRESS_SIZE);
00124   } else
00125       memcpy(clearLicense, CSTRING(macAddr), LICENSE_MAC_ADDRESS_SIZE);
00126 
00127   clearLicense[LICENSE_MAC_ADDRESS_SIZE] = crc(clearLicense, LICENSE_MAC_ADDRESS_SIZE);
00128 
00129   et = expirationTime == 0 ? SWAP32_IF_BE(LICENSE_MAGIC_TIME) : SWAP32_IF_BE(expirationTime);
00130 
00131   memcpy(clearLicense + LICENSE_MAC_ADDRESS_SIZE + 1, &et, sizeof(et));
00132 
00133   clearLicense[LICENSE_MAC_ADDRESS_SIZE + 1 + sizeof(et)] =
00134       crc(clearLicense + LICENSE_MAC_ADDRESS_SIZE + 1, sizeof(et));
00135 
00136   if (FAILED(res = encode(encodedLicense, clearLicense, LICENSE_MAC_ADDRESS_SIZE + sizeof(et) + 2)))
00137     return ERROR_BACKTRACE(res);
00138 
00139   license = encodedLicense;
00140 
00141   return OK;
00142 }
00143 
00144 // Private methods.
00145 
00146 License::License() : Object(), Singleton<License>()
00147 {
00148   _expirationTime = 0;
00149 }
00150 
00151 License::~License()
00152 {
00153 }
00154 
00155 int License::mac(String &mac)
00156 {
00157   struct ifreq ifReq;
00158   int sock;
00159 
00160   memset(&ifReq, 0, sizeof(ifReq));
00161   strcpy(ifReq.ifr_name, LICENSE_IF_NAME);
00162 
00163   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
00164     return ERROR(MSG_SOCKET_CANNOT_CREATE, strerror(errno));
00165 
00166   if (ioctl(sock, SIOCGIFHWADDR, &ifReq)) {
00167     close(sock);
00168     return ERROR(MSG_SOCKET_CANNOT_GET_INFO, strerror(errno));
00169   }
00170 
00171   if (close(sock))
00172     return ERROR(MSG_SOCKET_CANNOT_CLOSE, strerror(errno));
00173 
00174   mac = ifReq.ifr_hwaddr.sa_data;
00175 
00176   return OK;
00177 }
00178 
00179 int License::encode(char *encodedData, const char *data, const unsigned int size)
00180 {
00181   unsigned int i;
00182   char bs[3];
00183   int t;
00184   struct timeval tv;
00185   struct timezone tz;
00186   char *tp = (char *)(&t);
00187 
00188   gettimeofday(&tv, &tz);
00189   srand(tv.tv_usec);
00190   t = rand();
00191 
00192   DEBUG("Encoding mask: %d.", t);
00193 
00194   *encodedData = '\0';
00195   for (i = 0; i < size; ++i) {
00196     snprintf(bs, sizeof(bs), "%.2X", (unsigned char)(data[i] >> (8 - (t + i) % 7) | data[i] << ((t + i) % 7)));
00197     strcat((char *)encodedData, bs);
00198   }
00199 
00200   t = SWAP32_IF_BE(t);
00201 
00202   for (i = 0; i < sizeof(t); ++i) {
00203     snprintf(bs, sizeof(bs), "%.2X", (unsigned char)(tp[i] >> (8 - i % 7) | tp[i] << (i % 7)));
00204     strcat((char *)encodedData, bs);
00205   }
00206 
00207   return OK;
00208 }
00209 
00210 int License::decode(char *decodedData, const char *data, const unsigned int size)
00211 {
00212   unsigned int i, j = 0;
00213   char bs[3];
00214   unsigned int b;
00215   int t;
00216   char *tp = (char *)(&t);
00217 
00218   if (size < 8)
00219     return ERROR(MSG_LICENSE_INVALID);
00220 
00221   bs[2] = '\0';
00222   for (i = size / 2 - 4; i < size / 2; ++i) {
00223     memcpy(bs, data + i * 2, 2);
00224     sscanf(bs, "%X", &b);
00225     tp[j] = (char)((unsigned char)b << (8 - j % 7) | (unsigned char)b >> (j % 7));
00226     ++j;
00227   }
00228 
00229   t = SWAP32_IF_BE(t);
00230 
00231   printf("Decoding mask: %d.", t);
00232 
00233   for (i = 0; i < size / 2 - 4; ++i) {
00234     memcpy(bs, data + i * 2, 2);
00235     sscanf(bs, "%X", &b);
00236     decodedData[i] = (char)((unsigned char)b << (8 - (t + i) % 7) | (unsigned char)b >> ((t + i) % 7));
00237   }
00238   return OK;
00239 }
00240 
00241 unsigned char License::crc(const char *data, const unsigned int size)
00242 {
00243   unsigned int i;
00244   unsigned char crc = 0;
00245 
00246   for (i = 0; i < size; ++i)
00247     crc ^= data[i];
00248 
00249   return crc;
00250 }
00251 
00252 #ifdef DEBUG_MODE
00253 
00254 int License::test()
00255 {
00256   char *text = "QWERTYUIOPASDFGH";
00257   char clearData[LIMIT_CSTRING_SIZE];
00258   char encodedData[LIMIT_CSTRING_SIZE];
00259   int res;
00260 
00261   bzero(clearData, sizeof(clearData));
00262   bzero(encodedData, sizeof(encodedData));
00263   DEBUG("Algorithm test:\n");
00264   DEBUG("Source data  : '%s'", text);
00265   if (FAILED(res = encode(encodedData, text, strlen(text))))
00266     return ERROR_BACKTRACE(res);
00267   DEBUG("Encoded data : '%s'", encodedData);
00268   if (FAILED(res = decode(clearData, encodedData, strlen(encodedData))))
00269     return ERROR_BACKTRACE(res);
00270   DEBUG("Decoded data : '%s'\n", clearData);
00271 
00272   if (strcmp(clearData, text) == 0)
00273     DEBUG("Test succeeded.\n");
00274   else
00275     DEBUG("Test failed.\n");
00276 
00277   return OK;
00278 }
00279 
00280 #endif

Generated on Thu Sep 6 20:11:25 2007 for Pylon Application Platform by  doxygen 1.5.1