190792Sgshapiro/*
2261194Sgshapiro * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *	All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro *
990792Sgshapiro */
1090792Sgshapiro
1194334Sgshapiro#include <sm/gen.h>
12266527SgshapiroSM_RCSID("@(#)$Id: sasl.c,v 8.24 2013-11-22 20:51:56 ca Exp $")
1394334Sgshapiro
1490792Sgshapiro#if SASL
1590792Sgshapiro# include <stdlib.h>
1690792Sgshapiro# include <sendmail.h>
1790792Sgshapiro# include <errno.h>
1890792Sgshapiro
1990792Sgshapiro/*
2090792Sgshapiro**  In order to ensure that storage leaks are tracked, and to prevent
2190792Sgshapiro**  conflicts between the sm_heap package and sasl, we tell sasl to
2290792Sgshapiro**  use the following heap allocation functions.  Unfortunately,
23244833Sgshapiro**  older sasl packages incorrectly specifies the size of a block
2490792Sgshapiro**  using unsigned long: for portability, it should be size_t.
2590792Sgshapiro*/
2690792Sgshapiro
27244833Sgshapiro# if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a
28244833Sgshapiro#  define SM_SASL_SIZE_T	size_t
29363466Sgshapiro# else
30244833Sgshapiro#  define SM_SASL_SIZE_T	unsigned long
31363466Sgshapiro# endif
32243649Sume
33243649Sumevoid *sm_sasl_malloc __P((SM_SASL_SIZE_T));
34243649Sumestatic void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T));
35243649Sumestatic void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T));
3690792Sgshapirovoid sm_sasl_free __P((void *));
3790792Sgshapiro
3890792Sgshapiro/*
3998121Sgshapiro**  SASLv1:
4090792Sgshapiro**  We can't use an rpool for Cyrus-SASL memory management routines,
4190792Sgshapiro**	since the encryption/decryption routines in Cyrus-SASL
4290792Sgshapiro**	allocate/deallocate a buffer each time. Since rpool
4390792Sgshapiro**	don't release memory until the very end, memory consumption is
4490792Sgshapiro**	proportional to the size of an e-mail, which is unacceptable.
4590792Sgshapiro*/
4690792Sgshapiro
4790792Sgshapiro/*
4890792Sgshapiro**  SM_SASL_MALLOC -- malloc() for SASL
4990792Sgshapiro**
5090792Sgshapiro**	Parameters:
5190792Sgshapiro**		size -- size of requested memory.
5290792Sgshapiro**
5390792Sgshapiro**	Returns:
5490792Sgshapiro**		pointer to memory.
5590792Sgshapiro*/
5690792Sgshapiro
5790792Sgshapirovoid *
5890792Sgshapirosm_sasl_malloc(size)
59243649Sume	SM_SASL_SIZE_T size;
6090792Sgshapiro{
6190792Sgshapiro	return sm_malloc((size_t) size);
6290792Sgshapiro}
6390792Sgshapiro
6490792Sgshapiro/*
6590792Sgshapiro**  SM_SASL_CALLOC -- calloc() for SASL
6690792Sgshapiro**
6790792Sgshapiro**	Parameters:
6890792Sgshapiro**		nelem -- number of elements.
6990792Sgshapiro**		elemsize -- size of each element.
7090792Sgshapiro**
7190792Sgshapiro**	Returns:
7290792Sgshapiro**		pointer to memory.
7390792Sgshapiro**
7490792Sgshapiro**	Notice:
7590792Sgshapiro**		this isn't currently used by SASL.
7690792Sgshapiro*/
7790792Sgshapiro
7890792Sgshapirostatic void *
7990792Sgshapirosm_sasl_calloc(nelem, elemsize)
80243649Sume	SM_SASL_SIZE_T nelem;
81243649Sume	SM_SASL_SIZE_T elemsize;
8290792Sgshapiro{
8390792Sgshapiro	size_t size;
8490792Sgshapiro	void *p;
8590792Sgshapiro
8690792Sgshapiro	size = (size_t) nelem * (size_t) elemsize;
8790792Sgshapiro	p = sm_malloc(size);
8890792Sgshapiro	if (p == NULL)
8990792Sgshapiro		return NULL;
9090792Sgshapiro	memset(p, '\0', size);
9190792Sgshapiro	return p;
9290792Sgshapiro}
9390792Sgshapiro
9490792Sgshapiro/*
9590792Sgshapiro**  SM_SASL_REALLOC -- realloc() for SASL
9690792Sgshapiro**
9790792Sgshapiro**	Parameters:
9890792Sgshapiro**		p -- pointer to old memory.
9990792Sgshapiro**		size -- size of requested memory.
10090792Sgshapiro**
10190792Sgshapiro**	Returns:
10290792Sgshapiro**		pointer to new memory.
10390792Sgshapiro*/
10490792Sgshapiro
10590792Sgshapirostatic void *
10690792Sgshapirosm_sasl_realloc(o, size)
10790792Sgshapiro	void *o;
108243649Sume	SM_SASL_SIZE_T size;
10990792Sgshapiro{
11090792Sgshapiro	return sm_realloc(o, (size_t) size);
11190792Sgshapiro}
11290792Sgshapiro
11390792Sgshapiro/*
11490792Sgshapiro**  SM_SASL_FREE -- free() for SASL
11590792Sgshapiro**
11690792Sgshapiro**	Parameters:
11790792Sgshapiro**		p -- pointer to free.
11890792Sgshapiro**
11990792Sgshapiro**	Returns:
12090792Sgshapiro**		none
12190792Sgshapiro*/
12290792Sgshapiro
12390792Sgshapirovoid
12490792Sgshapirosm_sasl_free(p)
12590792Sgshapiro	void *p;
12690792Sgshapiro{
12790792Sgshapiro	sm_free(p);
12890792Sgshapiro}
12990792Sgshapiro
13090792Sgshapiro/*
13190792Sgshapiro**  SM_SASL_INIT -- sendmail specific SASL initialization
13290792Sgshapiro**
13390792Sgshapiro**	Parameters:
13490792Sgshapiro**		none.
13590792Sgshapiro**
13690792Sgshapiro**	Returns:
13790792Sgshapiro**		none
13890792Sgshapiro**
13990792Sgshapiro**	Side Effects:
14090792Sgshapiro**		installs memory management routines for SASL.
14190792Sgshapiro*/
14290792Sgshapiro
14390792Sgshapirovoid
14490792Sgshapirosm_sasl_init()
14590792Sgshapiro{
14690792Sgshapiro	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
14790792Sgshapiro		       sm_sasl_realloc, sm_sasl_free);
14890792Sgshapiro}
14990792Sgshapiro/*
15090792Sgshapiro**  INTERSECT -- create the intersection between two lists
15190792Sgshapiro**
15290792Sgshapiro**	Parameters:
15390792Sgshapiro**		s1, s2 -- lists of items (separated by single blanks).
15490792Sgshapiro**		rpool -- resource pool from which result is allocated.
15590792Sgshapiro**
15690792Sgshapiro**	Returns:
15790792Sgshapiro**		the intersection of both lists.
15890792Sgshapiro*/
15990792Sgshapiro
16090792Sgshapirochar *
16190792Sgshapirointersect(s1, s2, rpool)
16290792Sgshapiro	char *s1, *s2;
16390792Sgshapiro	SM_RPOOL_T *rpool;
16490792Sgshapiro{
16590792Sgshapiro	char *hr, *h1, *h, *res;
16690792Sgshapiro	int l1, l2, rl;
16790792Sgshapiro
16890792Sgshapiro	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
16990792Sgshapiro		return NULL;
17090792Sgshapiro	l1 = strlen(s1);
17190792Sgshapiro	l2 = strlen(s2);
17290792Sgshapiro	rl = SM_MIN(l1, l2);
17390792Sgshapiro	res = (char *) sm_rpool_malloc(rpool, rl + 1);
17490792Sgshapiro	if (res == NULL)
17590792Sgshapiro		return NULL;
17690792Sgshapiro	*res = '\0';
17790792Sgshapiro	if (rl == 0)	/* at least one string empty? */
17890792Sgshapiro		return res;
17990792Sgshapiro	hr = res;
18090792Sgshapiro	h1 = s1;
18190792Sgshapiro	h = s1;
18290792Sgshapiro
18390792Sgshapiro	/* walk through s1 */
18490792Sgshapiro	while (h != NULL && *h1 != '\0')
18590792Sgshapiro	{
18690792Sgshapiro		/* is there something after the current word? */
18790792Sgshapiro		if ((h = strchr(h1, ' ')) != NULL)
18890792Sgshapiro			*h = '\0';
18990792Sgshapiro		l1 = strlen(h1);
19090792Sgshapiro
19190792Sgshapiro		/* does the current word appear in s2 ? */
19290792Sgshapiro		if (iteminlist(h1, s2, " ") != NULL)
19390792Sgshapiro		{
19490792Sgshapiro			/* add a blank if not first item */
19590792Sgshapiro			if (hr != res)
19690792Sgshapiro				*hr++ = ' ';
19790792Sgshapiro
19890792Sgshapiro			/* copy the item */
19990792Sgshapiro			memcpy(hr, h1, l1);
20090792Sgshapiro
20190792Sgshapiro			/* advance pointer in result list */
20290792Sgshapiro			hr += l1;
20390792Sgshapiro			*hr = '\0';
20490792Sgshapiro		}
20590792Sgshapiro		if (h != NULL)
20690792Sgshapiro		{
20790792Sgshapiro			/* there are more items */
20890792Sgshapiro			*h = ' ';
20990792Sgshapiro			h1 = h + 1;
21090792Sgshapiro		}
21190792Sgshapiro	}
21290792Sgshapiro	return res;
21390792Sgshapiro}
21498121Sgshapiro# if SASL >= 20000
21598121Sgshapiro/*
21698121Sgshapiro**  IPTOSTRING -- create string for SASL_IP*PORT property
217132943Sgshapiro**		(borrowed from lib/iptostring.c in Cyrus-IMAP)
21898121Sgshapiro**
21998121Sgshapiro**	Parameters:
22098121Sgshapiro**		addr -- (pointer to) socket address
22198121Sgshapiro**		addrlen -- length of socket address
22298121Sgshapiro**		out -- output string (result)
22398121Sgshapiro**		outlen -- maximum length of output string
22498121Sgshapiro**
22598121Sgshapiro**	Returns:
22698121Sgshapiro**		true iff successful.
22798121Sgshapiro**
22898121Sgshapiro**	Side Effects:
22998121Sgshapiro**		creates output string if successful.
23098121Sgshapiro**		sets errno if unsuccessful.
23198121Sgshapiro*/
23298121Sgshapiro
23398121Sgshapiro#  include <arpa/inet.h>
23498121Sgshapiro
23598121Sgshapiro#  ifndef NI_MAXHOST
23698121Sgshapiro#   define NI_MAXHOST	1025
23798121Sgshapiro#  endif
23898121Sgshapiro#  ifndef NI_MAXSERV
23998121Sgshapiro#   define NI_MAXSERV	32
24098121Sgshapiro#  endif
24198121Sgshapiro
24298121Sgshapirobool
24398121Sgshapiroiptostring(addr, addrlen, out, outlen)
24498121Sgshapiro	SOCKADDR *addr;
24598121Sgshapiro	SOCKADDR_LEN_T addrlen;
24698121Sgshapiro	char *out;
24798121Sgshapiro	unsigned outlen;
24898121Sgshapiro{
24998121Sgshapiro	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
250141858Sgshapiro#  if NETINET6
251141858Sgshapiro	int niflags;
252363466Sgshapiro#  endif
25398121Sgshapiro
25498121Sgshapiro	if (addr == NULL || out == NULL)
25598121Sgshapiro	{
25698121Sgshapiro		errno = EINVAL;
25798121Sgshapiro		return false;
25898121Sgshapiro	}
25998121Sgshapiro
26098121Sgshapiro#  if NETINET6
261141858Sgshapiro	niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
262141858Sgshapiro#   ifdef NI_WITHSCOPEID
263141858Sgshapiro	if (addr->sa.sa_family == AF_INET6)
264141858Sgshapiro		niflags |= NI_WITHSCOPEID;
265363466Sgshapiro#   endif
26698121Sgshapiro	if (getnameinfo((struct sockaddr *) addr, addrlen,
267168515Sgshapiro			hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
26898121Sgshapiro		return false;
26998121Sgshapiro#  else /* NETINET6 */
27098121Sgshapiro	if (addr->sa.sa_family != AF_INET)
27198121Sgshapiro	{
27298121Sgshapiro		errno = EINVAL;
27398121Sgshapiro		return false;
27498121Sgshapiro	}
27598841Sgshapiro	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
27698841Sgshapiro	    >= sizeof(hbuf))
27798121Sgshapiro	{
27898841Sgshapiro		errno = ENOMEM;
27998121Sgshapiro		return false;
28098121Sgshapiro	}
281168515Sgshapiro	sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
28298121Sgshapiro#  endif /* NETINET6 */
28398121Sgshapiro
28498121Sgshapiro	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
28598121Sgshapiro	{
28698121Sgshapiro		errno = ENOMEM;
28798121Sgshapiro		return false;
28898121Sgshapiro	}
28998121Sgshapiro	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
29098121Sgshapiro	return true;
29198121Sgshapiro}
29298121Sgshapiro# endif /* SASL >= 20000 */
29390792Sgshapiro#endif /* SASL */
294