New unified security framework.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@4672 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
717
appl/ftp/ftp/security.c
Normal file
717
appl/ftp/ftp/security.c
Normal file
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1996, 1997, 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 the 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
|
||||
|
||||
RCSID("$Id$");
|
||||
|
||||
static enum protection_level command_prot;
|
||||
static enum protection_level data_prot;
|
||||
static size_t buffer_size;
|
||||
|
||||
struct buffer {
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t index;
|
||||
int eof_flag;
|
||||
};
|
||||
|
||||
static struct buffer in_buffer, out_buffer;
|
||||
int sec_complete;
|
||||
|
||||
static struct {
|
||||
enum protection_level level;
|
||||
const char *name;
|
||||
} level_names[] = {
|
||||
{ prot_clear, "clear" },
|
||||
{ prot_safe, "safe" },
|
||||
{ prot_confidential, "confidential" },
|
||||
{ prot_private, "private" }
|
||||
};
|
||||
|
||||
static const char *
|
||||
level_to_name(enum protection_level level)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
|
||||
if(level_names[i].level == level)
|
||||
return level_names[i].name;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
#ifndef FTP_SERVER /* not used in server */
|
||||
static enum protection_level
|
||||
name_to_level(const char *name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
|
||||
if(!strncasecmp(level_names[i].name, name, strlen(name)))
|
||||
return level_names[i].level;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FTP_SERVER
|
||||
|
||||
static struct sec_server_mech *mechs[] = {
|
||||
&gss_server_mech,
|
||||
&krb4_server_mech,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct sec_server_mech *mech;
|
||||
|
||||
#else
|
||||
|
||||
static struct sec_client_mech *mechs[] = {
|
||||
&gss_client_mech,
|
||||
&krb4_client_mech,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct sec_client_mech *mech;
|
||||
|
||||
#endif
|
||||
|
||||
static void *app_data;
|
||||
|
||||
int
|
||||
sec_getc(FILE *F)
|
||||
{
|
||||
if(sec_complete && data_prot) {
|
||||
char c;
|
||||
if(sec_read(fileno(F), &c, 1) == 0)
|
||||
return EOF;
|
||||
return c;
|
||||
} else
|
||||
return getc(F);
|
||||
}
|
||||
|
||||
static int
|
||||
block_read(int fd, void *buf, size_t len)
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
int b;
|
||||
while(len) {
|
||||
b = read(fd, p, len);
|
||||
if(b <= 0)
|
||||
return -1;
|
||||
len -= b;
|
||||
p += b;
|
||||
}
|
||||
return p - (unsigned char*)buf;
|
||||
}
|
||||
|
||||
static int
|
||||
block_write(int fd, void *buf, size_t len)
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
int b;
|
||||
while(len) {
|
||||
b = write(fd, p, len);
|
||||
if(b < 0)
|
||||
return -1;
|
||||
len -= b;
|
||||
p += b;
|
||||
}
|
||||
return p - (unsigned char*)buf;
|
||||
}
|
||||
|
||||
static int
|
||||
sec_get_data(int fd, struct buffer *buf, int level)
|
||||
{
|
||||
int len;
|
||||
|
||||
if(block_read(fd, &len, sizeof(len)) < 0)
|
||||
return -1;
|
||||
len = ntohl(len);
|
||||
buf->data = realloc(buf->data, len);
|
||||
if(block_read(fd, buf->data, len) < 0)
|
||||
return -1;
|
||||
buf->size = (*mech->decode)(app_data, buf->data, len, data_prot);
|
||||
buf->index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
buffer_read(struct buffer *buf, void *data, size_t len)
|
||||
{
|
||||
len = min(len, buf->size - buf->index);
|
||||
memcpy(data, (char*)buf->data + buf->index, len);
|
||||
buf->index += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t
|
||||
buffer_write(struct buffer *buf, void *data, size_t len)
|
||||
{
|
||||
if(buf->index + len > buf->size) {
|
||||
void *tmp;
|
||||
if(buf->data == NULL)
|
||||
tmp = malloc(1024);
|
||||
else
|
||||
tmp = realloc(buf->data, buf->index + len);
|
||||
if(tmp == NULL)
|
||||
return -1;
|
||||
buf->data = tmp;
|
||||
buf->size = buf->index + len;
|
||||
}
|
||||
memcpy((char*)buf->data + buf->index, data, len);
|
||||
buf->index += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
sec_read(int fd, void *data, int length)
|
||||
{
|
||||
size_t len;
|
||||
int rx = 0;
|
||||
|
||||
if(sec_complete == 0 || data_prot == 0)
|
||||
return read(fd, data, length);
|
||||
|
||||
if(in_buffer.eof_flag){
|
||||
in_buffer.eof_flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = buffer_read(&in_buffer, data, length);
|
||||
length -= len;
|
||||
rx += len;
|
||||
(char*)data += len;
|
||||
|
||||
while(length){
|
||||
if(sec_get_data(fd, &in_buffer, data_prot) < 0)
|
||||
return -1;
|
||||
if(in_buffer.size == 0) {
|
||||
if(rx)
|
||||
in_buffer.eof_flag = 1;
|
||||
return rx;
|
||||
}
|
||||
len = buffer_read(&in_buffer, data, length);
|
||||
length -= len;
|
||||
rx += len;
|
||||
(char*)data += len;
|
||||
}
|
||||
return rx;
|
||||
}
|
||||
|
||||
static int
|
||||
sec_send(int fd, char *from, int length)
|
||||
{
|
||||
int bytes;
|
||||
void *buf;
|
||||
bytes = (*mech->encode)(app_data, from, length, data_prot, &buf);
|
||||
bytes = htonl(bytes);
|
||||
block_write(fd, &bytes, sizeof(bytes));
|
||||
block_write(fd, buf, ntohl(bytes));
|
||||
free(buf);
|
||||
return length;
|
||||
}
|
||||
|
||||
int
|
||||
sec_fflush(FILE *F)
|
||||
{
|
||||
if(data_prot != prot_clear) {
|
||||
if(out_buffer.index > 0){
|
||||
sec_write(fileno(F), out_buffer.data, out_buffer.index);
|
||||
out_buffer.index = 0;
|
||||
}
|
||||
sec_send(fileno(F), NULL, 0);
|
||||
}
|
||||
fflush(F);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sec_write(int fd, char *data, int length)
|
||||
{
|
||||
int len = buffer_size;
|
||||
int tx = 0;
|
||||
|
||||
if(data_prot == prot_clear)
|
||||
return write(fd, data, length);
|
||||
|
||||
len -= (*mech->overhead)(app_data, data_prot, len);
|
||||
while(length){
|
||||
if(length < len)
|
||||
len = length;
|
||||
sec_send(fd, data, len);
|
||||
length -= len;
|
||||
data += len;
|
||||
tx += len;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
int
|
||||
sec_putc(int c, FILE *F)
|
||||
{
|
||||
char ch = c;
|
||||
if(data_prot == prot_clear)
|
||||
return putc(c, F);
|
||||
|
||||
buffer_write(&out_buffer, &ch, 1);
|
||||
if(c == '\n' || out_buffer.index >= 1024 /* XXX */) {
|
||||
sec_write(fileno(F), out_buffer.data, out_buffer.index);
|
||||
out_buffer.index = 0;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int
|
||||
sec_read_msg(char *s, int level)
|
||||
{
|
||||
int len;
|
||||
char *buf;
|
||||
int code;
|
||||
|
||||
buf = malloc(strlen(s));
|
||||
len = base64_decode(s + 4, buf); /* XXX */
|
||||
|
||||
len = (*mech->decode)(app_data, buf, len, level);
|
||||
if(len < 0)
|
||||
return -1;
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
if(buf[3] == '-')
|
||||
code = 0;
|
||||
else
|
||||
sscanf(buf, "%d", &code);
|
||||
if(buf[len-1] == '\n')
|
||||
buf[len-1] = '\0';
|
||||
strcpy(s, buf);
|
||||
free(buf);
|
||||
return code;
|
||||
}
|
||||
|
||||
int
|
||||
sec_vfprintf(FILE *f, const char *fmt, va_list ap)
|
||||
{
|
||||
char *buf;
|
||||
void *enc;
|
||||
int len;
|
||||
if(!sec_complete)
|
||||
return vfprintf(f, fmt, ap);
|
||||
|
||||
vasprintf(&buf, fmt, ap);
|
||||
len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc);
|
||||
free(buf);
|
||||
if(len < 0) {
|
||||
printf("Failed to encode command.\n");
|
||||
return -1;
|
||||
}
|
||||
if(base64_encode(enc, len, &buf) < 0){
|
||||
printf("Out of memory base64-encoding.\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef FTP_SERVER
|
||||
if(command_prot == prot_safe)
|
||||
fprintf(f, "631 %s\r\n", buf);
|
||||
else if(command_prot == prot_private)
|
||||
fprintf(f, "632 %s\r\n", buf);
|
||||
else if(command_prot == prot_confidential)
|
||||
fprintf(f, "633 %s\r\n", buf);
|
||||
#else
|
||||
if(command_prot == prot_safe)
|
||||
fprintf(f, "MIC %s", buf);
|
||||
else if(command_prot == prot_private)
|
||||
fprintf(f, "ENC %s", buf);
|
||||
else if(command_prot == prot_confidential)
|
||||
fprintf(f, "CONF %s", buf);
|
||||
#endif
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sec_fprintf(FILE *f, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
va_start(ap, fmt);
|
||||
ret = sec_vfprintf(f, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* end common stuff */
|
||||
|
||||
#ifdef FTP_SERVER
|
||||
|
||||
void
|
||||
auth(char *auth_name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; (mech = mechs[i]) != NULL; i++){
|
||||
if(!strcasecmp(auth_name, mech->name)){
|
||||
app_data = realloc(app_data, mech->size);
|
||||
if(mech->init && (*mech->init)(app_data) != 0) {
|
||||
reply(431, "Unable to accept %s at this time", mech->name);
|
||||
return;
|
||||
}
|
||||
if(mech->auth) {
|
||||
(*mech->auth)(app_data);
|
||||
return;
|
||||
}
|
||||
if(mech->adat)
|
||||
reply(334, "Send authorization data.");
|
||||
else
|
||||
reply(234, "Authorization complete.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
reply(504, "%s is unknown to me", auth_name);
|
||||
}
|
||||
|
||||
void
|
||||
adat(char *auth_data)
|
||||
{
|
||||
if(mech && !sec_complete) {
|
||||
void *buf = malloc(strlen(auth_data));
|
||||
size_t len;
|
||||
len = base64_decode(auth_data, buf);
|
||||
(*mech->adat)(app_data, buf, len);
|
||||
free(buf);
|
||||
} else
|
||||
reply(503, "You must %sissue an AUTH first.", mech ? "re-" : "");
|
||||
}
|
||||
|
||||
void pbsz(int size)
|
||||
{
|
||||
size_t new = size;
|
||||
if(!sec_complete)
|
||||
reply(503, "Incomplete security data exchange.");
|
||||
if(mech->pbsz)
|
||||
new = (*mech->pbsz)(app_data, size);
|
||||
if(buffer_size != new){
|
||||
buffer_size = size;
|
||||
}
|
||||
if(new != size)
|
||||
reply(200, "PBSZ=%lu", new);
|
||||
else
|
||||
reply(200, "OK");
|
||||
}
|
||||
|
||||
void
|
||||
prot(char *pl)
|
||||
{
|
||||
int p = -1;
|
||||
|
||||
if(buffer_size == 0){
|
||||
reply(503, "No protection buffer size negotiated.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!strcasecmp(pl, "C"))
|
||||
p = prot_clear;
|
||||
else if(!strcasecmp(pl, "S"))
|
||||
p = prot_safe;
|
||||
else if(!strcasecmp(pl, "E"))
|
||||
p = prot_confidential;
|
||||
else if(!strcasecmp(pl, "P"))
|
||||
p = prot_private;
|
||||
else {
|
||||
reply(504, "Unrecognized protection level.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(sec_complete){
|
||||
if((*mech->check_prot)(app_data, p)){
|
||||
reply(536, "%s does not support %s protection.",
|
||||
mech->name, level_to_name(p));
|
||||
}else{
|
||||
data_prot = p;
|
||||
reply(200, "Data protection is %s.", level_to_name(p));
|
||||
}
|
||||
}else{
|
||||
reply(503, "Incomplete security data exchange.");
|
||||
}
|
||||
}
|
||||
|
||||
void ccc(void)
|
||||
{
|
||||
if(sec_complete){
|
||||
if(mech->ccc && (*mech->ccc)(app_data) == 0)
|
||||
command_prot = data_prot = prot_clear;
|
||||
else
|
||||
reply(534, "You must be joking.");
|
||||
}else
|
||||
reply(503, "Incomplete security data exchange.");
|
||||
}
|
||||
|
||||
void mec(char *msg, enum protection_level level)
|
||||
{
|
||||
void *buf;
|
||||
size_t len;
|
||||
if(!sec_complete) {
|
||||
reply(503, "Incomplete security data exchange.");
|
||||
return;
|
||||
}
|
||||
buf = malloc(strlen(msg) + 2); /* XXX go figure out where that 2
|
||||
comes from :-) */
|
||||
len = base64_decode(msg, buf);
|
||||
command_prot = level;
|
||||
if(len == (size_t)-1) {
|
||||
reply(501, "Failed to base64-decode command");
|
||||
return;
|
||||
}
|
||||
len = (*mech->decode)(app_data, buf, len, level);
|
||||
if(len == (size_t)-1) {
|
||||
reply(535, "Failed to decode command");
|
||||
return;
|
||||
}
|
||||
((char*)buf)[len] = '\0';
|
||||
if(strstr((char*)buf, "\r\n") == NULL)
|
||||
strcat((char*)buf, "\r\n");
|
||||
new_ftp_command(buf);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
int
|
||||
sec_userok(char *user)
|
||||
{
|
||||
if(sec_complete)
|
||||
return (*mech->userok)(app_data, user);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ftp_command;
|
||||
|
||||
void
|
||||
new_ftp_command(char *command)
|
||||
{
|
||||
ftp_command = command;
|
||||
}
|
||||
|
||||
void
|
||||
delete_ftp_command(void)
|
||||
{
|
||||
free(ftp_command);
|
||||
ftp_command = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
secure_command(void)
|
||||
{
|
||||
return ftp_command != NULL;
|
||||
}
|
||||
|
||||
#else /* FTP_SERVER */
|
||||
|
||||
void
|
||||
sec_status(void)
|
||||
{
|
||||
if(sec_complete){
|
||||
printf("Using %s for authentication.\n", mech->name);
|
||||
printf("Using %s command channel.\n", level_to_name(command_prot));
|
||||
printf("Using %s data channel.\n", level_to_name(data_prot));
|
||||
if(buffer_size > 0)
|
||||
printf("Protection buffer size: %lu.\n",
|
||||
(unsigned long)buffer_size);
|
||||
}else{
|
||||
printf("Not using any security mechanism.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sec_prot_internal(int level)
|
||||
{
|
||||
int ret;
|
||||
char *p;
|
||||
unsigned int s = 1048576;
|
||||
|
||||
int old_verbose = verbose;
|
||||
verbose = 0;
|
||||
|
||||
if(!sec_complete){
|
||||
printf("No security data exchange has taken place.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(level){
|
||||
ret = command("PBSZ %u", s);
|
||||
if(ret != COMPLETE){
|
||||
printf("Failed to set protection buffer size.\n");
|
||||
return -1;
|
||||
}
|
||||
buffer_size = s;
|
||||
p = strstr(reply_string, "PBSZ=");
|
||||
if(p)
|
||||
sscanf(p, "PBSZ=%u", &s);
|
||||
if(s < buffer_size)
|
||||
buffer_size = s;
|
||||
}
|
||||
verbose = old_verbose;
|
||||
ret = command("PROT %c", level["CSEP"]); /* XXX :-) */
|
||||
if(ret != COMPLETE){
|
||||
printf("Failed to set protection level.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
data_prot = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
sec_prot(int argc, char **argv)
|
||||
{
|
||||
int level = -1;
|
||||
|
||||
if(argc != 2){
|
||||
printf("usage: %s (clear | safe | confidential | private)\n",
|
||||
argv[0]);
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
if(!sec_complete){
|
||||
printf("No security data exchange has taken place.\n");
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
level = name_to_level(argv[1]);
|
||||
|
||||
if(level == -1){
|
||||
printf("usage: %s (clear | safe | confidential | private)\n",
|
||||
argv[0]);
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if((*mech->check_prot)(app_data, level)) {
|
||||
printf("%s does not implement %s protection.\n",
|
||||
mech->name, level_to_name(level));
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(sec_prot_internal(level) < 0){
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
code = 0;
|
||||
}
|
||||
|
||||
static enum protection_level request_data_prot;
|
||||
|
||||
void
|
||||
sec_set_protection_level(void)
|
||||
{
|
||||
if(sec_complete && data_prot != request_data_prot)
|
||||
sec_prot_internal(request_data_prot);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sec_request_prot(char *level)
|
||||
{
|
||||
int l = name_to_level(level);
|
||||
if(l == -1)
|
||||
return -1;
|
||||
request_data_prot = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sec_login(char *host)
|
||||
{
|
||||
int ret;
|
||||
struct sec_client_mech **m;
|
||||
int old_verbose = verbose;
|
||||
|
||||
verbose = -1; /* shut up all messages this will produce (they
|
||||
are usually not very user friendly) */
|
||||
|
||||
for(m = mechs; (*m)->name; m++) {
|
||||
app_data = realloc(app_data, (*m)->size);
|
||||
if((*m)->init && (*(*m)->init)(app_data) != 0) {
|
||||
printf("Skipping %s...\n", (*m)->name);
|
||||
continue;
|
||||
}
|
||||
printf("Trying %s...\n", (*m)->name);
|
||||
ret = command("AUTH %s", (*m)->name);
|
||||
if(ret != CONTINUE){
|
||||
if(code == 504){
|
||||
printf("%s is not supported by the server.\n", (*m)->name);
|
||||
}else if(code == 534){
|
||||
printf("%s rejected as security mechanism.\n", (*m)->name);
|
||||
}else if(ret == ERROR) {
|
||||
printf("The server doesn't understand the FTP "
|
||||
"security extensions.\n");
|
||||
verbose = old_verbose;
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = (*(*m)->auth)(app_data, host);
|
||||
|
||||
if(ret != 0){
|
||||
/* mechanism is supposed to output error string */
|
||||
verbose = old_verbose;
|
||||
return -1;
|
||||
}
|
||||
mech = *m;
|
||||
sec_complete = 1;
|
||||
command_prot = prot_safe;
|
||||
break;
|
||||
}
|
||||
|
||||
verbose = old_verbose;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
sec_end(void)
|
||||
{
|
||||
if(mech->end)
|
||||
(*mech->end)(app_data);
|
||||
sec_complete = 0;
|
||||
data_prot = 0;
|
||||
memset(app_data, 0, mech->size);
|
||||
free(app_data);
|
||||
}
|
||||
|
||||
#endif /* FTP_SERVER */
|
||||
|
||||
131
appl/ftp/ftp/security.h
Normal file
131
appl/ftp/ftp/security.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef __security_h__
|
||||
#define __security_h__
|
||||
|
||||
enum protection_level {
|
||||
prot_clear,
|
||||
prot_safe,
|
||||
prot_confidential,
|
||||
prot_private
|
||||
};
|
||||
|
||||
extern enum protection_level command_prot;
|
||||
extern enum protection_level data_prot;
|
||||
extern size_t buffer_size;
|
||||
extern void *data_buffer;
|
||||
|
||||
struct sec_client_mech {
|
||||
char *name;
|
||||
size_t size;
|
||||
int (*init)(void *);
|
||||
int (*auth)(void *, char*);
|
||||
void (*end)(void *);
|
||||
int (*check_prot)(void *, int);
|
||||
int (*overhead)(void *, int, int);
|
||||
int (*encode)(void *, void*, int, int, void**);
|
||||
int (*decode)(void *, void*, int, int);
|
||||
};
|
||||
|
||||
struct sec_server_mech {
|
||||
char *name;
|
||||
size_t size;
|
||||
int (*init)(void *);
|
||||
void (*end)(void *);
|
||||
int (*check_prot)(void *, int);
|
||||
int (*overhead)(void *, int, int);
|
||||
int (*encode)(void *, void*, int, int, void**);
|
||||
int (*decode)(void *, void*, int, int);
|
||||
|
||||
int (*auth)(void *);
|
||||
int (*adat)(void *, void*, size_t);
|
||||
size_t (*pbsz)(void *, size_t);
|
||||
int (*ccc)(void*);
|
||||
int (*userok)(void*, char*);
|
||||
};
|
||||
|
||||
#ifdef FTP_SERVER
|
||||
extern struct sec_server_mech krb4_server_mech, gss_server_mech;
|
||||
#else
|
||||
extern struct sec_client_mech krb4_client_mech, gss_client_mech;
|
||||
#endif
|
||||
|
||||
extern int sec_complete;
|
||||
|
||||
#ifdef FTP_SERVER
|
||||
extern char *ftp_command;
|
||||
void new_ftp_command(char*);
|
||||
void delete_ftp_command(void);
|
||||
#endif
|
||||
|
||||
/* ---- */
|
||||
|
||||
|
||||
int sec_fflush (FILE *);
|
||||
int sec_fprintf (FILE *, const char *, ...);
|
||||
int sec_getc (FILE *);
|
||||
int sec_putc (int, FILE *);
|
||||
int sec_read (int, void *, int);
|
||||
int sec_read_msg (char *, int);
|
||||
int sec_vfprintf (FILE *, const char *, va_list);
|
||||
int sec_write (int, char *, int);
|
||||
|
||||
#ifdef FTP_SERVER
|
||||
void adat (char *);
|
||||
void auth (char *);
|
||||
void ccc (void);
|
||||
void mec (char *, enum protection_level);
|
||||
void pbsz (int);
|
||||
void prot (char *);
|
||||
void delete_ftp_command (void);
|
||||
void new_ftp_command (char *);
|
||||
int sec_userok (char *);
|
||||
int secure_command (void);
|
||||
#else
|
||||
void sec_end (void);
|
||||
int sec_login (char *);
|
||||
void sec_prot (int, char **);
|
||||
int sec_request_prot (char *);
|
||||
void sec_set_protection_level (void);
|
||||
void sec_status (void);
|
||||
#endif
|
||||
|
||||
#endif /* __security_h__ */
|
||||
Reference in New Issue
Block a user