1/* 2 * Copyright (c) 2001-2002 Proofpoint, 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.24 2013-11-22 20:51:56 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** older sasl packages 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 30# define SM_SASL_SIZE_T unsigned long 31# endif 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 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 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