summaryrefslogtreecommitdiff
path: root/pjlib-util/include
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-02-26 02:33:14 +0000
committerBenny Prijono <bennylp@teluu.com>2007-02-26 02:33:14 +0000
commitbf839cd77520ad28437e55a73fd8167838023f42 (patch)
tree140617414ee6d99323f69d2d478d767ddf4b7ecd /pjlib-util/include
parenta34fbb64e27b5075a4207318ba356349669b4f08 (diff)
Added CRC32 code to pjlib-util, and implemented STUN FINGERPRINT and MESSAGE-INTEGRITY
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1002 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjlib-util/include')
-rw-r--r--pjlib-util/include/pjlib-util.h1
-rw-r--r--pjlib-util/include/pjlib-util/crc32.h95
-rw-r--r--pjlib-util/include/pjlib-util/errno.h32
-rw-r--r--pjlib-util/include/pjlib-util/stun_msg.h277
4 files changed, 349 insertions, 56 deletions
diff --git a/pjlib-util/include/pjlib-util.h b/pjlib-util/include/pjlib-util.h
index 0cf5a90d..2b3326b4 100644
--- a/pjlib-util/include/pjlib-util.h
+++ b/pjlib-util/include/pjlib-util.h
@@ -32,6 +32,7 @@
#include <pjlib-util/getopt.h>
/* Crypto */
+#include <pjlib-util/crc32.h>
#include <pjlib-util/hmac_md5.h>
#include <pjlib-util/hmac_sha1.h>
#include <pjlib-util/md5.h>
diff --git a/pjlib-util/include/pjlib-util/crc32.h b/pjlib-util/include/pjlib-util/crc32.h
new file mode 100644
index 00000000..a85a51a6
--- /dev/null
+++ b/pjlib-util/include/pjlib-util/crc32.h
@@ -0,0 +1,95 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJLIB_UTIL_CRC32_H__
+#define __PJLIB_UTIL_CRC32_H__
+
+/**
+ * @file crc32.h
+ * @brief CRC32 implementation
+ */
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJLIB_UTIL_CRC32 CRC32 (Cyclic Redundancy Check)
+ * @ingroup PJLIB_UTIL_ENCRYPTION
+ * @{
+ * This implements CRC32 algorithm. See ITU-T V.42 for the formal
+ * specification.
+ */
+
+/** CRC32 context. */
+typedef struct pj_crc32_context
+{
+ pj_uint32_t crc_state; /**< Current state. */
+} pj_crc32_context;
+
+
+/**
+ * Initialize CRC32 context.
+ *
+ * @param ctx CRC32 context.
+ */
+PJ_DECL(void) pj_crc32_init(pj_crc32_context *ctx);
+
+/**
+ * Feed data incrementally to the CRC32 algorithm.
+ *
+ * @param ctx CRC32 context.
+ * @param data Input data.
+ * @param nbytes Length of the input data.
+ *
+ * @return The current CRC32 value.
+ */
+PJ_DECL(pj_uint32_t) pj_crc32_update(pj_crc32_context *ctx,
+ const pj_uint8_t *data,
+ pj_size_t nbytes);
+
+/**
+ * Finalize CRC32 calculation and retrieve the CRC32 value.
+ *
+ * @param ctx CRC32 context.
+ *
+ * @return The current CRC value.
+ */
+PJ_DECL(pj_uint32_t) pj_crc32_final(pj_crc32_context *ctx);
+
+/**
+ * Perform one-off CRC32 calculation to the specified data.
+ *
+ * @param data Input data.
+ * @param nbytes Length of input data.
+ *
+ * @return CRC value of the data.
+ */
+PJ_DECL(pj_uint32_t) pj_crc32_calc(const pj_uint8_t *data,
+ pj_size_t nbytes);
+
+
+/**
+ * @}
+ */
+
+PJ_END_DECL
+
+
+#endif /* __PJLIB_UTIL_CRC32_H__ */
+
diff --git a/pjlib-util/include/pjlib-util/errno.h b/pjlib-util/include/pjlib-util/errno.h
index 6d8c0b1f..3f004ca3 100644
--- a/pjlib-util/include/pjlib-util/errno.h
+++ b/pjlib-util/include/pjlib-util/errno.h
@@ -93,6 +93,16 @@
* Symetric NAT detected by STUN
*/
#define PJLIB_UTIL_ESTUNSYMMETRIC (PJLIB_UTIL_ERRNO_START+11) /* 320011 */
+/**
+ * @hideinitializer
+ * Invalid STUN magic value
+ */
+#define PJLIB_UTIL_ESTUNNOTMAGIC (PJLIB_UTIL_ERRNO_START+12) /* 320012 */
+/**
+ * @hideinitializer
+ * Invalid STUN fingerprint value
+ */
+#define PJLIB_UTIL_ESTUNFINGERPRINT (PJLIB_UTIL_ERRNO_START+13) /* 320013 */
@@ -266,12 +276,12 @@
#define PJLIB_UTIL_ESTUNUNKNOWNATTR (PJLIB_UTIL_ERRNO_START+112)/* 320112 */
/**
* @hideinitializer
- * Invalid socket address length.
+ * Invalid STUN socket address length.
*/
#define PJLIB_UTIL_ESTUNINADDRLEN (PJLIB_UTIL_ERRNO_START+113)/* 320113 */
/**
* @hideinitializer
- * IPv6 attribute not supported
+ * STUN IPv6 attribute not supported
*/
#define PJLIB_UTIL_ESTUNIPV6NOTSUPP (PJLIB_UTIL_ERRNO_START+113)/* 320113 */
/**
@@ -281,7 +291,7 @@
#define PJLIB_UTIL_ESTUNNOTRESPONSE (PJLIB_UTIL_ERRNO_START+114)/* 320114 */
/**
* @hideinitializer
- * Transaction ID mismatch.
+ * STUN transaction ID mismatch.
*/
#define PJLIB_UTIL_ESTUNINVALIDID (PJLIB_UTIL_ERRNO_START+115)/* 320115 */
/**
@@ -289,9 +299,23 @@
* Unable to find handler for the request.
*/
#define PJLIB_UTIL_ESTUNNOHANDLER (PJLIB_UTIL_ERRNO_START+116)/* 320116 */
+/**
+ * @hideinitializer
+ * Invalid STUN MESSAGE-INTEGRITY attribute position in message.
+ * STUN MESSAGE-INTEGRITY must be put last in the message, or before
+ * FINGERPRINT attribute.
+ */
+#define PJLIB_UTIL_ESTUNMSGINT (PJLIB_UTIL_ERRNO_START+117)/* 320117 */
+/**
+ * @hideinitializer
+ * Missing STUN USERNAME attribute.
+ * When credential is included in the STUN message (MESSAGE-INTEGRITY is
+ * present), the USERNAME attribute must be present in the message.
+ */
+#define PJLIB_UTIL_ESTUNNOUSERNAME (PJLIB_UTIL_ERRNO_START+118)/* 320118 */
-#define PJ_STATUS_FROM_STUN_CODE(code) -1
+#define PJ_STATUS_FROM_STUN_CODE(code) (PJLIB_UTIL_ERRNO_START+code)
diff --git a/pjlib-util/include/pjlib-util/stun_msg.h b/pjlib-util/include/pjlib-util/stun_msg.h
index b15b11f9..652472b5 100644
--- a/pjlib-util/include/pjlib-util/stun_msg.h
+++ b/pjlib-util/include/pjlib-util/stun_msg.h
@@ -601,7 +601,7 @@ typedef struct pj_stun_binary_attr
/**
* The raw data.
*/
- char *data;
+ pj_uint8_t *data;
} pj_stun_binary_attr;
@@ -1046,6 +1046,23 @@ typedef struct pj_stun_msg
} pj_stun_msg;
+/** STUN decoding options */
+enum pj_stun_options
+{
+ /**
+ * Tell the decoder that the message was received from datagram
+ * oriented transport (such as UDP).
+ */
+ PJ_STUN_IS_DATAGRAM = 1,
+
+ /**
+ * Tell pj_stun_msg_decode() to check the validity of the STUN
+ * message by calling pj_stun_msg_check() before starting to
+ * decode the packet.
+ */
+ PJ_STUN_CHECK_PACKET = 2
+};
+
/**
* Get STUN message method name.
*
@@ -1087,7 +1104,7 @@ PJ_DECL(pj_str_t) pj_stun_get_err_reason(int err_code);
/**
- * Create a blank STUN message.
+ * Create a generic STUN message.
*
* @param pool Pool to create the STUN message.
* @param msg_type The 14bit message type.
@@ -1105,6 +1122,28 @@ PJ_DECL(pj_status_t) pj_stun_msg_create(pj_pool_t *pool,
const pj_uint8_t tsx_id[12],
pj_stun_msg **p_msg);
+/**
+ * Create STUN response message.
+ *
+ * @param pool Pool to create the mesage.
+ * @param req_msg The request message.
+ * @param err_code STUN error code. If this value is not zero,
+ * then error response will be created, otherwise
+ * successful response will be created.
+ * @param err_msg Optional error message to explain err_code.
+ * If this value is NULL and err_code is not zero,
+ * the error string will be taken from the default
+ * STUN error message.
+ * @param p_response Pointer to receive the response.
+ *
+ * @return PJ_SUCCESS on success, or the appropriate error.
+ */
+PJ_DECL(pj_status_t) pj_stun_msg_create_response(pj_pool_t *pool,
+ const pj_stun_msg *req_msg,
+ unsigned err_code,
+ const pj_str_t *err_msg,
+ pj_stun_msg **p_response);
+
/**
* Add STUN attribute to STUN message.
@@ -1120,6 +1159,41 @@ PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg,
/**
+ * Print the STUN message structure to a packet buffer, ready to be
+ * sent to remote destination. This function will take care about
+ * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT
+ * value.
+ *
+ * If MESSAGE-INTEGRITY attribute is present, the function assumes
+ * that application wants to include credential (short or long term)
+ * in the message, and this function will calculate the HMAC digest
+ * from the message using the supplied password in the parameter.
+ * If REALM attribute is present, the HMAC digest is calculated as
+ * long term credential, otherwise as short term credential.
+ *
+ * If FINGERPRINT attribute is present, this function will calculate
+ * the FINGERPRINT CRC attribute for the message.
+ *
+ * @param msg The STUN message to be printed.
+ * @param pkt_buf The buffer to be filled with the packet.
+ * @param buf_size Size of the buffer.
+ * @param options Options, which currently must be zero.
+ * @param password Password to be used when credential is to be
+ * included. This parameter MUST be specified when
+ * the message contains MESSAGE-INTEGRITY attribute.
+ * @param p_msg_len Upon return, it will be filed with the size of
+ * the packet in bytes, or negative value on error.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_stun_msg_encode(const pj_stun_msg *msg,
+ pj_uint8_t *pkt_buf,
+ unsigned buf_size,
+ unsigned options,
+ const pj_str_t *password,
+ unsigned *p_msg_len);
+
+/**
* Check that the PDU is potentially a valid STUN message. This function
* is useful when application needs to multiplex STUN packets with other
* application traffic. When this function returns PJ_SUCCESS, there is a
@@ -1130,35 +1204,38 @@ PJ_DECL(pj_status_t) pj_stun_msg_add_attr(pj_stun_msg *msg,
*
* @param pdu The packet buffer.
* @param pdu_len The length of the packet buffer.
- * @param options Options.
+ * @param options Additional options to be applied in the checking,
+ * which can be taken from pj_stun_options. One of the
+ * useful option is PJ_STUN_IS_DATAGRAM which means that
+ * the pdu represents a whole STUN packet.
*
* @return PJ_SUCCESS if the PDU is a potentially valid STUN
* message.
*/
-PJ_DECL(pj_status_t) pj_stun_msg_check(const void *pdu, unsigned pdu_len,
+PJ_DECL(pj_status_t) pj_stun_msg_check(const pj_uint8_t *pdu, unsigned pdu_len,
unsigned options);
/**
- * Parse incoming packet into STUN message.
+ * Decode incoming packet into STUN message.
*
* @param pool Pool to allocate the message.
* @param pdu The incoming packet to be parsed.
* @param pdu_len The length of the incoming packet.
- * @param options Parsing flags.
+ * @param options Parsing flags, according to pj_stun_options.
* @param p_msg Pointer to receive the parsed message.
* @param p_parsed_len Optional pointer to receive how many bytes have
* been parsed for the STUN message. This is useful
* when the packet is received over stream oriented
* transport.
- * @param p_err_code Optional pointer to receive STUN error code when
- * parsing failed.
- * @param uattr_cnt Optional pointer to specify the number of elements
- * in uattr array. On return, this will be filled with
- * the actual number of attributes set in the uattr.
- * @param uattr Optional array to receive unknown attribute types.
+ * @param p_response Optional pointer to receive an instance of response
+ * message, if one can be created. If the packet being
+ * decoded is a request message, and it contains error,
+ * and a response can be created, then the STUN
+ * response message will be returned on this argument.
*
- * @return PJ_SUCCESS on success or the appropriate error code.
+ * @return PJ_SUCCESS if a STUN message has been successfully
+ * decoded.
*/
PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
const pj_uint8_t *pdu,
@@ -1166,44 +1243,43 @@ PJ_DECL(pj_status_t) pj_stun_msg_decode(pj_pool_t *pool,
unsigned options,
pj_stun_msg **p_msg,
unsigned *p_parsed_len,
- unsigned *p_err_code,
- unsigned *uattr_cnt,
- pj_uint16_t uattr[]);
+ pj_stun_msg **p_response);
/**
- * Print the STUN message structure to a packet buffer, ready to be
- * sent to remote destination. This function will take care about
- * calculating the MESSAGE-INTEGRITY digest as well as FINGERPRINT
- * value.
- *
- * If MESSAGE-INTEGRITY attribute is present, the function assumes
- * that application wants to include credential (short or long term)
- * in the message, and this function will calculate the HMAC digest
- * from the message using the supplied password in the parameter.
- * If REALM attribute is present, the HMAC digest is calculated as
- * long term credential, otherwise as short term credential.
+ * Verify credential in the STUN message. Note that before calling this
+ * function, application must have checked that the message contains
+ * PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute by calling pj_stun_msg_find_attr()
+ * function, because this function will reject the message with 401 error
+ * if it doesn't contain PJ_STUN_ATTR_MESSAGE_INTEGRITY attribute.
*
- * If FINGERPRINT attribute is present, this function will calculate
- * the FINGERPRINT CRC attribute for the message.
- *
- * @param msg The STUN message to be printed.
- * @param pkt_buf The buffer to be filled with the packet.
- * @param buf_size Size of the buffer.
- * @param options Options, which currently must be zero.
- * @param password Password to be used when credential is to be
- * included. This parameter MUST be specified when
- * the message contains MESSAGE-INTEGRITY attribute.
- * @param p_msg_len Upon return, it will be filed with the size of
- * the packet in bytes, or negative value on error.
+ * @param msg The message to be verified.
+ * @param realm Realm, if long term credential is required. If
+ * short term credential is required, this argument
+ * must be set to NULL.
+ * @param username If this attribute is specified, then the USERNAME
+ * attribute in the message will be compared against
+ * this value. If NULL is specified, then this function
+ * will accept any usernames.
+ * @param password The password.
+ * @param options Options, must be zero for now.
+ * @param pool If response is to be created, then memory will
+ * be allocated from this pool.
+ * @param p_response Optional pointer to receive the response message
+ * then the credential in the request fails to
+ * authenticate.
*
- * @return PJ_SUCCESS on success or the appropriate error code.
+ * @return PJ_SUCCESS if credential is verified successfully.
+ * If the verification fails and \a p_response is not
+ * NULL, an appropriate response will be returned in
+ * \a p_response.
*/
-PJ_DECL(pj_status_t) pj_stun_msg_encode(const pj_stun_msg *msg,
- pj_uint8_t *pkt_buf,
- unsigned buf_size,
- unsigned options,
- const pj_str_t *password,
- unsigned *p_msg_len);
+PJ_DECL(pj_status_t) pj_stun_verify_credential(const pj_stun_msg *msg,
+ const pj_str_t *realm,
+ const pj_str_t *username,
+ const pj_str_t *password,
+ unsigned options,
+ pj_pool_t *pool,
+ pj_stun_msg **p_response);
/**
@@ -1243,8 +1319,9 @@ PJ_DECL(pj_stun_attr_hdr*) pj_stun_msg_find_attr(const pj_stun_msg *msg,
/**
- * Create a generic STUN IP address attribute for IPv4 address. Note that
- * the port and ip_addr parameters are in host byte order.
+ * Create a generic STUN IP address attribute. The \a addr_len and
+ * \a addr parameters specify whether the address is IPv4 or IPv4
+ * address.
*
* @param pool The pool to allocate memory from.
* @param attr_type Attribute type, from #pj_stun_attr_type.
@@ -1266,6 +1343,29 @@ pj_stun_generic_ip_addr_attr_create(pj_pool_t *pool,
/**
+ * Create and add generic STUN IP address attribute to a STUN message.
+ * The \a addr_len and \a addr parameters specify whether the address is
+ * IPv4 or IPv4 address.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param msg The STUN message.
+ * @param attr_type Attribute type, from #pj_stun_attr_type.
+ * @param xor_ed If non-zero, the port and address will be XOR-ed
+ * with magic, to make the XOR-MAPPED-ADDRESS attribute.
+ * @param addr_len Length of \a addr parameter.
+ * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pj_stun_msg_add_generic_ip_addr_attr(pj_pool_t *pool,
+ pj_stun_msg *msg,
+ int attr_type,
+ pj_bool_t xor_ed,
+ unsigned addr_len,
+ const pj_sockaddr_t *addr);
+
+/**
* Create a STUN generic string attribute.
*
* @param pool The pool to allocate memory from.
@@ -1281,6 +1381,21 @@ pj_stun_generic_string_attr_create(pj_pool_t *pool,
const pj_str_t *value,
pj_stun_generic_string_attr **p_attr);
+/**
+ * Create and add STUN generic string attribute to the message.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param msg The STUN message.
+ * @param attr_type Attribute type, from #pj_stun_attr_type.
+ * @param value The string value to be assigned to the attribute.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pj_stun_msg_add_generic_string_attr(pj_pool_t *pool,
+ pj_stun_msg *msg,
+ int attr_type,
+ const pj_str_t *value);
/**
* Create a STUN generic 32bit value attribute.
@@ -1298,6 +1413,22 @@ pj_stun_generic_uint_attr_create(pj_pool_t *pool,
pj_uint32_t value,
pj_stun_generic_uint_attr **p_attr);
+/**
+ * Create and add STUN generic 32bit value attribute to the message.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param msg The STUN message
+ * @param attr_type Attribute type, from #pj_stun_attr_type.
+ * @param value The 32bit value to be assigned to the attribute.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pj_stun_msg_add_generic_uint_attr(pj_pool_t *pool,
+ pj_stun_msg *msg,
+ int attr_type,
+ pj_uint32_t value);
+
/**
* Create a STUN MESSAGE-INTEGRITY attribute.
@@ -1311,7 +1442,6 @@ PJ_DECL(pj_status_t)
pj_stun_msg_integrity_attr_create(pj_pool_t *pool,
pj_stun_msg_integrity_attr **p_attr);
-
/**
* Create a STUN ERROR-CODE attribute.
*
@@ -1331,7 +1461,8 @@ pj_stun_error_code_attr_create(pj_pool_t *pool,
/**
- * Create an empty instance of STUN UNKNOWN-ATTRIBUTES attribute.
+ * Create instance of STUN UNKNOWN-ATTRIBUTES attribute and copy the
+ * unknown attribute array to the attribute.
*
* @param pool The pool to allocate memory from.
* @param attr_cnt Number of attributes in the array (can be zero).
@@ -1343,15 +1474,34 @@ pj_stun_error_code_attr_create(pj_pool_t *pool,
PJ_DECL(pj_status_t)
pj_stun_unknown_attr_create(pj_pool_t *pool,
unsigned attr_cnt,
- pj_uint16_t attr[],
+ const pj_uint16_t attr[],
pj_stun_unknown_attr **p_attr);
+/**
+ * Create and add STUN UNKNOWN-ATTRIBUTES attribute to the message.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param msg The STUN message.
+ * @param attr_cnt Number of attributes in the array (can be zero).
+ * @param attr Optional array of attributes.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pj_stun_msg_add_unknown_attr(pj_pool_t *pool,
+ pj_stun_msg *msg,
+ unsigned attr_cnt,
+ const pj_uint16_t attr[]);
/**
- * Create a blank binary attribute.
+ * Create STUN binary attribute.
*
* @param pool The pool to allocate memory from.
* @param attr_type The attribute type, from #pj_stun_attr_type.
+ * @param data Data to be coped to the attribute, or NULL
+ * if no data to be copied now.
+ * @param length Length of data, or zero if no data is to be
+ * copied now.
* @param p_attr Pointer to receive the attribute.
*
* @return PJ_SUCCESS on success or the appropriate error code.
@@ -1359,8 +1509,31 @@ pj_stun_unknown_attr_create(pj_pool_t *pool,
PJ_DECL(pj_status_t)
pj_stun_binary_attr_create(pj_pool_t *pool,
int attr_type,
+ const pj_uint8_t *data,
+ unsigned length,
pj_stun_binary_attr **p_attr);
+/**
+ * Create STUN binary attribute and add the attribute to the message.
+ *
+ * @param pool The pool to allocate memory from.
+ * @param msg The STUN message.
+ * @param attr_type The attribute type, from #pj_stun_attr_type.
+ * @param data Data to be coped to the attribute, or NULL
+ * if no data to be copied now.
+ * @param length Length of data, or zero if no data is to be
+ * copied now.
+ * @param p_attr Pointer to receive the attribute.
+ *
+ * @return PJ_SUCCESS on success or the appropriate error code.
+ */
+PJ_DECL(pj_status_t)
+pj_stun_msg_add_binary_attr(pj_pool_t *pool,
+ pj_stun_msg *msg,
+ int attr_type,
+ const pj_uint8_t *data,
+ unsigned length);
+
/**
* @}