1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * 31 * gsscred utility 32 * Manages mapping between a security principal name and unix uid 33 */ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <errno.h> 39 #include <ctype.h> 40 #include "gsscred.h" 41 42 /* From g_glue.c */ 43 44 extern int 45 get_der_length(unsigned char **, unsigned int, unsigned int *); 46 47 extern unsigned int 48 der_length_size(unsigned int); 49 50 extern int 51 put_der_length(unsigned int, unsigned char **, unsigned int); 52 53 54 55 /* 56 * GSS export name constants 57 */ 58 static const char *expNameTokId = "\x04\x01"; 59 static const int expNameTokIdLen = 2; 60 static const int mechOidLenLen = 2; 61 static const int mechOidTagLen = 1; 62 63 64 /* 65 * Internal utility routines. 66 */ 67 68 /* 69 * gsscred_read_config_file 70 * 71 * function to read the optional gsscred configuration file 72 * which specifies which backend to use to store the gsscred 73 * table. 74 * 75 * we now only support flat files (btw, this file for backend is Obsoleted 76 * by PSARC) 77 */ 78 int 79 gsscred_read_config_file(void) 80 { 81 return (GSSCRED_FLAT_FILE); 82 } /* gsscred_read_config_file */ 83 84 85 /* 86 * gsscred_MakeName 87 * 88 * construct a principal name in the GSS_C_NT_EXPORT_NAME format. 89 */ 90 int gsscred_MakeName(const gss_OID mechOid, const char *name, 91 const char *nameOidStr, gss_buffer_t nameOut) 92 { 93 gss_OID nameOid; 94 gss_name_t intName; 95 OM_uint32 minor, major; 96 gss_buffer_desc aName = GSS_C_EMPTY_BUFFER, oidStr; 97 98 nameOut->length = 0; 99 nameOut->value = NULL; 100 101 /* we need to import the name, then canonicalize it, then export it */ 102 if (nameOidStr == NULL) 103 nameOid = (gss_OID)GSS_C_NT_USER_NAME; 104 else { 105 oidStr.length = strlen(nameOidStr); 106 oidStr.value = (void *)nameOidStr; 107 if (gss_str_to_oid(&minor, &oidStr, &nameOid) != 108 GSS_S_COMPLETE) { 109 (void) fprintf(stderr, 110 gettext("\nInvalid name oid supplied [%s].\n"), 111 nameOidStr); 112 return (0); 113 } 114 } 115 116 /* first import the name */ 117 aName.length = strlen(name); 118 aName.value = (void*)name; 119 major = gss_import_name(&minor, &aName, nameOid, &intName); 120 if (nameOidStr != NULL) { 121 free(nameOid->elements); 122 free(nameOid); 123 } 124 125 if (major != GSS_S_COMPLETE) { 126 (void) fprintf(stderr, 127 gettext("\nInternal error importing name [%s].\n"), 128 name); 129 return (0); 130 } 131 132 /* now canonicalize the name */ 133 if (gss_canonicalize_name(&minor, intName, mechOid, NULL) 134 != GSS_S_COMPLETE) { 135 (void) fprintf(stderr, 136 gettext("\nInternal error canonicalizing name" 137 " [%s].\n"), 138 name); 139 (void) gss_release_name(&minor, &intName); 140 return (0); 141 } 142 143 /* now convert to export format */ 144 if (gss_export_name(&minor, intName, nameOut) != GSS_S_COMPLETE) { 145 (void) fprintf(stderr, 146 gettext("\nInternal error exporting name [%s].\n"), 147 name); 148 (void) gss_release_name(&minor, &intName); 149 return (0); 150 } 151 152 (void) gss_release_name(&minor, &intName); 153 return (1); 154 } /* ******* makeName ****** */ 155 156 157 /* 158 * Constructs a part of the GSS_NT_EXPORT_NAME 159 * Only the mechanism independent name part is created. 160 */ 161 int 162 gsscred_MakeNameHeader(const gss_OID mechOid, gss_buffer_t outNameHdr) 163 { 164 unsigned char *buf = NULL; 165 int mechOidDERLength, mechOidLength; 166 167 /* determine the length of buffer needed */ 168 mechOidDERLength = der_length_size(mechOid->length); 169 outNameHdr->length = mechOidLenLen + mechOidTagLen + 170 mechOidDERLength + expNameTokIdLen + mechOid->length; 171 if ((outNameHdr->value = (void*)malloc(outNameHdr->length)) == NULL) { 172 outNameHdr->length = 0; 173 return (0); 174 } 175 176 /* start by putting the token id */ 177 buf = (unsigned char *) outNameHdr->value; 178 (void) memset(outNameHdr->value, '\0', outNameHdr->length); 179 (void) memcpy(buf, expNameTokId, expNameTokIdLen); 180 buf += expNameTokIdLen; 181 182 /* 183 * next 2 bytes contain the mech oid length (includes 184 * DER encoding) 185 */ 186 mechOidLength = mechOidTagLen + mechOidDERLength + 187 mechOid->length; 188 189 *buf++ = (mechOidLength & 0xFF00) >> 8; 190 *buf++ = (mechOidLength & 0x00FF); 191 *buf++ = 0x06; 192 if (put_der_length(mechOid->length, &buf, 193 mechOidDERLength) != 0) { 194 /* free the buffer */ 195 free(outNameHdr->value); 196 return (0); 197 } 198 199 /* now add the mechanism oid */ 200 (void) memcpy(buf, mechOid->elements, mechOid->length); 201 202 /* we stop here because the rest is mechanism specific */ 203 return (1); 204 } /* gsscred_MakeNameHeader */ 205 206 207 /* 208 * Converts the supplied string to HEX. 209 * The passed in buffer must be twice as long as the input buffer. 210 * Long form is used (i.e. '\0' will become '00'). This is needed 211 * to enable proper re-parsing of names. 212 */ 213 int 214 gsscred_AsHex(gss_buffer_t dataIn, gss_buffer_t dataOut) 215 { 216 int i; 217 char *out, *in; 218 unsigned int tmp; 219 220 if (dataOut->length < ((dataIn->length *2) + 1)) 221 return (0); 222 223 out = (char *)dataOut->value; 224 in = (char *)dataIn->value; 225 dataOut->length = 0; 226 227 for (i = 0; i < dataIn->length; i++) { 228 tmp = (unsigned int)(*in++)&0xff; 229 (void) sprintf(out, "%02X", tmp); 230 out++; 231 out++; 232 } 233 dataOut->length = out - (char *)dataOut->value; 234 *out = '\0'; 235 236 return (1); 237 } /* ******* gsscred_AsHex ******* */ 238 239 240 /* 241 * GSS entry point for retrieving user uid mappings. 242 * The name buffer contains a principal name in exported format. 243 */ 244 int 245 gss_getGssCredEntry(const gss_buffer_t expName, uid_t *uid) 246 { 247 int tableSource; 248 unsigned char *buf; 249 gss_buffer_desc mechOidDesc = GSS_C_EMPTY_BUFFER, 250 mechHexOidDesc = GSS_C_EMPTY_BUFFER, 251 expNameHexDesc = GSS_C_EMPTY_BUFFER; 252 char oidHexBuf[256], expNameHexBuf[1024]; 253 unsigned int dummy; 254 int len; 255 256 tableSource = gsscred_read_config_file(); 257 258 /* 259 * for xfn (ldap?), we must first construct, a hex mechansim oid string 260 */ 261 if (expName->length < (expNameTokIdLen + mechOidLenLen + 262 mechOidTagLen)) 263 return (0); 264 265 buf = (unsigned char *)expName->value; 266 buf += expNameTokIdLen; 267 268 /* skip oid length - get to der */ 269 buf++; 270 buf++; 271 272 /* skip oid tag */ 273 buf++; 274 275 /* get oid length */ 276 len = get_der_length(&buf, 277 (expName->length - expNameTokIdLen 278 - mechOidLenLen - mechOidTagLen), &dummy); 279 if (len == -1) 280 return (0); 281 else 282 mechOidDesc.length = len; 283 284 if (expName->length < 285 (expNameTokIdLen + mechOidLenLen + mechOidDesc.length 286 + dummy+ mechOidTagLen)) 287 return (0); 288 289 mechOidDesc.value = (void *)buf; 290 291 /* convert the oid buffer to hex */ 292 mechHexOidDesc.value = (void*) oidHexBuf; 293 mechHexOidDesc.length = sizeof (oidHexBuf); 294 if (!gsscred_AsHex(&mechOidDesc, &mechHexOidDesc)) 295 return (0); 296 297 /* also need to convert the name buffer into hex */ 298 expNameHexDesc.value = expNameHexBuf; 299 expNameHexDesc.length = sizeof (expNameHexBuf); 300 if (!gsscred_AsHex(expName, &expNameHexDesc)) 301 return (0); 302 303 if (tableSource == GSSCRED_FLAT_FILE) 304 return (file_getGssCredUid(&expNameHexDesc, uid)); 305 306 return (0); /* XXX for new backends (ldap, dss), 0->1 probably */ 307 } /* gss_getGssCredEntry */ 308