Deleted Added
sdiff udiff text old ( 243649 ) new ( 244833 )
full compact
1/*
2 * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sm/gen.h>
12SM_RCSID("@(#)$Id: sasl.c,v 8.22 2006/08/15 23:24:57 ca Exp $")
13
14#if SASL
15# include <stdlib.h>
16# include <sendmail.h>
17# include <errno.h>
18
19/*
20** In order to ensure that storage leaks are tracked, and to prevent
21** conflicts between the sm_heap package and sasl, we tell sasl to
22** use the following heap allocation functions. Unfortunately,
23** the sasl package incorrectly specifies the size of a block
24** using unsigned long: for portability, it should be size_t.
25*/
26
27#if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a
28#define SM_SASL_SIZE_T size_t
29#else /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */
30#define SM_SASL_SIZE_T unsigned long
31#endif /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */
32
33void *sm_sasl_malloc __P((SM_SASL_SIZE_T));
34static void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T));
35static void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T));
36void sm_sasl_free __P((void *));
37
38/*
39** SASLv1:
40** We can't use an rpool for Cyrus-SASL memory management routines,
41** since the encryption/decryption routines in Cyrus-SASL
42** allocate/deallocate a buffer each time. Since rpool
43** don't release memory until the very end, memory consumption is
44** proportional to the size of an e-mail, which is unacceptable.
45*/
46
47/*
48** SM_SASL_MALLOC -- malloc() for SASL
49**
50** Parameters:
51** size -- size of requested memory.
52**
53** Returns:
54** pointer to memory.
55*/
56
57void *
58sm_sasl_malloc(size)
59 SM_SASL_SIZE_T size;
60{
61 return sm_malloc((size_t) size);
62}
63
64/*
65** SM_SASL_CALLOC -- calloc() for SASL
66**
67** Parameters:
68** nelem -- number of elements.
69** elemsize -- size of each element.
70**
71** Returns:
72** pointer to memory.
73**
74** Notice:
75** this isn't currently used by SASL.
76*/
77
78static void *
79sm_sasl_calloc(nelem, elemsize)
80 SM_SASL_SIZE_T nelem;
81 SM_SASL_SIZE_T elemsize;
82{
83 size_t size;
84 void *p;
85
86 size = (size_t) nelem * (size_t) elemsize;
87 p = sm_malloc(size);
88 if (p == NULL)
89 return NULL;
90 memset(p, '\0', size);
91 return p;
92}
93
94/*
95** SM_SASL_REALLOC -- realloc() for SASL
96**
97** Parameters:
98** p -- pointer to old memory.
99** size -- size of requested memory.
100**
101** Returns:
102** pointer to new memory.
103*/
104
105static void *
106sm_sasl_realloc(o, size)
107 void *o;
108 SM_SASL_SIZE_T size;
109{
110 return sm_realloc(o, (size_t) size);
111}
112
113/*
114** SM_SASL_FREE -- free() for SASL
115**
116** Parameters:
117** p -- pointer to free.
118**
119** Returns:
120** none
121*/
122
123void
124sm_sasl_free(p)
125 void *p;
126{
127 sm_free(p);
128}
129
130/*
131** SM_SASL_INIT -- sendmail specific SASL initialization
132**
133** Parameters:
134** none.
135**
136** Returns:
137** none
138**
139** Side Effects:
140** installs memory management routines for SASL.
141*/
142
143void
144sm_sasl_init()
145{
146 sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc,
147 sm_sasl_realloc, sm_sasl_free);
148}
149/*
150** INTERSECT -- create the intersection between two lists
151**
152** Parameters:
153** s1, s2 -- lists of items (separated by single blanks).
154** rpool -- resource pool from which result is allocated.
155**
156** Returns:
157** the intersection of both lists.
158*/
159
160char *
161intersect(s1, s2, rpool)
162 char *s1, *s2;
163 SM_RPOOL_T *rpool;
164{
165 char *hr, *h1, *h, *res;
166 int l1, l2, rl;
167
168 if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */
169 return NULL;
170 l1 = strlen(s1);
171 l2 = strlen(s2);
172 rl = SM_MIN(l1, l2);
173 res = (char *) sm_rpool_malloc(rpool, rl + 1);
174 if (res == NULL)
175 return NULL;
176 *res = '\0';
177 if (rl == 0) /* at least one string empty? */
178 return res;
179 hr = res;
180 h1 = s1;
181 h = s1;
182
183 /* walk through s1 */
184 while (h != NULL && *h1 != '\0')
185 {
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 */