blob: 9753d47d06dcb1c9fd4424175c5f9b1fb5dfb5c4 [file] [log] [blame]
Jens Geyerc1d79432014-04-22 22:52:43 +02001/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20using System;
21using System.Net.Sockets;
22using System.Security.Cryptography.X509Certificates;
23
24namespace Thrift.Transport
25{
Jens Geyerd5436f52014-10-03 19:50:38 +020026 /// <summary>
27 /// SSL Server Socket Wrapper Class
28 /// </summary>
29 public class TTLSServerSocket : TServerTransport
30 {
31 /// <summary>
32 /// Underlying tcp server
33 /// </summary>
34 private TcpListener server = null;
Jens Geyerc1d79432014-04-22 22:52:43 +020035
Jens Geyerd5436f52014-10-03 19:50:38 +020036 /// <summary>
37 /// The port where the socket listen
38 /// </summary>
39 private int port = 0;
Jens Geyerc1d79432014-04-22 22:52:43 +020040
Jens Geyerd5436f52014-10-03 19:50:38 +020041 /// <summary>
42 /// Timeout for the created server socket
43 /// </summary>
44 private int clientTimeout = 0;
Jens Geyerc1d79432014-04-22 22:52:43 +020045
Jens Geyerd5436f52014-10-03 19:50:38 +020046 /// <summary>
47 /// Whether or not to wrap new TSocket connections in buffers
48 /// </summary>
49 private bool useBufferedSockets = false;
Jens Geyerc1d79432014-04-22 22:52:43 +020050
Jens Geyerd5436f52014-10-03 19:50:38 +020051 /// <summary>
52 /// The servercertificate with the private- and public-key
53 /// </summary>
54 private X509Certificate serverCertificate;
Jens Geyerc1d79432014-04-22 22:52:43 +020055
56
Jens Geyerd5436f52014-10-03 19:50:38 +020057 /// <summary>
58 /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
59 /// </summary>
60 /// <param name="port">The port where the server runs.</param>
61 /// <param name="certificate">The certificate object.</param>
62 public TTLSServerSocket(int port, X509Certificate2 certificate)
63 : this(port, 0, certificate)
64 {
65 }
Jens Geyerc1d79432014-04-22 22:52:43 +020066
Jens Geyerd5436f52014-10-03 19:50:38 +020067 /// <summary>
68 /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
69 /// </summary>
70 /// <param name="port">The port where the server runs.</param>
71 /// <param name="clientTimeout">Send/receive timeout.</param>
72 /// <param name="certificate">The certificate object.</param>
73 public TTLSServerSocket(int port, int clientTimeout, X509Certificate2 certificate)
74 : this(port, clientTimeout, false, certificate)
75 {
76 }
Jens Geyerc1d79432014-04-22 22:52:43 +020077
Jens Geyerd5436f52014-10-03 19:50:38 +020078 /// <summary>
79 /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
80 /// </summary>
81 /// <param name="port">The port where the server runs.</param>
82 /// <param name="clientTimeout">Send/receive timeout.</param>
83 /// <param name="useBufferedSockets">If set to <c>true</c> [use buffered sockets].</param>
84 /// <param name="certificate">The certificate object.</param>
85 public TTLSServerSocket(int port, int clientTimeout, bool useBufferedSockets, X509Certificate2 certificate)
86 {
87 if (!certificate.HasPrivateKey)
88 {
89 throw new TTransportException(TTransportException.ExceptionType.Unknown, "Your server-certificate needs to have a private key");
90 }
Jens Geyerc1d79432014-04-22 22:52:43 +020091
Jens Geyerd5436f52014-10-03 19:50:38 +020092 this.port = port;
93 this.serverCertificate = certificate;
94 this.useBufferedSockets = useBufferedSockets;
95 try
96 {
97 // Create server socket
98 server = new TcpListener(System.Net.IPAddress.Any, this.port);
99 server.Server.NoDelay = true;
100 }
101 catch (Exception)
102 {
103 server = null;
104 throw new TTransportException("Could not create ServerSocket on port " + port + ".");
105 }
106 }
Jens Geyerc1d79432014-04-22 22:52:43 +0200107
Jens Geyerd5436f52014-10-03 19:50:38 +0200108 /// <summary>
109 /// Starts the server.
110 /// </summary>
111 public override void Listen()
112 {
113 // Make sure accept is not blocking
114 if (this.server != null)
115 {
116 try
117 {
118 this.server.Start();
119 }
120 catch (SocketException sx)
121 {
122 throw new TTransportException("Could not accept on listening socket: " + sx.Message);
123 }
124 }
125 }
Jens Geyerc1d79432014-04-22 22:52:43 +0200126
Jens Geyerd5436f52014-10-03 19:50:38 +0200127 /// <summary>
128 /// Callback for Accept Implementation
129 /// </summary>
130 /// <returns>
131 /// TTransport-object.
132 /// </returns>
133 protected override TTransport AcceptImpl()
134 {
135 if (this.server == null)
136 {
137 throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
138 }
Jens Geyerc1d79432014-04-22 22:52:43 +0200139
Jens Geyerd5436f52014-10-03 19:50:38 +0200140 try
141 {
142 TcpClient client = this.server.AcceptTcpClient();
143 client.SendTimeout = client.ReceiveTimeout = this.clientTimeout;
Jens Geyerc1d79432014-04-22 22:52:43 +0200144
Jens Geyerd5436f52014-10-03 19:50:38 +0200145 //wrap the client in an SSL Socket passing in the SSL cert
146 TTLSSocket socket = new TTLSSocket(client, this.serverCertificate, true);
Jens Geyerc1d79432014-04-22 22:52:43 +0200147
Jens Geyerd5436f52014-10-03 19:50:38 +0200148 socket.setupTLS();
Jens Geyerc1d79432014-04-22 22:52:43 +0200149
Jens Geyerd5436f52014-10-03 19:50:38 +0200150 if (useBufferedSockets)
151 {
152 TBufferedTransport trans = new TBufferedTransport(socket);
153 return trans;
154 }
155 else
156 {
157 return socket;
158 }
Jens Geyerc1d79432014-04-22 22:52:43 +0200159
Jens Geyerd5436f52014-10-03 19:50:38 +0200160 }
161 catch (Exception ex)
162 {
163 throw new TTransportException(ex.ToString());
164 }
165 }
166
167 /// <summary>
168 /// Stops the Server
169 /// </summary>
170 public override void Close()
171 {
172 if (this.server != null)
173 {
174 try
175 {
176 this.server.Stop();
177 }
178 catch (Exception ex)
179 {
180 throw new TTransportException("WARNING: Could not close server socket: " + ex);
181 }
182 this.server = null;
183 }
184 }
185 }
Jens Geyerc1d79432014-04-22 22:52:43 +0200186}