xref: /freebsd/crypto/krb5/src/tests/gssapi/t_inq_ctx.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright 2015 Red Hat, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "common.h"
32 
33 
34 /*
35  * Test program for inquiring about a security context, intended to be run from
36  * a Python test script.  Partially establishes a context to test inquiring
37  * about an incomplete context, and then establishes full contexts and inquires
38  * them.  Exits with status 0 if all operations are successful, or 1 if not.
39  *
40  * Usage: ./t_inq_ctx target_name
41  */
42 
43 static void
check_inq_context(gss_ctx_id_t context,int incomplete,gss_OID expected_mech,OM_uint32 expected_flags,int expected_locally_init)44 check_inq_context(gss_ctx_id_t context, int incomplete, gss_OID expected_mech,
45                   OM_uint32 expected_flags, int expected_locally_init)
46 {
47     OM_uint32 major, minor;
48     gss_name_t out_init_name, out_accept_name;
49     OM_uint32 out_lifetime;
50     gss_OID out_mech_type;
51     OM_uint32 out_flags;
52     int out_locally_init;
53     int out_open;
54 
55     major = gss_inquire_context(&minor, context, &out_init_name,
56                                 &out_accept_name, &out_lifetime,
57                                 &out_mech_type, &out_flags, &out_locally_init,
58                                 &out_open);
59     check_gsserr("gss_inquire_context", major, minor);
60 
61     assert(gss_oid_equal(out_mech_type, expected_mech));
62     assert(out_flags == expected_flags);
63     assert(out_locally_init == expected_locally_init);
64     if (incomplete) {
65         assert(!out_open);
66         assert(out_lifetime == 0);
67         assert(out_init_name == GSS_C_NO_NAME);
68         assert(out_accept_name == GSS_C_NO_NAME);
69     } else {
70         assert(out_open);
71         assert(out_lifetime > 0);
72         assert(out_init_name != GSS_C_NO_NAME);
73         assert(out_accept_name != GSS_C_NO_NAME);
74     }
75 
76     (void)gss_release_name(&minor, &out_accept_name);
77     (void)gss_release_name(&minor, &out_init_name);
78 }
79 
80 /* Call gss_init_sec_context() once to create an initiator context (which will
81  * be partial if flags includes GSS_C_MUTUAL_FLAG and the mech is krb5). */
82 static void
start_init_context(gss_OID mech,gss_cred_id_t cred,gss_name_t tname,OM_uint32 flags,gss_ctx_id_t * ctx)83 start_init_context(gss_OID mech, gss_cred_id_t cred, gss_name_t tname,
84                    OM_uint32 flags, gss_ctx_id_t *ctx)
85 {
86     OM_uint32 major, minor;
87     gss_buffer_desc itok = GSS_C_EMPTY_BUFFER;
88 
89     *ctx = GSS_C_NO_CONTEXT;
90     major = gss_init_sec_context(&minor, cred, ctx, tname, mech, flags,
91                                  GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS,
92                                  NULL, NULL, &itok, NULL, NULL);
93     check_gsserr("gss_init_sec_context", major, minor);
94     (void)gss_release_buffer(&minor, &itok);
95 }
96 
97 /* Call gss_init_sec_context() and gss_accept_sec_context() once to create an
98  * acceptor context. */
99 static void
start_accept_context(gss_OID mech,gss_cred_id_t icred,gss_cred_id_t acred,gss_name_t tname,OM_uint32 flags,gss_ctx_id_t * ctx)100 start_accept_context(gss_OID mech, gss_cred_id_t icred, gss_cred_id_t acred,
101                      gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ctx)
102 {
103     OM_uint32 major, minor;
104     gss_ctx_id_t ictx = GSS_C_NO_CONTEXT;
105     gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER;
106 
107     major = gss_init_sec_context(&minor, icred, &ictx, tname, mech, flags,
108                                  GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS,
109                                  NULL, NULL, &itok, NULL, NULL);
110     check_gsserr("gss_init_sec_context", major, minor);
111 
112     *ctx = GSS_C_NO_CONTEXT;
113     major = gss_accept_sec_context(&minor, ctx, acred, &itok,
114                                    GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL,
115                                    &atok, NULL, NULL, NULL);
116     check_gsserr("gss_accept_sec_context", major, minor);
117 
118     (void)gss_release_buffer(&minor, &itok);
119     (void)gss_release_buffer(&minor, &atok);
120     (void)gss_delete_sec_context(&minor, &ictx, NULL);
121 }
122 
123 static void
partial_iakerb_acceptor(const char * username,const char * password,gss_name_t tname,OM_uint32 flags,gss_ctx_id_t * ctx)124 partial_iakerb_acceptor(const char *username, const char *password,
125                         gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ctx)
126 {
127     OM_uint32 major, minor;
128     gss_name_t name;
129     gss_buffer_desc ubuf, pwbuf;
130     gss_OID_set_desc mechlist;
131     gss_cred_id_t icred, acred;
132 
133     mechlist.count = 1;
134     mechlist.elements = &mech_iakerb;
135 
136     /* Import the username. */
137     ubuf.value = (void *)username;
138     ubuf.length = strlen(username);
139     major = gss_import_name(&minor, &ubuf, GSS_C_NT_USER_NAME, &name);
140     check_gsserr("gss_import_name", major, minor);
141 
142     /* Create an IAKERB initiator cred with the username and password. */
143     pwbuf.value = (void *)password;
144     pwbuf.length = strlen(password);
145     major = gss_acquire_cred_with_password(&minor, name, &pwbuf, 0,
146                                            &mechlist, GSS_C_INITIATE, &icred,
147                                            NULL, NULL);
148     check_gsserr("gss_acquire_cred_with_password", major, minor);
149 
150     /* Create an acceptor cred with support for IAKERB. */
151     major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
152                              &mechlist, GSS_C_ACCEPT, &acred, NULL, NULL);
153     check_gsserr("gss_acquire_cred", major, minor);
154 
155     /* Begin context establishment to get a partial acceptor context. */
156     start_accept_context(&mech_iakerb, icred, acred, tname, flags, ctx);
157 
158     (void)gss_release_name(&minor, &name);
159     (void)gss_release_cred(&minor, &icred);
160     (void)gss_release_cred(&minor, &acred);
161 }
162 
163 /* Create a partially established SPNEGO acceptor. */
164 static void
partial_spnego_acceptor(gss_name_t tname,gss_ctx_id_t * ctx)165 partial_spnego_acceptor(gss_name_t tname, gss_ctx_id_t *ctx)
166 {
167     OM_uint32 major, minor;
168     gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok;
169 
170     /*
171      * We could construct a fixed SPNEGO initiator token which forces a
172      * renegotiation, but a simpler approach is to pass an empty token to
173      * gss_accept_sec_context(), taking advantage of our compatibility support
174      * for SPNEGO NegHints.
175      */
176     *ctx = GSS_C_NO_CONTEXT;
177     major = gss_accept_sec_context(&minor, ctx, GSS_C_NO_CREDENTIAL, &itok,
178                                    GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL,
179                                    &atok, NULL, NULL, NULL);
180     check_gsserr("gss_accept_sec_context(neghints)", major, minor);
181 
182     (void)gss_release_buffer(&minor, &atok);
183 }
184 
185 int
main(int argc,char * argv[])186 main(int argc, char *argv[])
187 {
188     OM_uint32 minor, flags, dce_flags;
189     gss_name_t tname;
190     gss_ctx_id_t ictx, actx;
191     const char *username, *password;
192 
193     if (argc != 4) {
194         fprintf(stderr, "Usage: %s username password targetname\n", argv[0]);
195         return 1;
196     }
197     username = argv[1];
198     password = argv[2];
199     tname = import_name(argv[3]);
200 
201     flags = GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_CONF_FLAG |
202         GSS_C_INTEG_FLAG;
203     start_init_context(&mech_krb5, GSS_C_NO_CREDENTIAL, tname, flags, &ictx);
204     check_inq_context(ictx, 1, &mech_krb5, flags | GSS_C_TRANS_FLAG, 1);
205     (void)gss_delete_sec_context(&minor, &ictx, NULL);
206 
207     start_init_context(&mech_iakerb, GSS_C_NO_CREDENTIAL, tname, flags, &ictx);
208     check_inq_context(ictx, 1, &mech_iakerb, flags, 1);
209     (void)gss_delete_sec_context(&minor, &ictx, NULL);
210 
211     start_init_context(&mech_spnego, GSS_C_NO_CREDENTIAL, tname, flags, &ictx);
212     check_inq_context(ictx, 1, &mech_spnego, flags, 1);
213     (void)gss_delete_sec_context(&minor, &ictx, NULL);
214 
215     dce_flags = flags | GSS_C_DCE_STYLE;
216     start_accept_context(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
217                          tname, dce_flags, &actx);
218     check_inq_context(actx, 1, &mech_krb5, dce_flags | GSS_C_TRANS_FLAG, 0);
219     (void)gss_delete_sec_context(&minor, &actx, NULL);
220 
221     partial_iakerb_acceptor(username, password, tname, flags, &actx);
222     check_inq_context(actx, 1, &mech_iakerb, 0, 0);
223     (void)gss_delete_sec_context(&minor, &actx, NULL);
224 
225     partial_spnego_acceptor(tname, &actx);
226     check_inq_context(actx, 1, &mech_spnego, 0, 0);
227     (void)gss_delete_sec_context(&minor, &actx, NULL);
228 
229     establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
230                        tname, flags, &ictx, &actx, NULL, NULL, NULL);
231 
232     check_inq_context(ictx, 0, &mech_krb5, flags | GSS_C_TRANS_FLAG, 1);
233     check_inq_context(actx, 0, &mech_krb5,
234                       flags | GSS_C_TRANS_FLAG | GSS_C_PROT_READY_FLAG, 0);
235 
236     (void)gss_delete_sec_context(&minor, &ictx, NULL);
237     (void)gss_delete_sec_context(&minor, &actx, NULL);
238 
239     (void)gss_release_name(&minor, &tname);
240     return 0;
241 }
242