xref: /freebsd/contrib/sendmail/src/sasl.c (revision b6bacd3150f411c3de886f7615bc22129b6974ad)
140266059SGregory Neil Shapiro /*
2605302a5SGregory Neil Shapiro  * Copyright (c) 2001-2002 Sendmail, 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>
12b6bacd31SGregory Neil Shapiro SM_RCSID("@(#)$Id: sasl.c,v 8.21 2004/11/22 23:09:00 gshapiro 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,
2340266059SGregory Neil Shapiro **  the sasl package 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 
2740266059SGregory Neil Shapiro void *sm_sasl_malloc __P((unsigned long));
2840266059SGregory Neil Shapiro static void *sm_sasl_calloc __P((unsigned long, unsigned long));
2940266059SGregory Neil Shapiro static void *sm_sasl_realloc __P((void *, unsigned long));
3040266059SGregory Neil Shapiro void sm_sasl_free __P((void *));
3140266059SGregory Neil Shapiro 
3240266059SGregory Neil Shapiro /*
3394c01205SGregory Neil Shapiro **  SASLv1:
3440266059SGregory Neil Shapiro **  We can't use an rpool for Cyrus-SASL memory management routines,
3540266059SGregory Neil Shapiro **	since the encryption/decryption routines in Cyrus-SASL
3640266059SGregory Neil Shapiro **	allocate/deallocate a buffer each time. Since rpool
3740266059SGregory Neil Shapiro **	don't release memory until the very end, memory consumption is
3840266059SGregory Neil Shapiro **	proportional to the size of an e-mail, which is unacceptable.
3940266059SGregory Neil Shapiro */
4040266059SGregory Neil Shapiro 
4140266059SGregory Neil Shapiro /*
4240266059SGregory Neil Shapiro **  SM_SASL_MALLOC -- malloc() for SASL
4340266059SGregory Neil Shapiro **
4440266059SGregory Neil Shapiro **	Parameters:
4540266059SGregory Neil Shapiro **		size -- size of requested memory.
4640266059SGregory Neil Shapiro **
4740266059SGregory Neil Shapiro **	Returns:
4840266059SGregory Neil Shapiro **		pointer to memory.
4940266059SGregory Neil Shapiro */
5040266059SGregory Neil Shapiro 
5140266059SGregory Neil Shapiro void *
5240266059SGregory Neil Shapiro sm_sasl_malloc(size)
5340266059SGregory Neil Shapiro 	unsigned long size;
5440266059SGregory Neil Shapiro {
5540266059SGregory Neil Shapiro 	return sm_malloc((size_t) size);
5640266059SGregory Neil Shapiro }
5740266059SGregory Neil Shapiro 
5840266059SGregory Neil Shapiro /*
5940266059SGregory Neil Shapiro **  SM_SASL_CALLOC -- calloc() for SASL
6040266059SGregory Neil Shapiro **
6140266059SGregory Neil Shapiro **	Parameters:
6240266059SGregory Neil Shapiro **		nelem -- number of elements.
6340266059SGregory Neil Shapiro **		elemsize -- size of each element.
6440266059SGregory Neil Shapiro **
6540266059SGregory Neil Shapiro **	Returns:
6640266059SGregory Neil Shapiro **		pointer to memory.
6740266059SGregory Neil Shapiro **
6840266059SGregory Neil Shapiro **	Notice:
6940266059SGregory Neil Shapiro **		this isn't currently used by SASL.
7040266059SGregory Neil Shapiro */
7140266059SGregory Neil Shapiro 
7240266059SGregory Neil Shapiro static void *
7340266059SGregory Neil Shapiro sm_sasl_calloc(nelem, elemsize)
7440266059SGregory Neil Shapiro 	unsigned long nelem;
7540266059SGregory Neil Shapiro 	unsigned long elemsize;
7640266059SGregory Neil Shapiro {
7740266059SGregory Neil Shapiro 	size_t size;
7840266059SGregory Neil Shapiro 	void *p;
7940266059SGregory Neil Shapiro 
8040266059SGregory Neil Shapiro 	size = (size_t) nelem * (size_t) elemsize;
8140266059SGregory Neil Shapiro 	p = sm_malloc(size);
8240266059SGregory Neil Shapiro 	if (p == NULL)
8340266059SGregory Neil Shapiro 		return NULL;
8440266059SGregory Neil Shapiro 	memset(p, '\0', size);
8540266059SGregory Neil Shapiro 	return p;
8640266059SGregory Neil Shapiro }
8740266059SGregory Neil Shapiro 
8840266059SGregory Neil Shapiro /*
8940266059SGregory Neil Shapiro **  SM_SASL_REALLOC -- realloc() for SASL
9040266059SGregory Neil Shapiro **
9140266059SGregory Neil Shapiro **	Parameters:
9240266059SGregory Neil Shapiro **		p -- pointer to old memory.
9340266059SGregory Neil Shapiro **		size -- size of requested memory.
9440266059SGregory Neil Shapiro **
9540266059SGregory Neil Shapiro **	Returns:
9640266059SGregory Neil Shapiro **		pointer to new memory.
9740266059SGregory Neil Shapiro */
9840266059SGregory Neil Shapiro 
9940266059SGregory Neil Shapiro static void *
10040266059SGregory Neil Shapiro sm_sasl_realloc(o, size)
10140266059SGregory Neil Shapiro 	void *o;
10240266059SGregory Neil Shapiro 	unsigned long size;
10340266059SGregory Neil Shapiro {
10440266059SGregory Neil Shapiro 	return sm_realloc(o, (size_t) size);
10540266059SGregory Neil Shapiro }
10640266059SGregory Neil Shapiro 
10740266059SGregory Neil Shapiro /*
10840266059SGregory Neil Shapiro **  SM_SASL_FREE -- free() for SASL
10940266059SGregory Neil Shapiro **
11040266059SGregory Neil Shapiro **	Parameters:
11140266059SGregory Neil Shapiro **		p -- pointer to free.
11240266059SGregory Neil Shapiro **
11340266059SGregory Neil Shapiro **	Returns:
11440266059SGregory Neil Shapiro **		none
11540266059SGregory Neil Shapiro */
11640266059SGregory Neil Shapiro 
11740266059SGregory Neil Shapiro void
11840266059SGregory Neil Shapiro sm_sasl_free(p)
11940266059SGregory Neil Shapiro 	void *p;
12040266059SGregory Neil Shapiro {
12140266059SGregory Neil Shapiro 	sm_free(p);
12240266059SGregory Neil Shapiro }
12340266059SGregory Neil Shapiro 
12440266059SGregory Neil Shapiro /*
12540266059SGregory Neil Shapiro **  SM_SASL_INIT -- sendmail specific SASL initialization
12640266059SGregory Neil Shapiro **
12740266059SGregory Neil Shapiro **	Parameters:
12840266059SGregory Neil Shapiro **		none.
12940266059SGregory Neil Shapiro **
13040266059SGregory Neil Shapiro **	Returns:
13140266059SGregory Neil Shapiro **		none
13240266059SGregory Neil Shapiro **
13340266059SGregory Neil Shapiro **	Side Effects:
13440266059SGregory Neil Shapiro **		installs memory management routines for SASL.
13540266059SGregory Neil Shapiro */
13640266059SGregory Neil Shapiro 
13740266059SGregory Neil Shapiro void
13840266059SGregory Neil Shapiro sm_sasl_init()
13940266059SGregory Neil Shapiro {
14040266059SGregory Neil Shapiro 	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
14140266059SGregory Neil Shapiro 		       sm_sasl_realloc, sm_sasl_free);
14240266059SGregory Neil Shapiro }
14340266059SGregory Neil Shapiro /*
14440266059SGregory Neil Shapiro **  INTERSECT -- create the intersection between two lists
14540266059SGregory Neil Shapiro **
14640266059SGregory Neil Shapiro **	Parameters:
14740266059SGregory Neil Shapiro **		s1, s2 -- lists of items (separated by single blanks).
14840266059SGregory Neil Shapiro **		rpool -- resource pool from which result is allocated.
14940266059SGregory Neil Shapiro **
15040266059SGregory Neil Shapiro **	Returns:
15140266059SGregory Neil Shapiro **		the intersection of both lists.
15240266059SGregory Neil Shapiro */
15340266059SGregory Neil Shapiro 
15440266059SGregory Neil Shapiro char *
15540266059SGregory Neil Shapiro intersect(s1, s2, rpool)
15640266059SGregory Neil Shapiro 	char *s1, *s2;
15740266059SGregory Neil Shapiro 	SM_RPOOL_T *rpool;
15840266059SGregory Neil Shapiro {
15940266059SGregory Neil Shapiro 	char *hr, *h1, *h, *res;
16040266059SGregory Neil Shapiro 	int l1, l2, rl;
16140266059SGregory Neil Shapiro 
16240266059SGregory Neil Shapiro 	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
16340266059SGregory Neil Shapiro 		return NULL;
16440266059SGregory Neil Shapiro 	l1 = strlen(s1);
16540266059SGregory Neil Shapiro 	l2 = strlen(s2);
16640266059SGregory Neil Shapiro 	rl = SM_MIN(l1, l2);
16740266059SGregory Neil Shapiro 	res = (char *) sm_rpool_malloc(rpool, rl + 1);
16840266059SGregory Neil Shapiro 	if (res == NULL)
16940266059SGregory Neil Shapiro 		return NULL;
17040266059SGregory Neil Shapiro 	*res = '\0';
17140266059SGregory Neil Shapiro 	if (rl == 0)	/* at least one string empty? */
17240266059SGregory Neil Shapiro 		return res;
17340266059SGregory Neil Shapiro 	hr = res;
17440266059SGregory Neil Shapiro 	h1 = s1;
17540266059SGregory Neil Shapiro 	h = s1;
17640266059SGregory Neil Shapiro 
17740266059SGregory Neil Shapiro 	/* walk through s1 */
17840266059SGregory Neil Shapiro 	while (h != NULL && *h1 != '\0')
17940266059SGregory Neil Shapiro 	{
18040266059SGregory Neil Shapiro 		/* is there something after the current word? */
18140266059SGregory Neil Shapiro 		if ((h = strchr(h1, ' ')) != NULL)
18240266059SGregory Neil Shapiro 			*h = '\0';
18340266059SGregory Neil Shapiro 		l1 = strlen(h1);
18440266059SGregory Neil Shapiro 
18540266059SGregory Neil Shapiro 		/* does the current word appear in s2 ? */
18640266059SGregory Neil Shapiro 		if (iteminlist(h1, s2, " ") != NULL)
18740266059SGregory Neil Shapiro 		{
18840266059SGregory Neil Shapiro 			/* add a blank if not first item */
18940266059SGregory Neil Shapiro 			if (hr != res)
19040266059SGregory Neil Shapiro 				*hr++ = ' ';
19140266059SGregory Neil Shapiro 
19240266059SGregory Neil Shapiro 			/* copy the item */
19340266059SGregory Neil Shapiro 			memcpy(hr, h1, l1);
19440266059SGregory Neil Shapiro 
19540266059SGregory Neil Shapiro 			/* advance pointer in result list */
19640266059SGregory Neil Shapiro 			hr += l1;
19740266059SGregory Neil Shapiro 			*hr = '\0';
19840266059SGregory Neil Shapiro 		}
19940266059SGregory Neil Shapiro 		if (h != NULL)
20040266059SGregory Neil Shapiro 		{
20140266059SGregory Neil Shapiro 			/* there are more items */
20240266059SGregory Neil Shapiro 			*h = ' ';
20340266059SGregory Neil Shapiro 			h1 = h + 1;
20440266059SGregory Neil Shapiro 		}
20540266059SGregory Neil Shapiro 	}
20640266059SGregory Neil Shapiro 	return res;
20740266059SGregory Neil Shapiro }
20894c01205SGregory Neil Shapiro # if SASL >= 20000
20994c01205SGregory Neil Shapiro /*
21094c01205SGregory Neil Shapiro **  IPTOSTRING -- create string for SASL_IP*PORT property
21194c01205SGregory Neil Shapiro **		(borrowed from lib/iptostring.c in Cyrus-IMAP)
21294c01205SGregory Neil Shapiro **
21394c01205SGregory Neil Shapiro **	Parameters:
21494c01205SGregory Neil Shapiro **		addr -- (pointer to) socket address
21594c01205SGregory Neil Shapiro **		addrlen -- length of socket address
21694c01205SGregory Neil Shapiro **		out -- output string (result)
21794c01205SGregory Neil Shapiro **		outlen -- maximum length of output string
21894c01205SGregory Neil Shapiro **
21994c01205SGregory Neil Shapiro **	Returns:
22094c01205SGregory Neil Shapiro **		true iff successful.
22194c01205SGregory Neil Shapiro **
22294c01205SGregory Neil Shapiro **	Side Effects:
22394c01205SGregory Neil Shapiro **		creates output string if successful.
22494c01205SGregory Neil Shapiro **		sets errno if unsuccessful.
22594c01205SGregory Neil Shapiro */
22694c01205SGregory Neil Shapiro 
22794c01205SGregory Neil Shapiro #  include <arpa/inet.h>
22894c01205SGregory Neil Shapiro 
22994c01205SGregory Neil Shapiro #  ifndef NI_MAXHOST
23094c01205SGregory Neil Shapiro #   define NI_MAXHOST	1025
23194c01205SGregory Neil Shapiro #  endif
23294c01205SGregory Neil Shapiro #  ifndef NI_MAXSERV
23394c01205SGregory Neil Shapiro #   define NI_MAXSERV	32
23494c01205SGregory Neil Shapiro #  endif
23594c01205SGregory Neil Shapiro 
23694c01205SGregory Neil Shapiro bool
23794c01205SGregory Neil Shapiro iptostring(addr, addrlen, out, outlen)
23894c01205SGregory Neil Shapiro 	SOCKADDR *addr;
23994c01205SGregory Neil Shapiro 	SOCKADDR_LEN_T addrlen;
24094c01205SGregory Neil Shapiro 	char *out;
24194c01205SGregory Neil Shapiro 	unsigned outlen;
24294c01205SGregory Neil Shapiro {
24394c01205SGregory Neil Shapiro 	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
244b6bacd31SGregory Neil Shapiro #  if NETINET6
245b6bacd31SGregory Neil Shapiro 	int niflags;
246b6bacd31SGregory Neil Shapiro #  endif /* NETINET6 */
24794c01205SGregory Neil Shapiro 
24894c01205SGregory Neil Shapiro 	if (addr == NULL || out == NULL)
24994c01205SGregory Neil Shapiro 	{
25094c01205SGregory Neil Shapiro 		errno = EINVAL;
25194c01205SGregory Neil Shapiro 		return false;
25294c01205SGregory Neil Shapiro 	}
25394c01205SGregory Neil Shapiro 
25494c01205SGregory Neil Shapiro #  if NETINET6
255b6bacd31SGregory Neil Shapiro 	niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
256b6bacd31SGregory Neil Shapiro #   ifdef NI_WITHSCOPEID
257b6bacd31SGregory Neil Shapiro 	if (addr->sa.sa_family == AF_INET6)
258b6bacd31SGregory Neil Shapiro 		niflags |= NI_WITHSCOPEID;
259b6bacd31SGregory Neil Shapiro #   endif /* NI_WITHSCOPEID */
26094c01205SGregory Neil Shapiro 	if (getnameinfo((struct sockaddr *) addr, addrlen,
261b6bacd31SGregory Neil Shapiro 			hbuf, sizeof hbuf, pbuf, sizeof pbuf, niflags) != 0)
26294c01205SGregory Neil Shapiro 		return false;
26394c01205SGregory Neil Shapiro #  else /* NETINET6 */
26494c01205SGregory Neil Shapiro 	if (addr->sa.sa_family != AF_INET)
26594c01205SGregory Neil Shapiro 	{
26694c01205SGregory Neil Shapiro 		errno = EINVAL;
26794c01205SGregory Neil Shapiro 		return false;
26894c01205SGregory Neil Shapiro 	}
269739ac4d4SGregory Neil Shapiro 	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
270739ac4d4SGregory Neil Shapiro 	    >= sizeof(hbuf))
27194c01205SGregory Neil Shapiro 	{
272739ac4d4SGregory Neil Shapiro 		errno = ENOMEM;
27394c01205SGregory Neil Shapiro 		return false;
27494c01205SGregory Neil Shapiro 	}
27594c01205SGregory Neil Shapiro 	sm_snprintf(pbuf, sizeof pbuf, "%d", ntohs(addr->sin.sin_port));
27694c01205SGregory Neil Shapiro #  endif /* NETINET6 */
27794c01205SGregory Neil Shapiro 
27894c01205SGregory Neil Shapiro 	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
27994c01205SGregory Neil Shapiro 	{
28094c01205SGregory Neil Shapiro 		errno = ENOMEM;
28194c01205SGregory Neil Shapiro 		return false;
28294c01205SGregory Neil Shapiro 	}
28394c01205SGregory Neil Shapiro 	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
28494c01205SGregory Neil Shapiro 	return true;
28594c01205SGregory Neil Shapiro }
28694c01205SGregory Neil Shapiro # endif /* SASL >= 20000 */
28740266059SGregory Neil Shapiro #endif /* SASL */
288