GSS-API backend for the unified security framework.

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@4673 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Johan Danielsson
1998-03-26 02:58:22 +00:00
parent e3cea33ed5
commit 03240ce159

305
appl/ftp/ftp/gssapi.c Normal file
View File

@@ -0,0 +1,305 @@
/*
* Copyright (c) 1998 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Kungliga Tekniska
* H<>gskolan and its contributors.
*
* 4. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef FTP_SERVER
#include "ftpd_locl.h"
#else
#include "ftp_locl.h"
#endif
#include <gssapi.h>
RCSID("$Id$");
struct gss_data {
gss_ctx_id_t context_hdl;
};
static int
gss_init(void *app_data)
{
struct gss_data *d = app_data;
d->context_hdl = GSS_C_NO_CONTEXT;
return 0;
}
static int
gss_check_prot(void *app_data, int level)
{
if(level == prot_confidential)
return -1;
return 0;
}
static int
gss_decode(void *app_data, void *buf, int len, int level)
{
OM_uint32 maj_stat, min_stat;
gss_buffer_desc input, output;
gss_qop_t qop_state;
int conf_state;
struct gss_data *d = app_data;
input.length = len;
input.value = buf;
maj_stat = gss_unwrap (&min_stat,
d->context_hdl,
&input,
&output,
&conf_state,
&qop_state);
if(GSS_ERROR(maj_stat)) {
printf("Error unwrapping GSS packet: %x, %d, len = %d.\n",
maj_stat, min_stat, len);
abort();
}
memmove(buf, output.value, output.length);
return output.length;
}
static int
gss_overhead(void *app_data, int level, int len)
{
return 100; /* dunno? */
}
static int
gss_encode(void *app_data, void *from, int length, int level, void **to)
{
OM_uint32 maj_stat, min_stat;
gss_buffer_desc input, output;
int conf_state;
struct gss_data *d = app_data;
input.length = length;
input.value = from;
maj_stat = gss_wrap (&min_stat,
d->context_hdl,
level == prot_private,
GSS_C_QOP_DEFAULT,
&input,
&conf_state,
&output);
*to = output.value;
return output.length;
}
/* end common stuff */
#ifdef FTP_SERVER
static int
gss_adat(void *app_data, void *buf, size_t len)
{
char *p = NULL;
gss_buffer_desc input_token, output_token;
OM_uint32 maj_stat, min_stat;
gss_name_t client_name;
struct gss_data *d = app_data;
gss_channel_bindings_t bindings = malloc(sizeof(*bindings));
bindings->initiator_addrtype = GSS_C_AF_INET;
bindings->initiator_address.length = 4;
bindings->initiator_address.value = &his_addr.sin_addr;
bindings->acceptor_addrtype = GSS_C_AF_INET;
bindings->acceptor_address.length = 4;
bindings->acceptor_address.value = &ctrl_addr.sin_addr;
bindings->application_data.length = 0;
bindings->application_data.value = NULL;
input_token.value = buf;
input_token.length = len;
maj_stat = gss_accept_sec_context (&min_stat,
&d->context_hdl,
GSS_C_NO_CREDENTIAL,
&input_token,
bindings,
&client_name,
NULL,
&output_token,
NULL,
NULL,
NULL);
if(output_token.length) {
if(base64_encode(output_token.value, output_token.length, &p) < 0) {
reply(535, "Out of memory base64-encoding.");
return -1;
}
}
if(maj_stat == GSS_S_COMPLETE){
if(p)
reply(235, "ADAT=%s", p);
else
reply(235, "ADAT Complete");
sec_complete = 1;
} else if(maj_stat == GSS_S_CONTINUE_NEEDED)
if(p)
reply(335, "ADAT=%s", p);
else
reply(335, "OK, need more data");
else
reply(535, "foo?");
free(p);
return 0;
}
static int
gss_userok()
{
return 0;
}
struct sec_server_mech gss_server_mech = {
"GSSAPI",
sizeof(struct gss_data),
gss_init, /* init */
NULL, /* end */
gss_check_prot,
gss_overhead,
gss_encode,
gss_decode,
/* */
NULL,
gss_adat,
NULL, /* pbsz */
NULL, /* ccc */
gss_userok
};
#else
extern struct sockaddr_in hisctladdr, myctladdr;
static int
gss_auth(void *app_data, char *host)
{
OM_uint32 maj_stat, min_stat;
gss_buffer_desc name;
gss_name_t target_name;
gss_buffer_desc input, output_token;
int context_established = 0;
char *p;
int n;
gss_channel_bindings_t bindings;
struct gss_data *d = app_data;
name.length = asprintf((char**)&name.value, "ftp@%s", host);
maj_stat = gss_import_name(&min_stat,
&name,
GSS_C_NT_HOSTBASED_SERVICE,
&target_name);
free(name.value);
input.length = 0;
input.value = NULL;
bindings = malloc(sizeof(*bindings));
bindings->initiator_addrtype = GSS_C_AF_INET;
bindings->initiator_address.length = 4;
bindings->initiator_address.value = &hisctladdr.sin_addr;
bindings->acceptor_addrtype = GSS_C_AF_INET;
bindings->acceptor_address.length = 4;
bindings->acceptor_address.value = &myctladdr.sin_addr;
bindings->application_data.length = 0;
bindings->application_data.value = NULL;
while(!context_established) {
maj_stat = gss_init_sec_context(&min_stat,
GSS_C_NO_CREDENTIAL,
&d->context_hdl,
target_name,
GSS_C_NO_OID,
GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
0,
bindings,
&input,
NULL,
&output_token,
NULL,
NULL);
if (GSS_ERROR(maj_stat))
abort ();
gss_release_buffer(&min_stat, &input);
if (output_token.length != 0) {
base64_encode(output_token.value, output_token.length, &p);
gss_release_buffer(&min_stat, &output_token);
n = command("ADAT %s", p);
free(p);
}
if (GSS_ERROR(maj_stat)) {
if (d->context_hdl != GSS_C_NO_CONTEXT)
gss_delete_sec_context (&min_stat,
&d->context_hdl,
GSS_C_NO_BUFFER);
break;
}
if (maj_stat & GSS_S_CONTINUE_NEEDED) {
p = strstr(reply_string, "ADAT=");
if(p == NULL){
abort();
} else {
p+=5;
input.value = malloc(strlen(p));
input.length = base64_decode(p, input.value);
}
} else {
if(code != 235)
abort();
context_established = 1;
}
}
return 0;
}
struct sec_client_mech gss_client_mech = {
"GSSAPI",
sizeof(struct gss_data),
gss_init,
gss_auth,
NULL, /* end */
gss_check_prot,
gss_overhead,
gss_encode,
gss_decode,
};
#endif