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;
 }

Reply via email to