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.h> 36 #include "gss_common.h" 37 RCSID("$Id: gssapi_server.c,v 1.15 2000/08/09 20:53:07 assar Exp $"); 38 39 static int 40 process_it(int sock, 41 gss_ctx_id_t context_hdl, 42 gss_name_t client_name 43 ) 44 { 45 OM_uint32 maj_stat, min_stat; 46 gss_buffer_desc name_token; 47 gss_buffer_desc real_input_token, real_output_token; 48 gss_buffer_t input_token = &real_input_token, 49 output_token = &real_output_token; 50 51 maj_stat = gss_display_name (&min_stat, 52 client_name, 53 &name_token, 54 NULL); 55 if (GSS_ERROR(maj_stat)) 56 gss_err (1, min_stat, "gss_display_name"); 57 58 fprintf (stderr, "User is `%.*s'\n", (int)name_token.length, 59 (char *)name_token.value); 60 61 gss_release_buffer (&min_stat, &name_token); 62 63 /* gss_verify_mic */ 64 65 read_token (sock, input_token); 66 read_token (sock, output_token); 67 68 maj_stat = gss_verify_mic (&min_stat, 69 context_hdl, 70 input_token, 71 output_token, 72 NULL); 73 if (GSS_ERROR(maj_stat)) 74 gss_err (1, min_stat, "gss_verify_mic"); 75 76 fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length, 77 (char *)input_token->value); 78 79 gss_release_buffer (&min_stat, input_token); 80 gss_release_buffer (&min_stat, output_token); 81 82 /* gss_unwrap */ 83 84 read_token (sock, input_token); 85 86 maj_stat = gss_unwrap (&min_stat, 87 context_hdl, 88 input_token, 89 output_token, 90 NULL, 91 NULL); 92 if(GSS_ERROR(maj_stat)) 93 gss_err (1, min_stat, "gss_unwrap"); 94 95 fprintf (stderr, "gss_unwrap: %.*s\n", (int)output_token->length, 96 (char *)output_token->value); 97 98 gss_release_buffer (&min_stat, input_token); 99 gss_release_buffer (&min_stat, output_token); 100 101 return 0; 102 } 103 104 static int 105 proto (int sock, const char *service) 106 { 107 struct sockaddr_in remote, local; 108 socklen_t addrlen; 109 gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 110 gss_buffer_desc real_input_token, real_output_token; 111 gss_buffer_t input_token = &real_input_token, 112 output_token = &real_output_token; 113 OM_uint32 maj_stat, min_stat; 114 gss_name_t client_name; 115 struct gss_channel_bindings_struct input_chan_bindings; 116 gss_cred_id_t delegated_cred_handle = NULL; 117 krb5_ccache ccache; 118 u_char init_buf[4]; 119 u_char acct_buf[4]; 120 121 addrlen = sizeof(local); 122 if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 123 || addrlen != sizeof(local)) 124 err (1, "getsockname)"); 125 126 addrlen = sizeof(remote); 127 if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 128 || addrlen != sizeof(remote)) 129 err (1, "getpeername"); 130 131 input_chan_bindings.initiator_addrtype = GSS_C_AF_INET; 132 input_chan_bindings.initiator_address.length = 4; 133 init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF; 134 init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF; 135 init_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF; 136 init_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF; 137 138 input_chan_bindings.initiator_address.value = init_buf; 139 input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET; 140 141 input_chan_bindings.acceptor_address.length = 4; 142 acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF; 143 acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF; 144 acct_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF; 145 acct_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF; 146 input_chan_bindings.acceptor_address.value = acct_buf; 147 input_chan_bindings.application_data.value = emalloc(4); 148 #if 0 149 * (unsigned short *)input_chan_bindings.application_data.value = 150 remote.sin_port; 151 * ((unsigned short *)input_chan_bindings.application_data.value + 1) = 152 local.sin_port; 153 input_chan_bindings.application_data.length = 4; 154 #else 155 input_chan_bindings.application_data.length = 0; 156 input_chan_bindings.application_data.value = NULL; 157 #endif 158 159 delegated_cred_handle = emalloc(sizeof(*delegated_cred_handle)); 160 memset((char*)delegated_cred_handle, 0, sizeof(*delegated_cred_handle)); 161 162 do { 163 read_token (sock, input_token); 164 maj_stat = 165 gss_accept_sec_context (&min_stat, 166 &context_hdl, 167 GSS_C_NO_CREDENTIAL, 168 input_token, 169 &input_chan_bindings, 170 &client_name, 171 NULL, 172 output_token, 173 NULL, 174 NULL, 175 /*&delegated_cred_handle*/ NULL); 176 if(GSS_ERROR(maj_stat)) 177 gss_err (1, min_stat, "gss_accept_sec_context"); 178 if (output_token->length != 0) 179 write_token (sock, output_token); 180 if (GSS_ERROR(maj_stat)) { 181 if (context_hdl != GSS_C_NO_CONTEXT) 182 gss_delete_sec_context (&min_stat, 183 &context_hdl, 184 GSS_C_NO_BUFFER); 185 break; 186 } 187 } while(maj_stat & GSS_S_CONTINUE_NEEDED); 188 189 if (delegated_cred_handle->ccache) { 190 krb5_context context; 191 192 maj_stat = krb5_init_context(&context); 193 maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache); 194 maj_stat = krb5_cc_copy_cache(context, 195 delegated_cred_handle->ccache, ccache); 196 krb5_cc_close(context, ccache); 197 krb5_cc_destroy(context, delegated_cred_handle->ccache); 198 } 199 200 if (fork_flag) { 201 pid_t pid; 202 int pipefd[2]; 203 204 if (pipe (pipefd) < 0) 205 err (1, "pipe"); 206 207 pid = fork (); 208 if (pid < 0) 209 err (1, "fork"); 210 if (pid != 0) { 211 gss_buffer_desc buf; 212 213 maj_stat = gss_export_sec_context (&min_stat, 214 &context_hdl, 215 &buf); 216 if (GSS_ERROR(maj_stat)) 217 gss_err (1, min_stat, "gss_export_sec_context"); 218 write_token (pipefd[1], &buf); 219 exit (0); 220 } else { 221 gss_ctx_id_t context_hdl; 222 gss_buffer_desc buf; 223 224 close (pipefd[1]); 225 read_token (pipefd[0], &buf); 226 close (pipefd[0]); 227 maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 228 if (GSS_ERROR(maj_stat)) 229 gss_err (1, min_stat, "gss_import_sec_context"); 230 gss_release_buffer (&min_stat, &buf); 231 return process_it (sock, context_hdl, client_name); 232 } 233 } else { 234 return process_it (sock, context_hdl, client_name); 235 } 236 } 237 238 static int 239 doit (int port, const char *service) 240 { 241 int sock, sock2; 242 struct sockaddr_in my_addr; 243 int one = 1; 244 245 sock = socket (AF_INET, SOCK_STREAM, 0); 246 if (sock < 0) 247 err (1, "socket"); 248 249 memset (&my_addr, 0, sizeof(my_addr)); 250 my_addr.sin_family = AF_INET; 251 my_addr.sin_port = port; 252 my_addr.sin_addr.s_addr = INADDR_ANY; 253 254 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 255 (void *)&one, sizeof(one)) < 0) 256 warn ("setsockopt SO_REUSEADDR"); 257 258 if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 259 err (1, "bind"); 260 261 if (listen (sock, 1) < 0) 262 err (1, "listen"); 263 264 sock2 = accept (sock, NULL, NULL); 265 if (sock2 < 0) 266 err (1, "accept"); 267 268 return proto (sock2, service); 269 } 270 271 int 272 main(int argc, char **argv) 273 { 274 krb5_context context = NULL; /* XXX */ 275 int port = server_setup(&context, argc, argv); 276 return doit (port, service); 277 } 278