155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2000 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "test_locl.h" 35233294Sstas#include <gssapi/gssapi.h> 36233294Sstas#include <gssapi/gssapi_krb5.h> 37233294Sstas#include <gssapi/gssapi_spnego.h> 3855682Smarkm#include <krb5.h> 3955682Smarkm#include "nt_gss_common.h" 4055682Smarkm 41233294SstasRCSID("$Id$"); 4255682Smarkm 4355682Smarkm/* 4455682Smarkm * This program tries to act as a server for the sample in `Sample 4555682Smarkm * SSPI Code' in Windows 2000 RC1 SDK. 4655682Smarkm * 4772445Sassar * use --dump-auth to get a binary dump of the authorization data in the ticket 4855682Smarkm */ 4955682Smarkm 5055682Smarkmstatic int help_flag; 5155682Smarkmstatic int version_flag; 5255682Smarkmstatic char *port_str; 5355682Smarkmchar *service = SERVICE; 5455682Smarkmstatic char *auth_file; 5555682Smarkm 5655682Smarkmstatic struct getargs args[] = { 5755682Smarkm { "port", 'p', arg_string, &port_str, "port to listen to", "port" }, 5855682Smarkm { "service", 's', arg_string, &service, "service to use", "service" }, 5955682Smarkm { "dump-auth", 0, arg_string, &auth_file, "dump authorization data", 6055682Smarkm "file" }, 6155682Smarkm { "help", 'h', arg_flag, &help_flag }, 6255682Smarkm { "version", 0, arg_flag, &version_flag } 6355682Smarkm}; 6455682Smarkm 6555682Smarkmstatic int num_args = sizeof(args) / sizeof(args[0]); 6655682Smarkm 6755682Smarkmstatic int 6855682Smarkmproto (int sock, const char *service) 6955682Smarkm{ 7055682Smarkm struct sockaddr_in remote, local; 7172445Sassar socklen_t addrlen; 7255682Smarkm gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; 7355682Smarkm gss_buffer_t input_token, output_token; 7455682Smarkm gss_buffer_desc real_input_token, real_output_token; 7555682Smarkm OM_uint32 maj_stat, min_stat; 7655682Smarkm gss_name_t client_name; 7755682Smarkm gss_buffer_desc name_token; 7855682Smarkm 7955682Smarkm addrlen = sizeof(local); 8055682Smarkm if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0 8155682Smarkm || addrlen != sizeof(local)) 8255682Smarkm err (1, "getsockname)"); 8355682Smarkm 8455682Smarkm addrlen = sizeof(remote); 8555682Smarkm if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0 8655682Smarkm || addrlen != sizeof(remote)) 8755682Smarkm err (1, "getpeername"); 8855682Smarkm 8955682Smarkm input_token = &real_input_token; 9055682Smarkm output_token = &real_output_token; 9155682Smarkm 9255682Smarkm do { 9355682Smarkm nt_read_token (sock, input_token); 9455682Smarkm maj_stat = 9555682Smarkm gss_accept_sec_context (&min_stat, 9655682Smarkm &context_hdl, 9755682Smarkm GSS_C_NO_CREDENTIAL, 9855682Smarkm input_token, 9955682Smarkm GSS_C_NO_CHANNEL_BINDINGS, 10055682Smarkm &client_name, 10155682Smarkm NULL, 10255682Smarkm output_token, 10355682Smarkm NULL, 10455682Smarkm NULL, 10555682Smarkm NULL); 10655682Smarkm if(GSS_ERROR(maj_stat)) 10755682Smarkm gss_err (1, min_stat, "gss_accept_sec_context"); 10855682Smarkm if (output_token->length != 0) 10955682Smarkm nt_write_token (sock, output_token); 11055682Smarkm if (GSS_ERROR(maj_stat)) { 11155682Smarkm if (context_hdl != GSS_C_NO_CONTEXT) 11255682Smarkm gss_delete_sec_context (&min_stat, 11355682Smarkm &context_hdl, 11455682Smarkm GSS_C_NO_BUFFER); 11555682Smarkm break; 11655682Smarkm } 11755682Smarkm } while(maj_stat & GSS_S_CONTINUE_NEEDED); 11855682Smarkm 11955682Smarkm if (auth_file != NULL) { 120233294Sstas gss_buffer_desc data; 12155682Smarkm 122233294Sstas maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 123233294Sstas context_hdl, 124233294Sstas KRB5_AUTHDATA_WIN2K_PAC, 125233294Sstas &data); 126233294Sstas if (maj_stat == GSS_S_COMPLETE) { 127233294Sstas rk_dumpdata(auth_file, data.value, data.length); 128233294Sstas gss_release_buffer(&min_stat, &data); 129233294Sstas } 13055682Smarkm } 13155682Smarkm 13255682Smarkm maj_stat = gss_display_name (&min_stat, 13355682Smarkm client_name, 13455682Smarkm &name_token, 13555682Smarkm NULL); 13655682Smarkm if (GSS_ERROR(maj_stat)) 13755682Smarkm gss_err (1, min_stat, "gss_display_name"); 13855682Smarkm 13955682Smarkm fprintf (stderr, "User is `%.*s'\n", (int)name_token.length, 14055682Smarkm (char *)name_token.value); 14155682Smarkm 14255682Smarkm /* write something back */ 14355682Smarkm 14455682Smarkm output_token->value = strdup ("hejsan"); 14555682Smarkm output_token->length = strlen (output_token->value) + 1; 14655682Smarkm nt_write_token (sock, output_token); 14755682Smarkm 14855682Smarkm output_token->value = strdup ("hoppsan"); 14955682Smarkm output_token->length = strlen (output_token->value) + 1; 15055682Smarkm nt_write_token (sock, output_token); 15155682Smarkm 15255682Smarkm return 0; 15355682Smarkm} 15455682Smarkm 15555682Smarkmstatic int 15655682Smarkmdoit (int port, const char *service) 15755682Smarkm{ 15855682Smarkm int sock, sock2; 15955682Smarkm struct sockaddr_in my_addr; 16055682Smarkm int one = 1; 16155682Smarkm 16255682Smarkm sock = socket (AF_INET, SOCK_STREAM, 0); 16355682Smarkm if (sock < 0) 16455682Smarkm err (1, "socket"); 16555682Smarkm 16655682Smarkm memset (&my_addr, 0, sizeof(my_addr)); 16755682Smarkm my_addr.sin_family = AF_INET; 16855682Smarkm my_addr.sin_port = port; 16955682Smarkm my_addr.sin_addr.s_addr = INADDR_ANY; 17055682Smarkm 17155682Smarkm if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 17255682Smarkm (void *)&one, sizeof(one)) < 0) 17355682Smarkm warn ("setsockopt SO_REUSEADDR"); 17455682Smarkm 17555682Smarkm if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) 17655682Smarkm err (1, "bind"); 17755682Smarkm 17855682Smarkm if (listen (sock, 1) < 0) 17955682Smarkm err (1, "listen"); 18055682Smarkm 18155682Smarkm sock2 = accept (sock, NULL, NULL); 18255682Smarkm if (sock2 < 0) 18355682Smarkm err (1, "accept"); 18455682Smarkm 18555682Smarkm return proto (sock2, service); 18655682Smarkm} 18755682Smarkm 18855682Smarkmstatic void 18955682Smarkmusage(int code, struct getargs *args, int num_args) 19055682Smarkm{ 19155682Smarkm arg_printusage(args, num_args, NULL, ""); 19255682Smarkm exit(code); 19355682Smarkm} 19455682Smarkm 19555682Smarkmstatic int 196233294Sstascommon_setup(krb5_context *context, int *argc, char **argv, 19755682Smarkm void (*usage)(int, struct getargs*, int)) 19855682Smarkm{ 19955682Smarkm int port = 0; 20055682Smarkm *argc = krb5_program_setup(context, *argc, argv, args, num_args, usage); 20155682Smarkm 20255682Smarkm if(help_flag) 20355682Smarkm (*usage)(0, args, num_args); 20455682Smarkm if(version_flag) { 20555682Smarkm print_version(NULL); 20655682Smarkm exit(0); 20755682Smarkm } 208233294Sstas 20955682Smarkm if(port_str){ 21055682Smarkm struct servent *s = roken_getservbyname(port_str, "tcp"); 21155682Smarkm if(s) 21255682Smarkm port = s->s_port; 21355682Smarkm else { 21455682Smarkm char *ptr; 21555682Smarkm 21655682Smarkm port = strtol (port_str, &ptr, 10); 21755682Smarkm if (port == 0 && ptr == port_str) 21855682Smarkm errx (1, "Bad port `%s'", port_str); 21955682Smarkm port = htons(port); 22055682Smarkm } 22155682Smarkm } 22255682Smarkm 22355682Smarkm if (port == 0) 22455682Smarkm port = krb5_getportbyname (*context, PORT, "tcp", 4711); 225233294Sstas 22655682Smarkm return port; 22755682Smarkm} 22855682Smarkm 22955682Smarkmstatic int 23055682Smarkmsetup(krb5_context *context, int argc, char **argv) 23155682Smarkm{ 23255682Smarkm int port = common_setup(context, &argc, argv, usage); 23355682Smarkm if(argv[argc] != NULL) 23455682Smarkm usage(1, args, num_args); 23555682Smarkm return port; 23655682Smarkm} 23755682Smarkm 23855682Smarkmint 23955682Smarkmmain(int argc, char **argv) 24055682Smarkm{ 24155682Smarkm krb5_context context = NULL; /* XXX */ 24255682Smarkm int port = setup(&context, argc, argv); 24355682Smarkm return doit (port, service); 24455682Smarkm} 245