/* * ModSecurity, http://www.modsecurity.org/ * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) * * You may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * If any of the files related to licensing are missing or if you have any * other questions related to licensing please contact Trustwave Holdings, Inc. * directly using the email address security@modsecurity.org. * */ #include "src/unique_id.h" #include "src/config.h" #ifdef WIN32 #include "src/compat/msvc.h" #include #include #endif #if (defined(__linux__) || defined(__gnu_linux__)) || DARWIN #include #include #include #endif #ifdef DARWIN #include #include #include #include #ifndef IFT_ETHER #define IFT_ETHER 0x6 /* Ethernet CSMACD */ #endif #endif #if (defined(__linux__) || defined(__gnu_linux__)) #include #include #include #endif #ifdef HAVE_SYS_UTSNAME_H #include #endif #include #ifndef WIN32 #include #else #include #endif #include #include "src/utils/sha1.h" namespace modsecurity { std::once_flag UniqueId::onceFlag; void UniqueId::fillUniqueId() { std::string macAddress; std::string name; std::string data; macAddress = ethernetMacAddress(); name = machineName(); data = macAddress + name; this->uniqueId_str = Utils::Sha1::hexdigest(data); } // Based on: // http://stackoverflow.com/questions/16858782/how-to-obtain-almost-unique-system-identifier-in-a-cross-platform-way std::string UniqueId::machineName() { char machine_name[MAX_MACHINE_NAME_SIZE]; size_t len = MAX_MACHINE_NAME_SIZE; #ifdef WIN32 DWORD lenComputerName = len; #endif memset(machine_name, '\0', sizeof(char) * len); #ifdef WIN32 if (GetComputerName(machine_name, &lenComputerName) == 0) { goto failed; } #endif #ifdef HAVE_SYS_UTSNAME_H static struct utsname u; if (uname(&u) < 0) { goto failed; } snprintf(machine_name, len-1, "%s", u.nodename); #endif return std::string(machine_name); #if defined(HAVE_SYS_UTSNAME_H) || defined(WIN32) failed: return std::string(""); #endif } std::string UniqueId::ethernetMacAddress() { char mac[MAC_ADDRESS_SIZE]; memset(mac, '\0', sizeof(char)*(MAC_ADDRESS_SIZE)); #ifdef DARWIN struct ifaddrs* ifaphead; struct ifaddrs* ifap; int i = 0; if (getifaddrs(&ifaphead) != 0) { goto failed; } // iterate over the net interfaces 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) && mac[0] && mac[1] && mac[2] && i < 6) { snprintf(mac, MAC_ADDRESS_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)LLADDR(sdl)[0], (unsigned char)LLADDR(sdl)[1], (unsigned char)LLADDR(sdl)[2], (unsigned char)LLADDR(sdl)[3], (unsigned char)LLADDR(sdl)[4], (unsigned char)LLADDR(sdl)[5]); goto end; } } freeifaddrs(ifaphead); #endif #if (defined(__linux__) || defined(__gnu_linux__)) struct ifconf conf; int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); struct ifreq* ifr; if ( sock < 0 ) { goto failed; } 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)) { close(sock); goto failed; } for (ifr = conf.ifc_req; ifr < conf.ifc_req + conf.ifc_len; ifr++) { if (ioctl(sock, SIOCGIFFLAGS, ifr)) { continue; // failed to get flags, skip it } if (ioctl(sock, SIOCGIFHWADDR, ifr) == 0) { if (!ifr->ifr_addr.sa_data[0] && !ifr->ifr_addr.sa_data[1] && !ifr->ifr_addr.sa_data[2]) { continue; } snprintf(mac, MAC_ADDRESS_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)ifr->ifr_addr.sa_data[0], (unsigned char)ifr->ifr_addr.sa_data[1], (unsigned char)ifr->ifr_addr.sa_data[2], (unsigned char)ifr->ifr_addr.sa_data[3], (unsigned char)ifr->ifr_addr.sa_data[4], (unsigned char)ifr->ifr_addr.sa_data[5]); goto end; } } close(sock); #endif #if WIN32 PIP_ADAPTER_INFO pAdapterInfo; PIP_ADAPTER_INFO pAdapter = NULL; DWORD dwRetVal = 0; ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO); pAdapterInfo = reinterpret_cast(malloc( \ sizeof (IP_ADAPTER_INFO))); if (!pAdapterInfo) { goto failed; } if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { free(pAdapterInfo); pAdapterInfo = reinterpret_cast(malloc(ulOutBufLen)); if (!pAdapterInfo) { goto failed; } } dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); if (dwRetVal != NO_ERROR) { free(pAdapterInfo); goto failed; } pAdapter = pAdapterInfo; while (pAdapter && !mac[0] && !mac[1] && !mac[2]) { if (pAdapter->AddressLength > 4) { snprintf(mac, MAC_ADDRESS_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)pAdapter->Address[0], (unsigned char)pAdapter->Address[1], (unsigned char)pAdapter->Address[2], (unsigned char)pAdapter->Address[3], (unsigned char)pAdapter->Address[4], (unsigned char)pAdapter->Address[5]); goto end; } pAdapter = pAdapter->Next; } free(pAdapterInfo); #endif #if defined(__linux__) || defined(__gnu_linux__) || defined(DARWIN) || defined(WIN32) end: #endif return std::string(reinterpret_cast(mac)); #if defined(__linux__) || defined(__gnu_linux__) || defined(DARWIN) || defined(WIN32) failed: return std::string(""); #endif } } // namespace modsecurity