Commit 5ecee6fb authored by Olivier Crête's avatar Olivier Crête

agent: Allow using TURN with short term credentials

parent be9f046b
......@@ -133,6 +133,7 @@ struct _NiceAgent
guint timer_ta; /* property: timer Ta */
guint max_conn_checks; /* property: max connectivity checks */
gboolean force_relay; /* property: force relay */
gboolean turn_short_term; /* property: turn short term credentials */
GSList *local_addresses; /* list of NiceAddresses for local
interfaces */
......
......@@ -108,6 +108,7 @@ enum
PROP_BYTESTREAM_TCP,
PROP_KEEPALIVE_CONNCHECK,
PROP_FORCE_RELAY,
PROP_TURN_SHORT_TERM
};
......@@ -288,6 +289,10 @@ agent_to_turn_compatibility (NiceAgent *agent)
NiceTurnSocketCompatibility
agent_to_turn_socket_compatibility (NiceAgent *agent)
{
if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
agent->turn_short_term)
return NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM;
return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE :
agent->compatibility == NICE_COMPATIBILITY_MSN ?
......@@ -695,6 +700,24 @@ nice_agent_class_init (NiceAgentClass *klass)
FALSE,
G_PARAM_READWRITE));
/**
* NiceAgent:turn-short-term
*
* Force all traffic to go through a relay for added privacy, this
* allows hiding the local IP address. When this is enabled, so
* local candidates are available before relay servers have been set
* with nice_agent_set_relay_info().
*
* Since: UNRELEASED
*/
g_object_class_install_property (gobject_class, PROP_TURN_SHORT_TERM,
g_param_spec_boolean (
"turn-short-term",
"TURN Short Term Credentials",
"Login into TURN server with short term credentials",
FALSE,
G_PARAM_READWRITE));
/* install signals */
/**
......@@ -1119,6 +1142,10 @@ nice_agent_get_property (
g_value_set_boolean (value, agent->force_relay);
break;
case PROP_TURN_SHORT_TERM:
g_value_set_boolean (value, agent->turn_short_term);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
......@@ -1302,6 +1329,10 @@ nice_agent_set_property (
agent->force_relay = g_value_get_boolean (value);
break;
case PROP_TURN_SHORT_TERM:
agent->turn_short_term = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
......@@ -1758,6 +1789,12 @@ priv_add_new_candidate_discovery_turn (NiceAgent *agent,
STUN_COMPATIBILITY_OC2007,
STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS |
STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
} else if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
agent->turn_short_term) {
stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
STUN_COMPATIBILITY_RFC5389,
STUN_AGENT_USAGE_ADD_SOFTWARE |
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
} else {
stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
STUN_COMPATIBILITY_RFC5389,
......
......@@ -207,6 +207,10 @@ nice_udp_turn_socket_new (GMainContext *ctx, NiceAddress *addr,
STUN_COMPATIBILITY_OC2007,
STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS |
STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
} else if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM) {
stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES,
STUN_COMPATIBILITY_RFC5389,
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS | STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
}
priv->channels = NULL;
......@@ -716,6 +720,7 @@ socket_send_message (NiceSocket *sock, const NiceAddress *to,
if (binding) {
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
gsize message_len = output_message_get_size (message);
......@@ -763,6 +768,7 @@ socket_send_message (NiceSocket *sock, const NiceAddress *to,
gsize compacted_buf_len;
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
if (!stun_agent_init_indication (&priv->agent, &msg,
buffer, sizeof(buffer), STUN_IND_SEND))
......@@ -771,6 +777,13 @@ socket_send_message (NiceSocket *sock, const NiceAddress *to,
&sa.storage, sizeof(sa)) !=
STUN_MESSAGE_RETURN_SUCCESS)
goto error;
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM &&
priv->username != NULL && priv->username_len > 0) {
if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_USERNAME,
priv->username, priv->username_len) !=
STUN_MESSAGE_RETURN_SUCCESS)
goto error;
}
} else {
if (!stun_agent_init_request (&priv->agent, &msg,
buffer, sizeof(buffer), STUN_SEND))
......@@ -836,7 +849,8 @@ socket_send_message (NiceSocket *sock, const NiceAddress *to,
}
if (msg_len > 0) {
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
if ((priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) &&
!priv_has_permission_for_peer (priv, to)) {
if (!priv_has_sent_permission_for_peer (priv, to)) {
priv_send_create_permission (priv, to);
......@@ -1205,7 +1219,8 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
if (valid == STUN_VALIDATION_SUCCESS) {
if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 &&
priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM) {
uint32_t cookie;
if (stun_message_find32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE,
&cookie) != STUN_MESSAGE_RETURN_SUCCESS)
......@@ -1483,6 +1498,7 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
socklen_t from_len = sizeof (sa);
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
&sa.storage, &from_len) !=
......@@ -1503,8 +1519,9 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
nice_address_set_from_sockaddr (from, &sa.addr);
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
!priv_has_permission_for_peer (priv, from)) {
if ((priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) &&
!priv_has_permission_for_peer (priv, from)) {
if (!priv_has_sent_permission_for_peer (priv, from)) {
priv_send_create_permission (priv, from);
}
......@@ -1523,6 +1540,7 @@ nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
for (l = priv->channels; l; l = l->next) {
ChannelBinding *b = l->data;
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
if (b->channel == ntohs(recv_buf.u16[0])) {
recv_len = ntohs (recv_buf.u16[1]);
......@@ -1942,30 +1960,30 @@ priv_send_channel_bind (UdpTurnPriv *priv, uint16_t channel,
return FALSE;
}
if (priv->username != NULL && priv->username_len > 0 &&
priv->cached_realm != NULL && priv->cached_realm_len > 0 &&
priv->cached_nonce != NULL && priv->cached_nonce_len > 0) {
if (priv->username != NULL && priv->username_len) {
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME,
priv->username, priv->username_len)
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
return FALSE;
}
}
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM,
priv->cached_realm, priv->cached_realm_len)
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
return 0;
}
if (priv->cached_realm != NULL && priv->cached_realm_len > 0 &&
priv->cached_nonce != NULL && priv->cached_nonce_len > 0) {
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM,
priv->cached_realm, priv->cached_realm_len)
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
return FALSE;
}
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE,
priv->cached_nonce, priv->cached_nonce_len)
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
return 0;
}
if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE,
priv->cached_nonce, priv->cached_nonce_len)
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
return FALSE;
}
}
stun_len = stun_agent_finish_message (&priv->agent, &msg->message,
......@@ -1999,6 +2017,7 @@ priv_add_channel_binding (UdpTurnPriv *priv, const NiceAddress *peer)
}
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
uint16_t channel = 0x4000;
GList *i = priv->channels;
......
......@@ -44,6 +44,7 @@ typedef enum {
NICE_TURN_SOCKET_COMPATIBILITY_MSN,
NICE_TURN_SOCKET_COMPATIBILITY_OC2007,
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766,
NICE_TURN_SOCKET_COMPATIBILITY_RFC5766_SHORT_TERM
} NiceTurnSocketCompatibility;
#include "socket.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment