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 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <ctype.h> 34 #include "gsscred.h" 35 36 /* 37 * gsscred utility 38 * Manages mapping between a security principal name and unix uid. 39 * Implementation file for the file based gsscred utility. 40 */ 41 42 #define MAX_ENTRY_LEN 1024 43 static const char credFile[] = "/etc/gss/gsscred_db"; 44 static const char credFileTmp[] = "/etc/gss/gsscred_db.tmp"; 45 46 static int matchEntry(const char *entry, const gss_buffer_t name, 47 const char *uid, uid_t *uidOut); 48 49 /* 50 * file_addGssCredEntry 51 * 52 * Adds a new entry to the gsscred table. 53 * Does not check for duplicate entries. 54 */ 55 int file_addGssCredEntry(const gss_buffer_t hexName, const char *uid, 56 const char *comment, char **errDetails) 57 { 58 FILE *fp; 59 char tmpBuf[256]; 60 61 if ((fp = fopen(credFile, "a")) == NULL) { 62 if (errDetails) { 63 (void) snprintf(tmpBuf, sizeof (tmpBuf), 64 gettext("Unable to open gsscred file [%s]"), 65 credFile); 66 *errDetails = strdup(tmpBuf); 67 } 68 return (0); 69 } 70 71 (void) fprintf(fp, 72 "%s\t%s\t%s\n", (char *)hexName->value, uid, comment); 73 (void) fclose(fp); 74 return (1); 75 } /* ******* file_addGssCredEntry ****** */ 76 77 78 79 /* 80 * file_getGssCredEntry 81 * 82 * Searches the file for the file matching the name. Since the name 83 * contains a mechanism identifier, to search for all names for a given 84 * mechanism just supply the mechanism portion in the name buffer. 85 * To search by uid only, supply a non-null value of uid. 86 */ 87 int file_getGssCredEntry(const gss_buffer_t name, const char *uid, 88 char **errDetails) 89 { 90 FILE *fp; 91 char entry[MAX_ENTRY_LEN+1]; 92 93 if ((fp = fopen(credFile, "r")) == NULL) { 94 95 if (errDetails) { 96 (void) snprintf(entry, sizeof (entry), 97 gettext("Unable to open gsscred file [%s]"), 98 credFile); 99 *errDetails = strdup(entry); 100 } 101 102 return (0); 103 } 104 105 /* go through the file in sequential order */ 106 while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) { 107 /* is there any search criteria */ 108 if (name == NULL && uid == NULL) { 109 (void) fprintf(stdout, "%s", entry); 110 continue; 111 } 112 113 if (matchEntry(entry, name, uid, NULL)) 114 (void) fprintf(stdout, "%s", entry); 115 116 } /* while */ 117 118 (void) fclose(fp); 119 return (1); 120 } /* file_getGssCredEntry */ 121 122 /* 123 * file_getGssCredUid 124 * 125 * GSS entry point for retrieving user uid information. 126 * We need to go through the entire file to ensure that 127 * the last matching entry is retrieved - this is because 128 * new entries are added to the end, and in case of 129 * duplicates we want to get the latest entry. 130 */ 131 int 132 file_getGssCredUid(const gss_buffer_t expName, uid_t *uidOut) 133 { 134 FILE *fp; 135 char entry[MAX_ENTRY_LEN+1]; 136 int retVal = 0; 137 138 if ((fp = fopen(credFile, "r")) == NULL) 139 return (0); 140 141 /* go through the entire file in sequential order */ 142 while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) { 143 if (matchEntry(entry, expName, NULL, uidOut)) { 144 retVal = 1; 145 } 146 } /* while */ 147 148 (void) fclose(fp); 149 return (retVal); 150 } /* file_getGssCredUid */ 151 152 153 154 /* 155 * 156 * file_deleteGssCredEntry 157 * 158 * removes entries form file that match the delete criteria 159 */ 160 int file_deleteGssCredEntry(const gss_buffer_t name, const char *uid, 161 char **errDetails) 162 { 163 FILE *fp, *tempFp; 164 char entry[MAX_ENTRY_LEN+1]; 165 int foundOne = 0; 166 167 /* are we deleting everyone? */ 168 if (name == NULL && uid == NULL) { 169 170 if ((fp = fopen(credFile, "w")) == NULL) { 171 172 if (errDetails) { 173 (void) snprintf(entry, sizeof (entry), 174 gettext("Unable to open gsscred" 175 " file [%s]"), 176 credFile); 177 *errDetails = strdup(entry); 178 } 179 return (0); 180 } 181 182 (void) fclose(fp); 183 return (1); 184 } 185 186 /* selective delete - might still be everyone */ 187 if ((fp = fopen(credFile, "r")) == NULL) { 188 189 if (errDetails) { 190 (void) snprintf(entry, sizeof (entry), 191 gettext("Unable to open gsscred file [%s]"), 192 credFile); 193 *errDetails = strdup(entry); 194 } 195 return (0); 196 } 197 198 /* also need to open temp file */ 199 if ((tempFp = fopen(credFileTmp, "w")) == NULL) { 200 if (errDetails) { 201 (void) snprintf(entry, sizeof (entry), 202 gettext("Unable to open gsscred temporary" 203 " file [%s]"), 204 credFileTmp); 205 *errDetails = strdup(entry); 206 } 207 208 (void) fclose(fp); 209 return (0); 210 } 211 212 /* go through all the entries sequentially removing ones that match */ 213 while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) { 214 215 if (!matchEntry(entry, name, uid, NULL)) 216 (void) fputs(entry, tempFp); 217 else 218 foundOne = 1; 219 } 220 (void) fclose(tempFp); 221 (void) fclose(fp); 222 223 /* now make the tempfile the gsscred file */ 224 (void) rename(credFileTmp, credFile); 225 (void) unlink(credFileTmp); 226 227 if (!foundOne) { 228 *errDetails = strdup(gettext("No users found")); 229 return (0); 230 } 231 return (1); 232 } /* file_deleteGssCredEntry */ 233 234 235 236 /* 237 * 238 * match entry 239 * 240 * checks if the specified entry matches the supplied criteria 241 * returns 1 if yes, 0 if no 242 * uidOut value can be used to retrieve the uid from the entry 243 * when the uid string is passed in, the uidOut value is not set 244 */ 245 static int matchEntry(const char *entry, const gss_buffer_t name, 246 const char *uid, uid_t *uidOut) 247 { 248 char fullEntry[MAX_ENTRY_LEN+1], *item; 249 char dilims[] = "\t \n"; 250 251 252 if (entry == NULL || isspace(*entry)) 253 return (0); 254 255 /* save the entry since strtok will chop it up */ 256 (void) strcpy(fullEntry, entry); 257 258 if ((item = strtok(fullEntry, dilims)) == NULL) 259 return (0); 260 261 /* do wee need to search the name */ 262 if (name != NULL) { 263 /* we can match the prefix of the string */ 264 if (strlen(item) < name->length) 265 return (0); 266 267 /* check if the prefix of the name matches */ 268 if (memcmp(item, name->value, name->length) != 0) 269 return (0); 270 271 /* do we need to check the uid - if not then we found it */ 272 if (uid == NULL) { 273 /* do we ned to parse out the uid ? */ 274 if (uidOut) { 275 if ((item = strtok(NULL, dilims)) == NULL) 276 return (0); 277 *uidOut = atol(item); 278 } 279 return (1); 280 } 281 282 /* continue with checking the uid */ 283 } 284 285 if (uid == NULL) 286 return (1); 287 288 /* get the next token from the string - the uid */ 289 if ((item = strtok(NULL, dilims)) == NULL) 290 return (0); 291 292 if (strcmp(item, uid) == 0) 293 return (1); 294 295 return (0); 296 } /* ******* matchEntry ****** */ 297