Coverage Report

Created: 2026-05-24 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/krb5/src/lib/gssapi/mechglue/g_mechattr.c
Line
Count
Source
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/gssapi/mechglue/g_mechattr.c */
3
/*
4
 * Copyright (C) 2010 by the Massachusetts Institute of Technology.
5
 * All rights reserved.
6
 *
7
 * Export of this software from the United States of America may
8
 *   require a specific license from the United States Government.
9
 *   It is the responsibility of any person or organization contemplating
10
 *   export to obtain such a license before exporting.
11
 *
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
 * distribute this software and its documentation for any purpose and
14
 * without fee is hereby granted, provided that the above copyright
15
 * notice appear in all copies and that both that copyright notice and
16
 * this permission notice appear in supporting documentation, and that
17
 * the name of M.I.T. not be used in advertising or publicity pertaining
18
 * to distribution of the software without specific, written prior
19
 * permission.  Furthermore if you modify this software you must label
20
 * your software as modified software and not distribute it in such a
21
 * fashion that it might be confused with the original M.I.T. software.
22
 * M.I.T. makes no representations about the suitability of
23
 * this software for any purpose.  It is provided "as is" without express
24
 * or implied warranty.
25
 */
26
27
#include "mglueP.h"
28
29
static int
30
testMechAttr(gss_const_OID attr,
31
             gss_const_OID_set against)
32
408
{
33
408
    int present = 0;
34
408
    OM_uint32 minor;
35
36
408
    if (GSS_ERROR(generic_gss_test_oid_set_member(&minor, attr,
37
408
                                                  (gss_OID_set)against,
38
408
                                                  &present)))
39
0
        return 0;
40
41
408
    return present;
42
408
}
43
44
/*
45
 * Return TRUE iff all the elements of desired and none of the elements
46
 * of except exist in available.
47
 */
48
static int
49
testMechAttrsOffered(gss_const_OID_set desired,
50
                     gss_const_OID_set except,
51
                     gss_const_OID_set available)
52
153
{
53
153
    size_t i;
54
55
153
    if (desired != GSS_C_NO_OID_SET) {
56
0
        for (i = 0; i < desired->count; i++) {
57
0
            if (!testMechAttr(&desired->elements[i], available))
58
0
                return 0;
59
0
        }
60
0
    }
61
62
153
    if (except != GSS_C_NO_OID_SET) {
63
459
        for (i = 0; i < except->count; i++) {
64
408
            if (testMechAttr(&except->elements[i], available))
65
102
                return 0;
66
408
        }
67
153
    }
68
69
51
    return 1;
70
153
}
71
72
/*
73
 * Return TRUE iff all the elements of critical exist in known.
74
 */
75
static int
76
testMechAttrsKnown(gss_const_OID_set critical,
77
                   gss_const_OID_set known)
78
51
{
79
51
    size_t i;
80
81
51
    if (critical != GSS_C_NO_OID_SET) {
82
0
        for (i = 0; i < critical->count; i++) {
83
0
            if (!testMechAttr(&critical->elements[i], known))
84
0
                return 0;
85
0
        }
86
0
    }
87
88
51
    return 1;
89
51
}
90
91
OM_uint32 KRB5_CALLCONV
92
gss_indicate_mechs_by_attrs(
93
    OM_uint32         *minor,
94
    gss_const_OID_set  desired_mech_attrs,
95
    gss_const_OID_set  except_mech_attrs,
96
    gss_const_OID_set  critical_mech_attrs,
97
    gss_OID_set       *mechs)
98
51
{
99
51
    OM_uint32       status, tmpMinor;
100
51
    gss_OID_set     allMechs = GSS_C_NO_OID_SET;
101
51
    size_t          i;
102
103
51
    if (minor != NULL)
104
51
        *minor = 0;
105
106
51
    if (mechs != NULL)
107
51
        *mechs = GSS_C_NO_OID_SET;
108
109
51
    if (minor == NULL || mechs == NULL)
110
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
111
112
51
    status = gss_indicate_mechs(minor, &allMechs);
113
51
    if (GSS_ERROR(status))
114
0
        goto cleanup;
115
116
51
    status = generic_gss_create_empty_oid_set(minor, mechs);
117
51
    if (GSS_ERROR(status))
118
0
        goto cleanup;
119
120
204
    for (i = 0; i < allMechs->count; i++) {
121
153
        gss_OID_set supportedAttrs = GSS_C_NO_OID_SET;
122
153
        gss_OID_set knownAttrs = GSS_C_NO_OID_SET;
123
124
153
        status = gss_inquire_attrs_for_mech(minor, &allMechs->elements[i],
125
153
                                            &supportedAttrs, &knownAttrs);
126
153
        if (GSS_ERROR(status))
127
0
            continue;
128
129
153
        if (testMechAttrsOffered(desired_mech_attrs,
130
153
                                 except_mech_attrs, supportedAttrs) &&
131
51
            testMechAttrsKnown(critical_mech_attrs, knownAttrs)) {
132
51
            status = gss_add_oid_set_member(minor, &allMechs->elements[i],
133
51
                                            mechs);
134
51
            if (GSS_ERROR(status)) {
135
0
                gss_release_oid_set(&tmpMinor, &supportedAttrs);
136
0
                gss_release_oid_set(&tmpMinor, &knownAttrs);
137
0
                goto cleanup;
138
0
            }
139
51
        }
140
141
153
        gss_release_oid_set(&tmpMinor, &supportedAttrs);
142
153
        gss_release_oid_set(&tmpMinor, &knownAttrs);
143
153
    }
144
145
51
    *minor = 0;
146
51
    status = GSS_S_COMPLETE;
147
148
51
cleanup:
149
51
    gss_release_oid_set(&tmpMinor, &allMechs);
150
151
51
    return status;
152
51
}
153
154
OM_uint32 KRB5_CALLCONV
155
gss_inquire_attrs_for_mech(
156
    OM_uint32         *minor,
157
    gss_const_OID      mech_oid,
158
    gss_OID_set       *mech_attrs,
159
    gss_OID_set       *known_mech_attrs)
