190792Sgshapiro/* 2261363Sgshapiro * Copyright (c) 2001-2002 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * 590792Sgshapiro * By using this file, you agree to the terms and conditions set 690792Sgshapiro * forth in the LICENSE file which can be found at the top level of 790792Sgshapiro * the sendmail distribution. 890792Sgshapiro * 990792Sgshapiro */ 1090792Sgshapiro 1194334Sgshapiro#include <sm/gen.h> 12266692SgshapiroSM_RCSID("@(#)$Id: sasl.c,v 8.24 2013-11-22 20:51:56 ca Exp $") 1394334Sgshapiro 1490792Sgshapiro#if SASL 1590792Sgshapiro# include <stdlib.h> 1690792Sgshapiro# include <sendmail.h> 1790792Sgshapiro# include <errno.h> 1890792Sgshapiro 1990792Sgshapiro/* 2090792Sgshapiro** In order to ensure that storage leaks are tracked, and to prevent 2190792Sgshapiro** conflicts between the sm_heap package and sasl, we tell sasl to 2290792Sgshapiro** use the following heap allocation functions. Unfortunately, 23244833Sgshapiro** older sasl packages incorrectly specifies the size of a block 2490792Sgshapiro** using unsigned long: for portability, it should be size_t. 2590792Sgshapiro*/ 2690792Sgshapiro 27244833Sgshapiro# if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a 28244833Sgshapiro# define SM_SASL_SIZE_T size_t 29244833Sgshapiro# else /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */ 30244833Sgshapiro# define SM_SASL_SIZE_T unsigned long 31244833Sgshapiro# endif /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */ 32243649Sume 33243649Sumevoid *sm_sasl_malloc __P((SM_SASL_SIZE_T)); 34243649Sumestatic void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T)); 35243649Sumestatic void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T)); 3690792Sgshapirovoid sm_sasl_free __P((void *)); 3790792Sgshapiro 3890792Sgshapiro/* 3998121Sgshapiro** SASLv1: 4090792Sgshapiro** We can't use an rpool for Cyrus-SASL memory management routines, 4190792Sgshapiro** since the encryption/decryption routines in Cyrus-SASL 4290792Sgshapiro** allocate/deallocate a buffer each time. Since rpool 4390792Sgshapiro** don't release memory until the very end, memory consumption is 4490792Sgshapiro** proportional to the size of an e-mail, which is unacceptable. 4590792Sgshapiro*/ 4690792Sgshapiro 4790792Sgshapiro/* 4890792Sgshapiro** SM_SASL_MALLOC -- malloc() for SASL 4990792Sgshapiro** 5090792Sgshapiro** Parameters: 5190792Sgshapiro** size -- size of requested memory. 5290792Sgshapiro** 5390792Sgshapiro** Returns: 5490792Sgshapiro** pointer to memory. 5590792Sgshapiro*/ 5690792Sgshapiro 5790792Sgshapirovoid * 5890792Sgshapirosm_sasl_malloc(size) 59243649Sume SM_SASL_SIZE_T size; 6090792Sgshapiro{ 6190792Sgshapiro return sm_malloc((size_t) size); 6290792Sgshapiro} 6390792Sgshapiro 6490792Sgshapiro/* 6590792Sgshapiro** SM_SASL_CALLOC -- calloc() for SASL 6690792Sgshapiro** 6790792Sgshapiro** Parameters: 6890792Sgshapiro** nelem -- number of elements. 6990792Sgshapiro** elemsize -- size of each element. 7090792Sgshapiro** 7190792Sgshapiro** Returns: 7290792Sgshapiro** pointer to memory. 7390792Sgshapiro** 7490792Sgshapiro** Notice: 7590792Sgshapiro** this isn't currently used by SASL. 7690792Sgshapiro*/ 7790792Sgshapiro 7890792Sgshapirostatic void * 7990792Sgshapirosm_sasl_calloc(nelem, elemsize) 80243649Sume SM_SASL_SIZE_T nelem; 81243649Sume SM_SASL_SIZE_T elemsize; 8290792Sgshapiro{ 8390792Sgshapiro size_t size; 8490792Sgshapiro void *p; 8590792Sgshapiro 8690792Sgshapiro size = (size_t) nelem * (size_t) elemsize; 8790792Sgshapiro p = sm_malloc(size); 8890792Sgshapiro if (p == NULL) 8990792Sgshapiro return NULL; 9090792Sgshapiro memset(p, '\0', size); 9190792Sgshapiro return p; 9290792Sgshapiro} 9390792Sgshapiro 9490792Sgshapiro/* 9590792Sgshapiro** SM_SASL_REALLOC -- realloc() for SASL 9690792Sgshapiro** 9790792Sgshapiro** Parameters: 9890792Sgshapiro** p -- pointer to old memory. 9990792Sgshapiro** size -- size of requested memory. 10090792Sgshapiro** 10190792Sgshapiro** Returns: 10290792Sgshapiro** pointer to new memory. 10390792Sgshapiro*/ 10490792Sgshapiro 10590792Sgshapirostatic void * 10690792Sgshapirosm_sasl_realloc(o, size) 10790792Sgshapiro void *o; 108243649Sume SM_SASL_SIZE_T size; 10990792Sgshapiro{ 11090792Sgshapiro return sm_realloc(o, (size_t) size); 11190792Sgshapiro} 11290792Sgshapiro 11390792Sgshapiro/* 11490792Sgshapiro** SM_SASL_FREE -- free() for SASL 11590792Sgshapiro** 11690792Sgshapiro** Parameters: 11790792Sgshapiro** p -- pointer to free. 11890792Sgshapiro** 11990792Sgshapiro** Returns: 12090792Sgshapiro** none 12190792Sgshapiro*/ 12290792Sgshapiro 12390792Sgshapirovoid 12490792Sgshapirosm_sasl_free(p) 12590792Sgshapiro void *p; 12690792Sgshapiro{ 12790792Sgshapiro sm_free(p); 12890792Sgshapiro} 12990792Sgshapiro 13090792Sgshapiro/* 13190792Sgshapiro** SM_SASL_INIT -- sendmail specific SASL initialization 13290792Sgshapiro** 13390792Sgshapiro** Parameters: 13490792Sgshapiro** none. 13590792Sgshapiro** 13690792Sgshapiro** Returns: 13790792Sgshapiro** none 13890792Sgshapiro** 13990792Sgshapiro** Side Effects: 14090792Sgshapiro** installs memory management routines for SASL. 14190792Sgshapiro*/ 14290792Sgshapiro 14390792Sgshapirovoid 14490792Sgshapirosm_sasl_init() 14590792Sgshapiro{ 14690792Sgshapiro sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc, 14790792Sgshapiro sm_sasl_realloc, sm_sasl_free); 14890792Sgshapiro} 14990792Sgshapiro/* 15090792Sgshapiro** INTERSECT -- create the intersection between two lists 15190792Sgshapiro** 15290792Sgshapiro** Parameters: 15390792Sgshapiro** s1, s2 -- lists of items (separated by single blanks). 15490792Sgshapiro** rpool -- resource pool from which result is allocated. 15590792Sgshapiro** 15690792Sgshapiro** Returns: 15790792Sgshapiro** the intersection of both lists. 15890792Sgshapiro*/ 15990792Sgshapiro 16090792Sgshapirochar * 16190792Sgshapirointersect(s1, s2, rpool) 16290792Sgshapiro char *s1, *s2; 16390792Sgshapiro SM_RPOOL_T *rpool; 16490792Sgshapiro{ 16590792Sgshapiro char *hr, *h1, *h, *res; 16690792Sgshapiro int l1, l2, rl; 16790792Sgshapiro 16890792Sgshapiro if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */ 16990792Sgshapiro return NULL; 17090792Sgshapiro l1 = strlen(s1); 17190792Sgshapiro l2 = strlen(s2); 17290792Sgshapiro rl = SM_MIN(l1, l2); 17390792Sgshapiro res = (char *) sm_rpool_malloc(rpool, rl + 1); 17490792Sgshapiro if (res == NULL) 17590792Sgshapiro return NULL; 17690792Sgshapiro *res = '\0'; 17790792Sgshapiro if (rl == 0) /* at least one string empty? */ 17890792Sgshapiro return res; 17990792Sgshapiro hr = res; 18090792Sgshapiro h1 = s1; 18190792Sgshapiro h = s1; 18290792Sgshapiro 18390792Sgshapiro /* walk through s1 */ 18490792Sgshapiro while (h != NULL && *h1 != '\0') 18590792Sgshapiro { 18690792Sgshapiro /* is there something after the current word? */ 18790792Sgshapiro if ((h = strchr(h1, ' ')) != NULL) 18890792Sgshapiro *h = '\0'; 18990792Sgshapiro l1 = strlen(h1); 19090792Sgshapiro 19190792Sgshapiro /* does the current word appear in s2 ? */ 19290792Sgshapiro if (iteminlist(h1, s2, " ") != NULL) 19390792Sgshapiro { 19490792Sgshapiro /* add a blank if not first item */ 19590792Sgshapiro if (hr != res) 19690792Sgshapiro *hr++ = ' '; 19790792Sgshapiro 19890792Sgshapiro /* copy the item */ 19990792Sgshapiro memcpy(hr, h1, l1); 20090792Sgshapiro 20190792Sgshapiro /* advance pointer in result list */ 20290792Sgshapiro hr += l1; 20390792Sgshapiro *hr = '\0'; 20490792Sgshapiro } 20590792Sgshapiro if (h != NULL) 20690792Sgshapiro { 20790792Sgshapiro /* there are more items */ 20890792Sgshapiro *h = ' '; 20990792Sgshapiro h1 = h + 1; 21090792Sgshapiro } 21190792Sgshapiro } 21290792Sgshapiro return res; 21390792Sgshapiro} 21498121Sgshapiro# if SASL >= 20000 21598121Sgshapiro/* 21698121Sgshapiro** IPTOSTRING -- create string for SASL_IP*PORT property 217132943Sgshapiro** (borrowed from lib/iptostring.c in Cyrus-IMAP) 21898121Sgshapiro** 21998121Sgshapiro** Parameters: 22098121Sgshapiro** addr -- (pointer to) socket address 22198121Sgshapiro** addrlen -- length of socket address 22298121Sgshapiro** out -- output string (result) 22398121Sgshapiro** outlen -- maximum length of output string 22498121Sgshapiro** 22598121Sgshapiro** Returns: 22698121Sgshapiro** true iff successful. 22798121Sgshapiro** 22898121Sgshapiro** Side Effects: 22998121Sgshapiro** creates output string if successful. 23098121Sgshapiro** sets errno if unsuccessful. 23198121Sgshapiro*/ 23298121Sgshapiro 23398121Sgshapiro# include <arpa/inet.h> 23498121Sgshapiro 23598121Sgshapiro# ifndef NI_MAXHOST 23698121Sgshapiro# define NI_MAXHOST 1025 23798121Sgshapiro# endif 23898121Sgshapiro# ifndef NI_MAXSERV 23998121Sgshapiro# define NI_MAXSERV 32 24098121Sgshapiro# endif 24198121Sgshapiro 24298121Sgshapirobool 24398121Sgshapiroiptostring(addr, addrlen, out, outlen) 24498121Sgshapiro SOCKADDR *addr; 24598121Sgshapiro SOCKADDR_LEN_T addrlen; 24698121Sgshapiro char *out; 24798121Sgshapiro unsigned outlen; 24898121Sgshapiro{ 24998121Sgshapiro char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 250141858Sgshapiro# if NETINET6 251141858Sgshapiro int niflags; 252141858Sgshapiro# endif /* NETINET6 */ 25398121Sgshapiro 25498121Sgshapiro if (addr == NULL || out == NULL) 25598121Sgshapiro { 25698121Sgshapiro errno = EINVAL; 25798121Sgshapiro return false; 25898121Sgshapiro } 25998121Sgshapiro 26098121Sgshapiro# if NETINET6 261141858Sgshapiro niflags = (NI_NUMERICHOST | NI_NUMERICSERV); 262141858Sgshapiro# ifdef NI_WITHSCOPEID 263141858Sgshapiro if (addr->sa.sa_family == AF_INET6) 264141858Sgshapiro niflags |= NI_WITHSCOPEID; 265141858Sgshapiro# endif /* NI_WITHSCOPEID */ 26698121Sgshapiro if (getnameinfo((struct sockaddr *) addr, addrlen, 267168515Sgshapiro hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0) 26898121Sgshapiro return false; 26998121Sgshapiro# else /* NETINET6 */ 27098121Sgshapiro if (addr->sa.sa_family != AF_INET) 27198121Sgshapiro { 27298121Sgshapiro errno = EINVAL; 27398121Sgshapiro return false; 27498121Sgshapiro } 27598841Sgshapiro if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf)) 27698841Sgshapiro >= sizeof(hbuf)) 27798121Sgshapiro { 27898841Sgshapiro errno = ENOMEM; 27998121Sgshapiro return false; 28098121Sgshapiro } 281168515Sgshapiro sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port)); 28298121Sgshapiro# endif /* NETINET6 */ 28398121Sgshapiro 28498121Sgshapiro if (outlen < strlen(hbuf) + strlen(pbuf) + 2) 28598121Sgshapiro { 28698121Sgshapiro errno = ENOMEM; 28798121Sgshapiro return false; 28898121Sgshapiro } 28998121Sgshapiro sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf); 29098121Sgshapiro return true; 29198121Sgshapiro} 29298121Sgshapiro# endif /* SASL >= 20000 */ 29390792Sgshapiro#endif /* SASL */ 294