xref: /freebsd/crypto/krb5/src/tests/gssapi/t_enctypes.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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