Add SASL client support using the libsaslc(3) library.

From Anon Ymous
This commit is contained in:
christos 2011-02-12 19:07:08 +00:00
parent e43cceb285
commit 18b1a8268b
6 changed files with 386 additions and 7 deletions

View File

@ -1,20 +1,33 @@
# $NetBSD: Makefile.inc,v 1.2 2009/06/25 18:21:50 tron Exp $
# $NetBSD: Makefile.inc,v 1.3 2011/02/12 19:07:08 christos Exp $
.include <bsd.own.mk>
USE_FORT?= yes # network client and server
HAVE_LIB_SASLC?= yes
WARNS?= 0
PFIX_DISTDIR= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist
CPPFLAGS+= -DNETBSD4 -DUSE_SASL_AUTH -DDEF_SERVER_SASL_TYPE=\"dovecot\" \
CPPFLAGS+= -DNETBSD4 -DUSE_SASL_AUTH \
-I${DIST} \
-I${PFIX_DISTDIR}/src/dns -I${PFIX_DISTDIR}/src/global \
-I${PFIX_DISTDIR}/src/master -I${PFIX_DISTDIR}/src/util \
-I${PFIX_DISTDIR}/src/tls -I${PFIX_DISTDIR}/src/milter \
-I${PFIX_DISTDIR}/src/xsasl
.if defined(HAVE_LIB_SASLC)
CPPFLAGS+= -DUSE_SASL_AUTH -DUSE_SASLC_SASL
LDADD+= -lsaslc
.elif defined(HAVE_CYRUS_SASL)
CPPFLAGS+= -DUSE_SASL_AUTH -DUSE_CYRUS_SASL \
-DDEF_SERVER_SASL_TYPE=\"cyrus\" \
-I/usr/pkg/include/sasl
LDADD+= -lsasl2 -L/usr/pkg/lib -Wl,-R/usr/pkg/lib
.else
CPPFLAGS+= -DDEF_SERVER_SASL_TYPE=\"dovecot\"
.endif
.if defined(HAVE_PCC)
# code uses gcc-specific aggregate dynamic array
CPPFLAGS+= -DCANT_USE_SEND_RECV_MSG

View File

@ -162,6 +162,8 @@ case "$SYSTEM.$RELEASE" in
;;
NetBSD.4*) SYSTYPE=NETBSD4
;;
NetBSD.5*) SYSTYPE=NETBSD5
;;
BSD/OS.2*) SYSTYPE=BSDI2
;;
BSD/OS.3*) SYSTYPE=BSDI3

View File

@ -1,4 +1,4 @@
/* $NetBSD: xsasl_client.c,v 1.1.1.1 2009/06/23 10:09:02 tron Exp $ */
/* $NetBSD: xsasl_client.c,v 1.2 2011/02/12 19:07:09 christos Exp $ */
/*++
/* NAME
@ -199,6 +199,7 @@
#include <xsasl.h>
#include <xsasl_cyrus.h>
#include <xsasl_saslc.h>
/*
* Lookup table for available SASL client implementations.
@ -210,9 +211,12 @@ typedef struct {
static const XSASL_CLIENT_IMPL_INFO client_impl_info[] = {
#ifdef XSASL_TYPE_CYRUS
XSASL_TYPE_CYRUS, xsasl_cyrus_client_init,
{ XSASL_TYPE_CYRUS, xsasl_cyrus_client_init },
#endif
0,
#ifdef XSASL_TYPE_SASLC
{ XSASL_TYPE_SASLC, xsasl_saslc_client_init },
#endif
{ NULL, NULL }
};
/* xsasl_client_init - look up client implementation by name */

View File

@ -0,0 +1,43 @@
/* $NetBSD: xsasl_saslc.h,v 1.1 2011/02/12 19:07:09 christos Exp $ */
#ifndef _XSASL_SASLC_H_INCLUDED_
#define _XSASL_SASLC_H_INCLUDED_
/*++
/* NAME
/* xsasl_saslc 3h
/* SUMMARY
/* Saslc SASL plug-in
/* SYNOPSIS
/* #include <xsasl_saslc.h>
/* DESCRIPTION
/* .nf
/*
* XSASL library.
*/
#include "xsasl.h"
#if defined(USE_SASL_AUTH) && defined(USE_SASLC_SASL)
/*
* SASL protocol interface
*/
#define XSASL_TYPE_SASLC "saslc"
extern XSASL_CLIENT_IMPL *xsasl_saslc_client_init(const char *, const char *);
#endif
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
#endif /* _XSASL_SASLC_H_INCLUDED_ */

View File

