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 14762 2005-04-10 14:47:41Z lha $"); 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 real_input_token, real_output_token; 47 gss_buffer_t input_token = &real_input_token, 48 output_token = &real_output_token; 49 gss_name_t server_name; 50 int conf_flag; 51 52 print_gss_name("User is", client_name); 53 54 maj_stat = gss_inquire_context(&min_stat, 55 context_hdl, 56 NULL, 57 &server_name, 58 NULL, 59 NULL, 60 NULL, 61 NULL, 62 NULL); 63 if (GSS_ERROR(maj_stat)) 64 gss_err (1, min_stat, "gss_inquire_context"); 65 66 print_gss_name("Server is", server_name); 67 68 maj_stat = gss_release_name(&min_stat, &server_name); 69 if (GSS_ERROR(maj_stat)) 70 gss_err (1, min_stat, "gss_release_name"); 71 72 /* gss_verify_mic */ 73 74 read_token (sock, input_token); 75 read_token (sock, output_token); 76 77 maj_stat = gss_verify_mic (&min_stat, 78 context_hdl, 79 input_token, 80 output_token, 81 NULL); 82 if (GSS_ERROR(maj_stat)) 83 gss_err (1, min_stat, "gss_verify_mic"); 84 85 fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length, 86 (char *)input_token->value); 87 88 gss_release_buffer (&min_stat, input_token); 89 gss_release_buffer (&min_stat, output_token); 90 91 /* gss_unwrap */ 92 93 read_token (sock, input_token); 94 95 maj_stat = gss_unwrap (&min_stat, 96 context_hdl, 97 input_token, 98 output_token, 99 &conf_flag, 100 NULL); 101 if(GSS_ERROR(maj_stat)) 102 gss_err (1, min_stat, "gss_unwrap"); 103 104 fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length, 105 (char *)output_token->value, 106 conf_flag ? "CONF" : "INT"); 107 108 gss_release_buffer (&min_stat, input_token); 109 gss_release_buffer (&min_stat, output_token); 110 111 read_token (sock, input_token); 112 113 maj_stat = gss_unwrap (&min_stat, 114 context_hdl, 115 input_token, 116 output_token, 117 &conf_flag, 118 NULL); 119 if(GSS_ERROR(maj_stat)) 120 gss_err (1, min_stat, "gss_unwrap"); 121 122 fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length, 123 (char *)output_token->value, 124 conf_flag ? "CONF" : "INT"); 125 126 gss_release_buffer (&min_stat, input_token); 127 gss_release_buffer (&min_stat, output_token); 128 129 return 0; 130 } 131 132 static int 133 proto (int sock, const char *service) 134 { 135 struct sockaddr_in remote, local; 136 socklen_t addrlen; 137 gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 138 gss_buffer_desc real_input_token, real_output_token; 139 gss_buffer_t input_token = &real_input_token, 140 output_token = &real_output_token; 141 OM_uint32 maj_stat, min_stat; 142 gss_name_t client_name; 143 struct gss_channel_bindings_struct input_chan_bindings; 144 gss_cred_id_t delegated_cred_handle = NULL; 145 krb5_ccache ccache; 146 u_char init_buf[4]; 147 u_char acct_buf[4]; 148 gss_OID mech_oid; 149 char *mech, *p; 150 151 addrlen = sizeof(local); 152 if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 153 || addrlen != sizeof(local)) 154 err (1, "getsockname)"); 155 156 addrlen = sizeof(remote); 157 if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 158 || addrlen != sizeof(remote)) 159 err (1, "getpeername"); 160 161 input_chan_bindings.initiator_addrtype = GSS_C_AF_INET; 162 input_chan_bindings.initiator_address.length = 4; 163 init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF; 164 init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF; 165 init_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF; 166 init_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF; 167 168 input_chan_bindings.initiator_address.value = init_buf; 169 input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET; 170 171 input_chan_bindings.acceptor_address.length = 4; 172 acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF; 173 acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF; 174 acct_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF; 175 acct_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF; 176 input_chan_bindings.acceptor_address.value = acct_buf; 177 input_chan_bindings.application_data.value = emalloc(4); 178 #if 0 179 * (unsigned short *)input_chan_bindings.application_data.value = 180 remote.sin_port; 181 * ((unsigned short *)input_chan_bindings.application_data.value + 1) = 182 local.sin_port; 183 input_chan_bindings.application_data.length = 4; 184 #else 185 input_chan_bindings.application_data.length = 0; 186 input_chan_bindings.application_data.value = NULL; 187 #endif 188 189 delegated_cred_handle = GSS_C_NO_CREDENTIAL; 190 191 do { 192 read_token (sock, input_token); 193 maj_stat = 194 gss_accept_sec_context (&min_stat, 195 &context_hdl, 196 GSS_C_NO_CREDENTIAL, 197 input_token, 198 &input_chan_bindings, 199 &client_name, 200 &mech_oid, 201 output_token, 202 NULL, 203 NULL, 204 &delegated_cred_handle); 205 if(GSS_ERROR(maj_stat)) 206 gss_err (1, min_stat, "gss_accept_sec_context"); 207 if (output_token->length != 0) 208 write_token (sock, output_token); 209 if (GSS_ERROR(maj_stat)) { 210 if (context_hdl != GSS_C_NO_CONTEXT) 211 gss_delete_sec_context (&min_stat, 212 &context_hdl, 213 GSS_C_NO_BUFFER); 214 break; 215 } 216 } while(maj_stat & GSS_S_CONTINUE_NEEDED); 217 218 p = (char *)mech_oid->elements; 219 if (mech_oid->length == GSS_KRB5_MECHANISM->length 220 && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0) 221 mech = "Kerberos 5"; 222 else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length 223 && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0) 224 mech = "SPNEGO"; /* XXX Silly, wont show up */ 225 else 226 mech = "Unknown"; 227 228 printf("Using mech: %s\n", mech); 229 230 if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { 231 krb5_context context; 232 233 printf("Delegated cred found\n"); 234 235 maj_stat = krb5_init_context(&context); 236 maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache); 237 maj_stat = gss_krb5_copy_ccache(&min_stat, 238 delegated_cred_handle, 239 ccache); 240 if (maj_stat == 0) { 241 krb5_principal p; 242 maj_stat = krb5_cc_get_principal(context, ccache, &p); 243 if (maj_stat == 0) { 244 char *name; 245 maj_stat = krb5_unparse_name(context, p, &name); 246 if (maj_stat == 0) { 247 printf("Delegated user is: `%s'\n", name); 248 free(name); 249 } 250 krb5_free_principal(context, p); 251 } 252 } 253 krb5_cc_close(context, ccache); 254 gss_release_cred(&min_stat, &delegated_cred_handle); 255 } 256 257 if (fork_flag) { 258 pid_t pid; 259 int pipefd[2]; 260 261 if (pipe (pipefd) < 0) 262 err (1, "pipe"); 263 264 pid = fork (); 265 if (pid < 0) 266 err (1, "fork"); 267 if (pid != 0) { 268 gss_buffer_desc buf; 269 270 maj_stat = gss_export_sec_context (&min_stat, 271 &context_hdl, 272 &buf); 273 if (GSS_ERROR(maj_stat)) 274 gss_err (1, min_stat, "gss_export_sec_context"); 275 write_token (pipefd[1], &buf); 276 exit (0); 277 } else { 278 gss_ctx_id_t context_hdl; 279 gss_buffer_desc buf; 280 281 close (pipefd[1]); 282 read_token (pipefd[0], &buf); 283 close (pipefd[0]); 284 maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 285 if (GSS_ERROR(maj_stat)) 286 gss_err (1, min_stat, "gss_import_sec_context"); 287 gss_release_buffer (&min_stat, &buf); 288 return process_it (sock, context_hdl, client_name); 289 } 290 } else { 291 return process_it (sock, context_hdl, client_name); 292 } 293 } 294 295 static int 296 doit (int port, const char *service) 297 { 298 int sock, sock2; 299 struct sockaddr_in my_addr; 300 int one = 1; 301 302 sock = socket (AF_INET, SOCK_STREAM, 0); 303 if (sock < 0) 304 err (1, "socket"); 305 306 memset (&my_addr, 0, sizeof(my_addr)); 307 my_addr.sin_family = AF_INET; 308 my_addr.sin_port = port; 309 my_addr.sin_addr.s_addr = INADDR_ANY; 310 311 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 312 (void *)&one, sizeof(one)) < 0) 313 warn ("setsockopt SO_REUSEADDR"); 314 315 if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 316 err (1, "bind"); 317 318 if (listen (sock, 1) < 0) 319 err (1, "listen"); 320 321 sock2 = accept (sock, NULL, NULL); 322 if (sock2 < 0) 323 err (1, "accept"); 324 325 return proto (sock2, service); 326 } 327 328 int 329 main(int argc, char **argv) 330 { 331 krb5_context context = NULL; /* XXX */ 332 int port = server_setup(&context, argc, argv); 333 return doit (port, service); 334 } 335