Add SASL client support using the libsaslc(3) library.
From Anon Ymous
This commit is contained in:
parent
e43cceb285
commit
18b1a8268b
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_ */
|
|
@ -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) */
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue