/*
* Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: sasl-common.c,v 1.19 2007/07/28 16:45:03 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/net.h"
#include "sm/sasl.h"
#include "sm/io.h"
#if MTA_USE_SASL
static sasl_callback_t srvcallbacks[] =
{
#if 0
{ SASL_CB_VERIFYFILE, &safesaslfile, NULL },
{ SASL_CB_PROXY_POLICY, &proxy_policy, NULL },
#endif
{ SASL_CB_LIST_END, NULL, NULL }
};
#if !HAVE_SASL_VERSION_INFO
void sasl_version_info(const char **implementation,
const char **version_string,
int *version_major,
int *version_minor,
int *version_step,
int *version_patch)
{
int v;
sasl_version(implementation, &v);
if (version_major != NULL)
*version_major = (v >> 24) & 0xff;
if (version_minor != NULL)
*version_minor = (v >> 16) & 0xff;
if (version_step != NULL)
*version_step = v & 0xffff;
if (version_patch != NULL)
*version_patch = 0;
}
#endif
/*
** SM_SASLVERSIONOK -- check Cyrus SASL version
**
** Parameters:
** none
**
** Returns:
** usual sm_error code.
*/
sm_ret_T
sm_saslversionok(void)
{
int version_major, version_minor, version_step;
sasl_version_info(NULL, NULL, &version_major, &version_minor,
&version_step, NULL);
if (SASL_VERSION_MAJOR == version_major &&
SASL_VERSION_MINOR == version_minor &&
SASL_VERSION_STEP == version_step)
return SM_SUCCESS;
else
return sm_error_perm(SM_EM_SASL, SM_E_VER_MIX);
}
/*
** SM_SASLVERSIONPRT -- show Cyrus SASL version
**
** Parameters:
** fp -- file for output
**
** Returns:
** usual sm_error code.
*/
sm_ret_T
sm_saslversionprt(sm_file_T *fp)
{
const char *implementation, *version_string;
int version_major, version_minor, version_step, version_patch;
sasl_version_info(&implementation, &version_string,
&version_major, &version_minor,
&version_step, &version_patch);
sm_io_fprintf(fp,
"%s versions:\n"
"compiled against: version=%d.%d.%d\n"
"linked against: version=%d.%d.%d\n"
#if 0
"implementation=%s, version=%s, patch=%d\n"
#endif
, implementation
, SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP
, version_major, version_minor, version_step
#if 0
, implementation, version_string, version_patch
#endif
);
return sm_saslversionok();
}
/*
** SM_SASL_INIT -- initialize SASL
**
** Parameters:
** server -- server side?
** flags -- (security) flags
** srvcbs -- server call backs
** lctx -- log context
** psasl_ctx -- (pointer to) SASL context (output)
**
** Returns:
** usual return code
*/
sm_ret_T
sm_sasl_init(bool server, uint32_t flags, sasl_callback_t *srvcbs, sm_log_ctx_P lctx, sm_sasl_ctx_P *psasl_ctx)
{
sm_ret_T ret;
sm_sasl_ctx_P sasl_ctx;
SM_REQUIRE(psasl_ctx != NULL);
ret = SM_SUCCESS;
*psasl_ctx = NULL;
sasl_ctx = sm_zalloc(sizeof(*sasl_ctx));
if (sasl_ctx == NULL)
return sm_err_temp(ENOMEM);
sasl_ctx->sm_sasl_sec_flags = flags;
sasl_ctx->sm_sasl_lctx = lctx;
#if 0
sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
sm_sasl_realloc, sm_sasl_free);
#endif
if (server)
ret = sasl_server_init((srvcbs != NULL) ? srvcbs : srvcallbacks
, "meta1");
*psasl_ctx = sasl_ctx;
return ret;
}
/*
** ITEMINLIST -- does item appear in list?
**
** Check whether item appears in list (which must be separated by a
** character in delim) as a "word", i.e. it must appear at the begin
** of the list or after a space, and it must end with a space or the
** end of the list.
**
** Parameters:
** item -- item to search.
** list -- list of items.
** delim -- list of delimiters.
**
** Returns:
** pointer to occurrence (NULL if not found).
*/
char *
iteminlist(const char *item, char *list, const char *delim)
{
char *s;
int len;
if (list == NULL || *list == '\0')
return NULL;
if (item == NULL || *item == '\0')
return NULL;
s = list;
len = strlen(item);
while (s != NULL && *s != '\0')
{
if (strncasecmp(s, item, len) == 0 &&
(s[len] == '\0' || strchr(delim, s[len]) != NULL))
return s;
s = strpbrk(s, delim);
if (s != NULL)
while (*++s == ' ')
continue;
}
return NULL;
}
/*
** SM_SASLMECHS -- get list of possible AUTH mechanisms
**
** Parameters:
** sasl_ctx -- meta1 SASL context
** conn -- SASL connection (context)
** mech_list -- list of allowed SASL mechanisms (output)
**
** Returns:
** number of mechs.
*/
sm_ret_T
sm_saslmechs(sm_sasl_ctx_P sasl_ctx, sasl_conn_t *conn, char **mech_list)
{
int len, num, result;
SM_REQUIRE(sasl_ctx != NULL);
SM_REQUIRE(mech_list != NULL);
SM_REQUIRE(conn != NULL);
/* "user" is currently unused */
result = sasl_listmech(conn, NULL, "", " ", "",
(const char **)mech_list,
(uint *)&len, &num);
if (result != SASL_OK)
num = 0;
if (num == 0)
{
*mech_list = NULL; /* be paranoid... */
if (!SM_IS_FLAG(sasl_ctx->sm_sasl_flags, SASL_FL_NOMECH))
{
sm_log_write(sasl_ctx->sm_sasl_lctx,
NULL, NULL, /* todo: create logging cat! */
SM_LOG_WARN, 9,
"sev=WARN, func=sm_saslmechs, status=no_mechanisms");
SM_SET_FLAG(sasl_ctx->sm_sasl_flags, SASL_FL_NOMECH);
}
}
return num;
}
#endif /* MTA_USE_SASL */
syntax highlighted by Code2HTML, v. 0.9.1