1120945Snectar/* 2233294Sstas * Copyright (c) 2003-2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5120945Snectar * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9120945Snectar * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12120945Snectar * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16120945Snectar * 17120945Snectar * 3. Neither the name of KTH nor the names of its contributors may be 18120945Snectar * used to endorse or promote products derived from this software without 19120945Snectar * specific prior written permission. 20120945Snectar * 21120945Snectar * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22120945Snectar * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23120945Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24120945Snectar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25120945Snectar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26120945Snectar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27120945Snectar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28120945Snectar * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29120945Snectar * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30120945Snectar * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31178825Sdfr * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32178825Sdfr */ 33120945Snectar 34178825Sdfr#ifdef HAVE_CONFIG_H 35178825Sdfr#include <config.h> 36178825Sdfr#endif 37178825Sdfr 38233294Sstas#include <roken.h> 39178825Sdfr#include <stdio.h> 40178825Sdfr#include <stdlib.h> 41178825Sdfr#include <string.h> 42178825Sdfr#include <stdarg.h> 43178825Sdfr#include <gssapi.h> 44233294Sstas#include <gssapi_krb5.h> 45233294Sstas#include <gssapi_spnego.h> 46120945Snectar#include <err.h> 47178825Sdfr#include <getarg.h> 48120945Snectar 49178825Sdfr#include "test_common.h" 50120945Snectar 51120945Snectarstatic void 52120945Snectarprint_time(OM_uint32 time_rec) 53120945Snectar{ 54120945Snectar if (time_rec == GSS_C_INDEFINITE) { 55120945Snectar printf("cred never expire\n"); 56120945Snectar } else { 57178825Sdfr time_t t = time_rec + time(NULL); 58120945Snectar printf("expiration time: %s", ctime(&t)); 59120945Snectar } 60120945Snectar} 61120945Snectar 62178825Sdfr#if 0 63178825Sdfr 64178825Sdfrstatic void 65178825Sdfrtest_add(gss_cred_id_t cred_handle) 66120945Snectar{ 67120945Snectar OM_uint32 major_status, minor_status; 68178825Sdfr gss_cred_id_t copy_cred; 69120945Snectar OM_uint32 time_rec; 70120945Snectar 71120945Snectar major_status = gss_add_cred (&minor_status, 72120945Snectar cred_handle, 73120945Snectar GSS_C_NO_NAME, 74120945Snectar GSS_KRB5_MECHANISM, 75120945Snectar GSS_C_INITIATE, 76120945Snectar 0, 77120945Snectar 0, 78120945Snectar ©_cred, 79120945Snectar NULL, 80120945Snectar &time_rec, 81120945Snectar NULL); 82233294Sstas 83120945Snectar if (GSS_ERROR(major_status)) 84120945Snectar errx(1, "add_cred failed"); 85120945Snectar 86120945Snectar print_time(time_rec); 87120945Snectar 88120945Snectar major_status = gss_release_cred(&minor_status, 89178825Sdfr ©_cred); 90120945Snectar if (GSS_ERROR(major_status)) 91120945Snectar errx(1, "release_cred failed"); 92178825Sdfr} 93120945Snectar 94178825Sdfrstatic void 95178825Sdfrcopy_cred(void) 96178825Sdfr{ 97178825Sdfr OM_uint32 major_status, minor_status; 98178825Sdfr gss_cred_id_t cred_handle; 99178825Sdfr OM_uint32 time_rec; 100178825Sdfr 101233294Sstas major_status = gss_acquire_cred(&minor_status, 102178825Sdfr GSS_C_NO_NAME, 103178825Sdfr 0, 104178825Sdfr NULL, 105178825Sdfr GSS_C_INITIATE, 106178825Sdfr &cred_handle, 107178825Sdfr NULL, 108178825Sdfr &time_rec); 109178825Sdfr if (GSS_ERROR(major_status)) 110178825Sdfr errx(1, "acquire_cred failed"); 111233294Sstas 112178825Sdfr print_time(time_rec); 113178825Sdfr 114178825Sdfr test_add(cred_handle); 115178825Sdfr test_add(cred_handle); 116178825Sdfr test_add(cred_handle); 117178825Sdfr 118120945Snectar major_status = gss_release_cred(&minor_status, 119178825Sdfr &cred_handle); 120120945Snectar if (GSS_ERROR(major_status)) 121120945Snectar errx(1, "release_cred failed"); 122178825Sdfr} 123178825Sdfr#endif 124120945Snectar 125233294Sstasstatic gss_cred_id_t 126178825Sdfracquire_cred_service(const char *service, 127178825Sdfr gss_OID nametype, 128233294Sstas gss_OID_set oidset, 129178825Sdfr int flags) 130178825Sdfr{ 131178825Sdfr OM_uint32 major_status, minor_status; 132178825Sdfr gss_cred_id_t cred_handle; 133178825Sdfr OM_uint32 time_rec; 134178825Sdfr gss_buffer_desc name_buffer; 135178825Sdfr gss_name_t name = GSS_C_NO_NAME; 136178825Sdfr 137178825Sdfr if (service) { 138178825Sdfr name_buffer.value = rk_UNCONST(service); 139178825Sdfr name_buffer.length = strlen(service); 140233294Sstas 141178825Sdfr major_status = gss_import_name(&minor_status, 142178825Sdfr &name_buffer, 143178825Sdfr nametype, 144178825Sdfr &name); 145178825Sdfr if (GSS_ERROR(major_status)) 146178825Sdfr errx(1, "import_name failed"); 147178825Sdfr } 148178825Sdfr 149233294Sstas major_status = gss_acquire_cred(&minor_status, 150178825Sdfr name, 151178825Sdfr 0, 152233294Sstas oidset, 153178825Sdfr flags, 154178825Sdfr &cred_handle, 155178825Sdfr NULL, 156178825Sdfr &time_rec); 157178825Sdfr if (GSS_ERROR(major_status)) { 158233294Sstas warnx("acquire_cred failed: %s", 159178825Sdfr gssapi_err(major_status, minor_status, GSS_C_NO_OID)); 160233294Sstas } else { 161178825Sdfr print_time(time_rec); 162178825Sdfr gss_release_cred(&minor_status, &cred_handle); 163178825Sdfr } 164178825Sdfr 165178825Sdfr if (name != GSS_C_NO_NAME) 166178825Sdfr gss_release_name(&minor_status, &name); 167178825Sdfr 168178825Sdfr if (GSS_ERROR(major_status)) 169178825Sdfr exit(1); 170233294Sstas 171233294Sstas return cred_handle; 172178825Sdfr} 173178825Sdfr 174178825Sdfrstatic int version_flag = 0; 175178825Sdfrstatic int help_flag = 0; 176233294Sstasstatic int kerberos_flag = 0; 177233294Sstasstatic int enctype = 0; 178178825Sdfrstatic char *acquire_name; 179178825Sdfrstatic char *acquire_type; 180233294Sstasstatic char *target_name; 181178825Sdfrstatic char *name_type; 182178825Sdfrstatic char *ccache; 183233294Sstasstatic int num_loops = 1; 184178825Sdfr 185178825Sdfrstatic struct getargs args[] = { 186178825Sdfr {"acquire-name", 0, arg_string, &acquire_name, "name", NULL }, 187178825Sdfr {"acquire-type", 0, arg_string, &acquire_type, "type", NULL }, 188233294Sstas {"enctype", 0, arg_integer, &enctype, "enctype-num", NULL }, 189233294Sstas {"loops", 0, arg_integer, &num_loops, "enctype-num", NULL }, 190233294Sstas {"kerberos", 0, arg_flag, &kerberos_flag, "enctype-num", NULL }, 191233294Sstas {"target-name", 0, arg_string, &target_name, "name", NULL }, 192178825Sdfr {"ccache", 0, arg_string, &ccache, "name", NULL }, 193178825Sdfr {"name-type", 0, arg_string, &name_type, "type", NULL }, 194178825Sdfr {"version", 0, arg_flag, &version_flag, "print version", NULL }, 195178825Sdfr {"help", 0, arg_flag, &help_flag, NULL, NULL } 196178825Sdfr}; 197178825Sdfr 198178825Sdfrstatic void 199178825Sdfrusage (int ret) 200178825Sdfr{ 201178825Sdfr arg_printusage (args, sizeof(args)/sizeof(*args), NULL, ""); 202178825Sdfr exit (ret); 203178825Sdfr} 204178825Sdfr 205178825Sdfrint 206178825Sdfrmain(int argc, char **argv) 207178825Sdfr{ 208233294Sstas gss_OID_set oidset = GSS_C_NULL_OID_SET; 209233294Sstas gss_OID mechoid = GSS_C_NO_OID; 210233294Sstas OM_uint32 maj_stat, min_stat; 211233294Sstas gss_cred_id_t cred; 212233294Sstas gss_name_t target = GSS_C_NO_NAME; 213233294Sstas int i, optidx = 0; 214178825Sdfr OM_uint32 flag; 215178825Sdfr gss_OID type; 216178825Sdfr 217178825Sdfr setprogname(argv[0]); 218178825Sdfr if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 219178825Sdfr usage(1); 220233294Sstas 221178825Sdfr if (help_flag) 222178825Sdfr usage (0); 223178825Sdfr 224178825Sdfr if(version_flag){ 225178825Sdfr print_version(NULL); 226178825Sdfr exit(0); 227178825Sdfr } 228178825Sdfr 229178825Sdfr argc -= optidx; 230178825Sdfr argv += optidx; 231178825Sdfr 232178825Sdfr if (argc != 0) 233178825Sdfr usage(1); 234178825Sdfr 235178825Sdfr if (acquire_type) { 236178825Sdfr if (strcasecmp(acquire_type, "both") == 0) 237178825Sdfr flag = GSS_C_BOTH; 238178825Sdfr else if (strcasecmp(acquire_type, "accept") == 0) 239178825Sdfr flag = GSS_C_ACCEPT; 240178825Sdfr else if (strcasecmp(acquire_type, "initiate") == 0) 241178825Sdfr flag = GSS_C_INITIATE; 242178825Sdfr else 243178825Sdfr errx(1, "unknown type %s", acquire_type); 244178825Sdfr } else 245178825Sdfr flag = GSS_C_ACCEPT; 246233294Sstas 247178825Sdfr if (name_type) { 248178825Sdfr if (strcasecmp("hostbased-service", name_type) == 0) 249178825Sdfr type = GSS_C_NT_HOSTBASED_SERVICE; 250178825Sdfr else if (strcasecmp("user-name", name_type) == 0) 251178825Sdfr type = GSS_C_NT_USER_NAME; 252178825Sdfr else 253178825Sdfr errx(1, "unknown name type %s", name_type); 254178825Sdfr } else 255178825Sdfr type = GSS_C_NT_HOSTBASED_SERVICE; 256178825Sdfr 257178825Sdfr if (ccache) { 258233294Sstas maj_stat = gss_krb5_ccache_name(&min_stat, ccache, NULL); 259233294Sstas if (GSS_ERROR(maj_stat)) 260233294Sstas errx(1, "gss_krb5_ccache_name %s", 261233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 262178825Sdfr } 263178825Sdfr 264233294Sstas if (kerberos_flag) { 265233294Sstas mechoid = GSS_KRB5_MECHANISM; 266178825Sdfr 267233294Sstas maj_stat = gss_create_empty_oid_set(&min_stat, &oidset); 268233294Sstas if (maj_stat != GSS_S_COMPLETE) 269233294Sstas errx(1, "gss_create_empty_oid_set: %s", 270233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 271233294Sstas 272233294Sstas maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset); 273233294Sstas if (maj_stat != GSS_S_COMPLETE) 274233294Sstas errx(1, "gss_add_oid_set_member: %s", 275233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 276233294Sstas } 277233294Sstas 278233294Sstas if (target_name) { 279233294Sstas gss_buffer_desc name; 280233294Sstas 281233294Sstas name.value = target_name; 282233294Sstas name.length = strlen(target_name); 283233294Sstas maj_stat = gss_import_name(&min_stat, &name, 284233294Sstas GSS_C_NT_HOSTBASED_SERVICE, &target); 285233294Sstas if (maj_stat != GSS_S_COMPLETE) 286233294Sstas errx(1, "gss_import_name: %s", 287233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 288233294Sstas } 289233294Sstas 290233294Sstas for (i = 0; i < num_loops; i++) { 291233294Sstas 292233294Sstas cred = acquire_cred_service(acquire_name, type, oidset, flag); 293233294Sstas 294233294Sstas if (enctype) { 295233294Sstas int32_t enctypelist = enctype; 296233294Sstas 297233294Sstas maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred, 298233294Sstas 1, &enctypelist); 299233294Sstas if (maj_stat) 300233294Sstas errx(1, "gss_krb5_set_allowable_enctypes: %s", 301233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 302233294Sstas } 303233294Sstas 304233294Sstas if (target) { 305233294Sstas gss_ctx_id_t context = GSS_C_NO_CONTEXT; 306233294Sstas gss_buffer_desc out; 307233294Sstas 308233294Sstas out.length = 0; 309233294Sstas out.value = NULL; 310233294Sstas 311233294Sstas maj_stat = gss_init_sec_context(&min_stat, 312233294Sstas cred, &context, 313233294Sstas target, mechoid, 314233294Sstas GSS_C_MUTUAL_FLAG, 0, NULL, 315233294Sstas GSS_C_NO_BUFFER, NULL, 316233294Sstas &out, NULL, NULL); 317233294Sstas if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) 318233294Sstas errx(1, "init_sec_context failed: %s", 319233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 320233294Sstas 321233294Sstas gss_release_buffer(&min_stat, &out); 322233294Sstas gss_delete_sec_context(&min_stat, &context, NULL); 323233294Sstas } 324233294Sstas gss_release_cred(&min_stat, &cred); 325233294Sstas } 326233294Sstas 327233294Sstas 328120945Snectar return 0; 329120945Snectar} 330