sasl.c revision 182352
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 27void *sm_sasl_malloc __P((unsigned long)); 28static void *sm_sasl_calloc __P((unsigned long, unsigned long)); 29static void *sm_sasl_realloc __P((void *, unsigned long)); 30void 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 51void * 52sm_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 72static void * 73sm_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 99static void * 100sm_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 117void 118sm_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 137void 138sm_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 154char * 155intersect(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_MAXHOST 230# define NI_MAXHOST 1025 231# endif 232# ifndef NI_MAXSERV 233# define NI_MAXSERV 32 234# endif 235 236bool 237iptostring(addr, addrlen, out, outlen) 238 SOCKADDR *addr; 239 SOCKADDR_LEN_T addrlen; 240 char *out; 241 unsigned outlen; 242{ 243 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 244# if NETINET6 245 int niflags; 246# endif /* NETINET6 */ 247 248 if (addr == NULL || out == NULL) 249 { 250 errno = EINVAL; 251 return false; 252 } 253 254# if NETINET6 255 niflags = (NI_NUMERICHOST | NI_NUMERICSERV); 256# ifdef NI_WITHSCOPEID 257 if (addr->sa.sa_family == AF_INET6) 258 niflags |= NI_WITHSCOPEID; 259# endif /* NI_WITHSCOPEID */ 260 if (getnameinfo((struct sockaddr *) addr, addrlen, 261 hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0) 262 return false; 263# else /* NETINET6 */ 264 if (addr->sa.sa_family != AF_INET) 265 { 266 errno = EINVAL; 267 return false; 268 } 269 if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf)) 270 >= sizeof(hbuf)) 271 { 272 errno = ENOMEM; 273 return false; 274 } 275 sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port)); 276# endif /* NETINET6 */ 277 278 if (outlen < strlen(hbuf) + strlen(pbuf) + 2) 279 { 280 errno = ENOMEM; 281 return false; 282 } 283 sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf); 284 return true; 285} 286# endif /* SASL >= 20000 */ 287#endif /* SASL */ 288