@ -0,0 +1,317 @@
/* $NetBSD: xsasl_saslc_client.c,v 1.1 2011/02/12 19:07:09 christos Exp $ */
/*++
/* NAME
/* xsasl_saslc_client 3
/* SUMMARY
/* saslc SASL client-side plug-in
/* SYNOPSIS
/* #include <xsasl_saslc_client.h>
/*
/* XSASL_CLIENT_IMPL *xsasl_saslc_client_init(client_type, path_info)
/* const char *client_type;
/* DESCRIPTION
/* This module implements the saslc SASL client-side authentication
/* plug-in.
/*
/* xsasl_saslc_client_init() initializes the saslc SASL library and
/* returns an implementation handle that can be used to generate
/* SASL client instances.
/*
/* Arguments:
/* .IP client_type
/* The plug-in SASL client type (saslc). This argument is
/* ignored, but it could be used when one implementation
/* provides multiple variants.
/* .IP path_info
/* Implementation-specific information to specify the location
/* of a configuration file, rendez-vous point, etc. This
/* information is ignored by the saslc SASL client plug-in.
/* DIAGNOSTICS
/* Fatal: out of memory.
/*
/* Panic: interface violation.
/*
/* Other: the routines log a warning and return an error result
/* as specified in xsasl_client(3).
/* SEE ALSO
/* xsasl_client(3) Client API
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Original author:
/* Till Franke
/* SuSE Rhein/Main AG
/* 65760 Eschborn, Germany
/*
/* Adopted by:
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
#if defined(USE_SASL_AUTH) && defined(USE_SASLC_SASL)
/*
* System headers.
*/
#include <errno.h>
#include <saslc.h>
#include <stdlib.h>
#include <string.h>
#include "sys_defs.h"
/*
* Utility library
*/
#include "msg.h"
#include "mymalloc.h"
#include "stringops.h"
/*
* Global library
*/
#include "mail_params.h"
/*
* Application-specific
*/
#include "xsasl.h"
#include "xsasl_saslc.h"
#define XSASL_SASLC_APPNAME "postfix" /* The config files are in
/etc/saslc.d/<appname>/ */
typedef struct {
XSASL_CLIENT_IMPL xsasl; /* generic members, must be first */
saslc_t *saslc; /* saslc context */
} XSASL_SASLC_CLIENT_IMPL;
typedef struct {
XSASL_CLIENT xsasl; /* generic members, must be first */
saslc_t *saslc; /* saslc context */
saslc_sess_t *sess; /* session context */
const char *service; /* service (smtp) */
const char *hostname; /* server host name */
const char *sec_opts; /* security options */
} XSASL_SASLC_CLIENT;
static XSASL_CLIENT *xsasl_saslc_client_create(XSASL_CLIENT_IMPL *,
XSASL_CLIENT_CREATE_ARGS *);
static int xsasl_saslc_client_first(XSASL_CLIENT *, const char *,
const char *, const char *, const char **, VSTRING *);
static int xsasl_saslc_client_next(XSASL_CLIENT *, const char *,
VSTRING *);
static void xsasl_saslc_client_done(XSASL_CLIENT_IMPL *);
static void xsasl_saslc_client_free(XSASL_CLIENT *);
static void
setprop(saslc_sess_t *sess, int overwrite, const char *key, const char *value)
{
if (overwrite != 0 ||
saslc_sess_getprop(sess, key) == NULL)
saslc_sess_setprop(sess, key, value);
}
/*
* Run authentication protocol: first step.
*/
static int
xsasl_saslc_client_first(
XSASL_CLIENT *xp,
const char *mechanism_list,
const char *username,
const char *password,
const char **mechanism,
VSTRING *init_resp)
{
XSASL_SASLC_CLIENT *client = (XSASL_SASLC_CLIENT *)xp;
const char *mech;
void *out;
size_t outlen;
int rv;
if (msg_verbose) {
msg_info("%s: mechanism_list='%s'", __func__, mechanism_list);
msg_info("%s: username='%s'", __func__, username);
/* msg_info("%s: password='%s'", __func__, password); */
}
client->sess = saslc_sess_init(client->saslc, mechanism_list,
client->sec_opts);
if (client->sess == NULL) {
msg_info("%s: saslc_sess_init failed", __func__);
return XSASL_AUTH_FAIL;
}
mech = saslc_sess_getmech(client->sess);
if (mechanism)
*mechanism = mech;
if (msg_verbose)
msg_info("%s: mechanism='%s'", __func__, mech);
setprop(client->sess, 0, SASLC_PROP_AUTHCID, username);
setprop(client->sess, 1, SASLC_PROP_PASSWD, password);
setprop(client->sess, 1, SASLC_PROP_SERVICE, client->service);
setprop(client->sess, 1, SASLC_PROP_HOSTNAME, client->hostname);
setprop(client->sess, 1, SASLC_PROP_BASE64IO, "true");
setprop(client->sess, 0, SASLC_PROP_QOPMASK, "auth");
if ((rv = saslc_sess_cont(client->sess, NULL, 0, &out, &outlen))
== -1) {
msg_info("%s: saslc_sess_encode='%s'", __func__,
saslc_sess_strerror(client->sess));
return XSASL_AUTH_FAIL;
}
vstring_strcpy(init_resp, outlen ? out : "");
if (msg_verbose)
msg_info("%s: client_reply='%s'", __func__, outlen ? out : "");
if (outlen > 0)
memset(out, 0, outlen); /* XXX: silly? */
if (out != NULL)
free (out);
return XSASL_AUTH_OK;
}
/*
* Continue authentication.
*/
static int
xsasl_saslc_client_next(XSASL_CLIENT *xp, const char *server_reply,
VSTRING *client_reply)
{
XSASL_SASLC_CLIENT *client;
void *out;
size_t outlen;
client = (XSASL_SASLC_CLIENT *)xp;
if (msg_verbose)
msg_info("%s: server_reply='%s'", __func__, server_reply);
if (saslc_sess_cont(client->sess, server_reply, strlen(server_reply),
&out, &outlen) == -1) {
msg_info("%s: saslc_sess_encode='%s'", __func__,
saslc_sess_strerror(client->sess));
return XSASL_AUTH_FAIL;
}
vstring_strcpy(client_reply, outlen ? out : "");
if (msg_verbose)
msg_info("%s: client_reply='%s'", __func__,
outlen ? out : "");
if (outlen > 0)
memset(out, 0, outlen); /* XXX: silly? */
if (out != NULL)
free (out);
return XSASL_AUTH_OK;
}
/*
* Per-session cleanup.
*/
void
xsasl_saslc_client_free(XSASL_CLIENT *xp)
{
XSASL_SASLC_CLIENT *client;
client = (XSASL_SASLC_CLIENT *)xp;
if (client->sess)
saslc_sess_end(client->sess);
myfree((char *)client);
}
/*
* Per-session SASL initialization.
*/
XSASL_CLIENT *
xsasl_saslc_client_create(XSASL_CLIENT_IMPL *impl,
XSASL_CLIENT_CREATE_ARGS *args)
{
XSASL_SASLC_CLIENT_IMPL *xp;
XSASL_SASLC_CLIENT *client;
xp = (XSASL_SASLC_CLIENT_IMPL *)impl;
if (msg_verbose) {
msg_info("%s: service='%s'", __func__, args->service);
msg_info("%s: server_name='%s'", __func__, args->server_name);
msg_info("%s: security_options='%s'", __func__,
args->security_options);
}
/* NB: mymalloc never returns NULL, it calls _exit(3) instead */
client = (XSASL_SASLC_CLIENT *)mymalloc(sizeof(*client));
client->xsasl.free = xsasl_saslc_client_free;
client->xsasl.first = xsasl_saslc_client_first;
client->xsasl.next = xsasl_saslc_client_next;
client->saslc = xp->saslc;
/* XXX: should these be strdup()ed? */
client->service = args->service;
client->hostname = args->server_name;
client->sec_opts = args->security_options;
return &client->xsasl;
}
/*
* Dispose of implementation.
*/
static void
xsasl_saslc_client_done(XSASL_CLIENT_IMPL *impl)
{
XSASL_SASLC_CLIENT_IMPL *xp;
xp = (XSASL_SASLC_CLIENT_IMPL *)impl;
if (xp->saslc) {
saslc_end(xp->saslc);
xp->saslc = NULL; /* XXX: unnecessary as freeing impl */
}
myfree((char *)impl);
}
/*
* Initialize saslc SASL library.
*/
XSASL_CLIENT_IMPL *
xsasl_saslc_client_init(const char *client_type, const char *path_info)
{
XSASL_SASLC_CLIENT_IMPL *xp;
/* XXX: This should be unnecessary! */
if (strcmp(client_type, XSASL_TYPE_SASLC) != 0) {
msg_info("%s: invalid client_type: '%s'", __func__,
client_type);
return NULL;
}
if (msg_verbose) {
msg_info("%s: client_type='%s'", __func__, client_type);
msg_info("%s: path_info='%s'", __func__, path_info);
}
/* NB: mymalloc() never returns NULL, it calls _exit(3) instead */
xp = (XSASL_SASLC_CLIENT_IMPL *)mymalloc(sizeof(*xp));
xp->xsasl.create = xsasl_saslc_client_create;
xp->xsasl.done = xsasl_saslc_client_done;
/* NB: msg_fatal() exits the program immediately after printing */
if ((xp->saslc = saslc_alloc()) == NULL)
msg_fatal("%s: saslc_alloc failed: %s", __func__,
strerror(errno));
if (saslc_init(xp->saslc, XSASL_SASLC_APPNAME, path_info) == -1)
msg_fatal("%s: saslc_init failed: %s", __func__,
saslc_strerror(xp->saslc));
return &xp->xsasl;
}
#endif /* defined(USE_SASL_AUTH) && defined(USE_SASLC_SASL) */

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.1 2009/06/25 18:21:53 tron Exp $
# $NetBSD: Makefile,v 1.2 2011/02/12 19:07:09 christos Exp $
LIBISPRIVATE= yes
@ -11,6 +11,6 @@ DIST= ${NETBSDSRCDIR}/external/ibm-public/postfix/dist/src/${LIB}
SRCS= xsasl_server.c xsasl_cyrus_server.c xsasl_cyrus_log.c \
xsasl_cyrus_security.c xsasl_client.c xsasl_cyrus_client.c \
xsasl_dovecot_server.c
xsasl_dovecot_server.c xsasl_saslc_client.c
.include <bsd.lib.mk>