1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 31*7c478bd9Sstevel@tonic-gate #include <stdio.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <strings.h> 34*7c478bd9Sstevel@tonic-gate #include <ctype.h> 35*7c478bd9Sstevel@tonic-gate #include <errno.h> 36*7c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h> 37*7c478bd9Sstevel@tonic-gate #include <gssapi/gssapi_ext.h> 38*7c478bd9Sstevel@tonic-gate #include <synch.h> 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #define Q_DEFAULT "default" 41*7c478bd9Sstevel@tonic-gate #define BUFLEN 256 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate static int qop_num_pair_cnt; 44*7c478bd9Sstevel@tonic-gate static const char QOP_NUM_FILE[] = "/etc/gss/qop"; 45*7c478bd9Sstevel@tonic-gate static qop_num qop_num_pairs[MAX_QOP_NUM_PAIRS+1]; 46*7c478bd9Sstevel@tonic-gate static mutex_t qopfile_lock = DEFAULTMUTEX; 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate static OM_uint32 __gss_read_qop_file(void); 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate /* 51*7c478bd9Sstevel@tonic-gate * This routine fetches qop and num from "/etc/gss/qop". 52*7c478bd9Sstevel@tonic-gate * There is a memory leak associated with rereading this file, 53*7c478bd9Sstevel@tonic-gate * because we can't free the qop_num_pairs array when we reread 54*7c478bd9Sstevel@tonic-gate * the file (some callers may have been given these pointers). 55*7c478bd9Sstevel@tonic-gate * In general, this memory leak should be a small one, because 56*7c478bd9Sstevel@tonic-gate * we don't expect the qop file to be changed and reread often. 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate static OM_uint32 59*7c478bd9Sstevel@tonic-gate __gss_read_qop_file(void) 60*7c478bd9Sstevel@tonic-gate { 61*7c478bd9Sstevel@tonic-gate char buf[BUFLEN]; /* one line from the file */ 62*7c478bd9Sstevel@tonic-gate char *name, *next; 63*7c478bd9Sstevel@tonic-gate char *qopname, *num_str; 64*7c478bd9Sstevel@tonic-gate char *line; 65*7c478bd9Sstevel@tonic-gate FILE *fp; 66*7c478bd9Sstevel@tonic-gate static int last = 0; 67*7c478bd9Sstevel@tonic-gate struct stat stbuf; 68*7c478bd9Sstevel@tonic-gate OM_uint32 major = GSS_S_COMPLETE; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&qopfile_lock); 71*7c478bd9Sstevel@tonic-gate if (stat(QOP_NUM_FILE, &stbuf) != 0 || stbuf.st_mtime < last) { 72*7c478bd9Sstevel@tonic-gate if (!qop_num_pairs[0].qop) { 73*7c478bd9Sstevel@tonic-gate major = GSS_S_FAILURE; 74*7c478bd9Sstevel@tonic-gate } 75*7c478bd9Sstevel@tonic-gate goto done; 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate last = stbuf.st_mtime; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate fp = fopen(QOP_NUM_FILE, "r"); 80*7c478bd9Sstevel@tonic-gate if (fp == (FILE *)0) { 81*7c478bd9Sstevel@tonic-gate major = GSS_S_FAILURE; 82*7c478bd9Sstevel@tonic-gate goto done; 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* 86*7c478bd9Sstevel@tonic-gate * For each line in the file parse it appropriately. 87*7c478bd9Sstevel@tonic-gate * File format : qopname num(int) 88*7c478bd9Sstevel@tonic-gate * Note that we silently ignore corrupt entries. 89*7c478bd9Sstevel@tonic-gate */ 90*7c478bd9Sstevel@tonic-gate qop_num_pair_cnt = 0; 91*7c478bd9Sstevel@tonic-gate while (!feof(fp)) { 92*7c478bd9Sstevel@tonic-gate line = fgets(buf, BUFLEN, fp); 93*7c478bd9Sstevel@tonic-gate if (line == NULL) 94*7c478bd9Sstevel@tonic-gate break; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* Skip comments and blank lines */ 97*7c478bd9Sstevel@tonic-gate if ((*line == '#') || (*line == '\n')) 98*7c478bd9Sstevel@tonic-gate continue; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* Skip trailing comments */ 101*7c478bd9Sstevel@tonic-gate next = strchr(line, '#'); 102*7c478bd9Sstevel@tonic-gate if (next) 103*7c478bd9Sstevel@tonic-gate *next = '\0'; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate name = &(buf[0]); 106*7c478bd9Sstevel@tonic-gate while (isspace(*name)) 107*7c478bd9Sstevel@tonic-gate name++; 108*7c478bd9Sstevel@tonic-gate if (*name == '\0') /* blank line */ 109*7c478bd9Sstevel@tonic-gate continue; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate qopname = name; /* will contain qop name */ 112*7c478bd9Sstevel@tonic-gate while (!isspace(*qopname)) 113*7c478bd9Sstevel@tonic-gate qopname++; 114*7c478bd9Sstevel@tonic-gate if (*qopname == '\0') { 115*7c478bd9Sstevel@tonic-gate continue; 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate next = qopname+1; 118*7c478bd9Sstevel@tonic-gate *qopname = '\0'; /* null terminate qopname */ 119*7c478bd9Sstevel@tonic-gate qop_num_pairs[qop_num_pair_cnt].qop = strdup(name); 120*7c478bd9Sstevel@tonic-gate if (qop_num_pairs[qop_num_pair_cnt].qop == NULL) 121*7c478bd9Sstevel@tonic-gate continue; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate name = next; 124*7c478bd9Sstevel@tonic-gate while (isspace(*name)) 125*7c478bd9Sstevel@tonic-gate name++; 126*7c478bd9Sstevel@tonic-gate if (*name == '\0') { /* end of line, no num */ 127*7c478bd9Sstevel@tonic-gate free(qop_num_pairs[qop_num_pair_cnt].qop); 128*7c478bd9Sstevel@tonic-gate continue; 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate num_str = name; /* will contain num (n) */ 131*7c478bd9Sstevel@tonic-gate while (!isspace(*num_str)) 132*7c478bd9Sstevel@tonic-gate num_str++; 133*7c478bd9Sstevel@tonic-gate next = num_str+1; 134*7c478bd9Sstevel@tonic-gate *num_str++ = '\0'; /* null terminate num_str */ 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate qop_num_pairs[qop_num_pair_cnt].num = (OM_uint32)atoi(name); 137*7c478bd9Sstevel@tonic-gate name = next; 138*7c478bd9Sstevel@tonic-gate while (isspace(*name)) 139*7c478bd9Sstevel@tonic-gate name++; 140*7c478bd9Sstevel@tonic-gate if (*name == '\0') { /* end of line, no mechanism */ 141*7c478bd9Sstevel@tonic-gate free(qop_num_pairs[qop_num_pair_cnt].qop); 142*7c478bd9Sstevel@tonic-gate continue; 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate num_str = name; /* will contain mech */ 145*7c478bd9Sstevel@tonic-gate while (!isspace(*num_str)) 146*7c478bd9Sstevel@tonic-gate num_str++; 147*7c478bd9Sstevel@tonic-gate *num_str = '\0'; 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate qop_num_pairs[qop_num_pair_cnt].mech = strdup(name); 150*7c478bd9Sstevel@tonic-gate if (qop_num_pairs[qop_num_pair_cnt].mech == NULL) { 151*7c478bd9Sstevel@tonic-gate free(qop_num_pairs[qop_num_pair_cnt].qop); 152*7c478bd9Sstevel@tonic-gate continue; 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate if (qop_num_pair_cnt++ >= MAX_QOP_NUM_PAIRS) 156*7c478bd9Sstevel@tonic-gate break; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 159*7c478bd9Sstevel@tonic-gate done: 160*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&qopfile_lock); 161*7c478bd9Sstevel@tonic-gate return (major); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate OM_uint32 165*7c478bd9Sstevel@tonic-gate __gss_qop_to_num( 166*7c478bd9Sstevel@tonic-gate char *qop, 167*7c478bd9Sstevel@tonic-gate char *mech, 168*7c478bd9Sstevel@tonic-gate OM_uint32 *num 169*7c478bd9Sstevel@tonic-gate ) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate int i; 172*7c478bd9Sstevel@tonic-gate OM_uint32 major = GSS_S_FAILURE; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate if (!num) 175*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate if (qop == NULL || strlen(qop) == 0 || 178*7c478bd9Sstevel@tonic-gate strcasecmp(qop, Q_DEFAULT) == 0) { 179*7c478bd9Sstevel@tonic-gate *num = GSS_C_QOP_DEFAULT; 180*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE) 184*7c478bd9Sstevel@tonic-gate return (major); 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate for (i = 0; i < qop_num_pair_cnt; i++) { 187*7c478bd9Sstevel@tonic-gate if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) && 188*7c478bd9Sstevel@tonic-gate (strcasecmp(qop, qop_num_pairs[i].qop) == 0)) { 189*7c478bd9Sstevel@tonic-gate *num = qop_num_pairs[i].num; 190*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate OM_uint32 198*7c478bd9Sstevel@tonic-gate __gss_num_to_qop( 199*7c478bd9Sstevel@tonic-gate char *mech, 200*7c478bd9Sstevel@tonic-gate OM_uint32 num, 201*7c478bd9Sstevel@tonic-gate char **qop 202*7c478bd9Sstevel@tonic-gate ) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate int i; 205*7c478bd9Sstevel@tonic-gate OM_uint32 major; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate if (!qop) 208*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 209*7c478bd9Sstevel@tonic-gate *qop = NULL; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if (num == GSS_C_QOP_DEFAULT) { 212*7c478bd9Sstevel@tonic-gate *qop = Q_DEFAULT; 213*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate if (mech == NULL) 217*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE) 220*7c478bd9Sstevel@tonic-gate return (major); 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate for (i = 0; i < qop_num_pair_cnt; i++) { 223*7c478bd9Sstevel@tonic-gate if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) && 224*7c478bd9Sstevel@tonic-gate (num == qop_num_pairs[i].num)) { 225*7c478bd9Sstevel@tonic-gate *qop = qop_num_pairs[i].qop; 226*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate /* 233*7c478bd9Sstevel@tonic-gate * For a given mechanism pass back qop information about it in a buffer 234*7c478bd9Sstevel@tonic-gate * of size MAX_QOPS_PER_MECH+1. 235*7c478bd9Sstevel@tonic-gate */ 236*7c478bd9Sstevel@tonic-gate OM_uint32 237*7c478bd9Sstevel@tonic-gate __gss_get_mech_info( 238*7c478bd9Sstevel@tonic-gate char *mech, 239*7c478bd9Sstevel@tonic-gate char **qops 240*7c478bd9Sstevel@tonic-gate ) 241*7c478bd9Sstevel@tonic-gate { 242*7c478bd9Sstevel@tonic-gate int i, cnt = 0; 243*7c478bd9Sstevel@tonic-gate OM_uint32 major = GSS_S_COMPLETE; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (!qops) 246*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 247*7c478bd9Sstevel@tonic-gate *qops = NULL; 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if (!mech) 250*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE) 253*7c478bd9Sstevel@tonic-gate return (major); 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate for (i = 0; i < qop_num_pair_cnt; i++) { 256*7c478bd9Sstevel@tonic-gate if (strcmp(mech, qop_num_pairs[i].mech) == 0) { 257*7c478bd9Sstevel@tonic-gate if (cnt >= MAX_QOPS_PER_MECH) { 258*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate qops[cnt++] = qop_num_pairs[i].qop; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate qops[cnt] = NULL; 264*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* 268*7c478bd9Sstevel@tonic-gate * Copy the qop values and names for the mechanism back in a qop_num 269*7c478bd9Sstevel@tonic-gate * buffer of size MAX_QOPS_PER_MECH provided by the caller. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate OM_uint32 272*7c478bd9Sstevel@tonic-gate __gss_mech_qops( 273*7c478bd9Sstevel@tonic-gate char *mech, 274*7c478bd9Sstevel@tonic-gate qop_num *mechqops, 275*7c478bd9Sstevel@tonic-gate int *numqop 276*7c478bd9Sstevel@tonic-gate ) 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate int i; 279*7c478bd9Sstevel@tonic-gate OM_uint32 major; 280*7c478bd9Sstevel@tonic-gate int cnt = 0; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if (!mechqops || !numqop) 283*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 284*7c478bd9Sstevel@tonic-gate *numqop = 0; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate if (!mech) 287*7c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE) 290*7c478bd9Sstevel@tonic-gate return (major); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate for (i = 0; i < qop_num_pair_cnt; i++) { 293*7c478bd9Sstevel@tonic-gate if (strcasecmp(mech, qop_num_pairs[i].mech) == 0) { 294*7c478bd9Sstevel@tonic-gate if (cnt >= MAX_QOPS_PER_MECH) { 295*7c478bd9Sstevel@tonic-gate return (GSS_S_FAILURE); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate mechqops[cnt++] = qop_num_pairs[i]; 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate *numqop = cnt; 301*7c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE); 302*7c478bd9Sstevel@tonic-gate } 303