diff options
| author | Szczepan Zalega <szczepan@nitrokey.com> | 2017-12-04 19:21:09 +0100 | 
|---|---|---|
| committer | Szczepan Zalega <szczepan@nitrokey.com> | 2018-02-28 19:23:05 +0100 | 
| commit | 388cf5fcb33f24bc04f79cd1fbea980214518d54 (patch) | |
| tree | 1b57874287d02a1fe339f035ba84a54d3bf1f408 | |
| parent | 2faa8f6782a2e6294ed8849048a281d12d60da1c (diff) | |
| download | libnitrokey-388cf5fcb33f24bc04f79cd1fbea980214518d54.tar.gz libnitrokey-388cf5fcb33f24bc04f79cd1fbea980214518d54.tar.bz2 | |
List devices by unique SC:SD id
Add C API and tests
Add mutexes
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
| -rw-r--r-- | NK_C_API.cc | 21 | ||||
| -rw-r--r-- | NK_C_API.h | 6 | ||||
| -rw-r--r-- | NitrokeyManager.cc | 87 | ||||
| -rw-r--r-- | include/NitrokeyManager.h | 3 | ||||
| -rw-r--r-- | unittest/test_C_API.cpp | 28 | ||||
| -rw-r--r-- | unittest/test_multiple_devices.cc | 24 | 
6 files changed, 160 insertions, 9 deletions
| diff --git a/NK_C_API.cc b/NK_C_API.cc index f881caf..59247ba 100644 --- a/NK_C_API.cc +++ b/NK_C_API.cc @@ -608,6 +608,27 @@ extern "C" {  		});  	} +	NK_C_API const char* NK_list_devices_by_cpuID() { +		auto nm = NitrokeyManager::instance(); +		return get_with_string_result([&]() { +			auto v = nm->list_devices_by_cpuID(); +			std::string res; +			for (const auto a : v){ +				res += a+";"; +			} +			if (res.size()>0) res.pop_back(); // remove last delimeter char +			return strndup(res.c_str(), 4096); +		}); +	} + +	NK_C_API int NK_connect_with_ID(const char* id) { +		auto m = NitrokeyManager::instance(); +		return get_with_result([&]() { +			return m->connect_with_ID(id) ? 1 : 0; +		}); +	} + +  #ifdef __cplusplus  } @@ -568,6 +568,12 @@ extern "C" {  	 */  	NK_C_API int NK_get_progress_bar_value(); + +	NK_C_API const char* NK_list_devices_by_cpuID(); +	NK_C_API int NK_connect_with_ID(const char* id); + + +  #ifdef __cplusplus  }  #endif diff --git a/NitrokeyManager.cc b/NitrokeyManager.cc index da5f61a..4935076 100644 --- a/NitrokeyManager.cc +++ b/NitrokeyManager.cc @@ -81,6 +81,8 @@ using nitrokey::misc::strcpyT;          set_debug(true);      }      NitrokeyManager::~NitrokeyManager() { +        std::lock_guard<std::mutex> lock(mex_dev_com_manager); +          for (auto d : connected_devices){              if (d.second == nullptr) continue;              d.second->disconnect(); @@ -104,27 +106,98 @@ using nitrokey::misc::strcpyT;      }      std::vector<std::string> NitrokeyManager::list_devices(){ +        std::lock_guard<std::mutex> lock(mex_dev_com_manager); +          auto p = make_shared<Stick20>();          return p->enumerate(); // make static      } -    bool NitrokeyManager::connect_with_path(std::string path) { +    std::vector<std::string> NitrokeyManager::list_devices_by_cpuID(){          std::lock_guard<std::mutex> lock(mex_dev_com_manager); -        if(connected_devices.find(path) != connected_devices.end() -                && connected_devices[path] != nullptr) { -            device = connected_devices[path]; -            return true; +        std::vector<std::string> res; +        auto d = make_shared<Stick20>(); +        const auto v = d->enumerate(); +        for (auto & p: v){ +            d = make_shared<Stick20>(); +            d->set_path(p); +            try{ +                if (d->connect()){ +                    device = d; +                    const auto status = get_status_storage(); +                    const auto sc_id = status.ActiveSmartCardID_u32; +                    const auto sd_id = status.ActiveSD_CardID_u32; + +                    auto id = std::to_string(sc_id) + ":" + std::to_string(sd_id); +                    connected_devices_byID[id] = d; +                    res.push_back(id); +                } else{ +                    std::cout << "Could not connect to: " + p << std::endl; +                } +            } +            catch (const DeviceCommunicationException &e){ +                //ignore +                std::cout << p << ": " << " Exception encountered" << std::endl; +            }          } +        return res; +    } +/** + * Connect to the device using unique smartcard:datacard id. + * Needs list_device_by_cpuID run first + * @param id + * @return + */ +    bool NitrokeyManager::connect_with_ID(const std::string id) { +        std::lock_guard<std::mutex> lock(mex_dev_com_manager); +        auto position = connected_devices_byID.find(id); +        if (position == connected_devices_byID.end()) return false; + +        auto d = connected_devices_byID[id]; +        device = d; + +        try{ +            get_status(); +        } +        catch (const DeviceCommunicationException &){ +            d->disconnect(); +            connected_devices_byID[id] = nullptr; +            connected_devices_byID.erase(position); +            return false; +        } +        return true; +    } + +        /** +         * Connects device to path. +         * Assumes devices are not being disconnected and caches connections (param cache_connections). +         * @param path os-dependent device path +         * @return false, when could not connect, true otherwise +         */ +    bool NitrokeyManager::connect_with_path(std::string path) { +        const bool cache_connections = false; + +        std::lock_guard<std::mutex> lock(mex_dev_com_manager); + +        if (cache_connections){ +            if(connected_devices.find(path) != connected_devices.end() +                    && connected_devices[path] != nullptr) { +                device = connected_devices[path]; +                return true; +            } +        }          auto p = make_shared<Stick20>();          p->set_path(path);          if(!p->connect()) return false; -        connected_devices [path] = p; -        device = p; +        if(cache_connections){ +            connected_devices [path] = p; +        } + +        device = p; //previous device will be disconnected automatically          return true;      } diff --git a/include/NitrokeyManager.h b/include/NitrokeyManager.h index 2a79922..7ce432f 100644 --- a/include/NitrokeyManager.h +++ b/include/NitrokeyManager.h @@ -69,6 +69,8 @@ char * strndup(const char* str, size_t maxlen);          bool erase_totp_slot(uint8_t slot_number, const char *temporary_password);          bool erase_hotp_slot(uint8_t slot_number, const char *temporary_password);          std::vector<std::string> list_devices(); +        std::vector<std::string> list_devices_by_cpuID(); +        bool connect_with_ID(const std::string id);          bool connect_with_path (std::string path);          bool connect(const char *device_model);          bool connect(); @@ -202,6 +204,7 @@ char * strndup(const char* str, size_t maxlen);          static shared_ptr <NitrokeyManager> _instance;          std::shared_ptr<Device> device;          std::unordered_map<std::string, shared_ptr<Device> > connected_devices; +        std::unordered_map<std::string, shared_ptr<Device> > connected_devices_byID;          stick10::ReadSlot::ResponsePayload get_OTP_slot_data(const uint8_t slot_number); diff --git a/unittest/test_C_API.cpp b/unittest/test_C_API.cpp index be47f08..2d83ef4 100644 --- a/unittest/test_C_API.cpp +++ b/unittest/test_C_API.cpp @@ -43,6 +43,7 @@ TEST_CASE("C API connect", "[BASIC]") {  TEST_CASE("Check retry count", "[BASIC]") {    REQUIRE(login != 0); +  NK_set_debug_level(3);    REQUIRE(NK_get_admin_retry_count() == 3);    REQUIRE(NK_get_user_retry_count() == 3);  } @@ -56,4 +57,31 @@ TEST_CASE("Check long strings", "[STANDARD]") {    result = NK_change_user_PIN(pin, longPin);    REQUIRE(result == TOO_LONG_STRING);    CAPTURE(result); +} + +#include <string.h> + +TEST_CASE("multiple devices with ID", "[BASIC]") { +  NK_logout(); +  NK_set_debug_level(3); +  auto s = NK_list_devices_by_cpuID(); +  REQUIRE(s!=nullptr); +  REQUIRE(strnlen(s, 4096) < 4096); +  REQUIRE(strnlen(s, 4096) > 2*4); +  std::cout << s << std::endl; + +  char *string, *token; +  int t; + +  string = strndup(s, 4096); +  free ( (void*) s); + +  while ((token = strsep(&string, ";")) != nullptr){ +    if (strnlen(token, 4096) < 3) continue; +    std::cout << token << " connecting: "; +    std::cout << (t=NK_connect_with_ID(token)) << std::endl; +    REQUIRE(t == 1); +  } + +  free (string);  }
\ No newline at end of file diff --git a/unittest/test_multiple_devices.cc b/unittest/test_multiple_devices.cc index f5b4d6e..235a24d 100644 --- a/unittest/test_multiple_devices.cc +++ b/unittest/test_multiple_devices.cc @@ -78,15 +78,35 @@ TEST_CASE("Use API", "[BASIC]") {                            << " " << status_storage.ActiveSD_CardID_u32                            << std::endl; -                nm->fill_SD_card_with_random_data("12345678"); +//                nm->fill_SD_card_with_random_data("12345678");              }              catch (const LongOperationInProgressException &e){                  std::cout << "long operation in progress on " << a                          << " " << std::to_string(e.progress_bar_value) << std::endl; -                this_thread::sleep_for(1000ms); +//                this_thread::sleep_for(1000ms);              }          }          std::cout <<"Iteration: " << i << std::endl;      } +} + + +TEST_CASE("Use API ID", "[BASIC]") { +    auto nm = NitrokeyManager::instance(); +    nm->set_loglevel(2); + +    auto v = nm->list_devices_by_cpuID(); +    REQUIRE(v.size() > 0); + +    for(int i=0; i<1000; i++) { +        auto v = nm->list_devices_by_cpuID(); +        REQUIRE(v.size() > 0); +        for (auto i : v) { +            nm->connect_with_ID(i); +            auto retry_count = nm->get_admin_retry_count(); +            std::cout << i << " " << to_string(retry_count) << std::endl; +        } +    } +    std::cout << "finished" << std::endl;  }
\ No newline at end of file | 
