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.12 2000/02/12 21:34:11 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 int 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 116 addrlen = sizeof(local); 117 if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 118 || addrlen != sizeof(local)) 119 err (1, "getsockname)"); 120 121 addrlen = sizeof(remote); 122 if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 123 || addrlen != sizeof(remote)) 124 err (1, "getpeername"); 125 126 do { 127 read_token (sock, input_token); 128 maj_stat = 129 gss_accept_sec_context (&min_stat, 130 &context_hdl, 131 GSS_C_NO_CREDENTIAL, 132 input_token, 133 GSS_C_NO_CHANNEL_BINDINGS, 134 &client_name, 135 NULL, 136 output_token, 137 NULL, 138 NULL, 139 NULL); 140 if(GSS_ERROR(maj_stat)) 141 gss_err (1, min_stat, "gss_accept_sec_context"); 142 if (output_token->length != 0) 143 write_token (sock, output_token); 144 if (GSS_ERROR(maj_stat)) { 145 if (context_hdl != GSS_C_NO_CONTEXT) 146 gss_delete_sec_context (&min_stat, 147 &context_hdl, 148 GSS_C_NO_BUFFER); 149 break; 150 } 151 } while(maj_stat & GSS_S_CONTINUE_NEEDED); 152 153 if (fork_flag) { 154 pid_t pid; 155 int pipefd[2]; 156 157 if (pipe (pipefd) < 0) 158 err (1, "pipe"); 159 160 pid = fork (); 161 if (pid < 0) 162 err (1, "fork"); 163 if (pid != 0) { 164 gss_buffer_desc buf; 165 166 maj_stat = gss_export_sec_context (&min_stat, 167 &context_hdl, 168 &buf); 169 if (GSS_ERROR(maj_stat)) 170 gss_err (1, min_stat, "gss_export_sec_context"); 171 write_token (pipefd[1], &buf); 172 exit (0); 173 } else { 174 gss_ctx_id_t context_hdl; 175 gss_buffer_desc buf; 176 177 close (pipefd[1]); 178 read_token (pipefd[0], &buf); 179 close (pipefd[0]); 180 maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl); 181 if (GSS_ERROR(maj_stat)) 182 gss_err (1, min_stat, "gss_import_sec_context"); 183 gss_release_buffer (&min_stat, &buf); 184 return process_it (sock, context_hdl, client_name); 185 } 186 } else { 187 return process_it (sock, context_hdl, client_name); 188 } 189 } 190 191 static int 192 doit (int port, const char *service) 193 { 194 int sock, sock2; 195 struct sockaddr_in my_addr; 196 int one = 1; 197 198 sock = socket (AF_INET, SOCK_STREAM, 0); 199 if (sock < 0) 200 err (1, "socket"); 201 202 memset (&my_addr, 0, sizeof(my_addr)); 203 my_addr.sin_family = AF_INET; 204 my_addr.sin_port = port; 205 my_addr.sin_addr.s_addr = INADDR_ANY; 206 207 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 208 (void *)&one, sizeof(one)) < 0) 209 warn ("setsockopt SO_REUSEADDR"); 210 211 if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 212 err (1, "bind"); 213 214 if (listen (sock, 1) < 0) 215 err (1, "listen"); 216 217 sock2 = accept (sock, NULL, NULL); 218 if (sock2 < 0) 219 err (1, "accept"); 220 221 return proto (sock2, service); 222 } 223 224 int 225 main(int argc, char **argv) 226 { 227 krb5_context context = NULL; /* XXX */ 228 int port = server_setup(&context, argc, argv); 229 return doit (port, service); 230 } 231