sasl.c revision 243649
10SN/A/*
22509Sihse * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
30SN/A *	All rights reserved.
40SN/A *
50SN/A * By using this file, you agree to the terms and conditions set
60SN/A * forth in the LICENSE file which can be found at the top level of
7180SN/A * the sendmail distribution.
80SN/A *
9180SN/A */
100SN/A
110SN/A#include <sm/gen.h>
120SN/ASM_RCSID("@(#)$Id: sasl.c,v 8.22 2006/08/15 23:24:57 ca Exp $")
130SN/A
140SN/A#if SASL
150SN/A# include <stdlib.h>
160SN/A# include <sendmail.h>
170SN/A# include <errno.h>
180SN/A
190SN/A/*
200SN/A**  In order to ensure that storage leaks are tracked, and to prevent
21180SN/A**  conflicts between the sm_heap package and sasl, we tell sasl to
22180SN/A**  use the following heap allocation functions.  Unfortunately,
23180SN/A**  the sasl package incorrectly specifies the size of a block
240SN/A**  using unsigned long: for portability, it should be size_t.
250SN/A*/
261410Sihse
271410Sihse#if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a
281410Sihse#define SM_SASL_SIZE_T	size_t
291410Sihse#else /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */
301410Sihse#define SM_SASL_SIZE_T	unsigned long
311410Sihse#endif /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */
32910SN/A
33910SN/Avoid *sm_sasl_malloc __P((SM_SASL_SIZE_T));
341410Sihsestatic void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T));
355SN/Astatic void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T));
36910SN/Avoid sm_sasl_free __P((void *));
371410Sihse
38910SN/A/*
39338SN/A**  SASLv1:
401426Sihse**  We can't use an rpool for Cyrus-SASL memory management routines,
411410Sihse**	since the encryption/decryption routines in Cyrus-SASL
421426Sihse**	allocate/deallocate a buffer each time. Since rpool
431410Sihse**	don't release memory until the very end, memory consumption is
441410Sihse**	proportional to the size of an e-mail, which is unacceptable.
451426Sihse*/
461426Sihse
47311SN/A/*
481426Sihse**  SM_SASL_MALLOC -- malloc() for SASL
491426Sihse**
501426Sihse**	Parameters:
511410Sihse**		size -- size of requested memory.
521426Sihse**
531651Sihse**	Returns:
542509Sihse**		pointer to memory.
551120SN/A*/
561410Sihse
571410Sihsevoid *
581410Sihsesm_sasl_malloc(size)
591426Sihse	SM_SASL_SIZE_T size;
601426Sihse{
611426Sihse	return sm_malloc((size_t) size);
621426Sihse}
631426Sihse
641426Sihse/*
651426Sihse**  SM_SASL_CALLOC -- calloc() for SASL
661426Sihse**
671426Sihse**	Parameters:
681426Sihse**		nelem -- number of elements.
692475Sihse**		elemsize -- size of each element.
701426Sihse**
711426Sihse**	Returns:
721426Sihse**		pointer to memory.
731426Sihse**
741426Sihse**	Notice:
751426Sihse**		this isn't currently used by SASL.
761426Sihse*/
771426Sihse
781426Sihsestatic void *
791426Sihsesm_sasl_calloc(nelem, elemsize)
801426Sihse	SM_SASL_SIZE_T nelem;
811426Sihse	SM_SASL_SIZE_T elemsize;
821426Sihse{
831426Sihse	size_t size;
841426Sihse	void *p;
851426Sihse
861426Sihse	size = (size_t) nelem * (size_t) elemsize;
871426Sihse	p = sm_malloc(size);
881426Sihse	if (p == NULL)
891426Sihse		return NULL;
901426Sihse	memset(p, '\0', size);
911426Sihse	return p;
921426Sihse}
931426Sihse
941426Sihse/*
951426Sihse**  SM_SASL_REALLOC -- realloc() for SASL
961426Sihse**
971426Sihse**	Parameters:
981426Sihse**		p -- pointer to old memory.
991426Sihse**		size -- size of requested memory.
1001426Sihse**
1011426Sihse**	Returns:
1021426Sihse**		pointer to new memory.
1031426Sihse*/
1041426Sihse
1051426Sihsestatic void *
1061426Sihsesm_sasl_realloc(o, size)
1071426Sihse	void *o;
1081426Sihse	SM_SASL_SIZE_T size;
1091426Sihse{
1101426Sihse	return sm_realloc(o, (size_t) size);
1111426Sihse}
1121426Sihse
1131426Sihse/*
1141426Sihse**  SM_SASL_FREE -- free() for SASL
1151426Sihse**
1161426Sihse**	Parameters:
1171426Sihse**		p -- pointer to free.
1181426Sihse**
1191426Sihse**	Returns:
1201426Sihse**		none
1211426Sihse*/
1221426Sihse
1231426Sihsevoid
1241410Sihsesm_sasl_free(p)
1251120SN/A	void *p;
1261426Sihse{
1271426Sihse	sm_free(p);
1281426Sihse}
1291426Sihse
1301426Sihse/*
1311426Sihse**  SM_SASL_INIT -- sendmail specific SASL initialization
1321426Sihse**
1331410Sihse**	Parameters:
1341426Sihse**		none.
1351426Sihse**
1361426Sihse**	Returns:
13727SN/A**		none
1381410Sihse**
1391410Sihse**	Side Effects:
1401701Sihse**		installs memory management routines for SASL.
1411701Sihse*/
1421701Sihse
1431410Sihsevoid
1441410Sihsesm_sasl_init()
1451410Sihse{
1461410Sihse	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
1471410Sihse		       sm_sasl_realloc, sm_sasl_free);
1481410Sihse}
1491410Sihse/*
1501426Sihse**  INTERSECT -- create the intersection between two lists
1511426Sihse**
1521410Sihse**	Parameters:
1531410Sihse**		s1, s2 -- lists of items (separated by single blanks).
1541410Sihse**		rpool -- resource pool from which result is allocated.
1551156SN/A**
1561120SN/A**	Returns:
1571936Sihse**		the intersection of both lists.
1581936Sihse*/
1591936Sihse
1602360Sihsechar *
1611426Sihseintersect(s1, s2, rpool)
1621426Sihse	char *s1, *s2;
1631426Sihse	SM_RPOOL_T *rpool;
1641410Sihse{
16527SN/A	char *hr, *h1, *h, *res;
1661426Sihse	int l1, l2, rl;
1671426Sihse
1681426Sihse	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
1691426Sihse		return NULL;
1701426Sihse	l1 = strlen(s1);
1711426Sihse	l2 = strlen(s2);
1721651Sihse	rl = SM_MIN(l1, l2);
1731651Sihse	res = (char *) sm_rpool_malloc(rpool, rl + 1);
1741915Sihse	if (res == NULL)
1751651Sihse		return NULL;
1761651Sihse	*res = '\0';
1771651Sihse	if (rl == 0)	/* at least one string empty? */
1781651Sihse		return res;
1791426Sihse	hr = res;
1801426Sihse	h1 = s1;
1811426Sihse	h = s1;
1821426Sihse
1831651Sihse	/* walk through s1 */
1841426Sihse	while (h != NULL && *h1 != '\0')
1851410Sihse	{
1861410Sihse		/* is there something after the current word? */
1871410Sihse		if ((h = strchr(h1, ' ')) != NULL)
1881651Sihse			*h = '\0';
1891410Sihse		l1 = strlen(h1);
1901426Sihse
1911651Sihse		/* does the current word appear in s2 ? */
1921651Sihse		if (iteminlist(h1, s2, " ") != NULL)
1931651Sihse		{
1941651Sihse			/* add a blank if not first item */
1951651Sihse			if (hr != res)
1961651Sihse				*hr++ = ' ';
1971651Sihse
1981651Sihse			/* copy the item */
1991651Sihse			memcpy(hr, h1, l1);
2001651Sihse
2011651Sihse			/* advance pointer in result list */
2021651Sihse			hr += l1;
2031651Sihse			*hr = '\0';
2041651Sihse		}
2051410Sihse		if (h != NULL)
2061410Sihse		{
2071410Sihse			/* there are more items */
2081410Sihse			*h = ' ';
2090SN/A			h1 = h + 1;
2101426Sihse		}
2111410Sihse	}
2121410Sihse	return res;
2131410Sihse}
2141410Sihse# if SASL >= 20000
2151410Sihse/*
2161410Sihse**  IPTOSTRING -- create string for SASL_IP*PORT property
2171410Sihse**		(borrowed from lib/iptostring.c in Cyrus-IMAP)
2181410Sihse**
2191410Sihse**	Parameters:
2201426Sihse**		addr -- (pointer to) socket address
2211426Sihse**		addrlen -- length of socket address
2221426Sihse**		out -- output string (result)
2231426Sihse**		outlen -- maximum length of output string
2241426Sihse**
2251426Sihse**	Returns:
2261426Sihse**		true iff successful.
2271426Sihse**
2281651Sihse**	Side Effects:
2291651Sihse**		creates output string if successful.
2301651Sihse**		sets errno if unsuccessful.
2311410Sihse*/
2321862Serikj
2331862Serikj#  include <arpa/inet.h>
2341410Sihse
2351410Sihse#  ifndef NI_MAXHOST
2361410Sihse#   define NI_MAXHOST	1025
2371410Sihse#  endif
2381410Sihse#  ifndef NI_MAXSERV
2391410Sihse#   define NI_MAXSERV	32
2401426Sihse#  endif
2411426Sihse
2421426Sihsebool
2431426Sihseiptostring(addr, addrlen, out, outlen)
2441426Sihse	SOCKADDR *addr;
2451426Sihse	SOCKADDR_LEN_T addrlen;
2461426Sihse	char *out;
2471426Sihse	unsigned outlen;
2481426Sihse{
2491426Sihse	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
2501426Sihse#  if NETINET6
2511426Sihse	int niflags;
2521426Sihse#  endif /* NETINET6 */
2531327SN/A
2542509Sihse	if (addr == NULL || out == NULL)
2552509Sihse	{
2562509Sihse		errno = EINVAL;
2572509Sihse		return false;
2582509Sihse	}
2591628Sihse
2601628Sihse#  if NETINET6
2611628Sihse	niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
2621410Sihse#   ifdef NI_WITHSCOPEID
2631410Sihse	if (addr->sa.sa_family == AF_INET6)
2641410Sihse		niflags |= NI_WITHSCOPEID;
2651410Sihse#   endif /* NI_WITHSCOPEID */
2661410Sihse	if (getnameinfo((struct sockaddr *) addr, addrlen,
2671410Sihse			hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
2681410Sihse		return false;
2691410Sihse#  else /* NETINET6 */
2701410Sihse	if (addr->sa.sa_family != AF_INET)
2711426Sihse	{
2721426Sihse		errno = EINVAL;
2731426Sihse		return false;
2741410Sihse	}
2751651Sihse	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
2762034Serikj	    >= sizeof(hbuf))
2772034Serikj	{
2782034Serikj		errno = ENOMEM;
2792034Serikj		return false;
2802034Serikj	}
2811426Sihse	sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
2822034Serikj#  endif /* NETINET6 */
2831410Sihse
2841410Sihse	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
2851410Sihse	{
2862360Sihse		errno = ENOMEM;
2871410Sihse		return false;
2880SN/A	}
2891426Sihse	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
2901426Sihse	return true;
2911426Sihse}
2921623Sihse# endif /* SASL >= 20000 */
2931862Serikj#endif /* SASL */
2941426Sihse