/ appl / test / gssapi_client.c
gssapi_client.c
  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      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  
131  extern char *password;
132  
133  static int
134  proto (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  
301  int
302  main(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  }