160
2.19k
{
161
2.19k
    OM_uint32       status, tmpMinor;
162
2.19k
    gss_OID         selected_mech, public_mech;
163
2.19k
    gss_mechanism   mech;
164
165
2.19k
    if (minor != NULL)
166
2.19k
        *minor = 0;
167
168
2.19k
    if (mech_attrs != NULL)
169
2.19k
        *mech_attrs = GSS_C_NO_OID_SET;
170
171
2.19k
    if (known_mech_attrs != NULL)
172
153
        *known_mech_attrs = GSS_C_NO_OID_SET;
173
174
2.19k
    if (minor == NULL)
175
0
        return GSS_S_CALL_INACCESSIBLE_WRITE;
176
177
2.19k
    status = gssint_select_mech_type(minor, mech_oid, &selected_mech);
178
2.19k
    if (status != GSS_S_COMPLETE)
179
0
        return status;
180
181
2.19k
    mech = gssint_get_mechanism(selected_mech);
182
2.19k
    if (mech == NULL)
183
0
        return GSS_S_BAD_MECH;
184
185
2.19k
    if (mech->gss_inquire_attrs_for_mech != NULL) {
186
2.19k
        public_mech = gssint_get_public_oid(selected_mech);
187
2.19k
        status = mech->gss_inquire_attrs_for_mech(minor, public_mech,
188
2.19k
                                                  mech_attrs,
189
2.19k
                                                  known_mech_attrs);
190
2.19k
        if (GSS_ERROR(status)) {
191
0
            map_error(minor, mech);
192
0
            return status;
193
0
        }
194
2.19k
    }
195
196
    /* Make sure *mech_attrs is a proper OID set, as GSS_C_NO_OID_SET is not
197
     * accepted by gss_test_oid_set_member(). */
198
2.19k
    if (mech_attrs != NULL && *mech_attrs == GSS_C_NO_OID_SET) {
199
0
        status = generic_gss_create_empty_oid_set(minor, mech_attrs);
200
0
        if (status != GSS_S_COMPLETE) {
201
0
            if (known_mech_attrs != NULL)
202
0
                gss_release_oid_set(&tmpMinor, known_mech_attrs);
203
0
            return status;
204
0
        }
205
0
    }
206
207
2.19k
    if (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) {
208
153
        if (mech->gss_inquire_attrs_for_mech != NULL) {
209
            /* A mech can leave *known_mech_attrs alone as shorthand for
210
             * understanding the RFC 5587 attribute set. */
211
153
            status = generic_gss_copy_oid_set(minor,
212
153
                                              gss_ma_known_attrs,
213
153
                                              known_mech_attrs);
214
153
        } else {
215
            /* The mech does not implement RFC 5587.  Indicate that it doesn't
216
             * know about any attributes. */
217
0
            status = generic_gss_create_empty_oid_set(minor, known_mech_attrs);
218
0
        }
219
153
        if (GSS_ERROR(status)) {
220
0
            gss_release_oid_set(&tmpMinor, mech_attrs);
221
0
            if (mech_attrs != NULL)
222
0
                *mech_attrs = GSS_C_NO_OID_SET;
223
0
        }
224
153
    }
225
226
2.19k
    return GSS_S_COMPLETE;
227
2.19k
}
228
229
OM_uint32 KRB5_CALLCONV
230
gss_display_mech_attr(
231
    OM_uint32         *minor,
232
    gss_const_OID      mech_attr,
233
    gss_buffer_t       name,
234
    gss_buffer_t       short_desc,
235
    gss_buffer_t       long_desc)
236
0
{
237
0
    return generic_gss_display_mech_attr(minor, mech_attr,
238
0
                                         name, short_desc, long_desc);
239
0
}