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