xref: /illumos-gate/usr/src/cmd/sendmail/src/sasl.c (revision d0fccfcda73f8b52d101bd2b0f7885a766f7e354)
1*d0fccfcdSGary Mills /*
2*d0fccfcdSGary Mills  * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
3*d0fccfcdSGary Mills  *	All rights reserved.
4*d0fccfcdSGary Mills  *
5*d0fccfcdSGary Mills  * By using this file, you agree to the terms and conditions set
6*d0fccfcdSGary Mills  * forth in the LICENSE file which can be found at the top level of
7*d0fccfcdSGary Mills  * the sendmail distribution.
8*d0fccfcdSGary Mills  *
9*d0fccfcdSGary Mills  */
10*d0fccfcdSGary Mills 
11*d0fccfcdSGary Mills #include <sm/gen.h>
12*d0fccfcdSGary Mills SM_RCSID("@(#)$Id: sasl.c,v 8.22 2006/08/15 23:24:57 ca Exp $")
13*d0fccfcdSGary Mills 
14*d0fccfcdSGary Mills #if SASL
15*d0fccfcdSGary Mills # include <stdlib.h>
16*d0fccfcdSGary Mills # include <sendmail.h>
17*d0fccfcdSGary Mills # include <errno.h>
18*d0fccfcdSGary Mills 
19*d0fccfcdSGary Mills /*
20*d0fccfcdSGary Mills **  In order to ensure that storage leaks are tracked, and to prevent
21*d0fccfcdSGary Mills **  conflicts between the sm_heap package and sasl, we tell sasl to
22*d0fccfcdSGary Mills **  use the following heap allocation functions.  Unfortunately,
23*d0fccfcdSGary Mills **  the sasl package incorrectly specifies the size of a block
24*d0fccfcdSGary Mills **  using unsigned long: for portability, it should be size_t.
25*d0fccfcdSGary Mills */
26*d0fccfcdSGary Mills 
27*d0fccfcdSGary Mills void *sm_sasl_malloc __P((unsigned long));
28*d0fccfcdSGary Mills static void *sm_sasl_calloc __P((unsigned long, unsigned long));
29*d0fccfcdSGary Mills static void *sm_sasl_realloc __P((void *, unsigned long));
30*d0fccfcdSGary Mills void sm_sasl_free __P((void *));
31*d0fccfcdSGary Mills 
32*d0fccfcdSGary Mills /*
33*d0fccfcdSGary Mills **  SASLv1:
34*d0fccfcdSGary Mills **  We can't use an rpool for Cyrus-SASL memory management routines,
35*d0fccfcdSGary Mills **	since the encryption/decryption routines in Cyrus-SASL
36*d0fccfcdSGary Mills **	allocate/deallocate a buffer each time. Since rpool
37*d0fccfcdSGary Mills **	don't release memory until the very end, memory consumption is
38*d0fccfcdSGary Mills **	proportional to the size of an e-mail, which is unacceptable.
39*d0fccfcdSGary Mills */
40*d0fccfcdSGary Mills 
41*d0fccfcdSGary Mills /*
42*d0fccfcdSGary Mills **  SM_SASL_MALLOC -- malloc() for SASL
43*d0fccfcdSGary Mills **
44*d0fccfcdSGary Mills **	Parameters:
45*d0fccfcdSGary Mills **		size -- size of requested memory.
46*d0fccfcdSGary Mills **
47*d0fccfcdSGary Mills **	Returns:
48*d0fccfcdSGary Mills **		pointer to memory.
49*d0fccfcdSGary Mills */
50*d0fccfcdSGary Mills 
51*d0fccfcdSGary Mills void *
sm_sasl_malloc(size)52*d0fccfcdSGary Mills sm_sasl_malloc(size)
53*d0fccfcdSGary Mills 	unsigned long size;
54*d0fccfcdSGary Mills {
55*d0fccfcdSGary Mills 	return sm_malloc((size_t) size);
56*d0fccfcdSGary Mills }
57*d0fccfcdSGary Mills 
58*d0fccfcdSGary Mills /*
59*d0fccfcdSGary Mills **  SM_SASL_CALLOC -- calloc() for SASL
60*d0fccfcdSGary Mills **
61*d0fccfcdSGary Mills **	Parameters:
62*d0fccfcdSGary Mills **		nelem -- number of elements.
63*d0fccfcdSGary Mills **		elemsize -- size of each element.
64*d0fccfcdSGary Mills **
65*d0fccfcdSGary Mills **	Returns:
66*d0fccfcdSGary Mills **		pointer to memory.
67*d0fccfcdSGary Mills **
68*d0fccfcdSGary Mills **	Notice:
69*d0fccfcdSGary Mills **		this isn't currently used by SASL.
70*d0fccfcdSGary Mills */
71*d0fccfcdSGary Mills 
72*d0fccfcdSGary Mills static void *
sm_sasl_calloc(nelem,elemsize)73*d0fccfcdSGary Mills sm_sasl_calloc(nelem, elemsize)
74*d0fccfcdSGary Mills 	unsigned long nelem;
75*d0fccfcdSGary Mills 	unsigned long elemsize;
76*d0fccfcdSGary Mills {
77*d0fccfcdSGary Mills 	size_t size;
78*d0fccfcdSGary Mills 	void *p;
79*d0fccfcdSGary Mills 
80*d0fccfcdSGary Mills 	size = (size_t) nelem * (size_t) elemsize;
81*d0fccfcdSGary Mills 	p = sm_malloc(size);
82*d0fccfcdSGary Mills 	if (p == NULL)
83*d0fccfcdSGary Mills 		return NULL;
84*d0fccfcdSGary Mills 	memset(p, '\0', size);
85*d0fccfcdSGary Mills 	return p;
86*d0fccfcdSGary Mills }
87*d0fccfcdSGary Mills 
88*d0fccfcdSGary Mills /*
89*d0fccfcdSGary Mills **  SM_SASL_REALLOC -- realloc() for SASL
90*d0fccfcdSGary Mills **
91*d0fccfcdSGary Mills **	Parameters:
92*d0fccfcdSGary Mills **		p -- pointer to old memory.
93*d0fccfcdSGary Mills **		size -- size of requested memory.
94*d0fccfcdSGary Mills **
95*d0fccfcdSGary Mills **	Returns:
96*d0fccfcdSGary Mills **		pointer to new memory.
97*d0fccfcdSGary Mills */
98*d0fccfcdSGary Mills 
99*d0fccfcdSGary Mills static void *
sm_sasl_realloc(o,size)100*d0fccfcdSGary Mills sm_sasl_realloc(o, size)
101*d0fccfcdSGary Mills 	void *o;
102*d0fccfcdSGary Mills 	unsigned long size;
103*d0fccfcdSGary Mills {
104*d0fccfcdSGary Mills 	return sm_realloc(o, (size_t) size);
105*d0fccfcdSGary Mills }
106*d0fccfcdSGary Mills 
107*d0fccfcdSGary Mills /*
108*d0fccfcdSGary Mills **  SM_SASL_FREE -- free() for SASL
109*d0fccfcdSGary Mills **
110*d0fccfcdSGary Mills **	Parameters:
111*d0fccfcdSGary Mills **		p -- pointer to free.
112*d0fccfcdSGary Mills **
113*d0fccfcdSGary Mills **	Returns:
114*d0fccfcdSGary Mills **		none
115*d0fccfcdSGary Mills */
116*d0fccfcdSGary Mills 
117*d0fccfcdSGary Mills void
sm_sasl_free(p)118*d0fccfcdSGary Mills sm_sasl_free(p)
119*d0fccfcdSGary Mills 	void *p;
120*d0fccfcdSGary Mills {
121*d0fccfcdSGary Mills 	sm_free(p);
122*d0fccfcdSGary Mills }
123*d0fccfcdSGary Mills 
124*d0fccfcdSGary Mills /*
125*d0fccfcdSGary Mills **  SM_SASL_INIT -- sendmail specific SASL initialization
126*d0fccfcdSGary Mills **
127*d0fccfcdSGary Mills **	Parameters:
128*d0fccfcdSGary Mills **		none.
129*d0fccfcdSGary Mills **
130*d0fccfcdSGary Mills **	Returns:
131*d0fccfcdSGary Mills **		none
132*d0fccfcdSGary Mills **
133*d0fccfcdSGary Mills **	Side Effects:
134*d0fccfcdSGary Mills **		installs memory management routines for SASL.
135*d0fccfcdSGary Mills */
136*d0fccfcdSGary Mills 
137*d0fccfcdSGary Mills void
sm_sasl_init()138*d0fccfcdSGary Mills sm_sasl_init()
139*d0fccfcdSGary Mills {
140*d0fccfcdSGary Mills 	sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
141*d0fccfcdSGary Mills 		       sm_sasl_realloc, sm_sasl_free);
142*d0fccfcdSGary Mills }
143*d0fccfcdSGary Mills /*
144*d0fccfcdSGary Mills **  INTERSECT -- create the intersection between two lists
145*d0fccfcdSGary Mills **
146*d0fccfcdSGary Mills **	Parameters:
147*d0fccfcdSGary Mills **		s1, s2 -- lists of items (separated by single blanks).
148*d0fccfcdSGary Mills **		rpool -- resource pool from which result is allocated.
149*d0fccfcdSGary Mills **
150*d0fccfcdSGary Mills **	Returns:
151*d0fccfcdSGary Mills **		the intersection of both lists.
152*d0fccfcdSGary Mills */
153*d0fccfcdSGary Mills 
154*d0fccfcdSGary Mills char *
intersect(s1,s2,rpool)155*d0fccfcdSGary Mills intersect(s1, s2, rpool)
156*d0fccfcdSGary Mills 	char *s1, *s2;
157*d0fccfcdSGary Mills 	SM_RPOOL_T *rpool;
158*d0fccfcdSGary Mills {
159*d0fccfcdSGary Mills 	char *hr, *h1, *h, *res;
160*d0fccfcdSGary Mills 	int l1, l2, rl;
161*d0fccfcdSGary Mills 
162*d0fccfcdSGary Mills 	if (s1 == NULL || s2 == NULL)	/* NULL string(s) -> NULL result */
163*d0fccfcdSGary Mills 		return NULL;
164*d0fccfcdSGary Mills 	l1 = strlen(s1);
165*d0fccfcdSGary Mills 	l2 = strlen(s2);
166*d0fccfcdSGary Mills 	rl = SM_MIN(l1, l2);
167*d0fccfcdSGary Mills 	res = (char *) sm_rpool_malloc(rpool, rl + 1);
168*d0fccfcdSGary Mills 	if (res == NULL)
169*d0fccfcdSGary Mills 		return NULL;
170*d0fccfcdSGary Mills 	*res = '\0';
171*d0fccfcdSGary Mills 	if (rl == 0)	/* at least one string empty? */
172*d0fccfcdSGary Mills 		return res;
173*d0fccfcdSGary Mills 	hr = res;
174*d0fccfcdSGary Mills 	h1 = s1;
175*d0fccfcdSGary Mills 	h = s1;
176*d0fccfcdSGary Mills 
177*d0fccfcdSGary Mills 	/* walk through s1 */
178*d0fccfcdSGary Mills 	while (h != NULL && *h1 != '\0')
179*d0fccfcdSGary Mills 	{
180*d0fccfcdSGary Mills 		/* is there something after the current word? */
181*d0fccfcdSGary Mills 		if ((h = strchr(h1, ' ')) != NULL)
182*d0fccfcdSGary Mills 			*h = '\0';
183*d0fccfcdSGary Mills 		l1 = strlen(h1);
184*d0fccfcdSGary Mills 
185*d0fccfcdSGary Mills 		/* does the current word appear in s2 ? */
186*d0fccfcdSGary Mills 		if (iteminlist(h1, s2, " ") != NULL)
187*d0fccfcdSGary Mills 		{
188*d0fccfcdSGary Mills 			/* add a blank if not first item */
189*d0fccfcdSGary Mills 			if (hr != res)
190*d0fccfcdSGary Mills 				*hr++ = ' ';
191*d0fccfcdSGary Mills 
192*d0fccfcdSGary Mills 			/* copy the item */
193*d0fccfcdSGary Mills 			memcpy(hr, h1, l1);
194*d0fccfcdSGary Mills 
195*d0fccfcdSGary Mills 			/* advance pointer in result list */
196*d0fccfcdSGary Mills 			hr += l1;
197*d0fccfcdSGary Mills 			*hr = '\0';
198*d0fccfcdSGary Mills 		}
199*d0fccfcdSGary Mills 		if (h != NULL)
200*d0fccfcdSGary Mills 		{
201*d0fccfcdSGary Mills 			/* there are more items */
202*d0fccfcdSGary Mills 			*h = ' ';
203*d0fccfcdSGary Mills 			h1 = h + 1;
204*d0fccfcdSGary Mills 		}
205*d0fccfcdSGary Mills 	}
206*d0fccfcdSGary Mills 	return res;
207*d0fccfcdSGary Mills }
208*d0fccfcdSGary Mills # if SASL >= 20000
209*d0fccfcdSGary Mills /*
210*d0fccfcdSGary Mills **  IPTOSTRING -- create string for SASL_IP*PORT property
211*d0fccfcdSGary Mills **		(borrowed from lib/iptostring.c in Cyrus-IMAP)
212*d0fccfcdSGary Mills **
213*d0fccfcdSGary Mills **	Parameters:
214*d0fccfcdSGary Mills **		addr -- (pointer to) socket address
215*d0fccfcdSGary Mills **		addrlen -- length of socket address
216*d0fccfcdSGary Mills **		out -- output string (result)
217*d0fccfcdSGary Mills **		outlen -- maximum length of output string
218*d0fccfcdSGary Mills **
219*d0fccfcdSGary Mills **	Returns:
220*d0fccfcdSGary Mills **		true iff successful.
221*d0fccfcdSGary Mills **
222*d0fccfcdSGary Mills **	Side Effects:
223*d0fccfcdSGary Mills **		creates output string if successful.
224*d0fccfcdSGary Mills **		sets errno if unsuccessful.
225*d0fccfcdSGary Mills */
226*d0fccfcdSGary Mills 
227*d0fccfcdSGary Mills #  include <arpa/inet.h>
228*d0fccfcdSGary Mills 
229*d0fccfcdSGary Mills #  ifndef NI_MAXHOST
230*d0fccfcdSGary Mills #   define NI_MAXHOST	1025
231*d0fccfcdSGary Mills #  endif
232*d0fccfcdSGary Mills #  ifndef NI_MAXSERV
233*d0fccfcdSGary Mills #   define NI_MAXSERV	32
234*d0fccfcdSGary Mills #  endif
235*d0fccfcdSGary Mills 
236*d0fccfcdSGary Mills bool
iptostring(addr,addrlen,out,outlen)237*d0fccfcdSGary Mills iptostring(addr, addrlen, out, outlen)
238*d0fccfcdSGary Mills 	SOCKADDR *addr;
239*d0fccfcdSGary Mills 	SOCKADDR_LEN_T addrlen;
240*d0fccfcdSGary Mills 	char *out;
241*d0fccfcdSGary Mills 	unsigned outlen;
242*d0fccfcdSGary Mills {
243*d0fccfcdSGary Mills 	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
244*d0fccfcdSGary Mills #  if NETINET6
245*d0fccfcdSGary Mills 	int niflags;
246*d0fccfcdSGary Mills #  endif /* NETINET6 */
247*d0fccfcdSGary Mills 
248*d0fccfcdSGary Mills 	if (addr == NULL || out == NULL)
249*d0fccfcdSGary Mills 	{
250*d0fccfcdSGary Mills 		errno = EINVAL;
251*d0fccfcdSGary Mills 		return false;
252*d0fccfcdSGary Mills 	}
253*d0fccfcdSGary Mills 
254*d0fccfcdSGary Mills #  if NETINET6
255*d0fccfcdSGary Mills 	niflags = (NI_NUMERICHOST | NI_NUMERICSERV);
256*d0fccfcdSGary Mills #   ifdef NI_WITHSCOPEID
257*d0fccfcdSGary Mills 	if (addr->sa.sa_family == AF_INET6)
258*d0fccfcdSGary Mills 		niflags |= NI_WITHSCOPEID;
259*d0fccfcdSGary Mills #   endif /* NI_WITHSCOPEID */
260*d0fccfcdSGary Mills 	if (getnameinfo((struct sockaddr *) addr, addrlen,
261*d0fccfcdSGary Mills 			hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0)
262*d0fccfcdSGary Mills 		return false;
263*d0fccfcdSGary Mills #  else /* NETINET6 */
264*d0fccfcdSGary Mills 	if (addr->sa.sa_family != AF_INET)
265*d0fccfcdSGary Mills 	{
266*d0fccfcdSGary Mills 		errno = EINVAL;
267*d0fccfcdSGary Mills 		return false;
268*d0fccfcdSGary Mills 	}
269*d0fccfcdSGary Mills 	if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf))
270*d0fccfcdSGary Mills 	    >= sizeof(hbuf))
271*d0fccfcdSGary Mills 	{
272*d0fccfcdSGary Mills 		errno = ENOMEM;
273*d0fccfcdSGary Mills 		return false;
274*d0fccfcdSGary Mills 	}
275*d0fccfcdSGary Mills 	sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port));
276*d0fccfcdSGary Mills #  endif /* NETINET6 */
277*d0fccfcdSGary Mills 
278*d0fccfcdSGary Mills 	if (outlen < strlen(hbuf) + strlen(pbuf) + 2)
279*d0fccfcdSGary Mills 	{
280*d0fccfcdSGary Mills 		errno = ENOMEM;
281*d0fccfcdSGary Mills 		return false;
282*d0fccfcdSGary Mills 	}
283*d0fccfcdSGary Mills 	sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf);
284*d0fccfcdSGary Mills 	return true;
285*d0fccfcdSGary Mills }
286*d0fccfcdSGary Mills # endif /* SASL >= 20000 */
287*d0fccfcdSGary Mills #endif /* SASL */
288