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