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