Post not yet marked as solved
I have a certificate + private key in the Apple Keychain on a macOS 12 machine. The access control for the private key has been modified to add my program binary to the "Always allow access by these applications:" list. My program uses this certificate to do mTLS authentication using OpenSSL. Also inside the program I disable the Keychain UI temporarily while accessing items stored in there to disable any prompts. All this was working fine. I could even update this binary from a .pkg file installer to the same path and the access would still be inherited.
But that is no longer the case. If I upgrade the binary now at the same path, the Keychain does not allow the program to access that private key. I have to go into the Keychain access application and manually remove the earlier entry and re-add the binary at the same path again into the list.
Not sure if this is a macOS issue or by binary has changed somehow. There have been no major code base changes to the program.
If this is something by design, is there a command line to add certain binaries to the Access List for the private key? So that I can automate this process somehow and not have to re-add the binary at the same path again every time.
I have been trying to set up a HTTP Client which uses the Apple Network Framework for it's connection and TLS needs.
Using Objective-C calls in a C++ project. I have been playing around with the Implementation at Implementing netcat with Network Framework
. After a successful TLS handshake, I send a request to the server using the following code snippet:
dispatch_data_t content = dispatch_data_create(headers.c_str(), strlen(headers.c_str()), dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT);
nw_connection_send(m_connectionObject, content, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^ (nw_error_t nwError) {
if (nwError != NULL)
{
auto errNumber = nw_error_get_error_code(nwError);
logger->Error("Error sending data to [%s]:%d : Error Number :%d", request.Host(), request.Port(), errNumber);
}
else
{
logger->Debug("Sent %u byte(s) of HTTP headers", headersLen);
}
});
where std::string headers is a stream of HTTPS request headers.
The sending operation is successful but when it comes to receiving block which starts after the above snippet, the Network framework directly produces the content offered by the destination. I need to access the server's HTTP response headers first. Is there a way to do that?
Also I need to continue using this framework and can not more to NSURLSessions stuff.
The receive block:
nw_connection_receive(m_connectionObject, 1, UINT32_MAX, ^ (dispatch_data_t content, nw_content_context_t context, bool isComplete, nw_error_t receiveError) {
nw_retain(context);
dispatch_block_t schedule_next_receive = ^ {
// If the context is marked as complete, and is the final context,
// we're read-closed.
if (isComplete && (context == NULL || nw_content_context_get_is_final(context)))
{
logger->Info(
"HTTP Client was remotely disconnected from destination.");
nw_connection_cancel(m_connectionObject);
}
// If there was no error in receiving, request more data
if (receiveError == NULL)
{
ReceiveResponse(request, response, bodyParser);
}
nw_release(context);
};
if (content != NULL)
{
schedule_next_receive = Block_copy(schedule_next_receive);
//Convert dispatch_data_t to std::string
std::string message = CreateStringWithDispatchData(content);
//Parse the response message, false means unsuccessful parsing
if(ProcessResponse(message))
{
schedule_next_receive();
}
else
{
nw_connection_cancel(m_connectionObject);
}
}
else
{
// Content was NULL, so directly schedule the next receive
schedule_next_receive();
}
});
I have been working with Apple's Network Framework to implement a WebSocket Client. Here is the receive block for my code:
nw_connection_receive(connection, 1, UINT32_MAX, ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) {
nw_retain(context);
nw_protocol_metadata_t wsMetadata = nw_content_context_copy_protocol_metadata(context,nw_protocol_copy_ws_definition());
nw_ws_opcode_t inputOpCode = nw_ws_metadata_get_opcode(wsMetadata);
fprintf(stderr,"\n\nInput Opcode: %d\n", inputOpCode);
dispatch_block_t schedule_next_receive = ^{
// If the context is marked as complete, and is the final context,
// we're read-closed.
if (is_complete &&
(context == NULL || nw_content_context_get_is_final(context))) {
exit(0);
}
// If there was no error in receiving, request more data
if (receive_error == NULL) {
receive_loop(connection);
}
nw_release(context);
};
if (content != NULL) {
// If there is content, write it to stdout asynchronously
schedule_next_receive = Block_copy(schedule_next_receive);
dispatch_write(STDOUT_FILENO, content,dispatch_get_main_queue(), ^(__unused dispatch_data_t _Nullable data, int stdout_error) {
if (stdout_error != 0) {
errno = stdout_error;
fprintf(stderr,"stdout write error\n");
} else {
schedule_next_receive();
}
Block_release(schedule_next_receive);
});
} else {
// Content was NULL, so directly schedule the next receive
schedule_next_receive();
}
});
This code block is taken from (Implementing netcat with Network Framework | Apple Developer Documentation).
I now want to get rid of the dispatch_write block and convert the received dispatch_data_t object to a string representation either a CFStringRef or a C++ std::string.