xref: /freebsd/contrib/sendmail/src/sasl.c (revision e2c0e292e8a7ca00ba99bcfccc9e637f45c3e8b1)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *	All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  *
940266059SGregory Neil Shapiro  */
1040266059SGregory Neil Shapiro 
1140266059SGregory Neil Shapiro #include <sm/gen.h>
124313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: sasl.c,v 8.24 2013-11-22 20:51:56 ca Exp $")
13605302a5SGregory Neil Shapiro 
14605302a5SGregory Neil Shapiro #if SASL
1540266059SGregory Neil Shapiro # include <stdlib.h>
1640266059SGregory Neil Shapiro # include <sendmail.h>
1740266059SGregory Neil Shapiro # include <errno.h>
1840266059SGregory Neil Shapiro 
1940266059SGregory Neil Shapiro /*
2040266059SGregory Neil Shapiro **  In order to ensure that storage leaks are tracked, and to prevent
2140266059SGregory Neil Shapiro **  conflicts between the sm_heap package and sasl, we tell sasl to
2240266059SGregory Neil Shapiro **  use the following heap allocation functions.  Unfortunately,
23ba00ec3dSGregory Neil Shapiro **  older sasl packages incorrectly specifies the size of a block
2440266059SGregory Neil Shapiro **  using unsigned long: for portability, it should be size_t.
2540266059SGregory Neil Shapiro */
2640266059SGregory Neil Shapiro 
27a944d3c6SHajimu UMEMOTO # if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a
28a944d3c6SHajimu UMEMOTO #  define SM_SASL_SIZE_T	size_t
29*5b0945b5SGregory Neil Shapiro # else
30a944d3c6SHajimu UMEMOTO #  define SM_SASL_SIZE_T	unsigned long
31*5b0945b5SGregory Neil Shapiro # endif
32a944d3c6SHajimu UMEMOTO 
33a944d3c6SHajimu UMEMOTO void *sm_sasl_malloc __P((SM_SASL_SIZE_T));
34a944d3c6SHajimu UMEMOTO static void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T));
35a944d3c6SHajimu UMEMOTO static void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T));
3640266059SGregory Neil Shapiro void sm_sasl_free __P((void *));
3740266059SGregory Neil Shapiro 
3840266059SGregory Neil Shapiro /*
3994c01205SGregory Neil Shapiro **  SASLv1:
4040266059SGregory Neil Shapiro **  We can't use an rpool for Cyrus-SASL memory management routines,
4140266059SGregory Neil Shapiro **	since the encryption/decryption routines in Cyrus-SASL
4240266059SGregory Neil Shapiro **	allocate/deallocate a buffer each time. Since rpool
4340266059SGregory Neil Shapiro **	don't release memory until the very end, memory consumption is
4440266059SGregory Neil Shapiro **	proportional to the size of an e-mail, which is unacceptable.
4540266059SGregory Neil Shapiro */
4640266059SGregory Neil Shapiro 
4740266059SGregory Neil Shapiro /*
4840266059SGregory Neil Shapiro **  SM_SASL_MALLOC -- malloc() for SASL
4940266059SGregory Neil Shapiro **
5040266059SGregory Neil Shapiro **	Parameters:
5140266059SGregory Neil Shapiro **		size -- size of requested memory.
5240266059SGregory Neil Shapiro **
5340266059SGregory Neil Shapiro **	Returns:
5440266059SGregory Neil Shapiro **		pointer to memory.
5540266059SGregory Neil Shapiro */
5640266059SGregory Neil Shapiro 
5740266059SGregory Neil Shapiro void *
sm_sasl_malloc(size)5840266059SGregory Neil Shapiro sm_sasl_malloc(size)
59a944d3c6SHajimu UMEMOTO 	SM_SASL_SIZE_T size;
6040266059SGregory Neil Shapiro {
6140266059SGregory Neil Shapiro 	return sm_malloc((size_t) size);
6240266059SGregory Neil Shapiro }
6340266059SGregory Neil Shapiro 
6440266059SGregory Neil Shapiro /*
6540266059SGregory Neil Shapiro **  SM_SASL_CALLOC -- calloc() for SASL
6640266059SGregory Neil Shapiro **
6740266059SGregory Neil Shapiro **	Parameters:
6840266059SGregory Neil Shapiro **		nelem -- number of elements.
6940266059SGregory Neil Shapiro **		elemsize -- size of each element.
7040266059SGregory Neil Shapiro **
7140266059SGregory Neil Shapiro **	Returns:
7240266059SGregory Neil Shapiro **		pointer to memory.
7340266059SGregory Neil Shapiro **
7440266059SGregory Neil Shapiro **	Notice:
7540266059SGregory Neil Shapiro **		this isn't currently used by SASL.
7640266059SGregory Neil Shapiro */
7740266059SGregory Neil Shapiro 
7840266059SGregory Neil Shapiro static void *
sm_sasl_calloc(nelem,elemsize)7940266059SGregory Neil Shapiro sm_sasl_calloc(nelem, elemsize)
80a944d3c6SHajimu UMEMOTO 	SM_SASL_SIZE_T nelem;
81a944d3c6SHajimu UMEMOTO 	SM_SASL_SIZE_T elemsize;
8240266059SGregory Neil Shapiro {
8340266059SGregory Neil Shapiro 	size_t size;
8440266059SGregory Neil Shapiro 	void *p;
8540266059SGregory Neil Shapiro 
8640266059SGregory Neil Shapiro 	size = (size_t) nelem * (size_t) elemsize;
8740266059SGregory Neil Shapiro 	p = sm_malloc(size);
8840266059SGregory Neil Shapiro 	if (p == NULL)
8940266059SGregory Neil Shapiro 		return NULL;
9040266059SGregory Neil Shapiro 	memset(p, '\0', size);
9140266059SGregory Neil Shapiro 	return p;
9240266059SGregory Neil Shapiro }
9340266059SGregory Neil Shapiro 
9440266059SGregory Neil Shapiro /*
9540266059SGregory Neil Shapiro **  SM_SASL_REALLOC -- realloc() for SASL
9640266059SGregory Neil Shapiro **
9740266059SGregory Neil Shapiro **	Parameters:
9840266059SGregory Neil Shapiro **		p -- pointer to old memory.
9940266059SGregory Neil Shapiro **		size -- size of requested memory.
10040266059SGregory Neil Shapiro **
10140266059SGregory Neil Shapiro **	Returns:
10240266059SGregory Neil Shapiro **		pointer to new memory.
10340266059SGregory Neil Shapiro */
10440266059SGregory Neil Shapiro 
10540266059SGregory Neil Shapiro static void *
sm_sasl_realloc(o,size)10640266059SGregory Neil Shapiro sm_sasl_realloc(o, size)
10740266059SGregory Neil Shapiro 	void *o;
108a944d3c6SHajimu UMEMOTO 	SM_SASL_SIZE_T size;
10940266059SGregory Neil Shapiro {
11040266059SGregory Neil Shapiro 	return sm_realloc(o, (size_t) size);
11140266059SGregory Neil Shapiro }
11240266059SGregory Neil Shapiro 
11340266059SGregory Neil Shapiro /*
11440266059SGregory Neil Shapiro **  SM_SASL_FREE -- free() for SASL
11540266059SGregory Neil Shapiro **
11640266059SGregory Neil Shapiro **	Parameters:
11740266059SGregory Neil Shapiro **		p -- pointer to free.
11840266059SGregory Neil Shapiro **
11940266059SGregory Neil Shapiro **	Returns:
12040266059SGregory Neil Shapiro **		none
12140266059SGregory Neil Shapiro */
12240266059SGregory Neil Shapiro 
12340266059SGregory Neil Shapiro void
sm_sasl_free(p)12440266059SGregory Neil Shapiro sm_sasl_free(p)
12540266059SGregory Neil Shapiro 	void *p;
12640266059SGregory Neil Shapiro {
12740266059SGregory Neil Shapiro 	sm_free(p);
12840266059SGregory Neil Shapiro }
12940266059SGregory Neil Shapiro 
13040266059SGregory Neil Shapiro /*
13140266059SGregory Neil Shapiro **  SM_SASL_INIT -- sendmail specific SASL initialization
13240266059SGregory Neil Shapiro **
13340266059SGregory Neil Shapiro **	Parameters:
13440266059SGregory Neil Shapiro **		none.
13540266059SGregory Neil Shapiro **
13640266059SGregory Neil Shapiro **	Returns:
13740266059SGregory Neil Shapiro **		none
13840266059SGregory Neil Shapiro **
13940266059SGregory Neil Shapiro **	Side Effects:
14040266059SGregory Neil Shapiro **		installs memory management routines for SASL.
14140266059SGregory Neil Shapiro */
14240266059SGregory Neil Shapiro 
14340266059SGregory Neil Shapiro void
sm_sasl_init()14440266059SGregory Neil Shapiro sm_sasl_init()
14540266059SGregory Neil Shapiro {
14640266059SGregory Neil Shapiro 	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
14740266059SGregory Neil Shapiro 		       sm_sasl_realloc, sm_sasl_free);
14840266059SGregory Neil Shapiro }
14940266059SGregory Neil Shapiro /*
15040266059SGregory Neil Shapiro **  INTERSECT -- create the intersection between two lists
15140266059SGregory Neil Shapiro **
15240266059SGregory Neil Shapiro **	Parameters:
15340266059SGregory Neil Shapiro **		s1, s2 -- lists of items (separated by single blanks).
15440266059SGregory Neil Shapiro **		rpool -- resource pool from which result is allocated.
15540266059SGregory Neil Shapiro **
15640266059SGregory Neil Shapiro **	Returns:
15740266059SGregory Neil Shapiro **		the intersection of both lists.
15840266059SGregory Neil Shapiro */
15940266059SGregory Neil Shapiro 
16040266059SGregory Neil Shapiro char *
intersect(s1,s2,rpool)16140266059SGregory Neil Shapiro intersect(s1, s2, rpool)
16240266059SGregory Neil Shapiro 	char *s1, *s2;
16340266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
16440266059SGregory Neil Shapiro {
16540266059SGregory Neil Shapiro 	char *hr, *h1, *h, *res;
16640266059SGregory Neil Shapiro 	int l1, l2, rl;
16740266059SGregory Neil Shapiro 
16840266059SGregory Neil Shapiro 	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
16940266059SGregory Neil Shapiro 		return NULL;
17040266059SGregory Neil Shapiro 	l1 = strlen(s1);
17140266059SGregory Neil Shapiro 	l2 = strlen(s2);
17240266059SGregory Neil Shapiro 	rl = SM_MIN(l1, l2);
17340266059SGregory Neil Shapiro 	res = (char *) sm_rpool_malloc(rpool, rl + 1);
17440266059SGregory Neil Shapiro 	if (res == NULL)
17540266059SGregory Neil Shapiro 		return NULL;
17640266059SGregory Neil Shapiro 	*res = '\0';
17740266059SGregory Neil Shapiro 	if (rl == 0)	/* at least one string empty? */
17840266059SGregory Neil Shapiro 		return res;
17940266059SGregory Neil Shapiro 	hr = res;
18040266059SGregory Neil Shapiro 	h1 = s1;
18140266059SGregory Neil Shapiro 	h = s1;
18240266059SGregory Neil Shapiro 
18340266059SGregory Neil Shapiro 	/* walk through s1 */
18440266059SGregory Neil Shapiro 	while (h != NULL && *h1 != '\0')
18540266059SGregory Neil Shapiro 	{
18640266059SGregory Neil Shapiro 		/* is there something after the current word? */
18740266059SGregory Neil Shapiro 		if ((h = strchr(h1, ' ')) != NULL)
18840266059SGregory Neil Shapiro 			*h = '\0';
18940266059SGregory Neil Shapiro 		l1 = strlen(h1);
19040266059SGregory Neil Shapiro 
19140266059SGregory Neil Shapiro 		/* does the current word appear in s2 ? */
19240266059SGregory Neil Shapiro 		if (iteminlist(h1, s2, " ") != NULL)
19340266059SGregory Neil Shapiro 		{
19440266059SGregory Neil Shapiro 			/* add a blank if not first item */
19540266059SGregory Neil Shapiro 			if (hr != res)
19640266059SGregory Neil Shapiro 				*hr++ = ' ';
19740266059SGregory Neil Shapiro 
19840266059SGregory Neil Shapiro 			/* copy the item */
19940266059SGregory Neil Shapiro 			memcpy(hr, h1, l1);
20040266059SGregory Neil Shapiro 
20140266059SGregory Neil Shapiro 			/* advance pointer in result list */
20240266059SGregory Neil Shapiro 			hr += l1;
20340266059SGregory Neil Shapiro 			*hr = '\0';
20440266059SGregory Neil Shapiro 		}
20540266059SGregory Neil Shapiro 		if (h != NULL)
20640266059SGregory Neil Shapiro 		{
20740266059SGregory Neil Shapiro 			/* there are more items */
20840266059SGregory Neil Shapiro 			*h = ' ';
20940266059SGregory Neil Shapiro 			h1 = h + 1;
21040266059SGregory Neil Shapiro 		}
21140266059SGregory Neil Shapiro 	}
21240266059SGregory Neil Shapiro 	return res;
21340266059SGregory Neil Shapiro }
21494c01205SGregory Neil Shapiro # if SASL >= 20000
21594c01205SGregory Neil Shapiro /*
21694c01205SGregory Neil Shapiro **  IPTOSTRING -- create string for SASL_IP*PORT property
21794c01205SGregory Neil Shapiro **		(borrowed from lib/iptostring.c in Cyrus-IMAP)
21894c01205SGregory Neil Shapiro **
21994c01205SGregory Neil Shapiro **	Parameters:
22094c01205SGregory Neil Shapiro **		addr -- (pointer to) socket address
22194c01205SGregory Neil Shapiro **		addrlen -- length of socket address
22294c01205SGregory Neil Shapiro **		out -- output string (result)
22394c01205SGregory Neil Shapiro **		outlen -- maximum length of output string
22494c01205SGregory Neil Shapiro **
22594c01205SGregory Neil Shapiro **	Returns:
22694c01205SGregory Neil Shapiro **		true iff successful.
22794c01205SGregory Neil Shapiro **
22894c01205SGregory Neil Shapiro **	Side Effects:
22994c01205SGregory Neil Shapiro **		creates output string if successful.
23094c01205SGregory Neil Shapiro **		sets errno if unsuccessful.
23194c01205SGregory Neil Shapiro */
23294c01205SGregory Neil Shapiro 
23394c01205SGregory Neil Shapiro #  include <arpa/inet.h>
23494c01205SGregory Neil Shapiro 
23594c01205SGregory Neil Shapiro #  ifndef NI_MAXHOST
23694c01205SGregory Neil Shapiro #   define NI_MAXHOST	1025
23794c01205SGregory Neil Shapiro #  endif
23894c01205SGregory Neil Shapiro #  ifndef NI_MAXSERV
23994c01205SGregory Neil Shapiro #   define NI_MAXSERV	32
24094c01205SGregory Neil Shapiro #  endif
24194c01205SGregory Neil Shapiro 
24294c01205SGregory Neil Shapiro bool
iptostring(addr,addrlen,out,outlen)24394c01205SGregory Neil Shapiro iptostring(addr, addrlen, out, outlen)
24494c01205SGregory Neil Shapiro 	SOCKADDR *addr;
24594c01205SGregory Neil Shapiro 	SOCKADDR_LEN_T addrlen;
24694c01205SGregory Neil Shapiro 	char *out;
24794c01205SGregory Neil Shapiro 	unsigned outlen;
24894c01205SGregory Neil Shapiro {
24994c01205SGregory Neil Shapiro 	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
250b6bacd31SGregory Neil Shapiro #  if NETINET6
251b6bacd31SGregory Neil Shapiro 	int niflags;
252*5b0945b5SGregory Neil Shapiro #  endif
25394c01205SGregory Neil Shapiro 
25494c01205SGregory Neil Shapiro 	if (addr == NULL || out == NULL)
25594c01205SGregory Neil Shapiro 	{
25694c01205SGregory Neil Shapiro 		errno = EINVAL;
25794c01205SGregory Neil Shapiro 		return false;
25894c01205SGregory Neil Shapiro 	}
25994c01205SGregory Neil Shapiro 
26094c01205SGregory Neil Shapiro #  if NETINET6
261b6bacd31SGregory Neil Shapiro 	niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
262b6bacd31SGregory Neil Shapiro #   ifdef NI_WITHSCOPEID
263b6bacd31SGregory Neil Shapiro 	if (addr->sa.sa_family == AF_INET6)
264b6bacd31SGregory Neil Shapiro 		niflags |= NI_WITHSCOPEID;
265*5b0945b5SGregory Neil Shapiro #   endif
26694c01205SGregory Neil Shapiro 	if (getnameinfo((struct sockaddr *) addr, addrlen,
267d0cef73dSGregory Neil Shapiro 			hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
26894c01205SGregory Neil Shapiro 		return false;
26994c01205SGregory Neil Shapiro #  else /* NETINET6 */
27094c01205SGregory Neil Shapiro 	if (addr->sa.sa_family != AF_INET)
27194c01205SGregory Neil Shapiro 	{
27294c01205SGregory Neil Shapiro 		errno = EINVAL;
27394c01205SGregory Neil Shapiro 		return false;
27494c01205SGregory Neil Shapiro 	}
275739ac4d4SGregory Neil Shapiro 	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
276739ac4d4SGregory Neil Shapiro 	    >= sizeof(hbuf))
27794c01205SGregory Neil Shapiro 	{
278739ac4d4SGregory Neil Shapiro 		errno = ENOMEM;
27994c01205SGregory Neil Shapiro 		return false;
28094c01205SGregory Neil Shapiro 	}
281d0cef73dSGregory Neil Shapiro 	sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
28294c01205SGregory Neil Shapiro #  endif /* NETINET6 */
28394c01205SGregory Neil Shapiro 
28494c01205SGregory Neil Shapiro 	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
28594c01205SGregory Neil Shapiro 	{
28694c01205SGregory Neil Shapiro 		errno = ENOMEM;
28794c01205SGregory Neil Shapiro 		return false;
28894c01205SGregory Neil Shapiro 	}
28994c01205SGregory Neil Shapiro 	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
29094c01205SGregory Neil Shapiro 	return true;
29194c01205SGregory Neil Shapiro }
29294c01205SGregory Neil Shapiro # endif /* SASL >= 20000 */
29340266059SGregory Neil Shapiro #endif /* SASL */
294