1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* tests/gssapi/t_pcontok.c - gss_process_context_token tests */
3 /*
4 * Copyright (C) 2014 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 /*
34 * This test program exercises krb5 gss_process_context_token. It first
35 * establishes a context to a named target. Then, if the resulting context
36 * uses RFC 1964, it creates a context deletion token from the acceptor to the
37 * initiator and passes it to the initiator using gss_process_context_token.
38 * If the established context uses RFC 4121, this program feeds a made-up
39 * context token to gss_process_context_token and checks for the expected
40 * error.
41 */
42
43 #include "k5-int.h"
44 #include "common.h"
45
46 #define SGN_ALG_HMAC_SHA1_DES3_KD 0x04
47 #define SGN_ALG_HMAC_MD5 0x11
48
49 /*
50 * Create a valid RFC 1964 context deletion token using the information in *
51 * lctx. We must do this by hand since we no longer create context deletion
52 * tokens from gss_delete_sec_context.
53 */
54 static void
make_delete_token(gss_krb5_lucid_context_v1_t * lctx,gss_buffer_desc * out)55 make_delete_token(gss_krb5_lucid_context_v1_t *lctx, gss_buffer_desc *out)
56 {
57 krb5_error_code ret;
58 krb5_context context;
59 krb5_keyblock seqkb;
60 krb5_key seq;
61 krb5_checksum cksum;
62 krb5_cksumtype cktype;
63 krb5_keyusage ckusage;
64 krb5_crypto_iov iov;
65 krb5_data d;
66 size_t cksize, tlen;
67 unsigned char *token, *ptr, iv[8];
68 gss_krb5_lucid_key_t *lkey = &lctx->rfc1964_kd.ctx_key;
69 int signalg = lctx->rfc1964_kd.sign_alg;
70
71 ret = krb5_init_context(&context);
72 check_k5err(context, "krb5_init_context", ret);
73
74 seqkb.enctype = lkey->type;
75 seqkb.length = lkey->length;
76 seqkb.contents = lkey->data;
77 ret = krb5_k_create_key(context, &seqkb, &seq);
78 check_k5err(context, "krb5_k_create_key", ret);
79
80 if (signalg == SGN_ALG_HMAC_SHA1_DES3_KD) {
81 cktype = CKSUMTYPE_HMAC_SHA1_DES3;
82 cksize = 20;
83 ckusage = 23;
84 } else if (signalg == SGN_ALG_HMAC_MD5) {
85 cktype = CKSUMTYPE_HMAC_MD5_ARCFOUR;
86 cksize = 8;
87 ckusage = 15;
88 } else {
89 abort();
90 }
91
92 tlen = 20 + mech_krb5.length + cksize;
93 token = malloc(tlen);
94 assert(token != NULL);
95
96 /* Create the ASN.1 wrapper (4 + mech_krb5.length bytes). Assume the ASN.1
97 * lengths fit in one byte since deletion tokens are short. */
98 ptr = token;
99 *ptr++ = 0x60;
100 *ptr++ = tlen - 2;
101 *ptr++ = 0x06;
102 *ptr++ = mech_krb5.length;
103 memcpy(ptr, mech_krb5.elements, mech_krb5.length);
104 ptr += mech_krb5.length;
105
106 /* Create the RFC 1964 token header (8 bytes). */
107 *ptr++ = 0x01;
108 *ptr++ = 0x02;
109 store_16_le(signalg, ptr);
110 ptr += 2;
111 *ptr++ = 0xFF;
112 *ptr++ = 0xFF;
113 *ptr++ = 0xFF;
114 *ptr++ = 0xFF;
115
116 /* Create the checksum (cksize bytes at offset 8 from the header). */
117 d = make_data(ptr - 8, 8);
118 ret = krb5_k_make_checksum(context, cktype, seq, ckusage, &d, &cksum);
119 check_k5err(context, "krb5_k_make_checksum", ret);
120 memcpy(ptr + 8, cksum.contents, cksize);
121
122 /* Create the sequence number (8 bytes). */
123 iov.flags = KRB5_CRYPTO_TYPE_DATA;
124 iov.data = make_data(ptr, 8);
125 ptr[4] = ptr[5] = ptr[6] = ptr[7] = lctx->initiate ? 0 : 0xFF;
126 memcpy(iv, ptr + 8, 8);
127 d = make_data(iv, 8);
128 if (signalg == SGN_ALG_HMAC_MD5) {
129 store_32_be(lctx->send_seq, ptr);
130 ret = krb5int_arcfour_gsscrypt(&seq->keyblock, 0, &d, &iov, 1);
131 check_k5err(context, "krb5int_arcfour_gsscrypt(seq)", ret);
132 } else {
133 store_32_le(lctx->send_seq, ptr);
134 ret = krb5_k_encrypt_iov(context, seq, 24, &d, &iov, 1);
135 check_k5err(context, "krb5_k_encrypt_iov(seq)", ret);
136 }
137
138 krb5_free_checksum_contents(context, &cksum);
139 krb5_k_free_key(context, seq);
140 krb5_free_context(context);
141
142 out->length = tlen;
143 out->value = token;
144 }
145
146 int
main(int argc,char * argv[])147 main(int argc, char *argv[])
148 {
149 OM_uint32 minor, major, flags;
150 gss_name_t tname;
151 gss_buffer_desc token, in = GSS_C_EMPTY_BUFFER, out;
152 gss_ctx_id_t ictx, actx;
153 gss_krb5_lucid_context_v1_t *lctx;
154 void *lptr;
155
156 assert(argc == 2);
157 tname = import_name(argv[1]);
158
159 flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
160 establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL,
161 tname, flags, &ictx, &actx, NULL, NULL, NULL);
162
163 /* Export the acceptor context to a lucid context so we can look inside. */
164 major = gss_krb5_export_lucid_sec_context(&minor, &actx, 1, &lptr);
165 check_gsserr("gss_export_lucid_sec_context", major, minor);
166 lctx = lptr;
167 if (!lctx->protocol) {
168 /* Make an RFC 1964 context deletion token and pass it to
169 * gss_process_context_token. */
170 make_delete_token(lctx, &token);
171 major = gss_process_context_token(&minor, ictx, &token);
172 free(token.value);
173 check_gsserr("gss_process_context_token", major, minor);
174 /* Check for the appropriate major code from gss_wrap. */
175 major = gss_wrap(&minor, ictx, 1, GSS_C_QOP_DEFAULT, &in, NULL, &out);
176 assert(major == GSS_S_NO_CONTEXT);
177 } else {
178 /* RFC 4121 defines no context deletion token, so try passing something
179 * arbitrary and check for the appropriate major code. */
180 token.value = "abcd";
181 token.length = 4;
182 major = gss_process_context_token(&minor, ictx, &token);
183 assert(major == GSS_S_DEFECTIVE_TOKEN);
184 }
185
186 (void)gss_release_name(&minor, &tname);
187 (void)gss_delete_sec_context(&minor, &ictx, NULL);
188 (void)gss_krb5_free_lucid_sec_context(&minor, lptr);
189 return 0;
190 }
191