sml_elements.c
/*
* libsyncml - A syncml protocol implementation
* Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
* Copyright (C) 2007-2009 Michael Bell <michael.bell@opensync.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "syncml.h"
#include "syncml_internals.h"
#include "sml_parse_internals.h"
#include "sml_elements_internals.h"
#include "sml_command_internals.h"
#include "sml_error_internals.h"
SmlLocation *smlLocationNew(const char *locURI, const char *locName, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(locURI), VA_STRING(locName), error);
CHECK_ERROR_REF
if (!locURI) {
smlErrorSet(error, SML_ERROR_GENERIC, "No locURI was given");
goto error;
}
SmlLocation *location = smlTryMalloc0(sizeof(SmlLocation), error);
if (!location)
goto error;
location->refCount = 1;
location->locURI = g_strdup(locURI);
location->locName = g_strdup(locName);
smlTrace(TRACE_EXIT, "%s: %p", __func__, location);
return location;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlLocation *smlLocationRef(SmlLocation *loc)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, loc);
smlAssert(loc);
g_atomic_int_inc(&(loc->refCount));
smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, loc->refCount);
return loc;
}
void smlLocationUnref(SmlLocation *loc)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, loc);
smlAssert(loc);
if (g_atomic_int_dec_and_test(&(loc->refCount))) {
smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
if (loc->locURI)
smlSafeCFree(&(loc->locURI));
if (loc->locName)
smlSafeCFree(&(loc->locName));
smlSafeFree((gpointer *)&loc);
}
smlTrace(TRACE_EXIT, "%s", __func__);
}
const char *smlLocationGetURI(SmlLocation *loc)
{
smlAssert(loc);
return loc->locURI;
}
void smlLocationSetURI(SmlLocation *loc, const char *uri)
{
smlAssert(loc);
smlAssert(uri);
if (loc->locURI)
smlSafeCFree(&(loc->locURI));
loc->locURI = g_strdup(uri);
}
const char *smlLocationGetName(SmlLocation *loc)
{
smlAssert(loc);
return loc->locName;
}
void smlLocationSetName(SmlLocation *loc, const char *name)
{
smlAssert(loc);
smlAssert(name);
if (loc->locName)
smlSafeCFree(&(loc->locName));
loc->locName = g_strdup(name);
}
SmlLocation *smlLocationClone(SmlLocation *source, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, source, error);
CHECK_ERROR_REF
smlAssert(source);
SmlLocation *location = smlTryMalloc0(sizeof(SmlLocation), error);
if (!location)
goto error;
location->refCount = 1;
smlLocationCopy(source, location);
smlTrace(TRACE_EXIT, "%s: %p", __func__, location);
return location;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
void smlLocationCopy(SmlLocation *source, SmlLocation *target)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p)", __func__, source, target);
smlAssert(source);
smlAssert(target);
if (target->locURI)
smlSafeCFree(&(target->locURI));
if (target->locName)
smlSafeCFree(&(target->locName));
target->locURI = g_strdup(source->locURI);
target->locName = g_strdup(source->locName);
smlTrace(TRACE_EXIT, "%s", __func__);
}
#define URL_DELIMITER "/"
char *strreplace(const char *input, const char *needle, const char *replacement)
{
char *output = g_strdup(input);
while (g_strrstr(output, needle)) {
char *buffer = g_strndup(output, g_strrstr(output, needle) - output);
char *buffer2 = g_strconcat(buffer, replacement ? replacement : "", g_strrstr(output, needle) + strlen(needle), NULL);
smlSafeCFree(&output);
output = buffer2;
smlSafeCFree(&buffer);
}
return output;
}
char *normalizeUrl(const char *url)
{
smlTrace(TRACE_ENTRY, "%s(%s)", __func__, VA_STRING(url));
if (!url)
return NULL;
char *buffer = strreplace(url, "./", "");
char *buffer2 = strreplace(buffer, "//", "/");
smlSafeCFree(&buffer);
if (strlen(buffer2) > 0 && buffer2[strlen(buffer2) - 1] == '/')
buffer2[strlen(buffer2) - 1] = 0;
smlTrace(TRACE_EXIT, "%s: %s", __func__, VA_STRING(buffer2));
return buffer2;
}
SmlBool smlLocationCompare(SmlLocation *objectroot, SmlLocation *object, SmlLocation *urlroot, SmlLocation *url)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, objectroot, object, urlroot, url);
if (objectroot)
smlTrace(TRACE_INTERNAL, "%s: objectroot: %s", __func__, VA_STRING(objectroot->locURI));
if (object)
smlTrace(TRACE_INTERNAL, "%s: object: %s", __func__, VA_STRING(object->locURI));
if (urlroot)
smlTrace(TRACE_INTERNAL, "%s: urlroot: %s", __func__, VA_STRING(urlroot->locURI));
if (url)
smlTrace(TRACE_INTERNAL, "%s: url: %s", __func__, VA_STRING(url->locURI));
char *cmpobjurl = NULL;
char *cmpurl = NULL;
char *buffer = NULL;
char *buffer2 = NULL;
SmlBool ret = FALSE;
if (object && !url) {
smlTrace(TRACE_EXIT, "%s: url not given but object: FALSE", __func__);
return FALSE;
}
if (!object) {
smlTrace(TRACE_EXIT, "%s: No object given: TRUE", __func__);
return TRUE;
}
if (g_path_is_absolute(url->locURI) || !urlroot)
cmpurl = normalizeUrl(url->locURI);
else {
buffer2 = normalizeUrl(url->locURI);
buffer = g_strconcat(urlroot->locURI, "/", buffer2, NULL);
cmpurl = normalizeUrl(buffer);
smlSafeCFree(&buffer);
smlSafeCFree(&buffer2);
}
if (g_path_is_absolute(object->locURI) || !objectroot)
cmpobjurl = normalizeUrl(object->locURI);
else {
buffer2 = normalizeUrl(object->locURI);
buffer = g_strconcat(objectroot->locURI, "/", buffer2, NULL);
cmpobjurl = normalizeUrl(buffer);
smlSafeCFree(&buffer);
smlSafeCFree(&buffer2);
}
smlTrace(TRACE_INTERNAL, "%s: Comparing %s and %s", __func__, VA_STRING(cmpobjurl), VA_STRING(cmpurl));
if (strcmp(cmpobjurl, cmpurl))
ret = FALSE;
else
ret = TRUE;
smlSafeCFree(&cmpobjurl);
smlSafeCFree(&cmpurl);
smlTrace(TRACE_EXIT, "%s: %i", __func__, ret);
return ret;
}
SmlBool smlLocationIsRelative(SmlLocation *location)
{
smlAssert(location);
return g_path_is_absolute(location->locURI) ? FALSE : TRUE;
}
SmlAnchor *smlAnchorNew(const char *last, const char *next, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(last), VA_STRING(next), error);
CHECK_ERROR_REF
SmlAnchor *anchor = smlTryMalloc0(sizeof(SmlAnchor), error);
if (!anchor)
goto error;
anchor->last = g_strdup(last);
anchor->next = g_strdup(next);
smlTrace(TRACE_EXIT, "%s: %p", __func__, anchor);
return anchor;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
void smlAnchorFree(SmlAnchor *anchor)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, anchor);
smlAssert(anchor);
if (anchor->last)
smlSafeCFree(&(anchor->last));
if (anchor->next)
smlSafeCFree(&(anchor->next));
smlSafeFree((gpointer *)&anchor);
smlTrace(TRACE_EXIT, "%s", __func__);
}
void smlHeaderFree(SmlHeader *header)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, header);
if (header->sessionID)
smlSafeCFree(&(header->sessionID));
if (header->emi)
smlSafeCFree(&(header->emi));
if (header->source)
smlLocationUnref(header->source);
if (header->target)
smlLocationUnref(header->target);
if (header->responseURI)
smlSafeCFree(&(header->responseURI));
smlSafeFree((gpointer *)&header);
smlTrace(TRACE_EXIT, "%s", __func__);
}
SmlItem *smlItemNew(unsigned int size, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%i, %p)", __func__, size, error);
CHECK_ERROR_REF
SmlItem *item = smlTryMalloc0(sizeof(SmlItem), error);
if (!item)
goto error;
item->refCount = 1;
item->size = size;
smlTrace(TRACE_EXIT, "%s: %p", __func__, item);
return item;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
/* If data is NULL, this call is the same if smlItemNew */
SmlItem *smlItemNewForData(const char *data, unsigned int size, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %i, %p)", __func__, data, size, error);
CHECK_ERROR_REF
SmlItem *item = smlItemNew(size, error);
if (!item)
goto error;
if (data) {
if (!smlItemAddData(item, data, size, error))
goto error_free_item;
}
smlTrace(TRACE_EXIT, "%s: %p", __func__, item);
return item;
error_free_item:
smlItemUnref(item);
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlItem *smlItemRef(SmlItem *item)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
smlAssert(item);
g_atomic_int_inc(&(item->refCount));
smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, item->refCount);
return item;
}
void smlItemUnref(SmlItem *item)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
smlAssert(item);
if (g_atomic_int_dec_and_test(&(item->refCount))) {
smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
if (item->source)
smlLocationUnref(item->source);
if (item->target)
smlLocationUnref(item->target);
if (item->sourceParent)
smlLocationUnref(item->sourceParent);
if (item->targetParent)
smlLocationUnref(item->targetParent);
if (item->anchor)
smlAnchorFree(item->anchor);
if (item->buffer)
xmlBufferFree(item->buffer);
if (item->contenttype)
smlSafeCFree(&(item->contenttype));
smlSafeFree((gpointer *)&item);
}
smlTrace(TRACE_EXIT, "%s: %i", __func__, item ? item->refCount : 0);
}
SmlBool smlItemAddData(SmlItem *item, const char *data, unsigned int size, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %i, %p)", __func__, item, data, size, error);
CHECK_ERROR_REF
if (item->size && xmlBufferLength(item->buffer) + size > item->size) {
smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data. size limit reached");
goto error;
}
if (data) {
if (!item->buffer) {
if (item->size)
item->buffer = xmlBufferCreateSize(item->size);
else
item->buffer = xmlBufferCreateSize(size);
}
if (xmlBufferAdd(item->buffer, (xmlChar *)data, size) != 0) {
smlErrorSet(error, SML_ERROR_GENERIC, "Unable to add data.");
goto error;
}
}
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlBool smlItemCheck(SmlItem *item)
{
smlAssert(xmlBufferLength(item->buffer) >= 0);
smlAssert(item);
if (!item->size)
return TRUE;
if ((unsigned int)xmlBufferLength(item->buffer) != item->size)
{
smlTrace(TRACE_INTERNAL, "%s: failed because size (%d != %d) does not match (%s).",
__func__, item->size,
xmlBufferLength(item->buffer), VA_STRING((char *)xmlBufferContent(item->buffer)));
return FALSE;
}
return TRUE;
}
SmlBool smlItemHasData(SmlItem *item)
{
smlAssert(item);
return item->buffer ? TRUE : FALSE;
}
SmlBool smlItemStealData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, item, data, size, error);
CHECK_ERROR_REF
smlAssert(size);
if (!smlItemCheck(item)) {
smlErrorSet(error, SML_ERROR_GENERIC, "Item check failed");
goto error;
}
*size = xmlBufferLength(item->buffer);
*data = g_strndup((const char *) xmlBufferContent(item->buffer), *size);
xmlBufferFree(item->buffer);
item->buffer = NULL;
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%p, %p, %p, %p)", __func__, item, data, size, error);
CHECK_ERROR_REF
if (!smlItemCheck(item)) {
smlErrorSet(error, SML_ERROR_GENERIC, "Item check failed");
goto error;
}
*data = (char *)xmlBufferContent(item->buffer);
*size = xmlBufferLength(item->buffer);
smlTrace(TRACE_EXIT, "%s", __func__);
return TRUE;
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return FALSE;
}
void smlItemSetSource(SmlItem *item, SmlLocation *source)
{
smlAssert(item);
smlAssert(source);
item->source = source;
smlLocationRef(source);
}
SmlLocation *smlItemGetSource(SmlItem *item)
{
smlAssert(item);
return item->source;
}
void smlItemSetTarget(SmlItem *item, SmlLocation *target)
{
smlAssert(item);
smlAssert(target);
item->target = target;
smlLocationRef(target);
}
SmlLocation *smlItemGetTarget(SmlItem *item)
{
smlAssert(item);
return item->target;
}
void smlItemSetSourceParent(SmlItem *item, SmlLocation *sourceParent)
{
smlAssert(item);
smlAssert(sourceParent);
item->sourceParent = sourceParent;
smlLocationRef(sourceParent);
}
SmlLocation *smlItemGetSourceParent(SmlItem *item)
{
smlAssert(item);
return item->sourceParent;
}
void smlItemSetTargetParent(SmlItem *item, SmlLocation *targetParent)
{
smlAssert(item);
smlAssert(targetParent);
item->targetParent = targetParent;
smlLocationRef(targetParent);
}
SmlLocation *smlItemGetTargetParent(SmlItem *item)
{
smlAssert(item);
return item->targetParent;
}
void smlItemSetRaw(SmlItem *item, SmlBool raw)
{
smlAssert(item);
item->raw = raw;
}
SmlCred *smlCredNewFromString(const char *type,
const char *format,
const char *data,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%s, %s, %s, %p)", __func__, VA_STRING(data), VA_STRING(type), VA_STRING(format), error);
CHECK_ERROR_REF
SmlAuthType smlType = SML_AUTH_TYPE_UNKNOWN;
SmlFormatType smlFormat = SML_FORMAT_TYPE_UNKNOWN;
if (!type || !strcmp(type, SML_AUTH_BASIC)) {
smlType = SML_AUTH_TYPE_BASIC;
} else if (!strcmp(type, SML_AUTH_MD5)) {
smlType = SML_AUTH_TYPE_MD5;
} else {
smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type - %s.", type);
goto error;
}
if (!format || !strcmp(format, SML_BASE64)) {
smlFormat = SML_FORMAT_TYPE_BASE64;
} else {
smlErrorSet(error, SML_ERROR_GENERIC, "SyncML credential: Unknown format - %s.", format);
goto error;
}
if (!data) {
smlErrorSet(error, SML_ERROR_GENERIC, "Data is missing in %s.", __func__);
goto error;
}
smlTrace(TRACE_EXIT, "%s", __func__);
return smlCredNew(smlType, smlFormat, data, NULL, error);
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlCred *smlCredNewAuth(SmlAuthType type,
const char *username,
const char *password,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%d, %s, %p)", __func__, type, VA_STRING(username), error);
CHECK_ERROR_REF
SmlCred *cred = NULL;
if (username == NULL || !strlen(username)) {
smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
"If authentication should be used then the username must be set.");
goto error;
}
if (password == NULL || !strlen(password)) {
smlErrorSet(error, SML_ERROR_INTERNAL_MISCONFIGURATION,
"If authentication should be used then the password must be set.");
goto error;
}
cred = smlTryMalloc0(sizeof(SmlCred), error);
if (!cred)
goto error;
cred->refCount = 1;
cred->format = SML_FORMAT_TYPE_BASE64;
cred->type = type;
cred->username = g_strdup(username);
cred->password = g_strdup(password);
smlTrace(TRACE_EXIT, "%s", __func__);
return cred;
error:
if (cred)
smlSafeFree((gpointer *)&cred);
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlCred *smlCredNew(SmlAuthType type,
SmlFormatType format,
const char *data,
const char *username,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%s, %d, %d, %p)", __func__, VA_STRING(data), type, format, error);
CHECK_ERROR_REF
SmlCred *cred = smlTryMalloc0(sizeof(SmlCred), error);
if (!cred)
goto error;
cred->type = type;
cred->format = format;
cred->data = g_strdup(data);
if (username)
cred->username = g_strdup(username);
else
cred->username = NULL;
cred->refCount = 1;
smlTrace(TRACE_EXIT, "%s: %p", __func__, cred);
return cred;
error:
if (cred->data)
smlSafeCFree(&(cred->data));
if (cred->username)
smlSafeCFree(&(cred->username));
if (cred)
smlSafeFree((gpointer *)&cred);
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
void smlCredRef(SmlCred *cred)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred);
smlAssert(cred);
g_atomic_int_inc(&(cred->refCount));
smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, cred->refCount);
}
void smlCredUnref(SmlCred *cred)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred);
smlAssert(cred);
if (g_atomic_int_dec_and_test(&(cred->refCount))) {
smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
if (cred->data)
smlSafeCFree(&(cred->data));
if (cred->username)
smlSafeCFree(&(cred->username));
if (cred->password)
smlSafeCFree(&(cred->password));
smlSafeFree((gpointer *)&cred);
}
smlTrace(TRACE_EXIT, "%s", __func__);
}
/* FIXME: DEPRECATED */
void smlCredFree(SmlCred *cred)
{
smlCredUnref(cred);
}
SmlChal *smlChalNew(SmlAuthType type, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%u, %p)", __func__, type, error);
CHECK_ERROR_REF
SmlChal *chal = NULL;
/* allocate memory */
smlAssert(type != SML_AUTH_TYPE_UNKNOWN);
chal = smlTryMalloc0(sizeof(SmlChal), error);
if (!chal)
goto error;
chal->refCount = 1;
chal->type = type;
chal->format = SML_FORMAT_TYPE_BASE64;
if (type == SML_AUTH_TYPE_MD5)
{
/* A nonce must be generated for this type.
* minimum strength: 2^128
* strength per byte: 2^6 - 2 > 2^5
* needed bytes: 128 / 5 < 130 / 5 = 26
*/
chal->nonce_plain = smlRandStr(26, TRUE);
chal->nonce_length = 26;
chal->nonce_b64 = g_base64_encode(
(const unsigned char *) chal->nonce_plain,
chal->nonce_length);
if (!chal->nonce_b64) {
smlErrorSet(error, SML_ERROR_GENERIC,
"The nonce of the challenge cannot be base64 encoded.");
goto error;
}
}
smlTrace(TRACE_EXIT, "%s", __func__);
return chal;
error:
if (chal->nonce_plain)
smlSafeCFree(&(chal->nonce_plain));
if (chal->nonce_b64)
smlSafeCFree(&(chal->nonce_b64));
if (chal)
smlSafeFree((gpointer *)&chal);
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlChal *smlChalNewFromBinary(
SmlAuthType type,
const char *nonce,
size_t length,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s", __func__);
CHECK_ERROR_REF
SmlChal *chal = NULL;
/* only syncml:auth-md5 needs a nonce */
smlAssert(type == SML_AUTH_TYPE_MD5);
/* allocate memory */
chal = smlTryMalloc0(sizeof(SmlChal), error);
if (!chal)
goto error;
chal->refCount = 1;
/* copy nonce */
chal->type = SML_AUTH_TYPE_MD5;
chal->format = SML_FORMAT_TYPE_BASE64;
chal->nonce_plain = g_strndup(nonce, length);
chal->nonce_length = length;
/* create base64 nonce */
chal->nonce_b64 = g_base64_encode((const unsigned char *) nonce, length);
if (!chal->nonce_b64) {
smlErrorSet(error, SML_ERROR_GENERIC,
"The base64 encoding of the nonce failed.");
goto error;
}
smlTrace(TRACE_EXIT, "%s", __func__);
return chal;
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlChal *smlChalNewFromBase64(
SmlAuthType type,
const char *nonce,
SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s", __func__);
CHECK_ERROR_REF
SmlChal *chal = NULL;
/* only syncml:auth-md5 needs a nonce */
smlAssert(type == SML_AUTH_TYPE_MD5);
/* allocate memory */
chal = smlTryMalloc0(sizeof(SmlChal), error);
if (!chal)
goto error;
chal->refCount = 1;
/* copy nonce */
chal->type = SML_AUTH_TYPE_MD5;
chal->format = SML_FORMAT_TYPE_BASE64;
chal->nonce_b64 = g_strdup(nonce);
/* create binary nonce */
size_t length = 0;
chal->nonce_plain = (char *) g_base64_decode(nonce, &length);
if (!chal->nonce_plain || length < 1) {
smlErrorSet(error, SML_ERROR_GENERIC,
"The base64 encoded nonce cannot be decoded.");
goto error;
}
chal->nonce_length = length;
smlTrace(TRACE_EXIT, "%s", __func__);
return chal;
error:
smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error));
return NULL;
}
void smlChalRef(SmlChal *chal)
{
smlTrace(TRACE_ENTRY, "%s", __func__);
smlAssert(chal);
g_atomic_int_inc(&(chal->refCount));
smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, chal->refCount);
}
void smlChalUnref(SmlChal *chal)
{
smlTrace(TRACE_ENTRY, "%s", __func__);
smlAssert(chal);
if (g_atomic_int_dec_and_test(&(chal->refCount))) {
smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
if (chal->nonce_plain)
smlSafeCFree(&(chal->nonce_plain));
if (chal->nonce_b64)
smlSafeCFree(&(chal->nonce_b64));
smlSafeFree((gpointer *)&chal);
}
smlTrace(TRACE_EXIT, "%s", __func__);
}
/* FIXME: DEPRECATED */
void smlChalFree(SmlChal *chal)
{
smlChalUnref(chal);
}
SmlMapItem *smlMapItemNew(const char *uid, const char *newuid, SmlError **error)
{
smlTrace(TRACE_ENTRY, "%s(%s, %s, %p)", __func__, VA_STRING(uid), VA_STRING(newuid), error);
CHECK_ERROR_REF
smlAssert(uid);
smlAssert(newuid);
SmlMapItem *item = smlTryMalloc0(sizeof(SmlMapItem), error);
if (!item)
goto error;
item->refCount = 1;
item->source = smlLocationNew(newuid, NULL, error);
if (!item->source)
goto error_free_item;
item->target = smlLocationNew(uid, NULL, error);
if (!item->target)
goto error_free_source;
smlTrace(TRACE_EXIT, "%s: %p", __func__, item);
return item;
error_free_source:
smlLocationUnref(item->source);
error_free_item:
smlSafeFree((gpointer *)&item);
error:
smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error));
return NULL;
}
SmlMapItem *smlMapItemRef(SmlMapItem *item)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
smlAssert(item);
g_atomic_int_inc(&(item->refCount));
smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, item->refCount);
return item;
}
void smlMapItemUnref(SmlMapItem *item)
{
smlTrace(TRACE_ENTRY, "%s(%p)", __func__, item);
smlAssert(item);
if (g_atomic_int_dec_and_test(&(item->refCount))) {
smlTrace(TRACE_INTERNAL, "%s: Refcount == 0!", __func__);
if (item->source)
{
smlLocationUnref(item->source);
item->source = NULL;
}
if (item->target)
{
smlLocationUnref(item->target);
item->target = NULL;
}
smlSafeFree((gpointer *)&item);
}
smlTrace(TRACE_EXIT, "%s", __func__);
}
SmlCred
Definition: sml_elements_internals.h:87
smlErrorPrint
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlError::type
SmlErrorType type
Definition: sml_error_internals.h:31
smlItemStealData
SmlBool smlItemStealData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
Definition: sml_elements.c:470
SmlError::refCount
gint32 refCount
Definition: sml_error_internals.h:37
SmlAnchor
Definition: sml_elements_internals.h:35
smlRandStr
char * smlRandStr(int maxlength, SmlBool exact)
Creates a random string.
Definition: sml_support.c:302
SmlHeader
Definition: sml_elements_internals.h:73
SmlItem::raw
SmlBool raw
Definition: sml_elements_internals.h:64
SmlItem
Definition: sml_elements_internals.h:46
SmlChal
Definition: sml_elements_internals.h:96
SmlMapItem
Definition: sml_elements_internals.h:67
smlItemGetData
SmlBool smlItemGetData(SmlItem *item, char **data, unsigned int *size, SmlError **error)
Definition: sml_elements.c:495
smlItemCheck
SmlBool smlItemCheck(SmlItem *item)
Definition: sml_elements.c:444
smlTrace
void smlTrace(SmlTraceType type, const char *message,...)
Used for tracing the application.
Definition: sml_support.c:120
SmlLocation
Definition: sml_elements_internals.h:40
smlTryMalloc0
void * smlTryMalloc0(long n_bytes, SmlError **error)
Safely mallocs.
Definition: sml_support.c:335
smlErrorSet
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
SmlError
Represent an error.
Definition: sml_error_internals.h:29