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