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