Clean up vm CredentialPipe
This code is needlessly complicated for what it does. Even with the
intent, which is secure buffer cleanup, it's trivial to encase all this
into a single class that accepts the strings by rvalue reference, then
cleans them up afterward.
Doing this also cleans up a potential lifetime problem, where if the
unix socket returned immediately, it would've invalidated the buffers
that were being sent. It also moves to async_write, instead of
async_write_some. The former could in theory fail if the socket blocks
(unlikely in this scenario) but it's good to handle anyway.
Tested: Need some help here. There's no backend for this, so we might
just have to rely on inspection.
Change-Id: I9032d458f8eb7a0689bee575aae611641bacee26
Signed-off-by: Ed Tanous <edtanous@google.com>
diff --git a/include/credential_pipe.hpp b/include/credential_pipe.hpp
new file mode 100644
index 0000000..169d47c
--- /dev/null
+++ b/include/credential_pipe.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/process/async_pipe.hpp>
+
+#include <array>
+#include <string>
+
+// Wrapper for boost::async_pipe ensuring proper pipe cleanup
+class CredentialsPipe
+{
+ public:
+ explicit CredentialsPipe(boost::asio::io_context& io) : impl(io) {}
+
+ CredentialsPipe(const CredentialsPipe&) = delete;
+ CredentialsPipe(CredentialsPipe&&) = delete;
+ CredentialsPipe& operator=(const CredentialsPipe&) = delete;
+ CredentialsPipe& operator=(CredentialsPipe&&) = delete;
+
+ ~CredentialsPipe()
+ {
+ explicit_bzero(user.data(), user.capacity());
+ explicit_bzero(pass.data(), pass.capacity());
+ }
+
+ int fd() const
+ {
+ return impl.native_source();
+ }
+
+ template <typename WriteHandler>
+ void asyncWrite(std::string&& username, std::string&& password,
+ WriteHandler&& handler)
+ {
+ user = std::move(username);
+ pass = std::move(password);
+
+ // Add +1 to ensure that the null terminator is included.
+ std::array<boost::asio::const_buffer, 2> buffer{
+ {{user.data(), user.size() + 1}, {pass.data(), pass.size() + 1}}};
+ boost::asio::async_write(impl, buffer,
+ std::forward<WriteHandler>(handler));
+ }
+
+ boost::process::async_pipe impl;
+
+ private:
+ std::string user;
+ std::string pass;
+};