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