unix_domain_server_socket_posix.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/socket/unix_domain_server_socket_posix.h"
  5. #include <errno.h>
  6. #include <sys/socket.h>
  7. #include <sys/un.h>
  8. #include <unistd.h>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/logging.h"
  12. #include "build/build_config.h"
  13. #include "net/base/net_errors.h"
  14. #include "net/base/sockaddr_storage.h"
  15. #include "net/base/sockaddr_util_posix.h"
  16. #include "net/socket/socket_posix.h"
  17. #include "net/socket/unix_domain_client_socket_posix.h"
  18. namespace net {
  19. UnixDomainServerSocket::UnixDomainServerSocket(
  20. const AuthCallback& auth_callback,
  21. bool use_abstract_namespace)
  22. : auth_callback_(auth_callback),
  23. use_abstract_namespace_(use_abstract_namespace) {
  24. DCHECK(!auth_callback_.is_null());
  25. }
  26. UnixDomainServerSocket::~UnixDomainServerSocket() = default;
  27. // static
  28. bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket,
  29. Credentials* credentials) {
  30. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \
  31. BUILDFLAG(IS_FUCHSIA)
  32. struct ucred user_cred;
  33. socklen_t len = sizeof(user_cred);
  34. if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
  35. return false;
  36. credentials->process_id = user_cred.pid;
  37. credentials->user_id = user_cred.uid;
  38. credentials->group_id = user_cred.gid;
  39. return true;
  40. #else
  41. return getpeereid(
  42. socket, &credentials->user_id, &credentials->group_id) == 0;
  43. #endif
  44. }
  45. int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog) {
  46. NOTIMPLEMENTED();
  47. return ERR_NOT_IMPLEMENTED;
  48. }
  49. int UnixDomainServerSocket::ListenWithAddressAndPort(
  50. const std::string& address_string,
  51. uint16_t port,
  52. int backlog) {
  53. NOTIMPLEMENTED();
  54. return ERR_NOT_IMPLEMENTED;
  55. }
  56. int UnixDomainServerSocket::BindAndListen(const std::string& socket_path,
  57. int backlog) {
  58. DCHECK(!listen_socket_);
  59. SockaddrStorage address;
  60. if (!FillUnixAddress(socket_path, use_abstract_namespace_, &address)) {
  61. return ERR_ADDRESS_INVALID;
  62. }
  63. auto socket = std::make_unique<SocketPosix>();
  64. int rv = socket->Open(AF_UNIX);
  65. DCHECK_NE(ERR_IO_PENDING, rv);
  66. if (rv != OK)
  67. return rv;
  68. rv = socket->Bind(address);
  69. DCHECK_NE(ERR_IO_PENDING, rv);
  70. if (rv != OK) {
  71. PLOG(ERROR)
  72. << "Could not bind unix domain socket to " << socket_path
  73. << (use_abstract_namespace_ ? " (with abstract namespace)" : "");
  74. return rv;
  75. }
  76. rv = socket->Listen(backlog);
  77. DCHECK_NE(ERR_IO_PENDING, rv);
  78. if (rv != OK)
  79. return rv;
  80. listen_socket_.swap(socket);
  81. return rv;
  82. }
  83. int UnixDomainServerSocket::GetLocalAddress(IPEndPoint* address) const {
  84. DCHECK(address);
  85. // Unix domain sockets have no valid associated addr/port;
  86. // return address invalid.
  87. return ERR_ADDRESS_INVALID;
  88. }
  89. int UnixDomainServerSocket::Accept(std::unique_ptr<StreamSocket>* socket,
  90. CompletionOnceCallback callback) {
  91. DCHECK(socket);
  92. DCHECK(callback);
  93. DCHECK(!callback_ && !out_socket_.stream && !out_socket_.descriptor);
  94. out_socket_ = {socket, nullptr};
  95. int rv = DoAccept();
  96. if (rv == ERR_IO_PENDING)
  97. callback_ = std::move(callback);
  98. else
  99. CancelCallback();
  100. return rv;
  101. }
  102. int UnixDomainServerSocket::AcceptSocketDescriptor(
  103. SocketDescriptor* socket,
  104. CompletionOnceCallback callback) {
  105. DCHECK(socket);
  106. DCHECK(callback);
  107. DCHECK(!callback_ && !out_socket_.stream && !out_socket_.descriptor);
  108. out_socket_ = {nullptr, socket};
  109. int rv = DoAccept();
  110. if (rv == ERR_IO_PENDING)
  111. callback_ = std::move(callback);
  112. else
  113. CancelCallback();
  114. return rv;
  115. }
  116. int UnixDomainServerSocket::DoAccept() {
  117. DCHECK(listen_socket_);
  118. DCHECK(!accept_socket_);
  119. while (true) {
  120. int rv = listen_socket_->Accept(
  121. &accept_socket_,
  122. base::BindOnce(&UnixDomainServerSocket::AcceptCompleted,
  123. base::Unretained(this)));
  124. if (rv != OK)
  125. return rv;
  126. if (AuthenticateAndGetStreamSocket())
  127. return OK;
  128. // Accept another socket because authentication error should be transparent
  129. // to the caller.
  130. }
  131. }
  132. void UnixDomainServerSocket::AcceptCompleted(int rv) {
  133. DCHECK(!callback_.is_null());
  134. if (rv != OK) {
  135. RunCallback(rv);
  136. return;
  137. }
  138. if (AuthenticateAndGetStreamSocket()) {
  139. RunCallback(OK);
  140. return;
  141. }
  142. // Accept another socket because authentication error should be transparent
  143. // to the caller.
  144. rv = DoAccept();
  145. if (rv != ERR_IO_PENDING)
  146. RunCallback(rv);
  147. }
  148. bool UnixDomainServerSocket::AuthenticateAndGetStreamSocket() {
  149. DCHECK(accept_socket_);
  150. Credentials credentials;
  151. if (!GetPeerCredentials(accept_socket_->socket_fd(), &credentials) ||
  152. !auth_callback_.Run(credentials)) {
  153. accept_socket_.reset();
  154. return false;
  155. }
  156. SetSocketResult(std::move(accept_socket_));
  157. return true;
  158. }
  159. void UnixDomainServerSocket::SetSocketResult(
  160. std::unique_ptr<SocketPosix> accepted_socket) {
  161. // Exactly one of the output pointers should be set.
  162. DCHECK_NE(!!out_socket_.stream, !!out_socket_.descriptor);
  163. // Pass ownership of |accepted_socket|.
  164. if (out_socket_.descriptor) {
  165. *out_socket_.descriptor = accepted_socket->ReleaseConnectedSocket();
  166. return;
  167. }
  168. *out_socket_.stream =
  169. std::make_unique<UnixDomainClientSocket>(std::move(accepted_socket));
  170. }
  171. void UnixDomainServerSocket::RunCallback(int rv) {
  172. out_socket_ = SocketDestination();
  173. std::move(callback_).Run(rv);
  174. }
  175. void UnixDomainServerSocket::CancelCallback() {
  176. out_socket_ = SocketDestination();
  177. callback_.Reset();
  178. }
  179. } // namespace net