1 #pragma once
2 
3 #include <boost/asio/buffer.hpp>
4 #include <boost/asio/io_context.hpp>
5 #include <boost/asio/write.hpp>
6 #include <boost/process/async_pipe.hpp>
7 
8 #include <array>
9 #include <string>
10 
11 // Wrapper for boost::async_pipe ensuring proper pipe cleanup
12 class CredentialsPipe
13 {
14   public:
15     explicit CredentialsPipe(boost::asio::io_context& io) : impl(io) {}
16 
17     CredentialsPipe(const CredentialsPipe&) = delete;
18     CredentialsPipe(CredentialsPipe&&) = delete;
19     CredentialsPipe& operator=(const CredentialsPipe&) = delete;
20     CredentialsPipe& operator=(CredentialsPipe&&) = delete;
21 
22     ~CredentialsPipe()
23     {
24         explicit_bzero(user.data(), user.capacity());
25         explicit_bzero(pass.data(), pass.capacity());
26     }
27 
28     int fd() const
29     {
30         return impl.native_source();
31     }
32 
33     template <typename WriteHandler>
34     void asyncWrite(std::string&& username, std::string&& password,
35                     WriteHandler&& handler)
36     {
37         user = std::move(username);
38         pass = std::move(password);
39 
40         // Add +1 to ensure that the null terminator is included.
41         std::array<boost::asio::const_buffer, 2> buffer{
42             {{user.data(), user.size() + 1}, {pass.data(), pass.size() + 1}}};
43         boost::asio::async_write(impl, buffer,
44                                  std::forward<WriteHandler>(handler));
45     }
46 
47     boost::process::async_pipe impl;
48 
49   private:
50     std::string user;
51     std::string pass;
52 };
53