2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008 Collabora Ltd.
5 * (C) 2008 Nokia Corporation. All rights reserved.
6 * Contact: Youness Alaoui
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 * Alternatively, the contents of this file may be used under the terms of the
25 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
26 * case the provisions of LGPL are applicable instead of those above. If you
27 * wish to allow use of your version of this file only under the terms of the
28 * LGPL and not to allow others to use your version of this file under the
29 * MPL, indicate your decision by deleting the provisions above and replace
30 * them with the notice and other provisions required by the LGPL. If you do
31 * not delete the provisions above, a recipient may use your version of this
32 * file under either the MPL or the LGPL.
40 * @short_description: STUN agent for building and validating STUN messages
41 * @include: stun/stunagent.h
42 * @see_also: #StunMessage
45 * The STUN Agent allows you to create and validate STUN messages easily.
46 * It's main purpose is to make sure the building and validation methods used
47 * are compatible with the RFC you create it with. It also tracks the transaction
48 * ids of the requests you send, so you can validate if a STUN response you
49 * received should be processed by that agent or not.
55 #include "win32_common.h"
62 #include <sys/types.h>
67 * An opaque structure representing the STUN agent.
69 typedef struct stun_agent_t StunAgent
;
71 #include "stunmessage.h"
76 * @STUN_COMPATIBILITY_RFC3489: Use the STUN specifications compatible with
78 * @STUN_COMPATIBILITY_RFC5389: Use the STUN specifications compatible with
80 * @STUN_COMPATIBILITY_WLM2009: Use the STUN specifications compatible with
81 * Windows Live Messenger 2009 (a mix between RFC3489 and RFC5389, as well as
82 * a special usecase against a typo in their code)
83 * @STUN_COMPATIBILITY_LAST: Dummy last compatibility mode
85 * Enum that specifies the STUN compatibility mode of the #StunAgent
88 STUN_COMPATIBILITY_RFC3489
,
89 STUN_COMPATIBILITY_RFC5389
,
90 STUN_COMPATIBILITY_WLM2009
,
91 STUN_COMPATIBILITY_LAST
= STUN_COMPATIBILITY_WLM2009
96 * StunValidationStatus:
97 * @STUN_VALIDATION_SUCCESS: The message is validated
98 * @STUN_VALIDATION_NOT_STUN: This is not a valid STUN message
99 * @STUN_VALIDATION_INCOMPLETE_STUN: The message seems to be valid but incomplete
100 * @STUN_VALIDATION_BAD_REQUEST: The message does not have the cookie or the
101 * fingerprint while the agent needs it with its usage
102 * @STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST: The message is valid but
103 * unauthorized with no username and message-integrity attributes.
104 * A BAD_REQUEST error must be generated
105 * @STUN_VALIDATION_UNAUTHORIZED: The message is valid but unauthorized as
106 * the username/password do not match.
107 * An UNAUTHORIZED error must be generated
108 * @STUN_VALIDATION_UNMATCHED_RESPONSE: The message is valid but this is a
109 * response/error that doesn't match a previously sent request
110 * @STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE: The message is valid but
111 * contains one or more unknown comprehension attributes.
112 * stun_agent_build_unknown_attributes_error() should be called
113 * @STUN_VALIDATION_UNKNOWN_ATTRIBUTE: The message is valid but contains one
114 * or more unknown comprehension attributes. This is a response, or error,
115 * or indication message and no error response should be sent
117 * This enum is used as the return value of stun_agent_validate() and represents
118 * the status result of the validation of a STUN message.
121 STUN_VALIDATION_SUCCESS
,
122 STUN_VALIDATION_NOT_STUN
,
123 STUN_VALIDATION_INCOMPLETE_STUN
,
124 STUN_VALIDATION_BAD_REQUEST
,
125 STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST
,
126 STUN_VALIDATION_UNAUTHORIZED
,
127 STUN_VALIDATION_UNMATCHED_RESPONSE
,
128 STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE
,
129 STUN_VALIDATION_UNKNOWN_ATTRIBUTE
,
130 } StunValidationStatus
;
133 * StunAgentUsageFlags:
134 * @STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS: The agent should be using the short
135 * term credentials mechanism for authenticating STUN messages
136 * @STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS: The agent should be using the long
137 * term credentials mechanism for authenticating STUN messages
138 * @STUN_AGENT_USAGE_USE_FINGERPRINT: The agent should add the FINGERPRINT
139 * attribute to the STUN messages it creates.
140 * @STUN_AGENT_USAGE_ADD_SOFTWARE: The agent should add the SOFTWARE attribute
141 * to the STUN messages it creates
142 * @STUN_AGENT_USAGE_IGNORE_CREDENTIALS: The agent should ignore any credentials
143 * in the STUN messages it receives (the MESSAGE-INTEGRITY attribute
144 * will never be validated by stun_agent_validate())
145 * @STUN_AGENT_USAGE_NO_INDICATION_AUTH: The agent should ignore credentials
146 * in the STUN messages it receives if the #StunClass of the message is
147 * #STUN_INDICATION (some implementation require #STUN_INDICATION messages to
148 * be authenticated, while others never add a MESSAGE-INTEGRITY attribute to a
149 * #STUN_INDICATION message)
150 * @STUN_AGENT_USAGE_FORCE_VALIDATER: The agent should always try to validate
151 * the password of a STUN message, even if it already knows what the password
152 * should be (a response to a previously created request). This means that the
153 * #StunMessageIntegrityValidate callback will always be called when there is
154 * a MESSAGE-INTEGRITY attribute.
156 * This enum defines a bitflag usages for a #StunAgent and they will define how
157 * the agent should behave, independently of the compatibility mode it uses.
158 * <para> See also: stun_agent_init() </para>
159 * <para> See also: stun_agent_validate() </para>
162 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
= (1 << 0),
163 STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
= (1 << 1),
164 STUN_AGENT_USAGE_USE_FINGERPRINT
= (1 << 2),
165 STUN_AGENT_USAGE_ADD_SOFTWARE
= (1 << 3),
166 STUN_AGENT_USAGE_IGNORE_CREDENTIALS
= (1 << 4),
167 STUN_AGENT_USAGE_NO_INDICATION_AUTH
= (1 << 5),
168 STUN_AGENT_USAGE_FORCE_VALIDATER
= (1 << 6),
169 } StunAgentUsageFlags
;
173 StunTransactionId id
;
177 uint8_t long_term_key
[16];
178 bool long_term_valid
;
182 struct stun_agent_t
{
183 StunCompatibility compatibility
;
184 StunAgentSavedIds sent_ids
[STUN_AGENT_MAX_SAVED_IDS
];
185 uint16_t *known_attributes
;
186 StunAgentUsageFlags usage_flags
;
190 * StunDefaultValidaterData:
191 * @username: The username
192 * @username_len: The length of the @username
193 * @password: The password
194 * @password_len: The length of the @password
196 * This structure is used as an element of the user_data to the
197 * stun_agent_default_validater() function for authenticating a STUN
198 * message during validationg.
199 * <para> See also: stun_agent_default_validater() </para>
206 } StunDefaultValidaterData
;
210 * StunMessageIntegrityValidate:
211 * @agent: The #StunAgent
212 * @message: The #StunMessage being validated
213 * @username: The username found in the @message
214 * @username_len: The length of @username
215 * @password: The password associated with that username. This argument is a
216 * pointer to a byte array that must be set by the validater function.
217 * @password_len: The length of @password which must also be set by the
218 * validater function.
219 * @user_data: Data to give the function
221 * This is the prototype for the @validater argument of the stun_agent_validate()
223 * <para> See also: stun_agent_validate() </para>
224 * Returns: %TRUE if the authentication was successful,
225 * %FALSE if the authentication failed
227 typedef bool (*StunMessageIntegrityValidate
) (StunAgent
*agent
,
228 StunMessage
*message
, uint8_t *username
, uint16_t username_len
,
229 uint8_t **password
, size_t *password_len
, void *user_data
);
232 * stun_agent_default_validater:
233 * @agent: The #StunAgent
234 * @message: The #StunMessage being validated
235 * @username: The username found in the @message
236 * @username_len: The length of @username
237 * @password: The password associated with that username. This argument is a
238 * pointer to a byte array that must be set by the validater function.
239 * @password_len: The length of @password which must also be set by the
240 * validater function.
241 * @user_data: This must be an array of #StunDefaultValidaterData structures.
242 * The last element in the array must have a username set to NULL
244 * This is a helper function to be used with stun_agent_validate(). If no
245 * complicated processing of the username needs to be done, this function can
246 * be used with stun_agent_validate() to quickly and easily match the username
247 * of a STUN message with its password. Its @user_data argument must be an array
248 * of #StunDefaultValidaterData which will allow us to map a username to a
250 * <para> See also: stun_agent_validate() </para>
251 * Returns: %TRUE if the authentication was successful,
252 * %FALSE if the authentication failed
254 bool stun_agent_default_validater (StunAgent
*agent
,
255 StunMessage
*message
, uint8_t *username
, uint16_t username_len
,
256 uint8_t **password
, size_t *password_len
, void *user_data
);
260 * @agent: The #StunAgent to initialize
261 * @known_attributes: An array of #uint16_t specifying which attributes should
262 * be known by the agent. Any STUN message received that contains a mandatory
263 * attribute that is not in this array will yield a
264 * #STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE or a
265 * #STUN_VALIDATION_UNKNOWN_ATTRIBUTE error when calling stun_agent_validate()
266 * @compatibility: The #StunCompatibility to use for this agent. This will affect
267 * how the agent builds and validates the STUN messages
268 * @usage_flags: A bitflag using #StunAgentUsageFlags values to define which
269 * STUN usages the agent should use.
271 * This function must be called to initialize an agent before it is being used.
275 The @known_attributes data must exist in memory as long as the @agent is used
278 If the #STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS and
279 #STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS usage flags are not set, then the
280 agent will default in using the short term credentials mechanism
283 The #STUN_AGENT_USAGE_USE_FINGERPRINT and #STUN_AGENT_USAGE_ADD_SOFTWARE
284 usage flags are only valid if the #STUN_COMPATIBILITY_RFC5389 or
285 #STUN_COMPATIBILITY_WLM2009 @compatibility is used
289 void stun_agent_init (StunAgent
*agent
, const uint16_t *known_attributes
,
290 StunCompatibility compatibility
, StunAgentUsageFlags usage_flags
);
293 * stun_agent_validate:
294 * @agent: The #StunAgent
295 * @msg: The #StunMessage to build
296 * @buffer: The data buffer of the STUN message
297 * @buffer_len: The length of @buffer
298 * @validater: A #StunMessageIntegrityValidate function callback that will
299 * be called if the agent needs to validate a MESSAGE-INTEGRITY attribute. It
300 * will only be called if the agent finds a message that needs authentication
301 * and a USERNAME is present in the STUN message, but no password is known.
302 * The validater will not be called if the #STUN_AGENT_USAGE_IGNORE_CREDENTIALS
303 * usage flag is set on the agent, and it will always be called if the
304 * #STUN_AGENT_USAGE_FORCE_VALIDATER usage flag is set on the agent.
305 * @validater_data: A user data to give to the @validater callback when it gets
308 * This function is used to validate an inbound STUN message and transform its
309 * data buffer into a #StunMessage. It will take care of various validation
310 * algorithms to make sure that the STUN message is valid and correctly
312 * <para> See also: stun_agent_default_validater() </para>
313 * Returns: A #StunValidationStatus
316 if the return value is different from #STUN_VALIDATION_NOT_STUN or
317 #STUN_VALIDATION_INCOMPLETE_STUN, then the @msg argument will contain a valid
318 STUN message that can be used.
319 This means that you can use the @msg variable as the @request argument to
320 functions like stun_agent_init_error() or
321 stun_agent_build_unknown_attributes_error().
322 If the return value is #STUN_VALIDATION_BAD_REQUEST,
323 #STUN_VALIDATION_UNAUTHORIZED or #STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST
324 then the @key in the #StunMessage will not be set, so that error responses
325 will not have a MESSAGE-INTEGRITY attribute.
329 StunValidationStatus
stun_agent_validate (StunAgent
*agent
, StunMessage
*msg
,
330 const uint8_t *buffer
, size_t buffer_len
,
331 StunMessageIntegrityValidate validater
, void * validater_data
);
334 * stun_agent_forget_transaction:
335 * @agent: The #StunAgent
336 * @id: The #StunTransactionId of the transaction to forget
338 * This function is used to make the #StunAgent forget about a previously
339 * created transaction. <br/>
340 * This function should be called when a STUN request was previously
341 * created with stun_agent_finish_message() and for which no response was ever
342 * received (timed out). The #StunAgent keeps a list of the sent transactions
343 * in order to validate the responses received. If the response is never received
344 * this will allow the #StunAgent to forget about the timed out transaction and
345 * free its slot for future transactions.
346 * Returns: %TRUE if the transaction was found, %FALSE otherwise
348 bool stun_agent_forget_transaction (StunAgent
*agent
, StunTransactionId id
);
352 * stun_agent_init_request:
353 * @agent: The #StunAgent
354 * @msg: The #StunMessage to build
355 * @buffer: The buffer to use in the #StunMessage
356 * @buffer_len: The length of the buffer
357 * @m: The #StunMethod of the request
359 * Creates a new STUN message of class #STUN_REQUEST and with the method @m
360 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
362 bool stun_agent_init_request (StunAgent
*agent
, StunMessage
*msg
,
363 uint8_t *buffer
, size_t buffer_len
, StunMethod m
);
366 * stun_agent_init_indication:
367 * @agent: The #StunAgent
368 * @msg: The #StunMessage to build
369 * @buffer: The buffer to use in the #StunMessage
370 * @buffer_len: The length of the buffer
371 * @m: The #StunMethod of the indication
373 * Creates a new STUN message of class #STUN_INDICATION and with the method @m
374 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
376 bool stun_agent_init_indication (StunAgent
*agent
, StunMessage
*msg
,
377 uint8_t *buffer
, size_t buffer_len
, StunMethod m
);
380 * stun_agent_init_response:
381 * @agent: The #StunAgent
382 * @msg: The #StunMessage to build
383 * @buffer: The buffer to use in the #StunMessage
384 * @buffer_len: The length of the buffer
385 * @request: The #StunMessage of class #STUN_REQUEST that this response is for
387 * Creates a new STUN message of class #STUN_RESPONSE and with the same method
388 * and transaction ID as the message @request. This will also copy the pointer
389 * to the key that was used to authenticate the request, so you won't need to
390 * specify the key with stun_agent_finish_message()
391 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
393 bool stun_agent_init_response (StunAgent
*agent
, StunMessage
*msg
,
394 uint8_t *buffer
, size_t buffer_len
, const StunMessage
*request
);
397 * stun_agent_init_error:
398 * @agent: The #StunAgent
399 * @msg: The #StunMessage to build
400 * @buffer: The buffer to use in the #StunMessage
401 * @buffer_len: The length of the buffer
402 * @request: The #StunMessage of class #STUN_REQUEST that this error response
404 * @err: The #StunError to put in the ERROR-CODE attribute of the error response
406 * Creates a new STUN message of class #STUN_ERROR and with the same method
407 * and transaction ID as the message @request. This will also copy the pointer
408 * to the key that was used to authenticate the request (if authenticated),
409 * so you won't need to specify the key with stun_agent_finish_message().
410 * It will then add the ERROR-CODE attribute with code @err and the associated
412 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
414 bool stun_agent_init_error (StunAgent
*agent
, StunMessage
*msg
,
415 uint8_t *buffer
, size_t buffer_len
, const StunMessage
*request
,
419 * stun_agent_build_unknown_attributes_error:
420 * @agent: The #StunAgent
421 * @msg: The #StunMessage to build
422 * @buffer: The buffer to use in the #StunMessage
423 * @buffer_len: The length of the buffer
424 * @request: The #StunMessage of class #STUN_REQUEST that this response is for
426 * Creates a new STUN message of class #STUN_ERROR and with the same method
427 * and transaction ID as the message @request. It will then add the ERROR-CODE
428 * attribute with code #STUN_ERROR_UNKNOWN_ATTRIBUTE and add all the unknown
429 * mandatory attributes from the @request STUN message in the
430 * #STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES attribute, it will then finish the message
431 * by calling stun_agent_finish_message()
432 * Returns: The size of the message built
434 size_t stun_agent_build_unknown_attributes_error (StunAgent
*agent
,
435 StunMessage
*msg
, uint8_t *buffer
, size_t buffer_len
,
436 const StunMessage
*request
);
440 * stun_agent_finish_message:
441 * @agent: The #StunAgent
442 * @msg: The #StunMessage to finish
443 * @key: The key to use for the MESSAGE-INTEGRITY attribute
444 * @key_len: The length of the @key
446 * This function will 'finish' a message and make it ready to be sent. It will
447 * add the MESSAGE-INTEGRITY and FINGERPRINT attributes if necessary. If the
448 * STUN message has a #STUN_REQUEST class, it will save the transaction id of
449 * the message in the agent for future matching of the response.
450 * Returns: The final size of the message built
452 size_t stun_agent_finish_message (StunAgent
*agent
, StunMessage
*msg
,
453 const uint8_t *key
, size_t key_len
);
455 #endif /* _STUN_AGENT_H */