1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* tests/gssapi/t_enctypes.c - gss_krb5_set_allowable_enctypes test */
3 /*
4 * Copyright (C) 2013 by the Massachusetts Institute of Technology.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "k5-int.h"
34 #include "common.h"
35 #include "gssapi_ext.h"
36
37 /*
38 * This test program establishes contexts with the krb5 mech, the default
39 * initiator name, a specified target name, and the default acceptor name.
40 * Before the exchange, gss_set_allowable_enctypes is called for the initiator
41 * and the acceptor cred if requested. If the exchange is successful, the
42 * resulting contexts are exported with gss_krb5_export_lucid_sec_context,
43 * checked for mismatches, and the GSS protocol and keys are displayed. Exits
44 * with status 0 if all operations are successful, or 1 if not.
45 *
46 * Usage: ./t_enctypes [-i initenctypes] [-a accenctypes] targetname
47 */
48
49 static void
usage(void)50 usage(void)
51 {
52 errout("Usage: t_enctypes [-i initenctypes] [-a accenctypes] "
53 "targetname");
54 }
55
56 /* Error out if ikey is not the same as akey. */
57 static void
check_key_match(gss_krb5_lucid_key_t * ikey,gss_krb5_lucid_key_t * akey)58 check_key_match(gss_krb5_lucid_key_t *ikey, gss_krb5_lucid_key_t *akey)
59 {
60 if (ikey->type != akey->type || ikey->length != akey->length ||
61 memcmp(ikey->data, akey->data, ikey->length) != 0)
62 errout("Initiator and acceptor keys do not match");
63 }
64
65 /* Display the name of enctype. */
66 static void
display_enctype(krb5_enctype enctype)67 display_enctype(krb5_enctype enctype)
68 {
69 char ename[128];
70
71 if (krb5_enctype_to_name(enctype, FALSE, ename, sizeof(ename)) == 0)
72 fputs(ename, stdout);
73 else
74 fputs("(unknown)", stdout);
75 }
76
77 int
main(int argc,char * argv[])78 main(int argc, char *argv[])
79 {
80 krb5_error_code ret;
81 krb5_context kctx = NULL;
82 krb5_enctype *ienc = NULL, *aenc = NULL, zero = 0;
83 OM_uint32 minor, major, flags;
84 gss_name_t tname;
85 gss_cred_id_t icred = GSS_C_NO_CREDENTIAL, acred = GSS_C_NO_CREDENTIAL;
86 gss_ctx_id_t ictx, actx;
87 gss_krb5_lucid_context_v1_t *ilucid, *alucid;
88 gss_krb5_rfc1964_keydata_t *i1964, *a1964;
89 gss_krb5_cfx_keydata_t *icfx, *acfx;
90 gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
91 gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF;
92 unsigned int ssf;
93 size_t count;
94 void *lptr;
95 int c;
96
97 ret = krb5_init_context(&kctx);
98 check_k5err(kctx, "krb5_init_context", ret);
99
100 /* Parse arguments. */
101 while ((c = getopt(argc, argv, "i:a:")) != -1) {
102 switch (c) {
103 case 'i':
104 ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &ienc);
105 check_k5err(kctx, "krb5_parse_enctype_list(initiator)", ret);
106 break;
107 case 'a':
108 ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &aenc);
109 check_k5err(kctx, "krb5_parse_enctype_list(acceptor)", ret);
110 break;
111 default:
112 usage();
113 }
114 }
115 argc -= optind;
116 argv += optind;
117 if (argc != 1)
118 usage();
119 tname = import_name(*argv);
120
121 if (ienc != NULL) {
122 major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
123 &mechset_krb5, GSS_C_INITIATE, &icred, NULL,
124 NULL);
125 check_gsserr("gss_acquire_cred(initiator)", major, minor);
126
127 for (count = 0; ienc[count]; count++);
128 major = gss_krb5_set_allowable_enctypes(&minor, icred, count, ienc);
129 check_gsserr("gss_krb5_set_allowable_enctypes(init)", major, minor);
130 }
131 if (aenc != NULL) {
132 major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE,
133 &mechset_krb5, GSS_C_ACCEPT, &acred, NULL,
134 NULL);
135 check_gsserr("gss_acquire_cred(acceptor)", major, minor);
136
137 for (count = 0; aenc[count]; count++);
138 major = gss_krb5_set_allowable_enctypes(&minor, acred, count, aenc);
139 check_gsserr("gss_krb5_set_allowable_enctypes(acc)", major, minor);
140 }
141
142 flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
143 establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx,
144 NULL, NULL, NULL);
145
146 /* Query the SSF value and range-check the result. */
147 major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset);
148 check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor);
149 if (bufset->elements[0].length != 4)
150 errout("SSF buffer has unexpected length");
151 ssf = load_32_be(bufset->elements[0].value);
152 if (ssf < 56 || ssf > 256)
153 errout("SSF value not within acceptable range (56-256)");
154 (void)gss_release_buffer_set(&minor, &bufset);
155
156 /* Export to lucid contexts. */
157 major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
158 check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);
159 ilucid = lptr;
160 major = gss_krb5_export_lucid_sec_context(&minor, &actx, 1, &lptr);
161 check_gsserr("gss_export_lucid_sec_context(acceptor)", major, minor);
162 alucid = lptr;
163
164 /* Grab the session keys and make sure they match. */
165 if (ilucid->protocol != alucid->protocol)
166 errout("Initiator/acceptor protocol mismatch");
167 if (ilucid->protocol) {
168 icfx = &ilucid->cfx_kd;
169 acfx = &alucid->cfx_kd;
170 if (icfx->have_acceptor_subkey != acfx->have_acceptor_subkey)
171 errout("Initiator/acceptor have_acceptor_subkey mismatch");
172 check_key_match(&icfx->ctx_key, &acfx->ctx_key);
173 if (icfx->have_acceptor_subkey)
174 check_key_match(&icfx->acceptor_subkey, &acfx->acceptor_subkey);
175 fputs("cfx ", stdout);
176 display_enctype(icfx->ctx_key.type);
177 if (icfx->have_acceptor_subkey) {
178 fputs(" ", stdout);
179 display_enctype(icfx->acceptor_subkey.type);
180 }
181 fputs("\n", stdout);
182 } else {
183 i1964 = &ilucid->rfc1964_kd;
184 a1964 = &alucid->rfc1964_kd;
185 if (i1964->sign_alg != a1964->sign_alg ||
186 i1964->seal_alg != a1964->seal_alg)
187 errout("Initiator/acceptor sign or seal alg mismatch");
188 check_key_match(&i1964->ctx_key, &a1964->ctx_key);
189 fputs("rfc1964 ", stdout);
190 display_enctype(i1964->ctx_key.type);
191 fputs("\n", stdout);
192 }
193
194 krb5_free_context(kctx);
195 free(ienc);
196 free(aenc);
197 (void)gss_release_name(&minor, &tname);
198 (void)gss_release_cred(&minor, &icred);
199 (void)gss_release_cred(&minor, &acred);
200 (void)gss_delete_sec_context(&minor, &ictx, NULL);
201 (void)gss_delete_sec_context(&minor, &actx, NULL);
202 (void)gss_krb5_free_lucid_sec_context(&minor, ilucid);
203 (void)gss_krb5_free_lucid_sec_context(&minor, alucid);
204 return 0;
205 }
206