1184588Sdfr/*- 2184588Sdfr * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3184588Sdfr * Authors: Doug Rabson <dfr@rabson.org> 4184588Sdfr * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 5184588Sdfr * 6184588Sdfr * Redistribution and use in source and binary forms, with or without 7184588Sdfr * modification, are permitted provided that the following conditions 8184588Sdfr * are met: 9184588Sdfr * 1. Redistributions of source code must retain the above copyright 10184588Sdfr * notice, this list of conditions and the following disclaimer. 11184588Sdfr * 2. Redistributions in binary form must reproduce the above copyright 12184588Sdfr * notice, this list of conditions and the following disclaimer in the 13184588Sdfr * documentation and/or other materials provided with the distribution. 14184588Sdfr * 15184588Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16184588Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17184588Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18184588Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19184588Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20184588Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21184588Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22184588Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23184588Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24184588Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25184588Sdfr * SUCH DAMAGE. 26184588Sdfr * 27184588Sdfr * $FreeBSD$ 28184588Sdfr */ 29184588Sdfr 30184588Sdfr#include <sys/types.h> 31184588Sdfr#include <sys/syscall.h> 32184588Sdfr#include <sys/module.h> 33184588Sdfr 34184588Sdfr#include <stdio.h> 35184588Sdfr#include <string.h> 36184588Sdfr#include <err.h> 37184588Sdfr#include <unistd.h> 38184588Sdfr#include <stdlib.h> 39184588Sdfr 40184588Sdfr#include <krb5.h> 41184588Sdfr#include <gssapi/gssapi.h> 42184588Sdfr#include <gssapi/gssapi_krb5.h> 43184588Sdfr 44184588Sdfrstruct gsstest_2_args { 45184588Sdfr int step; /* test step number */ 46184588Sdfr gss_buffer_desc input_token; /* token from userland */ 47184588Sdfr gss_buffer_desc output_token; /* buffer to receive reply token */ 48184588Sdfr}; 49184588Sdfrstruct gsstest_2_res { 50184588Sdfr OM_uint32 maj_stat; /* maj_stat from kernel */ 51184588Sdfr OM_uint32 min_stat; /* min_stat from kernel */ 52184588Sdfr gss_buffer_desc output_token; /* reply token (using space from gsstest_2_args.output) */ 53184588Sdfr}; 54184588Sdfr 55184588Sdfrstatic void 56184588Sdfrreport_error(gss_OID mech, OM_uint32 maj, OM_uint32 min) 57184588Sdfr{ 58184588Sdfr OM_uint32 maj_stat, min_stat; 59184588Sdfr OM_uint32 message_context; 60184588Sdfr gss_buffer_desc buf; 61184588Sdfr 62184588Sdfr printf("major_stat=%d, minor_stat=%d\n", maj, min); 63184588Sdfr message_context = 0; 64184588Sdfr do { 65184588Sdfr maj_stat = gss_display_status(&min_stat, maj, 66184588Sdfr GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &buf); 67184588Sdfr printf("%.*s\n", (int)buf.length, (char *) buf.value); 68184588Sdfr gss_release_buffer(&min_stat, &buf); 69184588Sdfr } while (message_context); 70184588Sdfr if (mech) { 71184588Sdfr message_context = 0; 72184588Sdfr do { 73184588Sdfr maj_stat = gss_display_status(&min_stat, min, 74184588Sdfr GSS_C_MECH_CODE, mech, &message_context, &buf); 75184588Sdfr printf("%.*s\n", (int)buf.length, (char *) buf.value); 76184588Sdfr gss_release_buffer(&min_stat, &buf); 77184588Sdfr } while (message_context); 78184588Sdfr } 79184588Sdfr} 80184588Sdfr 81184588Sdfrint 82184588Sdfrmain(int argc, char **argv) 83184588Sdfr{ 84184588Sdfr struct module_stat stat; 85184588Sdfr int mod; 86184588Sdfr int syscall_num; 87184588Sdfr 88184588Sdfr stat.version = sizeof(stat); 89184588Sdfr mod = modfind("gsstest_syscall"); 90184588Sdfr if (mod < 0) { 91184588Sdfr fprintf(stderr, "%s: kernel support not present\n", argv[0]); 92184588Sdfr exit(1); 93184588Sdfr } 94184588Sdfr modstat(mod, &stat); 95184588Sdfr syscall_num = stat.data.intval; 96184588Sdfr 97184588Sdfr switch (atoi(argv[1])) { 98184588Sdfr case 1: 99184588Sdfr syscall(syscall_num, 1, NULL, NULL); 100184588Sdfr break; 101184588Sdfr 102184588Sdfr case 2: { 103184588Sdfr struct gsstest_2_args args; 104184588Sdfr struct gsstest_2_res res; 105184588Sdfr char hostname[512]; 106184588Sdfr char token_buffer[8192]; 107184588Sdfr OM_uint32 maj_stat, min_stat; 108184588Sdfr gss_ctx_id_t client_context = GSS_C_NO_CONTEXT; 109184588Sdfr gss_cred_id_t client_cred; 110184588Sdfr gss_OID mech_type = GSS_C_NO_OID; 111184588Sdfr gss_buffer_desc name_buf, message_buf; 112184588Sdfr gss_name_t name; 113184588Sdfr int32_t enctypes[] = { 114184588Sdfr ETYPE_DES_CBC_CRC, 115184588Sdfr ETYPE_ARCFOUR_HMAC_MD5, 116184588Sdfr ETYPE_ARCFOUR_HMAC_MD5_56, 117184588Sdfr ETYPE_AES256_CTS_HMAC_SHA1_96, 118184588Sdfr ETYPE_AES128_CTS_HMAC_SHA1_96, 119184588Sdfr ETYPE_DES3_CBC_SHA1, 120184588Sdfr }; 121184588Sdfr int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); 122184588Sdfr int established; 123184588Sdfr int i; 124184588Sdfr 125184588Sdfr for (i = 0; i < num_enctypes; i++) { 126184588Sdfr printf("testing etype %d\n", enctypes[i]); 127184588Sdfr args.output_token.length = sizeof(token_buffer); 128184588Sdfr args.output_token.value = token_buffer; 129184588Sdfr 130184588Sdfr gethostname(hostname, sizeof(hostname)); 131184588Sdfr snprintf(token_buffer, sizeof(token_buffer), 132184588Sdfr "nfs@%s", hostname); 133184588Sdfr name_buf.length = strlen(token_buffer); 134184588Sdfr name_buf.value = token_buffer; 135184588Sdfr maj_stat = gss_import_name(&min_stat, &name_buf, 136184588Sdfr GSS_C_NT_HOSTBASED_SERVICE, &name); 137184588Sdfr if (GSS_ERROR(maj_stat)) { 138184588Sdfr printf("gss_import_name failed\n"); 139184588Sdfr report_error(mech_type, maj_stat, min_stat); 140184588Sdfr goto out; 141184588Sdfr } 142184588Sdfr 143184588Sdfr maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME, 144184588Sdfr 0, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client_cred, 145184588Sdfr NULL, NULL); 146184588Sdfr if (GSS_ERROR(maj_stat)) { 147184588Sdfr printf("gss_acquire_cred (client) failed\n"); 148184588Sdfr report_error(mech_type, maj_stat, min_stat); 149184588Sdfr goto out; 150184588Sdfr } 151184588Sdfr 152184588Sdfr maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, 153184588Sdfr client_cred, 1, &enctypes[i]); 154184588Sdfr if (GSS_ERROR(maj_stat)) { 155184588Sdfr printf("gss_krb5_set_allowable_enctypes failed\n"); 156184588Sdfr report_error(mech_type, maj_stat, min_stat); 157184588Sdfr goto out; 158184588Sdfr } 159184588Sdfr 160184588Sdfr res.output_token.length = 0; 161184588Sdfr res.output_token.value = 0; 162184588Sdfr established = 0; 163184588Sdfr while (!established) { 164184588Sdfr maj_stat = gss_init_sec_context(&min_stat, 165184588Sdfr client_cred, 166184588Sdfr &client_context, 167184588Sdfr name, 168184588Sdfr GSS_C_NO_OID, 169184588Sdfr (GSS_C_MUTUAL_FLAG 170184588Sdfr |GSS_C_CONF_FLAG 171184588Sdfr |GSS_C_INTEG_FLAG 172184588Sdfr |GSS_C_SEQUENCE_FLAG 173184588Sdfr |GSS_C_REPLAY_FLAG), 174184588Sdfr 0, 175184588Sdfr GSS_C_NO_CHANNEL_BINDINGS, 176184588Sdfr &res.output_token, 177184588Sdfr &mech_type, 178184588Sdfr &args.input_token, 179184588Sdfr NULL, 180184588Sdfr NULL); 181184588Sdfr if (GSS_ERROR(maj_stat)) { 182184588Sdfr printf("gss_init_sec_context failed\n"); 183184588Sdfr report_error(mech_type, maj_stat, min_stat); 184184588Sdfr goto out; 185184588Sdfr } 186184588Sdfr if (args.input_token.length) { 187184588Sdfr args.step = 1; 188184588Sdfr syscall(syscall_num, 2, &args, &res); 189184588Sdfr gss_release_buffer(&min_stat, 190184588Sdfr &args.input_token); 191184588Sdfr if (res.maj_stat != GSS_S_COMPLETE 192184588Sdfr && res.maj_stat != GSS_S_CONTINUE_NEEDED) { 193184588Sdfr printf("gss_accept_sec_context (kernel) failed\n"); 194184588Sdfr report_error(mech_type, res.maj_stat, 195184588Sdfr res.min_stat); 196184588Sdfr goto out; 197184588Sdfr } 198184588Sdfr } 199184588Sdfr if (maj_stat == GSS_S_COMPLETE) 200184588Sdfr established = 1; 201184588Sdfr } 202184588Sdfr 203184588Sdfr message_buf.value = "Hello world"; 204184588Sdfr message_buf.length = strlen((char *) message_buf.value); 205184588Sdfr 206184588Sdfr maj_stat = gss_get_mic(&min_stat, client_context, 207184588Sdfr GSS_C_QOP_DEFAULT, &message_buf, &args.input_token); 208184588Sdfr if (GSS_ERROR(maj_stat)) { 209184588Sdfr printf("gss_get_mic failed\n"); 210184588Sdfr report_error(mech_type, maj_stat, min_stat); 211184588Sdfr goto out; 212184588Sdfr } 213184588Sdfr 214184588Sdfr args.step = 2; 215184588Sdfr syscall(syscall_num, 2, &args, &res); 216184588Sdfr gss_release_buffer(&min_stat, &args.input_token); 217184588Sdfr if (GSS_ERROR(res.maj_stat)) { 218184588Sdfr printf("kernel gss_verify_mic failed\n"); 219184588Sdfr report_error(mech_type, res.maj_stat, res.min_stat); 220184588Sdfr goto out; 221184588Sdfr } 222184588Sdfr 223184588Sdfr maj_stat = gss_verify_mic(&min_stat, client_context, 224184588Sdfr &message_buf, &res.output_token, NULL); 225184588Sdfr if (GSS_ERROR(maj_stat)) { 226184588Sdfr printf("gss_verify_mic failed\n"); 227184588Sdfr report_error(mech_type, maj_stat, min_stat); 228184588Sdfr goto out; 229184588Sdfr } 230184588Sdfr 231184588Sdfr maj_stat = gss_wrap(&min_stat, client_context, 232184588Sdfr TRUE, GSS_C_QOP_DEFAULT, &message_buf, NULL, 233184588Sdfr &args.input_token); 234184588Sdfr if (GSS_ERROR(maj_stat)) { 235184588Sdfr printf("gss_wrap failed\n"); 236184588Sdfr report_error(mech_type, maj_stat, min_stat); 237184588Sdfr goto out; 238184588Sdfr } 239184588Sdfr 240184588Sdfr args.step = 3; 241184588Sdfr syscall(syscall_num, 2, &args, &res); 242184588Sdfr gss_release_buffer(&min_stat, &args.input_token); 243184588Sdfr if (GSS_ERROR(res.maj_stat)) { 244184588Sdfr printf("kernel gss_unwrap failed\n"); 245184588Sdfr report_error(mech_type, res.maj_stat, res.min_stat); 246184588Sdfr goto out; 247184588Sdfr } 248184588Sdfr 249184588Sdfr maj_stat = gss_unwrap(&min_stat, client_context, 250184588Sdfr &res.output_token, &message_buf, NULL, NULL); 251184588Sdfr if (GSS_ERROR(maj_stat)) { 252184588Sdfr printf("gss_unwrap failed\n"); 253184588Sdfr report_error(mech_type, maj_stat, min_stat); 254184588Sdfr goto out; 255184588Sdfr } 256184588Sdfr gss_release_buffer(&min_stat, &message_buf); 257184588Sdfr 258184588Sdfr maj_stat = gss_wrap(&min_stat, client_context, 259184588Sdfr FALSE, GSS_C_QOP_DEFAULT, &message_buf, NULL, 260184588Sdfr &args.input_token); 261184588Sdfr if (GSS_ERROR(maj_stat)) { 262184588Sdfr printf("gss_wrap failed\n"); 263184588Sdfr report_error(mech_type, maj_stat, min_stat); 264184588Sdfr goto out; 265184588Sdfr } 266184588Sdfr 267184588Sdfr args.step = 4; 268184588Sdfr syscall(syscall_num, 2, &args, &res); 269184588Sdfr gss_release_buffer(&min_stat, &args.input_token); 270184588Sdfr if (GSS_ERROR(res.maj_stat)) { 271184588Sdfr printf("kernel gss_unwrap failed\n"); 272184588Sdfr report_error(mech_type, res.maj_stat, res.min_stat); 273184588Sdfr goto out; 274184588Sdfr } 275184588Sdfr 276184588Sdfr maj_stat = gss_unwrap(&min_stat, client_context, 277184588Sdfr &res.output_token, &message_buf, NULL, NULL); 278184588Sdfr if (GSS_ERROR(maj_stat)) { 279184588Sdfr printf("gss_unwrap failed\n"); 280184588Sdfr report_error(mech_type, maj_stat, min_stat); 281184588Sdfr goto out; 282184588Sdfr } 283184588Sdfr gss_release_buffer(&min_stat, &message_buf); 284184588Sdfr 285184588Sdfr args.step = 5; 286184588Sdfr syscall(syscall_num, 2, &args, &res); 287184588Sdfr 288184588Sdfr gss_release_name(&min_stat, &name); 289184588Sdfr gss_release_cred(&min_stat, &client_cred); 290184588Sdfr gss_delete_sec_context(&min_stat, &client_context, 291184588Sdfr GSS_C_NO_BUFFER); 292184588Sdfr } 293184588Sdfr 294184588Sdfr break; 295184588Sdfr } 296184588Sdfr case 3: 297184588Sdfr syscall(syscall_num, 3, NULL, NULL); 298184588Sdfr break; 299184588Sdfr case 4: 300184588Sdfr syscall(syscall_num, 4, NULL, NULL); 301184588Sdfr break; 302184588Sdfr } 303184588Sdfr return (0); 304184588Sdfr 305184588Sdfrout: 306184588Sdfr return (1); 307184588Sdfr} 308