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]
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>
35 #include <gssapi/gssapi.h>
36 #include <gssapi/gssapi_ext.h>
39 #define Q_DEFAULT "default"
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.
58 __gss_read_qop_file(void)
60 char buf
[BUFLEN
]; /* one line from the file */
62 char *qopname
, *num_str
;
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
;
76 last
= stbuf
.st_mtime
;
78 fp
= fopen(QOP_NUM_FILE
, "rF");
79 if (fp
== (FILE *)0) {
80 major
= GSS_S_FAILURE
;
85 * For each line in the file parse it appropriately.
86 * File format : qopname num(int)
87 * Note that we silently ignore corrupt entries.
91 line
= fgets(buf
, BUFLEN
, fp
);
95 /* Skip comments and blank lines */
96 if ((*line
== '#') || (*line
== '\n'))
99 /* Skip trailing comments */
100 next
= strchr(line
, '#');
105 while (isspace(*name
))
107 if (*name
== '\0') /* blank line */
110 qopname
= name
; /* will contain qop name */
111 while (!isspace(*qopname
))
113 if (*qopname
== '\0') {
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
)
123 while (isspace(*name
))
125 if (*name
== '\0') { /* end of line, no num */
126 free(qop_num_pairs
[qop_num_pair_cnt
].qop
);
129 num_str
= name
; /* will contain num (n) */
130 while (!isspace(*num_str
))
133 *num_str
++ = '\0'; /* null terminate num_str */
135 qop_num_pairs
[qop_num_pair_cnt
].num
= (OM_uint32
)atoi(name
);
137 while (isspace(*name
))
139 if (*name
== '\0') { /* end of line, no mechanism */
140 free(qop_num_pairs
[qop_num_pair_cnt
].qop
);
143 num_str
= name
; /* will contain mech */
144 while (!isspace(*num_str
))
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
);
154 if (qop_num_pair_cnt
++ >= MAX_QOP_NUM_PAIRS
)
159 (void) mutex_unlock(&qopfile_lock
);
171 OM_uint32 major
= GSS_S_FAILURE
;
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
)
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
);
207 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
210 if (num
== GSS_C_QOP_DEFAULT
) {
212 return (GSS_S_COMPLETE
);
216 return (GSS_S_CALL_INACCESSIBLE_READ
);
218 if ((major
= __gss_read_qop_file()) != GSS_S_COMPLETE
)
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.
242 OM_uint32 major
= GSS_S_COMPLETE
;
245 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
249 return (GSS_S_CALL_INACCESSIBLE_READ
);
251 if ((major
= __gss_read_qop_file()) != GSS_S_COMPLETE
)
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
;
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.
281 if (!mechqops
|| !numqop
)
282 return (GSS_S_CALL_INACCESSIBLE_WRITE
);
286 return (GSS_S_CALL_INACCESSIBLE_READ
);
288 if ((major
= __gss_read_qop_file()) != GSS_S_COMPLETE
)
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
];
300 return (GSS_S_COMPLETE
);