tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

addrs-win32.c (6257B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifdef WIN32
      6 
      7 #include "addrs-win32.h"
      8 #include <csi_platform.h>
      9 #include <assert.h>
     10 #include <string.h>
     11 #include "util.h"
     12 #include "stun_util.h"
     13 #include "util.h"
     14 #include <r_macros.h>
     15 #include "nr_crypto.h"
     16 
     17 #include <winsock2.h>
     18 #include <iphlpapi.h>
     19 #include <tchar.h>
     20 
     21 #define WIN32_MAX_NUM_INTERFACES  20
     22 
     23 #define NR_MD5_HASH_LENGTH 16
     24 
     25 #define _NR_MAX_KEY_LENGTH 256
     26 #define _NR_MAX_NAME_LENGTH 512
     27 
     28 #define _ADAPTERS_BASE_REG "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
     29 
     30 static int nr_win32_get_adapter_friendly_name(char *adapter_GUID, char **friendly_name)
     31 {
     32    int r,_status;
     33    HKEY adapter_reg;
     34    TCHAR adapter_key[_NR_MAX_KEY_LENGTH];
     35    TCHAR keyval_buf[_NR_MAX_KEY_LENGTH];
     36    TCHAR adapter_GUID_tchar[_NR_MAX_NAME_LENGTH];
     37    DWORD keyval_len, key_type;
     38    size_t converted_chars, newlen;
     39    char *my_fn = 0;
     40 
     41 #ifdef _UNICODE
     42    mbstowcs_s(&converted_chars, adapter_GUID_tchar, strlen(adapter_GUID)+1,
     43               adapter_GUID, _TRUNCATE);
     44 #else
     45    strlcpy(adapter_GUID_tchar, adapter_GUID, _NR_MAX_NAME_LENGTH);
     46 #endif
     47 
     48    _tcscpy_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT(_ADAPTERS_BASE_REG));
     49    _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\"));
     50    _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, adapter_GUID_tchar);
     51    _tcscat_s(adapter_key, _NR_MAX_KEY_LENGTH, TEXT("\\Connection"));
     52 
     53    r = RegOpenKeyEx(HKEY_LOCAL_MACHINE, adapter_key, 0, KEY_READ, &adapter_reg);
     54 
     55    if (r != ERROR_SUCCESS) {
     56      r_log(NR_LOG_STUN, LOG_ERR, "Got error %d opening adapter reg key\n", r);
     57      ABORT(R_INTERNAL);
     58    }
     59 
     60    keyval_len = sizeof(keyval_buf);
     61    r = RegQueryValueEx(adapter_reg, TEXT("Name"), NULL, &key_type,
     62                        (BYTE *)keyval_buf, &keyval_len);
     63 
     64    RegCloseKey(adapter_reg);
     65 
     66 #ifdef UNICODE
     67    newlen = wcslen(keyval_buf)+1;
     68    my_fn = (char *) RCALLOC(newlen);
     69    if (!my_fn) {
     70      ABORT(R_NO_MEMORY);
     71    }
     72    wcstombs_s(&converted_chars, my_fn, newlen, keyval_buf, _TRUNCATE);
     73 #else
     74    my_fn = r_strdup(keyval_buf);
     75 #endif
     76 
     77    *friendly_name = my_fn;
     78    _status=0;
     79 
     80 abort:
     81    if (_status) {
     82      if (my_fn) free(my_fn);
     83    }
     84    return(_status);
     85 }
     86 
     87 static int stun_win32_address_disallowed(IP_ADAPTER_UNICAST_ADDRESS *addr)
     88 {
     89  return (addr->DadState != NldsPreferred) &&
     90          (addr->DadState != IpDadStatePreferred);
     91 }
     92 
     93 static int stun_win32_address_temp_v6(IP_ADAPTER_UNICAST_ADDRESS *addr)
     94 {
     95  return (addr->Address.lpSockaddr->sa_family == AF_INET6) &&
     96      (addr->SuffixOrigin == IpSuffixOriginRandom);
     97 }
     98 
     99 int
    100 stun_getaddrs_filtered(nr_local_addr addrs[], int maxaddrs, int *count)
    101 {
    102    int r, _status;
    103    PIP_ADAPTER_ADDRESSES AdapterAddresses = NULL, tmpAddress = NULL;
    104    // recomended per https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx
    105    static const ULONG initialBufLen = 15000;
    106    ULONG buflen = initialBufLen;
    107    char bin_hashed_ifname[NR_MD5_HASH_LENGTH];
    108    char hex_hashed_ifname[MAXIFNAME];
    109    int n = 0;
    110 
    111    *count = 0;
    112 
    113    if (maxaddrs <= 0)
    114      ABORT(R_BAD_ARGS);
    115 
    116    /* According to MSDN (see above) we have try GetAdapterAddresses() multiple times */
    117    for (n = 0; n < 5; n++) {
    118      AdapterAddresses = (PIP_ADAPTER_ADDRESSES) RMALLOC(buflen);
    119      if (AdapterAddresses == NULL) {
    120        r_log(NR_LOG_STUN, LOG_ERR, "Error allocating buf for GetAdaptersAddresses()");
    121        ABORT(R_NO_MEMORY);
    122      }
    123 
    124      r = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, NULL, AdapterAddresses, &buflen);
    125      if (r == NO_ERROR) {
    126        break;
    127      }
    128      r_log(NR_LOG_STUN, LOG_ERR, "GetAdaptersAddresses() returned error (%d)", r);
    129      RFREE(AdapterAddresses);
    130      AdapterAddresses = NULL;
    131    }
    132 
    133    if (n >= 5) {
    134      r_log(NR_LOG_STUN, LOG_ERR, "5 failures calling GetAdaptersAddresses()");
    135      ABORT(R_INTERNAL);
    136    }
    137 
    138    n = 0;
    139 
    140    /* Loop through the adapters */
    141 
    142    for (tmpAddress = AdapterAddresses; tmpAddress != NULL; tmpAddress = tmpAddress->Next) {
    143 
    144      if (tmpAddress->OperStatus != IfOperStatusUp)
    145        continue;
    146 
    147      if ((tmpAddress->IfIndex != 0) || (tmpAddress->Ipv6IfIndex != 0)) {
    148        IP_ADAPTER_UNICAST_ADDRESS *u = 0;
    149 
    150        if(r=nr_crypto_md5((UCHAR *)tmpAddress->FriendlyName,
    151                           wcslen(tmpAddress->FriendlyName) * sizeof(wchar_t),
    152                           bin_hashed_ifname))
    153          ABORT(r);
    154        if(r=nr_bin2hex(bin_hashed_ifname, sizeof(bin_hashed_ifname),
    155          hex_hashed_ifname))
    156          ABORT(r);
    157 
    158        for (u = tmpAddress->FirstUnicastAddress; u != 0; u = u->Next) {
    159          SOCKET_ADDRESS *sa_addr = &u->Address;
    160 
    161          if ((sa_addr->lpSockaddr->sa_family != AF_INET) &&
    162              (sa_addr->lpSockaddr->sa_family != AF_INET6)) {
    163            r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized sa_family for address on adapter %lu", tmpAddress->IfIndex);
    164            continue;
    165          }
    166 
    167          if (stun_win32_address_disallowed(u)) {
    168            continue;
    169          }
    170 
    171          if ((r=nr_sockaddr_to_transport_addr((struct sockaddr*)sa_addr->lpSockaddr, IPPROTO_UDP, 0, &(addrs[n].addr)))) {
    172            ABORT(r);
    173          }
    174 
    175          strlcpy(addrs[n].addr.ifname, hex_hashed_ifname, sizeof(addrs[n].addr.ifname));
    176          if (tmpAddress->IfType == IF_TYPE_ETHERNET_CSMACD) {
    177            addrs[n].iface.type = NR_INTERFACE_TYPE_WIRED;
    178          } else if (tmpAddress->IfType == IF_TYPE_IEEE80211) {
    179            /* Note: this only works for >= Win Vista */
    180            addrs[n].iface.type = NR_INTERFACE_TYPE_WIFI;
    181          } else {
    182            addrs[n].iface.type = NR_INTERFACE_TYPE_UNKNOWN;
    183          }
    184          addrs[n].iface.estimated_speed = tmpAddress->TransmitLinkSpeed / 1000;
    185          if (stun_win32_address_temp_v6(u)) {
    186            addrs[n].flags |= NR_ADDR_FLAG_TEMPORARY;
    187          }
    188 
    189          if (++n >= maxaddrs)
    190            goto done;
    191        }
    192      }
    193    }
    194 
    195   done:
    196    *count = n;
    197    _status = 0;
    198 
    199  abort:
    200    RFREE(AdapterAddresses);
    201    return _status;
    202 }
    203 
    204 #endif //WIN32