2 Commits

Author SHA1 Message Date
Steffen Jaeckel
541c22cb13 Allow configuring compression level
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2024-11-18 10:13:43 +01:00
Steffen Jaeckel
06f2ba19b4 Introduce generic xmpp_conn_set_*() API
Instead of having a multitude of setter API functions for configuration
options, provide generic ones for the different types we have.

Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2024-11-18 10:13:43 +01:00
14 changed files with 513 additions and 231 deletions

View File

@@ -115,8 +115,8 @@ int main(int argc, char **argv)
*/ */
/* setup authentication information */ /* setup authentication information */
xmpp_conn_set_jid(conn, argv[1]); xmpp_conn_set_string(conn, XMPP_SETTING_JID, argv[1]);
xmpp_conn_set_pass(conn, argv[2]); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, argv[2]);
/* initiate connection */ /* initiate connection */
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx); xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);

View File

@@ -116,9 +116,9 @@ int main(int argc, char **argv)
/* setup authentication information */ /* setup authentication information */
if (jid) if (jid)
xmpp_conn_set_jid(conn, jid); xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
if (password) if (password)
xmpp_conn_set_pass(conn, password); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, password);
/* initiate connection */ /* initiate connection */
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) { if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {

View File

@@ -293,20 +293,24 @@ create_connection:
xmpp_conn_set_flags(conn, flags); xmpp_conn_set_flags(conn, flags);
/* ask for a password if key is protected */ /* ask for a password if key is protected */
xmpp_conn_set_password_callback(conn, password_callback, NULL); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK,
password_callback);
/* try at max 3 times in case the user enters the password wrong */ /* try at max 3 times in case the user enters the password wrong */
xmpp_conn_set_password_retries(conn, 3); xmpp_conn_set_int(conn, XMPP_SETTING_PASSWORD_RETRIES, 3);
/* setup authentication information */ /* setup authentication information */
if (key) if (key) {
xmpp_conn_set_client_cert(conn, cert, key); xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, cert);
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, key);
}
if (jid) if (jid)
xmpp_conn_set_jid(conn, jid); xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
if (password) if (password)
xmpp_conn_set_pass(conn, password); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, password);
/* enable TCP keepalive, using canned callback function */ /* enable TCP keepalive, using canned callback function */
if (tcp_keepalive) if (tcp_keepalive)
xmpp_conn_set_sockopt_callback(conn, xmpp_sockopt_cb_keepalive); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
xmpp_sockopt_cb_keepalive);
/* set Stream-Mangement state if available */ /* set Stream-Mangement state if available */
if (sm_state) { if (sm_state) {

View File

@@ -331,27 +331,31 @@ int main(int argc, char **argv)
xmpp_conn_set_flags(conn, flags); xmpp_conn_set_flags(conn, flags);
/* configure TCP keepalive (optional) */ /* configure TCP keepalive (optional) */
if (tcp_keepalive) if (tcp_keepalive)
xmpp_conn_set_sockopt_callback(conn, sockopt_cb); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
sockopt_cb);
/* ask for a password if key is protected */ /* ask for a password if key is protected */
xmpp_conn_set_password_callback(conn, password_callback, NULL); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK,
password_callback);
/* try at max 3 times in case the user enters the password wrong */ /* try at max 3 times in case the user enters the password wrong */
xmpp_conn_set_password_retries(conn, 3); xmpp_conn_set_int(conn, XMPP_SETTING_PASSWORD_RETRIES, 3);
/* setup authentication information */ /* setup authentication information */
if (key) { if (key) {
xmpp_conn_set_client_cert(conn, cert, key); xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, cert);
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, key);
} }
if (jid) if (jid)
xmpp_conn_set_jid(conn, jid); xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
if (password) if (password)
xmpp_conn_set_pass(conn, password); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, password);
if (certfail) if (certfail)
xmpp_conn_set_certfail_handler(conn, certfail_handler); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_CERTFAIL_HANDLER,
certfail_handler);
if (capath) if (capath)
xmpp_conn_set_capath(conn, capath); xmpp_conn_set_string(conn, XMPP_SETTING_CAPATH, capath);
if (cafile) if (cafile)
xmpp_conn_set_cafile(conn, cafile); xmpp_conn_set_string(conn, XMPP_SETTING_CAFILE, cafile);
/* initiate connection */ /* initiate connection */
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) { if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {

View File

@@ -80,8 +80,8 @@ int main(int argc, char **argv)
conn = xmpp_conn_new(ctx); conn = xmpp_conn_new(ctx);
/* setup authentication information */ /* setup authentication information */
xmpp_conn_set_jid(conn, jid); xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
xmpp_conn_set_pass(conn, pass); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, pass);
/* initiate connection */ /* initiate connection */
xmpp_connect_component(conn, host, port, conn_handler, ctx); xmpp_connect_component(conn, host, port, conn_handler, ctx);

View File

@@ -342,7 +342,7 @@ int main(int argc, char **argv)
/* jid can be a jid or domain for "raw" connection */ /* jid can be a jid or domain for "raw" connection */
domain = xmpp_jid_domain(ctx, jid); domain = xmpp_jid_domain(ctx, jid);
xmpp_conn_set_jid(conn, domain); xmpp_conn_set_string(conn, XMPP_SETTING_JID, domain);
xmpp_free(ctx, domain); xmpp_free(ctx, domain);
/* private data */ /* private data */

View File

@@ -118,8 +118,8 @@ int main(int argc, char **argv)
*/ */
/* setup authentication information */ /* setup authentication information */
xmpp_conn_set_jid(conn, argv[1]); xmpp_conn_set_string(conn, XMPP_SETTING_JID, argv[1]);
xmpp_conn_set_pass(conn, argv[2]); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, argv[2]);
/* initiate connection */ /* initiate connection */
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx); xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);

