-
Notifications
You must be signed in to change notification settings - Fork 99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rpc: Support protocol version negotiation #371
Conversation
Signed-off-by: Daiki Ueno <ueno@gnu.org>
It's a shame that this doesn't accompany any automated tests (because it would requires multiple versions compiled in), but it could be tested manually by running: $ P11_KIT_DEBUG=rpc _build/p11-kit/test-transport /transport/unix/basic
...
(p11-kit:19432) rpc_C_Initialize: authenticated with protocol version 1 after modifying |
8fc5d3e
to
330db46
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit confused to be honest, mostly because this is more like ground work if I get it correctly. Is it true that this is more like anticipating a future where protocol will have to change?
Further concerns:
- What should happen if client version min > server version max?
- What about testing? If protocol really changes in future, we need automated tests. Perhaps adding some override for strict checking of mins and maxes that can be specified at runtime?
case 0: | ||
goto out; | ||
case 1: | ||
if (version != 0) { | ||
#if P11_RPC_PROTOCOL_VERSION_MINIMUM > 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this #if
. Isn't 0
the current default of P11_RPC_PROTOCOL_VERSION_MINIMUM
? Or does P11_RPC_PROTOCOL_VERSION_MINIMUM == 0
mean "don't bother with checking versions"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to avoid static analyzer warning: otherwise the following if
condition always holds.
@@ -642,6 +619,51 @@ rpc_transport_uninit (p11_rpc_transport *rpc) | |||
p11_buffer_uninit (&rpc->options); | |||
} | |||
|
|||
static CK_RV | |||
rpc_transport_authenticate (p11_rpc_client_vtable *vtable, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is rpc_transport_authenticate
a reasonable name? We are negotiation protocol version rather than authenticating, aren't we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is named after AUTH command in D-Bus, and actually it allows the peers to exchange Unix credentials (UID and GID), so I think it's kind of authentication :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the analogy neither in D-Bus specification, nor in RPC. But I am no expert, I'll believe you know what you are doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the D-Bus specification, more relevant section is Authentication Protocol, where not only SASL-based authentication but also capability negotiations like Unix FD passing are part of the protocol, though there is no version negotiation (I guess it's not needed at this level of the protocol, because usually the D-Bus interface version is maintained at the interface level). But anyway, I don't have a strong opinion on the naming of the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Me neither, feel free to keep it. I was just slightly confused.
@@ -755,10 +756,17 @@ rpc_C_Initialize (CK_X_FUNCTION_LIST *self, | |||
assert (module->vtable->connect != NULL); | |||
ret = (module->vtable->connect) (module->vtable, reserved); | |||
|
|||
if (ret == CKR_OK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't be client further initialized to send P11_RPC_PROTOCOL_VERSION_MAXIMUM
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not possible to send data, if connect
returns error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might just be confused here. My concern was, the protocol description says client should tell server maximum version it supports. I don't see this logic anywhere in the code, so I'm assuming it sends 0 because of some implicit zeroing of some structure. Am I wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's sent in the default implementation of the authenticate
method (rpc_transport_authenticate
):
https://github.com/p11-glue/p11-kit/pull/371/files#diff-71598b22704d395f7e1134bcb2149f62123d7617365db84f3146cc5842115fe0R644
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, then I missed it, thanks for pointing it out.
Yes, this is a groundwork for future changes; we've already faced situations where we realized issues cannot be fixed without breaking the current protocol: #275 and #366 are the examples.
Good point; if there is no overwrap, the client should close the connection.
Indeed, I think the server side test case could be easily extended for that, as it crafts RPC messages, but the client side needs some mechanism to exercise the scenario. |
330db46
to
5edfec6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Followed up in some comments.
About the high level concerns, I still don't see the logic for the case where client_version_max < server_version_min. Also, no tests appear for the version negotiation.
Anyway, I'll mark this approved not to block you further in case I am totally wrong.
@@ -755,10 +756,17 @@ rpc_C_Initialize (CK_X_FUNCTION_LIST *self, | |||
assert (module->vtable->connect != NULL); | |||
ret = (module->vtable->connect) (module->vtable, reserved); | |||
|
|||
if (ret == CKR_OK) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might just be confused here. My concern was, the protocol description says client should tell server maximum version it supports. I don't see this logic anywhere in the code, so I'm assuming it sends 0 because of some implicit zeroing of some structure. Am I wrong?
@@ -642,6 +619,51 @@ rpc_transport_uninit (p11_rpc_transport *rpc) | |||
p11_buffer_uninit (&rpc->options); | |||
} | |||
|
|||
static CK_RV | |||
rpc_transport_authenticate (p11_rpc_client_vtable *vtable, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the analogy neither in D-Bus specification, nor in RPC. But I am no expert, I'll believe you know what you are doing.
One more high-level thought: Let's say there is indeed a problem in future that requires a change of the protocol. Is this groundwork really all we can do at this moment? Perhaps there is something else that would help in future that could be done already (still thinking about figuring out a reasonable way to test protocol changes). |
This works as follows: - a couple of build-time constants have been added to represent the minimal and maximum supported protocol versions - the client sends the maximum supported version upon connection establishment (when C_Initialize is called for first time from the client process) - the server checks the version sent from the client; if it is lower than the minimum supported version of the server, sends an error - otherwise, the server responds with either of smaller value between the version sent from the client and the maximum supported version of the server Signed-off-by: Daiki Ueno <ueno@gnu.org>
5edfec6
to
52e0194
Compare
I agree, though we probably wouldn't be able to identify what else is missing without a version bump. Let's explore in that area in the follow-up PRs. |
This works as follows:
minimal and maximum supported protocol versions
establishment (when
C_Initialize
is called for the first time for the client process)than the minimum supported version of the server, sends an error
the version sent from the client or the maximum supported version of
the server
Example:
Partially fixes #370