xref: /titanic_53/usr/src/lib/libsasl/lib/saslutil.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 /* saslutil.c
8*7c478bd9Sstevel@tonic-gate  * Rob Siemborski
9*7c478bd9Sstevel@tonic-gate  * Tim Martin
10*7c478bd9Sstevel@tonic-gate  * $Id: saslutil.c,v 1.41 2003/03/19 18:25:28 rjs3 Exp $
11*7c478bd9Sstevel@tonic-gate  */
12*7c478bd9Sstevel@tonic-gate /*
13*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
16*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
17*7c478bd9Sstevel@tonic-gate  * are met:
18*7c478bd9Sstevel@tonic-gate  *
19*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
20*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
23*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
24*7c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
25*7c478bd9Sstevel@tonic-gate  *    distribution.
26*7c478bd9Sstevel@tonic-gate  *
27*7c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
28*7c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
29*7c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
30*7c478bd9Sstevel@tonic-gate  *    details, please contact
31*7c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
32*7c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
33*7c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
34*7c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
35*7c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
36*7c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
37*7c478bd9Sstevel@tonic-gate  *
38*7c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
39*7c478bd9Sstevel@tonic-gate  *    acknowledgment:
40*7c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
41*7c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
42*7c478bd9Sstevel@tonic-gate  *
43*7c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
44*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
45*7c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
46*7c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
47*7c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
48*7c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
49*7c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #include <config.h>
53*7c478bd9Sstevel@tonic-gate #include <stdio.h>
54*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
55*7c478bd9Sstevel@tonic-gate #include <string.h>
56*7c478bd9Sstevel@tonic-gate #include <assert.h>
57*7c478bd9Sstevel@tonic-gate #include <ctype.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
60*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
61*7c478bd9Sstevel@tonic-gate #include <errno.h>
62*7c478bd9Sstevel@tonic-gate #ifdef HAVE_UNISTD_H
63*7c478bd9Sstevel@tonic-gate #include <unistd.h>
64*7c478bd9Sstevel@tonic-gate #endif
65*7c478bd9Sstevel@tonic-gate #ifdef HAVE_TIME_H
66*7c478bd9Sstevel@tonic-gate #include <time.h>
67*7c478bd9Sstevel@tonic-gate #endif
68*7c478bd9Sstevel@tonic-gate #include "saslint.h"
69*7c478bd9Sstevel@tonic-gate #include <saslutil.h>
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate /*  Contains:
72*7c478bd9Sstevel@tonic-gate  *
73*7c478bd9Sstevel@tonic-gate  * sasl_decode64
74*7c478bd9Sstevel@tonic-gate  * sasl_encode64
75*7c478bd9Sstevel@tonic-gate  * sasl_mkchal
76*7c478bd9Sstevel@tonic-gate  * sasl_utf8verify
77*7c478bd9Sstevel@tonic-gate  * sasl_randcreate
78*7c478bd9Sstevel@tonic-gate  * sasl_randfree
79*7c478bd9Sstevel@tonic-gate  * sasl_randseed
80*7c478bd9Sstevel@tonic-gate  * sasl_rand
81*7c478bd9Sstevel@tonic-gate  * sasl_churn
82*7c478bd9Sstevel@tonic-gate */
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
85*7c478bd9Sstevel@tonic-gate char *encode_table;
86*7c478bd9Sstevel@tonic-gate char *decode_table;
87*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate #define RPOOL_SIZE 3
90*7c478bd9Sstevel@tonic-gate struct sasl_rand_s {
91*7c478bd9Sstevel@tonic-gate     unsigned short pool[RPOOL_SIZE];
92*7c478bd9Sstevel@tonic-gate     /* since the init time might be really bad let's make this lazy */
93*7c478bd9Sstevel@tonic-gate     int initialized;
94*7c478bd9Sstevel@tonic-gate };
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate #define CHAR64(c)  (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate static char basis_64[] =
99*7c478bd9Sstevel@tonic-gate    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????";
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate static char index_64[128] = {
102*7c478bd9Sstevel@tonic-gate     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
103*7c478bd9Sstevel@tonic-gate     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
104*7c478bd9Sstevel@tonic-gate     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
105*7c478bd9Sstevel@tonic-gate     52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
106*7c478bd9Sstevel@tonic-gate     -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
107*7c478bd9Sstevel@tonic-gate     15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
108*7c478bd9Sstevel@tonic-gate     -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
109*7c478bd9Sstevel@tonic-gate     41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
110*7c478bd9Sstevel@tonic-gate };
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate /* base64 encode
113*7c478bd9Sstevel@tonic-gate  *  in      -- input data
114*7c478bd9Sstevel@tonic-gate  *  inlen   -- input data length
115*7c478bd9Sstevel@tonic-gate  *  out     -- output buffer (will be NUL terminated)
116*7c478bd9Sstevel@tonic-gate  *  outmax  -- max size of output buffer
117*7c478bd9Sstevel@tonic-gate  * result:
118*7c478bd9Sstevel@tonic-gate  *  outlen  -- gets actual length of output buffer (optional)
119*7c478bd9Sstevel@tonic-gate  *
120*7c478bd9Sstevel@tonic-gate  * Returns SASL_OK on success, SASL_BUFOVER if result won't fit
121*7c478bd9Sstevel@tonic-gate  */
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate int sasl_encode64(const char *_in, unsigned inlen,
124*7c478bd9Sstevel@tonic-gate 		  char *_out, unsigned outmax, unsigned *outlen)
125*7c478bd9Sstevel@tonic-gate {
126*7c478bd9Sstevel@tonic-gate     const unsigned char *in = (const unsigned char *)_in;
127*7c478bd9Sstevel@tonic-gate     unsigned char *out = (unsigned char *)_out;
128*7c478bd9Sstevel@tonic-gate     unsigned char oval;
129*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
130*7c478bd9Sstevel@tonic-gate     char *blah;
131*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
132*7c478bd9Sstevel@tonic-gate     unsigned olen;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate     /* check params */
135*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
136*7c478bd9Sstevel@tonic-gate     if (((inlen >0) && (in == NULL)) || _out == NULL) return SASL_BADPARAM;
137*7c478bd9Sstevel@tonic-gate #else
138*7c478bd9Sstevel@tonic-gate     if ((inlen >0) && (in == NULL)) return SASL_BADPARAM;
139*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate     /* Will it fit? */
142*7c478bd9Sstevel@tonic-gate     olen = (inlen + 2) / 3 * 4;
143*7c478bd9Sstevel@tonic-gate     if (outlen)
144*7c478bd9Sstevel@tonic-gate       *outlen = olen;
145*7c478bd9Sstevel@tonic-gate     if (outmax < olen)
146*7c478bd9Sstevel@tonic-gate       return SASL_BUFOVER;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate     /* Do the work... */
149*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
150*7c478bd9Sstevel@tonic-gate     blah=(char *) out;
151*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
152*7c478bd9Sstevel@tonic-gate     while (inlen >= 3) {
153*7c478bd9Sstevel@tonic-gate       /* user provided max buffer size; make sure we don't go over it */
154*7c478bd9Sstevel@tonic-gate         *out++ = basis_64[in[0] >> 2];
155*7c478bd9Sstevel@tonic-gate         *out++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)];
156*7c478bd9Sstevel@tonic-gate         *out++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
157*7c478bd9Sstevel@tonic-gate         *out++ = basis_64[in[2] & 0x3f];
158*7c478bd9Sstevel@tonic-gate         in += 3;
159*7c478bd9Sstevel@tonic-gate         inlen -= 3;
160*7c478bd9Sstevel@tonic-gate     }
161*7c478bd9Sstevel@tonic-gate     if (inlen > 0) {
162*7c478bd9Sstevel@tonic-gate       /* user provided max buffer size; make sure we don't go over it */
163*7c478bd9Sstevel@tonic-gate         *out++ = basis_64[in[0] >> 2];
164*7c478bd9Sstevel@tonic-gate         oval = (in[0] << 4) & 0x30;
165*7c478bd9Sstevel@tonic-gate         if (inlen > 1) oval |= in[1] >> 4;
166*7c478bd9Sstevel@tonic-gate         *out++ = basis_64[oval];
167*7c478bd9Sstevel@tonic-gate         *out++ = (inlen < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c];
168*7c478bd9Sstevel@tonic-gate         *out++ = '=';
169*7c478bd9Sstevel@tonic-gate     }
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate     if (olen < outmax)
172*7c478bd9Sstevel@tonic-gate       *out = '\0';
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate     return SASL_OK;
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate /* base64 decode
178*7c478bd9Sstevel@tonic-gate  *  in     -- input data
179*7c478bd9Sstevel@tonic-gate  *  inlen  -- length of input data
180*7c478bd9Sstevel@tonic-gate  *  out    -- output data (may be same as in, must have enough space)
181*7c478bd9Sstevel@tonic-gate  *  outmax  -- max size of output buffer
182*7c478bd9Sstevel@tonic-gate  * result:
183*7c478bd9Sstevel@tonic-gate  *  outlen -- actual output length
184*7c478bd9Sstevel@tonic-gate  *
185*7c478bd9Sstevel@tonic-gate  * returns:
186*7c478bd9Sstevel@tonic-gate  * SASL_BADPROT on bad base64,
187*7c478bd9Sstevel@tonic-gate  * SASL_BUFOVER if result won't fit,
188*7c478bd9Sstevel@tonic-gate  * SASL_OK on success
189*7c478bd9Sstevel@tonic-gate  */
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate int sasl_decode64(const char *in, unsigned inlen,
192*7c478bd9Sstevel@tonic-gate 		  char *out, unsigned outmax, unsigned *outlen)
193*7c478bd9Sstevel@tonic-gate {
194*7c478bd9Sstevel@tonic-gate     unsigned len = 0,lup;
195*7c478bd9Sstevel@tonic-gate     int c1, c2, c3, c4;
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate     /* check parameters */
198*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
199*7c478bd9Sstevel@tonic-gate     if (out==NULL || in == NULL) return SASL_FAIL;
200*7c478bd9Sstevel@tonic-gate #else
201*7c478bd9Sstevel@tonic-gate     if (out==NULL) return SASL_FAIL;
202*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate     /* xxx these necessary? */
205*7c478bd9Sstevel@tonic-gate     if (in[0] == '+' && in[1] == ' ') in += 2;
206*7c478bd9Sstevel@tonic-gate     if (*in == '\r') return SASL_FAIL;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate     for (lup=0;lup<inlen/4;lup++)
209*7c478bd9Sstevel@tonic-gate     {
210*7c478bd9Sstevel@tonic-gate         c1 = in[0];
211*7c478bd9Sstevel@tonic-gate         if (CHAR64(c1) == -1) return SASL_BADPROT;
212*7c478bd9Sstevel@tonic-gate         c2 = in[1];
213*7c478bd9Sstevel@tonic-gate         if (CHAR64(c2) == -1) return SASL_BADPROT;
214*7c478bd9Sstevel@tonic-gate         c3 = in[2];
215*7c478bd9Sstevel@tonic-gate         if (c3 != '=' && CHAR64(c3) == -1) return SASL_BADPROT;
216*7c478bd9Sstevel@tonic-gate         c4 = in[3];
217*7c478bd9Sstevel@tonic-gate         if (c4 != '=' && CHAR64(c4) == -1) return SASL_BADPROT;
218*7c478bd9Sstevel@tonic-gate         in += 4;
219*7c478bd9Sstevel@tonic-gate         *out++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);
220*7c478bd9Sstevel@tonic-gate         if(++len >= outmax) return SASL_BUFOVER;
221*7c478bd9Sstevel@tonic-gate         if (c3 != '=') {
222*7c478bd9Sstevel@tonic-gate             *out++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);
223*7c478bd9Sstevel@tonic-gate             if(++len >= outmax) return SASL_BUFOVER;
224*7c478bd9Sstevel@tonic-gate             if (c4 != '=') {
225*7c478bd9Sstevel@tonic-gate                 *out++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);
226*7c478bd9Sstevel@tonic-gate                 if(++len >= outmax) return SASL_BUFOVER;
227*7c478bd9Sstevel@tonic-gate             }
228*7c478bd9Sstevel@tonic-gate         }
229*7c478bd9Sstevel@tonic-gate     }
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate     *out=0; /* terminate string */
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate     if(outlen) *outlen=len;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate     return SASL_OK;
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate /* make a challenge string (NUL terminated)
239*7c478bd9Sstevel@tonic-gate  *  buf      -- buffer for result
240*7c478bd9Sstevel@tonic-gate  *  maxlen   -- max length of result
241*7c478bd9Sstevel@tonic-gate  *  hostflag -- 0 = don't include hostname, 1 = include hostname
242*7c478bd9Sstevel@tonic-gate  * returns final length or 0 if not enough space
243*7c478bd9Sstevel@tonic-gate  */
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate int sasl_mkchal(sasl_conn_t *conn,
246*7c478bd9Sstevel@tonic-gate 		char *buf,
247*7c478bd9Sstevel@tonic-gate 		unsigned maxlen,
248*7c478bd9Sstevel@tonic-gate 		unsigned hostflag)
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
251*7c478bd9Sstevel@tonic-gate   sasl_rand_t *pool = NULL;
252*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
253*7c478bd9Sstevel@tonic-gate   unsigned long randnum;
254*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
255*7c478bd9Sstevel@tonic-gate   int ret;
256*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
257*7c478bd9Sstevel@tonic-gate   time_t now;
258*7c478bd9Sstevel@tonic-gate   unsigned len;
259*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
260*7c478bd9Sstevel@tonic-gate   const sasl_utils_t *utils;
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate   if (conn->type == SASL_CONN_SERVER)
263*7c478bd9Sstevel@tonic-gate     utils = ((sasl_server_conn_t *)conn)->sparams->utils;
264*7c478bd9Sstevel@tonic-gate   else if (conn->type == SASL_CONN_CLIENT)
265*7c478bd9Sstevel@tonic-gate     utils = ((sasl_client_conn_t *)conn)->cparams->utils;
266*7c478bd9Sstevel@tonic-gate   else
267*7c478bd9Sstevel@tonic-gate     return 0;
268*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate   len = 4			/* <.>\0 */
271*7c478bd9Sstevel@tonic-gate     + (2 * 20);			/* 2 numbers, 20 => max size of 64bit
272*7c478bd9Sstevel@tonic-gate 				 * ulong in base 10 */
273*7c478bd9Sstevel@tonic-gate   if (hostflag && conn->serverFQDN)
274*7c478bd9Sstevel@tonic-gate     len += strlen(conn->serverFQDN) + 1 /* for the @ */;
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate   if (maxlen < len)
277*7c478bd9Sstevel@tonic-gate     return 0;
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
280*7c478bd9Sstevel@tonic-gate   utils->rand(utils->rpool, (char *)&randnum, sizeof (randnum));
281*7c478bd9Sstevel@tonic-gate #else
282*7c478bd9Sstevel@tonic-gate   ret = sasl_randcreate(&pool);
283*7c478bd9Sstevel@tonic-gate   if(ret != SASL_OK) return 0; /* xxx sasl return code? */
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate   sasl_rand(pool, (char *)&randnum, sizeof(randnum));
286*7c478bd9Sstevel@tonic-gate   sasl_randfree(&pool);
287*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate   time(&now);
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate   if (hostflag && conn->serverFQDN)
292*7c478bd9Sstevel@tonic-gate     snprintf(buf,maxlen, "<%lu.%lu@%s>", randnum, now, conn->serverFQDN);
293*7c478bd9Sstevel@tonic-gate   else
294*7c478bd9Sstevel@tonic-gate     snprintf(buf,maxlen, "<%lu.%lu>", randnum, now);
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate   return strlen(buf);
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate   /* borrowed from larry. probably works :)
300*7c478bd9Sstevel@tonic-gate    * probably is also in acap server somewhere
301*7c478bd9Sstevel@tonic-gate    */
302*7c478bd9Sstevel@tonic-gate int sasl_utf8verify(const char *str, unsigned len)
303*7c478bd9Sstevel@tonic-gate {
304*7c478bd9Sstevel@tonic-gate   unsigned i;
305*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
306*7c478bd9Sstevel@tonic-gate   if (str == NULL)
307*7c478bd9Sstevel@tonic-gate     return len == 0 ? SASL_OK : SASL_BADPARAM;
308*7c478bd9Sstevel@tonic-gate   if (len == 0) len = strlen(str);
309*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
310*7c478bd9Sstevel@tonic-gate   for (i = 0; i < len; i++) {
311*7c478bd9Sstevel@tonic-gate     /* how many octets? */
312*7c478bd9Sstevel@tonic-gate     int seqlen = 0;
313*7c478bd9Sstevel@tonic-gate     while (str[i] & (0x80 >> seqlen)) ++seqlen;
314*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
315*7c478bd9Sstevel@tonic-gate     if (seqlen == 0) {
316*7c478bd9Sstevel@tonic-gate 	if (str[i] == '\0' || str[i] == '\n' || str[i] == '\r')
317*7c478bd9Sstevel@tonic-gate 	   return SASL_BADPROT;
318*7c478bd9Sstevel@tonic-gate 	continue; /* this is a valid US-ASCII char */
319*7c478bd9Sstevel@tonic-gate     }
320*7c478bd9Sstevel@tonic-gate #else
321*7c478bd9Sstevel@tonic-gate     if (seqlen == 0) continue; /* this is a valid US-ASCII char */
322*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
323*7c478bd9Sstevel@tonic-gate     if (seqlen == 1) return SASL_BADPROT; /* this shouldn't happen here */
324*7c478bd9Sstevel@tonic-gate     if (seqlen > 6) return SASL_BADPROT; /* illegal */
325*7c478bd9Sstevel@tonic-gate     while (--seqlen)
326*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
327*7c478bd9Sstevel@tonic-gate       if ((str[++i] & 0xC0) != 0x80)
328*7c478bd9Sstevel@tonic-gate 	return SASL_BADPROT; /* needed an appropriate octet */
329*7c478bd9Sstevel@tonic-gate #else
330*7c478bd9Sstevel@tonic-gate       if ((str[++i] & 0xC0) != 0xF0) return SASL_BADPROT; /* needed a 10 octet */
331*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
332*7c478bd9Sstevel@tonic-gate   }
333*7c478bd9Sstevel@tonic-gate   return SASL_OK;
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate /*
337*7c478bd9Sstevel@tonic-gate  * To see why this is really bad see RFC 1750
338*7c478bd9Sstevel@tonic-gate  *
339*7c478bd9Sstevel@tonic-gate  * unfortunatly there currently is no way to make
340*7c478bd9Sstevel@tonic-gate  * cryptographically secure pseudo random numbers
341*7c478bd9Sstevel@tonic-gate  * without specialized hardware etc...
342*7c478bd9Sstevel@tonic-gate  * thus, this is for nonce use only
343*7c478bd9Sstevel@tonic-gate  */
344*7c478bd9Sstevel@tonic-gate void getranddata(unsigned short ret[RPOOL_SIZE])
345*7c478bd9Sstevel@tonic-gate {
346*7c478bd9Sstevel@tonic-gate     long curtime;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate     memset(ret, 0, RPOOL_SIZE*sizeof(unsigned short));
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate #ifdef DEV_RANDOM
351*7c478bd9Sstevel@tonic-gate     {
352*7c478bd9Sstevel@tonic-gate 	int fd;
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 	fd = open(DEV_RANDOM, O_RDONLY);
355*7c478bd9Sstevel@tonic-gate 	if(fd != -1) {
356*7c478bd9Sstevel@tonic-gate 	    unsigned char *buf = (unsigned char *)ret;
357*7c478bd9Sstevel@tonic-gate 	    ssize_t bytesread = 0;
358*7c478bd9Sstevel@tonic-gate 	    size_t bytesleft = RPOOL_SIZE*sizeof(unsigned short);
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	    do {
361*7c478bd9Sstevel@tonic-gate 		bytesread = read(fd, buf, bytesleft);
362*7c478bd9Sstevel@tonic-gate 		if(bytesread == -1 && errno == EINTR) continue;
363*7c478bd9Sstevel@tonic-gate 		else if(bytesread <= 0) break;
364*7c478bd9Sstevel@tonic-gate 		bytesleft -= bytesread;
365*7c478bd9Sstevel@tonic-gate 		buf += bytesread;
366*7c478bd9Sstevel@tonic-gate 	    } while(bytesleft != 0);
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	    close(fd);
369*7c478bd9Sstevel@tonic-gate 	}
370*7c478bd9Sstevel@tonic-gate     }
371*7c478bd9Sstevel@tonic-gate #endif
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GETPID
374*7c478bd9Sstevel@tonic-gate     ret[0] ^= (unsigned short) getpid();
375*7c478bd9Sstevel@tonic-gate #endif
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate #ifdef HAVE_GETTIMEOFDAY
378*7c478bd9Sstevel@tonic-gate     {
379*7c478bd9Sstevel@tonic-gate 	struct timeval tv;
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	/* xxx autoconf macro */
382*7c478bd9Sstevel@tonic-gate #ifdef _SVID_GETTOD
383*7c478bd9Sstevel@tonic-gate 	if (!gettimeofday(&tv))
384*7c478bd9Sstevel@tonic-gate #else
385*7c478bd9Sstevel@tonic-gate 	if (!gettimeofday(&tv, NULL))
386*7c478bd9Sstevel@tonic-gate #endif
387*7c478bd9Sstevel@tonic-gate 	{
388*7c478bd9Sstevel@tonic-gate 	    /* longs are guaranteed to be at least 32 bits; we need
389*7c478bd9Sstevel@tonic-gate 	       16 bits in each short */
390*7c478bd9Sstevel@tonic-gate 	    ret[0] ^= (unsigned short) (tv.tv_sec & 0xFFFF);
391*7c478bd9Sstevel@tonic-gate 	    ret[1] ^= (unsigned short) (clock() & 0xFFFF);
392*7c478bd9Sstevel@tonic-gate 	    ret[1] ^= (unsigned short) (tv.tv_usec >> 16);
393*7c478bd9Sstevel@tonic-gate 	    ret[2] ^= (unsigned short) (tv.tv_usec & 0xFFFF);
394*7c478bd9Sstevel@tonic-gate 	    return;
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate     }
397*7c478bd9Sstevel@tonic-gate #endif /* HAVE_GETTIMEOFDAY */
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate     /* if all else fails just use time() */
400*7c478bd9Sstevel@tonic-gate     curtime = (long) time(NULL); /* better be at least 32 bits */
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate     ret[0] ^= (unsigned short) (curtime >> 16);
403*7c478bd9Sstevel@tonic-gate     ret[1] ^= (unsigned short) (curtime & 0xFFFF);
404*7c478bd9Sstevel@tonic-gate     ret[2] ^= (unsigned short) (clock() & 0xFFFF);
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate     return;
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate int sasl_randcreate(sasl_rand_t **rpool)
410*7c478bd9Sstevel@tonic-gate {
411*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
412*7c478bd9Sstevel@tonic-gate   (*rpool)=sasl_sun_ALLOC(sizeof(sasl_rand_t));
413*7c478bd9Sstevel@tonic-gate #else
414*7c478bd9Sstevel@tonic-gate   (*rpool)=sasl_ALLOC(sizeof(sasl_rand_t));
415*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
416*7c478bd9Sstevel@tonic-gate   if ((*rpool) == NULL) return SASL_NOMEM;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate   /* init is lazy */
419*7c478bd9Sstevel@tonic-gate   (*rpool)->initialized = 0;
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate   return SASL_OK;
422*7c478bd9Sstevel@tonic-gate }
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate void sasl_randfree(sasl_rand_t **rpool)
425*7c478bd9Sstevel@tonic-gate {
426*7c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
427*7c478bd9Sstevel@tonic-gate     sasl_sun_FREE(*rpool);
428*7c478bd9Sstevel@tonic-gate #else
429*7c478bd9Sstevel@tonic-gate     sasl_FREE(*rpool);
430*7c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate void sasl_randseed (sasl_rand_t *rpool, const char *seed, unsigned len)
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate     /* is it acceptable to just use the 1st 3 char's given??? */
436*7c478bd9Sstevel@tonic-gate     unsigned int lup;
437*7c478bd9Sstevel@tonic-gate 
438*7c478bd9Sstevel@tonic-gate     /* check params */
439*7c478bd9Sstevel@tonic-gate     if (seed == NULL) return;
440*7c478bd9Sstevel@tonic-gate     if (rpool == NULL) return;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate     rpool->initialized = 1;
443*7c478bd9Sstevel@tonic-gate 
444*7c478bd9Sstevel@tonic-gate     if (len > sizeof(unsigned short)*RPOOL_SIZE)
445*7c478bd9Sstevel@tonic-gate       len = sizeof(unsigned short)*RPOOL_SIZE;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate     for (lup = 0; lup < len; lup += 2)
448*7c478bd9Sstevel@tonic-gate 	rpool->pool[lup/2] = (seed[lup] << 8) + seed[lup + 1];
449*7c478bd9Sstevel@tonic-gate }
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate static void randinit(sasl_rand_t *rpool)
452*7c478bd9Sstevel@tonic-gate {
453*7c478bd9Sstevel@tonic-gate     assert(rpool);
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate     if (!rpool->initialized) {
456*7c478bd9Sstevel@tonic-gate 	getranddata(rpool->pool);
457*7c478bd9Sstevel@tonic-gate 	rpool->initialized = 1;
458*7c478bd9Sstevel@tonic-gate #if !(defined(WIN32)||defined(macintosh))
459*7c478bd9Sstevel@tonic-gate #ifndef HAVE_JRAND48
460*7c478bd9Sstevel@tonic-gate     {
461*7c478bd9Sstevel@tonic-gate       /* xxx varies by platform */
462*7c478bd9Sstevel@tonic-gate 	unsigned int *foo = (unsigned int *)rpool->pool;
463*7c478bd9Sstevel@tonic-gate 	srandom(*foo);
464*7c478bd9Sstevel@tonic-gate     }
465*7c478bd9Sstevel@tonic-gate #endif /* HAVE_JRAND48 */
466*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */
467*7c478bd9Sstevel@tonic-gate     }
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate }
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate void sasl_rand (sasl_rand_t *rpool, char *buf, unsigned len)
472*7c478bd9Sstevel@tonic-gate {
473*7c478bd9Sstevel@tonic-gate     unsigned int lup;
474*7c478bd9Sstevel@tonic-gate     /* check params */
475*7c478bd9Sstevel@tonic-gate     if (!rpool || !buf) return;
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate     /* init if necessary */
478*7c478bd9Sstevel@tonic-gate     randinit(rpool);
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate #if (defined(WIN32)||defined(macintosh))
481*7c478bd9Sstevel@tonic-gate     for (lup=0;lup<len;lup++)
482*7c478bd9Sstevel@tonic-gate 	buf[lup] = (char) (rand() >> 8);
483*7c478bd9Sstevel@tonic-gate #else /* WIN32 */
484*7c478bd9Sstevel@tonic-gate #ifdef HAVE_JRAND48
485*7c478bd9Sstevel@tonic-gate     for (lup=0; lup<len; lup++)
486*7c478bd9Sstevel@tonic-gate 	buf[lup] = (char) (jrand48(rpool->pool) >> 8);
487*7c478bd9Sstevel@tonic-gate #else
488*7c478bd9Sstevel@tonic-gate     for (lup=0;lup<len;lup++)
489*7c478bd9Sstevel@tonic-gate 	buf[lup] = (char) (random() >> 8);
490*7c478bd9Sstevel@tonic-gate #endif /* HAVE_JRAND48 */
491*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate /* this function is just a bad idea all around, since we're not trying to
495*7c478bd9Sstevel@tonic-gate    implement a true random number generator */
496*7c478bd9Sstevel@tonic-gate void sasl_churn (sasl_rand_t *rpool, const char *data, unsigned len)
497*7c478bd9Sstevel@tonic-gate {
498*7c478bd9Sstevel@tonic-gate     unsigned int lup;
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate     /* check params */
501*7c478bd9Sstevel@tonic-gate     if (!rpool || !data) return;
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate     /* init if necessary */
504*7c478bd9Sstevel@tonic-gate     randinit(rpool);
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate     for (lup=0; lup<len; lup++)
507*7c478bd9Sstevel@tonic-gate 	rpool->pool[lup % RPOOL_SIZE] ^= data[lup];
508*7c478bd9Sstevel@tonic-gate }
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate void sasl_erasebuffer(char *buf, unsigned len) {
511*7c478bd9Sstevel@tonic-gate     memset(buf, 0, len);
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
515*7c478bd9Sstevel@tonic-gate #ifdef WIN32
516*7c478bd9Sstevel@tonic-gate /*****************************************************************************
517*7c478bd9Sstevel@tonic-gate  *
518*7c478bd9Sstevel@tonic-gate  *  MODULE NAME : GETOPT.C
519*7c478bd9Sstevel@tonic-gate  *
520*7c478bd9Sstevel@tonic-gate  *  COPYRIGHTS:
521*7c478bd9Sstevel@tonic-gate  *             This module contains code made available by IBM
522*7c478bd9Sstevel@tonic-gate  *             Corporation on an AS IS basis.  Any one receiving the
523*7c478bd9Sstevel@tonic-gate  *             module is considered to be licensed under IBM copyrights
524*7c478bd9Sstevel@tonic-gate  *             to use the IBM-provided source code in any way he or she
525*7c478bd9Sstevel@tonic-gate  *             deems fit, including copying it, compiling it, modifying
526*7c478bd9Sstevel@tonic-gate  *             it, and redistributing it, with or without
527*7c478bd9Sstevel@tonic-gate  *             modifications.  No license under any IBM patents or
528*7c478bd9Sstevel@tonic-gate  *             patent applications is to be implied from this copyright
529*7c478bd9Sstevel@tonic-gate  *             license.
530*7c478bd9Sstevel@tonic-gate  *
531*7c478bd9Sstevel@tonic-gate  *             A user of the module should understand that IBM cannot
532*7c478bd9Sstevel@tonic-gate  *             provide technical support for the module and will not be
533*7c478bd9Sstevel@tonic-gate  *             responsible for any consequences of use of the program.
534*7c478bd9Sstevel@tonic-gate  *
535*7c478bd9Sstevel@tonic-gate  *             Any notices, including this one, are not to be removed
536*7c478bd9Sstevel@tonic-gate  *             from the module without the prior written consent of
537*7c478bd9Sstevel@tonic-gate  *             IBM.
538*7c478bd9Sstevel@tonic-gate  *
539*7c478bd9Sstevel@tonic-gate  *  AUTHOR:   Original author:
540*7c478bd9Sstevel@tonic-gate  *                 G. R. Blair (BOBBLAIR at AUSVM1)
541*7c478bd9Sstevel@tonic-gate  *                 Internet: bobblair@bobblair.austin.ibm.com
542*7c478bd9Sstevel@tonic-gate  *
543*7c478bd9Sstevel@tonic-gate  *            Extensively revised by:
544*7c478bd9Sstevel@tonic-gate  *                 John Q. Walker II, Ph.D. (JOHHQ at RALVM6)
545*7c478bd9Sstevel@tonic-gate  *                 Internet: johnq@ralvm6.vnet.ibm.com
546*7c478bd9Sstevel@tonic-gate  *
547*7c478bd9Sstevel@tonic-gate  *****************************************************************************/
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate /******************************************************************************
550*7c478bd9Sstevel@tonic-gate  * getopt()
551*7c478bd9Sstevel@tonic-gate  *
552*7c478bd9Sstevel@tonic-gate  * The getopt() function is a command line parser.  It returns the next
553*7c478bd9Sstevel@tonic-gate  * option character in argv that matches an option character in opstring.
554*7c478bd9Sstevel@tonic-gate  *
555*7c478bd9Sstevel@tonic-gate  * The argv argument points to an array of argc+1 elements containing argc
556*7c478bd9Sstevel@tonic-gate  * pointers to character strings followed by a null pointer.
557*7c478bd9Sstevel@tonic-gate  *
558*7c478bd9Sstevel@tonic-gate  * The opstring argument points to a string of option characters; if an
559*7c478bd9Sstevel@tonic-gate  * option character is followed by a colon, the option is expected to have
560*7c478bd9Sstevel@tonic-gate  * an argument that may or may not be separated from it by white space.
561*7c478bd9Sstevel@tonic-gate  * The external variable optarg is set to point to the start of the option
562*7c478bd9Sstevel@tonic-gate  * argument on return from getopt().
563*7c478bd9Sstevel@tonic-gate  *
564*7c478bd9Sstevel@tonic-gate  * The getopt() function places in optind the argv index of the next argument
565*7c478bd9Sstevel@tonic-gate  * to be processed.  The system initializes the external variable optind to
566*7c478bd9Sstevel@tonic-gate  * 1 before the first call to getopt().
567*7c478bd9Sstevel@tonic-gate  *
568*7c478bd9Sstevel@tonic-gate  * When all options have been processed (that is, up to the first nonoption
569*7c478bd9Sstevel@tonic-gate  * argument), getopt() returns EOF.  The special option "--" may be used to
570*7c478bd9Sstevel@tonic-gate  * delimit the end of the options; EOF will be returned, and "--" will be
571*7c478bd9Sstevel@tonic-gate  * skipped.
572*7c478bd9Sstevel@tonic-gate  *
573*7c478bd9Sstevel@tonic-gate  * The getopt() function returns a question mark (?) when it encounters an
574*7c478bd9Sstevel@tonic-gate  * option character not included in opstring.  This error message can be
575*7c478bd9Sstevel@tonic-gate  * disabled by setting opterr to zero.  Otherwise, it returns the option
576*7c478bd9Sstevel@tonic-gate  * character that was detected.
577*7c478bd9Sstevel@tonic-gate  *
578*7c478bd9Sstevel@tonic-gate  * If the special option "--" is detected, or all options have been
579*7c478bd9Sstevel@tonic-gate  * processed, EOF is returned.
580*7c478bd9Sstevel@tonic-gate  *
581*7c478bd9Sstevel@tonic-gate  * Options are marked by either a minus sign (-) or a slash (/).
582*7c478bd9Sstevel@tonic-gate  *
583*7c478bd9Sstevel@tonic-gate  * No errors are defined.
584*7c478bd9Sstevel@tonic-gate  *****************************************************************************/
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate #include <string.h>                 /* for strchr() */
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate /* static (global) variables that are specified as exported by getopt() */
589*7c478bd9Sstevel@tonic-gate __declspec(dllexport) char *optarg = NULL;    /* pointer to the start of the option argument  */
590*7c478bd9Sstevel@tonic-gate __declspec(dllexport) int   optind = 1;       /* number of the next argv[] to be evaluated    */
591*7c478bd9Sstevel@tonic-gate __declspec(dllexport) int   opterr = 1;       /* non-zero if a question mark should be returned */
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate /* handle possible future character set concerns by putting this in a macro */
595*7c478bd9Sstevel@tonic-gate #define _next_char(string)  (char)(*(string+1))
596*7c478bd9Sstevel@tonic-gate 
597*7c478bd9Sstevel@tonic-gate int getopt(int argc, char *argv[], char *opstring)
598*7c478bd9Sstevel@tonic-gate {
599*7c478bd9Sstevel@tonic-gate     static char *pIndexPosition = NULL; /* place inside current argv string */
600*7c478bd9Sstevel@tonic-gate     char *pArgString = NULL;        /* where to start from next */
601*7c478bd9Sstevel@tonic-gate     char *pOptString;               /* the string in our program */
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate     if (pIndexPosition != NULL) {
605*7c478bd9Sstevel@tonic-gate         /* we last left off inside an argv string */
606*7c478bd9Sstevel@tonic-gate         if (*(++pIndexPosition)) {
607*7c478bd9Sstevel@tonic-gate             /* there is more to come in the most recent argv */
608*7c478bd9Sstevel@tonic-gate             pArgString = pIndexPosition;
609*7c478bd9Sstevel@tonic-gate         }
610*7c478bd9Sstevel@tonic-gate     }
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate     if (pArgString == NULL) {
613*7c478bd9Sstevel@tonic-gate         /* we didn't leave off in the middle of an argv string */
614*7c478bd9Sstevel@tonic-gate         if (optind >= argc) {
615*7c478bd9Sstevel@tonic-gate             /* more command-line arguments than the argument count */
616*7c478bd9Sstevel@tonic-gate             pIndexPosition = NULL;  /* not in the middle of anything */
617*7c478bd9Sstevel@tonic-gate             return EOF;             /* used up all command-line arguments */
618*7c478bd9Sstevel@tonic-gate         }
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate         /*---------------------------------------------------------------------
621*7c478bd9Sstevel@tonic-gate          * If the next argv[] is not an option, there can be no more options.
622*7c478bd9Sstevel@tonic-gate          *-------------------------------------------------------------------*/
623*7c478bd9Sstevel@tonic-gate         pArgString = argv[optind++]; /* set this to the next argument ptr */
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate         if (('/' != *pArgString) && /* doesn't start with a slash or a dash? */
626*7c478bd9Sstevel@tonic-gate             ('-' != *pArgString)) {
627*7c478bd9Sstevel@tonic-gate             --optind;               /* point to current arg once we're done */
628*7c478bd9Sstevel@tonic-gate             optarg = NULL;          /* no argument follows the option */
629*7c478bd9Sstevel@tonic-gate             pIndexPosition = NULL;  /* not in the middle of anything */
630*7c478bd9Sstevel@tonic-gate             return EOF;             /* used up all the command-line flags */
631*7c478bd9Sstevel@tonic-gate         }
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate         /* check for special end-of-flags markers */
634*7c478bd9Sstevel@tonic-gate         if ((strcmp(pArgString, "-") == 0) ||
635*7c478bd9Sstevel@tonic-gate             (strcmp(pArgString, "--") == 0)) {
636*7c478bd9Sstevel@tonic-gate             optarg = NULL;          /* no argument follows the option */
637*7c478bd9Sstevel@tonic-gate             pIndexPosition = NULL;  /* not in the middle of anything */
638*7c478bd9Sstevel@tonic-gate             return EOF;             /* encountered the special flag */
639*7c478bd9Sstevel@tonic-gate         }
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate         pArgString++;               /* look past the / or - */
642*7c478bd9Sstevel@tonic-gate     }
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate     if (':' == *pArgString) {       /* is it a colon? */
645*7c478bd9Sstevel@tonic-gate         /*---------------------------------------------------------------------
646*7c478bd9Sstevel@tonic-gate          * Rare case: if opterr is non-zero, return a question mark;
647*7c478bd9Sstevel@tonic-gate          * otherwise, just return the colon we're on.
648*7c478bd9Sstevel@tonic-gate          *-------------------------------------------------------------------*/
649*7c478bd9Sstevel@tonic-gate         return (opterr ? (int)'?' : (int)':');
650*7c478bd9Sstevel@tonic-gate     }
651*7c478bd9Sstevel@tonic-gate     else if ((pOptString = strchr(opstring, *pArgString)) == 0) {
652*7c478bd9Sstevel@tonic-gate         /*---------------------------------------------------------------------
653*7c478bd9Sstevel@tonic-gate          * The letter on the command-line wasn't any good.
654*7c478bd9Sstevel@tonic-gate          *-------------------------------------------------------------------*/
655*7c478bd9Sstevel@tonic-gate         optarg = NULL;              /* no argument follows the option */
656*7c478bd9Sstevel@tonic-gate         pIndexPosition = NULL;      /* not in the middle of anything */
657*7c478bd9Sstevel@tonic-gate         return (opterr ? (int)'?' : (int)*pArgString);
658*7c478bd9Sstevel@tonic-gate     }
659*7c478bd9Sstevel@tonic-gate     else {
660*7c478bd9Sstevel@tonic-gate         /*---------------------------------------------------------------------
661*7c478bd9Sstevel@tonic-gate          * The letter on the command-line matches one we expect to see
662*7c478bd9Sstevel@tonic-gate          *-------------------------------------------------------------------*/
663*7c478bd9Sstevel@tonic-gate         if (':' == _next_char(pOptString)) { /* is the next letter a colon? */
664*7c478bd9Sstevel@tonic-gate             /* It is a colon.  Look for an argument string. */
665*7c478bd9Sstevel@tonic-gate             if ('\0' != _next_char(pArgString)) {  /* argument in this argv? */
666*7c478bd9Sstevel@tonic-gate                 optarg = &pArgString[1];   /* Yes, it is */
667*7c478bd9Sstevel@tonic-gate             }
668*7c478bd9Sstevel@tonic-gate             else {
669*7c478bd9Sstevel@tonic-gate                 /*-------------------------------------------------------------
670*7c478bd9Sstevel@tonic-gate                  * The argument string must be in the next argv.
671*7c478bd9Sstevel@tonic-gate                  * But, what if there is none (bad input from the user)?
672*7c478bd9Sstevel@tonic-gate                  * In that case, return the letter, and optarg as NULL.
673*7c478bd9Sstevel@tonic-gate                  *-----------------------------------------------------------*/
674*7c478bd9Sstevel@tonic-gate                 if (optind < argc)
675*7c478bd9Sstevel@tonic-gate                     optarg = argv[optind++];
676*7c478bd9Sstevel@tonic-gate                 else {
677*7c478bd9Sstevel@tonic-gate                     optarg = NULL;
678*7c478bd9Sstevel@tonic-gate                     return (opterr ? (int)'?' : (int)*pArgString);
679*7c478bd9Sstevel@tonic-gate                 }
680*7c478bd9Sstevel@tonic-gate             }
681*7c478bd9Sstevel@tonic-gate             pIndexPosition = NULL;  /* not in the middle of anything */
682*7c478bd9Sstevel@tonic-gate         }
683*7c478bd9Sstevel@tonic-gate         else {
684*7c478bd9Sstevel@tonic-gate             /* it's not a colon, so just return the letter */
685*7c478bd9Sstevel@tonic-gate             optarg = NULL;          /* no argument follows the option */
686*7c478bd9Sstevel@tonic-gate             pIndexPosition = pArgString;    /* point to the letter we're on */
687*7c478bd9Sstevel@tonic-gate         }
688*7c478bd9Sstevel@tonic-gate         return (int)*pArgString;    /* return the letter that matched */
689*7c478bd9Sstevel@tonic-gate     }
690*7c478bd9Sstevel@tonic-gate }
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate #ifndef PASSWORD_MAX
693*7c478bd9Sstevel@tonic-gate #  define PASSWORD_MAX 255
694*7c478bd9Sstevel@tonic-gate #endif
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate #include <conio.h>
697*7c478bd9Sstevel@tonic-gate char *
698*7c478bd9Sstevel@tonic-gate getpass(prompt)
699*7c478bd9Sstevel@tonic-gate const char *prompt;
700*7c478bd9Sstevel@tonic-gate {
701*7c478bd9Sstevel@tonic-gate 	register char *p;
702*7c478bd9Sstevel@tonic-gate 	register c;
703*7c478bd9Sstevel@tonic-gate 	static char pbuf[PASSWORD_MAX];
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s", prompt); (void) fflush(stderr);
706*7c478bd9Sstevel@tonic-gate 	for (p=pbuf; (c = _getch())!=13 && c!=EOF;) {
707*7c478bd9Sstevel@tonic-gate 		if (p < &pbuf[sizeof(pbuf)-1])
708*7c478bd9Sstevel@tonic-gate 			*p++ = c;
709*7c478bd9Sstevel@tonic-gate 	}
710*7c478bd9Sstevel@tonic-gate 	*p = '\0';
711*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "\n"); (void) fflush(stderr);
712*7c478bd9Sstevel@tonic-gate 	return(pbuf);
713*7c478bd9Sstevel@tonic-gate }
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate #endif /* WIN32 */
718*7c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
719