View File

@@ -269,8 +269,8 @@ int main(int argc, char **argv)
log = xmpp_get_default_logger(XMPP_LEVEL_INFO); log = xmpp_get_default_logger(XMPP_LEVEL_INFO);
ctx = xmpp_ctx_new(NULL, log); ctx = xmpp_ctx_new(NULL, log);
conn = xmpp_conn_new(ctx); conn = xmpp_conn_new(ctx);
xmpp_conn_set_jid(conn, jid); xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
xmpp_conn_set_pass(conn, pass); xmpp_conn_set_string(conn, XMPP_SETTING_PASS, pass);
vcard.ctx = ctx; vcard.ctx = ctx;
xmpp_connect_client(conn, NULL, 0, conn_handler, &vcard); xmpp_connect_client(conn, NULL, 0, conn_handler, &vcard);
xmpp_run(ctx); xmpp_run(ctx);

View File

@@ -280,7 +280,8 @@ struct _xmpp_conn_t {
struct { struct {
struct xmpp_compression *state; struct xmpp_compression *state;
int allowed, supported, dont_reset; int allowed, dont_reset, level;
int supported;
} compression; } compression;
char *lang; char *lang;

View File

@@ -227,7 +227,7 @@ int compression_init(xmpp_conn_t *conn)
comp->compression.stream.next_out = comp->compression.buffer; comp->compression.stream.next_out = comp->compression.buffer;
comp->compression.stream.avail_out = STROPHE_COMPRESSION_BUFFER_SIZE; comp->compression.stream.avail_out = STROPHE_COMPRESSION_BUFFER_SIZE;
int ret = deflateInit(&comp->compression.stream, Z_DEFAULT_COMPRESSION); int ret = deflateInit(&comp->compression.stream, conn->compression.level);
if (ret != Z_OK) { if (ret != Z_OK) {
strophe_free_and_null(conn->ctx, comp->compression.buffer); strophe_free_and_null(conn->ctx, comp->compression.buffer);
conn->error = ret; conn->error = ret;

View File

@@ -167,6 +167,8 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
tls_clear_password_cache(conn); tls_clear_password_cache(conn);
conn->password_retries = 1; conn->password_retries = 1;
conn->compression.level = -1;
conn->parser = conn->parser =
parser_new(conn->ctx, _handle_stream_start, _handle_stream_end, parser_new(conn->ctx, _handle_stream_start, _handle_stream_end,
_handle_stream_stanza, conn); _handle_stream_stanza, conn);
@@ -217,32 +219,6 @@ xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn)
return conn; return conn;
} }
/** Register sockopt callback
* Set function to be called when a new socket is created to allow setting
* socket options before connection is started.
*
* If the connection is already connected, this callback will be called
* immediately.
*
* To set options that can only be applied to disconnected sockets, the
* callback must be registered before connecting.
*
* @param conn The Strophe connection object this callback is being registered
* for
* @param callback a xmpp_sockopt_callback callback function that will receive
* notifications of connection status
*
* @ingroup Connections
*/
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
xmpp_sockopt_callback callback)
{
conn->sockopt_cb = callback;
if (conn->state != XMPP_STATE_DISCONNECTED)
callback(conn, &conn->sock);
}
/** Release a Strophe connection object. /** Release a Strophe connection object.
* Decrement the reference count by one for a connection, freeing the * Decrement the reference count by one for a connection, freeing the
* connection object if the count reaches 0. * connection object if the count reaches 0.
@@ -366,6 +342,204 @@ int xmpp_conn_release(xmpp_conn_t *conn)
return released; return released;
} }
/** Configure a connection-related int setting
*
* `setting` can be one of:
* - \ref XMPP_SETTING_PASSWORD_RETRIES
* Set the number of retry attempts to decrypt a private key file. \n
* In case the user enters the password manually it can be useful to
* directly retry if the decryption of the key file failed.
*
* - \ref XMPP_SETTING_COMPRESSION_LEVEL
* Set the compression level. \n
* For zlib the valid range is `-1` to `9`.
*
* @param conn a Strophe connection object
* @param setting The setting that shall be configured
* @param value The value, the settings should get
*
* @ingroup Connections
*/
void xmpp_conn_set_int(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
int value)
{
switch (setting) {
case XMPP_SETTING_PASSWORD_RETRIES:
if (value <= 0)
conn->password_retries = 1;
else
conn->password_retries = value;
break;
case XMPP_SETTING_COMPRESSION_LEVEL:
conn->compression.level = value;
break;
default:
strophe_warn(conn->ctx, "xmpp", "Invalid Int setting %d", setting);
return;
}
}
/** Configure a connection-related string setting
*
* `setting` can be one of:
* - \ref XMPP_SETTING_JID
* Set the JID of the user that will be bound to the connection. \n
* This should not be used after a connection is created. \n
* If the supplied JID is missing the node, SASL ANONYMOUS authentication
* will be used.
*
* - \ref XMPP_SETTING_PASS
* Set the password used to authenticate the connection.
*
* - \ref XMPP_SETTING_CAFILE
* Set CAfile.
*
* - \ref XMPP_SETTING_CAPATH
* Set CApath.
*
* - \ref XMPP_SETTING_CLIENT_CERT
* Set the Client Certificate or PKCS#12 encoded file that will be bound to
* the connection. \n
* This should not be used after a connection is created. \n
* In case the PKCS#12 file is encrypted, a callback must be set via
* \ref xmpp_conn_set_functionpointer with the option
* \ref XMPP_SETTING_PASSWORD_CALLBACK so the TLS stack can retrieve the
* password.
*
* - \ref XMPP_SETTING_CLIENT_KEY
* Set the Private Key that will be bound to the connection. \n
* This should not be used after a connection is created. \n
* In case the Private Key is encrypted, a callback must be set via
* \ref xmpp_conn_set_functionpointer with the option
* \ref XMPP_SETTING_PASSWORD_CALLBACK so the TLS stack can retrieve the
* password.
*
*
*
* If any value was previously set, it will be discarded.
* The function will make a copy of the value given.
*
* @param conn a Strophe connection object
* @param setting The setting that shall be configured
* @param value The value, the settings should get
*
* @ingroup Connections
*/
void xmpp_conn_set_string(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
const char *value)
{
char **target;
switch (setting) {
case XMPP_SETTING_JID:
target = &conn->jid;
break;
case XMPP_SETTING_PASS:
target = &conn->pass;
break;
case XMPP_SETTING_CAFILE:
target = &conn->tls_cafile;
break;
case XMPP_SETTING_CAPATH:
target = &conn->tls_capath;
break;
case XMPP_SETTING_CLIENT_CERT:
target = &conn->tls_client_cert;
break;
case XMPP_SETTING_CLIENT_KEY:
target = &conn->tls_client_key;
break;
default:
strophe_warn(conn->ctx, "xmpp", "Invalid String setting %d", setting);
return;
}
if (*target)
strophe_free(conn->ctx, *target);
*target = NULL;
if (value) {
*target = strophe_strdup(conn->ctx, value);
}
}
/** Configure a connection-related pointer setting
*
* `setting` can be one of:
* - \ref XMPP_SETTING_PASSWORD_CALLBACK_USERDATA
* Set the userdata pointer that is pass when the password-retrieval
* callback is called. \ref XMPP_SETTING_PASSWORD_CALLBACK
*
* @param conn a Strophe connection object
* @param setting The setting that shall be configured
* @param value The value, the settings should get
*
* @ingroup Connections
*/
void xmpp_conn_set_pointer(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
void *value)
{
switch (setting) {
case XMPP_SETTING_PASSWORD_CALLBACK_USERDATA:
conn->password_callback_userdata = value;
break;
default:
strophe_warn(conn->ctx, "xmpp", "Invalid Pointer setting %d", setting);
return;
}
}
/** Configure a connection-related functionpointer setting
*
* `setting` can be one of:
* - \ref XMPP_SETTING_PASSWORD_CALLBACK
* Set the Callback function which will be called when the TLS stack can't
* decrypt a password protected key file. The userdata pointer can be set
* via \ref xmpp_conn_set_pointer with the setting
* \ref XMPP_SETTING_PASSWORD_CALLBACK_USERDATA
*
* - \ref XMPP_SETTING_CERTFAIL_HANDLER
* Set the Handler function which will be called when the TLS stack can't
* verify the CA of the server we're trying to connect to.
*
* - \ref XMPP_SETTING_SOCKOPT_CALLBACK
* Set function to be called when a new socket is created to allow setting
* socket options before connection is started. \n
* If the connection is already connected, this callback will be called
* immediately. \n
* To set options that can only be applied to disconnected sockets, the
* callback must be registered before connecting.
*
* @param conn a Strophe connection object
* @param setting The setting that shall be configured
* @param value The value, the settings should get
*
* @ingroup Connections
*/
void xmpp_conn_set_functionpointer_impl(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
xmpp_conn_pfn_t value)
{
switch (setting) {
case XMPP_SETTING_PASSWORD_CALLBACK:
conn->password_callback = (xmpp_password_callback)value;
break;
case XMPP_SETTING_CERTFAIL_HANDLER:
conn->certfail_handler = (xmpp_certfail_handler)value;
break;
case XMPP_SETTING_SOCKOPT_CALLBACK:
conn->sockopt_cb = (xmpp_sockopt_callback)value;
if (conn->state != XMPP_STATE_DISCONNECTED)
conn->sockopt_cb(conn, &conn->sock);
break;
default:
strophe_warn(conn->ctx, "xmpp", "Invalid Functionpointer setting %d",
setting);
return;
}
}
/** Get the JID which is or will be bound to the connection. /** Get the JID which is or will be bound to the connection.
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
@@ -397,66 +571,6 @@ const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn)
return conn->bound_jid; return conn->bound_jid;
} }
/** Set the JID of the user that will be bound to the connection.
* If any JID was previously set, it will be discarded. This should not be
* be used after a connection is created. The function will make a copy of
* the JID string. If the supplied JID is missing the node, SASL
* ANONYMOUS authentication will be used.
*
* @param conn a Strophe connection object
* @param jid a full or bare JID
*
* @ingroup Connections
*/
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid)
{
if (conn->jid)
strophe_free(conn->ctx, conn->jid);
conn->jid = strophe_strdup(conn->ctx, jid);
}
/** Set the Handler function which will be called when the TLS stack can't
* verify the CA of the server we're trying to connect to.
*
* @param conn a Strophe connection object
* @param hndl certfail Handler function
*
* @ingroup TLS
*/
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
xmpp_certfail_handler hndl)
{
conn->certfail_handler = hndl;
}
/** Set the CAfile
*
* @param conn a Strophe connection object
* @param path path to a certificate file
*
* @ingroup TLS
*/
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path)
{
if (conn->tls_cafile)
strophe_free(conn->ctx, conn->tls_cafile);
conn->tls_cafile = strophe_strdup(conn->ctx, path);
}
/** Set the CApath
*
* @param conn a Strophe connection object
* @param path path to a folder containing certificates
*
* @ingroup TLS
*/
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path)
{
if (conn->tls_capath)
strophe_free(conn->ctx, conn->tls_capath);
conn->tls_capath = strophe_strdup(conn->ctx, path);
}
/** Retrieve the peer certificate /** Retrieve the peer certificate
* *
* The returned Certificate object must be free'd by calling * The returned Certificate object must be free'd by calling
@@ -473,41 +587,6 @@ xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn)
return tls_peer_cert(conn); return tls_peer_cert(conn);
} }
/** Set the Callback function which will be called when the TLS stack can't
* decrypt a password protected key file.
*
* @param conn a Strophe connection object
* @param cb The callback function that shall be called
* @param userdata An opaque data pointer that will be passed to the callback
*
* @ingroup TLS
*/
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
xmpp_password_callback cb,
void *userdata)
{
conn->password_callback = cb;
conn->password_callback_userdata = userdata;
}
/** Set the number of retry attempts to decrypt a private key file.
*
* In case the user enters the password manually it can be useful to
* directly retry if the decryption of the key file failed.
*
* @param conn a Strophe connection object
* @param retries The number of retries that should be tried
*
* @ingroup TLS
*/
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries)
{
if (retries == 0)
conn->password_retries = 1;
else
conn->password_retries = retries;
}
/** Retrieve the path of the key file that shall be unlocked. /** Retrieve the path of the key file that shall be unlocked.
* *
* This makes usually sense to be called from the * This makes usually sense to be called from the
@@ -524,49 +603,6 @@ const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn)
return conn->tls_client_key; return conn->tls_client_key;
} }
/** Set the Client Certificate and Private Key or PKCS#12 encoded file that
* will be bound to the connection. If any of them was previously set, it
* will be discarded. This should not be used after a connection is created.
* The function will make a copy of the strings passed in.
*
* In case the Private Key is encrypted, a callback must be set via
* \ref xmpp_conn_set_password_callback so the TLS stack can retrieve the
* password.
*
* In case one wants to use a PKCS#12 encoded file, it should be passed via
* the `cert` parameter and `key` should be NULL. Passing a PKCS#12 file in
* `key` is deprecated.
*
* @param conn a Strophe connection object
* @param cert path to a certificate file or a P12 file
* @param key path to a private key file or a P12 file
*
* @ingroup TLS
*/
void xmpp_conn_set_client_cert(xmpp_conn_t *const conn,
const char *const cert,
const char *const key)
{
strophe_debug(conn->ctx, "conn", "set client cert %s %s", cert, key);
if (conn->tls_client_cert)
strophe_free(conn->ctx, conn->tls_client_cert);
conn->tls_client_cert = NULL;
if (conn->tls_client_key)
strophe_free(conn->ctx, conn->tls_client_key);
conn->tls_client_key = NULL;
if (cert && key) {
conn->tls_client_cert = strophe_strdup(conn->ctx, cert);
conn->tls_client_key = strophe_strdup(conn->ctx, key);
} else if (cert && !key) {
conn->tls_client_cert = strophe_strdup(conn->ctx, cert);
} else if (!cert && key) {
strophe_warn(conn->ctx, "xmpp",
"xmpp_conn_set_client_cert: Passing PKCS#12 in 'key' "
"parameter is deprecated. Use 'cert' instead");
conn->tls_client_cert = strophe_strdup(conn->ctx, key);
}
}
/** Get the number of xmppAddr entries in the client certificate. /** Get the number of xmppAddr entries in the client certificate.
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
@@ -607,22 +643,6 @@ const char *xmpp_conn_get_pass(const xmpp_conn_t *conn)
return conn->pass; return conn->pass;
} }
/** Set the password used to authenticate the connection.
* If any password was previously set, it will be discarded. The function
* will make a copy of the password string.
*
* @param conn a Strophe connection object
* @param pass the password
*
* @ingroup Connections
*/
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass)
{
if (conn->pass)
strophe_free(conn->ctx, conn->pass);
conn->pass = pass ? strophe_strdup(conn->ctx, pass) : NULL;
}
/** Get the strophe context that the connection is associated with. /** Get the strophe context that the connection is associated with.
* @param conn a Strophe connection object * @param conn a Strophe connection object
* *

View File

@@ -19,6 +19,7 @@
*/ */
#include "common.h" #include "common.h"
#include <limits.h>
/** Allocate memory in a Strophe context. /** Allocate memory in a Strophe context.
* All Strophe functions will use this to allocate memory. * All Strophe functions will use this to allocate memory.
@@ -86,6 +87,10 @@ char *xmpp_strndup(const xmpp_ctx_t *ctx, const char *s, size_t len)
return strophe_strndup(ctx, s, len); return strophe_strndup(ctx, s, len);
} }
/** Write to the log.
*
* @ingroup Deprecated
*/
void xmpp_log(const xmpp_ctx_t *ctx, void xmpp_log(const xmpp_ctx_t *ctx,
xmpp_log_level_t level, xmpp_log_level_t level,
const char *area, const char *area,
@@ -217,6 +222,10 @@ char *xmpp_strtok_r(char *s, const char *delim, char **saveptr)
return strophe_strtok_r(s, delim, saveptr); return strophe_strtok_r(s, delim, saveptr);
} }
/** snprintf(3) implementation.
*
* @ingroup Deprecated
*/
int xmpp_snprintf(char *str, size_t count, const char *fmt, ...) int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
{ {
va_list ap; va_list ap;
@@ -228,11 +237,184 @@ int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
return ret; return ret;
} }
/** vsnprintf(3) implementation.
*
* @ingroup Deprecated
*/
int xmpp_vsnprintf(char *str, size_t count, const char *fmt, va_list arg) int xmpp_vsnprintf(char *str, size_t count, const char *fmt, va_list arg)
{ {
return strophe_vsnprintf(str, count, fmt, arg); return strophe_vsnprintf(str, count, fmt, arg);
} }
/** Set the JID of the user that will be bound to the connection.
* If any JID was previously set, it will be discarded. This should not be
* be used after a connection is created. The function will make a copy of
* the JID string. If the supplied JID is missing the node, SASL
* ANONYMOUS authentication will be used.
*
* @param conn a Strophe connection object
* @param jid a full or bare JID
*
* @ingroup Deprecated
*/
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid)
{
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
}
/** Set the password used to authenticate the connection.
* If any password was previously set, it will be discarded. The function
* will make a copy of the password string.
*
* @param conn a Strophe connection object
* @param pass the password
*
* @ingroup Deprecated
*/
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass)
{
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, pass);
}
/** Set the CAfile
*
* @param conn a Strophe connection object
* @param path path to a certificate file
*
* @ingroup Deprecated
*/
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path)
{
xmpp_conn_set_string(conn, XMPP_SETTING_CAFILE, path);
}
/** Set the CApath
*
* @param conn a Strophe connection object
* @param path path to a folder containing certificates
*
* @ingroup Deprecated
*/
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path)
{
xmpp_conn_set_string(conn, XMPP_SETTING_CAPATH, path);
}
/** Set the Client Certificate and Private Key or PKCS#12 encoded file that
* will be bound to the connection. If any of them was previously set, it
* will be discarded. This should not be used after a connection is created.
* The function will make a copy of the strings passed in.
*
* In case the Private Key is encrypted, a callback must be set via
* \ref xmpp_conn_set_password_callback so the TLS stack can retrieve the
* password.
*
* In case one wants to use a PKCS#12 encoded file, it should be passed via
* the `cert` parameter and `key` should be NULL. Passing a PKCS#12 file in
* `key` is deprecated.
*
* @param conn a Strophe connection object
* @param cert path to a certificate file or a P12 file
* @param key path to a private key file or a P12 file
*
* @ingroup Deprecated
*/
void xmpp_conn_set_client_cert(xmpp_conn_t *const conn,
const char *const cert,
const char *const key)
{
strophe_debug(conn->ctx, "conn", "set client cert %s %s", cert, key);
if (!cert && key) {
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, key);
strophe_warn(conn->ctx, "xmpp",
"xmpp_conn_set_client_cert: Passing PKCS#12 in 'key' "
"parameter is deprecated. Use 'cert' instead");
} else {
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, cert);
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, key);
}
}
/** Set the number of retry attempts to decrypt a private key file.
*
* In case the user enters the password manually it can be useful to
* directly retry if the decryption of the key file failed.
*
* @param conn a Strophe connection object
* @param retries The number of retries that should be tried
*
* @ingroup Deprecated
*/
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries)
{
int val;
if (retries > INT_MAX) {
val = INT_MAX;
strophe_warn(conn->ctx, "xmpp", "retries capped from %u to %d", retries,
val);
} else {
val = (int)retries;
}
xmpp_conn_set_int(conn, XMPP_SETTING_PASSWORD_RETRIES, val);
}
/** Set the Callback function which will be called when the TLS stack can't
* decrypt a password protected key file.
*
* @param conn a Strophe connection object
* @param cb The callback function that shall be called
* @param userdata An opaque data pointer that will be passed to the callback
*
* @ingroup Deprecated
*/
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
xmpp_password_callback cb,
void *userdata)
{
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK, cb);
xmpp_conn_set_pointer(conn, XMPP_SETTING_PASSWORD_CALLBACK_USERDATA,
userdata);
}
/** Set the Handler function which will be called when the TLS stack can't
* verify the CA of the server we're trying to connect to.
*
* @param conn a Strophe connection object
* @param hndl certfail Handler function
*
* @ingroup Deprecated
*/
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
xmpp_certfail_handler hndl)
{
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_CERTFAIL_HANDLER, hndl);
}
/** Register sockopt callback
* Set function to be called when a new socket is created to allow setting
* socket options before connection is started.
*
* If the connection is already connected, this callback will be called
* immediately.
*
* To set options that can only be applied to disconnected sockets, the
* callback must be registered before connecting.
*
* @param conn The Strophe connection object this callback is being registered
* for
* @param callback a xmpp_sockopt_callback callback function that will receive
* notifications of connection status
*
* @ingroup Deprecated
*/
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
xmpp_sockopt_callback callback)
{
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
callback);
}
/** Set TCP keepalive parameters /** Set TCP keepalive parameters
* Turn on TCP keepalive and set timeout and interval. Zero timeout * Turn on TCP keepalive and set timeout and interval. Zero timeout
* disables TCP keepalives. The parameters are applied immediately for * disables TCP keepalives. The parameters are applied immediately for
@@ -253,7 +435,8 @@ void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval)
conn->ka_timeout = timeout; conn->ka_timeout = timeout;
conn->ka_interval = interval; conn->ka_interval = interval;
conn->ka_count = 0; conn->ka_count = 0;
xmpp_conn_set_sockopt_callback(conn, xmpp_sockopt_cb_keepalive); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
xmpp_sockopt_cb_keepalive);
} }
/** Disable TLS for this connection, called by users of the library. /** Disable TLS for this connection, called by users of the library.

View File

@@ -371,37 +371,70 @@ typedef int (*xmpp_sockopt_callback)(xmpp_conn_t *conn, void *sock);
/* an example callback that sets basic keepalive parameters */ /* an example callback that sets basic keepalive parameters */
int xmpp_sockopt_cb_keepalive(xmpp_conn_t *conn, void *sock); int xmpp_sockopt_cb_keepalive(xmpp_conn_t *conn, void *sock);
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text);
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx); xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx);
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn); xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn);
int xmpp_conn_release(xmpp_conn_t *conn); int xmpp_conn_release(xmpp_conn_t *conn);
/** Connection settings
*/
typedef enum xmpp_conn_setting_t {
/* String values */
XMPP_SETTING_JID = 0x0, /**< JID */
XMPP_SETTING_PASS, /**< Password */
XMPP_SETTING_CAFILE, /**< CAfile */
XMPP_SETTING_CAPATH, /**< CApath */
XMPP_SETTING_CLIENT_CERT, /**< Client Certificate */
XMPP_SETTING_CLIENT_KEY, /**< Key of Client Certificate */
/* Int values */
XMPP_SETTING_PASSWORD_RETRIES = 0x40, /**< Number of retry attempts to
decrypt a private key file. */
XMPP_SETTING_COMPRESSION_LEVEL, /**< Compression level. */
/* Pointer values */
XMPP_SETTING_PASSWORD_CALLBACK_USERDATA = 0x80, /**< Userdata for password
callback function */
/* Functionpointer values */
XMPP_SETTING_PASSWORD_CALLBACK = 0xC0, /**< Callback function to retrieve
password for key file. */
XMPP_SETTING_CERTFAIL_HANDLER, /**< Handler function when certificate chain
can't be verified */
XMPP_SETTING_SOCKOPT_CALLBACK, /**< Callback function when a new socket is
created. */
} xmpp_conn_setting_t;
void xmpp_conn_set_int(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
int value);
void xmpp_conn_set_string(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
const char *value);
void xmpp_conn_set_pointer(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
void *value);
/* Provide a wrapper macro, so users don't have to cast their function pointer
* type manually. */
typedef int (*xmpp_conn_pfn_t)();
#define xmpp_conn_set_functionpointer(c, s, p) \
do { \
xmpp_conn_set_functionpointer_impl(c, s, (xmpp_conn_pfn_t)p); \
} while (0)
void xmpp_conn_set_functionpointer_impl(xmpp_conn_t *conn,
xmpp_conn_setting_t setting,
xmpp_conn_pfn_t pfn);
long xmpp_conn_get_flags(const xmpp_conn_t *conn); long xmpp_conn_get_flags(const xmpp_conn_t *conn);
int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags); int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags);
const char *xmpp_conn_get_jid(const xmpp_conn_t *conn); const char *xmpp_conn_get_jid(const xmpp_conn_t *conn);
const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn); const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn);
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid);
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path);
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path);
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
xmpp_certfail_handler hndl);
xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn); xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn);
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
xmpp_password_callback cb,
void *userdata);
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries);
const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn); const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn);
void xmpp_conn_set_client_cert(xmpp_conn_t *conn,
const char *cert,
const char *key);
unsigned int xmpp_conn_cert_xmppaddr_num(xmpp_conn_t *conn); unsigned int xmpp_conn_cert_xmppaddr_num(xmpp_conn_t *conn);
char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *conn, unsigned int n); char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *conn, unsigned int n);
const char *xmpp_conn_get_pass(const xmpp_conn_t *conn); const char *xmpp_conn_get_pass(const xmpp_conn_t *conn);
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass);
xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn); xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn);
int xmpp_conn_is_secured(xmpp_conn_t *conn); int xmpp_conn_is_secured(xmpp_conn_t *conn);
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
xmpp_sockopt_callback callback);
int xmpp_conn_is_connecting(xmpp_conn_t *conn); int xmpp_conn_is_connecting(xmpp_conn_t *conn);
int xmpp_conn_is_connected(xmpp_conn_t *conn); int xmpp_conn_is_connected(xmpp_conn_t *conn);
int xmpp_conn_is_disconnected(xmpp_conn_t *conn); int xmpp_conn_is_disconnected(xmpp_conn_t *conn);
@@ -445,6 +478,7 @@ int xmpp_conn_tls_start(xmpp_conn_t *conn);
void xmpp_disconnect(xmpp_conn_t *conn); void xmpp_disconnect(xmpp_conn_t *conn);
void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza); void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza);
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text);
void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...); void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...);
void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len); void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len);
@@ -712,6 +746,7 @@ void xmpp_rand_nonce(xmpp_rand_t *rand, char *output, size_t len);
* deprecation */ * deprecation */
#include <stdarg.h> #include <stdarg.h>
#if !defined(XMPP_DEPRECATED)
/** /**
* XMPP_DEPRECATED(x) macro to show a compiler warning for deprecated API * XMPP_DEPRECATED(x) macro to show a compiler warning for deprecated API
* functions * functions
@@ -730,6 +765,7 @@ void xmpp_rand_nonce(xmpp_rand_t *rand, char *output, size_t len);
#else #else
#define XMPP_DEPRECATED(x) #define XMPP_DEPRECATED(x)
#endif #endif
#endif
XMPP_DEPRECATED(internal) void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size); XMPP_DEPRECATED(internal) void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size);
XMPP_DEPRECATED(internal) XMPP_DEPRECATED(internal)
@@ -769,6 +805,31 @@ void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval);
XMPP_DEPRECATED(xmpp_conn_set_flags) XMPP_DEPRECATED(xmpp_conn_set_flags)
void xmpp_conn_disable_tls(xmpp_conn_t *conn); void xmpp_conn_disable_tls(xmpp_conn_t *conn);
XMPP_DEPRECATED(xmpp_conn_set_string)
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid);
XMPP_DEPRECATED(xmpp_conn_set_string)
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass);
XMPP_DEPRECATED(xmpp_conn_set_string)
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path);
XMPP_DEPRECATED(xmpp_conn_set_string)
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path);
XMPP_DEPRECATED(xmpp_conn_set_string)
void xmpp_conn_set_client_cert(xmpp_conn_t *conn,
const char *cert,
const char *key);
XMPP_DEPRECATED(xmpp_conn_set_int)
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries);
XMPP_DEPRECATED(xmpp_conn_set_functionpointer)
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
xmpp_password_callback cb,
void *userdata);
XMPP_DEPRECATED(xmpp_conn_set_functionpointer)
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
xmpp_certfail_handler hndl);
XMPP_DEPRECATED(xmpp_conn_set_functionpointer)
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
xmpp_sockopt_callback callback);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -16,6 +16,7 @@
#include <string.h> #include <string.h>
#include <sys/param.h> #include <sys/param.h>
#define XMPP_DEPRECATED(x)
#include "strophe.h" #include "strophe.h"
#include "test.h" #include "test.h"
@@ -41,12 +42,14 @@ int main()
} client_cert[] = { } client_cert[] = {
{0, "tests/cert.pem", "tests/key.pem"}, {0, "tests/cert.pem", "tests/key.pem"},
{1, "tests/cert.pem", "tests/key_encrypted.pem"}, {1, "tests/cert.pem", "tests/key_encrypted.pem"},
{0, NULL, "tests/cert.emptypass.pfx"},
{0, NULL, "tests/cert.nopass.pfx"},
{1, NULL, "tests/cert.pfx"},
{0, "tests/cert.emptypass.pfx", NULL}, {0, "tests/cert.emptypass.pfx", NULL},
{0, "tests/cert.nopass.pfx", NULL}, {0, "tests/cert.nopass.pfx", NULL},
{1, "tests/cert.pfx", NULL}, {1, "tests/cert.pfx", NULL},
/* Backward compatibility checks for change introduced in #208
* To be removed, once xmpp_conn_set_client_cert() is gone */
{0, NULL, "tests/cert.emptypass.pfx"},
{0, NULL, "tests/cert.nopass.pfx"},
{1, NULL, "tests/cert.pfx"},
}; };
const char *srcdir; const char *srcdir;
@@ -78,9 +81,15 @@ int main()
keyfile = NULL; keyfile = NULL;
if (client_cert[m].needs_callback) if (client_cert[m].needs_callback)
xmpp_conn_set_password_callback(conn, password_callback, NULL); xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK,
password_callback);
if (certfile) {
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, certfile);
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, keyfile);
} else {
xmpp_conn_set_client_cert(conn, certfile, keyfile); xmpp_conn_set_client_cert(conn, certfile, keyfile);
}
xmppaddr_num[0] = '0' + xmpp_conn_cert_xmppaddr_num(conn); xmppaddr_num[0] = '0' + xmpp_conn_cert_xmppaddr_num(conn);