Module Name: src
Committed By: christos
Date: Sun Feb 20 01:59:46 UTC 2011
Modified Files:
src/crypto/external/bsd/libsaslc/dist/man: libsaslc.3
src/crypto/external/bsd/libsaslc/dist/src: list.c list.h
mech_digestmd5.c mech_gssapi.c xsess.c
Log Message:
improve error handling, from Anon Ymous
To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 \
src/crypto/external/bsd/libsaslc/dist/man/libsaslc.3
cvs rdiff -u -r1.2 -r1.3 src/crypto/external/bsd/libsaslc/dist/src/list.c
cvs rdiff -u -r1.1 -r1.2 src/crypto/external/bsd/libsaslc/dist/src/list.h
cvs rdiff -u -r1.9 -r1.10 \
src/crypto/external/bsd/libsaslc/dist/src/mech_digestmd5.c
cvs rdiff -u -r1.5 -r1.6 \
src/crypto/external/bsd/libsaslc/dist/src/mech_gssapi.c \
src/crypto/external/bsd/libsaslc/dist/src/xsess.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/crypto/external/bsd/libsaslc/dist/man/libsaslc.3
diff -u src/crypto/external/bsd/libsaslc/dist/man/libsaslc.3:1.9 src/crypto/external/bsd/libsaslc/dist/man/libsaslc.3:1.10
--- src/crypto/external/bsd/libsaslc/dist/man/libsaslc.3:1.9 Tue Feb 15 21:14:22 2011
+++ src/crypto/external/bsd/libsaslc/dist/man/libsaslc.3 Sat Feb 19 20:59:46 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: libsaslc.3,v 1.9 2011/02/16 02:14:22 christos Exp $
+.\" $NetBSD: libsaslc.3,v 1.10 2011/02/20 01:59:46 christos Exp $
.\"
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd February 14, 2011
+.Dd February 18, 2011
.Dt LIBSASLC 3
.Os
.Sh NAME
@@ -778,6 +778,10 @@
authentication with a
.Xr postfix 1
SMTP server using the cyrus-sasl library.
+LOGIN, PLAIN, CRAM-MD5, and DIGEST-MD5 have also been tested and shown
+to work with a
+.Xr postfix 1
+SMTP server using a dovecot backend for authentication.
The DIGEST-MD5 and GSSAPI specs also provide for integrity and
confidentiality layers via the
.Fn saslc_sess_encode
Index: src/crypto/external/bsd/libsaslc/dist/src/list.c
diff -u src/crypto/external/bsd/libsaslc/dist/src/list.c:1.2 src/crypto/external/bsd/libsaslc/dist/src/list.c:1.3
--- src/crypto/external/bsd/libsaslc/dist/src/list.c:1.2 Sat Feb 12 18:21:32 2011
+++ src/crypto/external/bsd/libsaslc/dist/src/list.c Sat Feb 19 20:59:46 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: list.c,v 1.2 2011/02/12 23:21:32 christos Exp $ */
+/* $NetBSD: list.c,v 1.3 2011/02/20 01:59:46 christos Exp $ */
/* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -32,7 +32,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: list.c,v 1.2 2011/02/12 23:21:32 christos Exp $");
+__RCSID("$NetBSD: list.c,v 1.3 2011/02/20 01:59:46 christos Exp $");
#include <stdio.h>
#include <stdlib.h>
@@ -164,11 +164,14 @@
/**
* @brief Parse a list of the following format:
* ( *LWS element *( *LWS "," *LWS element ))
+ * @param lp pointer to list_t type for returned list. Cannot be NULL.
* @param p string to parse
- * @return allocated list.
+ * @return 0 on success, -1 on error (no memory).
+ *
+ * Note: the list is allocated. Use saslc__list_free() to free it.
*/
-list_t *
-saslc__list_parse(const char *p)
+int
+saslc__list_parse(list_t **lp, const char *p)
{
const char *e, *n;
list_t *l, *t, **tp;
@@ -189,7 +192,7 @@
t = alloc_list(p, (size_t)(e - p));
if (t == NULL) {
saslc__list_free(l);
- return NULL;
+ return -1;
}
if (tp != NULL)
*tp = t;
@@ -197,7 +200,8 @@
l = t;
tp = &t->next;
}
- return l;
+ *lp = l;
+ return 0;
}
/**
Index: src/crypto/external/bsd/libsaslc/dist/src/list.h
diff -u src/crypto/external/bsd/libsaslc/dist/src/list.h:1.1 src/crypto/external/bsd/libsaslc/dist/src/list.h:1.2
--- src/crypto/external/bsd/libsaslc/dist/src/list.h:1.1 Fri Feb 11 18:44:43 2011
+++ src/crypto/external/bsd/libsaslc/dist/src/list.h Sat Feb 19 20:59:46 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: list.h,v 1.1 2011/02/11 23:44:43 christos Exp $ */
+/* $NetBSD: list.h,v 1.2 2011/02/20 01:59:46 christos Exp $ */
/* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -49,6 +49,6 @@
uint32_t saslc__list_flags(list_t *, const named_flag_t *);
void saslc__list_free(list_t *);
void saslc__list_log(list_t *, const char *);
-list_t * saslc__list_parse(const char *);
+int saslc__list_parse(list_t **, const char *);
#endif /* ! _LIST_H_ */
Index: src/crypto/external/bsd/libsaslc/dist/src/mech_digestmd5.c
diff -u src/crypto/external/bsd/libsaslc/dist/src/mech_digestmd5.c:1.9 src/crypto/external/bsd/libsaslc/dist/src/mech_digestmd5.c:1.10
--- src/crypto/external/bsd/libsaslc/dist/src/mech_digestmd5.c:1.9 Tue Feb 15 21:14:22 2011
+++ src/crypto/external/bsd/libsaslc/dist/src/mech_digestmd5.c Sat Feb 19 20:59:46 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mech_digestmd5.c,v 1.9 2011/02/16 02:14:22 christos Exp $ */
+/* $NetBSD: mech_digestmd5.c,v 1.10 2011/02/20 01:59:46 christos Exp $ */
/* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -35,7 +35,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: mech_digestmd5.c,v 1.9 2011/02/16 02:14:22 christos Exp $");
+__RCSID("$NetBSD: mech_digestmd5.c,v 1.10 2011/02/20 01:59:46 christos Exp $");
#include <sys/param.h>
@@ -651,22 +651,23 @@
* @param hqlist a comma delimited list with entries of the form
* "[hostname:]string".
* @param hostname the hostname to use in the selection.
- * @return the best matching string or NULL if none found.
+ * @param rval pointer to location for returned string. Set to NULL
+ * if none found, otherwise set to strdup(3) of the string found.
+ * @return 0 on success, -1 on failure (no memory).
*
- * NOTE: hqlist must not be NULL.
+ * NOTE: hqlist and rval must not be NULL.
* NOTE: this allocates memory for its output and the caller is
* responsible for freeing it.
*/
-static char *
-choose_from_hqlist(const char *hqlist, const char *hostname)
+static int
+choose_from_hqlist(const char *hqlist, const char *hostname, char **rval)
{
list_t *l, *list;
size_t len;
char *p;
- list = saslc__list_parse(hqlist);
- if (list == NULL)
- return NULL;
+ if (saslc__list_parse(&list, hqlist) == -1)
+ return -1; /* no memory */
/*
* If the user provided a list and the caller provided a
@@ -677,14 +678,14 @@
len = strlen(hostname);
for (l = list; l != NULL; l = l->next) {
p = l->value + len;
- if (strncasecmp(l->value, hostname, len) != 0 ||
- *p != ':')
+ if (*p != ':' ||
+ strncasecmp(l->value, hostname, len) != 0)
continue;
if (*(++p) != '\0' && isalnum((unsigned char)*p)) {
- p = strdup(p);
- saslc__list_free(list);
- return p;
+ if ((p = strdup(p)) == NULL)
+ goto nomem;
+ goto done;
}
}
}
@@ -695,12 +696,18 @@
p = NULL;
for (l = list; l != NULL; l = l->next) {
if (strchr(l->value, ':') == NULL) {
- p = strdup(l->value);
- break;
+ if ((p = strdup(l->value)) == NULL)
+ goto nomem;
+ goto done;
}
}
+ done:
saslc__list_free(list);
- return p;
+ *rval = p;
+ return 0;
+ nomem:
+ saslc__list_free(list);
+ return -1;
}
/**
@@ -714,15 +721,12 @@
static char *
saslc__mech_digestmd5_digesturi(saslc_sess_t *sess, const char *serv_host)
{
- saslc__mech_digestmd5_sess_t *ms;
const char *serv_list;
char *serv_name;
const char *serv_type;
char *r;
int rv;
- ms = sess->mech_sess;
-
serv_type = saslc_sess_getprop(sess, SASLC_DIGESTMD5_SERVICE);
if (serv_type == NULL) {
saslc__error_set(ERR(sess), ERROR_MECH,
@@ -730,10 +734,13 @@
return NULL;
}
serv_list = saslc_sess_getprop(sess, SASLC_DIGESTMD5_SERVNAME);
- serv_name = serv_list != NULL
- ? choose_from_hqlist(serv_list, serv_host) : NULL;
+ if (serv_list == NULL)
+ serv_name = NULL;
+ else if (choose_from_hqlist(serv_list, serv_host, &serv_name) == -1)
+ goto nomem;
- saslc__msg_dbg("%s: serv_name='%s'", __func__, serv_name);
+ saslc__msg_dbg("%s: serv_name='%s'", __func__,
+ serv_name ? serv_name : "<null>");
/****************************************************************/
/* digest-uri = "digest-uri" "=" <"> digest-uri-value <"> */
@@ -753,12 +760,14 @@
: asprintf(&r, "%s/%s/%s", serv_type, serv_host, serv_name);
if (serv_name != NULL)
free(serv_name);
- if (rv == -1) {
- saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
- return NULL;
- }
+ if (rv == -1)
+ goto nomem;
+
saslc__msg_dbg("%s: digest-uri='%s'", __func__, r);
return r;
+ nomem:
+ saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
+ return NULL;
}
/**
@@ -871,15 +880,21 @@
*/
if (realms == NULL) {
/*
- * No realm was supplied. Figure out a plausable
- * default.
+ * No realm was supplied in challenge. Figure out a
+ * plausable default.
*/
- if (user_realms != NULL) {
- p = choose_from_hqlist(user_realms, hostname);
- if (p != NULL)
- return p;
+ if (user_realms == NULL) {
+ saslc__error_set(ERR(sess), ERROR_MECH,
+ "cannot determine the realm");
+ return NULL;
}
- return NULL;
+ if (choose_from_hqlist(user_realms, hostname, &p) == -1)
+ goto nomem;
+
+ if (p == NULL)
+ saslc__error_set(ERR(sess), ERROR_MECH,
+ "cannot choose a realm");
+ return p;
}
/************************************************************/
@@ -892,9 +907,14 @@
* one from the user provided list, just take the first realm
* from the challenge.
*/
- if (user_realms == NULL ||
- (p = choose_from_hqlist(user_realms, hostname)) == NULL)
- return strdup(realms->value);
+ if (user_realms == NULL)
+ goto use_1st_realm;
+
+ if (choose_from_hqlist(user_realms, hostname, &p) == -1)
+ goto nomem;
+
+ if (p == NULL)
+ goto use_1st_realm;
/*
* If we found a matching user provide realm, make sure it is
@@ -905,7 +925,13 @@
if (strcasecmp(p, l->value) == 0)
return p;
}
- return strdup(realms->value);
+ use_1st_realm:
+ if ((p = strdup(realms->value)) == NULL)
+ goto nomem;
+ return p;
+ nomem:
+ saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
+ return NULL;
}
/**
@@ -1445,7 +1471,10 @@
qop_flags &= DEFAULT_QOP_MASK;
user_qop = saslc_sess_getprop(sess, SASLC_DIGESTMD5_QOPMASK);
if (user_qop != NULL) {
- list = saslc__list_parse(user_qop);
+ if (saslc__list_parse(&list, user_qop) == -1) {
+ saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
+ return -1;
+ }
qop_flags &= saslc__mech_qop_list_flags(list);
saslc__list_free(list);
}
@@ -1481,13 +1510,18 @@
unsigned int cipher_mask;
const char *user_cipher;
- if (cipher_flags == 0) /* no cipher spec in challenge */
+ if (cipher_flags == 0) {
+ saslc__error_set(ERR(sess), ERROR_MECH,
+ "no cipher spec in challenge");
return -1;
-
+ }
cipher_mask = DEFAULT_CIPHER_MASK;
user_cipher = saslc_sess_getprop(sess, SASLC_DIGESTMD5_CIPHERMASK);
if (user_cipher != NULL) {
- list = saslc__list_parse(user_cipher);
+ if (saslc__list_parse(&list, user_cipher) == -1) {
+ saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
+ return -1;
+ }
cipher_mask = cipher_list_flags(list);
saslc__list_free(list);
}
@@ -1510,6 +1544,8 @@
if ((cipher_flags & F_CIPHER_RC4_40) != 0)
return CIPHER_RC4_40;
+ saslc__error_set(ERR(sess), ERROR_MECH,
+ "qop \"auth-conf\" requires a cipher");
return -1;
}
@@ -1555,7 +1591,7 @@
saslc__mech_digestmd5_parse_challenge(saslc_sess_t *sess, const char *challenge)
{
saslc__mech_digestmd5_sess_t *ms;
- list_t *l, *n;
+ list_t *list, *n;
list_t *tmp_list;
cdata_t *cdata;
size_t maxbuf;
@@ -1575,9 +1611,12 @@
rv = -1;
memset(cdata, 0, sizeof(*cdata));
- l = saslc__list_parse(challenge);
- saslc__list_log(l, "parse list:\n");
- for (n = l; n != NULL; n = n->next) {
+ if (saslc__list_parse(&list, challenge) == -1) {
+ saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
+ return -1;
+ }
+ saslc__list_log(list, "parse list:\n");
+ for (n = list; n != NULL; n = n->next) {
char *key;
char *val;
@@ -1641,7 +1680,8 @@
/* no option, it should abort the authentication */
/* exchange. */
/**************************************************/
- tmp_list = saslc__list_parse(val);
+ if (saslc__list_parse(&tmp_list, val) == -1)
+ goto no_mem;
saslc__list_log(tmp_list, "qop list:\n");
tmp_flags = saslc__mech_qop_list_flags(tmp_list);
saslc__list_free(tmp_list);
@@ -1752,7 +1792,8 @@
/* no option, it should abort the authentication */
/* exchange. */
/**************************************************/
- tmp_list = saslc__list_parse(val);
+ if (saslc__list_parse(&tmp_list, val) == -1)
+ goto no_mem;
saslc__list_log(tmp_list, "cipher list:\n");
tmp_flags = cipher_list_flags(tmp_list);
saslc__list_free(tmp_list);
@@ -1812,7 +1853,7 @@
rv = 0;
out:
- saslc__list_free(l);
+ saslc__list_free(list);
return rv;
no_mem:
saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
@@ -1922,17 +1963,12 @@
rdata = &ms->rdata;
if ((rv = choose_qop(sess, cdata->qop_flags)) == -1)
- return -1;
-
+ return -1; /* error message already set */
ms->mech_sess.qop = rv;
if (ms->mech_sess.qop == QOP_CONF) {
- rv = choose_cipher(sess, cdata->cipher_flags);
- if (rv == -1) {
- saslc__error_set(ERR(sess), ERROR_MECH,
- "qop \"auth-conf\" requires a cipher");
- return -1;
- }
+ if ((rv = choose_cipher(sess, cdata->cipher_flags)) == -1)
+ return -1; /* error message already set */
rdata->cipher = rv;
}
@@ -1944,11 +1980,8 @@
}
rdata->realm = choose_realm(sess, hostname, cdata->realm);
- if (rdata->realm == NULL) {
- saslc__error_set(ERR(sess), ERROR_MECH,
- "cannot determine the realm");
- return -1;
- }
+ if (rdata->realm == NULL)
+ return -1; /* error message already set */
rdata->digesturi = saslc__mech_digestmd5_digesturi(sess, hostname);
if (rdata->digesturi == NULL)
@@ -1991,8 +2024,11 @@
{
const char *cnonce;
cnonce = saslc_sess_getprop(sess, SASLC_DIGESTMD5_CNONCE);
- if (cnonce != NULL)
+ if (cnonce != NULL) {
rdata->cnonce = strdup(cnonce);
+ if (rdata->cnonce == NULL)
+ goto no_mem;
+ }
}
#endif
if (ms->mech_sess.qop != QOP_NONE) {
@@ -2012,7 +2048,6 @@
no_mem:
saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
return -1;
-
}
/**
Index: src/crypto/external/bsd/libsaslc/dist/src/mech_gssapi.c
diff -u src/crypto/external/bsd/libsaslc/dist/src/mech_gssapi.c:1.5 src/crypto/external/bsd/libsaslc/dist/src/mech_gssapi.c:1.6
--- src/crypto/external/bsd/libsaslc/dist/src/mech_gssapi.c:1.5 Sat Feb 12 18:21:32 2011
+++ src/crypto/external/bsd/libsaslc/dist/src/mech_gssapi.c Sat Feb 19 20:59:46 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mech_gssapi.c,v 1.5 2011/02/12 23:21:32 christos Exp $ */
+/* $NetBSD: mech_gssapi.c,v 1.6 2011/02/20 01:59:46 christos Exp $ */
/* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -35,7 +35,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: mech_gssapi.c,v 1.5 2011/02/12 23:21:32 christos Exp $");
+__RCSID("$NetBSD: mech_gssapi.c,v 1.6 2011/02/20 01:59:46 christos Exp $");
#include <assert.h>
#include <errno.h>
@@ -53,7 +53,6 @@
#include "msg.h"
#include "saslc_private.h"
-
/* See RFC 2222 section 7.2.1. */
/* properties */
@@ -643,7 +642,10 @@
qop_flags &= DEFAULT_QOP_MASK;
user_qop = saslc_sess_getprop(sess, SASLC_GSSAPI_QOPMASK);
if (user_qop != NULL) {
- list = saslc__list_parse(user_qop);
+ if (saslc__list_parse(&list, user_qop) == -1) {
+ saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
+ return -1;
+ }
qop_flags &= saslc__mech_qop_list_flags(list);
saslc__list_free(list);
}
Index: src/crypto/external/bsd/libsaslc/dist/src/xsess.c
diff -u src/crypto/external/bsd/libsaslc/dist/src/xsess.c:1.5 src/crypto/external/bsd/libsaslc/dist/src/xsess.c:1.6
--- src/crypto/external/bsd/libsaslc/dist/src/xsess.c:1.5 Sat Feb 12 18:21:32 2011
+++ src/crypto/external/bsd/libsaslc/dist/src/xsess.c Sat Feb 19 20:59:46 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: xsess.c,v 1.5 2011/02/12 23:21:32 christos Exp $ */
+/* $NetBSD: xsess.c,v 1.6 2011/02/20 01:59:46 christos Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: xsess.c,v 1.5 2011/02/12 23:21:32 christos Exp $");
+__RCSID("$NetBSD: xsess.c,v 1.6 2011/02/20 01:59:46 christos Exp $");
#include <assert.h>
#include <saslc.h>
@@ -95,6 +95,11 @@
}
}
+/**
+ * @brief get the security flags from a comma delimited string.
+ * @param sec_opt the security option comman delimited string.
+ * @return the flags on success, or -1 on error (no memory).
+ */
static int
get_security_flags(const char *sec_opts)
{
@@ -109,6 +114,7 @@
list_t *list;
char *opts;
uint32_t flags;
+ int rv;
if (sec_opts == NULL)
return 0;
@@ -117,11 +123,10 @@
return -1;
normalize_list_string(opts);
- list = saslc__list_parse(opts);
+ rv = saslc__list_parse(&list, opts);
free(opts);
- if (list == NULL)
+ if (rv == -1)
return -1;
-
flags = saslc__list_flags(list, flag_tbl);
saslc__list_free(list);
return flags;
@@ -176,32 +181,27 @@
int rv;
rv = get_security_flags(sec_opts);
- if (rv == -1) {
- saslc__error_set_errno(ERR(ctx), ERROR_NOMEM);
- return NULL;
- }
+ if (rv == -1)
+ goto nomem;
flags = rv;
sec_opts = saslc__dict_get(ctx->prop, SASLC_PROP_SECURITY);
if (sec_opts != NULL) {
rv = get_security_flags(sec_opts);
- if (rv == -1) {
- saslc__error_set_errno(ERR(ctx), ERROR_NOMEM);
- return NULL;
- }
+ if (rv == -1)
+ goto nomem;
flags |= rv;
}
- if ((tmpstr = strdup(mechs)) == NULL) {
- saslc__error_set_errno(ERR(ctx), ERROR_NOMEM);
- return NULL;
- }
+ if ((tmpstr = strdup(mechs)) == NULL)
+ goto nomem;
+
normalize_list_string(tmpstr);
- list = saslc__list_parse(tmpstr);
+ rv = saslc__list_parse(&list, tmpstr);
free(tmpstr);
- if (list == NULL) {
- saslc__error_set_errno(ERR(ctx), ERROR_NOMEM);
- return NULL;
- }
+ if (rv == -1)
+ goto nomem;
+
+ m = NULL;
for (l = list; l != NULL; l = l->next) {
m = saslc__mech_list_get(ctx->mechanisms, l->value);
if (mechanism_flags_OK(m, flags))
@@ -209,7 +209,15 @@
}
saslc__list_free(list);
- return m != NULL ? m->mech : NULL;
+ if (m == NULL) {
+ saslc__error_set(ERR(ctx), ERROR_MECH,
+ "mechanism not supported");
+ return NULL;
+ }
+ return m->mech;
+ nomem:
+ saslc__error_set_errno(ERR(ctx), ERROR_NOMEM);
+ return NULL;
}
/**
@@ -234,11 +242,8 @@
/* mechanism initialization */
if ((sess->mech = saslc__sess_choose_mech(ctx, mechs, sec_opts))
- == NULL) {
- saslc__error_set(ERR(ctx), ERROR_MECH,
- "mechanism is not supported");
+ == NULL)
goto error;
- }
/* XXX: special early check of mechanism dictionary for debug flag */
m = saslc__mech_list_get(ctx->mechanisms, sess->mech->name);
@@ -264,8 +269,7 @@
saslc__msg_dbg("mechanism: %s\n", saslc_sess_getmech(sess));
return sess;
-
-error:
+ error:
free(sess);
return NULL;
}