Home | History | Annotate | Line # | Download | only in gssapi
      1  1.1     elric /*	$NetBSD: test_context.c,v 1.3 2023/06/19 21:41:42 christos Exp $	*/
      2  1.1     elric 
      3  1.1     elric /*
      4  1.1     elric  * Copyright (c) 2006 - 2008 Kungliga Tekniska Hgskolan
      5  1.1     elric  * (Royal Institute of Technology, Stockholm, Sweden).
      6  1.1     elric  * All rights reserved.
      7  1.1     elric  *
      8  1.1     elric  * Redistribution and use in source and binary forms, with or without
      9  1.1     elric  * modification, are permitted provided that the following conditions
     10  1.1     elric  * are met:
     11  1.1     elric  *
     12  1.1     elric  * 1. Redistributions of source code must retain the above copyright
     13  1.1     elric  *    notice, this list of conditions and the following disclaimer.
     14  1.1     elric  *
     15  1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     17  1.1     elric  *    documentation and/or other materials provided with the distribution.
     18  1.1     elric  *
     19  1.1     elric  * 3. Neither the name of KTH nor the names of its contributors may be
     20  1.1     elric  *    used to endorse or promote products derived from this software without
     21  1.1     elric  *    specific prior written permission.
     22  1.1     elric  *
     23  1.1     elric  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     24  1.1     elric  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.1     elric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     26  1.1     elric  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
     27  1.1     elric  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     28  1.1     elric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     29  1.1     elric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     30  1.1     elric  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     31  1.1     elric  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     32  1.1     elric  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     33  1.1     elric  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34  1.1     elric  */
     35  1.1     elric 
     36  1.1     elric #include "krb5/gsskrb5_locl.h"
     37  1.1     elric #include <err.h>
     38  1.1     elric #include <krb5/getarg.h>
     39  1.1     elric #include <gssapi/gssapi.h>
     40  1.1     elric #include <gssapi/gssapi_krb5.h>
     41  1.1     elric #include <gssapi/gssapi_spnego.h>
     42  1.1     elric #include <gssapi/gssapi_ntlm.h>
     43  1.1     elric #include "test_common.h"
     44  1.1     elric 
     45  1.1     elric static char *type_string;
     46  1.1     elric static char *mech_string;
     47  1.2  christos static char *mechs_string;
     48  1.1     elric static char *ret_mech_string;
     49  1.1     elric static char *client_name;
     50  1.2  christos static char *client_password;
     51  1.1     elric static int dns_canon_flag = -1;
     52  1.1     elric static int mutual_auth_flag = 0;
     53  1.1     elric static int dce_style_flag = 0;
     54  1.1     elric static int wrapunwrap_flag = 0;
     55  1.1     elric static int iov_flag = 0;
     56  1.2  christos static int aead_flag = 0;
     57  1.1     elric static int getverifymic_flag = 0;
     58  1.1     elric static int deleg_flag = 0;
     59  1.1     elric static int policy_deleg_flag = 0;
     60  1.1     elric static int server_no_deleg_flag = 0;
     61  1.1     elric static int ei_flag = 0;
     62  1.1     elric static char *gsskrb5_acceptor_identity = NULL;
     63  1.1     elric static char *session_enctype_string = NULL;
     64  1.1     elric static int client_time_offset = 0;
     65  1.1     elric static int server_time_offset = 0;
     66  1.1     elric static int max_loops = 0;
     67  1.1     elric static char *limit_enctype_string = NULL;
     68  1.1     elric static int version_flag = 0;
     69  1.1     elric static int verbose_flag = 0;
     70  1.1     elric static int help_flag	= 0;
     71  1.1     elric 
     72  1.1     elric static krb5_context context;
     73  1.1     elric static krb5_enctype limit_enctype = 0;
     74  1.1     elric 
     75  1.1     elric static struct {
     76  1.1     elric     const char *name;
     77  1.1     elric     gss_OID oid;
     78  1.1     elric } o2n[] = {
     79  1.1     elric     { "krb5", NULL /* GSS_KRB5_MECHANISM */ },
     80  1.1     elric     { "spnego", NULL /* GSS_SPNEGO_MECHANISM */ },
     81  1.1     elric     { "ntlm", NULL /* GSS_NTLM_MECHANISM */ },
     82  1.1     elric     { "sasl-digest-md5", NULL /* GSS_SASL_DIGEST_MD5_MECHANISM */ }
     83  1.1     elric };
     84  1.1     elric 
     85  1.1     elric static void
     86  1.1     elric init_o2n(void)
     87  1.1     elric {
     88  1.1     elric     o2n[0].oid = GSS_KRB5_MECHANISM;
     89  1.1     elric     o2n[1].oid = GSS_SPNEGO_MECHANISM;
     90  1.1     elric     o2n[2].oid = GSS_NTLM_MECHANISM;
     91  1.1     elric     o2n[3].oid = GSS_SASL_DIGEST_MD5_MECHANISM;
     92  1.1     elric }
     93  1.1     elric 
     94  1.1     elric static gss_OID
     95  1.1     elric string_to_oid(const char *name)
     96  1.1     elric {
     97  1.2  christos     size_t i;
     98  1.1     elric     for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
     99  1.1     elric 	if (strcasecmp(name, o2n[i].name) == 0)
    100  1.1     elric 	    return o2n[i].oid;
    101  1.1     elric     errx(1, "name '%s' not unknown", name);
    102  1.1     elric }
    103  1.1     elric 
    104  1.2  christos static void
    105  1.2  christos string_to_oids(gss_OID_set *oidsetp, gss_OID_set oidset,
    106  1.2  christos                gss_OID_desc *oidarray, size_t oidarray_len,
    107  1.2  christos                char *names)
    108  1.2  christos {
    109  1.2  christos     char *name;
    110  1.2  christos     char *s;
    111  1.2  christos 
    112  1.2  christos     if (names[0] == '\0') {
    113  1.2  christos         *oidsetp = GSS_C_NO_OID_SET;
    114  1.2  christos         return;
    115  1.2  christos     }
    116  1.2  christos 
    117  1.2  christos     oidset->elements = &oidarray[0];
    118  1.2  christos     if (strcasecmp(names, "all") == 0) {
    119  1.2  christos         if (sizeof(o2n)/sizeof(o2n[0]) > oidarray_len)
    120  1.2  christos             errx(1, "internal error: oidarray must be enlarged");
    121  1.2  christos         for (oidset->count = 0; oidset->count < oidarray_len; oidset->count++)
    122  1.2  christos             oidset->elements[oidset->count] = *o2n[oidset->count].oid;
    123  1.2  christos     } else {
    124  1.2  christos         for (oidset->count = 0, name = strtok_r(names, ", ", &s);
    125  1.2  christos              name != NULL;
    126  1.2  christos              oidset->count++, name = strtok_r(NULL, ", ", &s)) {
    127  1.2  christos             if (oidset->count >= oidarray_len)
    128  1.2  christos                 errx(1, "too many mech names given");
    129  1.2  christos             oidset->elements[oidset->count] = *string_to_oid(name);
    130  1.2  christos         }
    131  1.2  christos         oidset->count = oidset->count;
    132  1.2  christos     }
    133  1.2  christos     *oidsetp = oidset;
    134  1.2  christos }
    135  1.2  christos 
    136  1.1     elric static const char *
    137  1.1     elric oid_to_string(const gss_OID oid)
    138  1.1     elric {
    139  1.2  christos     size_t i;
    140  1.1     elric     for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
    141  1.1     elric 	if (gss_oid_equal(oid, o2n[i].oid))
    142  1.1     elric 	    return o2n[i].name;
    143  1.1     elric     return "unknown oid";
    144  1.1     elric }
    145  1.1     elric 
    146  1.1     elric static void
    147  1.1     elric loop(gss_OID mechoid,
    148  1.1     elric      gss_OID nameoid, const char *target,
    149  1.1     elric      gss_cred_id_t init_cred,
    150  1.1     elric      gss_ctx_id_t *sctx, gss_ctx_id_t *cctx,
    151  1.1     elric      gss_OID *actual_mech,
    152  1.1     elric      gss_cred_id_t *deleg_cred)
    153  1.1     elric {
    154  1.1     elric     int server_done = 0, client_done = 0;
    155  1.1     elric     int num_loops = 0;
    156  1.1     elric     OM_uint32 maj_stat, min_stat;
    157  1.1     elric     gss_name_t gss_target_name;
    158  1.1     elric     gss_buffer_desc input_token, output_token;
    159  1.1     elric     OM_uint32 flags = 0, ret_cflags, ret_sflags;
    160  1.1     elric     gss_OID actual_mech_client;
    161  1.1     elric     gss_OID actual_mech_server;
    162  1.1     elric 
    163  1.1     elric     *actual_mech = GSS_C_NO_OID;
    164  1.1     elric 
    165  1.1     elric     flags |= GSS_C_INTEG_FLAG;
    166  1.1     elric     flags |= GSS_C_CONF_FLAG;
    167  1.1     elric 
    168  1.1     elric     if (mutual_auth_flag)
    169  1.1     elric 	flags |= GSS_C_MUTUAL_FLAG;
    170  1.1     elric     if (dce_style_flag)
    171  1.1     elric 	flags |= GSS_C_DCE_STYLE;
    172  1.1     elric     if (deleg_flag)
    173  1.1     elric 	flags |= GSS_C_DELEG_FLAG;
    174  1.1     elric     if (policy_deleg_flag)
    175  1.1     elric 	flags |= GSS_C_DELEG_POLICY_FLAG;
    176  1.1     elric 
    177  1.1     elric     input_token.value = rk_UNCONST(target);
    178  1.1     elric     input_token.length = strlen(target);
    179  1.1     elric 
    180  1.1     elric     maj_stat = gss_import_name(&min_stat,
    181  1.1     elric 			       &input_token,
    182  1.1     elric 			       nameoid,
    183  1.1     elric 			       &gss_target_name);
    184  1.1     elric     if (GSS_ERROR(maj_stat))
    185  1.1     elric 	err(1, "import name creds failed with: %d", maj_stat);
    186  1.1     elric 
    187  1.1     elric     input_token.length = 0;
    188  1.1     elric     input_token.value = NULL;
    189  1.1     elric 
    190  1.1     elric     while (!server_done || !client_done) {
    191  1.1     elric 	num_loops++;
    192  1.1     elric 
    193  1.1     elric 	gsskrb5_set_time_offset(client_time_offset);
    194  1.1     elric 
    195  1.1     elric 	maj_stat = gss_init_sec_context(&min_stat,
    196  1.1     elric 					init_cred,
    197  1.1     elric 					cctx,
    198  1.1     elric 					gss_target_name,
    199  1.1     elric 					mechoid,
    200  1.1     elric 					flags,
    201  1.1     elric 					0,
    202  1.1     elric 					NULL,
    203  1.1     elric 					&input_token,
    204  1.1     elric 					&actual_mech_client,
    205  1.1     elric 					&output_token,
    206  1.1     elric 					&ret_cflags,
    207  1.1     elric 					NULL);
    208  1.1     elric 	if (GSS_ERROR(maj_stat))
    209  1.1     elric 	    errx(1, "init_sec_context: %s",
    210  1.1     elric 		 gssapi_err(maj_stat, min_stat, mechoid));
    211  1.1     elric 	if (maj_stat & GSS_S_CONTINUE_NEEDED)
    212  1.1     elric 	    ;
    213  1.1     elric 	else
    214  1.1     elric 	    client_done = 1;
    215  1.1     elric 
    216  1.1     elric 	gsskrb5_get_time_offset(&client_time_offset);
    217  1.1     elric 
    218  1.1     elric 	if (client_done && server_done)
    219  1.1     elric 	    break;
    220  1.1     elric 
    221  1.1     elric 	if (input_token.length != 0)
    222  1.1     elric 	    gss_release_buffer(&min_stat, &input_token);
    223  1.1     elric 
    224  1.1     elric 	gsskrb5_set_time_offset(server_time_offset);
    225  1.1     elric 
    226  1.1     elric 	maj_stat = gss_accept_sec_context(&min_stat,
    227  1.1     elric 					  sctx,
    228  1.1     elric 					  GSS_C_NO_CREDENTIAL,
    229  1.1     elric 					  &output_token,
    230  1.1     elric 					  GSS_C_NO_CHANNEL_BINDINGS,
    231  1.1     elric 					  NULL,
    232  1.1     elric 					  &actual_mech_server,
    233  1.1     elric 					  &input_token,
    234  1.1     elric 					  &ret_sflags,
    235  1.1     elric 					  NULL,
    236  1.1     elric 					  deleg_cred);
    237  1.1     elric 	if (GSS_ERROR(maj_stat))
    238  1.1     elric 		errx(1, "accept_sec_context: %s",
    239  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech_server));
    240  1.1     elric 
    241  1.1     elric 	gsskrb5_get_time_offset(&server_time_offset);
    242  1.1     elric 
    243  1.1     elric 	if (output_token.length != 0)
    244  1.1     elric 	    gss_release_buffer(&min_stat, &output_token);
    245  1.1     elric 
    246  1.1     elric 	if (maj_stat & GSS_S_CONTINUE_NEEDED)
    247  1.1     elric 	    ;
    248  1.1     elric 	else
    249  1.1     elric 	    server_done = 1;
    250  1.2  christos     }
    251  1.1     elric     if (output_token.length != 0)
    252  1.1     elric 	gss_release_buffer(&min_stat, &output_token);
    253  1.1     elric     if (input_token.length != 0)
    254  1.1     elric 	gss_release_buffer(&min_stat, &input_token);
    255  1.1     elric     gss_release_name(&min_stat, &gss_target_name);
    256  1.1     elric 
    257  1.1     elric     if (deleg_flag || policy_deleg_flag) {
    258  1.1     elric 	if (server_no_deleg_flag) {
    259  1.1     elric 	    if (*deleg_cred != GSS_C_NO_CREDENTIAL)
    260  1.1     elric 		errx(1, "got delegated cred but didn't expect one");
    261  1.1     elric 	} else if (*deleg_cred == GSS_C_NO_CREDENTIAL)
    262  1.1     elric 	    errx(1, "asked for delegarated cred but did get one");
    263  1.1     elric     } else if (*deleg_cred != GSS_C_NO_CREDENTIAL)
    264  1.1     elric 	  errx(1, "got deleg_cred cred but didn't ask");
    265  1.1     elric 
    266  1.1     elric     if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0)
    267  1.1     elric 	errx(1, "mech mismatch");
    268  1.1     elric     *actual_mech = actual_mech_server;
    269  1.1     elric 
    270  1.1     elric     if (max_loops && num_loops > max_loops)
    271  1.1     elric 	errx(1, "num loops %d was lager then max loops %d",
    272  1.1     elric 	     num_loops, max_loops);
    273  1.1     elric 
    274  1.1     elric     if (verbose_flag) {
    275  1.1     elric 	printf("server time offset: %d\n", server_time_offset);
    276  1.1     elric 	printf("client time offset: %d\n", client_time_offset);
    277  1.1     elric 	printf("num loops %d\n", num_loops);
    278  1.1     elric     }
    279  1.1     elric }
    280  1.1     elric 
    281  1.1     elric static void
    282  1.1     elric wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
    283  1.1     elric {
    284  1.1     elric     gss_buffer_desc input_token, output_token, output_token2;
    285  1.1     elric     OM_uint32 min_stat, maj_stat;
    286  1.1     elric     gss_qop_t qop_state;
    287  1.1     elric     int conf_state;
    288  1.1     elric 
    289  1.1     elric     input_token.value = "foo";
    290  1.1     elric     input_token.length = 3;
    291  1.1     elric 
    292  1.1     elric     maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token,
    293  1.1     elric 			&conf_state, &output_token);
    294  1.1     elric     if (maj_stat != GSS_S_COMPLETE)
    295  1.1     elric 	errx(1, "gss_wrap failed: %s",
    296  1.1     elric 	     gssapi_err(maj_stat, min_stat, mechoid));
    297  1.1     elric 
    298  1.1     elric     maj_stat = gss_unwrap(&min_stat, sctx, &output_token,
    299  1.1     elric 			  &output_token2, &conf_state, &qop_state);
    300  1.1     elric     if (maj_stat != GSS_S_COMPLETE)
    301  1.1     elric 	errx(1, "gss_unwrap failed: %s",
    302  1.1     elric 	     gssapi_err(maj_stat, min_stat, mechoid));
    303  1.1     elric 
    304  1.1     elric     gss_release_buffer(&min_stat, &output_token);
    305  1.1     elric     gss_release_buffer(&min_stat, &output_token2);
    306  1.1     elric 
    307  1.1     elric #if 0 /* doesn't work for NTLM yet */
    308  1.1     elric     if (!!conf_state != !!flags)
    309  1.1     elric 	errx(1, "conf_state mismatch");
    310  1.1     elric #endif
    311  1.1     elric }
    312  1.1     elric 
    313  1.1     elric #define USE_CONF		1
    314  1.1     elric #define USE_HEADER_ONLY		2
    315  1.1     elric #define USE_SIGN_ONLY		4
    316  1.1     elric #define FORCE_IOV		8
    317  1.1     elric 
    318  1.1     elric static void
    319  1.1     elric wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
    320  1.1     elric {
    321  1.1     elric     krb5_data token, header, trailer;
    322  1.1     elric     OM_uint32 min_stat, maj_stat;
    323  1.1     elric     gss_qop_t qop_state;
    324  1.1     elric     int conf_state, conf_state2;
    325  1.1     elric     gss_iov_buffer_desc iov[6];
    326  1.1     elric     unsigned char *p;
    327  1.1     elric     int iov_len;
    328  1.1     elric     char header_data[9] = "ABCheader";
    329  1.1     elric     char trailer_data[10] = "trailerXYZ";
    330  1.1     elric 
    331  1.1     elric     char token_data[16] = "0123456789abcdef";
    332  1.1     elric 
    333  1.1     elric     memset(&iov, 0, sizeof(iov));
    334  1.1     elric 
    335  1.1     elric     if (flags & USE_SIGN_ONLY) {
    336  1.1     elric 	header.data = header_data;
    337  1.1     elric 	header.length = 9;
    338  1.1     elric 	trailer.data = trailer_data;
    339  1.1     elric 	trailer.length = 10;
    340  1.1     elric     } else {
    341  1.1     elric 	header.data = NULL;
    342  1.1     elric 	header.length = 0;
    343  1.1     elric 	trailer.data = NULL;
    344  1.1     elric 	trailer.length = 0;
    345  1.1     elric     }
    346  1.1     elric 
    347  1.1     elric     token.data = token_data;
    348  1.1     elric     token.length = 16;
    349  1.1     elric 
    350  1.1     elric     iov_len = sizeof(iov)/sizeof(iov[0]);
    351  1.1     elric 
    352  1.1     elric     memset(iov, 0, sizeof(iov));
    353  1.1     elric 
    354  1.3  christos     iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
    355  1.1     elric 
    356  1.1     elric     if (header.length != 0) {
    357  1.1     elric 	iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
    358  1.1     elric 	iov[1].buffer.length = header.length;
    359  1.1     elric 	iov[1].buffer.value = header.data;
    360  1.1     elric     } else {
    361  1.1     elric 	iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
    362  1.1     elric 	iov[1].buffer.length = 0;
    363  1.1     elric 	iov[1].buffer.value = NULL;
    364  1.1     elric     }
    365  1.1     elric     iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
    366  1.1     elric     iov[2].buffer.length = token.length;
    367  1.1     elric     iov[2].buffer.value = token.data;
    368  1.1     elric     if (trailer.length != 0) {
    369  1.1     elric 	iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
    370  1.1     elric 	iov[3].buffer.length = trailer.length;
    371  1.1     elric 	iov[3].buffer.value = trailer.data;
    372  1.1     elric     } else {
    373  1.1     elric 	iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
    374  1.1     elric 	iov[3].buffer.length = 0;
    375  1.1     elric 	iov[3].buffer.value = NULL;
    376  1.1     elric     }
    377  1.1     elric     if (dce_style_flag) {
    378  1.1     elric 	iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY;
    379  1.1     elric     } else {
    380  1.3  christos 	iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE;
    381  1.1     elric     }
    382  1.1     elric     iov[4].buffer.length = 0;
    383  1.1     elric     iov[4].buffer.value = 0;
    384  1.1     elric     if (dce_style_flag) {
    385  1.1     elric 	iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
    386  1.1     elric     } else if (flags & USE_HEADER_ONLY) {
    387  1.1     elric 	iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
    388  1.1     elric     } else {
    389  1.3  christos 	iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
    390  1.1     elric     }
    391  1.1     elric     iov[5].buffer.length = 0;
    392  1.1     elric     iov[5].buffer.value = 0;
    393  1.1     elric 
    394  1.1     elric     maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state,
    395  1.1     elric 			    iov, iov_len);
    396  1.1     elric     if (maj_stat != GSS_S_COMPLETE)
    397  1.1     elric 	errx(1, "gss_wrap_iov failed");
    398  1.1     elric 
    399  1.1     elric     token.length =
    400  1.2  christos 	iov[0].buffer.length +
    401  1.1     elric 	iov[1].buffer.length +
    402  1.1     elric 	iov[2].buffer.length +
    403  1.2  christos 	iov[3].buffer.length +
    404  1.1     elric 	iov[4].buffer.length +
    405  1.1     elric 	iov[5].buffer.length;
    406  1.1     elric     token.data = emalloc(token.length);
    407  1.1     elric 
    408  1.1     elric     p = token.data;
    409  1.3  christos 
    410  1.3  christos     if (iov[0].buffer.length)
    411  1.3  christos         memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
    412  1.1     elric     p += iov[0].buffer.length;
    413  1.3  christos 
    414  1.3  christos     if (iov[1].buffer.length)
    415  1.3  christos         memcpy(p, iov[1].buffer.value, iov[1].buffer.length);
    416  1.1     elric     p += iov[1].buffer.length;
    417  1.3  christos 
    418  1.3  christos     if (iov[2].buffer.length)
    419  1.3  christos         memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
    420  1.1     elric     p += iov[2].buffer.length;
    421  1.3  christos 
    422  1.3  christos     if (iov[3].buffer.length)
    423  1.3  christos         memcpy(p, iov[3].buffer.value, iov[3].buffer.length);
    424  1.1     elric     p += iov[3].buffer.length;
    425  1.3  christos 
    426  1.3  christos     if (iov[4].buffer.length)
    427  1.3  christos         memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
    428  1.1     elric     p += iov[4].buffer.length;
    429  1.3  christos 
    430  1.3  christos     if (iov[5].buffer.length)
    431  1.3  christos         memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
    432  1.1     elric     p += iov[5].buffer.length;
    433  1.1     elric 
    434  1.1     elric     assert(p - ((unsigned char *)token.data) == token.length);
    435  1.1     elric 
    436  1.1     elric     if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
    437  1.1     elric 	gss_buffer_desc input, output;
    438  1.1     elric 
    439  1.1     elric 	input.value = token.data;
    440  1.1     elric 	input.length = token.length;
    441  1.1     elric 
    442  1.1     elric 	maj_stat = gss_unwrap(&min_stat, sctx, &input,
    443  1.1     elric 			      &output, &conf_state2, &qop_state);
    444  1.1     elric 
    445  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    446  1.1     elric 	    errx(1, "gss_unwrap from gss_wrap_iov failed: %s",
    447  1.1     elric 		 gssapi_err(maj_stat, min_stat, mechoid));
    448  1.1     elric 
    449  1.1     elric 	gss_release_buffer(&min_stat, &output);
    450  1.1     elric     } else {
    451  1.1     elric 	maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state,
    452  1.1     elric 				  iov, iov_len);
    453  1.2  christos 
    454  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    455  1.1     elric 	    errx(1, "gss_unwrap_iov failed: %x %s", flags,
    456  1.1     elric 		 gssapi_err(maj_stat, min_stat, mechoid));
    457  1.2  christos 
    458  1.1     elric     }
    459  1.1     elric     if (conf_state2 != conf_state)
    460  1.1     elric 	errx(1, "conf state wrong for iov: %x", flags);
    461  1.1     elric 
    462  1.2  christos     gss_release_iov_buffer(&min_stat, iov, iov_len);
    463  1.1     elric 
    464  1.1     elric     free(token.data);
    465  1.1     elric }
    466  1.1     elric 
    467  1.1     elric static void
    468  1.2  christos wrapunwrap_aead(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
    469  1.2  christos {
    470  1.2  christos     gss_buffer_desc token, assoc, message = GSS_C_EMPTY_BUFFER;
    471  1.2  christos     gss_buffer_desc output;
    472  1.2  christos     OM_uint32 min_stat, maj_stat;
    473  1.2  christos     gss_qop_t qop_state;
    474  1.2  christos     int conf_state, conf_state2;
    475  1.2  christos     char assoc_data[9] = "ABCheader";
    476  1.2  christos     char token_data[16] = "0123456789abcdef";
    477  1.2  christos 
    478  1.2  christos     if (flags & USE_SIGN_ONLY) {
    479  1.2  christos 	assoc.value = assoc_data;
    480  1.2  christos 	assoc.length = 9;
    481  1.2  christos     } else {
    482  1.2  christos 	assoc.value = NULL;
    483  1.2  christos 	assoc.length = 0;
    484  1.2  christos     }
    485  1.2  christos 
    486  1.2  christos     token.value = token_data;
    487  1.2  christos     token.length = 16;
    488  1.2  christos 
    489  1.2  christos     maj_stat = gss_wrap_aead(&min_stat, cctx, dce_style_flag || flags & USE_CONF,
    490  1.2  christos 			     GSS_C_QOP_DEFAULT, &assoc, &token,
    491  1.2  christos 			     &conf_state, &message);
    492  1.2  christos     if (maj_stat != GSS_S_COMPLETE)
    493  1.2  christos 	errx(1, "gss_wrap_aead failed");
    494  1.2  christos 
    495  1.2  christos     if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
    496  1.2  christos 	maj_stat = gss_unwrap(&min_stat, sctx, &message,
    497  1.2  christos 			      &output, &conf_state2, &qop_state);
    498  1.2  christos 
    499  1.2  christos 	if (maj_stat != GSS_S_COMPLETE)
    500  1.2  christos 	    errx(1, "gss_unwrap from gss_wrap_aead failed: %s",
    501  1.2  christos 		 gssapi_err(maj_stat, min_stat, mechoid));
    502  1.2  christos     } else {
    503  1.2  christos 	maj_stat = gss_unwrap_aead(&min_stat, sctx, &message, &assoc,
    504  1.2  christos 				   &output, &conf_state2, &qop_state);
    505  1.2  christos 	if (maj_stat != GSS_S_COMPLETE)
    506  1.2  christos 	    errx(1, "gss_unwrap_aead failed: %x %s", flags,
    507  1.2  christos 		 gssapi_err(maj_stat, min_stat, mechoid));
    508  1.2  christos     }
    509  1.2  christos 
    510  1.2  christos     if (output.length != token.length)
    511  1.2  christos 	errx(1, "plaintext length wrong for aead");
    512  1.2  christos     else if (memcmp(output.value, token.value, token.length) != 0)
    513  1.2  christos 	errx(1, "plaintext wrong for aead");
    514  1.2  christos     if (conf_state2 != conf_state)
    515  1.2  christos 	errx(1, "conf state wrong for aead: %x", flags);
    516  1.2  christos 
    517  1.2  christos     gss_release_buffer(&min_stat, &message);
    518  1.2  christos     gss_release_buffer(&min_stat, &output);
    519  1.2  christos }
    520  1.2  christos 
    521  1.2  christos static void
    522  1.1     elric getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid)
    523  1.1     elric {
    524  1.1     elric     gss_buffer_desc input_token, output_token;
    525  1.1     elric     OM_uint32 min_stat, maj_stat;
    526  1.1     elric     gss_qop_t qop_state;
    527  1.1     elric 
    528  1.1     elric     input_token.value = "bar";
    529  1.1     elric     input_token.length = 3;
    530  1.1     elric 
    531  1.1     elric     maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token,
    532  1.1     elric 			   &output_token);
    533  1.1     elric     if (maj_stat != GSS_S_COMPLETE)
    534  1.1     elric 	errx(1, "gss_get_mic failed: %s",
    535  1.1     elric 	     gssapi_err(maj_stat, min_stat, mechoid));
    536  1.1     elric 
    537  1.1     elric     maj_stat = gss_verify_mic(&min_stat, sctx, &input_token,
    538  1.1     elric 			      &output_token, &qop_state);
    539  1.1     elric     if (maj_stat != GSS_S_COMPLETE)
    540  1.1     elric 	errx(1, "gss_verify_mic failed: %s",
    541  1.1     elric 	     gssapi_err(maj_stat, min_stat, mechoid));
    542  1.1     elric 
    543  1.1     elric     gss_release_buffer(&min_stat, &output_token);
    544  1.1     elric }
    545  1.1     elric 
    546  1.1     elric static void
    547  1.1     elric empty_release(void)
    548  1.1     elric {
    549  1.1     elric     gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    550  1.1     elric     gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
    551  1.1     elric     gss_name_t name = GSS_C_NO_NAME;
    552  1.1     elric     gss_OID_set oidset = GSS_C_NO_OID_SET;
    553  1.1     elric     OM_uint32 junk;
    554  1.2  christos 
    555  1.1     elric     gss_delete_sec_context(&junk, &ctx, NULL);
    556  1.1     elric     gss_release_cred(&junk, &cred);
    557  1.1     elric     gss_release_name(&junk, &name);
    558  1.1     elric     gss_release_oid_set(&junk, &oidset);
    559  1.1     elric }
    560  1.1     elric 
    561  1.1     elric /*
    562  1.1     elric  *
    563  1.1     elric  */
    564  1.1     elric 
    565  1.1     elric static struct getargs args[] = {
    566  1.1     elric     {"name-type",0,	arg_string, &type_string,  "type of name", NULL },
    567  1.2  christos     {"mech-type",0,	arg_string, &mech_string,  "mech type (name)", NULL },
    568  1.2  christos     {"mech-types",0,	arg_string, &mechs_string, "mech types (names)", NULL },
    569  1.1     elric     {"ret-mech-type",0,	arg_string, &ret_mech_string,
    570  1.1     elric      "type of return mech", NULL },
    571  1.1     elric     {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag,
    572  1.1     elric      "use dns to canonicalize", NULL },
    573  1.1     elric     {"mutual-auth",0,	arg_flag,	&mutual_auth_flag,"mutual auth", NULL },
    574  1.1     elric     {"client-name", 0,  arg_string,     &client_name, "client name", NULL },
    575  1.2  christos     {"client-password", 0,  arg_string, &client_password, "client password", NULL },
    576  1.1     elric     {"limit-enctype",0,	arg_string,	&limit_enctype_string, "enctype", NULL },
    577  1.1     elric     {"dce-style",0,	arg_flag,	&dce_style_flag, "dce-style", NULL },
    578  1.1     elric     {"wrapunwrap",0,	arg_flag,	&wrapunwrap_flag, "wrap/unwrap", NULL },
    579  1.1     elric     {"iov", 0, 		arg_flag,	&iov_flag, "wrap/unwrap iov", NULL },
    580  1.2  christos     {"aead", 0, 	arg_flag,	&aead_flag, "wrap/unwrap aead", NULL },
    581  1.1     elric     {"getverifymic",0,	arg_flag,	&getverifymic_flag,
    582  1.1     elric      "get and verify mic", NULL },
    583  1.1     elric     {"delegate",0,	arg_flag,	&deleg_flag, "delegate credential", NULL },
    584  1.1     elric     {"policy-delegate",0,	arg_flag,	&policy_deleg_flag, "policy delegate credential", NULL },
    585  1.1     elric     {"server-no-delegate",0,	arg_flag,	&server_no_deleg_flag,
    586  1.1     elric      "server should get a credential", NULL },
    587  1.1     elric     {"export-import-cred",0,	arg_flag,	&ei_flag, "test export/import cred", NULL },
    588  1.1     elric     {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL },
    589  1.1     elric     {"session-enctype",	0, arg_string,	&session_enctype_string, "enctype", NULL },
    590  1.1     elric     {"client-time-offset",	0, arg_integer,	&client_time_offset, "time", NULL },
    591  1.1     elric     {"server-time-offset",	0, arg_integer,	&server_time_offset, "time", NULL },
    592  1.1     elric     {"max-loops",	0, arg_integer,	&max_loops, "time", NULL },
    593  1.1     elric     {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
    594  1.1     elric     {"verbose",	'v',	arg_flag,	&verbose_flag, "verbose", NULL },
    595  1.1     elric     {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
    596  1.1     elric };
    597  1.1     elric 
    598  1.1     elric static void
    599  1.1     elric usage (int ret)
    600  1.1     elric {
    601  1.1     elric     arg_printusage (args, sizeof(args)/sizeof(*args),
    602  1.1     elric 		    NULL, "service@host");
    603  1.1     elric     exit (ret);
    604  1.1     elric }
    605  1.1     elric 
    606  1.1     elric int
    607  1.1     elric main(int argc, char **argv)
    608  1.1     elric {
    609  1.2  christos     int optidx = 0;
    610  1.1     elric     OM_uint32 min_stat, maj_stat;
    611  1.1     elric     gss_ctx_id_t cctx, sctx;
    612  1.1     elric     void *ctx;
    613  1.1     elric     gss_OID nameoid, mechoid, actual_mech, actual_mech2;
    614  1.1     elric     gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL;
    615  1.2  christos     gss_name_t cname = GSS_C_NO_NAME;
    616  1.2  christos     gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER;
    617  1.2  christos     gss_OID_desc oids[4];
    618  1.2  christos     gss_OID_set_desc mechoid_descs;
    619  1.2  christos     gss_OID_set mechoids = GSS_C_NO_OID_SET;
    620  1.1     elric 
    621  1.1     elric     setprogname(argv[0]);
    622  1.1     elric 
    623  1.1     elric     init_o2n();
    624  1.1     elric 
    625  1.1     elric     if (krb5_init_context(&context))
    626  1.1     elric 	errx(1, "krb5_init_context");
    627  1.1     elric 
    628  1.1     elric     cctx = sctx = GSS_C_NO_CONTEXT;
    629  1.1     elric 
    630  1.2  christos     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
    631  1.1     elric 	usage(1);
    632  1.1     elric 
    633  1.1     elric     if (help_flag)
    634  1.1     elric 	usage (0);
    635  1.1     elric 
    636  1.1     elric     if(version_flag){
    637  1.1     elric 	print_version(NULL);
    638  1.1     elric 	exit(0);
    639  1.1     elric     }
    640  1.1     elric 
    641  1.2  christos     argc -= optidx;
    642  1.2  christos     argv += optidx;
    643  1.1     elric 
    644  1.1     elric     if (argc != 1)
    645  1.1     elric 	usage(1);
    646  1.1     elric 
    647  1.1     elric     if (dns_canon_flag != -1)
    648  1.1     elric 	gsskrb5_set_dns_canonicalize(dns_canon_flag);
    649  1.1     elric 
    650  1.1     elric     if (type_string == NULL)
    651  1.1     elric 	nameoid = GSS_C_NT_HOSTBASED_SERVICE;
    652  1.1     elric     else if (strcmp(type_string, "hostbased-service") == 0)
    653  1.1     elric 	nameoid = GSS_C_NT_HOSTBASED_SERVICE;
    654  1.1     elric     else if (strcmp(type_string, "krb5-principal-name") == 0)
    655  1.1     elric 	nameoid = GSS_KRB5_NT_PRINCIPAL_NAME;
    656  1.1     elric     else
    657  1.2  christos 	errx(1, "%s not supported", type_string);
    658  1.1     elric 
    659  1.1     elric     if (mech_string == NULL)
    660  1.1     elric 	mechoid = GSS_KRB5_MECHANISM;
    661  1.1     elric     else
    662  1.1     elric 	mechoid = string_to_oid(mech_string);
    663  1.1     elric 
    664  1.2  christos     if (mechs_string == NULL) {
    665  1.2  christos         /*
    666  1.2  christos          * We ought to be able to use the OID set of the one mechanism
    667  1.2  christos          * OID given.  But there's some breakage that conspires to make
    668  1.2  christos          * that fail though it should succeed:
    669  1.2  christos          *
    670  1.2  christos          *  - the NTLM gss_acquire_cred() refuses to work with
    671  1.2  christos          *    desired_name == GSS_C_NO_NAME
    672  1.2  christos          *  - gss_acquire_cred() with desired_mechs == GSS_C_NO_OID_SET
    673  1.2  christos          *    does work here because we happen to have Kerberos
    674  1.2  christos          *    credentials in check-ntlm, and the subsequent
    675  1.2  christos          *    gss_init_sec_context() call finds no cred element for NTLM
    676  1.2  christos          *    but plows on anyways, surprisingly enough, and then the
    677  1.2  christos          *    NTLM gss_init_sec_context() just works.
    678  1.2  christos          *
    679  1.2  christos          * In summary, there's some breakage in gss_init_sec_context()
    680  1.2  christos          * and some breakage in NTLM that conspires against us here.
    681  1.2  christos          *
    682  1.2  christos          * We work around this in check-ntlm and check-spnego by adding
    683  1.2  christos          * --client-name=user1@${R} to the invocations of this test
    684  1.2  christos          * program that require it.
    685  1.2  christos          */
    686  1.2  christos         oids[0] = *mechoid;
    687  1.2  christos         mechoid_descs.elements = &oids[0];
    688  1.2  christos         mechoid_descs.count = 1;
    689  1.2  christos         mechoids = &mechoid_descs;
    690  1.2  christos     } else {
    691  1.2  christos         string_to_oids(&mechoids, &mechoid_descs,
    692  1.2  christos                        oids, sizeof(oids)/sizeof(oids[0]), mechs_string);
    693  1.2  christos     }
    694  1.2  christos 
    695  1.2  christos     if (gsskrb5_acceptor_identity) {
    696  1.2  christos 	maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity);
    697  1.2  christos 	if (maj_stat)
    698  1.2  christos 	    errx(1, "gsskrb5_acceptor_identity: %s",
    699  1.2  christos 		 gssapi_err(maj_stat, 0, GSS_C_NO_OID));
    700  1.2  christos     }
    701  1.2  christos 
    702  1.2  christos     if (client_password) {
    703  1.2  christos 	credential_data.value = client_password;
    704  1.2  christos 	credential_data.length = strlen(client_password);
    705  1.2  christos     }
    706  1.1     elric 
    707  1.1     elric     if (client_name) {
    708  1.1     elric 	gss_buffer_desc cn;
    709  1.2  christos 
    710  1.1     elric 	cn.value = client_name;
    711  1.1     elric 	cn.length = strlen(client_name);
    712  1.2  christos 
    713  1.1     elric 	maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname);
    714  1.1     elric 	if (maj_stat)
    715  1.1     elric 	    errx(1, "gss_import_name: %s",
    716  1.1     elric 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    717  1.2  christos     }
    718  1.1     elric 
    719  1.2  christos     if (client_password) {
    720  1.2  christos 	maj_stat = gss_acquire_cred_with_password(&min_stat,
    721  1.2  christos 						  cname,
    722  1.2  christos 						  &credential_data,
    723  1.2  christos 						  GSS_C_INDEFINITE,
    724  1.2  christos 						  mechoids,
    725  1.2  christos 						  GSS_C_INITIATE,
    726  1.2  christos 						  &client_cred,
    727  1.2  christos 						  NULL,
    728  1.2  christos 						  NULL);
    729  1.2  christos 	if (GSS_ERROR(maj_stat)) {
    730  1.2  christos             if (mechoids != GSS_C_NO_OID_SET && mechoids->count == 1)
    731  1.2  christos                 mechoid = &mechoids->elements[0];
    732  1.2  christos             else
    733  1.2  christos                 mechoid = GSS_C_NO_OID;
    734  1.2  christos 	    errx(1, "gss_acquire_cred_with_password: %s",
    735  1.2  christos 		 gssapi_err(maj_stat, min_stat, mechoid));
    736  1.2  christos         }
    737  1.2  christos     } else {
    738  1.2  christos 	maj_stat = gss_acquire_cred(&min_stat,
    739  1.2  christos 				    cname,
    740  1.2  christos 				    GSS_C_INDEFINITE,
    741  1.2  christos 				    mechoids,
    742  1.2  christos 				    GSS_C_INITIATE,
    743  1.2  christos 				    &client_cred,
    744  1.2  christos 				    NULL,
    745  1.2  christos 				    NULL);
    746  1.1     elric 	if (GSS_ERROR(maj_stat))
    747  1.2  christos 	    errx(1, "gss_acquire_cred: %s",
    748  1.1     elric 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    749  1.1     elric     }
    750  1.1     elric 
    751  1.1     elric     if (limit_enctype_string) {
    752  1.1     elric 	krb5_error_code ret;
    753  1.1     elric 
    754  1.1     elric 	ret = krb5_string_to_enctype(context,
    755  1.1     elric 				     limit_enctype_string,
    756  1.1     elric 				     &limit_enctype);
    757  1.1     elric 	if (ret)
    758  1.1     elric 	    krb5_err(context, 1, ret, "krb5_string_to_enctype");
    759  1.1     elric     }
    760  1.1     elric 
    761  1.1     elric 
    762  1.1     elric     if (limit_enctype) {
    763  1.1     elric 	if (client_cred == NULL)
    764  1.1     elric 	    errx(1, "client_cred missing");
    765  1.1     elric 
    766  1.1     elric 	maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred,
    767  1.2  christos 						   1, &limit_enctype);
    768  1.1     elric 	if (maj_stat)
    769  1.1     elric 	    errx(1, "gss_krb5_set_allowable_enctypes: %s",
    770  1.1     elric 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
    771  1.1     elric     }
    772  1.1     elric 
    773  1.1     elric     loop(mechoid, nameoid, argv[0], client_cred,
    774  1.1     elric 	 &sctx, &cctx, &actual_mech, &deleg_cred);
    775  1.1     elric 
    776  1.1     elric     if (verbose_flag)
    777  1.1     elric 	printf("resulting mech: %s\n", oid_to_string(actual_mech));
    778  1.1     elric 
    779  1.1     elric     if (ret_mech_string) {
    780  1.1     elric 	gss_OID retoid;
    781  1.1     elric 
    782  1.1     elric 	retoid = string_to_oid(ret_mech_string);
    783  1.1     elric 
    784  1.1     elric 	if (gss_oid_equal(retoid, actual_mech) == 0)
    785  1.1     elric 	    errx(1, "actual_mech mech is not the expected type %s",
    786  1.1     elric 		 ret_mech_string);
    787  1.1     elric     }
    788  1.1     elric 
    789  1.1     elric     /* XXX should be actual_mech */
    790  1.1     elric     if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) {
    791  1.2  christos 	time_t sc_time;
    792  1.1     elric 	gss_buffer_desc authz_data;
    793  1.1     elric 	gss_buffer_desc in, out1, out2;
    794  1.1     elric 	krb5_keyblock *keyblock, *keyblock2;
    795  1.1     elric 	krb5_timestamp now;
    796  1.1     elric 	krb5_error_code ret;
    797  1.1     elric 
    798  1.1     elric 	ret = krb5_timeofday(context, &now);
    799  1.1     elric 	if (ret)
    800  1.1     elric 	    errx(1, "krb5_timeofday failed");
    801  1.2  christos 
    802  1.1     elric 	/* client */
    803  1.1     elric 	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
    804  1.1     elric 						     &cctx,
    805  1.1     elric 						     1, /* version */
    806  1.1     elric 						     &ctx);
    807  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    808  1.1     elric 	    errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
    809  1.1     elric 		 gssapi_err(maj_stat, min_stat, actual_mech));
    810  1.2  christos 
    811  1.2  christos 
    812  1.1     elric 	maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx);
    813  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    814  1.1     elric 	    errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
    815  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    816  1.2  christos 
    817  1.1     elric 	/* server */
    818  1.1     elric 	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
    819  1.1     elric 						     &sctx,
    820  1.1     elric 						     1, /* version */
    821  1.1     elric 						     &ctx);
    822  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    823  1.1     elric 	    errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
    824  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    825  1.1     elric 	maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx);
    826  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    827  1.1     elric 	    errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
    828  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    829  1.1     elric 
    830  1.1     elric  	maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
    831  1.1     elric 							     sctx,
    832  1.2  christos 							     &sc_time);
    833  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    834  1.1     elric 	    errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s",
    835  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    836  1.1     elric 
    837  1.2  christos 	if (sc_time > now)
    838  1.1     elric 	    errx(1, "gsskrb5_extract_authtime_from_sec_context failed: "
    839  1.2  christos 		 "time authtime is before now: %ld %ld",
    840  1.2  christos 		 (long)sc_time, (long)now);
    841  1.1     elric 
    842  1.1     elric  	maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
    843  1.1     elric 						    sctx,
    844  1.1     elric 						    &keyblock);
    845  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    846  1.1     elric 	    errx(1, "gsskrb5_export_service_keyblock failed: %s",
    847  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    848  1.1     elric 
    849  1.1     elric 	krb5_free_keyblock(context, keyblock);
    850  1.1     elric 
    851  1.1     elric  	maj_stat = gsskrb5_get_subkey(&min_stat,
    852  1.1     elric 				      sctx,
    853  1.1     elric 				      &keyblock);
    854  1.1     elric 	if (maj_stat != GSS_S_COMPLETE
    855  1.1     elric 	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
    856  1.1     elric 	    errx(1, "gsskrb5_get_subkey server failed: %s",
    857  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    858  1.1     elric 
    859  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    860  1.1     elric 	    keyblock = NULL;
    861  1.1     elric 	else if (limit_enctype && keyblock->keytype != limit_enctype)
    862  1.1     elric 	    errx(1, "gsskrb5_get_subkey wrong enctype");
    863  1.2  christos 
    864  1.1     elric  	maj_stat = gsskrb5_get_subkey(&min_stat,
    865  1.1     elric 				      cctx,
    866  1.1     elric 				      &keyblock2);
    867  1.1     elric 	if (maj_stat != GSS_S_COMPLETE
    868  1.1     elric 	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
    869  1.1     elric 	    errx(1, "gsskrb5_get_subkey client failed: %s",
    870  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    871  1.1     elric 
    872  1.1     elric 	if (maj_stat != GSS_S_COMPLETE)
    873  1.1     elric 	    keyblock2 = NULL;
    874  1.1     elric 	else if (limit_enctype && keyblock->keytype != limit_enctype)
    875  1.1     elric 	    errx(1, "gsskrb5_get_subkey wrong enctype");
    876  1.1     elric 
    877  1.1     elric 	if (keyblock || keyblock2) {
    878  1.1     elric 	    if (keyblock == NULL)
    879  1.1     elric 		errx(1, "server missing token keyblock");
    880  1.1     elric 	    if (keyblock2 == NULL)
    881  1.1     elric 		errx(1, "client missing token keyblock");
    882  1.1     elric 
    883  1.1     elric 	    if (keyblock->keytype != keyblock2->keytype)
    884  1.1     elric 		errx(1, "enctype mismatch");
    885  1.1     elric 	    if (keyblock->keyvalue.length != keyblock2->keyvalue.length)
    886  1.1     elric 		errx(1, "key length mismatch");
    887  1.1     elric 	    if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data,
    888  1.1     elric 		       keyblock2->keyvalue.length) != 0)
    889  1.1     elric 		errx(1, "key data mismatch");
    890  1.1     elric 	}
    891  1.1     elric 
    892  1.1     elric 	if (session_enctype_string) {
    893  1.1     elric 	    krb5_enctype enctype;
    894  1.1     elric 
    895  1.1     elric 	    ret = krb5_string_to_enctype(context,
    896  1.1     elric 					 session_enctype_string,
    897  1.1     elric 					 &enctype);
    898  1.2  christos 
    899  1.1     elric 	    if (ret)
    900  1.1     elric 		krb5_err(context, 1, ret, "krb5_string_to_enctype");
    901  1.1     elric 
    902  1.1     elric 	    if (enctype != keyblock->keytype)
    903  1.1     elric 		errx(1, "keytype is not the expected %d != %d",
    904  1.1     elric 		     (int)enctype, (int)keyblock2->keytype);
    905  1.1     elric 	}
    906  1.1     elric 
    907  1.1     elric 	if (keyblock)
    908  1.1     elric 	    krb5_free_keyblock(context, keyblock);
    909  1.1     elric 	if (keyblock2)
    910  1.1     elric 	    krb5_free_keyblock(context, keyblock2);
    911  1.1     elric 
    912  1.1     elric  	maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
    913  1.1     elric 						sctx,
    914  1.1     elric 						&keyblock);
    915  1.1     elric 	if (maj_stat != GSS_S_COMPLETE
    916  1.1     elric 	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
    917  1.1     elric 	    errx(1, "gsskrb5_get_initiator_subkey failed: %s",
    918  1.1     elric 		     gssapi_err(maj_stat, min_stat, actual_mech));
    919  1.1     elric 
    920  1.1     elric 	if (maj_stat == GSS_S_COMPLETE) {
    921  1.1     elric 
    922  1.1     elric 	    if (limit_enctype && keyblock->keytype != limit_enctype)
    923  1.1     elric 		errx(1, "gsskrb5_get_initiator_subkey wrong enctype");
    924  1.1     elric 	    krb5_free_keyblock(context, keyblock);
    925  1.1     elric 	}
    926  1.1     elric 
    927  1.1     elric  	maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
    928  1.1     elric 							       sctx,
    929  1.1     elric 							       128,
    930  1.1     elric 							       &authz_data);
    931  1.1     elric 	if (maj_stat == GSS_S_COMPLETE)
    932  1.1     elric 	    gss_release_buffer(&min_stat, &authz_data);
    933  1.1     elric 
    934  1.1     elric 
    935  1.1     elric 	memset(&out1, 0, sizeof(out1));
    936  1.1     elric 	memset(&out2, 0, sizeof(out2));
    937  1.1     elric 
    938  1.1     elric 	in.value = "foo";
    939  1.1     elric 	in.length = 3;
    940  1.1     elric 
    941  1.1     elric 	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
    942  1.1     elric 			  100, &out1);
    943  1.1     elric 	gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in,
    944  1.1     elric 			  100, &out2);
    945  1.1     elric 
    946  1.1     elric 	if (out1.length != out2.length)
    947  1.1     elric 	    errx(1, "prf len mismatch");
    948  1.3  christos 	if (out1.length && memcmp(out1.value, out2.value, out1.length) != 0)
    949  1.1     elric 	    errx(1, "prf data mismatch");
    950  1.2  christos 
    951  1.1     elric 	gss_release_buffer(&min_stat, &out1);
    952  1.1     elric 
    953  1.1     elric 	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
    954  1.1     elric 			  100, &out1);
    955  1.1     elric 
    956  1.1     elric 	if (out1.length != out2.length)
    957  1.1     elric 	    errx(1, "prf len mismatch");
    958  1.3  christos 	if (out1.length && memcmp(out1.value, out2.value, out1.length) != 0)
    959  1.1     elric 	    errx(1, "prf data mismatch");
    960  1.1     elric 
    961  1.1     elric 	gss_release_buffer(&min_stat, &out1);
    962  1.1     elric 	gss_release_buffer(&min_stat, &out2);
    963  1.1     elric 
    964  1.1     elric 	in.value = "bar";
    965  1.1     elric 	in.length = 3;
    966  1.1     elric 
    967  1.1     elric 	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in,
    968  1.1     elric 			  100, &out1);
    969  1.1     elric 	gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in,
    970  1.1     elric 			  100, &out2);
    971  1.1     elric 
    972  1.1     elric 	if (out1.length != out2.length)
    973  1.1     elric 	    errx(1, "prf len mismatch");
    974  1.1     elric 	if (memcmp(out1.value, out2.value, out1.length) != 0)
    975  1.1     elric 	    errx(1, "prf data mismatch");
    976  1.1     elric 
    977  1.1     elric 	gss_release_buffer(&min_stat, &out1);
    978  1.1     elric 	gss_release_buffer(&min_stat, &out2);
    979  1.1     elric 
    980  1.1     elric 	wrapunwrap_flag = 1;
    981  1.1     elric 	getverifymic_flag = 1;
    982  1.1     elric     }
    983  1.1     elric 
    984  1.1     elric     if (wrapunwrap_flag) {
    985  1.1     elric 	wrapunwrap(cctx, sctx, 0, actual_mech);
    986  1.1     elric 	wrapunwrap(cctx, sctx, 1, actual_mech);
    987  1.1     elric 	wrapunwrap(sctx, cctx, 0, actual_mech);
    988  1.1     elric 	wrapunwrap(sctx, cctx, 1, actual_mech);
    989  1.1     elric     }
    990  1.1     elric 
    991  1.1     elric     if (iov_flag) {
    992  1.1     elric 	wrapunwrap_iov(cctx, sctx, 0, actual_mech);
    993  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
    994  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
    995  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
    996  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
    997  1.1     elric 
    998  1.1     elric 	wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
    999  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
   1000  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
   1001  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
   1002  1.1     elric 
   1003  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1004  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1005  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1006  1.1     elric 
   1007  1.1     elric /* works */
   1008  1.1     elric 	wrapunwrap_iov(cctx, sctx, 0, actual_mech);
   1009  1.1     elric 	wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
   1010  1.1     elric 
   1011  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
   1012  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
   1013  1.1     elric 
   1014  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech);
   1015  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1016  1.1     elric 
   1017  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
   1018  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1019  1.1     elric 
   1020  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
   1021  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
   1022  1.1     elric 
   1023  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
   1024  1.1     elric 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
   1025  1.1     elric     }
   1026  1.1     elric 
   1027  1.2  christos     if (aead_flag) {
   1028  1.2  christos 	wrapunwrap_aead(cctx, sctx, 0, actual_mech);
   1029  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech);
   1030  1.2  christos 
   1031  1.2  christos 	wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech);
   1032  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
   1033  1.2  christos 
   1034  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1035  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1036  1.2  christos 
   1037  1.2  christos 	wrapunwrap_aead(cctx, sctx, 0, actual_mech);
   1038  1.2  christos 	wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech);
   1039  1.2  christos 
   1040  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech);
   1041  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
   1042  1.2  christos 
   1043  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY, actual_mech);
   1044  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1045  1.2  christos 
   1046  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
   1047  1.2  christos 	wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
   1048  1.2  christos     }
   1049  1.2  christos 
   1050  1.1     elric     if (getverifymic_flag) {
   1051  1.1     elric 	getverifymic(cctx, sctx, actual_mech);
   1052  1.1     elric 	getverifymic(cctx, sctx, actual_mech);
   1053  1.1     elric 	getverifymic(sctx, cctx, actual_mech);
   1054  1.1     elric 	getverifymic(sctx, cctx, actual_mech);
   1055  1.1     elric     }
   1056  1.1     elric 
   1057  1.1     elric 
   1058  1.1     elric     gss_delete_sec_context(&min_stat, &cctx, NULL);
   1059  1.1     elric     gss_delete_sec_context(&min_stat, &sctx, NULL);
   1060  1.1     elric 
   1061  1.1     elric     if (deleg_cred != GSS_C_NO_CREDENTIAL) {
   1062  1.1     elric 	gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL;
   1063  1.1     elric 	gss_buffer_desc cb;
   1064  1.1     elric 
   1065  1.1     elric 	if (verbose_flag)
   1066  1.2  christos 	    printf("checking actual mech (%s) on delegated cred\n",
   1067  1.1     elric 		   oid_to_string(actual_mech));
   1068  1.1     elric 	loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2);
   1069  1.1     elric 
   1070  1.1     elric 	gss_delete_sec_context(&min_stat, &cctx, NULL);
   1071  1.1     elric 	gss_delete_sec_context(&min_stat, &sctx, NULL);
   1072  1.1     elric 
   1073  1.1     elric 	gss_release_cred(&min_stat, &cred2);
   1074  1.1     elric 
   1075  1.2  christos #if 0
   1076  1.2  christos         /*
   1077  1.2  christos          * XXX We can't do this.  Delegated credentials only work with
   1078  1.2  christos          * the actual_mech.  We could gss_store_cred the delegated
   1079  1.2  christos          * credentials *then* gss_add/acquire_cred() with SPNEGO, then
   1080  1.2  christos          * we could try loop() with those credentials.
   1081  1.2  christos          */
   1082  1.1     elric 	/* try again using SPNEGO */
   1083  1.1     elric 	if (verbose_flag)
   1084  1.1     elric 	    printf("checking spnego on delegated cred\n");
   1085  1.1     elric 	loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx,
   1086  1.1     elric 	     &actual_mech2, &cred2);
   1087  1.1     elric 
   1088  1.1     elric 	gss_delete_sec_context(&min_stat, &cctx, NULL);
   1089  1.1     elric 	gss_delete_sec_context(&min_stat, &sctx, NULL);
   1090  1.1     elric 
   1091  1.1     elric 	gss_release_cred(&min_stat, &cred2);
   1092  1.2  christos #endif
   1093  1.1     elric 
   1094  1.1     elric 	/* check export/import */
   1095  1.1     elric 	if (ei_flag) {
   1096  1.1     elric 
   1097  1.1     elric 	    maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb);
   1098  1.1     elric 	    if (maj_stat != GSS_S_COMPLETE)
   1099  1.1     elric 		errx(1, "export failed: %s",
   1100  1.1     elric 		     gssapi_err(maj_stat, min_stat, NULL));
   1101  1.1     elric 
   1102  1.1     elric 	    maj_stat = gss_import_cred(&min_stat, &cb, &cred2);
   1103  1.1     elric 	    if (maj_stat != GSS_S_COMPLETE)
   1104  1.1     elric 		errx(1, "import failed: %s",
   1105  1.1     elric 		     gssapi_err(maj_stat, min_stat, NULL));
   1106  1.2  christos 
   1107  1.1     elric 	    gss_release_buffer(&min_stat, &cb);
   1108  1.1     elric 	    gss_release_cred(&min_stat, &deleg_cred);
   1109  1.2  christos 
   1110  1.1     elric 	    if (verbose_flag)
   1111  1.2  christos 		printf("checking actual mech (%s) on export/imported cred\n",
   1112  1.1     elric 		       oid_to_string(actual_mech));
   1113  1.1     elric 	    loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx,
   1114  1.1     elric 		 &actual_mech2, &deleg_cred);
   1115  1.1     elric 
   1116  1.1     elric 	    gss_release_cred(&min_stat, &deleg_cred);
   1117  1.1     elric 
   1118  1.1     elric 	    gss_delete_sec_context(&min_stat, &cctx, NULL);
   1119  1.1     elric 	    gss_delete_sec_context(&min_stat, &sctx, NULL);
   1120  1.1     elric 
   1121  1.2  christos #if 0
   1122  1.2  christos             /* XXX See above */
   1123  1.1     elric 	    /* try again using SPNEGO */
   1124  1.1     elric 	    if (verbose_flag)
   1125  1.1     elric 		printf("checking SPNEGO on export/imported cred\n");
   1126  1.1     elric 	    loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx,
   1127  1.1     elric 		 &actual_mech2, &deleg_cred);
   1128  1.1     elric 
   1129  1.1     elric 	    gss_release_cred(&min_stat, &deleg_cred);
   1130  1.2  christos 
   1131  1.1     elric 	    gss_delete_sec_context(&min_stat, &cctx, NULL);
   1132  1.1     elric 	    gss_delete_sec_context(&min_stat, &sctx, NULL);
   1133  1.2  christos #endif
   1134  1.1     elric 
   1135  1.1     elric 	    gss_release_cred(&min_stat, &cred2);
   1136  1.1     elric 
   1137  1.1     elric 	} else  {
   1138  1.1     elric 	    gss_release_cred(&min_stat, &deleg_cred);
   1139  1.1     elric 	}
   1140  1.1     elric 
   1141  1.1     elric     }
   1142  1.1     elric 
   1143  1.1     elric     empty_release();
   1144  1.2  christos 
   1145  1.1     elric     krb5_free_context(context);
   1146  1.1     elric 
   1147  1.1     elric     return 0;
   1148  1.1     elric }
   1149