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.
42 * @short_description: STUN agent for building and validating STUN messages
43 * @include: stun/stunagent.h
44 * @see_also: #StunMessage
47 * The STUN Agent allows you to create and validate STUN messages easily.
48 * It's main purpose is to make sure the building and validation methods used
49 * are compatible with the RFC you create it with. It also tracks the transaction
50 * ids of the requests you send, so you can validate if a STUN response you
51 * received should be processed by that agent or not.
57 #include "win32_common.h"
64 #include <sys/types.h>
69 * An opaque structure representing the STUN agent.
71 typedef struct stun_agent_t StunAgent
;
73 #include "stunmessage.h"
78 * @STUN_COMPATIBILITY_RFC3489: Use the STUN specifications compatible with
80 * @STUN_COMPATIBILITY_RFC5389: Use the STUN specifications compatible with
82 * @STUN_COMPATIBILITY_WLM2009: Use the STUN specifications compatible with
83 * Windows Live Messenger 2009 (a mix between RFC3489 and RFC5389, as well as
84 * a special usecase against a typo in their code)
85 * @STUN_COMPATIBILITY_OC2007: Use the STUN specifications compatible with
86 * Microsoft Office Communicator 2007 (basically RFC3489 with swapped
87 * REALM and NONCE attribute hex IDs, attributes are not aligned)
88 * @STUN_COMPATIBILITY_LAST: Dummy last compatibility mode
90 * Enum that specifies the STUN compatibility mode of the #StunAgent
93 STUN_COMPATIBILITY_RFC3489
,
94 STUN_COMPATIBILITY_RFC5389
,
95 STUN_COMPATIBILITY_WLM2009
,
96 STUN_COMPATIBILITY_OC2007
,
97 STUN_COMPATIBILITY_LAST
= STUN_COMPATIBILITY_OC2007
102 * StunValidationStatus:
103 * @STUN_VALIDATION_SUCCESS: The message is validated
104 * @STUN_VALIDATION_NOT_STUN: This is not a valid STUN message
105 * @STUN_VALIDATION_INCOMPLETE_STUN: The message seems to be valid but incomplete
106 * @STUN_VALIDATION_BAD_REQUEST: The message does not have the cookie or the
107 * fingerprint while the agent needs it with its usage
108 * @STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST: The message is valid but
109 * unauthorized with no username and message-integrity attributes.
110 * A BAD_REQUEST error must be generated
111 * @STUN_VALIDATION_UNAUTHORIZED: The message is valid but unauthorized as
112 * the username/password do not match.
113 * An UNAUTHORIZED error must be generated
114 * @STUN_VALIDATION_UNMATCHED_RESPONSE: The message is valid but this is a
115 * response/error that doesn't match a previously sent request
116 * @STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE: The message is valid but
117 * contains one or more unknown comprehension attributes.
118 * stun_agent_build_unknown_attributes_error() should be called
119 * @STUN_VALIDATION_UNKNOWN_ATTRIBUTE: The message is valid but contains one
120 * or more unknown comprehension attributes. This is a response, or error,
121 * or indication message and no error response should be sent
123 * This enum is used as the return value of stun_agent_validate() and represents
124 * the status result of the validation of a STUN message.
127 STUN_VALIDATION_SUCCESS
,
128 STUN_VALIDATION_NOT_STUN
,
129 STUN_VALIDATION_INCOMPLETE_STUN
,
130 STUN_VALIDATION_BAD_REQUEST
,
131 STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST
,
132 STUN_VALIDATION_UNAUTHORIZED
,
133 STUN_VALIDATION_UNMATCHED_RESPONSE
,
134 STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE
,
135 STUN_VALIDATION_UNKNOWN_ATTRIBUTE
,
136 } StunValidationStatus
;
139 * StunAgentUsageFlags:
140 * @STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS: The agent should be using the short
141 * term credentials mechanism for authenticating STUN messages
142 * @STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS: The agent should be using the long
143 * term credentials mechanism for authenticating STUN messages
144 * @STUN_AGENT_USAGE_USE_FINGERPRINT: The agent should add the FINGERPRINT
145 * attribute to the STUN messages it creates.
146 * @STUN_AGENT_USAGE_ADD_SOFTWARE: The agent should add the SOFTWARE attribute
147 * to the STUN messages it creates. Calling nice_agent_set_software() will have
148 * the same effect as enabling this Usage. STUN Indications do not have the
149 * SOFTWARE attributes added to them though. The SOFTWARE attribute is only
150 * added for the RFC5389 and WLM2009 compatibility modes.
151 * @STUN_AGENT_USAGE_IGNORE_CREDENTIALS: The agent should ignore any credentials
152 * in the STUN messages it receives (the MESSAGE-INTEGRITY attribute
153 * will never be validated by stun_agent_validate())
154 * @STUN_AGENT_USAGE_NO_INDICATION_AUTH: The agent should ignore credentials
155 * in the STUN messages it receives if the #StunClass of the message is
156 * #STUN_INDICATION (some implementation require #STUN_INDICATION messages to
157 * be authenticated, while others never add a MESSAGE-INTEGRITY attribute to a
158 * #STUN_INDICATION message)
159 * @STUN_AGENT_USAGE_FORCE_VALIDATER: The agent should always try to validate
160 * the password of a STUN message, even if it already knows what the password
161 * should be (a response to a previously created request). This means that the
162 * #StunMessageIntegrityValidate callback will always be called when there is
163 * a MESSAGE-INTEGRITY attribute.
164 * @STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES: The agent should not assume STUN
165 * attributes are aligned on 32-bit boundaries when parsing messages and also
166 * do not add padding when creating messages.
168 * This enum defines a bitflag usages for a #StunAgent and they will define how
169 * the agent should behave, independently of the compatibility mode it uses.
170 * <para> See also: stun_agent_init() </para>
171 * <para> See also: stun_agent_validate() </para>
174 STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
= (1 << 0),
175 STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS
= (1 << 1),
176 STUN_AGENT_USAGE_USE_FINGERPRINT
= (1 << 2),
177 STUN_AGENT_USAGE_ADD_SOFTWARE
= (1 << 3),
178 STUN_AGENT_USAGE_IGNORE_CREDENTIALS
= (1 << 4),
179 STUN_AGENT_USAGE_NO_INDICATION_AUTH
= (1 << 5),
180 STUN_AGENT_USAGE_FORCE_VALIDATER
= (1 << 6),
181 STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES
= (1 << 7),
182 } StunAgentUsageFlags
;
186 StunTransactionId id
;
190 uint8_t long_term_key
[16];
191 bool long_term_valid
;
195 struct stun_agent_t
{
196 StunCompatibility compatibility
;
197 StunAgentSavedIds sent_ids
[STUN_AGENT_MAX_SAVED_IDS
];
198 uint16_t *known_attributes
;
199 StunAgentUsageFlags usage_flags
;
200 const char *software_attribute
;
204 * StunDefaultValidaterData:
205 * @username: The username
206 * @username_len: The length of the @username
207 * @password: The password
208 * @password_len: The length of the @password
210 * This structure is used as an element of the user_data to the
211 * stun_agent_default_validater() function for authenticating a STUN
212 * message during validationg.
213 * <para> See also: stun_agent_default_validater() </para>
220 } StunDefaultValidaterData
;
224 * StunMessageIntegrityValidate:
225 * @agent: The #StunAgent
226 * @message: The #StunMessage being validated
227 * @username: The username found in the @message
228 * @username_len: The length of @username
229 * @password: The password associated with that username. This argument is a
230 * pointer to a byte array that must be set by the validater function.
231 * @password_len: The length of @password which must also be set by the
232 * validater function.
233 * @user_data: Data to give the function
235 * This is the prototype for the @validater argument of the stun_agent_validate()
237 * <para> See also: stun_agent_validate() </para>
238 * Returns: %TRUE if the authentication was successful,
239 * %FALSE if the authentication failed
241 typedef bool (*StunMessageIntegrityValidate
) (StunAgent
*agent
,
242 StunMessage
*message
, uint8_t *username
, uint16_t username_len
,
243 uint8_t **password
, size_t *password_len
, void *user_data
);
246 * stun_agent_default_validater:
247 * @agent: The #StunAgent
248 * @message: The #StunMessage being validated
249 * @username: The username found in the @message
250 * @username_len: The length of @username
251 * @password: The password associated with that username. This argument is a
252 * pointer to a byte array that must be set by the validater function.
253 * @password_len: The length of @password which must also be set by the
254 * validater function.
255 * @user_data: This must be an array of #StunDefaultValidaterData structures.
256 * The last element in the array must have a username set to NULL
258 * This is a helper function to be used with stun_agent_validate(). If no
259 * complicated processing of the username needs to be done, this function can
260 * be used with stun_agent_validate() to quickly and easily match the username
261 * of a STUN message with its password. Its @user_data argument must be an array
262 * of #StunDefaultValidaterData which will allow us to map a username to a
264 * <para> See also: stun_agent_validate() </para>
265 * Returns: %TRUE if the authentication was successful,
266 * %FALSE if the authentication failed
268 bool stun_agent_default_validater (StunAgent
*agent
,
269 StunMessage
*message
, uint8_t *username
, uint16_t username_len
,
270 uint8_t **password
, size_t *password_len
, void *user_data
);
274 * @agent: The #StunAgent to initialize
275 * @known_attributes: An array of #uint16_t specifying which attributes should
276 * be known by the agent. Any STUN message received that contains a mandatory
277 * attribute that is not in this array will yield a
278 * #STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE or a
279 * #STUN_VALIDATION_UNKNOWN_ATTRIBUTE error when calling stun_agent_validate()
280 * @compatibility: The #StunCompatibility to use for this agent. This will affect
281 * how the agent builds and validates the STUN messages
282 * @usage_flags: A bitflag using #StunAgentUsageFlags values to define which
283 * STUN usages the agent should use.
285 * This function must be called to initialize an agent before it is being used.
289 The @known_attributes data must exist in memory as long as the @agent is used
292 If the #STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS and
293 #STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS usage flags are not set, then the
294 agent will default in using the short term credentials mechanism
297 The #STUN_AGENT_USAGE_USE_FINGERPRINT and #STUN_AGENT_USAGE_ADD_SOFTWARE
298 usage flags are only valid if the #STUN_COMPATIBILITY_RFC5389 or
299 #STUN_COMPATIBILITY_WLM2009 @compatibility is used
303 void stun_agent_init (StunAgent
*agent
, const uint16_t *known_attributes
,
304 StunCompatibility compatibility
, StunAgentUsageFlags usage_flags
);
307 * stun_agent_validate:
308 * @agent: The #StunAgent
309 * @msg: The #StunMessage to build
310 * @buffer: The data buffer of the STUN message
311 * @buffer_len: The length of @buffer
312 * @validater: A #StunMessageIntegrityValidate function callback that will
313 * be called if the agent needs to validate a MESSAGE-INTEGRITY attribute. It
314 * will only be called if the agent finds a message that needs authentication
315 * and a USERNAME is present in the STUN message, but no password is known.
316 * The validater will not be called if the #STUN_AGENT_USAGE_IGNORE_CREDENTIALS
317 * usage flag is set on the agent, and it will always be called if the
318 * #STUN_AGENT_USAGE_FORCE_VALIDATER usage flag is set on the agent.
319 * @validater_data: A user data to give to the @validater callback when it gets
322 * This function is used to validate an inbound STUN message and transform its
323 * data buffer into a #StunMessage. It will take care of various validation
324 * algorithms to make sure that the STUN message is valid and correctly
326 * <para> See also: stun_agent_default_validater() </para>
327 * Returns: A #StunValidationStatus
330 if the return value is different from #STUN_VALIDATION_NOT_STUN or
331 #STUN_VALIDATION_INCOMPLETE_STUN, then the @msg argument will contain a valid
332 STUN message that can be used.
333 This means that you can use the @msg variable as the @request argument to
334 functions like stun_agent_init_error() or
335 stun_agent_build_unknown_attributes_error().
336 If the return value is #STUN_VALIDATION_BAD_REQUEST,
337 #STUN_VALIDATION_UNAUTHORIZED or #STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST
338 then the @key in the #StunMessage will not be set, so that error responses
339 will not have a MESSAGE-INTEGRITY attribute.
343 StunValidationStatus
stun_agent_validate (StunAgent
*agent
, StunMessage
*msg
,
344 const uint8_t *buffer
, size_t buffer_len
,
345 StunMessageIntegrityValidate validater
, void * validater_data
);
348 * stun_agent_init_request:
349 * @agent: The #StunAgent
350 * @msg: The #StunMessage to build
351 * @buffer: The buffer to use in the #StunMessage
352 * @buffer_len: The length of the buffer
353 * @m: The #StunMethod of the request
355 * Creates a new STUN message of class #STUN_REQUEST and with the method @m
356 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
358 bool stun_agent_init_request (StunAgent
*agent
, StunMessage
*msg
,
359 uint8_t *buffer
, size_t buffer_len
, StunMethod m
);
362 * stun_agent_init_indication:
363 * @agent: The #StunAgent
364 * @msg: The #StunMessage to build
365 * @buffer: The buffer to use in the #StunMessage
366 * @buffer_len: The length of the buffer
367 * @m: The #StunMethod of the indication
369 * Creates a new STUN message of class #STUN_INDICATION and with the method @m
370 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
372 bool stun_agent_init_indication (StunAgent
*agent
, StunMessage
*msg
,
373 uint8_t *buffer
, size_t buffer_len
, StunMethod m
);
376 * stun_agent_init_response:
377 * @agent: The #StunAgent
378 * @msg: The #StunMessage to build
379 * @buffer: The buffer to use in the #StunMessage
380 * @buffer_len: The length of the buffer
381 * @request: The #StunMessage of class #STUN_REQUEST that this response is for
383 * Creates a new STUN message of class #STUN_RESPONSE and with the same method
384 * and transaction ID as the message @request. This will also copy the pointer
385 * to the key that was used to authenticate the request, so you won't need to
386 * specify the key with stun_agent_finish_message()
387 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
389 bool stun_agent_init_response (StunAgent
*agent
, StunMessage
*msg
,
390 uint8_t *buffer
, size_t buffer_len
, const StunMessage
*request
);
393 * stun_agent_init_error:
394 * @agent: The #StunAgent
395 * @msg: The #StunMessage to build
396 * @buffer: The buffer to use in the #StunMessage
397 * @buffer_len: The length of the buffer
398 * @request: The #StunMessage of class #STUN_REQUEST that this error response
400 * @err: The #StunError to put in the ERROR-CODE attribute of the error response
402 * Creates a new STUN message of class #STUN_ERROR and with the same method
403 * and transaction ID as the message @request. This will also copy the pointer
404 * to the key that was used to authenticate the request (if authenticated),
405 * so you won't need to specify the key with stun_agent_finish_message().
406 * It will then add the ERROR-CODE attribute with code @err and the associated
408 * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
410 bool stun_agent_init_error (StunAgent
*agent
, StunMessage
*msg
,
411 uint8_t *buffer
, size_t buffer_len
, const StunMessage
*request
,
415 * stun_agent_build_unknown_attributes_error:
416 * @agent: The #StunAgent
417 * @msg: The #StunMessage to build
418 * @buffer: The buffer to use in the #StunMessage
419 * @buffer_len: The length of the buffer
420 * @request: The #StunMessage of class #STUN_REQUEST that this response is for
422 * Creates a new STUN message of class #STUN_ERROR and with the same method
423 * and transaction ID as the message @request. It will then add the ERROR-CODE
424 * attribute with code #STUN_ERROR_UNKNOWN_ATTRIBUTE and add all the unknown
425 * mandatory attributes from the @request STUN message in the
426 * #STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES attribute, it will then finish the message
427 * by calling stun_agent_finish_message()
428 * Returns: The size of the message built
430 size_t stun_agent_build_unknown_attributes_error (StunAgent
*agent
,
431 StunMessage
*msg
, uint8_t *buffer
, size_t buffer_len
,
432 const StunMessage
*request
);
436 * stun_agent_finish_message:
437 * @agent: The #StunAgent
438 * @msg: The #StunMessage to finish
439 * @key: The key to use for the MESSAGE-INTEGRITY attribute
440 * @key_len: The length of the @key
442 * This function will 'finish' a message and make it ready to be sent. It will
443 * add the MESSAGE-INTEGRITY and FINGERPRINT attributes if necessary. If the
444 * STUN message has a #STUN_REQUEST class, it will save the transaction id of
445 * the message in the agent for future matching of the response.
446 * <para>See also: stun_agent_forget_transaction()</para>
447 * Returns: The final size of the message built or 0 if an error occured
450 The return value must always be checked. a value of 0 means the either
451 the buffer's size is too small to contain the finishing attributes
452 (MESSAGE-INTEGRITY, FINGERPRINT), or that there is no more free slots
453 for saving the sent id in the agent's state.
456 Everytime stun_agent_finish_message() is called for a #STUN_REQUEST
457 message, you must make sure to call stun_agent_forget_transaction() in
458 case the response times out and is never received. This is to avoid
459 filling up the #StunAgent's sent ids state preventing any further
460 use of the stun_agent_finish_message()
464 size_t stun_agent_finish_message (StunAgent
*agent
, StunMessage
*msg
,
465 const uint8_t *key
, size_t key_len
);
468 * stun_agent_forget_transaction:
469 * @agent: The #StunAgent
470 * @id: The #StunTransactionId of the transaction to forget
472 * This function is used to make the #StunAgent forget about a previously
473 * created transaction.
475 * This function should be called when a STUN request was previously
476 * created with stun_agent_finish_message() and for which no response was ever
477 * received (timed out). The #StunAgent keeps a list of the sent transactions
478 * in order to validate the responses received. If the response is never received
479 * this will allow the #StunAgent to forget about the timed out transaction and
480 * free its slot for future transactions.
483 * Returns: %TRUE if the transaction was found, %FALSE otherwise
485 bool stun_agent_forget_transaction (StunAgent
*agent
, StunTransactionId id
);
489 * stun_agent_set_software:
490 * @agent: The #StunAgent
491 * @software: The value of the SOFTWARE attribute to add.
493 * This function will set the value of the SOFTWARE attribute to be added to
494 * STUN requests, responses and error responses.
496 * Calling this function will automatically enable the addition of the SOFTWARE
497 * attribute for RFC5389 and WLM2009 compatibility modes.
502 The @software argument must be in UTF-8 encoding and only the first
503 128 characters will be sent.
506 The value of the @software argument must stay valid throughout the life of
507 the StunAgent's life. Do not free its content.
514 void stun_agent_set_software (StunAgent
*agent
, const char *software
);
516 #endif /* _STUN_AGENT_H */