sasl.c revision 98121
1193326Sed/*
2193326Sed * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
3193326Sed *	All rights reserved.
4193326Sed *
5193326Sed * By using this file, you agree to the terms and conditions set
6193326Sed * forth in the LICENSE file which can be found at the top level of
7193326Sed * the sendmail distribution.
8193326Sed *
9193326Sed */
10193326Sed
11193326Sed#include <sm/gen.h>
12193326SedSM_RCSID("@(#)$Id: sasl.c,v 8.18 2002/05/25 00:26:42 gshapiro Exp $")
13193326Sed
14193326Sed#if SASL
15193326Sed# include <stdlib.h>
16193326Sed# include <sendmail.h>
17193326Sed# include <errno.h>
18193326Sed
19193326Sed/*
20193326Sed**  In order to ensure that storage leaks are tracked, and to prevent
21193326Sed**  conflicts between the sm_heap package and sasl, we tell sasl to
22193326Sed**  use the following heap allocation functions.  Unfortunately,
23193326Sed**  the sasl package incorrectly specifies the size of a block
24193326Sed**  using unsigned long: for portability, it should be size_t.
25193326Sed*/
26193326Sed
27193326Sedvoid *sm_sasl_malloc __P((unsigned long));
28193326Sedstatic void *sm_sasl_calloc __P((unsigned long, unsigned long));
29193326Sedstatic void *sm_sasl_realloc __P((void *, unsigned long));
30193326Sedvoid sm_sasl_free __P((void *));
31198893Srdivacky
32198893Srdivacky/*
33193326Sed**  SASLv1:
34193326Sed**  We can't use an rpool for Cyrus-SASL memory management routines,
35193326Sed**	since the encryption/decryption routines in Cyrus-SASL
36193326Sed**	allocate/deallocate a buffer each time. Since rpool
37193326Sed**	don't release memory until the very end, memory consumption is
38193326Sed**	proportional to the size of an e-mail, which is unacceptable.
39199482Srdivacky*/
40199482Srdivacky
41199482Srdivacky/*
42199482Srdivacky**  SM_SASL_MALLOC -- malloc() for SASL
43199482Srdivacky**
44199482Srdivacky**	Parameters:
45199482Srdivacky**		size -- size of requested memory.
46199482Srdivacky**
47199482Srdivacky**	Returns:
48199482Srdivacky**		pointer to memory.
49199482Srdivacky*/
50199482Srdivacky
51199482Srdivackyvoid *
52199482Srdivackysm_sasl_malloc(size)
53199482Srdivacky	unsigned long size;
54199482Srdivacky{
55199482Srdivacky	return sm_malloc((size_t) size);
56199482Srdivacky}
57199482Srdivacky
58199482Srdivacky/*
59199482Srdivacky**  SM_SASL_CALLOC -- calloc() for SASL
60199482Srdivacky**
61199482Srdivacky**	Parameters:
62199482Srdivacky**		nelem -- number of elements.
63193326Sed**		elemsize -- size of each element.
64193326Sed**
65198954Srdivacky**	Returns:
66199482Srdivacky**		pointer to memory.
67199482Srdivacky**
68199482Srdivacky**	Notice:
69198954Srdivacky**		this isn't currently used by SASL.
70199482Srdivacky*/
71199482Srdivacky
72199482Srdivackystatic void *
73199482Srdivackysm_sasl_calloc(nelem, elemsize)
74199482Srdivacky	unsigned long nelem;
75199482Srdivacky	unsigned long elemsize;
76199482Srdivacky{
77199482Srdivacky	size_t size;
78199482Srdivacky	void *p;
79193326Sed
80199482Srdivacky	size = (size_t) nelem * (size_t) elemsize;
81199482Srdivacky	p = sm_malloc(size);
82199482Srdivacky	if (p == NULL)
83199482Srdivacky		return NULL;
84199482Srdivacky	memset(p, '\0', size);
85199482Srdivacky	return p;
86199482Srdivacky}
87199482Srdivacky
88199482Srdivacky/*
89199482Srdivacky**  SM_SASL_REALLOC -- realloc() for SASL
90199482Srdivacky**
91199482Srdivacky**	Parameters:
92199482Srdivacky**		p -- pointer to old memory.
93199482Srdivacky**		size -- size of requested memory.
94199482Srdivacky**
95199482Srdivacky**	Returns:
96199482Srdivacky**		pointer to new memory.
97199482Srdivacky*/
98199482Srdivacky
99199482Srdivackystatic void *
100199482Srdivackysm_sasl_realloc(o, size)
101199482Srdivacky	void *o;
102199482Srdivacky	unsigned long size;
103199482Srdivacky{
104199482Srdivacky	return sm_realloc(o, (size_t) size);
105199482Srdivacky}
106199482Srdivacky
107199482Srdivacky/*
108199482Srdivacky**  SM_SASL_FREE -- free() for SASL
109199482Srdivacky**
110199482Srdivacky**	Parameters:
111199482Srdivacky**		p -- pointer to free.
112199482Srdivacky**
113199482Srdivacky**	Returns:
114199482Srdivacky**		none
115199482Srdivacky*/
116199482Srdivacky
117199482Srdivackyvoid
118199482Srdivackysm_sasl_free(p)
119199482Srdivacky	void *p;
120199482Srdivacky{
121199482Srdivacky	sm_free(p);
122199482Srdivacky}
123199482Srdivacky
124199482Srdivacky/*
125199482Srdivacky**  SM_SASL_INIT -- sendmail specific SASL initialization
126199482Srdivacky**
127199482Srdivacky**	Parameters:
128199482Srdivacky**		none.
129199482Srdivacky**
130199482Srdivacky**	Returns:
131199482Srdivacky**		none
132199482Srdivacky**
133199482Srdivacky**	Side Effects:
134199482Srdivacky**		installs memory management routines for SASL.
135199482Srdivacky*/
136199482Srdivacky
137199482Srdivackyvoid
138199482Srdivackysm_sasl_init()
139199482Srdivacky{
140199482Srdivacky	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
141199482Srdivacky		       sm_sasl_realloc, sm_sasl_free);
142199482Srdivacky}
143193326Sed/*
144199482Srdivacky**  INTERSECT -- create the intersection between two lists
145193326Sed**
146199482Srdivacky**	Parameters:
147199482Srdivacky**		s1, s2 -- lists of items (separated by single blanks).
148199482Srdivacky**		rpool -- resource pool from which result is allocated.
149199482Srdivacky**
150199482Srdivacky**	Returns:
151199482Srdivacky**		the intersection of both lists.
152199482Srdivacky*/
153198954Srdivacky
154199482Srdivackychar *
155199482Srdivackyintersect(s1, s2, rpool)
156199482Srdivacky	char *s1, *s2;
157199482Srdivacky	SM_RPOOL_T *rpool;
158199482Srdivacky{
159199482Srdivacky	char *hr, *h1, *h, *res;
160199482Srdivacky	int l1, l2, rl;
161199482Srdivacky
162199482Srdivacky	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
163199482Srdivacky		return NULL;
164199482Srdivacky	l1 = strlen(s1);
165199482Srdivacky	l2 = strlen(s2);
166199482Srdivacky	rl = SM_MIN(l1, l2);
167199482Srdivacky	res = (char *) sm_rpool_malloc(rpool, rl + 1);
168199482Srdivacky	if (res == NULL)
169199482Srdivacky		return NULL;
170199482Srdivacky	*res = '\0';
171199482Srdivacky	if (rl == 0)	/* at least one string empty? */
172199482Srdivacky		return res;
173199482Srdivacky	hr = res;
174199482Srdivacky	h1 = s1;
175199482Srdivacky	h = s1;
176199482Srdivacky
177199482Srdivacky	/* walk through s1 */
178198954Srdivacky	while (h != NULL && *h1 != '\0')
179199482Srdivacky	{
180199482Srdivacky		/* is there something after the current word? */
181199482Srdivacky		if ((h = strchr(h1, ' ')) != NULL)
182199482Srdivacky			*h = '\0';
183199482Srdivacky		l1 = strlen(h1);
184193326Sed
185199482Srdivacky		/* does the current word appear in s2 ? */
186199482Srdivacky		if (iteminlist(h1, s2, " ") != NULL)
187199482Srdivacky		{
188199482Srdivacky			/* add a blank if not first item */
189199482Srdivacky			if (hr != res)
190199482Srdivacky				*hr++ = ' ';
191193326Sed
192199482Srdivacky			/* copy the item */
193199482Srdivacky			memcpy(hr, h1, l1);
194199482Srdivacky
195198954Srdivacky			/* advance pointer in result list */
196199482Srdivacky			hr += l1;
197198954Srdivacky			*hr = '\0';
198199482Srdivacky		}
199199482Srdivacky		if (h != NULL)
200199482Srdivacky		{
201198954Srdivacky			/* there are more items */
202199482Srdivacky			*h = ' ';
203199482Srdivacky			h1 = h + 1;
204199482Srdivacky		}
205199482Srdivacky	}
206199482Srdivacky	return res;
207199482Srdivacky}
208199482Srdivacky# if SASL >= 20000
209198954Srdivacky/*
210198954Srdivacky**  IPTOSTRING -- create string for SASL_IP*PORT property
211198954Srdivacky**                (borrowed from lib/iptostring.c in Cyrus-IMAP)
212198954Srdivacky**
213198954Srdivacky**	Parameters:
214193326Sed**		addr -- (pointer to) socket address
215193326Sed**		addrlen -- length of socket address
216199512Srdivacky**		out -- output string (result)
217199512Srdivacky**		outlen -- maximum length of output string
218199990Srdivacky**
219199990Srdivacky**	Returns:
220199990Srdivacky**		true iff successful.
221207619Srdivacky**
222193326Sed**	Side Effects:
223199990Srdivacky**		creates output string if successful.
224193326Sed**		sets errno if unsuccessful.
225207619Srdivacky*/
226193326Sed
227207619Srdivacky#  include <arpa/inet.h>
228207619Srdivacky
229207619Srdivacky#  ifndef NI_WITHSCOPEID
230199990Srdivacky#   define NI_WITHSCOPEID	0
231207619Srdivacky#  endif
232207619Srdivacky#  ifndef NI_MAXHOST
233193326Sed#   define NI_MAXHOST	1025
234193326Sed#  endif
235193326Sed#  ifndef NI_MAXSERV
236199990Srdivacky#   define NI_MAXSERV	32
237199990Srdivacky#  endif
238193326Sed
239198954Srdivackybool
240198954Srdivackyiptostring(addr, addrlen, out, outlen)
241199482Srdivacky	SOCKADDR *addr;
242199482Srdivacky	SOCKADDR_LEN_T addrlen;
243199482Srdivacky	char *out;
244199482Srdivacky	unsigned outlen;
245199482Srdivacky{
246199482Srdivacky	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
247199482Srdivacky
248199482Srdivacky	if (addr == NULL || out == NULL)
249199482Srdivacky	{
250199482Srdivacky		errno = EINVAL;
251199482Srdivacky		return false;
252198954Srdivacky	}
253198954Srdivacky
254198954Srdivacky#  if NETINET6
255198954Srdivacky	if (getnameinfo((struct sockaddr *) addr, addrlen,
256199482Srdivacky			hbuf, sizeof hbuf, pbuf, sizeof pbuf,
257199482Srdivacky			NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV) != 0)
258199482Srdivacky		return false;
259199482Srdivacky#  else /* NETINET6 */
260199482Srdivacky	if (addr->sa.sa_family != AF_INET)
261198954Srdivacky	{
262199482Srdivacky		errno = EINVAL;
263199482Srdivacky		return false;
264199482Srdivacky	}
265199482Srdivacky	if (inet_ntop(AF_INET, &(addr->sin.sin_addr),
266199482Srdivacky		      hbuf, sizeof hbuf) == NULL)
267199482Srdivacky	{
268199482Srdivacky		errno = EINVAL;
269199482Srdivacky		return false;
270199482Srdivacky	}
271199482Srdivacky	sm_snprintf(pbuf, sizeof pbuf, "%d", ntohs(addr->sin.sin_port));
272199482Srdivacky#  endif /* NETINET6 */
273199482Srdivacky
274198954Srdivacky	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
275199482Srdivacky	{
276199482Srdivacky		errno = ENOMEM;
277199482Srdivacky		return false;
278199482Srdivacky	}
279199482Srdivacky	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
280199482Srdivacky	return true;
281199482Srdivacky}
282199482Srdivacky# endif /* SASL >= 20000 */
283199482Srdivacky#endif /* SASL */
284198954Srdivacky