0

Trying to access the keychain for the purpose of retrieving proxy credentials on MacOs-Catalina, I am unable to retrieve anything due to errSecItemNotFound or "The specified item could not be found in the keychain."

However, accessing the keychain through Keychain Access, I am able to filter and see the given credentials.

The question is ultimately: How to access the Keychain to retrieve proxy credentials?
But more specifically: What concept am I missing? What is wrong with this?

Here is a minimal code for testing:

#include <iostream>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <Security/SecKeychain.h>

using namespace std;

/// CFSTR equivalent, not throwing old-c cast warning.
#define CFSTRv2(cStr) (reinterpret_cast<const CFStringRef>(\
    __builtin___CFStringMakeConstantString ("" cStr "")))


std::string getPasswordForService(const std::string& service)
{
    std::string account="collector";
    char* buffer=nullptr;
    uint32_t size=0;


    auto errorCode = SecKeychainFindGenericPassword (
                nullptr,//CFSTRv2("login"), 
                static_cast<uint32_t>(service.size()),  
                service.c_str(), 
                static_cast<uint32_t>(account.size()), 
                account.c_str(), 
                &size,
                reinterpret_cast<void**>(&buffer), 
                nullptr);

    if (errorCode != errSecSuccess)
    {
        //cerr << CFStringRefToStdString(SecCopyErrorMessageString(errorCode, nullptr),
        //    "no-error-string") << endl;
        cerr << "Error returned: " << static_cast<int>(errorCode) << endl;
    }

    std::string result(buffer, size);

    return result;
}

int main(int, char*[])
{
    std::string service{"proxy_test"};
    auto password = getPasswordForService(service);
    cout << "Passoword for: " <<service << " : " << password << endl;
}

Also, here is a screenshot of the Keystore:

enter image description here

Finally, and only if it make your life easier, here is the CMakeFile:

cmake_minimum_required(VERSION 3.0)

if (APPLE)
    set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "Minimum OS X deployment version")
endif()

project("Password_support")
set(CMAKE_CXX_STANDARD 17)

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Foundation -framework Security")

find_library(CORE_FOUNDATION CoreFoundation)

set ( TESTCPP password.cpp )
set ( LIBS ${CORE_FOUNDATION})

if (APPLE)
    add_executable( ${PROJECT_NAME} ${TESTCPP} ) 
    target_link_libraries(${PROJECT_NAME} ${LIBS})
endif()

Following, some related questions which helps but did not answered my question:

Adrian Maire
  • 14,354
  • 9
  • 45
  • 85

1 Answers1

0

The issue was related to the function used to retrieve the password: SecKeychainGenericPassword. Proxies are internet technology, and in consequence, the password is stored in another kind whatever this means.

The proper function to retrieve this is SecKeychainFindInternetPassword

auto errorCode = SecKeychainFindInternetPassword (
            nullptr,

            static_cast<uint32_t>(service.size()),  
            service.c_str(), 

            static_cast<uint32_t>(0),
            nullptr,

            static_cast<uint32_t>(0), 
            nullptr, 

            static_cast<uint32_t>(0),
            nullptr,

            static_cast<uint16_t>(1080),

            SecProtocolType::kSecProtocolTypeAny,
            SecAuthenticationType::kSecAuthenticationTypeAny,
            &size,
            reinterpret_cast<void**>(&buffer), 
            nullptr);

Mental note: kill my employee if he ever write a function with that many parameters (joking)

Adrian Maire
  • 14,354
  • 9
  • 45
  • 85
  • 1
    `SecKeychainFindGeneric/InternetPassword` are legacy functions; the functions discussed in [Searching for Keychain Items](https://developer.apple.com/documentation/security/keychain_services/keychain_items/searching_for_keychain_items?language=objc) have a better API. – TheNextman Feb 24 '20 at 17:54