From 8af6b12ee8716d2004d13bbfc81281953975b466 Mon Sep 17 00:00:00 2001 From: open-license-manager <rillf@maildrop.cc> Date: 周一, 04 8月 2014 00:15:33 +0800 Subject: [PATCH] new identifier strategy (to be reverted --- test/scratch/stackoverflow.cpp | 187 +++++++++++++ test/functional/CMakeLists.txt | 14 + test/scratch/base62.c | 131 +++++++++ src/library/os/linux/os-linux.c | 24 + test/scratch/pc-identifiers.c | 415 +++++++++++++++++++++++++++++ test/functional/volid_test.cpp | 10 src/library/pc-identifiers.c | 22 + 7 files changed, 791 insertions(+), 12 deletions(-) diff --git a/src/library/os/linux/os-linux.c b/src/library/os/linux/os-linux.c index b791859..af828bd 100644 --- a/src/library/os/linux/os-linux.c +++ b/src/library/os/linux/os-linux.c @@ -31,6 +31,9 @@ #include <dirent.h> #include <stdio.h> +#include <dbus-1.0/dbus/dbus.h> +#include <sys/utsname.h> + static int ifname_position(char *ifnames, char * ifname, int ifnames_max) { int i, position; position = -1; @@ -49,7 +52,7 @@ FUNCTION_RETURN f_return = OK; struct ifaddrs *ifaddr, *ifa; - int family, i, n, if_name_position; + int family, i, n, if_name_position; unsigned int if_num, if_max; //char host[NI_MAXHOST]; char *ifnames; @@ -408,3 +411,22 @@ return NONE; } +FUNCTION_RETURN getMachineName(unsigned char identifier[6]) { + static struct utsname u; + + if (uname(&u) < 0) { + return ERROR; + } + memcpy(identifier, u.nodename, 6); + return OK; +} + +FUNCTION_RETURN getOsSpecificIdentifier(unsigned char identifier[6]) { + char* dbus_id = dbus_get_local_machine_id(); + if (dbus_id == NULL) { + return ERROR; + } + memcpy(identifier, dbus_id, 6); + dbus_free(dbus_id); + return OK; +} diff --git a/src/library/pc-identifiers.c b/src/library/pc-identifiers.c index e674d77..07a362a 100644 --- a/src/library/pc-identifiers.c +++ b/src/library/pc-identifiers.c @@ -13,6 +13,14 @@ #include "base/base64.h" #include <valgrind/memcheck.h> +FUNCTION_RETURN generate_ethernet_pc_id(PcIdentifier * identifiers, + unsigned int * num_identifiers, bool use_mac); +static void encodeStrategy(PcIdentifier * identifier, + IDENTIFICATION_STRATEGY strategy); +static FUNCTION_RETURN generate_platform_specific_pc_id( + PcIdentifier * identifiers, unsigned int * num_identifiers); + + static FUNCTION_RETURN generate_default_pc_id(PcIdentifier * identifiers, unsigned int * num_identifiers) { size_t adapter_num, disk_num, plat_spec_id; @@ -64,18 +72,20 @@ identifiers[current_identifier][k] = diskInfos[i].disk_sn[k + 2] ^ adapterInfos[j].mac_address[k + 2]; } - encodeStrategy(identifiers[current_identifier], DEFAULT); + encodeStrategy(&identifiers[current_identifier], DEFAULT); current_identifier++; } } free(diskInfos); free(adapterInfos); } else if (result_adapterInfos == OK) { + i=defined_identifiers-current_identifier; return generate_ethernet_pc_id(&identifiers[current_identifier], - defined_identifiers-current_identifier, true); + &i, true); } else if (result_diskinfos == OK) { + i=defined_identifiers-current_identifier; return generate_disk_pc_id(&identifiers[current_identifier], - defined_identifiers-current_identifier, false); + &i, false); } return OK; @@ -84,12 +94,14 @@ static void encodeStrategy(PcIdentifier * identifier, IDENTIFICATION_STRATEGY strategy) { unsigned char strategy_num = strategy << 5; - identifier[0] = (identifier[0] & 15) | strategy_num; + identifier[0][0] = (identifier[0][0] & 15) + + ++ | strategy_num; } static FUNCTION_RETURN generate_platform_specific_pc_id( - PcIdentifier * identifiers, unsigned int * num_identifiers) { + * identifiers, unsigned int * num_identifiers) { } diff --git a/test/functional/CMakeLists.txt b/test/functional/CMakeLists.txt index 66c8195..86296ab 100644 --- a/test/functional/CMakeLists.txt +++ b/test/functional/CMakeLists.txt @@ -44,3 +44,17 @@ ADD_TEST(standard_license_test ${EXECUTABLE_OUTPUT_PATH}/standard_license_test) ADD_TEST(date_test ${EXECUTABLE_OUTPUT_PATH}/date_test) ADD_TEST(volid_test ${EXECUTABLE_OUTPUT_PATH}/volid_test) + + + +add_executable( + stackoverflow + stackoverflow.cpp +) + +target_link_libraries( + stackoverflow + license_generator_lib +) + +SET_TARGET_PROPERTIES(stackoverflow PROPERTIES LINK_SEARCH_START_STATIC ON) \ No newline at end of file diff --git a/test/functional/volid_test.cpp b/test/functional/volid_test.cpp index 501c815..4e1e847 100644 --- a/test/functional/volid_test.cpp +++ b/test/functional/volid_test.cpp @@ -11,12 +11,12 @@ #include "../../src/library/ini/SimpleIni.h" #include "generate-license.h" #include "../../src/library/pc-identifiers.h" -#include <dbus/dbus.h> +#include <dbus-1.0/dbus/dbus.h> namespace fs = boost::filesystem; using namespace license; using namespace std; -/* + BOOST_AUTO_TEST_CASE( default_volid_lic_file ) { const string licLocation(PROJECT_TEST_TEMP_DIR "/volid_license.lic"); PcSignature identifier_out; @@ -99,7 +99,5 @@ } } } - */ -BOOST_AUTO_TEST_CASE( ciiii ) { - cout << dbus_get_local_machine_id() << endl; -} + + diff --git a/test/scratch/base62.c b/test/scratch/base62.c new file mode 100644 index 0000000..7fae217 --- /dev/null +++ b/test/scratch/base62.c @@ -0,0 +1,131 @@ + + +/* Division by 62 on an arbitrary length input. + (TODO: Note: the cast will segfault on some systems, so you will need + to use a memcpy instead). + Also TODO: Optimisation: use >32 bit integers if available. + */ +static void b62_divide(const unsigned char* dividend, int dividend_len, + unsigned char* quotient, unsigned int* remainder) +{ + unsigned int quantity; + int i; + + quantity = 0; + for (i=dividend_len-2;i>=0;i-=2) { + quantity |= *((unsigned short*)÷nd[i]); + *((unsigned short *)"ient[i]) = (unsigned short)(quantity/62); + quantity = (quantity%62)<<16; + } + *remainder = quantity>>16; +} + +/* pseudo-base62 encode + base62 encoding is not a very nice mapping to character data. The only + way that we can properly do this is to divide by 62 each time and get + the remainder, this will ensure full use of the base62 space. This is + /not/ very performant. So instead we operate the base62 encoding on + 56 bit (7 byte) chunks. This gives a pretty good usage, with far less + lengthy division operations on moderately sized input. I only did this + for completeness as I got interested in it, but we can prove that you have + to do the full division each time (although you may find a better way of + implementing it!) as follows. We want to encode data as a bitstream, so + we want to find N,M s.t. 62^M = 2^N, and M,N are integers. There are + no such M,N (proof on request). For base64 encoding we get 64^M = 2^N, + obviously we can fit M=1,N=6 which equates to sucking up 6 bits each time + for the encoding algorithm. So instead we try to find a comprise between + the the block size, and the number of bits wasted by the conversion to + base62 space. The constraints here are + + (1) we want to deal with whole numbers of bytes to simplify the code + (2) we want to waste as little of the encoding space as possible + (3) we want to keep the division operations restricted to a reasonable + number of bits as the running time of the division operation depends + on the length of the input bit string. + + The ratio of the length of the bit strings in the two bases will be + log2(256)/log2(62) + For base64 encoding we get 4/3 exactly. So to minimize waste here we + want to take chunks of 3 bytes, then there is no wastage between blocks. + For base62 encoding we get ~1.34. Picking 5 as the block size wastes + some 30% of the encoding space for the last byte. Let me know if you + think another pick is better. This one means that we are operating + on 40-bit strings, so the division isn't too strenuous to compute, and + on a 64-bit platform can be done all in a register. + */ +#define msg_id_length (((134359*(sizeof(time_t)+sizeof(int)*2))/100000)+2) + +static char base62_tab[62] = { + 'A','B','C','D','E','F','G','H', + 'I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X', + 'Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n', + 'o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3', + '4','5','6','7','8','9' +}; + +int b62_encode(char* out, const unsigned char* data, int length, int linelength) +{ + int i,j; + char *start = out; + uint64_t bitstring; + + linelength; + for (i=0;i<length-4;i+=5) { + bitstring = + (uint64_t)data[i]<<32|(uint64_t)data[i+1]<<24|(uint64_t)data[i+2]<<16| + (uint64_t)data[i+3]<<8|(uint64_t)data[i+4]; + + for (j=0;j<7;++j) { + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + } +/* + b62_divide(quotient,len,quotient,&rem); + *out++ = base62_tab[rem]; + for (j=1;j<len;++j) { + b62_divide(quotient,len,quotient,&rem); + *out++ = base62_tab[rem]; + }*/ + } + switch (length-i) { + case 1: + *out++ = base62_tab[data[i]%62]; + *out++ = base62_tab[data[i]/62]; + break; + case 2: + bitstring = data[i]<<8|data[i+1]; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + *out++ = base62_tab[bitstring/62]; + break; + case 3: + bitstring = data[i]<<16|data[i+1]<<8|data[i]; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + *out++ = base62_tab[bitstring/62]; + break; + case 4: + bitstring = data[i]<<24|data[i+1]<<16|data[i+2]<<8|data[i]; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + bitstring /= 62; + *out++ = base62_tab[bitstring%62]; + *out++ = base62_tab[bitstring/62]; + break; + } + return (int)(out-start); +} diff --git a/test/scratch/pc-identifiers.c b/test/scratch/pc-identifiers.c new file mode 100644 index 0000000..07a362a --- /dev/null +++ b/test/scratch/pc-identifiers.c @@ -0,0 +1,415 @@ +/* + * pc-identifiers.c + * + * Created on: Apr 16, 2014 + * Author: devel + */ + +#include "os/os.h" +#include "pc-identifiers.h" +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include "base/base64.h" +#include <valgrind/memcheck.h> + +FUNCTION_RETURN generate_ethernet_pc_id(PcIdentifier * identifiers, + unsigned int * num_identifiers, bool use_mac); +static void encodeStrategy(PcIdentifier * identifier, + IDENTIFICATION_STRATEGY strategy); +static FUNCTION_RETURN generate_platform_specific_pc_id( + PcIdentifier * identifiers, unsigned int * num_identifiers); + + +static FUNCTION_RETURN generate_default_pc_id(PcIdentifier * identifiers, + unsigned int * num_identifiers) { + size_t adapter_num, disk_num, plat_spec_id; + FUNCTION_RETURN result_adapterInfos, result_diskinfos, result_plat_spec; + unsigned int required_id_size, current_identifier, i, j, k; + DiskInfo * diskInfos; + AdapterInfo *adapterInfos; + required_id_size = 0; + + //just calculate the number of required identifiers + result_plat_spec = generate_platform_specific_pc_id(NULL, &plat_spec_id); + if (result_plat_spec == OK) { + required_id_size += 1; + } + result_adapterInfos = getAdapterInfos(NULL, &adapter_num); + result_diskinfos = getDiskInfos(NULL, &disk_num); + if (result_diskinfos == OK && result_adapterInfos == OK) { + required_id_size += disk_num * adapter_num; + } else if (result_adapterInfos == OK) { + required_id_size += adapter_num; + } else if (result_diskinfos == OK) { + required_id_size += disk_num; + } + int defined_identifiers = *num_identifiers; + if (identifiers == NULL) { + *num_identifiers = required_id_size; + return OK; + } else if (required_id_size > defined_identifiers) { + return BUFFER_TOO_SMALL; + } + + //calculate the identifiers + current_identifier = 0; + if (result_plat_spec == OK) { + generate_platform_specific_pc_id(identifiers, 1); + current_identifier += 1; + } + if (result_diskinfos == OK && result_adapterInfos == OK) { + diskInfos = (DiskInfo*) malloc(disk_num * sizeof(DiskInfo)); + result_diskinfos = getDiskInfos(diskInfos, &disk_num); + adapterInfos = (AdapterInfo*) malloc(adapter_num * sizeof(AdapterInfo)); + result_adapterInfos = getAdapterInfos(adapterInfos, &adapter_num); + for (i = 0; i < disk_num; i++) { + for (j = 0; j < adapter_num; j++) { + if (current_identifier > defined_identifiers) { + break; + } + for (k = 0; k < 6; k++) { + identifiers[current_identifier][k] = diskInfos[i].disk_sn[k + + 2] ^ adapterInfos[j].mac_address[k + 2]; + } + encodeStrategy(&identifiers[current_identifier], DEFAULT); + current_identifier++; + } + } + free(diskInfos); + free(adapterInfos); + } else if (result_adapterInfos == OK) { + i=defined_identifiers-current_identifier; + return generate_ethernet_pc_id(&identifiers[current_identifier], + &i, true); + } else if (result_diskinfos == OK) { + i=defined_identifiers-current_identifier; + return generate_disk_pc_id(&identifiers[current_identifier], + &i, false); + } + + return OK; +} + +static void encodeStrategy(PcIdentifier * identifier, + IDENTIFICATION_STRATEGY strategy) { + unsigned char strategy_num = strategy << 5; + identifier[0][0] = (identifier[0][0] & 15) + + ++ | strategy_num; + +} + +static FUNCTION_RETURN generate_platform_specific_pc_id( + * identifiers, unsigned int * num_identifiers) { + +} + +static FUNCTION_RETURN generate_ethernet_pc_id(PcIdentifier * identifiers, + unsigned int * num_identifiers, bool use_mac) { + size_t adapters; + FUNCTION_RETURN result_adapterInfos; + unsigned int j, k; + AdapterInfo *adapterInfos; + + result_adapterInfos = getAdapterInfos(NULL, &adapters); + if (result_adapterInfos != OK) { + return result_adapterInfos; + } + + int defined_adapters = *num_identifiers; + *num_identifiers = adapters; + if (identifiers == NULL) { + return OK; + } else if (adapters > defined_adapters) { + return BUFFER_TOO_SMALL; + } + + adapterInfos = (AdapterInfo*) malloc(adapters * sizeof(AdapterInfo)); + result_adapterInfos = getAdapterInfos(adapterInfos, &adapters); + for (j = 0; j < adapters; j++) { + for (k = 0; k < 6; k++) + if (use_mac) { + identifiers[j][k] = adapterInfos[j].mac_address[k + 2]; + } else { + //use ip + if (k < 4) { + identifiers[j][k] = adapterInfos[j].ipv4_address[k]; + } else { + //padding + identifiers[j][k] = 42; + } + } + } + free(adapterInfos); + return OK; +} + +static FUNCTION_RETURN generate_disk_pc_id(PcIdentifier * identifiers, + unsigned int * num_identifiers, bool use_label) { + size_t disk_num, available_disk_info = 0; + FUNCTION_RETURN result_diskinfos; + unsigned int i, j; + char firstChar; + DiskInfo * diskInfos; + + result_diskinfos = getDiskInfos(NULL, &disk_num); + if (result_diskinfos != OK) { + return result_diskinfos; + } + diskInfos = (DiskInfo*) malloc(disk_num * sizeof(DiskInfo)); +//memset(diskInfos,0,disk_num * sizeof(DiskInfo)); + result_diskinfos = getDiskInfos(diskInfos, &disk_num); + if (result_diskinfos != OK) { + free(diskInfos); + return result_diskinfos; + } + for (i = 0; i < disk_num; i++) { + firstChar = use_label ? diskInfos[i].label[0] : diskInfos[i].disk_sn[0]; + available_disk_info += firstChar == 0 ? 0 : 1; + } + + int defined_identifiers = *num_identifiers; + *num_identifiers = available_disk_info; + if (identifiers == NULL) { + free(diskInfos); + return OK; + } else if (available_disk_info > defined_identifiers) { + free(diskInfos); + return BUFFER_TOO_SMALL; + } + + j = 0; + for (i = 0; i < disk_num; i++) { + if (use_label) { + if (diskInfos[i].label[0] != 0) { + memset(identifiers[j], 0, sizeof(PcIdentifier)); //!!!!!!! + strncpy(identifiers[j], diskInfos[i].label, + sizeof(PcIdentifier)); + j++; + } + } else { + if (diskInfos[i].disk_sn[0] != 0) { + memcpy(identifiers[j], &diskInfos[i].disk_sn[2], + sizeof(PcIdentifier)); + j++; + } + } + } + free(diskInfos); + return OK; +} + +/** + * + * Calculates all the possible identifiers for the current machine, for the + * given calculation strategy requested. Pc identifiers are more than one, + * for instance a machine with more than one disk and one network interface has + * usually multiple identifiers. + * + * First 4 bit of each pc identifier are reserved 3 for the type of strategy + * used in calculation and 1 for parity checks (not implemented here) + * + * @param identifiers + * @param array_size + * @param + * @return + */ +FUNCTION_RETURN generate_pc_id(PcIdentifier * identifiers, + unsigned int * array_size, IDENTIFICATION_STRATEGY strategy) { + FUNCTION_RETURN result; + unsigned int i, j; + const unsigned int original_array_size = *array_size; + unsigned char strategy_num; + switch (strategy) { + case DEFAULT: + result = generate_default_pc_id(identifiers, array_size); + break; + case ETHERNET: + result = generate_ethernet_pc_id(identifiers, array_size, true); + break; + case IP_ADDRESS: + result = generate_ethernet_pc_id(identifiers, array_size, false); + break; + case DISK_NUM: + result = generate_disk_pc_id(identifiers, array_size, false); + break; + case PLATFORM_SPECIFIC: + result = generate_platform_specific_pc_id(identifiers, array_size); + break; + default: + return ERROR; + } + + if (result == OK && identifiers != NULL) { + //fill array if larger + for (i = *array_size; i < original_array_size; i++) { + identifiers[i][0] = STRATEGY_UNKNOWN << 5; + for (j = 1; j < sizeof(PcIdentifier); j++) { + identifiers[i][j] = 42; //padding + } + } + } + return result; +} + +char *MakeCRC(char *BitString) { + static char Res[3]; // CRC Result + char CRC[2]; + int i; + char DoInvert; + + for (i = 0; i < 2; ++i) + CRC[i] = 0; // Init before calculation + + for (i = 0; i < strlen(BitString); ++i) { + DoInvert = ('1' == BitString[i]) ^ CRC[1]; // XOR required? + + CRC[1] = CRC[0]; + CRC[0] = DoInvert; + } + + for (i = 0; i < 2; ++i) + Res[1 - i] = CRC[i] ? '1' : '0'; // Convert binary to ASCII + Res[2] = 0; // Set string terminator + + return (Res); +} + +FUNCTION_RETURN encode_pc_id(PcIdentifier identifier1, PcIdentifier identifier2, + PcSignature pc_identifier_out) { +//TODO base62 encoding, now uses base64 + PcIdentifier concat_identifiers[2]; + int b64_size = 0; + size_t concatIdentifiersSize = sizeof(PcIdentifier) * 2; +//concat_identifiers = (PcIdentifier *) malloc(concatIdentifiersSize); + memcpy(&concat_identifiers[0], identifier1, sizeof(PcIdentifier)); + memcpy(&concat_identifiers[1], identifier2, sizeof(PcIdentifier)); + char* b64_data = base64(concat_identifiers, concatIdentifiersSize, + &b64_size); + if (b64_size > sizeof(PcSignature)) { + return BUFFER_TOO_SMALL; + } + sprintf(pc_identifier_out, "%.4s-%.4s-%.4s-%.4s", &b64_data[0], + &b64_data[4], &b64_data[8], &b64_data[12]); +//free(concat_identifiers); + free(b64_data); + return OK; +} + +FUNCTION_RETURN parity_check_id(PcSignature pc_identifier) { + return OK; +} + +FUNCTION_RETURN generate_user_pc_signature(PcSignature identifier_out, + IDENTIFICATION_STRATEGY strategy) { + FUNCTION_RETURN result; + PcIdentifier* identifiers; + unsigned int req_buffer_size = 0; + result = generate_pc_id(NULL, &req_buffer_size, strategy); + if (result != OK) { + return result; + } + if (req_buffer_size == 0) { + return ERROR; + } + req_buffer_size = req_buffer_size < 2 ? 2 : req_buffer_size; + identifiers = (PcIdentifier *) malloc( + sizeof(PcIdentifier) * req_buffer_size); + result = generate_pc_id(identifiers, &req_buffer_size, strategy); + if (result != OK) { + free(identifiers); + return result; + } + VALGRIND_CHECK_VALUE_IS_DEFINED(identifiers[0]); + VALGRIND_CHECK_VALUE_IS_DEFINED(identifiers[1]); + result = encode_pc_id(identifiers[0], identifiers[1], identifier_out); + VALGRIND_CHECK_VALUE_IS_DEFINED(identifier_out); + free(identifiers); + return result; +} + +/** + * Extract the two pc identifiers from the user provided code. + * @param identifier1_out + * @param identifier2_out + * @param str_code: the code in the string format XXXX-XXXX-XXXX-XXXX + * @return + */ +static FUNCTION_RETURN decode_pc_id(PcIdentifier identifier1_out, + PcIdentifier identifier2_out, PcSignature pc_signature_in) { +//TODO base62 encoding, now uses base64 + + unsigned char * concat_identifiers; + char base64ids[17]; + int identifiers_size; + + sscanf(pc_signature_in, "%4s-%4s-%4s-%4s", &base64ids[0], &base64ids[4], + &base64ids[8], &base64ids[12]); + concat_identifiers = unbase64(base64ids, 16, &identifiers_size); + if (identifiers_size > sizeof(PcIdentifier) * 2) { + return BUFFER_TOO_SMALL; + } + memcpy(identifier1_out, concat_identifiers, sizeof(PcIdentifier)); + memcpy(identifier2_out, concat_identifiers + sizeof(PcIdentifier), + sizeof(PcIdentifier)); + free(concat_identifiers); + return OK; +} + +static IDENTIFICATION_STRATEGY strategy_from_pc_id(PcIdentifier identifier) { + return (IDENTIFICATION_STRATEGY) identifier[0] >> 5; +} + +EVENT_TYPE validate_pc_signature(PcSignature str_code) { + PcIdentifier user_identifiers[2]; + FUNCTION_RETURN result; + IDENTIFICATION_STRATEGY previous_strategy_id, current_strategy_id; + PcIdentifier* calculated_identifiers = NULL; + unsigned int calc_identifiers_size = 0; + int i = 0, j = 0; +//bool found; +#ifdef _DEBUG + printf("Comparing pc identifiers: \n"); +#endif + result = decode_pc_id(user_identifiers[0], user_identifiers[1], str_code); + if (result != OK) { + return result; + } + previous_strategy_id = STRATEGY_UNKNOWN; +//found = false; + for (i = 0; i < 2; i++) { + current_strategy_id = strategy_from_pc_id(user_identifiers[i]); + if (current_strategy_id == STRATEGY_UNKNOWN) { + return LICENSE_MALFORMED; + } + if (current_strategy_id != previous_strategy_id) { + if (calculated_identifiers != NULL) { + free(calculated_identifiers); + } + previous_strategy_id = current_strategy_id; + generate_pc_id(NULL, &calc_identifiers_size, current_strategy_id); + calculated_identifiers = (PcIdentifier *) malloc( + sizeof(PcIdentifier) * calc_identifiers_size); + generate_pc_id(calculated_identifiers, &calc_identifiers_size, + current_strategy_id); + } + //maybe skip the byte 0 + for (j = 0; j < calc_identifiers_size; j++) { +#ifdef _DEBUG + printf("generated id: %02x%02x%02x%02x%02x%02x index %d, user_supplied id %02x%02x%02x%02x%02x%02x idx: %d\n", + calculated_identifiers[j][0],calculated_identifiers[j][1],calculated_identifiers[j][2], + calculated_identifiers[j][3],calculated_identifiers[j][4],calculated_identifiers[j][5],j, + user_identifiers[i][0],user_identifiers[i][1],user_identifiers[i][2],user_identifiers[i][3],user_identifiers[i][4],user_identifiers[i][5],i); + +#endif + if (!memcmp(user_identifiers[i], calculated_identifiers[j], + sizeof(PcIdentifier))) { + free(calculated_identifiers); + return LICENSE_OK; + } + } + } + free(calculated_identifiers); + return IDENTIFIERS_MISMATCH; +} diff --git a/test/scratch/stackoverflow.cpp b/test/scratch/stackoverflow.cpp new file mode 100644 index 0000000..198bfc8 --- /dev/null +++ b/test/scratch/stackoverflow.cpp @@ -0,0 +1,187 @@ +//http://stackoverflow.com/questions/16858782/how-to-obtain-almost-unique-system-identifier-in-a-cross-platform-way +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/resource.h> +#include <sys/utsname.h> +#include <netdb.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <assert.h> +#include <stdbool.h> + +#ifdef DARWIN +#include <net/if_dl.h> +#include <ifaddrs.h> +#include <net/if_types.h> +#else //!DARWIN +#include <linux/if.h> +#include <linux/sockios.h> +#endif //!DARWIN + +const char* getMachineName() { + static struct utsname u; + + if (uname(&u) < 0) { + assert(0); + return "unknown"; + } + + return u.nodename; +} + +//---------------------------------get MAC addresses ------------------------------------unsigned short-unsigned short---------- +// we just need this for purposes of unique machine id. So any one or two mac's is fine. +unsigned short hashMacAddress(unsigned char* mac) { + unsigned short hash = 0; + + for (unsigned int i = 0; i < 6; i++) { + hash += (mac[i] << ((i & 1) * 8)); + } + return hash; +} + +void getMacHash(unsigned short *mac1, unsigned short *mac2) { + *mac1 = 0; + *mac2 = 0; + +#ifdef DARWIN + + struct ifaddrs* ifaphead; + if ( getifaddrs( &ifaphead ) != 0 ) + return; + + // iterate over the net interfaces + bool foundMac1 = false; + struct ifaddrs* ifap; + for ( ifap = ifaphead; ifap; ifap = ifap->ifa_next ) + { + struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifap->ifa_addr; + if ( sdl && ( sdl->sdl_family == AF_LINK ) && ( sdl->sdl_type == IFT_ETHER )) + { + if ( !foundMac1 ) + { + foundMac1 = true; + mac1 = hashMacAddress( (unsigned char*)(LLADDR(sdl))); //sdl->sdl_data) + sdl->sdl_nlen) ); + } else { + mac2 = hashMacAddress( (unsigned char*)(LLADDR(sdl))); //sdl->sdl_data) + sdl->sdl_nlen) ); + break; + } + } + } + + freeifaddrs( ifaphead ); + +#else // !DARWIN + + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sock < 0) + return; + + // enumerate all IP addresses of the system + struct ifconf conf; + char ifconfbuf[128 * sizeof(struct ifreq)]; + memset(ifconfbuf, 0, sizeof(ifconfbuf)); + conf.ifc_buf = ifconfbuf; + conf.ifc_len = sizeof(ifconfbuf); + if (ioctl(sock, SIOCGIFCONF, &conf)) { + assert(0); + return; + } + + // get MAC address + bool foundMac1 = false; + struct ifreq* ifr; + for (ifr = conf.ifc_req; (char*) ifr < (char*) conf.ifc_req + conf.ifc_len; + ifr++) { + if (ifr->ifr_addr.sa_data == (ifr + 1)->ifr_addr.sa_data) + continue; // duplicate, skip it + + if (ioctl(sock, SIOCGIFFLAGS, ifr)) + continue; // failed to get flags, skip it + if (ioctl(sock, SIOCGIFHWADDR, ifr) == 0) { + if (!foundMac1) { + foundMac1 = true; + *mac1 = hashMacAddress( + (unsigned char*) &(ifr->ifr_addr.sa_data)); + } else { + *mac2 = hashMacAddress( + (unsigned char*) &(ifr->ifr_addr.sa_data)); + break; + } + } + } + + close(sock); + +#endif // !DARWIN + + // sort the mac addresses. We don't want to invalidate + // both macs if they just change order. + if (*mac1 > *mac2) { + unsigned short tmp = *mac2; + *mac2 = *mac1; + *mac1 = tmp; + } +} + +unsigned short getVolumeHash() { + // we don't have a 'volume serial number' like on windows. Lets hash the system name instead. + unsigned char* sysname = (unsigned char*) getMachineName(); + unsigned short hash = 0; + + for (unsigned int i = 0; sysname[i]; i++) + hash += (sysname[i] << ((i & 1) * 8)); + + return hash; +} + +#ifdef DARWIN +#include <mach-o/arch.h> +unsigned short getCpuHash() +{ + const NXArchInfo* info = NXGetLocalArchInfo(); + unsigned short val = 0; + val += (unsigned short)info->cputype; + val += (unsigned short)info->cpusubtype; + return val; +} + +#else // !DARWIN + +static void getCpuid(unsigned int* p, unsigned int ax) { + __asm __volatile + ( "movl %%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl %%ebx, %%esi" + : "=a" (p[0]), "=S" (p[1]), + "=c" (p[2]), "=d" (p[3]) + : "0" (ax) + ); +} + +unsigned short getCpuHash() { + unsigned int cpuinfo[4] = { 0, 0, 0, 0 }; + getCpuid(cpuinfo, 0); + unsigned short hash = 0; + unsigned int* ptr = (&cpuinfo[0]); + for (unsigned int i = 0; i < 4; i++) + hash += (ptr[i] & 0xFFFF) + (ptr[i] >> 16); + + return hash; +} +#endif // !DARWIN + +int main() { + + printf("Machine: %s\n", getMachineName()); + printf("CPU: %d\n", getCpuHash()); + printf("Volume: %d\n", getVolumeHash()); + return 0; +} -- Gitblit v1.9.1