blob: 7190dd25225033307726d04346615def91fe9193 [file] [log] [blame]
Ben Schwartzded1b702017-10-25 14:41:02 -04001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _DNS_DNSTLSSOCKET_H
18#define _DNS_DNSTLSSOCKET_H
19
20#include <future>
21#include <mutex>
22#include <openssl/ssl.h>
23
24#include <android-base/thread_annotations.h>
25#include <android-base/unique_fd.h>
26#include <netdutils/Slice.h>
27#include <netdutils/Status.h>
28
Mike Yu5ae61542018-10-19 22:11:43 +080029#include "DnsTlsServer.h"
30#include "IDnsTlsSocket.h"
31#include "params.h"
Ben Schwartzded1b702017-10-25 14:41:02 -040032
33namespace android {
34namespace net {
35
Ben Schwartz33860762017-10-25 14:41:02 -040036class IDnsTlsSocketObserver;
Ben Schwartzded1b702017-10-25 14:41:02 -040037class DnsTlsSessionCache;
38
39using netdutils::Slice;
40
41// A class for managing a TLS socket that sends and receives messages in
42// [length][value] format, with a 2-byte length (i.e. DNS-over-TCP format).
Ben Schwartz33860762017-10-25 14:41:02 -040043// This class is not aware of query-response pairing or anything else about DNS.
44// For the observer:
45// This class is not re-entrant: the observer is not permitted to wait for a call to query()
46// or the destructor in a callback. Doing so will result in deadlocks.
47// This class may call the observer at any time after initialize(), until the destructor
48// returns (but not after).
Mike Yu5ae61542018-10-19 22:11:43 +080049class LIBNETD_RESOLV_TLS_EXPORT DnsTlsSocket : public IDnsTlsSocket {
Ben Schwartzded1b702017-10-25 14:41:02 -040050public:
51 DnsTlsSocket(const DnsTlsServer& server, unsigned mark,
Ben Schwartz33860762017-10-25 14:41:02 -040052 IDnsTlsSocketObserver* _Nonnull observer,
Ben Schwartzded1b702017-10-25 14:41:02 -040053 DnsTlsSessionCache* _Nonnull cache) :
Ben Schwartz33860762017-10-25 14:41:02 -040054 mMark(mark), mServer(server), mObserver(observer), mCache(cache) {}
Ben Schwartzded1b702017-10-25 14:41:02 -040055 ~DnsTlsSocket();
56
57 // Creates the SSL context for this session and connect. Returns false on failure.
58 // This method should be called after construction and before use of a DnsTlsSocket.
59 // Only call this method once per DnsTlsSocket.
60 bool initialize() EXCLUDES(mLock);
61
62 // Send a query on the provided SSL socket. |query| contains
Ben Schwartz33860762017-10-25 14:41:02 -040063 // the body of a query, not including the ID header. This function will typically return before
64 // the query is actually sent. If this function fails, DnsTlsSocketObserver will be
65 // notified that the socket is closed.
66 // Note that success here indicates successful sending, not receipt of a response.
67 // Thread-safe.
68 bool query(uint16_t id, const Slice query) override;
Ben Schwartzded1b702017-10-25 14:41:02 -040069
70private:
Ben Schwartz33860762017-10-25 14:41:02 -040071 // Lock to be held by the SSL event loop thread. This is not normally in contention.
Ben Schwartzded1b702017-10-25 14:41:02 -040072 std::mutex mLock;
73
Ben Schwartz33860762017-10-25 14:41:02 -040074 // Forwards queries and receives responses. Blocks until the idle timeout.
75 void loop() EXCLUDES(mLock);
76 std::unique_ptr<std::thread> mLoopThread GUARDED_BY(mLock);
77
Ben Schwartzded1b702017-10-25 14:41:02 -040078 // On success, sets mSslFd to a socket connected to mAddr (the
79 // connection will likely be in progress if mProtocol is IPPROTO_TCP).
80 // On error, returns the errno.
81 netdutils::Status tcpConnect() REQUIRES(mLock);
82
83 // Connect an SSL session on the provided socket. If connection fails, closing the
84 // socket remains the caller's responsibility.
85 bssl::UniquePtr<SSL> sslConnect(int fd) REQUIRES(mLock);
86
87 // Disconnect the SSL session and close the socket.
88 void sslDisconnect() REQUIRES(mLock);
89
90 // Writes a buffer to the socket.
91 bool sslWrite(const Slice buffer) REQUIRES(mLock);
92
Ben Schwartz33860762017-10-25 14:41:02 -040093 // Reads exactly the specified number of bytes from the socket, or fails.
94 // Returns SSL_ERROR_NONE on success.
95 // If |wait| is true, then this function always blocks. Otherwise, it
96 // will return SSL_ERROR_WANT_READ if there is no data from the server to read.
97 int sslRead(const Slice buffer, bool wait) REQUIRES(mLock);
Ben Schwartzded1b702017-10-25 14:41:02 -040098
99 struct Query {
100 uint16_t id;
Ben Schwartz33860762017-10-25 14:41:02 -0400101 Slice query;
Ben Schwartzded1b702017-10-25 14:41:02 -0400102 };
103
104 bool sendQuery(const Query& q) REQUIRES(mLock);
Ben Schwartz33860762017-10-25 14:41:02 -0400105 bool readResponse() REQUIRES(mLock);
106
107 // SOCK_SEQPACKET socket pair used for sending queries from myriad query
108 // threads to the SSL thread. EOF indicates a close request.
Bernie Innocenti23bf9272018-05-23 15:45:40 +0900109 // We have to use a socket pair (i.e. a pipe) because the SSL thread needs
110 // to wait in poll() for input from either a remote server or a query thread.
Ben Schwartz33860762017-10-25 14:41:02 -0400111 base::unique_fd mIpcInFd;
112 base::unique_fd mIpcOutFd GUARDED_BY(mLock);
Ben Schwartzded1b702017-10-25 14:41:02 -0400113
114 // SSL Socket fields.
115 bssl::UniquePtr<SSL_CTX> mSslCtx GUARDED_BY(mLock);
116 base::unique_fd mSslFd GUARDED_BY(mLock);
117 bssl::UniquePtr<SSL> mSsl GUARDED_BY(mLock);
Ben Schwartz33860762017-10-25 14:41:02 -0400118 static constexpr std::chrono::seconds kIdleTimeout = std::chrono::seconds(20);
Ben Schwartzded1b702017-10-25 14:41:02 -0400119
120 const unsigned mMark; // Socket mark
121 const DnsTlsServer mServer;
Ben Schwartz33860762017-10-25 14:41:02 -0400122 IDnsTlsSocketObserver* _Nonnull const mObserver;
Ben Schwartzded1b702017-10-25 14:41:02 -0400123 DnsTlsSessionCache* _Nonnull const mCache;
124};
125
126} // end of namespace net
127} // end of namespace android
128
129#endif // _DNS_DNSTLSSOCKET_H