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" 39 RCSID("$Id$"); 40 41 static int 42 do_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 49 /* get_mic */ 50 51 input_token->length = 3; 52 input_token->value = strdup("hej"); 53 54 maj_stat = gss_get_mic(&min_stat, 55 context_hdl, 56 GSS_C_QOP_DEFAULT, 57 input_token, 58 output_token); 59 if (GSS_ERROR(maj_stat)) 60 gss_err (1, min_stat, "gss_get_mic"); 61 62 write_token (sock, input_token); 63 write_token (sock, output_token); 64 65 /* wrap */ 66 67 input_token->length = 7; 68 input_token->value = "hemligt"; 69 70 maj_stat = gss_wrap (&min_stat, 71 context_hdl, 72 0, 73 GSS_C_QOP_DEFAULT, 74 input_token, 75 NULL, 76 output_token); 77 if (GSS_ERROR(maj_stat)) 78 gss_err (1, min_stat, "gss_wrap"); 79 80 write_token (sock, output_token); 81 82 maj_stat = gss_wrap (&min_stat, 83 context_hdl, 84 1, 85 GSS_C_QOP_DEFAULT, 86 input_token, 87 NULL, 88 output_token); 89 if (GSS_ERROR(maj_stat)) 90 gss_err (1, min_stat, "gss_wrap"); 91 92 write_token (sock, output_token); 93 94 return 0; 95 } 96 97 extern char *password; 98 99 static int 100 proto (int sock, const char *hostname, const char *service) 101 { 102 struct sockaddr_storage remote, local; 103 socklen_t addrlen; 104 105 int context_established = 0; 106 gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 107 gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 108 gss_buffer_desc real_input_token, real_output_token; 109 gss_buffer_t input_token = &real_input_token, 110 output_token = &real_output_token; 111 OM_uint32 maj_stat, min_stat; 112 gss_name_t server; 113 gss_buffer_desc name_token; 114 u_char init_buf[4]; 115 u_char acct_buf[4]; 116 gss_OID mech_oid; 117 char *str; 118 119 mech_oid = select_mech(mech); 120 121 name_token.length = asprintf (&str, 122 "%s@%s", service, hostname); 123 if (str == NULL) 124 errx(1, "malloc - out of memory"); 125 name_token.value = str; 126 127 maj_stat = gss_import_name (&min_stat, 128 &name_token, 129 GSS_C_NT_HOSTBASED_SERVICE, 130 &server); 131 if (GSS_ERROR(maj_stat)) 132 gss_err (1, min_stat, 133 "Error importing name `%s@%s':\n", service, hostname); 134 135 if (password) { 136 gss_buffer_desc pw; 137 138 pw.value = password; 139 pw.length = strlen(password); 140 141 maj_stat = gss_acquire_cred_with_password(&min_stat, 142 GSS_C_NO_NAME, 143 &pw, 144 GSS_C_INDEFINITE, 145 GSS_C_NO_OID_SET, 146 GSS_C_INITIATE, 147 &cred, 148 NULL, 149 NULL); 150 if (GSS_ERROR(maj_stat)) 151 gss_err (1, min_stat, 152 "Error acquiring default initiator credentials"); 153 } 154 155 addrlen = sizeof(local); 156 if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 157 || addrlen > sizeof(local)) 158 err (1, "getsockname(%s)", hostname); 159 160 addrlen = sizeof(remote); 161 if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 162 || addrlen > sizeof(remote)) 163 err (1, "getpeername(%s)", hostname); 164 165 input_token->length = 0; 166 output_token->length = 0; 167 168 #if 0 169 struct gss_channel_bindings_struct input_chan_bindings; 170 171 input_chan_bindings.initiator_addrtype = GSS_C_AF_INET; 172 input_chan_bindings.initiator_address.length = 4; 173 init_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF; 174 init_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF; 175 init_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF; 176 init_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF; 177 input_chan_bindings.initiator_address.value = init_buf; 178 179 input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET; 180 input_chan_bindings.acceptor_address.length = 4; 181 acct_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF; 182 acct_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF; 183 acct_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF; 184 acct_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF; 185 input_chan_bindings.acceptor_address.value = acct_buf; 186 187 input_chan_bindings.application_data.value = emalloc(4); 188 * (unsigned short*)input_chan_bindings.application_data.value = local.sin_port; 189 * ((unsigned short *)input_chan_bindings.application_data.value + 1) = remote.sin_port; 190 input_chan_bindings.application_data.length = 4; 191 192 input_chan_bindings.application_data.length = 0; 193 input_chan_bindings.application_data.value = NULL; 194 #endif 195 196 while(!context_established) { 197 maj_stat = 198 gss_init_sec_context(&min_stat, 199 cred, 200 &context_hdl, 201 server, 202 mech_oid, 203 GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, 204 0, 205 NULL, 206 input_token, 207 NULL, 208 output_token, 209 NULL, 210 NULL); 211 if (GSS_ERROR(maj_stat)) 212 gss_err (1, min_stat, "gss_init_sec_context"); 213 if (output_token->length != 0) 214 write_token (sock, output_token); 215 if (GSS_ERROR(maj_stat)) { 216 if (context_hdl != GSS_C_NO_CONTEXT) 217 gss_delete_sec_context (&min_stat, 218 &context_hdl, 219 GSS_C_NO_BUFFER); 220 break; 221 } 222 if (maj_stat & GSS_S_CONTINUE_NEEDED) { 223 read_token (sock, input_token); 224 } else { 225 context_established = 1; 226 } 227 228 } 229 if (fork_flag) { 230 pid_t pid; 231 int pipefd[2]; 232 233 if (pipe (pipefd) < 0) 234 err (1, "pipe"); 235 236 pid = fork (); 237 if (pid < 0) 238 err (1, "fork"); 239 if (pid != 0) { 240 gss_buffer_desc buf; 241 242 maj_stat = gss_export_sec_context (&min_stat, 243 &context_hdl, 244 &buf); 245 if (GSS_ERROR(maj_stat)) 246 gss_err (1, min_stat, "gss_export_sec_context"); 247 write_token (pipefd[1], &buf); 248 exit (0); 249 } else { 250 gss_ctx_id_t context_hdl; 251 gss_buffer_desc buf; 252 253 close (pipefd[1]); 254 read_token (pipefd[0], &buf); 255 close (pipefd[0]); 256 maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 257 if (GSS_ERROR(maj_stat)) 258 gss_err (1, min_stat, "gss_import_sec_context"); 259 gss_release_buffer (&min_stat, &buf); 260 return do_trans (sock, context_hdl); 261 } 262 } else { 263 return do_trans (sock, context_hdl); 264 } 265 } 266 267 int 268 main(int argc, char **argv) 269 { 270 krb5_context context; /* XXX */ 271 int port = client_setup(&context, &argc, argv); 272 return client_doit (argv[argc], port, service, proto); 273 } 274