1/* 2 * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include "test_locl.h" 35#include <gssapi/gssapi.h> 36#include <gssapi/gssapi_krb5.h> 37#include <gssapi/gssapi_spnego.h> 38#include "gss_common.h" 39RCSID("$Id$"); 40 41static int 42do_trans (int sock, gss_ctx_id_t context_hdl) 43{ 44 OM_uint32 maj_stat, min_stat; 45 gss_buffer_desc real_input_token, real_output_token; 46 gss_buffer_t input_token = &real_input_token, 47 output_token = &real_output_token; 48 int conf_flag; 49 50 /* get_mic */ 51 52 input_token->length = 3; 53 input_token->value = strdup("hej"); 54 55 maj_stat = gss_get_mic(&min_stat, 56 context_hdl, 57 GSS_C_QOP_DEFAULT, 58 input_token, 59 output_token); 60 if (GSS_ERROR(maj_stat)) 61 gss_err (1, min_stat, "gss_get_mic"); 62 63 write_token (sock, input_token); 64 write_token (sock, output_token); 65 66 gss_release_buffer(&min_stat, output_token); 67 68 /* verify mic */ 69 70 read_token (sock, input_token); 71 read_token (sock, output_token); 72 73 maj_stat = gss_verify_mic(&min_stat, 74 context_hdl, 75 input_token, 76 output_token, 77 NULL); 78 if (GSS_ERROR(maj_stat)) 79 gss_err (1, min_stat, "gss_verify_mic"); 80 81 gss_release_buffer (&min_stat, input_token); 82 gss_release_buffer (&min_stat, output_token); 83 84 /* wrap */ 85 86 input_token->length = 7; 87 input_token->value = "hemligt"; 88 89 maj_stat = gss_wrap (&min_stat, 90 context_hdl, 91 0, 92 GSS_C_QOP_DEFAULT, 93 input_token, 94 NULL, 95 output_token); 96 if (GSS_ERROR(maj_stat)) 97 gss_err (1, min_stat, "gss_wrap"); 98 99 write_token (sock, output_token); 100 101 maj_stat = gss_wrap (&min_stat, 102 context_hdl, 103 1, 104 GSS_C_QOP_DEFAULT, 105 input_token, 106 NULL, 107 output_token); 108 if (GSS_ERROR(maj_stat)) 109 gss_err (1, min_stat, "gss_wrap"); 110 111 write_token (sock, output_token); 112 113 read_token (sock, input_token); 114 115 maj_stat = gss_unwrap (&min_stat, 116 context_hdl, 117 input_token, 118 output_token, 119 &conf_flag, 120 NULL); 121 if(GSS_ERROR(maj_stat)) 122 gss_err (1, min_stat, "gss_unwrap"); 123 124 write_token (sock, output_token); 125 126 gss_release_buffer(&min_stat, output_token); 127 128 return 0; 129} 130 131extern char *password; 132 133static int 134proto (int sock, const char *hostname, const char *service) 135{ 136 struct sockaddr_storage remote, local; 137 socklen_t addrlen; 138 139 int context_established = 0; 140 gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 141 gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 142 gss_buffer_desc real_input_token, real_output_token; 143 gss_buffer_t input_token = &real_input_token, 144 output_token = &real_output_token; 145 OM_uint32 maj_stat, min_stat; 146 gss_name_t server; 147 gss_buffer_desc name_token; 148 u_char init_buf[4]; 149 u_char acct_buf[4]; 150 gss_OID mech_oid; 151 char *str; 152 153 mech_oid = select_mech(mech); 154 155 name_token.length = asprintf (&str, 156 "%s@%s", service, hostname); 157 if (str == NULL) 158 errx(1, "malloc - out of memory"); 159 name_token.value = str; 160 161 maj_stat = gss_import_name (&min_stat, 162 &name_token, 163 GSS_C_NT_HOSTBASED_SERVICE, 164 &server); 165 if (GSS_ERROR(maj_stat)) 166 gss_err (1, min_stat, 167 "Error importing name `%s@%s':\n", service, hostname); 168 169 if (password) { 170 gss_buffer_desc pw; 171 172 pw.value = password; 173 pw.length = strlen(password); 174 175 maj_stat = gss_acquire_cred_with_password(&min_stat, 176 GSS_C_NO_NAME, 177 &pw, 178 GSS_C_INDEFINITE, 179 GSS_C_NO_OID_SET, 180 GSS_C_INITIATE, 181 &cred, 182 NULL, 183 NULL); 184 if (GSS_ERROR(maj_stat)) 185 gss_err (1, min_stat, 186 "Error acquiring default initiator credentials"); 187 } 188 189 addrlen = sizeof(local); 190 if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 191 || addrlen > sizeof(local)) 192 err (1, "getsockname(%s)", hostname); 193 194 addrlen = sizeof(remote); 195 if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 196 || addrlen > sizeof(remote)) 197 err (1, "getpeername(%s)", hostname); 198 199 input_token->length = 0; 200 output_token->length = 0; 201 202#if 0 203 struct gss_channel_bindings_struct input_chan_bindings; 204 205 input_chan_bindings.initiator_addrtype = GSS_C_AF_INET; 206 input_chan_bindings.initiator_address.length = 4; 207 init_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF; 208 init_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF; 209 init_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF; 210 init_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF; 211 input_chan_bindings.initiator_address.value = init_buf; 212 213 input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET; 214 input_chan_bindings.acceptor_address.length = 4; 215 acct_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF; 216 acct_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF; 217 acct_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF; 218 acct_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF; 219 input_chan_bindings.acceptor_address.value = acct_buf; 220 221 input_chan_bindings.application_data.value = emalloc(4); 222 * (unsigned short*)input_chan_bindings.application_data.value = local.sin_port; 223 * ((unsigned short *)input_chan_bindings.application_data.value + 1) = remote.sin_port; 224 input_chan_bindings.application_data.length = 4; 225 226 input_chan_bindings.application_data.length = 0; 227 input_chan_bindings.application_data.value = NULL; 228#endif 229 230 while(!context_established) { 231 maj_stat = 232 gss_init_sec_context(&min_stat, 233 cred, 234 &context_hdl, 235 server, 236 mech_oid, 237 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, 238 0, 239 NULL, 240 input_token, 241 NULL, 242 output_token, 243 NULL, 244 NULL); 245 if (GSS_ERROR(maj_stat)) 246 gss_err (1, min_stat, "gss_init_sec_context"); 247 if (output_token->length != 0) 248 write_token (sock, output_token); 249 if (GSS_ERROR(maj_stat)) { 250 if (context_hdl != GSS_C_NO_CONTEXT) 251 gss_delete_sec_context (&min_stat, 252 &context_hdl, 253 GSS_C_NO_BUFFER); 254 break; 255 } 256 if (maj_stat & GSS_S_CONTINUE_NEEDED) { 257 read_token (sock, input_token); 258 } else { 259 context_established = 1; 260 } 261 262 } 263 if (fork_flag) { 264 pid_t pid; 265 int pipefd[2]; 266 267 if (pipe (pipefd) < 0) 268 err (1, "pipe"); 269 270 pid = fork (); 271 if (pid < 0) 272 err (1, "fork"); 273 if (pid != 0) { 274 gss_buffer_desc buf; 275 276 maj_stat = gss_export_sec_context (&min_stat, 277 &context_hdl, 278 &buf); 279 if (GSS_ERROR(maj_stat)) 280 gss_err (1, min_stat, "gss_export_sec_context"); 281 write_token (pipefd[1], &buf); 282 exit (0); 283 } else { 284 gss_ctx_id_t context_hdl; 285 gss_buffer_desc buf; 286 287 close (pipefd[1]); 288 read_token (pipefd[0], &buf); 289 close (pipefd[0]); 290 maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 291 if (GSS_ERROR(maj_stat)) 292 gss_err (1, min_stat, "gss_import_sec_context"); 293 gss_release_buffer (&min_stat, &buf); 294 return do_trans (sock, context_hdl); 295 } 296 } else { 297 return do_trans (sock, context_hdl); 298 } 299} 300 301int 302main(int argc, char **argv) 303{ 304 krb5_context context; /* XXX */ 305 int port = client_setup(&context, &argc, argv); 306 return client_doit (argv[argc], port, service, proto); 307} 308