10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*110Sdduvall * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <stdlib.h> 310Sstevel@tonic-gate #include <string.h> 320Sstevel@tonic-gate #include <unistd.h> 330Sstevel@tonic-gate #include <ctype.h> 340Sstevel@tonic-gate #include "gsscred.h" 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * gsscred utility 380Sstevel@tonic-gate * Manages mapping between a security principal name and unix uid. 390Sstevel@tonic-gate * Implementation file for the file based gsscred utility. 400Sstevel@tonic-gate */ 410Sstevel@tonic-gate 420Sstevel@tonic-gate #define MAX_ENTRY_LEN 1024 430Sstevel@tonic-gate static const char credFile[] = "/etc/gss/gsscred_db"; 440Sstevel@tonic-gate static const char credFileTmp[] = "/etc/gss/gsscred_db.tmp"; 450Sstevel@tonic-gate 460Sstevel@tonic-gate static int matchEntry(const char *entry, const gss_buffer_t name, 470Sstevel@tonic-gate const char *uid, uid_t *uidOut); 480Sstevel@tonic-gate 490Sstevel@tonic-gate /* 500Sstevel@tonic-gate * file_addGssCredEntry 510Sstevel@tonic-gate * 520Sstevel@tonic-gate * Adds a new entry to the gsscred table. 530Sstevel@tonic-gate * Does not check for duplicate entries. 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate int file_addGssCredEntry(const gss_buffer_t hexName, const char *uid, 560Sstevel@tonic-gate const char *comment, char **errDetails) 570Sstevel@tonic-gate { 580Sstevel@tonic-gate FILE *fp; 590Sstevel@tonic-gate char tmpBuf[256]; 600Sstevel@tonic-gate 610Sstevel@tonic-gate if ((fp = fopen(credFile, "a")) == NULL) { 620Sstevel@tonic-gate if (errDetails) { 630Sstevel@tonic-gate (void) snprintf(tmpBuf, sizeof (tmpBuf), 640Sstevel@tonic-gate gettext("Unable to open gsscred file [%s]"), 650Sstevel@tonic-gate credFile); 660Sstevel@tonic-gate *errDetails = strdup(tmpBuf); 670Sstevel@tonic-gate } 680Sstevel@tonic-gate return (0); 690Sstevel@tonic-gate } 700Sstevel@tonic-gate 710Sstevel@tonic-gate (void) fprintf(fp, 720Sstevel@tonic-gate "%s\t%s\t%s\n", (char *)hexName->value, uid, comment); 730Sstevel@tonic-gate (void) fclose(fp); 740Sstevel@tonic-gate return (1); 750Sstevel@tonic-gate } /* ******* file_addGssCredEntry ****** */ 760Sstevel@tonic-gate 770Sstevel@tonic-gate 780Sstevel@tonic-gate 790Sstevel@tonic-gate /* 800Sstevel@tonic-gate * file_getGssCredEntry 810Sstevel@tonic-gate * 820Sstevel@tonic-gate * Searches the file for the file matching the name. Since the name 830Sstevel@tonic-gate * contains a mechanism identifier, to search for all names for a given 840Sstevel@tonic-gate * mechanism just supply the mechanism portion in the name buffer. 850Sstevel@tonic-gate * To search by uid only, supply a non-null value of uid. 860Sstevel@tonic-gate */ 870Sstevel@tonic-gate int file_getGssCredEntry(const gss_buffer_t name, const char *uid, 880Sstevel@tonic-gate char **errDetails) 890Sstevel@tonic-gate { 900Sstevel@tonic-gate FILE *fp; 910Sstevel@tonic-gate char entry[MAX_ENTRY_LEN+1]; 920Sstevel@tonic-gate 930Sstevel@tonic-gate if ((fp = fopen(credFile, "r")) == NULL) { 940Sstevel@tonic-gate 950Sstevel@tonic-gate if (errDetails) { 960Sstevel@tonic-gate (void) snprintf(entry, sizeof (entry), 970Sstevel@tonic-gate gettext("Unable to open gsscred file [%s]"), 980Sstevel@tonic-gate credFile); 990Sstevel@tonic-gate *errDetails = strdup(entry); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate return (0); 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate /* go through the file in sequential order */ 1060Sstevel@tonic-gate while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) { 1070Sstevel@tonic-gate /* is there any search criteria */ 1080Sstevel@tonic-gate if (name == NULL && uid == NULL) { 1090Sstevel@tonic-gate (void) fprintf(stdout, "%s", entry); 1100Sstevel@tonic-gate continue; 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate if (matchEntry(entry, name, uid, NULL)) 1140Sstevel@tonic-gate (void) fprintf(stdout, "%s", entry); 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate } /* while */ 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate (void) fclose(fp); 1190Sstevel@tonic-gate return (1); 1200Sstevel@tonic-gate } /* file_getGssCredEntry */ 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* 1230Sstevel@tonic-gate * file_getGssCredUid 1240Sstevel@tonic-gate * 1250Sstevel@tonic-gate * GSS entry point for retrieving user uid information. 1260Sstevel@tonic-gate * We need to go through the entire file to ensure that 1270Sstevel@tonic-gate * the last matching entry is retrieved - this is because 1280Sstevel@tonic-gate * new entries are added to the end, and in case of 1290Sstevel@tonic-gate * duplicates we want to get the latest entry. 1300Sstevel@tonic-gate */ 1310Sstevel@tonic-gate int 1320Sstevel@tonic-gate file_getGssCredUid(const gss_buffer_t expName, uid_t *uidOut) 1330Sstevel@tonic-gate { 1340Sstevel@tonic-gate FILE *fp; 1350Sstevel@tonic-gate char entry[MAX_ENTRY_LEN+1]; 1360Sstevel@tonic-gate int retVal = 0; 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate if ((fp = fopen(credFile, "r")) == NULL) 1390Sstevel@tonic-gate return (0); 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* go through the entire file in sequential order */ 1420Sstevel@tonic-gate while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) { 1430Sstevel@tonic-gate if (matchEntry(entry, expName, NULL, uidOut)) { 1440Sstevel@tonic-gate retVal = 1; 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate } /* while */ 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate (void) fclose(fp); 1490Sstevel@tonic-gate return (retVal); 1500Sstevel@tonic-gate } /* file_getGssCredUid */ 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /* 1550Sstevel@tonic-gate * 1560Sstevel@tonic-gate * file_deleteGssCredEntry 1570Sstevel@tonic-gate * 1580Sstevel@tonic-gate * removes entries form file that match the delete criteria 1590Sstevel@tonic-gate */ 1600Sstevel@tonic-gate int file_deleteGssCredEntry(const gss_buffer_t name, const char *uid, 1610Sstevel@tonic-gate char **errDetails) 1620Sstevel@tonic-gate { 1630Sstevel@tonic-gate FILE *fp, *tempFp; 1640Sstevel@tonic-gate char entry[MAX_ENTRY_LEN+1]; 1650Sstevel@tonic-gate int foundOne = 0; 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /* are we deleting everyone? */ 1680Sstevel@tonic-gate if (name == NULL && uid == NULL) { 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate if ((fp = fopen(credFile, "w")) == NULL) { 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate if (errDetails) { 1730Sstevel@tonic-gate (void) snprintf(entry, sizeof (entry), 1740Sstevel@tonic-gate gettext("Unable to open gsscred" 1750Sstevel@tonic-gate " file [%s]"), 1760Sstevel@tonic-gate credFile); 1770Sstevel@tonic-gate *errDetails = strdup(entry); 1780Sstevel@tonic-gate } 1790Sstevel@tonic-gate return (0); 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate (void) fclose(fp); 1830Sstevel@tonic-gate return (1); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* selective delete - might still be everyone */ 1870Sstevel@tonic-gate if ((fp = fopen(credFile, "r")) == NULL) { 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate if (errDetails) { 1900Sstevel@tonic-gate (void) snprintf(entry, sizeof (entry), 1910Sstevel@tonic-gate gettext("Unable to open gsscred file [%s]"), 1920Sstevel@tonic-gate credFile); 1930Sstevel@tonic-gate *errDetails = strdup(entry); 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate return (0); 1960Sstevel@tonic-gate } 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* also need to open temp file */ 1990Sstevel@tonic-gate if ((tempFp = fopen(credFileTmp, "w")) == NULL) { 2000Sstevel@tonic-gate if (errDetails) { 2010Sstevel@tonic-gate (void) snprintf(entry, sizeof (entry), 2020Sstevel@tonic-gate gettext("Unable to open gsscred temporary" 2030Sstevel@tonic-gate " file [%s]"), 2040Sstevel@tonic-gate credFileTmp); 2050Sstevel@tonic-gate *errDetails = strdup(entry); 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate (void) fclose(fp); 2090Sstevel@tonic-gate return (0); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* go through all the entries sequentially removing ones that match */ 2130Sstevel@tonic-gate while (fgets(entry, MAX_ENTRY_LEN, fp) != NULL) { 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate if (!matchEntry(entry, name, uid, NULL)) 2160Sstevel@tonic-gate (void) fputs(entry, tempFp); 2170Sstevel@tonic-gate else 2180Sstevel@tonic-gate foundOne = 1; 2190Sstevel@tonic-gate } 2200Sstevel@tonic-gate (void) fclose(tempFp); 2210Sstevel@tonic-gate (void) fclose(fp); 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate /* now make the tempfile the gsscred file */ 2240Sstevel@tonic-gate (void) rename(credFileTmp, credFile); 2250Sstevel@tonic-gate (void) unlink(credFileTmp); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate if (!foundOne) { 2280Sstevel@tonic-gate *errDetails = strdup(gettext("No users found")); 2290Sstevel@tonic-gate return (0); 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate return (1); 2320Sstevel@tonic-gate } /* file_deleteGssCredEntry */ 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* 2370Sstevel@tonic-gate * 2380Sstevel@tonic-gate * match entry 2390Sstevel@tonic-gate * 2400Sstevel@tonic-gate * checks if the specified entry matches the supplied criteria 2410Sstevel@tonic-gate * returns 1 if yes, 0 if no 2420Sstevel@tonic-gate * uidOut value can be used to retrieve the uid from the entry 2430Sstevel@tonic-gate * when the uid string is passed in, the uidOut value is not set 2440Sstevel@tonic-gate */ 2450Sstevel@tonic-gate static int matchEntry(const char *entry, const gss_buffer_t name, 2460Sstevel@tonic-gate const char *uid, uid_t *uidOut) 2470Sstevel@tonic-gate { 248*110Sdduvall char fullEntry[MAX_ENTRY_LEN+1], *item; 2490Sstevel@tonic-gate char dilims[] = "\t \n"; 250*110Sdduvall 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (entry == NULL || isspace(*entry)) 2530Sstevel@tonic-gate return (0); 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* save the entry since strtok will chop it up */ 2560Sstevel@tonic-gate (void) strcpy(fullEntry, entry); 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate if ((item = strtok(fullEntry, dilims)) == NULL) 2590Sstevel@tonic-gate return (0); 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate /* do wee need to search the name */ 2620Sstevel@tonic-gate if (name != NULL) { 2630Sstevel@tonic-gate /* we can match the prefix of the string */ 2640Sstevel@tonic-gate if (strlen(item) < name->length) 2650Sstevel@tonic-gate return (0); 2660Sstevel@tonic-gate 267*110Sdduvall /* check if the prefix of the name matches */ 268*110Sdduvall if (memcmp(item, name->value, name->length) != 0) 269*110Sdduvall return (0); 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* do we need to check the uid - if not then we found it */ 2720Sstevel@tonic-gate if (uid == NULL) { 2730Sstevel@tonic-gate /* do we ned to parse out the uid ? */ 2740Sstevel@tonic-gate if (uidOut) { 2750Sstevel@tonic-gate if ((item = strtok(NULL, dilims)) == NULL) 2760Sstevel@tonic-gate return (0); 2770Sstevel@tonic-gate *uidOut = atol(item); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate return (1); 2800Sstevel@tonic-gate } 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate /* continue with checking the uid */ 2830Sstevel@tonic-gate } 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (uid == NULL) 2860Sstevel@tonic-gate return (1); 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate /* get the next token from the string - the uid */ 2890Sstevel@tonic-gate if ((item = strtok(NULL, dilims)) == NULL) 2900Sstevel@tonic-gate return (0); 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate if (strcmp(item, uid) == 0) 2930Sstevel@tonic-gate return (1); 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate return (0); 2960Sstevel@tonic-gate } /* ******* matchEntry ****** */ 297