sasl.c revision 261194
1196200Sscottl/*
2196200Sscottl * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers.
3196200Sscottl *	All rights reserved.
4196200Sscottl *
5196200Sscottl * By using this file, you agree to the terms and conditions set
6196200Sscottl * forth in the LICENSE file which can be found at the top level of
7196200Sscottl * the sendmail distribution.
8196200Sscottl *
9196200Sscottl */
10196200Sscottl
11196200Sscottl#include <sm/gen.h>
12196200SscottlSM_RCSID("@(#)$Id: sasl.c,v 8.24 2013/11/22 20:51:56 ca Exp $")
13196200Sscottl
14196200Sscottl#if SASL
15196200Sscottl# include <stdlib.h>
16196200Sscottl# include <sendmail.h>
17196200Sscottl# include <errno.h>
18196200Sscottl
19196200Sscottl/*
20196200Sscottl**  In order to ensure that storage leaks are tracked, and to prevent
21196200Sscottl**  conflicts between the sm_heap package and sasl, we tell sasl to
22196200Sscottl**  use the following heap allocation functions.  Unfortunately,
23196200Sscottl**  older sasl packages incorrectly specifies the size of a block
24196200Sscottl**  using unsigned long: for portability, it should be size_t.
25196200Sscottl*/
26196200Sscottl
27196200Sscottl# if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a
28196200Sscottl#  define SM_SASL_SIZE_T	size_t
29196200Sscottl# else /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */
30196200Sscottl#  define SM_SASL_SIZE_T	unsigned long
31196200Sscottl# endif /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */
32196200Sscottl
33196200Sscottlvoid *sm_sasl_malloc __P((SM_SASL_SIZE_T));
34196200Sscottlstatic void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T));
35196200Sscottlstatic void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T));
36196200Sscottlvoid sm_sasl_free __P((void *));
37196200Sscottl
38196200Sscottl/*
39196200Sscottl**  SASLv1:
40196200Sscottl**  We can't use an rpool for Cyrus-SASL memory management routines,
41196200Sscottl**	since the encryption/decryption routines in Cyrus-SASL
42196200Sscottl**	allocate/deallocate a buffer each time. Since rpool
43196200Sscottl**	don't release memory until the very end, memory consumption is
44196200Sscottl**	proportional to the size of an e-mail, which is unacceptable.
45196200Sscottl*/
46196200Sscottl
47223345Sbz/*
48241776Sed**  SM_SASL_MALLOC -- malloc() for SASL
49223345Sbz**
50196200Sscottl**	Parameters:
51196200Sscottl**		size -- size of requested memory.
52196200Sscottl**
53196200Sscottl**	Returns:
54223345Sbz**		pointer to memory.
55196200Sscottl*/
56196200Sscottl
57196200Sscottlvoid *
58196200Sscottlsm_sasl_malloc(size)
59196200Sscottl	SM_SASL_SIZE_T size;
60196200Sscottl{
61196200Sscottl	return sm_malloc((size_t) size);
62196200Sscottl}
63251516Ssbruno
64223267Sbz/*
65196200Sscottl**  SM_SASL_CALLOC -- calloc() for SASL
66196200Sscottl**
67221208Sjhb**	Parameters:
68196200Sscottl**		nelem -- number of elements.
69254906Ssbruno**		elemsize -- size of each element.
70196200Sscottl**
71254906Ssbruno**	Returns:
72196200Sscottl**		pointer to memory.
73196200Sscottl**
74196200Sscottl**	Notice:
75196200Sscottl**		this isn't currently used by SASL.
76196200Sscottl*/
77196200Sscottl
78196200Sscottlstatic void *
79196200Sscottlsm_sasl_calloc(nelem, elemsize)
80196200Sscottl	SM_SASL_SIZE_T nelem;
81196200Sscottl	SM_SASL_SIZE_T elemsize;
82196200Sscottl{
83196200Sscottl	size_t size;
84196200Sscottl	void *p;
85196200Sscottl
86196200Sscottl	size = (size_t) nelem * (size_t) elemsize;
87196200Sscottl	p = sm_malloc(size);
88251516Ssbruno	if (p == NULL)
89251516Ssbruno		return NULL;
90251516Ssbruno	memset(p, '\0', size);
91251516Ssbruno	return p;
92251516Ssbruno}
93196200Sscottl
94249257Smarkj/*
95249257Smarkj**  SM_SASL_REALLOC -- realloc() for SASL
96272041Ssmh**
97272041Ssmh**	Parameters:
98196200Sscottl**		p -- pointer to old memory.
99196200Sscottl**		size -- size of requested memory.
100196200Sscottl**
101196200Sscottl**	Returns:
102196200Sscottl**		pointer to new memory.
103196200Sscottl*/
104196200Sscottl
105196200Sscottlstatic void *
106237260Seadlersm_sasl_realloc(o, size)
107196200Sscottl	void *o;
108196200Sscottl	SM_SASL_SIZE_T size;
109254906Ssbruno{
110196200Sscottl	return sm_realloc(o, (size_t) size);
111196200Sscottl}
112196200Sscottl
113196200Sscottl/*
114196200Sscottl**  SM_SASL_FREE -- free() for SASL
115196200Sscottl**
116196200Sscottl**	Parameters:
117196200Sscottl**		p -- pointer to free.
118196200Sscottl**
119196200Sscottl**	Returns:
120196200Sscottl**		none
121196200Sscottl*/
122196200Sscottl
123196200Sscottlvoid
124223345Sbzsm_sasl_free(p)
125196200Sscottl	void *p;
126223345Sbz{
127223345Sbz	sm_free(p);
128223345Sbz}
129223345Sbz
130223345Sbz/*
131223345Sbz**  SM_SASL_INIT -- sendmail specific SASL initialization
132196200Sscottl**
133196200Sscottl**	Parameters:
134196200Sscottl**		none.
135196200Sscottl**
136196200Sscottl**	Returns:
137196200Sscottl**		none
138196200Sscottl**
139196200Sscottl**	Side Effects:
140196200Sscottl**		installs memory management routines for SASL.
141196200Sscottl*/
142196200Sscottl
143196200Sscottlvoid
144196200Sscottlsm_sasl_init()
145196200Sscottl{
146196200Sscottl	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
147196200Sscottl		       sm_sasl_realloc, sm_sasl_free);
148196200Sscottl}
149213672Srandi/*
150213672Srandi**  INTERSECT -- create the intersection between two lists
151213672Srandi**
152213672Srandi**	Parameters:
153196200Sscottl**		s1, s2 -- lists of items (separated by single blanks).
154196200Sscottl**		rpool -- resource pool from which result is allocated.
155196200Sscottl**
156213672Srandi**	Returns:
157196200Sscottl**		the intersection of both lists.
158241776Sed*/
159241776Sed
160241776Sedchar *
161241776Sedintersect(s1, s2, rpool)
162241776Sed	char *s1, *s2;
163241776Sed	SM_RPOOL_T *rpool;
164241776Sed{
165241776Sed	char *hr, *h1, *h, *res;
166241776Sed	int l1, l2, rl;
167241776Sed
168241776Sed	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
169241776Sed		return NULL;
170241776Sed	l1 = strlen(s1);
171241776Sed	l2 = strlen(s2);
172241776Sed	rl = SM_MIN(l1, l2);
173241776Sed	res = (char *) sm_rpool_malloc(rpool, rl + 1);
174241776Sed	if (res == NULL)
175241776Sed		return NULL;
176241776Sed	*res = '\0';
177241776Sed	if (rl == 0)	/* at least one string empty? */
178241776Sed		return res;
179241776Sed	hr = res;
180241776Sed	h1 = s1;
181241776Sed	h = s1;
182241776Sed
183241776Sed	/* walk through s1 */
184241776Sed	while (h != NULL && *h1 != '\0')
185241776Sed	{
186		/* is there something after the current word? */
187		if ((h = strchr(h1, ' ')) != NULL)
188			*h = '\0';
189		l1 = strlen(h1);
190
191		/* does the current word appear in s2 ? */
192		if (iteminlist(h1, s2, " ") != NULL)
193		{
194			/* add a blank if not first item */
195			if (hr != res)
196				*hr++ = ' ';
197
198			/* copy the item */
199			memcpy(hr, h1, l1);
200
201			/* advance pointer in result list */
202			hr += l1;
203			*hr = '\0';
204		}
205		if (h != NULL)
206		{
207			/* there are more items */
208			*h = ' ';
209			h1 = h + 1;
210		}
211	}
212	return res;
213}
214# if SASL >= 20000
215/*
216**  IPTOSTRING -- create string for SASL_IP*PORT property
217**		(borrowed from lib/iptostring.c in Cyrus-IMAP)
218**
219**	Parameters:
220**		addr -- (pointer to) socket address
221**		addrlen -- length of socket address
222**		out -- output string (result)
223**		outlen -- maximum length of output string
224**
225**	Returns:
226**		true iff successful.
227**
228**	Side Effects:
229**		creates output string if successful.
230**		sets errno if unsuccessful.
231*/
232
233#  include <arpa/inet.h>
234
235#  ifndef NI_MAXHOST
236#   define NI_MAXHOST	1025
237#  endif
238#  ifndef NI_MAXSERV
239#   define NI_MAXSERV	32
240#  endif
241
242bool
243iptostring(addr, addrlen, out, outlen)
244	SOCKADDR *addr;
245	SOCKADDR_LEN_T addrlen;
246	char *out;
247	unsigned outlen;
248{
249	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
250#  if NETINET6
251	int niflags;
252#  endif /* NETINET6 */
253
254	if (addr == NULL || out == NULL)
255	{
256		errno = EINVAL;
257		return false;
258	}
259
260#  if NETINET6
261	niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
262#   ifdef NI_WITHSCOPEID
263	if (addr->sa.sa_family == AF_INET6)
264		niflags |= NI_WITHSCOPEID;
265#   endif /* NI_WITHSCOPEID */
266	if (getnameinfo((struct sockaddr *) addr, addrlen,
267			hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
268		return false;
269#  else /* NETINET6 */
270	if (addr->sa.sa_family != AF_INET)
271	{
272		errno = EINVAL;
273		return false;
274	}
275	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
276	    >= sizeof(hbuf))
277	{
278		errno = ENOMEM;
279		return false;
280	}
281	sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
282#  endif /* NETINET6 */
283
284	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
285	{
286		errno = ENOMEM;
287		return false;
288	}
289	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
290	return true;
291}
292# endif /* SASL >= 20000 */
293#endif /* SASL */
294