5960 zfs recv should prefetch indirect blocks
[illumos-gate.git] / usr / src / lib / libgss / g_utils.c
blob1fc34b11086b47f04b9ddce09b49872c46b31233
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <gssapi/gssapi.h>
36 #include <gssapi/gssapi_ext.h>
37 #include <synch.h>
39 #define Q_DEFAULT "default"
40 #define BUFLEN 256
42 static int qop_num_pair_cnt;
43 static const char QOP_NUM_FILE[] = "/etc/gss/qop";
44 static qop_num qop_num_pairs[MAX_QOP_NUM_PAIRS+1];
45 static mutex_t qopfile_lock = DEFAULTMUTEX;
47 static OM_uint32 __gss_read_qop_file(void);
50 * This routine fetches qop and num from "/etc/gss/qop".
51 * There is a memory leak associated with rereading this file,
52 * because we can't free the qop_num_pairs array when we reread
53 * the file (some callers may have been given these pointers).
54 * In general, this memory leak should be a small one, because
55 * we don't expect the qop file to be changed and reread often.
57 static OM_uint32
58 __gss_read_qop_file(void)
60 char buf[BUFLEN]; /* one line from the file */
61 char *name, *next;
62 char *qopname, *num_str;
63 char *line;
64 FILE *fp;
65 static int last = 0;
66 struct stat stbuf;
67 OM_uint32 major = GSS_S_COMPLETE;
69 (void) mutex_lock(&qopfile_lock);
70 if (stat(QOP_NUM_FILE, &stbuf) != 0 || stbuf.st_mtime < last) {
71 if (!qop_num_pairs[0].qop) {
72 major = GSS_S_FAILURE;
74 goto done;
76 last = stbuf.st_mtime;
78 fp = fopen(QOP_NUM_FILE, "rF");
79 if (fp == (FILE *)0) {
80 major = GSS_S_FAILURE;
81 goto done;
85 * For each line in the file parse it appropriately.
86 * File format : qopname num(int)
87 * Note that we silently ignore corrupt entries.
89 qop_num_pair_cnt = 0;
90 while (!feof(fp)) {
91 line = fgets(buf, BUFLEN, fp);
92 if (line == NULL)
93 break;
95 /* Skip comments and blank lines */
96 if ((*line == '#') || (*line == '\n'))
97 continue;
99 /* Skip trailing comments */
100 next = strchr(line, '#');
101 if (next)
102 *next = '\0';
104 name = &(buf[0]);
105 while (isspace(*name))
106 name++;
107 if (*name == '\0') /* blank line */
108 continue;
110 qopname = name; /* will contain qop name */
111 while (!isspace(*qopname))
112 qopname++;
113 if (*qopname == '\0') {
114 continue;
116 next = qopname+1;
117 *qopname = '\0'; /* null terminate qopname */
118 qop_num_pairs[qop_num_pair_cnt].qop = strdup(name);
119 if (qop_num_pairs[qop_num_pair_cnt].qop == NULL)
120 continue;
122 name = next;
123 while (isspace(*name))
124 name++;
125 if (*name == '\0') { /* end of line, no num */
126 free(qop_num_pairs[qop_num_pair_cnt].qop);
127 continue;
129 num_str = name; /* will contain num (n) */
130 while (!isspace(*num_str))
131 num_str++;
132 next = num_str+1;
133 *num_str++ = '\0'; /* null terminate num_str */
135 qop_num_pairs[qop_num_pair_cnt].num = (OM_uint32)atoi(name);
136 name = next;
137 while (isspace(*name))
138 name++;
139 if (*name == '\0') { /* end of line, no mechanism */
140 free(qop_num_pairs[qop_num_pair_cnt].qop);
141 continue;
143 num_str = name; /* will contain mech */
144 while (!isspace(*num_str))
145 num_str++;
146 *num_str = '\0';
148 qop_num_pairs[qop_num_pair_cnt].mech = strdup(name);
149 if (qop_num_pairs[qop_num_pair_cnt].mech == NULL) {
150 free(qop_num_pairs[qop_num_pair_cnt].qop);
151 continue;
154 if (qop_num_pair_cnt++ >= MAX_QOP_NUM_PAIRS)
155 break;
157 (void) fclose(fp);
158 done:
159 (void) mutex_unlock(&qopfile_lock);
160 return (major);
163 OM_uint32
164 __gss_qop_to_num(
165 char *qop,
166 char *mech,
167 OM_uint32 *num
170 int i;
171 OM_uint32 major = GSS_S_FAILURE;
173 if (!num)
174 return (GSS_S_CALL_INACCESSIBLE_WRITE);
176 if (qop == NULL || strlen(qop) == 0 ||
177 strcasecmp(qop, Q_DEFAULT) == 0) {
178 *num = GSS_C_QOP_DEFAULT;
179 return (GSS_S_COMPLETE);
182 if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
183 return (major);
185 for (i = 0; i < qop_num_pair_cnt; i++) {
186 if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) &&
187 (strcasecmp(qop, qop_num_pairs[i].qop) == 0)) {
188 *num = qop_num_pairs[i].num;
189 return (GSS_S_COMPLETE);
193 return (GSS_S_FAILURE);
196 OM_uint32
197 __gss_num_to_qop(
198 char *mech,
199 OM_uint32 num,
200 char **qop
203 int i;
204 OM_uint32 major;
206 if (!qop)
207 return (GSS_S_CALL_INACCESSIBLE_WRITE);
208 *qop = NULL;
210 if (num == GSS_C_QOP_DEFAULT) {
211 *qop = Q_DEFAULT;
212 return (GSS_S_COMPLETE);
215 if (mech == NULL)
216 return (GSS_S_CALL_INACCESSIBLE_READ);
218 if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
219 return (major);
221 for (i = 0; i < qop_num_pair_cnt; i++) {
222 if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) &&
223 (num == qop_num_pairs[i].num)) {
224 *qop = qop_num_pairs[i].qop;
225 return (GSS_S_COMPLETE);
228 return (GSS_S_FAILURE);
232 * For a given mechanism pass back qop information about it in a buffer
233 * of size MAX_QOPS_PER_MECH+1.
235 OM_uint32
236 __gss_get_mech_info(
237 char *mech,
238 char **qops
241 int i, cnt = 0;
242 OM_uint32 major = GSS_S_COMPLETE;
244 if (!qops)
245 return (GSS_S_CALL_INACCESSIBLE_WRITE);
246 *qops = NULL;
248 if (!mech)
249 return (GSS_S_CALL_INACCESSIBLE_READ);
251 if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
252 return (major);
254 for (i = 0; i < qop_num_pair_cnt; i++) {
255 if (strcmp(mech, qop_num_pairs[i].mech) == 0) {
256 if (cnt >= MAX_QOPS_PER_MECH) {
257 return (GSS_S_FAILURE);
259 qops[cnt++] = qop_num_pairs[i].qop;
262 qops[cnt] = NULL;
263 return (GSS_S_COMPLETE);
267 * Copy the qop values and names for the mechanism back in a qop_num
268 * buffer of size MAX_QOPS_PER_MECH provided by the caller.
270 OM_uint32
271 __gss_mech_qops(
272 char *mech,
273 qop_num *mechqops,
274 int *numqop
277 int i;
278 OM_uint32 major;
279 int cnt = 0;
281 if (!mechqops || !numqop)
282 return (GSS_S_CALL_INACCESSIBLE_WRITE);
283 *numqop = 0;
285 if (!mech)
286 return (GSS_S_CALL_INACCESSIBLE_READ);
288 if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
289 return (major);
291 for (i = 0; i < qop_num_pair_cnt; i++) {
292 if (strcasecmp(mech, qop_num_pairs[i].mech) == 0) {
293 if (cnt >= MAX_QOPS_PER_MECH) {
294 return (GSS_S_FAILURE);
296 mechqops[cnt++] = qop_num_pairs[i];
299 *numqop = cnt;
300 return (GSS_S_COMPLETE);