140266059SGregory Neil Shapiro /* 2605302a5SGregory Neil Shapiro * Copyright (c) 2001-2002 Sendmail, Inc. and its suppliers. 340266059SGregory Neil Shapiro * All rights reserved. 440266059SGregory Neil Shapiro * 540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set 640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of 740266059SGregory Neil Shapiro * the sendmail distribution. 840266059SGregory Neil Shapiro * 940266059SGregory Neil Shapiro */ 1040266059SGregory Neil Shapiro 1140266059SGregory Neil Shapiro #include <sm/gen.h> 12b6bacd31SGregory Neil Shapiro SM_RCSID("@(#)$Id: sasl.c,v 8.21 2004/11/22 23:09:00 gshapiro Exp $") 13605302a5SGregory Neil Shapiro 14605302a5SGregory Neil Shapiro #if SASL 1540266059SGregory Neil Shapiro # include <stdlib.h> 1640266059SGregory Neil Shapiro # include <sendmail.h> 1740266059SGregory Neil Shapiro # include <errno.h> 1840266059SGregory Neil Shapiro 1940266059SGregory Neil Shapiro /* 2040266059SGregory Neil Shapiro ** In order to ensure that storage leaks are tracked, and to prevent 2140266059SGregory Neil Shapiro ** conflicts between the sm_heap package and sasl, we tell sasl to 2240266059SGregory Neil Shapiro ** use the following heap allocation functions. Unfortunately, 2340266059SGregory Neil Shapiro ** the sasl package incorrectly specifies the size of a block 2440266059SGregory Neil Shapiro ** using unsigned long: for portability, it should be size_t. 2540266059SGregory Neil Shapiro */ 2640266059SGregory Neil Shapiro 2740266059SGregory Neil Shapiro void *sm_sasl_malloc __P((unsigned long)); 2840266059SGregory Neil Shapiro static void *sm_sasl_calloc __P((unsigned long, unsigned long)); 2940266059SGregory Neil Shapiro static void *sm_sasl_realloc __P((void *, unsigned long)); 3040266059SGregory Neil Shapiro void sm_sasl_free __P((void *)); 3140266059SGregory Neil Shapiro 3240266059SGregory Neil Shapiro /* 3394c01205SGregory Neil Shapiro ** SASLv1: 3440266059SGregory Neil Shapiro ** We can't use an rpool for Cyrus-SASL memory management routines, 3540266059SGregory Neil Shapiro ** since the encryption/decryption routines in Cyrus-SASL 3640266059SGregory Neil Shapiro ** allocate/deallocate a buffer each time. Since rpool 3740266059SGregory Neil Shapiro ** don't release memory until the very end, memory consumption is 3840266059SGregory Neil Shapiro ** proportional to the size of an e-mail, which is unacceptable. 3940266059SGregory Neil Shapiro */ 4040266059SGregory Neil Shapiro 4140266059SGregory Neil Shapiro /* 4240266059SGregory Neil Shapiro ** SM_SASL_MALLOC -- malloc() for SASL 4340266059SGregory Neil Shapiro ** 4440266059SGregory Neil Shapiro ** Parameters: 4540266059SGregory Neil Shapiro ** size -- size of requested memory. 4640266059SGregory Neil Shapiro ** 4740266059SGregory Neil Shapiro ** Returns: 4840266059SGregory Neil Shapiro ** pointer to memory. 4940266059SGregory Neil Shapiro */ 5040266059SGregory Neil Shapiro 5140266059SGregory Neil Shapiro void * 5240266059SGregory Neil Shapiro sm_sasl_malloc(size) 5340266059SGregory Neil Shapiro unsigned long size; 5440266059SGregory Neil Shapiro { 5540266059SGregory Neil Shapiro return sm_malloc((size_t) size); 5640266059SGregory Neil Shapiro } 5740266059SGregory Neil Shapiro 5840266059SGregory Neil Shapiro /* 5940266059SGregory Neil Shapiro ** SM_SASL_CALLOC -- calloc() for SASL 6040266059SGregory Neil Shapiro ** 6140266059SGregory Neil Shapiro ** Parameters: 6240266059SGregory Neil Shapiro ** nelem -- number of elements. 6340266059SGregory Neil Shapiro ** elemsize -- size of each element. 6440266059SGregory Neil Shapiro ** 6540266059SGregory Neil Shapiro ** Returns: 6640266059SGregory Neil Shapiro ** pointer to memory. 6740266059SGregory Neil Shapiro ** 6840266059SGregory Neil Shapiro ** Notice: 6940266059SGregory Neil Shapiro ** this isn't currently used by SASL. 7040266059SGregory Neil Shapiro */ 7140266059SGregory Neil Shapiro 7240266059SGregory Neil Shapiro static void * 7340266059SGregory Neil Shapiro sm_sasl_calloc(nelem, elemsize) 7440266059SGregory Neil Shapiro unsigned long nelem; 7540266059SGregory Neil Shapiro unsigned long elemsize; 7640266059SGregory Neil Shapiro { 7740266059SGregory Neil Shapiro size_t size; 7840266059SGregory Neil Shapiro void *p; 7940266059SGregory Neil Shapiro 8040266059SGregory Neil Shapiro size = (size_t) nelem * (size_t) elemsize; 8140266059SGregory Neil Shapiro p = sm_malloc(size); 8240266059SGregory Neil Shapiro if (p == NULL) 8340266059SGregory Neil Shapiro return NULL; 8440266059SGregory Neil Shapiro memset(p, '\0', size); 8540266059SGregory Neil Shapiro return p; 8640266059SGregory Neil Shapiro } 8740266059SGregory Neil Shapiro 8840266059SGregory Neil Shapiro /* 8940266059SGregory Neil Shapiro ** SM_SASL_REALLOC -- realloc() for SASL 9040266059SGregory Neil Shapiro ** 9140266059SGregory Neil Shapiro ** Parameters: 9240266059SGregory Neil Shapiro ** p -- pointer to old memory. 9340266059SGregory Neil Shapiro ** size -- size of requested memory. 9440266059SGregory Neil Shapiro ** 9540266059SGregory Neil Shapiro ** Returns: 9640266059SGregory Neil Shapiro ** pointer to new memory. 9740266059SGregory Neil Shapiro */ 9840266059SGregory Neil Shapiro 9940266059SGregory Neil Shapiro static void * 10040266059SGregory Neil Shapiro sm_sasl_realloc(o, size) 10140266059SGregory Neil Shapiro void *o; 10240266059SGregory Neil Shapiro unsigned long size; 10340266059SGregory Neil Shapiro { 10440266059SGregory Neil Shapiro return sm_realloc(o, (size_t) size); 10540266059SGregory Neil Shapiro } 10640266059SGregory Neil Shapiro 10740266059SGregory Neil Shapiro /* 10840266059SGregory Neil Shapiro ** SM_SASL_FREE -- free() for SASL 10940266059SGregory Neil Shapiro ** 11040266059SGregory Neil Shapiro ** Parameters: 11140266059SGregory Neil Shapiro ** p -- pointer to free. 11240266059SGregory Neil Shapiro ** 11340266059SGregory Neil Shapiro ** Returns: 11440266059SGregory Neil Shapiro ** none 11540266059SGregory Neil Shapiro */ 11640266059SGregory Neil Shapiro 11740266059SGregory Neil Shapiro void 11840266059SGregory Neil Shapiro sm_sasl_free(p) 11940266059SGregory Neil Shapiro void *p; 12040266059SGregory Neil Shapiro { 12140266059SGregory Neil Shapiro sm_free(p); 12240266059SGregory Neil Shapiro } 12340266059SGregory Neil Shapiro 12440266059SGregory Neil Shapiro /* 12540266059SGregory Neil Shapiro ** SM_SASL_INIT -- sendmail specific SASL initialization 12640266059SGregory Neil Shapiro ** 12740266059SGregory Neil Shapiro ** Parameters: 12840266059SGregory Neil Shapiro ** none. 12940266059SGregory Neil Shapiro ** 13040266059SGregory Neil Shapiro ** Returns: 13140266059SGregory Neil Shapiro ** none 13240266059SGregory Neil Shapiro ** 13340266059SGregory Neil Shapiro ** Side Effects: 13440266059SGregory Neil Shapiro ** installs memory management routines for SASL. 13540266059SGregory Neil Shapiro */ 13640266059SGregory Neil Shapiro 13740266059SGregory Neil Shapiro void 13840266059SGregory Neil Shapiro sm_sasl_init() 13940266059SGregory Neil Shapiro { 14040266059SGregory Neil Shapiro sasl_set_alloc(sm_sasl_malloc, sm_sasl_calloc, 14140266059SGregory Neil Shapiro sm_sasl_realloc, sm_sasl_free); 14240266059SGregory Neil Shapiro } 14340266059SGregory Neil Shapiro /* 14440266059SGregory Neil Shapiro ** INTERSECT -- create the intersection between two lists 14540266059SGregory Neil Shapiro ** 14640266059SGregory Neil Shapiro ** Parameters: 14740266059SGregory Neil Shapiro ** s1, s2 -- lists of items (separated by single blanks). 14840266059SGregory Neil Shapiro ** rpool -- resource pool from which result is allocated. 14940266059SGregory Neil Shapiro ** 15040266059SGregory Neil Shapiro ** Returns: 15140266059SGregory Neil Shapiro ** the intersection of both lists. 15240266059SGregory Neil Shapiro */ 15340266059SGregory Neil Shapiro 15440266059SGregory Neil Shapiro char * 15540266059SGregory Neil Shapiro intersect(s1, s2, rpool) 15640266059SGregory Neil Shapiro char *s1, *s2; 15740266059SGregory Neil Shapiro SM_RPOOL_T *rpool; 15840266059SGregory Neil Shapiro { 15940266059SGregory Neil Shapiro char *hr, *h1, *h, *res; 16040266059SGregory Neil Shapiro int l1, l2, rl; 16140266059SGregory Neil Shapiro 16240266059SGregory Neil Shapiro if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */ 16340266059SGregory Neil Shapiro return NULL; 16440266059SGregory Neil Shapiro l1 = strlen(s1); 16540266059SGregory Neil Shapiro l2 = strlen(s2); 16640266059SGregory Neil Shapiro rl = SM_MIN(l1, l2); 16740266059SGregory Neil Shapiro res = (char *) sm_rpool_malloc(rpool, rl + 1); 16840266059SGregory Neil Shapiro if (res == NULL) 16940266059SGregory Neil Shapiro return NULL; 17040266059SGregory Neil Shapiro *res = '\0'; 17140266059SGregory Neil Shapiro if (rl == 0) /* at least one string empty? */ 17240266059SGregory Neil Shapiro return res; 17340266059SGregory Neil Shapiro hr = res; 17440266059SGregory Neil Shapiro h1 = s1; 17540266059SGregory Neil Shapiro h = s1; 17640266059SGregory Neil Shapiro 17740266059SGregory Neil Shapiro /* walk through s1 */ 17840266059SGregory Neil Shapiro while (h != NULL && *h1 != '\0') 17940266059SGregory Neil Shapiro { 18040266059SGregory Neil Shapiro /* is there something after the current word? */ 18140266059SGregory Neil Shapiro if ((h = strchr(h1, ' ')) != NULL) 18240266059SGregory Neil Shapiro *h = '\0'; 18340266059SGregory Neil Shapiro l1 = strlen(h1); 18440266059SGregory Neil Shapiro 18540266059SGregory Neil Shapiro /* does the current word appear in s2 ? */ 18640266059SGregory Neil Shapiro if (iteminlist(h1, s2, " ") != NULL) 18740266059SGregory Neil Shapiro { 18840266059SGregory Neil Shapiro /* add a blank if not first item */ 18940266059SGregory Neil Shapiro if (hr != res) 19040266059SGregory Neil Shapiro *hr++ = ' '; 19140266059SGregory Neil Shapiro 19240266059SGregory Neil Shapiro /* copy the item */ 19340266059SGregory Neil Shapiro memcpy(hr, h1, l1); 19440266059SGregory Neil Shapiro 19540266059SGregory Neil Shapiro /* advance pointer in result list */ 19640266059SGregory Neil Shapiro hr += l1; 19740266059SGregory Neil Shapiro *hr = '\0'; 19840266059SGregory Neil Shapiro } 19940266059SGregory Neil Shapiro if (h != NULL) 20040266059SGregory Neil Shapiro { 20140266059SGregory Neil Shapiro /* there are more items */ 20240266059SGregory Neil Shapiro *h = ' '; 20340266059SGregory Neil Shapiro h1 = h + 1; 20440266059SGregory Neil Shapiro } 20540266059SGregory Neil Shapiro } 20640266059SGregory Neil Shapiro return res; 20740266059SGregory Neil Shapiro } 20894c01205SGregory Neil Shapiro # if SASL >= 20000 20994c01205SGregory Neil Shapiro /* 21094c01205SGregory Neil Shapiro ** IPTOSTRING -- create string for SASL_IP*PORT property 21194c01205SGregory Neil Shapiro ** (borrowed from lib/iptostring.c in Cyrus-IMAP) 21294c01205SGregory Neil Shapiro ** 21394c01205SGregory Neil Shapiro ** Parameters: 21494c01205SGregory Neil Shapiro ** addr -- (pointer to) socket address 21594c01205SGregory Neil Shapiro ** addrlen -- length of socket address 21694c01205SGregory Neil Shapiro ** out -- output string (result) 21794c01205SGregory Neil Shapiro ** outlen -- maximum length of output string 21894c01205SGregory Neil Shapiro ** 21994c01205SGregory Neil Shapiro ** Returns: 22094c01205SGregory Neil Shapiro ** true iff successful. 22194c01205SGregory Neil Shapiro ** 22294c01205SGregory Neil Shapiro ** Side Effects: 22394c01205SGregory Neil Shapiro ** creates output string if successful. 22494c01205SGregory Neil Shapiro ** sets errno if unsuccessful. 22594c01205SGregory Neil Shapiro */ 22694c01205SGregory Neil Shapiro 22794c01205SGregory Neil Shapiro # include <arpa/inet.h> 22894c01205SGregory Neil Shapiro 22994c01205SGregory Neil Shapiro # ifndef NI_MAXHOST 23094c01205SGregory Neil Shapiro # define NI_MAXHOST 1025 23194c01205SGregory Neil Shapiro # endif 23294c01205SGregory Neil Shapiro # ifndef NI_MAXSERV 23394c01205SGregory Neil Shapiro # define NI_MAXSERV 32 23494c01205SGregory Neil Shapiro # endif 23594c01205SGregory Neil Shapiro 23694c01205SGregory Neil Shapiro bool 23794c01205SGregory Neil Shapiro iptostring(addr, addrlen, out, outlen) 23894c01205SGregory Neil Shapiro SOCKADDR *addr; 23994c01205SGregory Neil Shapiro SOCKADDR_LEN_T addrlen; 24094c01205SGregory Neil Shapiro char *out; 24194c01205SGregory Neil Shapiro unsigned outlen; 24294c01205SGregory Neil Shapiro { 24394c01205SGregory Neil Shapiro char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 244b6bacd31SGregory Neil Shapiro # if NETINET6 245b6bacd31SGregory Neil Shapiro int niflags; 246b6bacd31SGregory Neil Shapiro # endif /* NETINET6 */ 24794c01205SGregory Neil Shapiro 24894c01205SGregory Neil Shapiro if (addr == NULL || out == NULL) 24994c01205SGregory Neil Shapiro { 25094c01205SGregory Neil Shapiro errno = EINVAL; 25194c01205SGregory Neil Shapiro return false; 25294c01205SGregory Neil Shapiro } 25394c01205SGregory Neil Shapiro 25494c01205SGregory Neil Shapiro # if NETINET6 255b6bacd31SGregory Neil Shapiro niflags = (NI_NUMERICHOST | NI_NUMERICSERV); 256b6bacd31SGregory Neil Shapiro # ifdef NI_WITHSCOPEID 257b6bacd31SGregory Neil Shapiro if (addr->sa.sa_family == AF_INET6) 258b6bacd31SGregory Neil Shapiro niflags |= NI_WITHSCOPEID; 259b6bacd31SGregory Neil Shapiro # endif /* NI_WITHSCOPEID */ 26094c01205SGregory Neil Shapiro if (getnameinfo((struct sockaddr *) addr, addrlen, 261b6bacd31SGregory Neil Shapiro hbuf, sizeof hbuf, pbuf, sizeof pbuf, niflags) != 0) 26294c01205SGregory Neil Shapiro return false; 26394c01205SGregory Neil Shapiro # else /* NETINET6 */ 26494c01205SGregory Neil Shapiro if (addr->sa.sa_family != AF_INET) 26594c01205SGregory Neil Shapiro { 26694c01205SGregory Neil Shapiro errno = EINVAL; 26794c01205SGregory Neil Shapiro return false; 26894c01205SGregory Neil Shapiro } 269739ac4d4SGregory Neil Shapiro if (sm_strlcpy(hbuf, inet_ntoa(addr->sin.sin_addr), sizeof(hbuf)) 270739ac4d4SGregory Neil Shapiro >= sizeof(hbuf)) 27194c01205SGregory Neil Shapiro { 272739ac4d4SGregory Neil Shapiro errno = ENOMEM; 27394c01205SGregory Neil Shapiro return false; 27494c01205SGregory Neil Shapiro } 27594c01205SGregory Neil Shapiro sm_snprintf(pbuf, sizeof pbuf, "%d", ntohs(addr->sin.sin_port)); 27694c01205SGregory Neil Shapiro # endif /* NETINET6 */ 27794c01205SGregory Neil Shapiro 27894c01205SGregory Neil Shapiro if (outlen < strlen(hbuf) + strlen(pbuf) + 2) 27994c01205SGregory Neil Shapiro { 28094c01205SGregory Neil Shapiro errno = ENOMEM; 28194c01205SGregory Neil Shapiro return false; 28294c01205SGregory Neil Shapiro } 28394c01205SGregory Neil Shapiro sm_snprintf(out, outlen, "%s;%s", hbuf, pbuf); 28494c01205SGregory Neil Shapiro return true; 28594c01205SGregory Neil Shapiro } 28694c01205SGregory Neil Shapiro # endif /* SASL >= 20000 */ 28740266059SGregory Neil Shapiro #endif /* SASL */ 288