sasl.c revision 261194
1196200Sscottl/* 2196200Sscottl * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers. 3196200Sscottl * All rights reserved. 4196200Sscottl * 5196200Sscottl * By using this file, you agree to the terms and conditions set 6196200Sscottl * forth in the LICENSE file which can be found at the top level of 7196200Sscottl * the sendmail distribution. 8196200Sscottl * 9196200Sscottl */ 10196200Sscottl 11196200Sscottl#include <sm/gen.h> 12196200SscottlSM_RCSID("@(#)$Id: sasl.c,v 8.24 2013/11/22 20:51:56 ca Exp $") 13196200Sscottl 14196200Sscottl#if SASL 15196200Sscottl# include <stdlib.h> 16196200Sscottl# include <sendmail.h> 17196200Sscottl# include <errno.h> 18196200Sscottl 19196200Sscottl/* 20196200Sscottl** In order to ensure that storage leaks are tracked, and to prevent 21196200Sscottl** conflicts between the sm_heap package and sasl, we tell sasl to 22196200Sscottl** use the following heap allocation functions. Unfortunately, 23196200Sscottl** older sasl packages incorrectly specifies the size of a block 24196200Sscottl** using unsigned long: for portability, it should be size_t. 25196200Sscottl*/ 26196200Sscottl 27196200Sscottl# if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a 28196200Sscottl# define SM_SASL_SIZE_T size_t 29196200Sscottl# else /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */ 30196200Sscottl# define SM_SASL_SIZE_T unsigned long 31196200Sscottl# endif /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */ 32196200Sscottl 33196200Sscottlvoid *sm_sasl_malloc __P((SM_SASL_SIZE_T)); 34196200Sscottlstatic void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T)); 35196200Sscottlstatic void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T)); 36196200Sscottlvoid sm_sasl_free __P((void *)); 37196200Sscottl 38196200Sscottl/* 39196200Sscottl** SASLv1: 40196200Sscottl** We can't use an rpool for Cyrus-SASL memory management routines, 41196200Sscottl** since the encryption/decryption routines in Cyrus-SASL 42196200Sscottl** allocate/deallocate a buffer each time. Since rpool 43196200Sscottl** don't release memory until the very end, memory consumption is 44196200Sscottl** proportional to the size of an e-mail, which is unacceptable. 45196200Sscottl*/ 46196200Sscottl 47223345Sbz/* 48241776Sed** SM_SASL_MALLOC -- malloc() for SASL 49223345Sbz** 50196200Sscottl** Parameters: 51196200Sscottl** size -- size of requested memory. 52196200Sscottl** 53196200Sscottl** Returns: 54223345Sbz** pointer to memory. 55196200Sscottl*/ 56196200Sscottl 57196200Sscottlvoid * 58196200Sscottlsm_sasl_malloc(size) 59196200Sscottl SM_SASL_SIZE_T size; 60196200Sscottl{ 61196200Sscottl return sm_malloc((size_t) size); 62196200Sscottl} 63251516Ssbruno 64223267Sbz/* 65196200Sscottl** SM_SASL_CALLOC -- calloc() for SASL 66196200Sscottl** 67221208Sjhb** Parameters: 68196200Sscottl** nelem -- number of elements. 69254906Ssbruno** elemsize -- size of each element. 70196200Sscottl** 71254906Ssbruno** Returns: 72196200Sscottl** pointer to memory. 73196200Sscottl** 74196200Sscottl** Notice: 75196200Sscottl** this isn't currently used by SASL. 76196200Sscottl*/ 77196200Sscottl 78196200Sscottlstatic void * 79196200Sscottlsm_sasl_calloc(nelem, elemsize) 80196200Sscottl SM_SASL_SIZE_T nelem; 81196200Sscottl SM_SASL_SIZE_T elemsize; 82196200Sscottl{ 83196200Sscottl size_t size; 84196200Sscottl void *p; 85196200Sscottl 86196200Sscottl size = (size_t) nelem * (size_t) elemsize; 87196200Sscottl p = sm_malloc(size); 88251516Ssbruno if (p == NULL) 89251516Ssbruno return NULL; 90251516Ssbruno memset(p, '\0', size); 91251516Ssbruno return p; 92251516Ssbruno} 93196200Sscottl 94249257Smarkj/* 95249257Smarkj** SM_SASL_REALLOC -- realloc() for SASL 96272041Ssmh** 97272041Ssmh** Parameters: 98196200Sscottl** p -- pointer to old memory. 99196200Sscottl** size -- size of requested memory. 100196200Sscottl** 101196200Sscottl** Returns: 102196200Sscottl** pointer to new memory. 103196200Sscottl*/ 104196200Sscottl 105196200Sscottlstatic void * 106237260Seadlersm_sasl_realloc(o, size) 107196200Sscottl void *o; 108196200Sscottl SM_SASL_SIZE_T size; 109254906Ssbruno{ 110196200Sscottl return sm_realloc(o, (size_t) size); 111196200Sscottl} 112196200Sscottl 113196200Sscottl/* 114196200Sscottl** SM_SASL_FREE -- free() for SASL 115196200Sscottl** 116196200Sscottl** Parameters: 117196200Sscottl** p -- pointer to free. 118196200Sscottl** 119196200Sscottl** Returns: 120196200Sscottl** none 121196200Sscottl*/ 122196200Sscottl 123196200Sscottlvoid 124223345Sbzsm_sasl_free(p) 125196200Sscottl void *p; 126223345Sbz{ 127223345Sbz sm_free(p); 128223345Sbz} 129223345Sbz 130223345Sbz/* 131223345Sbz** SM_SASL_INIT -- sendmail specific SASL initialization 132196200Sscottl** 133196200Sscottl** Parameters: 134196200Sscottl** none. 135196200Sscottl** 136196200Sscottl** Returns: 137196200Sscottl** none 138196200Sscottl** 139196200Sscottl** Side Effects: 140196200Sscottl** installs memory management routines for SASL. 141196200Sscottl*/ 142196200Sscottl 143196200Sscottlvoid 144196200Sscottlsm_sasl_init() 145196200Sscottl{ 146196200Sscottl sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc, 147196200Sscottl sm_sasl_realloc, sm_sasl_free); 148196200Sscottl} 149213672Srandi/* 150213672Srandi** INTERSECT -- create the intersection between two lists 151213672Srandi** 152213672Srandi** Parameters: 153196200Sscottl** s1, s2 -- lists of items (separated by single blanks). 154196200Sscottl** rpool -- resource pool from which result is allocated. 155196200Sscottl** 156213672Srandi** Returns: 157196200Sscottl** the intersection of both lists. 158241776Sed*/ 159241776Sed 160241776Sedchar * 161241776Sedintersect(s1, s2, rpool) 162241776Sed char *s1, *s2; 163241776Sed SM_RPOOL_T *rpool; 164241776Sed{ 165241776Sed char *hr, *h1, *h, *res; 166241776Sed int l1, l2, rl; 167241776Sed 168241776Sed if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */ 169241776Sed return NULL; 170241776Sed l1 = strlen(s1); 171241776Sed l2 = strlen(s2); 172241776Sed rl = SM_MIN(l1, l2); 173241776Sed res = (char *) sm_rpool_malloc(rpool, rl + 1); 174241776Sed if (res == NULL) 175241776Sed return NULL; 176241776Sed *res = '\0'; 177241776Sed if (rl == 0) /* at least one string empty? */ 178241776Sed return res; 179241776Sed hr = res; 180241776Sed h1 = s1; 181241776Sed h = s1; 182241776Sed 183241776Sed /* walk through s1 */ 184241776Sed while (h != NULL && *h1 != '\0') 185241776Sed { 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 */ 294