xref: /onnv-gate/usr/src/cmd/gss/gsscred/gsscred_file.c (revision 110:ea567b4336cc)
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