2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2008-2009 Nokia Corporation. All rights reserved.
8 * The contents of this file are subject to the Mozilla Public License Version
9 * 1.1 (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS" basis,
14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 * for the specific language governing rights and limitations under the
18 * The Original Code is the Nice GLib ICE library.
20 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
21 * Corporation. All Rights Reserved.
24 * Youness Alaoui, Collabora Ltd.
26 * Alternatively, the contents of this file may be used under the terms of the
27 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
28 * case the provisions of LGPL are applicable instead of those above. If you
29 * wish to allow use of your version of this file only under the terms of the
30 * LGPL and not to allow others to use your version of this file under the
31 * MPL, indicate your decision by deleting the provisions above and replace
32 * them with the notice and other provisions required by the LGPL. If you do
33 * not delete the provisions above, a recipient may use your version of this
34 * file under either the MPL or the LGPL.
38 * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
39 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
45 #include "pseudossl.h"
46 #include "agent-priv.h"
47 #include "socket-priv.h"
57 NiceSocket *base_socket;
59 NicePseudoSSLSocketCompatibility compatibility;
63 static const gchar SSL_SERVER_GOOGLE_HANDSHAKE[] = {
64 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
65 0x46, 0x03, 0x01, 0x42, 0x85, 0x45, 0xa7, 0x27,
66 0xa9, 0x5d, 0xa0, 0xb3, 0xc5, 0xe7, 0x53, 0xda,
67 0x48, 0x2b, 0x3f, 0xc6, 0x5a, 0xca, 0x89, 0xc1,
68 0x58, 0x52, 0xa1, 0x78, 0x3c, 0x5b, 0x17, 0x46,
69 0x00, 0x85, 0x3f, 0x20, 0x0e, 0xd3, 0x06, 0x72,
70 0x5b, 0x5b, 0x1b, 0x5f, 0x15, 0xac, 0x13, 0xf9,
71 0x88, 0x53, 0x9d, 0x9b, 0xe8, 0x3d, 0x7b, 0x0c,
72 0x30, 0x32, 0x6e, 0x38, 0x4d, 0xa2, 0x75, 0x57,
73 0x41, 0x6c, 0x34, 0x5c, 0x00, 0x04, 0x00};
75 static const gchar SSL_CLIENT_GOOGLE_HANDSHAKE[] = {
76 0x80, 0x46, 0x01, 0x03, 0x01, 0x00, 0x2d, 0x00,
77 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x03, 0x00,
78 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x40, 0x02,
79 0x00, 0x80, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04,
80 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, 0x00, 0xfe,
81 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, 0x00,
82 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06,
83 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc,
84 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea};
86 static const gchar SSL_SERVER_MSOC_HANDSHAKE[] = {
87 0x16, 0x03, 0x01, 0x00, 0x4e, 0x02, 0x00, 0x00,
88 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0e,
99 static const gchar SSL_CLIENT_MSOC_HANDSHAKE[] = {
100 0x16, 0x03, 0x01, 0x00, 0x2d, 0x01, 0x00, 0x00,
101 0x29, 0x03, 0x01, 0xc1, 0xfc, 0xd5, 0xa3, 0x6d,
102 0x93, 0xdd, 0x7e, 0x0b, 0x45, 0x67, 0x3f, 0xec,
103 0x79, 0x85, 0xfb, 0xbc, 0x3f, 0xd6, 0x60, 0xc2,
104 0xce, 0x84, 0x85, 0x08, 0x1b, 0x81, 0x21, 0xbc,
105 0xaa, 0x10, 0xfb, 0x00, 0x00, 0x02, 0x00, 0x18,
108 static void socket_close (NiceSocket *sock);
109 static gint socket_recv_messages (NiceSocket *sock,
110 NiceInputMessage *recv_messages, guint n_recv_messages);
111 static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
112 const NiceOutputMessage *messages, guint n_messages);
113 static gint socket_send_messages_reliable (NiceSocket *sock,
114 const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
115 static gboolean socket_is_reliable (NiceSocket *sock);
116 static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
117 static void socket_set_writable_callback (NiceSocket *sock,
118 NiceSocketWritableCb callback, gpointer user_data);
119 static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
122 nice_pseudossl_socket_new (NiceSocket *base_socket,
123 NicePseudoSSLSocketCompatibility compatibility)
130 if (compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC) {
131 buf = SSL_CLIENT_MSOC_HANDSHAKE;
132 len = sizeof(SSL_CLIENT_MSOC_HANDSHAKE);
133 } else if (compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE) {
134 buf = SSL_CLIENT_GOOGLE_HANDSHAKE;
135 len = sizeof(SSL_CLIENT_GOOGLE_HANDSHAKE);
140 sock = g_slice_new0 (NiceSocket);
141 sock->priv = priv = g_slice_new0 (PseudoSSLPriv);
143 priv->handshaken = FALSE;
144 priv->base_socket = base_socket;
145 priv->compatibility = compatibility;
147 sock->type = NICE_SOCKET_TYPE_PSEUDOSSL;
148 sock->fileno = priv->base_socket->fileno;
149 sock->addr = priv->base_socket->addr;
150 sock->send_messages = socket_send_messages;
151 sock->send_messages_reliable = socket_send_messages_reliable;
152 sock->recv_messages = socket_recv_messages;
153 sock->is_reliable = socket_is_reliable;
154 sock->can_send = socket_can_send;
155 sock->set_writable_callback = socket_set_writable_callback;
156 sock->is_based_on = socket_is_based_on;
157 sock->close = socket_close;
159 /* We send 'to' NULL because it will always be to an already connected
160 * TCP base socket, which ignores the destination */
161 nice_socket_send_reliable (priv->base_socket, NULL, len, buf);
168 socket_close (NiceSocket *sock)
170 PseudoSSLPriv *priv = sock->priv;
172 if (priv->base_socket)
173 nice_socket_free (priv->base_socket);
175 nice_socket_free_send_queue (&priv->send_queue);
177 g_slice_free(PseudoSSLPriv, sock->priv);
182 server_handshake_valid(NiceSocket *sock, GInputVector *data, guint length)
184 PseudoSSLPriv *priv = sock->priv;
186 if (priv->compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC) {
187 if (length == sizeof(SSL_SERVER_MSOC_HANDSHAKE)) {
188 guint8 *buf = data->buffer;
190 memset(buf + 11, 0, 32);
191 memset(buf + 44, 0, 32);
192 return memcmp(SSL_SERVER_MSOC_HANDSHAKE, data->buffer,
193 sizeof(SSL_SERVER_MSOC_HANDSHAKE)) == 0;
197 return length == sizeof(SSL_SERVER_GOOGLE_HANDSHAKE) &&
198 memcmp(SSL_SERVER_GOOGLE_HANDSHAKE, data->buffer,
199 sizeof(SSL_SERVER_GOOGLE_HANDSHAKE)) == 0;
204 socket_recv_messages (NiceSocket *sock,
205 NiceInputMessage *recv_messages, guint n_recv_messages)
207 PseudoSSLPriv *priv = sock->priv;
209 /* Make sure socket has not been freed: */
210 g_assert (sock->priv != NULL);
212 if (priv->handshaken) {
213 if (priv->base_socket) {
214 /* Fast path: once we’ve done the handshake, pass straight through to the
216 return nice_socket_recv_messages (priv->base_socket,
217 recv_messages, n_recv_messages);
220 guint8 data[MAX(sizeof(SSL_SERVER_GOOGLE_HANDSHAKE),
221 sizeof(SSL_SERVER_MSOC_HANDSHAKE))];
223 GInputVector local_recv_buf = { data, sizeof(data) };
224 NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
227 if (priv->compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC) {
228 local_recv_buf.size = sizeof(SSL_SERVER_MSOC_HANDSHAKE);
230 local_recv_buf.size = sizeof(SSL_SERVER_GOOGLE_HANDSHAKE);
232 if (priv->base_socket) {
233 ret = nice_socket_recv_messages (priv->base_socket,
234 &local_recv_message, 1);
239 } else if (ret == 1 && server_handshake_valid(sock, &local_recv_buf,
240 local_recv_message.length)) {
241 priv->handshaken = TRUE;
242 nice_socket_flush_send_queue (priv->base_socket, &priv->send_queue);
244 if (priv->base_socket)
245 nice_socket_free (priv->base_socket);
246 priv->base_socket = NULL;
255 socket_send_messages (NiceSocket *sock, const NiceAddress *to,
256 const NiceOutputMessage *messages, guint n_messages)
258 PseudoSSLPriv *priv = sock->priv;
260 /* Make sure socket has not been freed: */
261 g_assert (sock->priv != NULL);
263 if (priv->handshaken) {
264 /* Fast path: pass directly through to the base socket once the handshake is
266 if (priv->base_socket == NULL)
269 return nice_socket_send_messages (priv->base_socket, to, messages,
279 socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
280 const NiceOutputMessage *messages, guint n_messages)
282 PseudoSSLPriv *priv = sock->priv;
284 if (priv->handshaken) {
285 /* Fast path: pass directly through to the base socket once the handshake is
287 if (priv->base_socket == NULL)
290 return nice_socket_send_messages_reliable (priv->base_socket, to, messages,
293 nice_socket_queue_send (&priv->send_queue, to, messages, n_messages);
299 socket_is_reliable (NiceSocket *sock)
301 PseudoSSLPriv *priv = sock->priv;
303 return nice_socket_is_reliable (priv->base_socket);
307 socket_can_send (NiceSocket *sock, NiceAddress *addr)
309 PseudoSSLPriv *priv = sock->priv;
311 return nice_socket_can_send (priv->base_socket, addr);
315 socket_set_writable_callback (NiceSocket *sock,
316 NiceSocketWritableCb callback, gpointer user_data)
318 PseudoSSLPriv *priv = sock->priv;
320 nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
324 socket_is_based_on (NiceSocket *sock, NiceSocket *other)
326 PseudoSSLPriv *priv = sock->priv;
328 return (sock == other) ||
329 (priv && nice_socket_is_based_on (priv->base_socket, other));