# # # patch "ssh_agent.cc" # from [38b45ca447a33fcfde8079e3012a3934ffcd45bd] # to [70f17663e93951d16eb9224873f0754aeda5a098] # # patch "unix/ssh_agent_platform.cc" # from [4d943a83d3933586e66a3a801606a4c493075b64] # to [38a5880fd0b308fdcbc7b0cd96566bf998a47ad6] # # patch "unix/ssh_agent_platform.hh" # from [4f48ace4c0cb407ccfdfa2a149b080717f135a3b] # to [fdf540a64a48b22b9b7941feb7850b879f353eac] # # patch "win32/ssh_agent_platform.cc" # from [9dd114aa8691e56fe4b0990eff53bdda704b1b21] # to [0c9cfe97c961efffa7b19b1fda41252722bdd64c] # # patch "win32/ssh_agent_platform.hh" # from [9f7f837a96f42a915dbe5c5370bb18da1357c250] # to [d331366b5dde642fb849cdf0b2016803563c0eed] # ============================================================ --- ssh_agent.cc 38b45ca447a33fcfde8079e3012a3934ffcd45bd +++ ssh_agent.cc 70f17663e93951d16eb9224873f0754aeda5a098 @@ -15,7 +15,6 @@ #include "netio.hh" #include "botan/numthry.h" #include "numeric_vocab.hh" -#include "netxx/stream.h" #include "botan/rsa.h" #include "botan/bigint.h" #include @@ -39,7 +38,6 @@ using Botan::X509_PublicKey; using Botan::BigInt; using Botan::SecureVector; using Botan::X509_PublicKey; -using Netxx::Stream; struct ssh_agent_state : ssh_agent_platform { ============================================================ --- unix/ssh_agent_platform.cc 4d943a83d3933586e66a3a801606a4c493075b64 +++ unix/ssh_agent_platform.cc 38a5880fd0b308fdcbc7b0cd96566bf998a47ad6 @@ -8,92 +8,131 @@ // PURPOSE. #include "base.hh" +#include "sanity.hh" +#include "ssh_agent_platform.hh" + #include -#include #include +#include #include +#include #include #include -#include -#include "../sanity.hh" +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif +#ifndef MSG_WAITALL +#define MSG_WAITALL 0 +#endif -#include "ssh_agent_platform.hh" - -using Netxx::Stream; -using Netxx::socket_type; using std::min; using std::string; // helper function for constructor -socket_type -ssh_agent_platform::connect() +static int +connect_to_agent() { - const char *authsocket; - struct sockaddr_un sunaddr; - socket_type sock; - - authsocket = getenv("SSH_AUTH_SOCK"); + const char *authsocket = getenv("SSH_AUTH_SOCK"); - if (!authsocket || !strlen(authsocket)) + if (!authsocket || !*authsocket) { - L(FL("ssh_agent: connect: ssh-agent socket not found")); + L(FL("ssh_agent: no agent")); return -1; } - sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); - - sock = socket(AF_UNIX, SOCK_STREAM, 0); + int sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { - W(F("ssh_agent: connect: could not open socket to ssh-agent")); + W(F("ssh_agent: failed to create a socket: %s") + % strerror(errno)); return -1; } - - int ret = fcntl(sock, F_SETFD, FD_CLOEXEC); - if (ret == -1) + if (fcntl(sock, F_SETFD, FD_CLOEXEC)) { close(sock); - W(F("ssh_agent: connect: could not set up socket for ssh-agent")); + W(F("ssh_agent: failed to set socket as close-on-exec: %s") + % strerror(errno)); return -1; } - ret = ::connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr); - if (ret < 0) + + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, authsocket, sizeof(addr.sun_path)); + + if (::connect(sock, (struct sockaddr *)&addr, sizeof addr)) { close(sock); - W(F("ssh_agent: connect: could not connect to socket for ssh-agent")); + W(F("ssh_agent: failed to connect to agent: %s") + % strerror(errno)); return -1; } return sock; } +ssh_agent_platform::ssh_agent_platform() + : sock(connect_to_agent()) +{} + +ssh_agent_platform::~ssh_agent_platform() +{ + close(sock); +} + void ssh_agent_platform::write_data(string const & data) { - L(FL("ssh_agent_platform::write_data: asked to write %u bytes") - % data.length()); I(connected()); - stream.write(data.c_str(), data.length()); + + size_t put = data.length(); + const char *buf = data.data(); + int deadcycles = 0; + + L(FL("ssh_agent: write_data: asked to send %u bytes") % put); + while (put > 0) + { + ssize_t sent = ::send(sock, buf, put, MSG_NOSIGNAL); + + E(sent >= 0, origin::system, + F("ssh_agent: error during send: %s") % strerror(errno)); + if (sent == 0) + E(++deadcycles < 8, origin::system, + F("ssh_agent: giving up after %d ineffective sends to agent") + % deadcycles); + + buf += sent; + put -= sent; + } + E(put == 0, origin::system, + F("ssh_agent: sent %u extra bytes to agent") % -put); } void -ssh_agent_platform::read_data(u32 const len, string & out) +ssh_agent_platform::read_data(string::size_type len, string & out) { - int ret; - const u32 bufsize = 4096; - char read_buf[bufsize]; - u32 get = len; - L(FL("ssh_agent: read_data: asked to read %u bytes") % len); I(connected()); + size_t get = len; + const size_t bufsize = 4096; + char buf[bufsize]; + int deadcycles = 0; + + L(FL("ssh_agent: read_data: asked to read %u bytes") % len); + while (get > 0) { - ret = stream.read(read_buf, min(get, bufsize)); - E(ret >= 0, origin::system, F("stream read failed (%i)") % ret); - out.append(read_buf, ret); - get -= ret; + ssize_t recvd = ::recv(sock, buf, min(get, bufsize), MSG_WAITALL); + + E(recvd >= 0, origin::system, + F("ssh_agent: error during recieve: %s") % strerror(errno)); + if (recvd == 0) + E(++deadcycles < 8, origin::system, + F("ssh_agent: giving up after %d ineffective receives from agent")); + + out.append(buf, recvd); + get -= recvd; } - E(get == 0, origin::system, F("%u extra bytes from ssh-agent") % -get); + E(get == 0, origin::system, + F("ssh_agent: received %u extra bytes from agent") % -get); } ============================================================ --- unix/ssh_agent_platform.hh 4f48ace4c0cb407ccfdfa2a149b080717f135a3b +++ unix/ssh_agent_platform.hh fdf540a64a48b22b9b7941feb7850b879f353eac @@ -7,21 +7,20 @@ // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. -#include "../numeric_vocab.hh" -#include "../netxx/stream.h" +#ifndef __SSH_AGENT_PLATFORM_HH__ +#define __SSH_AGENT_PLATFORM_HH__ class ssh_agent_platform { private: - Netxx::Stream stream; - Netxx::socket_type connect(); + int sock; public: - // We rely on Netxx::Stream not blowing up if constructed from an - // invalid file descriptor, as long as no one actually tries to write() - // or read() on it. - ssh_agent_platform() : stream(connect()) {} - bool connected() { return stream.get_socketfd() != -1; } + ssh_agent_platform(); + ~ssh_agent_platform(); + bool connected() { return sock != -1; } void write_data(std::string const & data); - void read_data(u32 const len, std::string & out); + void read_data(std::string::size_type len, std::string & out); }; + +#endif ============================================================ --- win32/ssh_agent_platform.cc 9dd114aa8691e56fe4b0990eff53bdda704b1b21 +++ win32/ssh_agent_platform.cc 0c9cfe97c961efffa7b19b1fda41252722bdd64c @@ -8,9 +8,7 @@ // PURPOSE. #include "base.hh" - -#include "../sanity.hh" - +#include "sanity.hh" #include "ssh_agent_platform.hh" using std::string; ============================================================ --- win32/ssh_agent_platform.hh 9f7f837a96f42a915dbe5c5370bb18da1357c250 +++ win32/ssh_agent_platform.hh d331366b5dde642fb849cdf0b2016803563c0eed @@ -7,7 +7,10 @@ // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. -#include "../numeric_vocab.hh" +#ifndef __SSH_AGENT_PLATFORM_HH__ +#define __SSH_AGENT_PLATFORM_HH__ + +#include "numeric_vocab.hh" #define WIN32_LEAN_AND_MEAN // no gui definitions #include @@ -26,3 +29,5 @@ public: void write_data(std::string const & data); void read_data(u32 const len, std::string & out); }; + +#endif