sasl.c revision 102528
112891Swpaul/*
212891Swpaul * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
312891Swpaul *	All rights reserved.
412891Swpaul *
512891Swpaul * By using this file, you agree to the terms and conditions set
612891Swpaul * forth in the LICENSE file which can be found at the top level of
712891Swpaul * the sendmail distribution.
812891Swpaul *
912891Swpaul */
1012891Swpaul
1112891Swpaul#include <sm/gen.h>
1212891SwpaulSM_RCSID("@(#)$Id: sasl.c,v 8.19.2.1 2002/07/13 18:04:56 ca Exp $")
1312891Swpaul
1412891Swpaul#if SASL
1512891Swpaul# include <stdlib.h>
1612891Swpaul# include <sendmail.h>
1712891Swpaul# include <errno.h>
1812891Swpaul
1912891Swpaul/*
2012891Swpaul**  In order to ensure that storage leaks are tracked, and to prevent
2112891Swpaul**  conflicts between the sm_heap package and sasl, we tell sasl to
2212891Swpaul**  use the following heap allocation functions.  Unfortunately,
2312891Swpaul**  the sasl package incorrectly specifies the size of a block
2412891Swpaul**  using unsigned long: for portability, it should be size_t.
2512891Swpaul*/
2612891Swpaul
2712891Swpaulvoid *sm_sasl_malloc __P((unsigned long));
2812891Swpaulstatic void *sm_sasl_calloc __P((unsigned long, unsigned long));
2912891Swpaulstatic void *sm_sasl_realloc __P((void *, unsigned long));
3012891Swpaulvoid sm_sasl_free __P((void *));
3150479Speter
3212891Swpaul/*
33200478Shrs**  SASLv1:
3412891Swpaul**  We can't use an rpool for Cyrus-SASL memory management routines,
3512891Swpaul**	since the encryption/decryption routines in Cyrus-SASL
3612891Swpaul**	allocate/deallocate a buffer each time. Since rpool
3712891Swpaul**	don't release memory until the very end, memory consumption is
3824946Sjmg**	proportional to the size of an e-mail, which is unacceptable.
3912891Swpaul*/
4024946Sjmg
4112891Swpaul/*
4212891Swpaul**  SM_SASL_MALLOC -- malloc() for SASL
43175951Smatteo**
4412891Swpaul**	Parameters:
4512891Swpaul**		size -- size of requested memory.
4624946Sjmg**
4712891Swpaul**	Returns:
4857673Ssheldonh**		pointer to memory.
4957673Ssheldonh*/
5012891Swpaul
5112891Swpaulvoid *
5212891Swpaulsm_sasl_malloc(size)
5312891Swpaul	unsigned long size;
5412891Swpaul{
5512891Swpaul	return sm_malloc((size_t) size);
5630827Scharnier}
5730827Scharnier
5812891Swpaul/*
5912891Swpaul**  SM_SASL_CALLOC -- calloc() for SASL
6012891Swpaul**
6124946Sjmg**	Parameters:
6224946Sjmg**		nelem -- number of elements.
6399968Scharnier**		elemsize -- size of each element.
6430827Scharnier**
6530827Scharnier**	Returns:
6630827Scharnier**		pointer to memory.
6724946Sjmg**
6830827Scharnier**	Notice:
6930827Scharnier**		this isn't currently used by SASL.
7030827Scharnier*/
7112891Swpaul
7224946Sjmgstatic void *
7312891Swpaulsm_sasl_calloc(nelem, elemsize)
7412891Swpaul	unsigned long nelem;
7557673Ssheldonh	unsigned long elemsize;
7657673Ssheldonh{
7712891Swpaul	size_t size;
7812891Swpaul	void *p;
7930827Scharnier
8030827Scharnier	size = (size_t) nelem * (size_t) elemsize;
8130827Scharnier	p = sm_malloc(size);
8212891Swpaul	if (p == NULL)
8312891Swpaul		return NULL;
8424946Sjmg	memset(p, '\0', size);
8512891Swpaul	return p;
8612891Swpaul}
8712891Swpaul
8812891Swpaul/*
8957673Ssheldonh**  SM_SASL_REALLOC -- realloc() for SASL
9057673Ssheldonh**
9112891Swpaul**	Parameters:
9224946Sjmg**		p -- pointer to old memory.
9312891Swpaul**		size -- size of requested memory.
9412891Swpaul**
9512891Swpaul**	Returns:
9612891Swpaul**		pointer to new memory.
9712891Swpaul*/
9812891Swpaul
9924946Sjmgstatic void *
10057673Ssheldonhsm_sasl_realloc(o, size)
10157673Ssheldonh	void *o;
10212891Swpaul	unsigned long size;
10312891Swpaul{
10430827Scharnier	return sm_realloc(o, (size_t) size);
10556416Smpp}
10630827Scharnier
10757673Ssheldonh/*
10857673Ssheldonh**  SM_SASL_FREE -- free() for SASL
10912891Swpaul**
110141851Sru**	Parameters:
11112891Swpaul**		p -- pointer to free.
11212891Swpaul**
11324946Sjmg**	Returns:
11424946Sjmg**		none
11599968Scharnier*/
116109724Smtm
11712891Swpaulvoid
11830827Scharniersm_sasl_free(p)
11912891Swpaul	void *p;
12056416Smpp{
12156416Smpp	sm_free(p);
12256416Smpp}
12330827Scharnier
124101828Sru/*
12556416Smpp**  SM_SASL_INIT -- sendmail specific SASL initialization
12630827Scharnier**
12712891Swpaul**	Parameters:
12812891Swpaul**		none.
12957673Ssheldonh**
13057673Ssheldonh**	Returns:
13130827Scharnier**		none
13230827Scharnier**
13330827Scharnier**	Side Effects:
13412891Swpaul**		installs memory management routines for SASL.
13530827Scharnier*/
13656416Smpp
13730827Scharniervoid
13824946Sjmgsm_sasl_init()
13912891Swpaul{
14012891Swpaul	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
14112891Swpaul		       sm_sasl_realloc, sm_sasl_free);
14261248Sasmodai}
14357673Ssheldonh/*
14457673Ssheldonh**  INTERSECT -- create the intersection between two lists
145194968Sbrian**
146194968Sbrian**	Parameters:
147194968Sbrian**		s1, s2 -- lists of items (separated by single blanks).
148194968Sbrian**		rpool -- resource pool from which result is allocated.
149194968Sbrian**
15012891Swpaul**	Returns:
15157695Ssheldonh**		the intersection of both lists.
15257695Ssheldonh*/
15312891Swpaul
15412891Swpaulchar *
15512891Swpaulintersect(s1, s2, rpool)
15612891Swpaul	char *s1, *s2;
15712891Swpaul	SM_RPOOL_T *rpool;
15812891Swpaul{
15956416Smpp	char *hr, *h1, *h, *res;
16079755Sdd	int l1, l2, rl;
16130827Scharnier
16212891Swpaul	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
16312891Swpaul		return NULL;
16412891Swpaul	l1 = strlen(s1);
16512891Swpaul	l2 = strlen(s2);
16612891Swpaul	rl = SM_MIN(l1, l2);
16712891Swpaul	res = (char *) sm_rpool_malloc(rpool, rl + 1);
16812891Swpaul	if (res == NULL)
16912891Swpaul		return NULL;
17012891Swpaul	*res = '\0';
17157673Ssheldonh	if (rl == 0)	/* at least one string empty? */
17257673Ssheldonh		return res;
17324946Sjmg	hr = res;
17412891Swpaul	h1 = s1;
17512891Swpaul	h = s1;
17612891Swpaul
17757673Ssheldonh	/* walk through s1 */
17857673Ssheldonh	while (h != NULL && *h1 != '\0')
17912891Swpaul	{
18012891Swpaul		/* is there something after the current word? */
18130827Scharnier		if ((h = strchr(h1, ' ')) != NULL)
18230827Scharnier			*h = '\0';
18312891Swpaul		l1 = strlen(h1);
18444227Sghelmer
18544227Sghelmer		/* does the current word appear in s2 ? */
18644227Sghelmer		if (iteminlist(h1, s2, " ") != NULL)
18744227Sghelmer		{
18844227Sghelmer			/* add a blank if not first item */
18912891Swpaul			if (hr != res)
19030827Scharnier				*hr++ = ' ';
19130827Scharnier
19212891Swpaul			/* copy the item */
19312891Swpaul			memcpy(hr, h1, l1);
19412891Swpaul
19512891Swpaul			/* advance pointer in result list */
19624946Sjmg			hr += l1;
19724946Sjmg			*hr = '\0';
19824946Sjmg		}
19912891Swpaul		if (h != NULL)
20012891Swpaul		{
20112891Swpaul			/* there are more items */
20230827Scharnier			*h = ' ';
20356416Smpp			h1 = h + 1;
20430827Scharnier		}
20568716Sru	}
20630827Scharnier	return res;
20712891Swpaul}
20812891Swpaul# if SASL >= 20000
20924946Sjmg/*
21012891Swpaul**  IPTOSTRING -- create string for SASL_IP*PORT property
21124946Sjmg**		(borrowed from lib/iptostring.c in Cyrus-IMAP)
21212891Swpaul**
21312891Swpaul**	Parameters:
21412891Swpaul**		addr -- (pointer to) socket address
21512891Swpaul**		addrlen -- length of socket address
21612891Swpaul**		out -- output string (result)
21730827Scharnier**		outlen -- maximum length of output string
21868716Sru**
21930827Scharnier**	Returns:
22030827Scharnier**		true iff successful.
22130827Scharnier**
22212891Swpaul**	Side Effects:
22312891Swpaul**		creates output string if successful.
22414240Swpaul**		sets errno if unsuccessful.
22524946Sjmg*/
22630827Scharnier
22730827Scharnier#  include <arpa/inet.h>
22830827Scharnier
22957673Ssheldonh#  ifndef NI_WITHSCOPEID
23057673Ssheldonh#   define NI_WITHSCOPEID	0
23124946Sjmg#  endif
23214240Swpaul#  ifndef NI_MAXHOST
23314240Swpaul#   define NI_MAXHOST	1025
23414240Swpaul#  endif
23514240Swpaul#  ifndef NI_MAXSERV
23624946Sjmg#   define NI_MAXSERV	32
23714240Swpaul#  endif
23814240Swpaul
23924946Sjmgbool
24014240Swpauliptostring(addr, addrlen, out, outlen)
24114240Swpaul	SOCKADDR *addr;
24214240Swpaul	SOCKADDR_LEN_T addrlen;
24357695Ssheldonh	char *out;
24457695Ssheldonh	unsigned outlen;
24514240Swpaul{
24614240Swpaul	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
24724946Sjmg
24824946Sjmg	if (addr == NULL || out == NULL)
24957673Ssheldonh	{
25057673Ssheldonh		errno = EINVAL;
25114240Swpaul		return false;
25214240Swpaul	}
25314240Swpaul
25414240Swpaul#  if NETINET6
25514240Swpaul	if (getnameinfo((struct sockaddr *) addr, addrlen,
25630884Sjseger			hbuf, sizeof hbuf, pbuf, sizeof pbuf,
25714240Swpaul			NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV) != 0)
25814240Swpaul		return false;
25914240Swpaul#  else /* NETINET6 */
26014240Swpaul	if (addr->sa.sa_family != AF_INET)
26114240Swpaul	{
26214240Swpaul		errno = EINVAL;
26314240Swpaul		return false;
26424946Sjmg	}
26514240Swpaul	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
26657673Ssheldonh	    >= sizeof(hbuf))
26757673Ssheldonh	{
26814240Swpaul		errno = ENOMEM;
26957673Ssheldonh		return false;
27057673Ssheldonh	}
27114240Swpaul	sm_snprintf(pbuf, sizeof pbuf, "%d", ntohs(addr->sin.sin_port));
27214240Swpaul#  endif /* NETINET6 */
27324946Sjmg
27414240Swpaul	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
27514240Swpaul	{
27624946Sjmg		errno = ENOMEM;
27724946Sjmg		return false;
27899968Scharnier	}
27924946Sjmg	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
28090321Smarkm	return true;
28157673Ssheldonh}
28281462Sru# endif /* SASL >= 20000 */
28381462Sru#endif /* SASL */
28414240Swpaul