1bbd80c28SJacques Vidrine /* 2*ae771770SStanislav Sedov * Copyright (c) 2003-2007 Kungliga Tekniska Högskolan 3bbd80c28SJacques Vidrine * (Royal Institute of Technology, Stockholm, Sweden). 4bbd80c28SJacques Vidrine * All rights reserved. 5bbd80c28SJacques Vidrine * 6bbd80c28SJacques Vidrine * Redistribution and use in source and binary forms, with or without 7bbd80c28SJacques Vidrine * modification, are permitted provided that the following conditions 8bbd80c28SJacques Vidrine * are met: 9bbd80c28SJacques Vidrine * 10bbd80c28SJacques Vidrine * 1. Redistributions of source code must retain the above copyright 11bbd80c28SJacques Vidrine * notice, this list of conditions and the following disclaimer. 12bbd80c28SJacques Vidrine * 13bbd80c28SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright 14bbd80c28SJacques Vidrine * notice, this list of conditions and the following disclaimer in the 15bbd80c28SJacques Vidrine * documentation and/or other materials provided with the distribution. 16bbd80c28SJacques Vidrine * 17bbd80c28SJacques Vidrine * 3. Neither the name of KTH nor the names of its contributors may be 18bbd80c28SJacques Vidrine * used to endorse or promote products derived from this software without 19bbd80c28SJacques Vidrine * specific prior written permission. 20bbd80c28SJacques Vidrine * 21bbd80c28SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22bbd80c28SJacques Vidrine * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23bbd80c28SJacques Vidrine * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24bbd80c28SJacques Vidrine * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25bbd80c28SJacques Vidrine * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26bbd80c28SJacques Vidrine * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27bbd80c28SJacques Vidrine * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28bbd80c28SJacques Vidrine * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29bbd80c28SJacques Vidrine * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30bbd80c28SJacques Vidrine * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31c19800e8SDoug Rabson * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32c19800e8SDoug Rabson */ 33bbd80c28SJacques Vidrine 34c19800e8SDoug Rabson #ifdef HAVE_CONFIG_H 35c19800e8SDoug Rabson #include <config.h> 36c19800e8SDoug Rabson #endif 37c19800e8SDoug Rabson 38*ae771770SStanislav Sedov #include <roken.h> 39c19800e8SDoug Rabson #include <stdio.h> 40c19800e8SDoug Rabson #include <stdlib.h> 41c19800e8SDoug Rabson #include <string.h> 42c19800e8SDoug Rabson #include <stdarg.h> 43c19800e8SDoug Rabson #include <gssapi.h> 44*ae771770SStanislav Sedov #include <gssapi_krb5.h> 45*ae771770SStanislav Sedov #include <gssapi_spnego.h> 46bbd80c28SJacques Vidrine #include <err.h> 47c19800e8SDoug Rabson #include <getarg.h> 48bbd80c28SJacques Vidrine 49c19800e8SDoug Rabson #include "test_common.h" 50c19800e8SDoug Rabson 51bbd80c28SJacques Vidrine static void 52bbd80c28SJacques Vidrine print_time(OM_uint32 time_rec) 53bbd80c28SJacques Vidrine { 54bbd80c28SJacques Vidrine if (time_rec == GSS_C_INDEFINITE) { 55bbd80c28SJacques Vidrine printf("cred never expire\n"); 56bbd80c28SJacques Vidrine } else { 57c19800e8SDoug Rabson time_t t = time_rec + time(NULL); 58bbd80c28SJacques Vidrine printf("expiration time: %s", ctime(&t)); 59bbd80c28SJacques Vidrine } 60bbd80c28SJacques Vidrine } 61bbd80c28SJacques Vidrine 62c19800e8SDoug Rabson #if 0 63c19800e8SDoug Rabson 64c19800e8SDoug Rabson static void 65c19800e8SDoug Rabson test_add(gss_cred_id_t cred_handle) 66bbd80c28SJacques Vidrine { 67bbd80c28SJacques Vidrine OM_uint32 major_status, minor_status; 68c19800e8SDoug Rabson gss_cred_id_t copy_cred; 69bbd80c28SJacques Vidrine OM_uint32 time_rec; 70bbd80c28SJacques Vidrine 71bbd80c28SJacques Vidrine major_status = gss_add_cred (&minor_status, 72bbd80c28SJacques Vidrine cred_handle, 73bbd80c28SJacques Vidrine GSS_C_NO_NAME, 74bbd80c28SJacques Vidrine GSS_KRB5_MECHANISM, 75bbd80c28SJacques Vidrine GSS_C_INITIATE, 76bbd80c28SJacques Vidrine 0, 77bbd80c28SJacques Vidrine 0, 78bbd80c28SJacques Vidrine ©_cred, 79bbd80c28SJacques Vidrine NULL, 80bbd80c28SJacques Vidrine &time_rec, 81bbd80c28SJacques Vidrine NULL); 82bbd80c28SJacques Vidrine 83bbd80c28SJacques Vidrine if (GSS_ERROR(major_status)) 84bbd80c28SJacques Vidrine errx(1, "add_cred failed"); 85bbd80c28SJacques Vidrine 86bbd80c28SJacques Vidrine print_time(time_rec); 87bbd80c28SJacques Vidrine 88bbd80c28SJacques Vidrine major_status = gss_release_cred(&minor_status, 89bbd80c28SJacques Vidrine ©_cred); 90bbd80c28SJacques Vidrine if (GSS_ERROR(major_status)) 91bbd80c28SJacques Vidrine errx(1, "release_cred failed"); 92c19800e8SDoug Rabson } 93c19800e8SDoug Rabson 94c19800e8SDoug Rabson static void 95c19800e8SDoug Rabson copy_cred(void) 96c19800e8SDoug Rabson { 97c19800e8SDoug Rabson OM_uint32 major_status, minor_status; 98c19800e8SDoug Rabson gss_cred_id_t cred_handle; 99c19800e8SDoug Rabson OM_uint32 time_rec; 100c19800e8SDoug Rabson 101c19800e8SDoug Rabson major_status = gss_acquire_cred(&minor_status, 102c19800e8SDoug Rabson GSS_C_NO_NAME, 103c19800e8SDoug Rabson 0, 104c19800e8SDoug Rabson NULL, 105c19800e8SDoug Rabson GSS_C_INITIATE, 106c19800e8SDoug Rabson &cred_handle, 107c19800e8SDoug Rabson NULL, 108c19800e8SDoug Rabson &time_rec); 109c19800e8SDoug Rabson if (GSS_ERROR(major_status)) 110c19800e8SDoug Rabson errx(1, "acquire_cred failed"); 111c19800e8SDoug Rabson 112c19800e8SDoug Rabson print_time(time_rec); 113c19800e8SDoug Rabson 114c19800e8SDoug Rabson test_add(cred_handle); 115c19800e8SDoug Rabson test_add(cred_handle); 116c19800e8SDoug Rabson test_add(cred_handle); 117c19800e8SDoug Rabson 118c19800e8SDoug Rabson major_status = gss_release_cred(&minor_status, 119c19800e8SDoug Rabson &cred_handle); 120c19800e8SDoug Rabson if (GSS_ERROR(major_status)) 121c19800e8SDoug Rabson errx(1, "release_cred failed"); 122c19800e8SDoug Rabson } 123c19800e8SDoug Rabson #endif 124c19800e8SDoug Rabson 125*ae771770SStanislav Sedov static gss_cred_id_t 126c19800e8SDoug Rabson acquire_cred_service(const char *service, 127c19800e8SDoug Rabson gss_OID nametype, 128*ae771770SStanislav Sedov gss_OID_set oidset, 129c19800e8SDoug Rabson int flags) 130c19800e8SDoug Rabson { 131c19800e8SDoug Rabson OM_uint32 major_status, minor_status; 132c19800e8SDoug Rabson gss_cred_id_t cred_handle; 133c19800e8SDoug Rabson OM_uint32 time_rec; 134c19800e8SDoug Rabson gss_buffer_desc name_buffer; 135c19800e8SDoug Rabson gss_name_t name = GSS_C_NO_NAME; 136c19800e8SDoug Rabson 137c19800e8SDoug Rabson if (service) { 138c19800e8SDoug Rabson name_buffer.value = rk_UNCONST(service); 139c19800e8SDoug Rabson name_buffer.length = strlen(service); 140c19800e8SDoug Rabson 141c19800e8SDoug Rabson major_status = gss_import_name(&minor_status, 142c19800e8SDoug Rabson &name_buffer, 143c19800e8SDoug Rabson nametype, 144c19800e8SDoug Rabson &name); 145c19800e8SDoug Rabson if (GSS_ERROR(major_status)) 146c19800e8SDoug Rabson errx(1, "import_name failed"); 147c19800e8SDoug Rabson } 148c19800e8SDoug Rabson 149c19800e8SDoug Rabson major_status = gss_acquire_cred(&minor_status, 150c19800e8SDoug Rabson name, 151c19800e8SDoug Rabson 0, 152*ae771770SStanislav Sedov oidset, 153c19800e8SDoug Rabson flags, 154c19800e8SDoug Rabson &cred_handle, 155c19800e8SDoug Rabson NULL, 156c19800e8SDoug Rabson &time_rec); 157c19800e8SDoug Rabson if (GSS_ERROR(major_status)) { 158c19800e8SDoug Rabson warnx("acquire_cred failed: %s", 159c19800e8SDoug Rabson gssapi_err(major_status, minor_status, GSS_C_NO_OID)); 160c19800e8SDoug Rabson } else { 161c19800e8SDoug Rabson print_time(time_rec); 162c19800e8SDoug Rabson gss_release_cred(&minor_status, &cred_handle); 163c19800e8SDoug Rabson } 164c19800e8SDoug Rabson 165c19800e8SDoug Rabson if (name != GSS_C_NO_NAME) 166c19800e8SDoug Rabson gss_release_name(&minor_status, &name); 167c19800e8SDoug Rabson 168c19800e8SDoug Rabson if (GSS_ERROR(major_status)) 169c19800e8SDoug Rabson exit(1); 170*ae771770SStanislav Sedov 171*ae771770SStanislav Sedov return cred_handle; 172c19800e8SDoug Rabson } 173c19800e8SDoug Rabson 174c19800e8SDoug Rabson static int version_flag = 0; 175c19800e8SDoug Rabson static int help_flag = 0; 176*ae771770SStanislav Sedov static int kerberos_flag = 0; 177*ae771770SStanislav Sedov static int enctype = 0; 178c19800e8SDoug Rabson static char *acquire_name; 179c19800e8SDoug Rabson static char *acquire_type; 180*ae771770SStanislav Sedov static char *target_name; 181c19800e8SDoug Rabson static char *name_type; 182c19800e8SDoug Rabson static char *ccache; 183*ae771770SStanislav Sedov static int num_loops = 1; 184c19800e8SDoug Rabson 185c19800e8SDoug Rabson static struct getargs args[] = { 186c19800e8SDoug Rabson {"acquire-name", 0, arg_string, &acquire_name, "name", NULL }, 187c19800e8SDoug Rabson {"acquire-type", 0, arg_string, &acquire_type, "type", NULL }, 188*ae771770SStanislav Sedov {"enctype", 0, arg_integer, &enctype, "enctype-num", NULL }, 189*ae771770SStanislav Sedov {"loops", 0, arg_integer, &num_loops, "enctype-num", NULL }, 190*ae771770SStanislav Sedov {"kerberos", 0, arg_flag, &kerberos_flag, "enctype-num", NULL }, 191*ae771770SStanislav Sedov {"target-name", 0, arg_string, &target_name, "name", NULL }, 192c19800e8SDoug Rabson {"ccache", 0, arg_string, &ccache, "name", NULL }, 193c19800e8SDoug Rabson {"name-type", 0, arg_string, &name_type, "type", NULL }, 194c19800e8SDoug Rabson {"version", 0, arg_flag, &version_flag, "print version", NULL }, 195c19800e8SDoug Rabson {"help", 0, arg_flag, &help_flag, NULL, NULL } 196c19800e8SDoug Rabson }; 197c19800e8SDoug Rabson 198c19800e8SDoug Rabson static void 199c19800e8SDoug Rabson usage (int ret) 200c19800e8SDoug Rabson { 201c19800e8SDoug Rabson arg_printusage (args, sizeof(args)/sizeof(*args), NULL, ""); 202c19800e8SDoug Rabson exit (ret); 203c19800e8SDoug Rabson } 204c19800e8SDoug Rabson 205c19800e8SDoug Rabson int 206c19800e8SDoug Rabson main(int argc, char **argv) 207c19800e8SDoug Rabson { 208*ae771770SStanislav Sedov gss_OID_set oidset = GSS_C_NULL_OID_SET; 209*ae771770SStanislav Sedov gss_OID mechoid = GSS_C_NO_OID; 210*ae771770SStanislav Sedov OM_uint32 maj_stat, min_stat; 211*ae771770SStanislav Sedov gss_cred_id_t cred; 212*ae771770SStanislav Sedov gss_name_t target = GSS_C_NO_NAME; 213*ae771770SStanislav Sedov int i, optidx = 0; 214c19800e8SDoug Rabson OM_uint32 flag; 215c19800e8SDoug Rabson gss_OID type; 216c19800e8SDoug Rabson 217c19800e8SDoug Rabson setprogname(argv[0]); 218c19800e8SDoug Rabson if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 219c19800e8SDoug Rabson usage(1); 220c19800e8SDoug Rabson 221c19800e8SDoug Rabson if (help_flag) 222c19800e8SDoug Rabson usage (0); 223c19800e8SDoug Rabson 224c19800e8SDoug Rabson if(version_flag){ 225c19800e8SDoug Rabson print_version(NULL); 226c19800e8SDoug Rabson exit(0); 227c19800e8SDoug Rabson } 228c19800e8SDoug Rabson 229c19800e8SDoug Rabson argc -= optidx; 230c19800e8SDoug Rabson argv += optidx; 231c19800e8SDoug Rabson 232c19800e8SDoug Rabson if (argc != 0) 233c19800e8SDoug Rabson usage(1); 234c19800e8SDoug Rabson 235c19800e8SDoug Rabson if (acquire_type) { 236c19800e8SDoug Rabson if (strcasecmp(acquire_type, "both") == 0) 237c19800e8SDoug Rabson flag = GSS_C_BOTH; 238c19800e8SDoug Rabson else if (strcasecmp(acquire_type, "accept") == 0) 239c19800e8SDoug Rabson flag = GSS_C_ACCEPT; 240c19800e8SDoug Rabson else if (strcasecmp(acquire_type, "initiate") == 0) 241c19800e8SDoug Rabson flag = GSS_C_INITIATE; 242c19800e8SDoug Rabson else 243c19800e8SDoug Rabson errx(1, "unknown type %s", acquire_type); 244c19800e8SDoug Rabson } else 245c19800e8SDoug Rabson flag = GSS_C_ACCEPT; 246c19800e8SDoug Rabson 247c19800e8SDoug Rabson if (name_type) { 248c19800e8SDoug Rabson if (strcasecmp("hostbased-service", name_type) == 0) 249c19800e8SDoug Rabson type = GSS_C_NT_HOSTBASED_SERVICE; 250c19800e8SDoug Rabson else if (strcasecmp("user-name", name_type) == 0) 251c19800e8SDoug Rabson type = GSS_C_NT_USER_NAME; 252c19800e8SDoug Rabson else 253c19800e8SDoug Rabson errx(1, "unknown name type %s", name_type); 254c19800e8SDoug Rabson } else 255c19800e8SDoug Rabson type = GSS_C_NT_HOSTBASED_SERVICE; 256c19800e8SDoug Rabson 257c19800e8SDoug Rabson if (ccache) { 258*ae771770SStanislav Sedov maj_stat = gss_krb5_ccache_name(&min_stat, ccache, NULL); 259*ae771770SStanislav Sedov if (GSS_ERROR(maj_stat)) 260c19800e8SDoug Rabson errx(1, "gss_krb5_ccache_name %s", 261*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 262c19800e8SDoug Rabson } 263c19800e8SDoug Rabson 264*ae771770SStanislav Sedov if (kerberos_flag) { 265*ae771770SStanislav Sedov mechoid = GSS_KRB5_MECHANISM; 266*ae771770SStanislav Sedov 267*ae771770SStanislav Sedov maj_stat = gss_create_empty_oid_set(&min_stat, &oidset); 268*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE) 269*ae771770SStanislav Sedov errx(1, "gss_create_empty_oid_set: %s", 270*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 271*ae771770SStanislav Sedov 272*ae771770SStanislav Sedov maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset); 273*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE) 274*ae771770SStanislav Sedov errx(1, "gss_add_oid_set_member: %s", 275*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 276*ae771770SStanislav Sedov } 277*ae771770SStanislav Sedov 278*ae771770SStanislav Sedov if (target_name) { 279*ae771770SStanislav Sedov gss_buffer_desc name; 280*ae771770SStanislav Sedov 281*ae771770SStanislav Sedov name.value = target_name; 282*ae771770SStanislav Sedov name.length = strlen(target_name); 283*ae771770SStanislav Sedov maj_stat = gss_import_name(&min_stat, &name, 284*ae771770SStanislav Sedov GSS_C_NT_HOSTBASED_SERVICE, &target); 285*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE) 286*ae771770SStanislav Sedov errx(1, "gss_import_name: %s", 287*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 288*ae771770SStanislav Sedov } 289*ae771770SStanislav Sedov 290*ae771770SStanislav Sedov for (i = 0; i < num_loops; i++) { 291*ae771770SStanislav Sedov 292*ae771770SStanislav Sedov cred = acquire_cred_service(acquire_name, type, oidset, flag); 293*ae771770SStanislav Sedov 294*ae771770SStanislav Sedov if (enctype) { 295*ae771770SStanislav Sedov int32_t enctypelist = enctype; 296*ae771770SStanislav Sedov 297*ae771770SStanislav Sedov maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred, 298*ae771770SStanislav Sedov 1, &enctypelist); 299*ae771770SStanislav Sedov if (maj_stat) 300*ae771770SStanislav Sedov errx(1, "gss_krb5_set_allowable_enctypes: %s", 301*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 302*ae771770SStanislav Sedov } 303*ae771770SStanislav Sedov 304*ae771770SStanislav Sedov if (target) { 305*ae771770SStanislav Sedov gss_ctx_id_t context = GSS_C_NO_CONTEXT; 306*ae771770SStanislav Sedov gss_buffer_desc out; 307*ae771770SStanislav Sedov 308*ae771770SStanislav Sedov out.length = 0; 309*ae771770SStanislav Sedov out.value = NULL; 310*ae771770SStanislav Sedov 311*ae771770SStanislav Sedov maj_stat = gss_init_sec_context(&min_stat, 312*ae771770SStanislav Sedov cred, &context, 313*ae771770SStanislav Sedov target, mechoid, 314*ae771770SStanislav Sedov GSS_C_MUTUAL_FLAG, 0, NULL, 315*ae771770SStanislav Sedov GSS_C_NO_BUFFER, NULL, 316*ae771770SStanislav Sedov &out, NULL, NULL); 317*ae771770SStanislav Sedov if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) 318*ae771770SStanislav Sedov errx(1, "init_sec_context failed: %s", 319*ae771770SStanislav Sedov gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 320*ae771770SStanislav Sedov 321*ae771770SStanislav Sedov gss_release_buffer(&min_stat, &out); 322*ae771770SStanislav Sedov gss_delete_sec_context(&min_stat, &context, NULL); 323*ae771770SStanislav Sedov } 324*ae771770SStanislav Sedov gss_release_cred(&min_stat, &cred); 325*ae771770SStanislav Sedov } 326*ae771770SStanislav Sedov 327bbd80c28SJacques Vidrine 328bbd80c28SJacques Vidrine return 0; 329bbd80c28SJacques Vidrine } 330