1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 6*7c478bd9Sstevel@tonic-gate 7*7c478bd9Sstevel@tonic-gate /* Generic SASL plugin utility functions 8*7c478bd9Sstevel@tonic-gate * Rob Siemborski 9*7c478bd9Sstevel@tonic-gate * $Id: plugin_common.c,v 1.13 2003/02/13 19:56:05 rjs3 Exp $ 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate /* 12*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 15*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 16*7c478bd9Sstevel@tonic-gate * are met: 17*7c478bd9Sstevel@tonic-gate * 18*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 19*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 20*7c478bd9Sstevel@tonic-gate * 21*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 22*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 23*7c478bd9Sstevel@tonic-gate * the documentation and/or other materials provided with the 24*7c478bd9Sstevel@tonic-gate * distribution. 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * 3. The name "Carnegie Mellon University" must not be used to 27*7c478bd9Sstevel@tonic-gate * endorse or promote products derived from this software without 28*7c478bd9Sstevel@tonic-gate * prior written permission. For permission or any other legal 29*7c478bd9Sstevel@tonic-gate * details, please contact 30*7c478bd9Sstevel@tonic-gate * Office of Technology Transfer 31*7c478bd9Sstevel@tonic-gate * Carnegie Mellon University 32*7c478bd9Sstevel@tonic-gate * 5000 Forbes Avenue 33*7c478bd9Sstevel@tonic-gate * Pittsburgh, PA 15213-3890 34*7c478bd9Sstevel@tonic-gate * (412) 268-4387, fax: (412) 268-7395 35*7c478bd9Sstevel@tonic-gate * tech-transfer@andrew.cmu.edu 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * 4. Redistributions of any form whatsoever must retain the following 38*7c478bd9Sstevel@tonic-gate * acknowledgment: 39*7c478bd9Sstevel@tonic-gate * "This product includes software developed by Computing Services 40*7c478bd9Sstevel@tonic-gate * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 41*7c478bd9Sstevel@tonic-gate * 42*7c478bd9Sstevel@tonic-gate * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 43*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 44*7c478bd9Sstevel@tonic-gate * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 45*7c478bd9Sstevel@tonic-gate * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46*7c478bd9Sstevel@tonic-gate * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 47*7c478bd9Sstevel@tonic-gate * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 48*7c478bd9Sstevel@tonic-gate * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #include <config.h> 52*7c478bd9Sstevel@tonic-gate #ifndef macintosh 53*7c478bd9Sstevel@tonic-gate #ifdef WIN32 54*7c478bd9Sstevel@tonic-gate # include <winsock.h> 55*7c478bd9Sstevel@tonic-gate #else 56*7c478bd9Sstevel@tonic-gate # include <sys/socket.h> 57*7c478bd9Sstevel@tonic-gate # include <netinet/in.h> 58*7c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 59*7c478bd9Sstevel@tonic-gate # include <netdb.h> 60*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */ 61*7c478bd9Sstevel@tonic-gate #endif /* macintosh */ 62*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H 63*7c478bd9Sstevel@tonic-gate #include <unistd.h> 64*7c478bd9Sstevel@tonic-gate #endif 65*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 66*7c478bd9Sstevel@tonic-gate #include <sasl.h> 67*7c478bd9Sstevel@tonic-gate #include <saslutil.h> 68*7c478bd9Sstevel@tonic-gate #include <saslplug.h> 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #include <errno.h> 71*7c478bd9Sstevel@tonic-gate #include <ctype.h> 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #ifdef HAVE_INTTYPES_H 74*7c478bd9Sstevel@tonic-gate #include <inttypes.h> 75*7c478bd9Sstevel@tonic-gate #endif 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #include "plugin_common.h" 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate /* translate IPv4 mapped IPv6 address to IPv4 address */ 80*7c478bd9Sstevel@tonic-gate static void sockaddr_unmapped( 81*7c478bd9Sstevel@tonic-gate #ifdef IN6_IS_ADDR_V4MAPPED 82*7c478bd9Sstevel@tonic-gate struct sockaddr *sa, socklen_t *len 83*7c478bd9Sstevel@tonic-gate #else 84*7c478bd9Sstevel@tonic-gate struct sockaddr *sa __attribute__((unused)), 85*7c478bd9Sstevel@tonic-gate socklen_t *len __attribute__((unused)) 86*7c478bd9Sstevel@tonic-gate #endif 87*7c478bd9Sstevel@tonic-gate ) 88*7c478bd9Sstevel@tonic-gate { 89*7c478bd9Sstevel@tonic-gate #ifdef IN6_IS_ADDR_V4MAPPED 90*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *sin6; 91*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin4; 92*7c478bd9Sstevel@tonic-gate uint32_t addr; 93*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 94*7c478bd9Sstevel@tonic-gate in_port_t port; 95*7c478bd9Sstevel@tonic-gate #else 96*7c478bd9Sstevel@tonic-gate int port; 97*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate if (sa->sa_family != AF_INET6) 100*7c478bd9Sstevel@tonic-gate return; 101*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 102*7c478bd9Sstevel@tonic-gate sin6 = (struct sockaddr_in6 *)sa; 103*7c478bd9Sstevel@tonic-gate if (!IN6_IS_ADDR_V4MAPPED((&sin6->sin6_addr))) 104*7c478bd9Sstevel@tonic-gate return; 105*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 106*7c478bd9Sstevel@tonic-gate sin4 = (struct sockaddr_in *)sa; 107*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 108*7c478bd9Sstevel@tonic-gate addr = *(uint32_t *)&sin6->sin6_addr.s6_addr[12]; 109*7c478bd9Sstevel@tonic-gate port = sin6->sin6_port; 110*7c478bd9Sstevel@tonic-gate memset(sin4, 0, sizeof(struct sockaddr_in)); 111*7c478bd9Sstevel@tonic-gate sin4->sin_addr.s_addr = addr; 112*7c478bd9Sstevel@tonic-gate sin4->sin_port = port; 113*7c478bd9Sstevel@tonic-gate sin4->sin_family = AF_INET; 114*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SOCKADDR_SA_LEN 115*7c478bd9Sstevel@tonic-gate sin4->sin_len = sizeof(struct sockaddr_in); 116*7c478bd9Sstevel@tonic-gate #endif 117*7c478bd9Sstevel@tonic-gate *len = sizeof(struct sockaddr_in); 118*7c478bd9Sstevel@tonic-gate #else 119*7c478bd9Sstevel@tonic-gate return; 120*7c478bd9Sstevel@tonic-gate #endif 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate int _plug_ipfromstring(const sasl_utils_t *utils, const char *addr, 124*7c478bd9Sstevel@tonic-gate struct sockaddr *out, socklen_t outlen) 125*7c478bd9Sstevel@tonic-gate { 126*7c478bd9Sstevel@tonic-gate int i, j; 127*7c478bd9Sstevel@tonic-gate socklen_t len; 128*7c478bd9Sstevel@tonic-gate #ifdef WINNT /* _SUN_SDK_ */ 129*7c478bd9Sstevel@tonic-gate struct sockaddr_in ss; 130*7c478bd9Sstevel@tonic-gate #else 131*7c478bd9Sstevel@tonic-gate struct sockaddr_storage ss; 132*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 133*7c478bd9Sstevel@tonic-gate struct addrinfo hints, *ai = NULL; 134*7c478bd9Sstevel@tonic-gate char hbuf[NI_MAXHOST]; 135*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 136*7c478bd9Sstevel@tonic-gate const char *start, *end, *p; 137*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate if(!utils || !addr || !out) { 140*7c478bd9Sstevel@tonic-gate if(utils) PARAMERROR( utils ); 141*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 145*7c478bd9Sstevel@tonic-gate end = strchr(addr, ']'); 146*7c478bd9Sstevel@tonic-gate if (end != NULL) { 147*7c478bd9Sstevel@tonic-gate /* This an rfc 2732 ipv6 address */ 148*7c478bd9Sstevel@tonic-gate start = strchr(addr, '['); 149*7c478bd9Sstevel@tonic-gate if (start >= end || start == NULL) { 150*7c478bd9Sstevel@tonic-gate if(utils) PARAMERROR( utils ); 151*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate for (i = 0, p = start + 1; p < end; p++) { 154*7c478bd9Sstevel@tonic-gate hbuf[i++] = *p; 155*7c478bd9Sstevel@tonic-gate if (i >= NI_MAXHOST) 156*7c478bd9Sstevel@tonic-gate break; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate p = strchr(end, ':'); 159*7c478bd9Sstevel@tonic-gate if (p == NULL) 160*7c478bd9Sstevel@tonic-gate p = end + 1; 161*7c478bd9Sstevel@tonic-gate else 162*7c478bd9Sstevel@tonic-gate p = p + 1; 163*7c478bd9Sstevel@tonic-gate } else { 164*7c478bd9Sstevel@tonic-gate for (i = 0; addr[i] != '\0' && addr[i] != ';'; ) { 165*7c478bd9Sstevel@tonic-gate hbuf[i] = addr[i]; 166*7c478bd9Sstevel@tonic-gate if (++i >= NI_MAXHOST) 167*7c478bd9Sstevel@tonic-gate break; 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate if (addr[i] == ';') 170*7c478bd9Sstevel@tonic-gate p = &addr[i+1]; 171*7c478bd9Sstevel@tonic-gate else 172*7c478bd9Sstevel@tonic-gate p = &addr[i]; 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate if (i >= NI_MAXHOST) { 175*7c478bd9Sstevel@tonic-gate if(utils) PARAMERROR( utils ); 176*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate hbuf[i] = '\0'; 179*7c478bd9Sstevel@tonic-gate for (j = 0; p[j] != '\0'; j++) 180*7c478bd9Sstevel@tonic-gate if (!isdigit((int)(p[j]))) { 181*7c478bd9Sstevel@tonic-gate PARAMERROR( utils ); 182*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate #else 185*7c478bd9Sstevel@tonic-gate /* Parse the address */ 186*7c478bd9Sstevel@tonic-gate for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) { 187*7c478bd9Sstevel@tonic-gate if (i >= NI_MAXHOST) { 188*7c478bd9Sstevel@tonic-gate if(utils) PARAMERROR( utils ); 189*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate hbuf[i] = addr[i]; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate hbuf[i] = '\0'; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (addr[i] == ';') 196*7c478bd9Sstevel@tonic-gate i++; 197*7c478bd9Sstevel@tonic-gate /* XXX/FIXME: Do we need this check? */ 198*7c478bd9Sstevel@tonic-gate for (j = i; addr[j] != '\0'; j++) 199*7c478bd9Sstevel@tonic-gate if (!isdigit((int)(addr[j]))) { 200*7c478bd9Sstevel@tonic-gate PARAMERROR( utils ); 201*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate memset(&hints, 0, sizeof(hints)); 206*7c478bd9Sstevel@tonic-gate hints.ai_family = PF_UNSPEC; 207*7c478bd9Sstevel@tonic-gate hints.ai_socktype = SOCK_STREAM; 208*7c478bd9Sstevel@tonic-gate hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 211*7c478bd9Sstevel@tonic-gate if (getaddrinfo(hbuf, p, &hints, &ai) != 0) { 212*7c478bd9Sstevel@tonic-gate #else 213*7c478bd9Sstevel@tonic-gate if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0) { 214*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 215*7c478bd9Sstevel@tonic-gate PARAMERROR( utils ); 216*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate len = ai->ai_addrlen; 220*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 221*7c478bd9Sstevel@tonic-gate if (len > sizeof(ss)) 222*7c478bd9Sstevel@tonic-gate return (SASL_BUFOVER); 223*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 224*7c478bd9Sstevel@tonic-gate memcpy(&ss, ai->ai_addr, len); 225*7c478bd9Sstevel@tonic-gate freeaddrinfo(ai); 226*7c478bd9Sstevel@tonic-gate sockaddr_unmapped((struct sockaddr *)&ss, &len); 227*7c478bd9Sstevel@tonic-gate if (outlen < len) { 228*7c478bd9Sstevel@tonic-gate PARAMERROR( utils ); 229*7c478bd9Sstevel@tonic-gate return SASL_BUFOVER; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate memcpy(out, &ss, len); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate return SASL_OK; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate int _plug_iovec_to_buf(const sasl_utils_t *utils, const struct iovec *vec, 238*7c478bd9Sstevel@tonic-gate unsigned numiov, buffer_info_t **output) 239*7c478bd9Sstevel@tonic-gate { 240*7c478bd9Sstevel@tonic-gate unsigned i; 241*7c478bd9Sstevel@tonic-gate int ret; 242*7c478bd9Sstevel@tonic-gate buffer_info_t *out; 243*7c478bd9Sstevel@tonic-gate char *pos; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if(!utils || !vec || !output) { 246*7c478bd9Sstevel@tonic-gate if(utils) PARAMERROR( utils ); 247*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if(!(*output)) { 251*7c478bd9Sstevel@tonic-gate *output = utils->malloc(sizeof(buffer_info_t)); 252*7c478bd9Sstevel@tonic-gate if(!*output) { 253*7c478bd9Sstevel@tonic-gate MEMERROR(utils); 254*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate memset(*output,0,sizeof(buffer_info_t)); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate out = *output; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate out->curlen = 0; 262*7c478bd9Sstevel@tonic-gate for(i=0; i<numiov; i++) 263*7c478bd9Sstevel@tonic-gate out->curlen += vec[i].iov_len; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, &out->data, &out->reallen, out->curlen); 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) { 268*7c478bd9Sstevel@tonic-gate MEMERROR(utils); 269*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate memset(out->data, 0, out->reallen); 273*7c478bd9Sstevel@tonic-gate pos = out->data; 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate for(i=0; i<numiov; i++) { 276*7c478bd9Sstevel@tonic-gate memcpy(pos, vec[i].iov_base, vec[i].iov_len); 277*7c478bd9Sstevel@tonic-gate pos += vec[i].iov_len; 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate return SASL_OK; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* Basically a conditional call to realloc(), if we need more */ 284*7c478bd9Sstevel@tonic-gate int _plug_buf_alloc(const sasl_utils_t *utils, char **rwbuf, 285*7c478bd9Sstevel@tonic-gate unsigned *curlen, unsigned newlen) 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate if(!utils || !rwbuf || !curlen) { 288*7c478bd9Sstevel@tonic-gate PARAMERROR(utils); 289*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate if(!(*rwbuf)) { 293*7c478bd9Sstevel@tonic-gate *rwbuf = utils->malloc(newlen); 294*7c478bd9Sstevel@tonic-gate if (*rwbuf == NULL) { 295*7c478bd9Sstevel@tonic-gate *curlen = 0; 296*7c478bd9Sstevel@tonic-gate MEMERROR(utils); 297*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate *curlen = newlen; 300*7c478bd9Sstevel@tonic-gate } else if(*rwbuf && *curlen < newlen) { 301*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 302*7c478bd9Sstevel@tonic-gate unsigned needed = 2*(*curlen); 303*7c478bd9Sstevel@tonic-gate #else 304*7c478bd9Sstevel@tonic-gate size_t needed = 2*(*curlen); 305*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate while(needed < newlen) 308*7c478bd9Sstevel@tonic-gate needed *= 2; 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate *rwbuf = utils->realloc(*rwbuf, needed); 311*7c478bd9Sstevel@tonic-gate if (*rwbuf == NULL) { 312*7c478bd9Sstevel@tonic-gate *curlen = 0; 313*7c478bd9Sstevel@tonic-gate MEMERROR(utils); 314*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate *curlen = needed; 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate return SASL_OK; 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate /* copy a string */ 323*7c478bd9Sstevel@tonic-gate int _plug_strdup(const sasl_utils_t * utils, const char *in, 324*7c478bd9Sstevel@tonic-gate char **out, int *outlen) 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 327*7c478bd9Sstevel@tonic-gate int len; 328*7c478bd9Sstevel@tonic-gate #else 329*7c478bd9Sstevel@tonic-gate size_t len = strlen(in); 330*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate if(!utils || !in || !out) { 333*7c478bd9Sstevel@tonic-gate if(utils) PARAMERROR(utils); 334*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 335*7c478bd9Sstevel@tonic-gate } 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 338*7c478bd9Sstevel@tonic-gate len = strlen(in); 339*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 340*7c478bd9Sstevel@tonic-gate *out = utils->malloc(len + 1); 341*7c478bd9Sstevel@tonic-gate if (!*out) { 342*7c478bd9Sstevel@tonic-gate MEMERROR(utils); 343*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate strcpy((char *) *out, in); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate if (outlen) 349*7c478bd9Sstevel@tonic-gate *outlen = len; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate return SASL_OK; 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate void _plug_free_string(const sasl_utils_t *utils, char **str) 355*7c478bd9Sstevel@tonic-gate { 356*7c478bd9Sstevel@tonic-gate size_t len; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if (!utils || !str || !(*str)) return; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate len = strlen(*str); 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate utils->erasebuffer(*str, len); 363*7c478bd9Sstevel@tonic-gate utils->free(*str); 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate *str=NULL; 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate void _plug_free_secret(const sasl_utils_t *utils, sasl_secret_t **secret) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate if(!utils || !secret || !(*secret)) return; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 373*7c478bd9Sstevel@tonic-gate utils->erasebuffer((char *)(*secret)->data, (*secret)->len); 374*7c478bd9Sstevel@tonic-gate #else 375*7c478bd9Sstevel@tonic-gate utils->erasebuffer((*secret)->data, (*secret)->len); 376*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 377*7c478bd9Sstevel@tonic-gate utils->free(*secret); 378*7c478bd9Sstevel@tonic-gate *secret = NULL; 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /* 382*7c478bd9Sstevel@tonic-gate * Trys to find the prompt with the lookingfor id in the prompt list 383*7c478bd9Sstevel@tonic-gate * Returns it if found. NULL otherwise 384*7c478bd9Sstevel@tonic-gate */ 385*7c478bd9Sstevel@tonic-gate sasl_interact_t *_plug_find_prompt(sasl_interact_t **promptlist, 386*7c478bd9Sstevel@tonic-gate unsigned int lookingfor) 387*7c478bd9Sstevel@tonic-gate { 388*7c478bd9Sstevel@tonic-gate sasl_interact_t *prompt; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate if (promptlist && *promptlist) { 391*7c478bd9Sstevel@tonic-gate for (prompt = *promptlist; prompt->id != SASL_CB_LIST_END; ++prompt) { 392*7c478bd9Sstevel@tonic-gate if (prompt->id==lookingfor) 393*7c478bd9Sstevel@tonic-gate return prompt; 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate return NULL; 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate /* 401*7c478bd9Sstevel@tonic-gate * Retrieve the simple string given by the callback id. 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate int _plug_get_simple(const sasl_utils_t *utils, unsigned int id, int required, 404*7c478bd9Sstevel@tonic-gate const char **result, sasl_interact_t **prompt_need) 405*7c478bd9Sstevel@tonic-gate { 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate int ret = SASL_FAIL; 408*7c478bd9Sstevel@tonic-gate sasl_getsimple_t *simple_cb; 409*7c478bd9Sstevel@tonic-gate void *simple_context; 410*7c478bd9Sstevel@tonic-gate sasl_interact_t *prompt; 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate *result = NULL; 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate /* see if we were given the result in the prompt */ 415*7c478bd9Sstevel@tonic-gate prompt = _plug_find_prompt(prompt_need, id); 416*7c478bd9Sstevel@tonic-gate if (prompt != NULL) { 417*7c478bd9Sstevel@tonic-gate /* We prompted, and got.*/ 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate if (required && !prompt->result) { 420*7c478bd9Sstevel@tonic-gate SETERROR(utils, "Unexpectedly missing a prompt result"); 421*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 422*7c478bd9Sstevel@tonic-gate } 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate *result = prompt->result; 425*7c478bd9Sstevel@tonic-gate return SASL_OK; 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* Try to get the callback... */ 429*7c478bd9Sstevel@tonic-gate ret = utils->getcallback(utils->conn, id, &simple_cb, &simple_context); 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate if (ret == SASL_FAIL && !required) 432*7c478bd9Sstevel@tonic-gate return SASL_OK; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK && simple_cb) { 435*7c478bd9Sstevel@tonic-gate ret = simple_cb(simple_context, id, result, NULL); 436*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) 437*7c478bd9Sstevel@tonic-gate return ret; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate if (required && !*result) { 440*7c478bd9Sstevel@tonic-gate PARAMERROR(utils); 441*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate return ret; 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate /* 449*7c478bd9Sstevel@tonic-gate * Retrieve the user password. 450*7c478bd9Sstevel@tonic-gate */ 451*7c478bd9Sstevel@tonic-gate int _plug_get_password(const sasl_utils_t *utils, sasl_secret_t **password, 452*7c478bd9Sstevel@tonic-gate unsigned int *iscopy, sasl_interact_t **prompt_need) 453*7c478bd9Sstevel@tonic-gate { 454*7c478bd9Sstevel@tonic-gate int ret = SASL_FAIL; 455*7c478bd9Sstevel@tonic-gate sasl_getsecret_t *pass_cb; 456*7c478bd9Sstevel@tonic-gate void *pass_context; 457*7c478bd9Sstevel@tonic-gate sasl_interact_t *prompt; 458*7c478bd9Sstevel@tonic-gate 459*7c478bd9Sstevel@tonic-gate *password = NULL; 460*7c478bd9Sstevel@tonic-gate *iscopy = 0; 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate /* see if we were given the password in the prompt */ 463*7c478bd9Sstevel@tonic-gate prompt = _plug_find_prompt(prompt_need, SASL_CB_PASS); 464*7c478bd9Sstevel@tonic-gate if (prompt != NULL) { 465*7c478bd9Sstevel@tonic-gate /* We prompted, and got.*/ 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate if (!prompt->result) { 468*7c478bd9Sstevel@tonic-gate SETERROR(utils, "Unexpectedly missing a prompt result"); 469*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate /* copy what we got into a secret_t */ 473*7c478bd9Sstevel@tonic-gate *password = (sasl_secret_t *) utils->malloc(sizeof(sasl_secret_t) + 474*7c478bd9Sstevel@tonic-gate prompt->len + 1); 475*7c478bd9Sstevel@tonic-gate if (!*password) { 476*7c478bd9Sstevel@tonic-gate MEMERROR(utils); 477*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate (*password)->len=prompt->len; 481*7c478bd9Sstevel@tonic-gate memcpy((*password)->data, prompt->result, prompt->len); 482*7c478bd9Sstevel@tonic-gate (*password)->data[(*password)->len]=0; 483*7c478bd9Sstevel@tonic-gate 484*7c478bd9Sstevel@tonic-gate *iscopy = 1; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate return SASL_OK; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* Try to get the callback... */ 490*7c478bd9Sstevel@tonic-gate ret = utils->getcallback(utils->conn, SASL_CB_PASS, 491*7c478bd9Sstevel@tonic-gate &pass_cb, &pass_context); 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK && pass_cb) { 494*7c478bd9Sstevel@tonic-gate ret = pass_cb(utils->conn, pass_context, SASL_CB_PASS, password); 495*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) 496*7c478bd9Sstevel@tonic-gate return ret; 497*7c478bd9Sstevel@tonic-gate 498*7c478bd9Sstevel@tonic-gate if (!*password) { 499*7c478bd9Sstevel@tonic-gate PARAMERROR(utils); 500*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate return ret; 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate /* 508*7c478bd9Sstevel@tonic-gate * Retrieve the string given by the challenge prompt id. 509*7c478bd9Sstevel@tonic-gate */ 510*7c478bd9Sstevel@tonic-gate int _plug_challenge_prompt(const sasl_utils_t *utils, unsigned int id, 511*7c478bd9Sstevel@tonic-gate const char *challenge, const char *promptstr, 512*7c478bd9Sstevel@tonic-gate const char **result, sasl_interact_t **prompt_need) 513*7c478bd9Sstevel@tonic-gate { 514*7c478bd9Sstevel@tonic-gate int ret = SASL_FAIL; 515*7c478bd9Sstevel@tonic-gate sasl_chalprompt_t *chalprompt_cb; 516*7c478bd9Sstevel@tonic-gate void *chalprompt_context; 517*7c478bd9Sstevel@tonic-gate sasl_interact_t *prompt; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate *result = NULL; 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* see if we were given the password in the prompt */ 522*7c478bd9Sstevel@tonic-gate prompt = _plug_find_prompt(prompt_need, id); 523*7c478bd9Sstevel@tonic-gate if (prompt != NULL) { 524*7c478bd9Sstevel@tonic-gate /* We prompted, and got.*/ 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate if (!prompt->result) { 527*7c478bd9Sstevel@tonic-gate SETERROR(utils, "Unexpectedly missing a prompt result"); 528*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate *result = prompt->result; 532*7c478bd9Sstevel@tonic-gate return SASL_OK; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* Try to get the callback... */ 536*7c478bd9Sstevel@tonic-gate ret = utils->getcallback(utils->conn, id, 537*7c478bd9Sstevel@tonic-gate &chalprompt_cb, &chalprompt_context); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK && chalprompt_cb) { 540*7c478bd9Sstevel@tonic-gate ret = chalprompt_cb(chalprompt_context, id, 541*7c478bd9Sstevel@tonic-gate challenge, promptstr, NULL, result, NULL); 542*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) 543*7c478bd9Sstevel@tonic-gate return ret; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate if (!*result) { 546*7c478bd9Sstevel@tonic-gate PARAMERROR(utils); 547*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate return ret; 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate /* 555*7c478bd9Sstevel@tonic-gate * Retrieve the client realm. 556*7c478bd9Sstevel@tonic-gate */ 557*7c478bd9Sstevel@tonic-gate int _plug_get_realm(const sasl_utils_t *utils, const char **availrealms, 558*7c478bd9Sstevel@tonic-gate const char **realm, sasl_interact_t **prompt_need) 559*7c478bd9Sstevel@tonic-gate { 560*7c478bd9Sstevel@tonic-gate int ret = SASL_FAIL; 561*7c478bd9Sstevel@tonic-gate sasl_getrealm_t *realm_cb; 562*7c478bd9Sstevel@tonic-gate void *realm_context; 563*7c478bd9Sstevel@tonic-gate sasl_interact_t *prompt; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate *realm = NULL; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate /* see if we were given the result in the prompt */ 568*7c478bd9Sstevel@tonic-gate prompt = _plug_find_prompt(prompt_need, SASL_CB_GETREALM); 569*7c478bd9Sstevel@tonic-gate if (prompt != NULL) { 570*7c478bd9Sstevel@tonic-gate /* We prompted, and got.*/ 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if (!prompt->result) { 573*7c478bd9Sstevel@tonic-gate SETERROR(utils, "Unexpectedly missing a prompt result"); 574*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate *realm = prompt->result; 578*7c478bd9Sstevel@tonic-gate return SASL_OK; 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* Try to get the callback... */ 582*7c478bd9Sstevel@tonic-gate ret = utils->getcallback(utils->conn, SASL_CB_GETREALM, 583*7c478bd9Sstevel@tonic-gate &realm_cb, &realm_context); 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK && realm_cb) { 586*7c478bd9Sstevel@tonic-gate ret = realm_cb(realm_context, SASL_CB_GETREALM, availrealms, realm); 587*7c478bd9Sstevel@tonic-gate if (ret != SASL_OK) 588*7c478bd9Sstevel@tonic-gate return ret; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate if (!*realm) { 591*7c478bd9Sstevel@tonic-gate PARAMERROR(utils); 592*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate return ret; 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate /* 600*7c478bd9Sstevel@tonic-gate * Make the requested prompts. (prompt==NULL means we don't want it) 601*7c478bd9Sstevel@tonic-gate */ 602*7c478bd9Sstevel@tonic-gate int _plug_make_prompts(const sasl_utils_t *utils, 603*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 604*7c478bd9Sstevel@tonic-gate void **h, 605*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 606*7c478bd9Sstevel@tonic-gate sasl_interact_t **prompts_res, 607*7c478bd9Sstevel@tonic-gate const char *user_prompt, const char *user_def, 608*7c478bd9Sstevel@tonic-gate const char *auth_prompt, const char *auth_def, 609*7c478bd9Sstevel@tonic-gate const char *pass_prompt, const char *pass_def, 610*7c478bd9Sstevel@tonic-gate const char *echo_chal, 611*7c478bd9Sstevel@tonic-gate const char *echo_prompt, const char *echo_def, 612*7c478bd9Sstevel@tonic-gate const char *realm_chal, 613*7c478bd9Sstevel@tonic-gate const char *realm_prompt, const char *realm_def) 614*7c478bd9Sstevel@tonic-gate { 615*7c478bd9Sstevel@tonic-gate int num = 1; 616*7c478bd9Sstevel@tonic-gate int alloc_size; 617*7c478bd9Sstevel@tonic-gate sasl_interact_t *prompts; 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate if (user_prompt) num++; 620*7c478bd9Sstevel@tonic-gate if (auth_prompt) num++; 621*7c478bd9Sstevel@tonic-gate if (pass_prompt) num++; 622*7c478bd9Sstevel@tonic-gate if (echo_prompt) num++; 623*7c478bd9Sstevel@tonic-gate if (realm_prompt) num++; 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate if (num == 1) { 626*7c478bd9Sstevel@tonic-gate SETERROR( utils, "make_prompts() called with no actual prompts" ); 627*7c478bd9Sstevel@tonic-gate return SASL_FAIL; 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate alloc_size = sizeof(sasl_interact_t)*num; 631*7c478bd9Sstevel@tonic-gate prompts = utils->malloc(alloc_size); 632*7c478bd9Sstevel@tonic-gate if (!prompts) { 633*7c478bd9Sstevel@tonic-gate MEMERROR( utils ); 634*7c478bd9Sstevel@tonic-gate return SASL_NOMEM; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate memset(prompts, 0, alloc_size); 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate *prompts_res = prompts; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate if (user_prompt) { 641*7c478bd9Sstevel@tonic-gate (prompts)->id = SASL_CB_USER; 642*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 643*7c478bd9Sstevel@tonic-gate (prompts)->challenge = convert_prompt(utils, h, 644*7c478bd9Sstevel@tonic-gate gettext("Authorization Name")); 645*7c478bd9Sstevel@tonic-gate #else 646*7c478bd9Sstevel@tonic-gate (prompts)->challenge = "Authorization Name"; 647*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 648*7c478bd9Sstevel@tonic-gate (prompts)->prompt = user_prompt; 649*7c478bd9Sstevel@tonic-gate (prompts)->defresult = user_def; 650*7c478bd9Sstevel@tonic-gate 651*7c478bd9Sstevel@tonic-gate prompts++; 652*7c478bd9Sstevel@tonic-gate } 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate if (auth_prompt) { 655*7c478bd9Sstevel@tonic-gate (prompts)->id = SASL_CB_AUTHNAME; 656*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 657*7c478bd9Sstevel@tonic-gate (prompts)->challenge = convert_prompt(utils, h, 658*7c478bd9Sstevel@tonic-gate gettext( "Authentication Name")); 659*7c478bd9Sstevel@tonic-gate #else 660*7c478bd9Sstevel@tonic-gate (prompts)->challenge = "Authentication Name"; 661*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 662*7c478bd9Sstevel@tonic-gate (prompts)->prompt = auth_prompt; 663*7c478bd9Sstevel@tonic-gate (prompts)->defresult = auth_def; 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate prompts++; 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate if (pass_prompt) { 669*7c478bd9Sstevel@tonic-gate (prompts)->id = SASL_CB_PASS; 670*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 671*7c478bd9Sstevel@tonic-gate (prompts)->challenge = convert_prompt(utils, h, gettext("Password")); 672*7c478bd9Sstevel@tonic-gate #else 673*7c478bd9Sstevel@tonic-gate (prompts)->challenge = "Password"; 674*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 675*7c478bd9Sstevel@tonic-gate (prompts)->prompt = pass_prompt; 676*7c478bd9Sstevel@tonic-gate (prompts)->defresult = pass_def; 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate prompts++; 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate if (echo_prompt) { 682*7c478bd9Sstevel@tonic-gate (prompts)->id = SASL_CB_ECHOPROMPT; 683*7c478bd9Sstevel@tonic-gate (prompts)->challenge = echo_chal; 684*7c478bd9Sstevel@tonic-gate (prompts)->prompt = echo_prompt; 685*7c478bd9Sstevel@tonic-gate (prompts)->defresult = echo_def; 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate prompts++; 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate if (realm_prompt) { 691*7c478bd9Sstevel@tonic-gate (prompts)->id = SASL_CB_GETREALM; 692*7c478bd9Sstevel@tonic-gate (prompts)->challenge = realm_chal; 693*7c478bd9Sstevel@tonic-gate (prompts)->prompt = realm_prompt; 694*7c478bd9Sstevel@tonic-gate (prompts)->defresult = realm_def; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate prompts++; 697*7c478bd9Sstevel@tonic-gate } 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* add the ending one */ 700*7c478bd9Sstevel@tonic-gate (prompts)->id = SASL_CB_LIST_END; 701*7c478bd9Sstevel@tonic-gate (prompts)->challenge = NULL; 702*7c478bd9Sstevel@tonic-gate (prompts)->prompt = NULL; 703*7c478bd9Sstevel@tonic-gate (prompts)->defresult = NULL; 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate return SASL_OK; 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate /* 709*7c478bd9Sstevel@tonic-gate * Decode and concatenate multiple packets using the given function 710*7c478bd9Sstevel@tonic-gate * to decode each packet. 711*7c478bd9Sstevel@tonic-gate */ 712*7c478bd9Sstevel@tonic-gate int _plug_decode(const sasl_utils_t *utils, 713*7c478bd9Sstevel@tonic-gate void *context, 714*7c478bd9Sstevel@tonic-gate const char *input, unsigned inputlen, 715*7c478bd9Sstevel@tonic-gate char **output, /* output buffer */ 716*7c478bd9Sstevel@tonic-gate unsigned *outputsize, /* current size of output buffer */ 717*7c478bd9Sstevel@tonic-gate unsigned *outputlen, /* length of data in output buffer */ 718*7c478bd9Sstevel@tonic-gate int (*decode_pkt)(void *context, 719*7c478bd9Sstevel@tonic-gate const char **input, unsigned *inputlen, 720*7c478bd9Sstevel@tonic-gate char **output, unsigned *outputlen)) 721*7c478bd9Sstevel@tonic-gate { 722*7c478bd9Sstevel@tonic-gate char *tmp = NULL; 723*7c478bd9Sstevel@tonic-gate unsigned tmplen = 0; 724*7c478bd9Sstevel@tonic-gate int ret; 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate *outputlen = 0; 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate while (inputlen!=0) 729*7c478bd9Sstevel@tonic-gate { 730*7c478bd9Sstevel@tonic-gate /* no need to free tmp */ 731*7c478bd9Sstevel@tonic-gate ret = decode_pkt(context, &input, &inputlen, &tmp, &tmplen); 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) return ret; 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate if (tmp!=NULL) /* if received 2 packets merge them together */ 736*7c478bd9Sstevel@tonic-gate { 737*7c478bd9Sstevel@tonic-gate ret = _plug_buf_alloc(utils, output, outputsize, 738*7c478bd9Sstevel@tonic-gate *outputlen + tmplen + 1); 739*7c478bd9Sstevel@tonic-gate if(ret != SASL_OK) return ret; 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate memcpy(*output + *outputlen, tmp, tmplen); 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate /* Protect stupid clients */ 744*7c478bd9Sstevel@tonic-gate *(*output + *outputlen + tmplen) = '\0'; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate *outputlen+=tmplen; 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate return SASL_OK; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* returns the realm we should pretend to be in */ 754*7c478bd9Sstevel@tonic-gate int _plug_parseuser(const sasl_utils_t *utils, 755*7c478bd9Sstevel@tonic-gate char **user, char **realm, const char *user_realm, 756*7c478bd9Sstevel@tonic-gate const char *serverFQDN, const char *input) 757*7c478bd9Sstevel@tonic-gate { 758*7c478bd9Sstevel@tonic-gate int ret; 759*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 760*7c478bd9Sstevel@tonic-gate const char *r; 761*7c478bd9Sstevel@tonic-gate #else 762*7c478bd9Sstevel@tonic-gate char *r; 763*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate if(!user || !serverFQDN) { 766*7c478bd9Sstevel@tonic-gate PARAMERROR( utils ); 767*7c478bd9Sstevel@tonic-gate return SASL_BADPARAM; 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate r = strchr(input, '@'); 771*7c478bd9Sstevel@tonic-gate if (!r) { 772*7c478bd9Sstevel@tonic-gate /* hmmm, the user didn't specify a realm */ 773*7c478bd9Sstevel@tonic-gate if(user_realm && user_realm[0]) { 774*7c478bd9Sstevel@tonic-gate ret = _plug_strdup(utils, user_realm, realm, NULL); 775*7c478bd9Sstevel@tonic-gate } else { 776*7c478bd9Sstevel@tonic-gate /* Default to serverFQDN */ 777*7c478bd9Sstevel@tonic-gate ret = _plug_strdup(utils, serverFQDN, realm, NULL); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate 780*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 781*7c478bd9Sstevel@tonic-gate ret = _plug_strdup(utils, input, user, NULL); 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate } else { 784*7c478bd9Sstevel@tonic-gate r++; 785*7c478bd9Sstevel@tonic-gate ret = _plug_strdup(utils, r, realm, NULL); 786*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_ 787*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK) { 788*7c478bd9Sstevel@tonic-gate *user = utils->malloc(r - input); 789*7c478bd9Sstevel@tonic-gate if (*user) { 790*7c478bd9Sstevel@tonic-gate memcpy(*user, input, r - input - 1); 791*7c478bd9Sstevel@tonic-gate (*user)[r - input - 1] = '\0'; 792*7c478bd9Sstevel@tonic-gate } else { 793*7c478bd9Sstevel@tonic-gate MEMERROR( utils ); 794*7c478bd9Sstevel@tonic-gate ret = SASL_NOMEM; 795*7c478bd9Sstevel@tonic-gate } 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate #else 798*7c478bd9Sstevel@tonic-gate *--r = '\0'; 799*7c478bd9Sstevel@tonic-gate *user = utils->malloc(r - input + 1); 800*7c478bd9Sstevel@tonic-gate if (*user) { 801*7c478bd9Sstevel@tonic-gate strncpy(*user, input, r - input +1); 802*7c478bd9Sstevel@tonic-gate } else { 803*7c478bd9Sstevel@tonic-gate MEMERROR( utils ); 804*7c478bd9Sstevel@tonic-gate ret = SASL_NOMEM; 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate *r = '@'; 807*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */ 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate 810*7c478bd9Sstevel@tonic-gate return ret; 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate #ifdef _INTEGRATED_SOLARIS_ 814*7c478bd9Sstevel@tonic-gate int 815*7c478bd9Sstevel@tonic-gate use_locale(const char *lang_list, int is_client) 816*7c478bd9Sstevel@tonic-gate { 817*7c478bd9Sstevel@tonic-gate const char *s; 818*7c478bd9Sstevel@tonic-gate const char *begin; 819*7c478bd9Sstevel@tonic-gate const char *end; 820*7c478bd9Sstevel@tonic-gate const char *i_default = "i-default"; 821*7c478bd9Sstevel@tonic-gate const int i_default_len = 9; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate if (lang_list == NULL) 824*7c478bd9Sstevel@tonic-gate return is_client; 825*7c478bd9Sstevel@tonic-gate 826*7c478bd9Sstevel@tonic-gate begin = lang_list; 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate for (;;) { 829*7c478bd9Sstevel@tonic-gate /* skip over leading whitespace and commas */ 830*7c478bd9Sstevel@tonic-gate while (isspace(*begin) || *begin == ',') 831*7c478bd9Sstevel@tonic-gate begin++; 832*7c478bd9Sstevel@tonic-gate if (*begin == '\0') 833*7c478bd9Sstevel@tonic-gate break; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate /* Find the end of the language tag */ 836*7c478bd9Sstevel@tonic-gate for (end = begin; end[1] != ',' && end[1] != '\0'; end++) {} 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate for (s = end; isspace(*s); s--) {} 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate if (s == begin && *begin == '*') 841*7c478bd9Sstevel@tonic-gate return 1; 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate if (s - begin == (i_default_len - 1) && 844*7c478bd9Sstevel@tonic-gate strncasecmp(begin, i_default, i_default_len) == 0) 845*7c478bd9Sstevel@tonic-gate return 0; 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate begin = end + 1; 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate 850*7c478bd9Sstevel@tonic-gate return is_client; 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate typedef struct prompt_list { 854*7c478bd9Sstevel@tonic-gate char *prompt; 855*7c478bd9Sstevel@tonic-gate struct prompt_list *next; 856*7c478bd9Sstevel@tonic-gate } prompt_list; 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate const char * 859*7c478bd9Sstevel@tonic-gate convert_prompt(const sasl_utils_t *utils, void **h, const char *s) 860*7c478bd9Sstevel@tonic-gate { 861*7c478bd9Sstevel@tonic-gate sasl_getsimple_t *simple_cb; 862*7c478bd9Sstevel@tonic-gate void *simple_context; 863*7c478bd9Sstevel@tonic-gate const char *result = NULL; 864*7c478bd9Sstevel@tonic-gate const char *s_locale; 865*7c478bd9Sstevel@tonic-gate int ret; 866*7c478bd9Sstevel@tonic-gate char *buf; 867*7c478bd9Sstevel@tonic-gate const char *ret_buf; 868*7c478bd9Sstevel@tonic-gate prompt_list *list; 869*7c478bd9Sstevel@tonic-gate prompt_list *next; 870*7c478bd9Sstevel@tonic-gate 871*7c478bd9Sstevel@tonic-gate if (utils == NULL || utils->conn == NULL) 872*7c478bd9Sstevel@tonic-gate return s; 873*7c478bd9Sstevel@tonic-gate 874*7c478bd9Sstevel@tonic-gate if (s == NULL) { 875*7c478bd9Sstevel@tonic-gate for (list = (prompt_list *)*h; list != NULL; list = next) { 876*7c478bd9Sstevel@tonic-gate if (list->prompt) 877*7c478bd9Sstevel@tonic-gate utils->free(list->prompt); 878*7c478bd9Sstevel@tonic-gate next = list->next; 879*7c478bd9Sstevel@tonic-gate utils->free(list); 880*7c478bd9Sstevel@tonic-gate } 881*7c478bd9Sstevel@tonic-gate *h = NULL; 882*7c478bd9Sstevel@tonic-gate return NULL; 883*7c478bd9Sstevel@tonic-gate } 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate ret = utils->getcallback(utils->conn, SASL_CB_LANGUAGE, &simple_cb, 886*7c478bd9Sstevel@tonic-gate &simple_context); 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK && simple_cb) { 889*7c478bd9Sstevel@tonic-gate ret = simple_cb(simple_context, SASL_CB_LANGUAGE, &result, NULL); 890*7c478bd9Sstevel@tonic-gate } else 891*7c478bd9Sstevel@tonic-gate ret = SASL_FAIL; 892*7c478bd9Sstevel@tonic-gate if (ret == SASL_OK && !use_locale(result, 1)) 893*7c478bd9Sstevel@tonic-gate return s; 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate s_locale = dgettext(TEXT_DOMAIN, s); 896*7c478bd9Sstevel@tonic-gate if (s == s_locale) { 897*7c478bd9Sstevel@tonic-gate return s; 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate buf = local_to_utf(utils, s_locale); 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate if (buf != NULL) { 903*7c478bd9Sstevel@tonic-gate list = utils->malloc(sizeof (prompt_list)); 904*7c478bd9Sstevel@tonic-gate if (list == NULL) { 905*7c478bd9Sstevel@tonic-gate utils->free(buf); 906*7c478bd9Sstevel@tonic-gate buf = NULL; 907*7c478bd9Sstevel@tonic-gate } else { 908*7c478bd9Sstevel@tonic-gate list->prompt = buf; 909*7c478bd9Sstevel@tonic-gate list->next = *h; 910*7c478bd9Sstevel@tonic-gate *h = list; 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate ret_buf = (buf == NULL) ? s : buf; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate return ret_buf; 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate #include <iconv.h> 920*7c478bd9Sstevel@tonic-gate #include <langinfo.h> 921*7c478bd9Sstevel@tonic-gate 922*7c478bd9Sstevel@tonic-gate /* 923*7c478bd9Sstevel@tonic-gate * local_to_utf converts a string in the current codeset to utf-8. 924*7c478bd9Sstevel@tonic-gate * If no codeset is specified, then codeset 646 will be used. 925*7c478bd9Sstevel@tonic-gate * Upon successful completion, this function will return a non-NULL buffer 926*7c478bd9Sstevel@tonic-gate * that is allocated by local_to_utf. 927*7c478bd9Sstevel@tonic-gate * 928*7c478bd9Sstevel@tonic-gate * If utils is NULL, local_to_utf will use the standard memory allocation 929*7c478bd9Sstevel@tonic-gate * functions, otherwise the memory functions defined in sasl_utils_t will 930*7c478bd9Sstevel@tonic-gate * be used. 931*7c478bd9Sstevel@tonic-gate * 932*7c478bd9Sstevel@tonic-gate * local_to_utf will return NULL in the case of any error 933*7c478bd9Sstevel@tonic-gate */ 934*7c478bd9Sstevel@tonic-gate char * 935*7c478bd9Sstevel@tonic-gate local_to_utf(const sasl_utils_t *utils, const char *s) 936*7c478bd9Sstevel@tonic-gate { 937*7c478bd9Sstevel@tonic-gate const char *code_set = nl_langinfo(CODESET); 938*7c478bd9Sstevel@tonic-gate iconv_t cd; 939*7c478bd9Sstevel@tonic-gate char *buf, *tmp; 940*7c478bd9Sstevel@tonic-gate size_t in_len; 941*7c478bd9Sstevel@tonic-gate size_t buf_size; 942*7c478bd9Sstevel@tonic-gate size_t ileft, oleft; 943*7c478bd9Sstevel@tonic-gate const char *inptr; 944*7c478bd9Sstevel@tonic-gate char *outptr; 945*7c478bd9Sstevel@tonic-gate size_t ret; 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate if (s == NULL) 948*7c478bd9Sstevel@tonic-gate return NULL; 949*7c478bd9Sstevel@tonic-gate 950*7c478bd9Sstevel@tonic-gate if (code_set == NULL) 951*7c478bd9Sstevel@tonic-gate code_set = "646"; 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (strcasecmp(code_set, "UTF-8") == 0) { 954*7c478bd9Sstevel@tonic-gate if (utils == NULL) 955*7c478bd9Sstevel@tonic-gate buf = strdup(s); 956*7c478bd9Sstevel@tonic-gate else { 957*7c478bd9Sstevel@tonic-gate if (_plug_strdup(utils, s, &buf, NULL) != SASL_OK) 958*7c478bd9Sstevel@tonic-gate buf = NULL; 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate return buf; 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", code_set); 963*7c478bd9Sstevel@tonic-gate if (cd == (iconv_t)-1) 964*7c478bd9Sstevel@tonic-gate return NULL; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate in_len = strlen(s); 967*7c478bd9Sstevel@tonic-gate buf_size = 4 * (in_len + 1); /* guess */ 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate if (utils == NULL) 970*7c478bd9Sstevel@tonic-gate buf = malloc(buf_size); 971*7c478bd9Sstevel@tonic-gate else 972*7c478bd9Sstevel@tonic-gate buf = utils->malloc(buf_size); 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 975*7c478bd9Sstevel@tonic-gate (void) iconv_close(cd); 976*7c478bd9Sstevel@tonic-gate return NULL; 977*7c478bd9Sstevel@tonic-gate } 978*7c478bd9Sstevel@tonic-gate inptr = s; 979*7c478bd9Sstevel@tonic-gate ileft = in_len; 980*7c478bd9Sstevel@tonic-gate outptr = buf; 981*7c478bd9Sstevel@tonic-gate oleft = buf_size; 982*7c478bd9Sstevel@tonic-gate for (;;) { 983*7c478bd9Sstevel@tonic-gate ret = iconv(cd, &inptr, &ileft, &outptr, &oleft); 984*7c478bd9Sstevel@tonic-gate if (ret == (size_t)(-1)) { 985*7c478bd9Sstevel@tonic-gate if (errno == E2BIG) { 986*7c478bd9Sstevel@tonic-gate oleft += buf_size; 987*7c478bd9Sstevel@tonic-gate buf_size *= 2; 988*7c478bd9Sstevel@tonic-gate if (utils == NULL) 989*7c478bd9Sstevel@tonic-gate tmp = realloc(buf, buf_size); 990*7c478bd9Sstevel@tonic-gate else 991*7c478bd9Sstevel@tonic-gate tmp = utils->realloc(buf, buf_size); 992*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 993*7c478bd9Sstevel@tonic-gate oleft = (size_t)(-1); 994*7c478bd9Sstevel@tonic-gate break; 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate outptr = tmp + (outptr-buf); 997*7c478bd9Sstevel@tonic-gate buf = tmp; 998*7c478bd9Sstevel@tonic-gate continue; 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate oleft = (size_t)(-1); 1001*7c478bd9Sstevel@tonic-gate break; 1002*7c478bd9Sstevel@tonic-gate } 1003*7c478bd9Sstevel@tonic-gate if (inptr == NULL) 1004*7c478bd9Sstevel@tonic-gate break; 1005*7c478bd9Sstevel@tonic-gate inptr = NULL; 1006*7c478bd9Sstevel@tonic-gate ileft = 0; 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate if (oleft > 0) { 1009*7c478bd9Sstevel@tonic-gate *outptr = '\0'; 1010*7c478bd9Sstevel@tonic-gate } else if (oleft != (size_t)(-1)) { 1011*7c478bd9Sstevel@tonic-gate if (utils == NULL) 1012*7c478bd9Sstevel@tonic-gate tmp = realloc(buf, buf_size + 1); 1013*7c478bd9Sstevel@tonic-gate else 1014*7c478bd9Sstevel@tonic-gate tmp = utils->realloc(buf, buf_size + 1); 1015*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { 1016*7c478bd9Sstevel@tonic-gate oleft = (size_t)(-1); 1017*7c478bd9Sstevel@tonic-gate } else { 1018*7c478bd9Sstevel@tonic-gate buf = tmp; 1019*7c478bd9Sstevel@tonic-gate buf[buf_size] = '\0'; 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate } 1022*7c478bd9Sstevel@tonic-gate if (oleft == (size_t)(-1)) { 1023*7c478bd9Sstevel@tonic-gate if (utils == NULL) 1024*7c478bd9Sstevel@tonic-gate free(buf); 1025*7c478bd9Sstevel@tonic-gate else 1026*7c478bd9Sstevel@tonic-gate utils->free(buf); 1027*7c478bd9Sstevel@tonic-gate buf = NULL; 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate (void) iconv_close(cd); 1031*7c478bd9Sstevel@tonic-gate return buf; 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate #endif /* _INTEGRATED_SOLARIS_ */ 1034