sasl.c revision 243649
10SN/A/* 22509Sihse * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. 30SN/A * All rights reserved. 40SN/A * 50SN/A * By using this file, you agree to the terms and conditions set 60SN/A * forth in the LICENSE file which can be found at the top level of 7180SN/A * the sendmail distribution. 80SN/A * 9180SN/A */ 100SN/A 110SN/A#include <sm/gen.h> 120SN/ASM_RCSID("@(#)$Id: sasl.c,v 8.22 2006/08/15 23:24:57 ca Exp $") 130SN/A 140SN/A#if SASL 150SN/A# include <stdlib.h> 160SN/A# include <sendmail.h> 170SN/A# include <errno.h> 180SN/A 190SN/A/* 200SN/A** In order to ensure that storage leaks are tracked, and to prevent 21180SN/A** conflicts between the sm_heap package and sasl, we tell sasl to 22180SN/A** use the following heap allocation functions. Unfortunately, 23180SN/A** the sasl package incorrectly specifies the size of a block 240SN/A** using unsigned long: for portability, it should be size_t. 250SN/A*/ 261410Sihse 271410Sihse#if defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a 281410Sihse#define SM_SASL_SIZE_T size_t 291410Sihse#else /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */ 301410Sihse#define SM_SASL_SIZE_T unsigned long 311410Sihse#endif /* defined(SASL_VERSION_FULL) && SASL_VERSION_FULL >= 0x02011a */ 32910SN/A 33910SN/Avoid *sm_sasl_malloc __P((SM_SASL_SIZE_T)); 341410Sihsestatic void *sm_sasl_calloc __P((SM_SASL_SIZE_T, SM_SASL_SIZE_T)); 355SN/Astatic void *sm_sasl_realloc __P((void *, SM_SASL_SIZE_T)); 36910SN/Avoid sm_sasl_free __P((void *)); 371410Sihse 38910SN/A/* 39338SN/A** SASLv1: 401426Sihse** We can't use an rpool for Cyrus-SASL memory management routines, 411410Sihse** since the encryption/decryption routines in Cyrus-SASL 421426Sihse** allocate/deallocate a buffer each time. Since rpool 431410Sihse** don't release memory until the very end, memory consumption is 441410Sihse** proportional to the size of an e-mail, which is unacceptable. 451426Sihse*/ 461426Sihse 47311SN/A/* 481426Sihse** SM_SASL_MALLOC -- malloc() for SASL 491426Sihse** 501426Sihse** Parameters: 511410Sihse** size -- size of requested memory. 521426Sihse** 531651Sihse** Returns: 542509Sihse** pointer to memory. 551120SN/A*/ 561410Sihse 571410Sihsevoid * 581410Sihsesm_sasl_malloc(size) 591426Sihse SM_SASL_SIZE_T size; 601426Sihse{ 611426Sihse return sm_malloc((size_t) size); 621426Sihse} 631426Sihse 641426Sihse/* 651426Sihse** SM_SASL_CALLOC -- calloc() for SASL 661426Sihse** 671426Sihse** Parameters: 681426Sihse** nelem -- number of elements. 692475Sihse** elemsize -- size of each element. 701426Sihse** 711426Sihse** Returns: 721426Sihse** pointer to memory. 731426Sihse** 741426Sihse** Notice: 751426Sihse** this isn't currently used by SASL. 761426Sihse*/ 771426Sihse 781426Sihsestatic void * 791426Sihsesm_sasl_calloc(nelem, elemsize) 801426Sihse SM_SASL_SIZE_T nelem; 811426Sihse SM_SASL_SIZE_T elemsize; 821426Sihse{ 831426Sihse size_t size; 841426Sihse void *p; 851426Sihse 861426Sihse size = (size_t) nelem * (size_t) elemsize; 871426Sihse p = sm_malloc(size); 881426Sihse if (p == NULL) 891426Sihse return NULL; 901426Sihse memset(p, '\0', size); 911426Sihse return p; 921426Sihse} 931426Sihse 941426Sihse/* 951426Sihse** SM_SASL_REALLOC -- realloc() for SASL 961426Sihse** 971426Sihse** Parameters: 981426Sihse** p -- pointer to old memory. 991426Sihse** size -- size of requested memory. 1001426Sihse** 1011426Sihse** Returns: 1021426Sihse** pointer to new memory. 1031426Sihse*/ 1041426Sihse 1051426Sihsestatic void * 1061426Sihsesm_sasl_realloc(o, size) 1071426Sihse void *o; 1081426Sihse SM_SASL_SIZE_T size; 1091426Sihse{ 1101426Sihse return sm_realloc(o, (size_t) size); 1111426Sihse} 1121426Sihse 1131426Sihse/* 1141426Sihse** SM_SASL_FREE -- free() for SASL 1151426Sihse** 1161426Sihse** Parameters: 1171426Sihse** p -- pointer to free. 1181426Sihse** 1191426Sihse** Returns: 1201426Sihse** none 1211426Sihse*/ 1221426Sihse 1231426Sihsevoid 1241410Sihsesm_sasl_free(p) 1251120SN/A void *p; 1261426Sihse{ 1271426Sihse sm_free(p); 1281426Sihse} 1291426Sihse 1301426Sihse/* 1311426Sihse** SM_SASL_INIT -- sendmail specific SASL initialization 1321426Sihse** 1331410Sihse** Parameters: 1341426Sihse** none. 1351426Sihse** 1361426Sihse** Returns: 13727SN/A** none 1381410Sihse** 1391410Sihse** Side Effects: 1401701Sihse** installs memory management routines for SASL. 1411701Sihse*/ 1421701Sihse 1431410Sihsevoid 1441410Sihsesm_sasl_init() 1451410Sihse{ 1461410Sihse sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc, 1471410Sihse sm_sasl_realloc, sm_sasl_free); 1481410Sihse} 1491410Sihse/* 1501426Sihse** INTERSECT -- create the intersection between two lists 1511426Sihse** 1521410Sihse** Parameters: 1531410Sihse** s1, s2 -- lists of items (separated by single blanks). 1541410Sihse** rpool -- resource pool from which result is allocated. 1551156SN/A** 1561120SN/A** Returns: 1571936Sihse** the intersection of both lists. 1581936Sihse*/ 1591936Sihse 1602360Sihsechar * 1611426Sihseintersect(s1, s2, rpool) 1621426Sihse char *s1, *s2; 1631426Sihse SM_RPOOL_T *rpool; 1641410Sihse{ 16527SN/A char *hr, *h1, *h, *res; 1661426Sihse int l1, l2, rl; 1671426Sihse 1681426Sihse if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */ 1691426Sihse return NULL; 1701426Sihse l1 = strlen(s1); 1711426Sihse l2 = strlen(s2); 1721651Sihse rl = SM_MIN(l1, l2); 1731651Sihse res = (char *) sm_rpool_malloc(rpool, rl + 1); 1741915Sihse if (res == NULL) 1751651Sihse return NULL; 1761651Sihse *res = '\0'; 1771651Sihse if (rl == 0) /* at least one string empty? */ 1781651Sihse return res; 1791426Sihse hr = res; 1801426Sihse h1 = s1; 1811426Sihse h = s1; 1821426Sihse 1831651Sihse /* walk through s1 */ 1841426Sihse while (h != NULL && *h1 != '\0') 1851410Sihse { 1861410Sihse /* is there something after the current word? */ 1871410Sihse if ((h = strchr(h1, ' ')) != NULL) 1881651Sihse *h = '\0'; 1891410Sihse l1 = strlen(h1); 1901426Sihse 1911651Sihse /* does the current word appear in s2 ? */ 1921651Sihse if (iteminlist(h1, s2, " ") != NULL) 1931651Sihse { 1941651Sihse /* add a blank if not first item */ 1951651Sihse if (hr != res) 1961651Sihse *hr++ = ' '; 1971651Sihse 1981651Sihse /* copy the item */ 1991651Sihse memcpy(hr, h1, l1); 2001651Sihse 2011651Sihse /* advance pointer in result list */ 2021651Sihse hr += l1; 2031651Sihse *hr = '\0'; 2041651Sihse } 2051410Sihse if (h != NULL) 2061410Sihse { 2071410Sihse /* there are more items */ 2081410Sihse *h = ' '; 2090SN/A h1 = h + 1; 2101426Sihse } 2111410Sihse } 2121410Sihse return res; 2131410Sihse} 2141410Sihse# if SASL >= 20000 2151410Sihse/* 2161410Sihse** IPTOSTRING -- create string for SASL_IP*PORT property 2171410Sihse** (borrowed from lib/iptostring.c in Cyrus-IMAP) 2181410Sihse** 2191410Sihse** Parameters: 2201426Sihse** addr -- (pointer to) socket address 2211426Sihse** addrlen -- length of socket address 2221426Sihse** out -- output string (result) 2231426Sihse** outlen -- maximum length of output string 2241426Sihse** 2251426Sihse** Returns: 2261426Sihse** true iff successful. 2271426Sihse** 2281651Sihse** Side Effects: 2291651Sihse** creates output string if successful. 2301651Sihse** sets errno if unsuccessful. 2311410Sihse*/ 2321862Serikj 2331862Serikj# include <arpa/inet.h> 2341410Sihse 2351410Sihse# ifndef NI_MAXHOST 2361410Sihse# define NI_MAXHOST 1025 2371410Sihse# endif 2381410Sihse# ifndef NI_MAXSERV 2391410Sihse# define NI_MAXSERV 32 2401426Sihse# endif 2411426Sihse 2421426Sihsebool 2431426Sihseiptostring(addr, addrlen, out, outlen) 2441426Sihse SOCKADDR *addr; 2451426Sihse SOCKADDR_LEN_T addrlen; 2461426Sihse char *out; 2471426Sihse unsigned outlen; 2481426Sihse{ 2491426Sihse char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 2501426Sihse# if NETINET6 2511426Sihse int niflags; 2521426Sihse# endif /* NETINET6 */ 2531327SN/A 2542509Sihse if (addr == NULL || out == NULL) 2552509Sihse { 2562509Sihse errno = EINVAL; 2572509Sihse return false; 2582509Sihse } 2591628Sihse 2601628Sihse# if NETINET6 2611628Sihse niflags = (NI_NUMERICHOST | NI_NUMERICSERV); 2621410Sihse# ifdef NI_WITHSCOPEID 2631410Sihse if (addr->sa.sa_family == AF_INET6) 2641410Sihse niflags |= NI_WITHSCOPEID; 2651410Sihse# endif /* NI_WITHSCOPEID */ 2661410Sihse if (getnameinfo((struct sockaddr *) addr, addrlen, 2671410Sihse hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), niflags) != 0) 2681410Sihse return false; 2691410Sihse# else /* NETINET6 */ 2701410Sihse if (addr->sa.sa_family != AF_INET) 2711426Sihse { 2721426Sihse errno = EINVAL; 2731426Sihse return false; 2741410Sihse } 2751651Sihse if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf)) 2762034Serikj >= sizeof(hbuf)) 2772034Serikj { 2782034Serikj errno = ENOMEM; 2792034Serikj return false; 2802034Serikj } 2811426Sihse sm_snprintf(pbuf, sizeof(pbuf), "%d", ntohs(addr->sin.sin_port)); 2822034Serikj# endif /* NETINET6 */ 2831410Sihse 2841410Sihse if (outlen < strlen(hbuf) + strlen(pbuf) + 2) 2851410Sihse { 2862360Sihse errno = ENOMEM; 2871410Sihse return false; 2880SN/A } 2891426Sihse sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf); 2901426Sihse return true; 2911426Sihse} 2921623Sihse# endif /* SASL >= 20000 */ 2931862Serikj#endif /* SASL */ 2941426Sihse