From d5cfca5d6eae5fdc99f04e50c19b12e1803ca90b Mon Sep 17 00:00:00 2001 From: open-license-manager <rillf@maildrop.cc> Date: ćšć, 16 10æ 2014 02:55:25 +0800 Subject: [PATCH] optional dbus --- src/library/os/linux/os-linux.c | 461 +++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 319 insertions(+), 142 deletions(-) diff --git a/src/library/os/linux/os-linux.c b/src/library/os/linux/os-linux.c index b316c17..79ec0e5 100644 --- a/src/library/os/linux/os-linux.c +++ b/src/library/os/linux/os-linux.c @@ -1,15 +1,9 @@ -#define _GNU_SOURCE /* To get defns of NI_MAXSERV and NI_MAXHOST */ -#include <arpa/inet.h> -#include <sys/socket.h> -#include <netdb.h> -#include <ifaddrs.h> #include <stdio.h> +#include <ctype.h> #include <stdlib.h> #include <unistd.h> -#include <linux/if_link.h> -#include <sys/socket.h> -#include <netpacket/packet.h> +#include <valgrind/memcheck.h> #include <paths.h> #include <stdlib.h> @@ -19,161 +13,204 @@ #include <sys/ioctl.h> #include <sys/stat.h> #include "../os.h" -#include "../../base/public-key.h" +#include "public-key.h" +#include "../../base/logger.h" #include <openssl/evp.h> #include <openssl/bio.h> #include <openssl/pem.h> #include <openssl/err.h> -static int ifname_position(char *ifnames, char * ifname, int ifnames_max) { - int i, position; - position = -1; - for (i = 0; i < ifnames_max; i++) { - if (strcmp(ifname, &ifnames[i * NI_MAXHOST]) == 0) { - position = i; - break; - } - } - return position; +#include <mntent.h> +#include <dirent.h> +#include <stdio.h> -} +#include <sys/utsname.h> +#ifdef USE_DBUS +#include <dbus-1.0/dbus/dbus.h> +#endif -FUNCTION_RETURN getAdapterInfos(AdapterInfo * adapterInfos, - size_t * adapter_info_size) { +/** + *Usually uuid are hex number separated by "-". this method read up to 8 hex + *numbers skipping - characters. + *@param uuid uuid as read in /dev/disk/by-uuid + *@param buffer_out: unsigned char buffer[8] output buffer for result + */ +static void parseUUID(const char *uuid, unsigned char* buffer_out, + unsigned int out_size) { + size_t len; + unsigned int i, j; + char * hexuuid; + unsigned char cur_character; + //remove characters not in hex set + len = strlen(uuid); + hexuuid = (char *) malloc(sizeof(char) * strlen(uuid)); + memset(buffer_out, 0, out_size); + memset(hexuuid, 0, sizeof(char) * strlen(uuid)); - FUNCTION_RETURN f_return = OK; - struct ifaddrs *ifaddr, *ifa; - int family, i, s, n, if_name_position; - unsigned int if_num, if_max; - char host[NI_MAXHOST]; - char *ifnames; - - if (getifaddrs(&ifaddr) == -1) { - perror("getifaddrs"); - return ERROR; - } - /* count the maximum number of interfaces */ - for (ifa = ifaddr, if_max = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { - if (ifa->ifa_addr == NULL) { + for (i = 0, j = 0; i < len; i++) { + if (isxdigit(uuid[i])) { + hexuuid[j] = uuid[i]; + j++; + } else { + //skip continue; } - if_max++; + } + if (j % 2 == 1) { + hexuuid[j++] = '0'; + } + hexuuid[j] = '\0'; + for (i = 0; i < j / 2; i++) { + sscanf(&hexuuid[i * 2], "%2hhx", &cur_character); + buffer_out[i % out_size] = buffer_out[i % out_size] ^ cur_character; } - /* allocate space for names */ - ifnames = (char*) malloc(NI_MAXHOST * if_max); - memset(ifnames, 0, NI_MAXHOST * if_max); - /* Walk through linked list, maintaining head pointer so we - can free list later */ - for (ifa = ifaddr, n = 0, if_num = 0; ifa != NULL; - ifa = ifa->ifa_next, n++) { - if (ifa->ifa_addr == NULL) { - continue; - } - if_name_position = ifname_position(ifnames, ifa->ifa_name, if_num); - //interface name not seen en advance - if (if_name_position < 0) { - strncpy(&ifnames[if_num * NI_MAXHOST], ifa->ifa_name, NI_MAXHOST); - if (adapterInfos != NULL && if_num < *adapter_info_size) { - strncpy(adapterInfos[if_num].description, ifa->ifa_name, - NI_MAXHOST); - } - if_name_position = if_num; - if_num++; - if (adapterInfos == NULL) { - continue; - } - } - family = ifa->ifa_addr->sa_family; - /* Display interface name and family (including symbolic - form of the latter for the common families) */ -#ifdef _DEBUG - printf("%-8s %s (%d)\n", ifa->ifa_name, - (family == AF_PACKET) ? "AF_PACKET" : - (family == AF_INET) ? "AF_INET" : - (family == AF_INET6) ? "AF_INET6" : "???", family); -#endif - /* For an AF_INET* interface address, display the address - * || family == AF_INET6*/ - if (family == AF_INET) { - /* - s = getnameinfo(ifa->ifa_addr, - (family == AF_INET) ? - sizeof(struct sockaddr_in) : - sizeof(struct sockaddr_in6), host, NI_MAXHOST, - NULL, 0, NI_NUMERICHOST); - */ -#ifdef _DEBUG - s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, - NI_MAXHOST, - NULL, 0, NI_NUMERICHOST); - if (s != 0) { - printf("getnameinfo() failed: %s\n", gai_strerror(s)); - } - printf("\t\taddress: <%s>\n", host); -#endif - - if (adapterInfos != NULL && if_name_position < *adapter_info_size) { - struct sockaddr_in *s1 = (struct sockaddr_in*) ifa->ifa_addr; - in_addr_t iaddr = s1->sin_addr.s_addr; - adapterInfos[if_name_position].ipv4_address[0] = (iaddr - & 0x000000ff); - adapterInfos[if_name_position].ipv4_address[1] = (iaddr - & 0x0000ff00) >> 8; - adapterInfos[if_name_position].ipv4_address[2] = (iaddr - & 0x00ff0000) >> 16; - adapterInfos[if_name_position].ipv4_address[3] = (iaddr - & 0xff000000) >> 24; - } - } else if (family == AF_PACKET && ifa->ifa_data != NULL) { - struct sockaddr_ll *s1 = (struct sockaddr_ll*) ifa->ifa_addr; - if (adapterInfos != NULL && if_name_position < *adapter_info_size) { - for (i = 0; i < 6; i++) { - adapterInfos[if_name_position].mac_address[i] = - s1->sll_addr[i]; -#ifdef _DEBUG - printf("%02x:", s1->sll_addr[i]); -#endif - } -#ifdef _DEBUG - printf("\t %s\n", ifa->ifa_name); -#endif - - } - } - } - - *adapter_info_size = if_num; - if (adapterInfos == NULL) { - f_return = OK; - } else if (*adapter_info_size < if_num) { - f_return = BUFFER_TOO_SMALL; - } - freeifaddrs(ifaddr); - return f_return; + free(hexuuid); } +#define MAX_UNITS 20 FUNCTION_RETURN getDiskInfos(DiskInfo * diskInfos, size_t * disk_info_size) { - struct stat filename_stat, mount_stat; - static char discard[1024]; - char device[64], name[64], type[64]; - FILE *mounts = fopen(_PATH_MOUNTED, "r"); - if (mounts == NULL) { - return ERROR; + struct stat mount_stat, sym_stat; + /*static char discard[1024]; + char device[64], name[64], type[64]; + */ + char cur_dir[MAX_PATH]; + struct mntent *ent; + + int maxDrives, currentDrive, i, drive_found; + __ino64_t *statDrives; + DiskInfo *tmpDrives; + FILE *aFile; + DIR *disk_by_uuid_dir, *disk_by_label; + struct dirent *dir; + FUNCTION_RETURN result; + + if (diskInfos != NULL) { + maxDrives = *disk_info_size; + tmpDrives = diskInfos; + } else { + maxDrives = MAX_UNITS; + tmpDrives = (DiskInfo *) malloc(sizeof(DiskInfo) * maxDrives); + } + memset(tmpDrives, 0, sizeof(DiskInfo) * maxDrives); + statDrives = (__ino64_t *) malloc(maxDrives * sizeof(__ino64_t )); + memset(statDrives, 0, sizeof(__ino64_t ) * maxDrives); + ; + + aFile = setmntent("/proc/mounts", "r"); + if (aFile == NULL) { + /*proc not mounted*/ + return FUNC_RET_ERROR; } - while (fscanf(mounts, "%64s %64s %64s %1024[^\n]", device, name, type, - discard) != EOF) { - if (stat(device, &mount_stat) != 0) - continue; - if (filename_stat.st_dev == mount_stat.st_rdev) { - fprintf(stderr, "device: %s; name: %s; type: %s\n", device, name, - type); + currentDrive = 0; + while (NULL != (ent = getmntent(aFile))) { + if ((strncmp(ent->mnt_type, "ext", 3) == 0 + || strncmp(ent->mnt_type, "vfat", 4) == 0 + || strncmp(ent->mnt_type, "ntfs", 4) == 0) + && ent->mnt_fsname != NULL + && strncmp(ent->mnt_fsname, "/dev/", 5) == 0) { + if (stat(ent->mnt_fsname, &mount_stat) == 0) { + drive_found = -1; + for (i = 0; i < currentDrive; i++) { + if (statDrives[i] == mount_stat.st_ino) { + drive_found = i; + } + } + if (drive_found == -1) { + LOG_DEBUG("mntent: %s %s %d\n", ent->mnt_fsname, ent->mnt_dir, + (unsigned long int)mount_stat.st_ino); + strcpy(tmpDrives[currentDrive].device, ent->mnt_fsname); + statDrives[currentDrive] = mount_stat.st_ino; + drive_found = currentDrive; + currentDrive++; + } + if (strcmp(ent->mnt_dir, "/") == 0) { + strcpy(tmpDrives[drive_found].label, "root"); + LOG_DEBUG("drive %s set to preferred\n", ent->mnt_fsname); + tmpDrives[drive_found].preferred = true; + } + } } } + endmntent(aFile); - return ERROR; + if (diskInfos == NULL) { + *disk_info_size = currentDrive; + free(tmpDrives); + result = FUNC_RET_OK; + } else if (*disk_info_size >= currentDrive) { + disk_by_uuid_dir = opendir("/dev/disk/by-uuid"); + if (disk_by_uuid_dir == NULL) { + LOG_WARN("Open /dev/disk/by-uuid fail"); + free(statDrives); + return FUNC_RET_ERROR; + } + result = FUNC_RET_OK; + *disk_info_size = currentDrive; + while ((dir = readdir(disk_by_uuid_dir)) != NULL) { + strcpy(cur_dir, "/dev/disk/by-uuid/"); + strncat(cur_dir, dir->d_name, 200); + if (stat(cur_dir, &sym_stat) == 0) { + for (i = 0; i < currentDrive; i++) { + if (sym_stat.st_ino == statDrives[i]) { + parseUUID(dir->d_name, tmpDrives[i].disk_sn, + sizeof(tmpDrives[i].disk_sn)); +#ifdef _DEBUG + VALGRIND_CHECK_VALUE_IS_DEFINED(tmpDrives[i].device); + + LOG_DEBUG("uuid %d %s %02x%02x%02x%02x\n", i, + tmpDrives[i].device, + tmpDrives[i].disk_sn[0], + tmpDrives[i].disk_sn[1], + tmpDrives[i].disk_sn[2], + tmpDrives[i].disk_sn[3]); +#endif + } + } + } + } + closedir(disk_by_uuid_dir); + + disk_by_label = opendir("/dev/disk/by-label"); + if (disk_by_label != NULL) { + while ((dir = readdir(disk_by_label)) != NULL) { + strcpy(cur_dir, "/dev/disk/by-label/"); + strcat(cur_dir, dir->d_name); + if (stat(cur_dir, &sym_stat) == 0) { + for (i = 0; i < currentDrive; i++) { + if (sym_stat.st_ino == statDrives[i]) { + strncpy(tmpDrives[i].label, dir->d_name, 255); + printf("label %d %s %s\n", i, tmpDrives[i].label, + tmpDrives[i].device); + } + } + } + } + closedir(disk_by_label); + } + } else { + result = FUNC_RET_BUFFER_TOO_SMALL; + } + /* + FILE *mounts = fopen(_PATH_MOUNTED, "r"); + if (mounts == NULL) { + return ERROR; + } + + while (fscanf(mounts, "%64s %64s %64s %1024[^\n]", device, name, type, + discard) != EOF) { + if (stat(device, &mount_stat) != 0) + continue; + if (filename_stat.st_dev == mount_stat.st_rdev) { + fprintf(stderr, "device: %s; name: %s; type: %s\n", device, name, + type); + } + } + */ + free(statDrives); + return result; } void os_initialize() { @@ -184,6 +221,28 @@ ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); } +} + +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) + ); +} + +FUNCTION_RETURN getCpuId(unsigned char identifier[6]) { + unsigned int i; + unsigned int cpuinfo[4] = { 0, 0, 0, 0 }; + _getCpuid(cpuinfo, 0); + for (i = 0; i < 3; i++) { + identifier[i * 2] = cpuinfo[i] & 0xFF; + identifier[i * 2 + 1] = (cpuinfo[i] & 0xFF00) >> 8; + } + return FUNC_RET_OK; } VIRTUALIZATION getVirtualization() { @@ -209,3 +268,121 @@ return NONE; } +FUNCTION_RETURN getMachineName(unsigned char identifier[6]) { + static struct utsname u; + + if (uname(&u) < 0) { + return FUNC_RET_ERROR; + } + memcpy(identifier, u.nodename, 6); + return FUNC_RET_OK; +} + +FUNCTION_RETURN getOsSpecificIdentifier(unsigned char identifier[6]) { +#if USE_DBUS + char* dbus_id = dbus_get_local_machine_id(); + if (dbus_id == NULL) { + return FUNC_RET_ERROR; + } + memcpy(identifier, dbus_id, 6); + dbus_free(dbus_id); + return FUNC_RET_OK; +#else + return FUNC_RET_NOT_AVAIL; +#endif +} + +FUNCTION_RETURN getModuleName(char buffer[MAX_PATH]) { + FUNCTION_RETURN result; + char path[MAX_PATH] = { 0 }; + char proc_path[MAX_PATH], pidStr[64]; + pid_t pid = getpid(); + sprintf(pidStr, "%d", pid); + strcpy(proc_path, "/proc/"); + strcat(proc_path, pidStr); + strcat(proc_path, "/exe"); + + int ch = readlink(proc_path, path, MAX_PATH); + if (ch != -1) { + path[ch] = '\0'; + strncpy(buffer, path, ch); + result = FUNC_RET_OK; + } else { + result = FUNC_RET_ERROR; + } + return result; +} + +static void free_resources(EVP_PKEY* pkey, EVP_MD_CTX* mdctx) { + if (pkey) { + EVP_PKEY_free(pkey); + } + if (mdctx) { + EVP_MD_CTX_destroy(mdctx); + } +} + +FUNCTION_RETURN verifySignature(const char* stringToVerify, + const char* signatureB64) { + EVP_MD_CTX *mdctx = NULL; + const char *pubKey = PUBLIC_KEY; + int func_ret = 0; + + BIO* bio = BIO_new_mem_buf((void*) (pubKey), strlen(pubKey)); + RSA *rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL); + BIO_free(bio); + if (rsa == NULL) { + LOG_ERROR("Error reading public key"); + return FUNC_RET_ERROR; + } + EVP_PKEY *pkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(pkey, rsa); + + /*BIO* bo = BIO_new(BIO_s_mem()); + BIO_write(bo, pubKey, strlen(pubKey)); + RSA *key = 0; + PEM_read_bio_RSAPublicKey(bo, &key, 0, 0); + BIO_free(bo);*/ + +//RSA* rsa = EVP_PKEY_get1_RSA( key ); +//RSA * pubKey = d2i_RSA_PUBKEY(NULL, <der encoded byte stream pointer>, <num bytes>); + unsigned char buffer[512]; + BIO* b64 = BIO_new(BIO_f_base64()); + BIO* encoded_signature = BIO_new_mem_buf((void *) signatureB64, + strlen(signatureB64)); + BIO* biosig = BIO_push(b64, encoded_signature); + BIO_set_flags(biosig, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer + unsigned int len = BIO_read(biosig, (void *) buffer, strlen(signatureB64)); +//Can test here if len == decodeLen - if not, then return an error + buffer[len] = 0; + + BIO_free_all(biosig); + + /* Create the Message Digest Context */ + if (!(mdctx = EVP_MD_CTX_create())) { + free_resources(pkey, mdctx); + LOG_ERROR("Error creating context"); + return FUNC_RET_ERROR; + } + if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey)) { + LOG_ERROR("Error initializing digest"); + free_resources(pkey, mdctx); + return FUNC_RET_ERROR; + } + int en = strlen(stringToVerify); + func_ret = EVP_DigestVerifyUpdate(mdctx, stringToVerify, en); + if (1 != func_ret) { + LOG_ERROR("Error verifying digest %d", func_ret); + free_resources(pkey, mdctx); + return FUNC_RET_ERROR; + } + FUNCTION_RETURN result; + func_ret = EVP_DigestVerifyFinal(mdctx, buffer, len); + if (1 != func_ret) { + LOG_ERROR("Error verifying digest %d", func_ret); + } + result = (1 == func_ret ? FUNC_RET_OK : FUNC_RET_ERROR); + + free_resources(pkey, mdctx); + return result; +} -- Gitblit v1.9.1