Encryption of data stream. Cleanup.
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@391 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -20,7 +20,7 @@ libdir = $(exec_prefix)/lib
|
|||||||
|
|
||||||
ATHENA = /usr/athena
|
ATHENA = /usr/athena
|
||||||
|
|
||||||
ftp_OBJS = cmds.o cmdtab.o ftp.o main.o ruserpass.o domacro.o globals.o
|
ftp_OBJS = cmds.o cmdtab.o ftp.o krb4.o main.o ruserpass.o domacro.o globals.o kauth.o
|
||||||
|
|
||||||
all: ftp
|
all: ftp
|
||||||
|
|
||||||
|
@@ -106,6 +106,9 @@ char umaskhelp[] = "get (set) umask on remote side";
|
|||||||
char userhelp[] = "send new user information";
|
char userhelp[] = "send new user information";
|
||||||
char verbosehelp[] = "toggle verbose mode";
|
char verbosehelp[] = "toggle verbose mode";
|
||||||
|
|
||||||
|
char prothelp[] = "set protection level";
|
||||||
|
char kauthhelp[] = "get remote tokens";
|
||||||
|
|
||||||
struct cmd cmdtab[] = {
|
struct cmd cmdtab[] = {
|
||||||
{ "!", shellhelp, 0, 0, 0, shell },
|
{ "!", shellhelp, 0, 0, 0, shell },
|
||||||
{ "$", domachelp, 1, 0, 0, domacro },
|
{ "$", domachelp, 1, 0, 0, domacro },
|
||||||
@@ -179,6 +182,10 @@ struct cmd cmdtab[] = {
|
|||||||
{ "umask", umaskhelp, 0, 1, 1, do_umask },
|
{ "umask", umaskhelp, 0, 1, 1, do_umask },
|
||||||
{ "verbose", verbosehelp, 0, 0, 0, setverbose },
|
{ "verbose", verbosehelp, 0, 0, 0, setverbose },
|
||||||
{ "?", helphelp, 0, 0, 1, help },
|
{ "?", helphelp, 0, 0, 1, help },
|
||||||
|
|
||||||
|
{ "prot", prothelp, 0, 1, 0, sec_prot },
|
||||||
|
{ "kauth", kauthhelp, 0, 1, 0, kauth },
|
||||||
|
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -165,3 +165,5 @@ extern int proxy;
|
|||||||
extern char reply_string[];
|
extern char reply_string[];
|
||||||
extern off_t restart_point;
|
extern off_t restart_point;
|
||||||
extern int NCMDS;
|
extern int NCMDS;
|
||||||
|
|
||||||
|
extern char username[32];
|
||||||
|
@@ -35,8 +35,6 @@
|
|||||||
|
|
||||||
#include "ftp_locl.h"
|
#include "ftp_locl.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct sockaddr_in hisctladdr;
|
struct sockaddr_in hisctladdr;
|
||||||
struct sockaddr_in data_addr;
|
struct sockaddr_in data_addr;
|
||||||
int data = -1;
|
int data = -1;
|
||||||
@@ -159,77 +157,6 @@ bad:
|
|||||||
return ((char *)0);
|
return ((char *)0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <des.h>
|
|
||||||
#include <krb.h>
|
|
||||||
|
|
||||||
int krb4_auth = 0;
|
|
||||||
KTEXT_ST krb4_adat;
|
|
||||||
|
|
||||||
static des_cblock key;
|
|
||||||
static des_key_schedule schedule;
|
|
||||||
|
|
||||||
int do_auth(char *service, char *host)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
CREDENTIALS cred;
|
|
||||||
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
|
|
||||||
strcpy(sname, service);
|
|
||||||
strcpy(inst, krb_get_phost(host));
|
|
||||||
strcpy(realm, krb_realmofhost(host));
|
|
||||||
ret = krb_mk_req(&krb4_adat, sname, inst, realm, 0);
|
|
||||||
if(ret)
|
|
||||||
return ret;
|
|
||||||
strcpy(sname, service);
|
|
||||||
strcpy(inst, krb_get_phost(host));
|
|
||||||
strcpy(realm, krb_realmofhost(host));
|
|
||||||
ret = krb_get_cred(sname, inst, realm, &cred);
|
|
||||||
memmove(&key, &cred.session, sizeof(des_cblock));
|
|
||||||
des_key_sched(&key, schedule);
|
|
||||||
memset(&cred, 0, sizeof(cred));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int do_klogin(char *host)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
char *phost;
|
|
||||||
char *p, *q;
|
|
||||||
int len;
|
|
||||||
char *serv = "ftp";
|
|
||||||
char adat[1024];
|
|
||||||
MSG_DAT msg_data;
|
|
||||||
int checksum;
|
|
||||||
|
|
||||||
ret = command("AUTH KERBEROS_V4");
|
|
||||||
if(ret == CONTINUE){
|
|
||||||
ret = do_auth("ftp", host);
|
|
||||||
if(ret == KDC_PR_UNKNOWN)
|
|
||||||
ret = do_auth("rcmd", host);
|
|
||||||
if(ret)
|
|
||||||
return ret;
|
|
||||||
base64_encode(krb4_adat.dat, krb4_adat.length, &p);
|
|
||||||
ret = command("ADAT %s", p);
|
|
||||||
free(p);
|
|
||||||
if(ret == COMPLETE){
|
|
||||||
p = strstr(reply_string, "ADAT=");
|
|
||||||
if(p){
|
|
||||||
p+=5;
|
|
||||||
for(q = p; isalnum(*q) || strchr("/+=", *q); q++);
|
|
||||||
*q = 0;
|
|
||||||
len = base64_decode(p, adat);
|
|
||||||
ret = krb_rd_safe(adat, len, &key,
|
|
||||||
&hisctladdr, &myctladdr, &msg_data);
|
|
||||||
memmove(&checksum, msg_data.app_data, 4);
|
|
||||||
checksum = ntohl(checksum);
|
|
||||||
}
|
|
||||||
krb4_auth = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
login(char *host)
|
login(char *host)
|
||||||
{
|
{
|
||||||
@@ -263,13 +190,17 @@ login(char *host)
|
|||||||
user = tmp;
|
user = tmp;
|
||||||
}
|
}
|
||||||
if(strcmp(user, "ftp") && strcmp(user, "anonymous")){
|
if(strcmp(user, "ftp") && strcmp(user, "anonymous")){
|
||||||
do_klogin(host);
|
if(do_klogin(host) < 0)
|
||||||
|
fprintf(stderr, "Resorting to plaintext user and password.\n");
|
||||||
}
|
}
|
||||||
|
strcpy(username, user);
|
||||||
n = command("USER %s", user);
|
n = command("USER %s", user);
|
||||||
if (n == CONTINUE) {
|
if (n == CONTINUE) {
|
||||||
if (pass == NULL)
|
if(auth_complete)
|
||||||
pass = getpass("Password:");
|
pass = user;
|
||||||
n = command("PASS %s", pass);
|
else if (pass == NULL)
|
||||||
|
pass = getpass("Password:");
|
||||||
|
n = command("PASS %s", pass);
|
||||||
}
|
}
|
||||||
if (n == CONTINUE) {
|
if (n == CONTINUE) {
|
||||||
aflag++;
|
aflag++;
|
||||||
@@ -306,69 +237,6 @@ cmdabort(int sig)
|
|||||||
longjmp(ptabort,1);
|
longjmp(ptabort,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_write_enc(FILE *F, char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char *p;
|
|
||||||
char buf[1024];
|
|
||||||
char enc[1024];
|
|
||||||
vsprintf(buf, fmt, ap);
|
|
||||||
len = krb_mk_priv(buf, enc, strlen(buf), schedule, &key,
|
|
||||||
&myctladdr, &hisctladdr);
|
|
||||||
base64_encode(enc, len, &p);
|
|
||||||
|
|
||||||
fprintf(F, "ENC %s", p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int krb4_read_msg(char *s, int priv)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
int ret;
|
|
||||||
char buf[1024];
|
|
||||||
MSG_DAT m;
|
|
||||||
int code;
|
|
||||||
|
|
||||||
len = base64_decode(s + 4, buf);
|
|
||||||
if(priv)
|
|
||||||
ret = krb_rd_priv(buf, len, schedule, &key,
|
|
||||||
&hisctladdr, &myctladdr, &m);
|
|
||||||
else
|
|
||||||
ret = krb_rd_safe(buf, len, &key, &myctladdr, &hisctladdr, &m);
|
|
||||||
if(ret){
|
|
||||||
fprintf(stderr, "%s\n", krb_get_err_text(ret));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m.app_data[m.app_length] = 0;
|
|
||||||
if(m.app_data[3] == '-')
|
|
||||||
code = 0;
|
|
||||||
else
|
|
||||||
sscanf((char*)m.app_data, "%d", &code);
|
|
||||||
strncpy(s, (char*)m.app_data, strlen((char*)m.app_data));
|
|
||||||
|
|
||||||
s[m.app_length] = 0;
|
|
||||||
len = strlen(s);
|
|
||||||
if(s[len-1] == '\n')
|
|
||||||
s[len-1] = 0;
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
krb4_read_mic(char *s)
|
|
||||||
{
|
|
||||||
return krb4_read_msg(s, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
krb4_read_enc(char *s)
|
|
||||||
{
|
|
||||||
return krb4_read_msg(s, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
command(char *fmt, ...)
|
command(char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -391,7 +259,7 @@ command(char *fmt, ...)
|
|||||||
printf("PASS XXXX");
|
printf("PASS XXXX");
|
||||||
else
|
else
|
||||||
vfprintf(stdout, fmt, ap);
|
vfprintf(stdout, fmt, ap);
|
||||||
if(krb4_auth)
|
if(auth_complete)
|
||||||
krb4_write_enc(cout, fmt, ap);
|
krb4_write_enc(cout, fmt, ap);
|
||||||
else
|
else
|
||||||
vfprintf(cout, fmt, ap);
|
vfprintf(cout, fmt, ap);
|
||||||
@@ -464,8 +332,8 @@ getreply(int expecteof)
|
|||||||
sscanf(buf, "%d", &code);
|
sscanf(buf, "%d", &code);
|
||||||
fprintf(stdout, "P:");
|
fprintf(stdout, "P:");
|
||||||
}else if(code == 633){
|
}else if(code == 633){
|
||||||
fprintf(stdout, "Confidentiality is meaningless:/n");
|
fprintf(stdout, "Confidentiality is meaningless:\n");
|
||||||
}else if(krb4_auth)
|
}else if(auth_complete)
|
||||||
fprintf(stdout, "!!"); /* clear text */
|
fprintf(stdout, "!!"); /* clear text */
|
||||||
fprintf(stdout, "%s\n", buf);
|
fprintf(stdout, "%s\n", buf);
|
||||||
if(buf[3] == ' '){
|
if(buf[3] == ' '){
|
||||||
@@ -484,7 +352,7 @@ getreply(int expecteof)
|
|||||||
return code / 100;
|
return code / 100;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(krb4_auth)
|
if(auth_complete)
|
||||||
fprintf(stdout, "!!");
|
fprintf(stdout, "!!");
|
||||||
fprintf(stdout, "%s\n", buf);
|
fprintf(stdout, "%s\n", buf);
|
||||||
}
|
}
|
||||||
@@ -589,7 +457,7 @@ getreply(int expecteof)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
if(krb4_auth){
|
if(auth_complete){
|
||||||
if(code == 631)
|
if(code == 631)
|
||||||
krb4_read_mic(reply_string);
|
krb4_read_mic(reply_string);
|
||||||
else
|
else
|
||||||
@@ -784,8 +652,8 @@ sendrequest(char *cmd, char *local, char *remote, int printnames)
|
|||||||
while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
|
while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
|
||||||
bytes += c;
|
bytes += c;
|
||||||
for (bufp = buf; c > 0; c -= d, bufp += d)
|
for (bufp = buf; c > 0; c -= d, bufp += d)
|
||||||
if ((d = write(fileno(dout), bufp, c)) <= 0)
|
if ((d = sec_write(fileno(dout), bufp, c)) <= 0)
|
||||||
break;
|
break;
|
||||||
if (hash) {
|
if (hash) {
|
||||||
while (bytes >= hashbytes) {
|
while (bytes >= hashbytes) {
|
||||||
(void) putchar('#');
|
(void) putchar('#');
|
||||||
@@ -794,6 +662,7 @@ sendrequest(char *cmd, char *local, char *remote, int printnames)
|
|||||||
(void) fflush(stdout);
|
(void) fflush(stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sec_fflush(dout);
|
||||||
if (hash && bytes > 0) {
|
if (hash && bytes > 0) {
|
||||||
if (bytes < HASHBYTES)
|
if (bytes < HASHBYTES)
|
||||||
(void) putchar('#');
|
(void) putchar('#');
|
||||||
@@ -810,39 +679,36 @@ sendrequest(char *cmd, char *local, char *remote, int printnames)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_A:
|
case TYPE_A:
|
||||||
while ((c = getc(fin)) != EOF) {
|
while ((c = getc(fin)) != EOF) {
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
while (hash && (bytes >= hashbytes)) {
|
while (hash && (bytes >= hashbytes)) {
|
||||||
(void) putchar('#');
|
(void) putchar('#');
|
||||||
(void) fflush(stdout);
|
|
||||||
hashbytes += HASHBYTES;
|
|
||||||
}
|
|
||||||
if (ferror(dout))
|
|
||||||
break;
|
|
||||||
(void) putc('\r', dout);
|
|
||||||
bytes++;
|
|
||||||
}
|
|
||||||
(void) putc(c, dout);
|
|
||||||
bytes++;
|
|
||||||
/* if (c == '\r') { */
|
|
||||||
/* (void) putc('\0', dout); // this violates rfc */
|
|
||||||
/* bytes++; */
|
|
||||||
/* } */
|
|
||||||
}
|
|
||||||
if (hash) {
|
|
||||||
if (bytes < hashbytes)
|
|
||||||
(void) putchar('#');
|
|
||||||
(void) putchar('\n');
|
|
||||||
(void) fflush(stdout);
|
(void) fflush(stdout);
|
||||||
|
hashbytes += HASHBYTES;
|
||||||
|
}
|
||||||
|
if (ferror(dout))
|
||||||
|
break;
|
||||||
|
(void) sec_putc('\r', dout);
|
||||||
|
bytes++;
|
||||||
}
|
}
|
||||||
if (ferror(fin))
|
sec_putc(c, dout);
|
||||||
warn("local: %s", local);
|
bytes++;
|
||||||
if (ferror(dout)) {
|
}
|
||||||
if (errno != EPIPE)
|
sec_fflush(dout);
|
||||||
warn("netout");
|
if (hash) {
|
||||||
bytes = -1;
|
if (bytes < hashbytes)
|
||||||
}
|
(void) putchar('#');
|
||||||
break;
|
(void) putchar('\n');
|
||||||
|
(void) fflush(stdout);
|
||||||
|
}
|
||||||
|
if (ferror(fin))
|
||||||
|
warn("local: %s", local);
|
||||||
|
if (ferror(dout)) {
|
||||||
|
if (errno != EPIPE)
|
||||||
|
warn("netout");
|
||||||
|
bytes = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (closefunc != NULL)
|
if (closefunc != NULL)
|
||||||
(*closefunc)(fin);
|
(*closefunc)(fin);
|
||||||
@@ -1048,17 +914,17 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
errno = d = 0;
|
errno = d = 0;
|
||||||
while ((c = read(fileno(din), buf, bufsize)) > 0) {
|
while ((c = sec_read(fileno(din), buf, bufsize)) > 0) {
|
||||||
if ((d = write(fileno(fout), buf, c)) != c)
|
if ((d = write(fileno(fout), buf, c)) != c)
|
||||||
break;
|
break;
|
||||||
bytes += c;
|
bytes += c;
|
||||||
if (hash) {
|
if (hash) {
|
||||||
while (bytes >= hashbytes) {
|
while (bytes >= hashbytes) {
|
||||||
(void) putchar('#');
|
(void) putchar('#');
|
||||||
hashbytes += HASHBYTES;
|
hashbytes += HASHBYTES;
|
||||||
}
|
|
||||||
(void) fflush(stdout);
|
|
||||||
}
|
}
|
||||||
|
(void) fflush(stdout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hash && bytes > 0) {
|
if (hash && bytes > 0) {
|
||||||
if (bytes < HASHBYTES)
|
if (bytes < HASHBYTES)
|
||||||
@@ -1087,7 +953,7 @@ recvrequest(char *cmd, char *local, char *remote, char *lmode, int printnames)
|
|||||||
goto done;
|
goto done;
|
||||||
n = restart_point;
|
n = restart_point;
|
||||||
for (i = 0; i++ < n;) {
|
for (i = 0; i++ < n;) {
|
||||||
if ((ch = getc(fout)) == EOF)
|
if ((ch = sec_getc(fout)) == EOF)
|
||||||
goto done;
|
goto done;
|
||||||
if (ch == '\n')
|
if (ch == '\n')
|
||||||
i++;
|
i++;
|
||||||
@@ -1100,7 +966,8 @@ done:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ((c = getc(din)) != EOF) {
|
|
||||||
|
while ((c = sec_getc(din)) != EOF) {
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
bare_lfs++;
|
bare_lfs++;
|
||||||
while (c == '\r') {
|
while (c == '\r') {
|
||||||
@@ -1110,7 +977,7 @@ done:
|
|||||||
hashbytes += HASHBYTES;
|
hashbytes += HASHBYTES;
|
||||||
}
|
}
|
||||||
bytes++;
|
bytes++;
|
||||||
if ((c = getc(din)) != '\n' || tcrflag) {
|
if ((c = sec_getc(din)) != '\n' || tcrflag) {
|
||||||
if (ferror(fout))
|
if (ferror(fout))
|
||||||
goto break2;
|
goto break2;
|
||||||
(void) putc('\r', fout);
|
(void) putc('\r', fout);
|
||||||
|
@@ -26,12 +26,15 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "ftp_var.h"
|
#include "ftp_var.h"
|
||||||
#include "pathnames.h"
|
#include "pathnames.h"
|
||||||
|
|
||||||
|
#include "krb4.h"
|
||||||
|
|
||||||
#if defined(__sun__) && !defined(__svr4)
|
#if defined(__sun__) && !defined(__svr4)
|
||||||
int fclose(FILE*);
|
int fclose(FILE*);
|
||||||
int pclose(FILE*);
|
int pclose(FILE*);
|
||||||
|
@@ -127,3 +127,5 @@ struct macel {
|
|||||||
extern int macnum; /* number of defined macros */
|
extern int macnum; /* number of defined macros */
|
||||||
extern struct macel macros[16];
|
extern struct macel macros[16];
|
||||||
extern char macbuf[4096];
|
extern char macbuf[4096];
|
||||||
|
|
||||||
|
|
||||||
|
@@ -69,3 +69,5 @@ int options; /* used during socket creation */
|
|||||||
int macnum; /* number of defined macros */
|
int macnum; /* number of defined macros */
|
||||||
struct macel macros[16];
|
struct macel macros[16];
|
||||||
char macbuf[4096];
|
char macbuf[4096];
|
||||||
|
|
||||||
|
char username[32];
|
||||||
|
75
appl/ftp/ftp/kauth.c
Normal file
75
appl/ftp/ftp/kauth.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ftp_locl.h"
|
||||||
|
#include <krb.h>
|
||||||
|
|
||||||
|
void kauth(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char buf[1024];
|
||||||
|
des_cblock key;
|
||||||
|
des_key_schedule schedule;
|
||||||
|
KTEXT_ST tkt;
|
||||||
|
char *name;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
|
||||||
|
if(argc > 2){
|
||||||
|
printf("usage: %s [principal]\n", argv[0]);
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(argc == 2)
|
||||||
|
name = argv[1];
|
||||||
|
else
|
||||||
|
name = username;
|
||||||
|
ret = command("SITE KAUTH %s", name);
|
||||||
|
if(ret != CONTINUE){
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p = strstr(reply_string, "T=");
|
||||||
|
if(!p){
|
||||||
|
printf("Bad reply from server.\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p += 2;
|
||||||
|
tkt.length = base64_decode(p, &tkt.dat);
|
||||||
|
if(tkt.length < 0){
|
||||||
|
printf("Failed to decode base64 in reply.\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strstr(reply_string, "P=");
|
||||||
|
if(!p){
|
||||||
|
printf("Bad reply from server.\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
name = p + 2;
|
||||||
|
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
|
||||||
|
sprintf(buf, "Password for %s:", name);
|
||||||
|
des_read_password(&key, buf, 0);
|
||||||
|
|
||||||
|
des_set_key(&key, schedule);
|
||||||
|
|
||||||
|
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tkt.dat, tkt.length,
|
||||||
|
schedule, &key, DES_DECRYPT);
|
||||||
|
memset(key, 0, sizeof(key));
|
||||||
|
memset(schedule, 0, sizeof(schedule));
|
||||||
|
base64_encode(tkt.dat, tkt.length, &p);
|
||||||
|
ret = command("SITE KAUTH %s %s", name, p);
|
||||||
|
free(p);
|
||||||
|
if(ret != COMPLETE){
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
code = 0;
|
||||||
|
}
|
421
appl/ftp/ftp/krb4.c
Normal file
421
appl/ftp/ftp/krb4.c
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
|
||||||
|
#include "ftp_locl.h"
|
||||||
|
|
||||||
|
#include <des.h>
|
||||||
|
#include <krb.h>
|
||||||
|
|
||||||
|
KTEXT_ST krb4_adat;
|
||||||
|
|
||||||
|
static des_cblock key;
|
||||||
|
static des_key_schedule schedule;
|
||||||
|
|
||||||
|
static char *data_buffer;
|
||||||
|
|
||||||
|
enum { prot_clear, prot_safe, prot_confidential, prot_private };
|
||||||
|
|
||||||
|
extern struct sockaddr_in hisctladdr, myctladdr;
|
||||||
|
|
||||||
|
int auth_complete;
|
||||||
|
|
||||||
|
static int command_prot;
|
||||||
|
|
||||||
|
static int auth_pbsz;
|
||||||
|
static int data_prot;
|
||||||
|
|
||||||
|
void sec_prot(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
int ret;
|
||||||
|
char *p;
|
||||||
|
int level = -1;
|
||||||
|
if(argc != 2){
|
||||||
|
fprintf(stderr, "foo?\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!auth_complete){
|
||||||
|
fprintf(stderr, "ehu?\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!strcmp(argv[1], "clear"))
|
||||||
|
level = prot_clear;
|
||||||
|
|
||||||
|
if(!strcmp(argv[1], "safe"))
|
||||||
|
level = prot_safe;
|
||||||
|
|
||||||
|
if(!strcmp(argv[1], "private"))
|
||||||
|
level = prot_private;
|
||||||
|
|
||||||
|
if(level == -1){
|
||||||
|
fprintf(stderr, "ehu?\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(level){
|
||||||
|
s = 65536;
|
||||||
|
ret = command("PBSZ %d", s);
|
||||||
|
if(ret != COMPLETE){
|
||||||
|
fprintf(stderr, "Ehu?\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auth_pbsz = s;
|
||||||
|
p = strstr(reply_string, "PBSZ=");
|
||||||
|
if(p)
|
||||||
|
sscanf(p, "PBSZ=%d", &s);
|
||||||
|
if(s < auth_pbsz)
|
||||||
|
auth_pbsz = s;
|
||||||
|
if(data_buffer)
|
||||||
|
free(data_buffer);
|
||||||
|
data_buffer = malloc(auth_pbsz);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = command("PROT %c", level["CSEP"]); /* XXX :-) */
|
||||||
|
if(ret != COMPLETE){
|
||||||
|
fprintf(stderr, "Ehu?\n");
|
||||||
|
code = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data_prot = level;
|
||||||
|
code = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int sec_getc(FILE *F)
|
||||||
|
{
|
||||||
|
if(auth_complete && data_prot)
|
||||||
|
return krb4_getc(F);
|
||||||
|
else
|
||||||
|
return getc(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sec_read(int fd, void *data, int length)
|
||||||
|
{
|
||||||
|
if(auth_complete && data_prot)
|
||||||
|
return krb4_read(fd, data, length);
|
||||||
|
else
|
||||||
|
return read(fd, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb4_recv(int fd)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
MSG_DAT m;
|
||||||
|
int kerror;
|
||||||
|
|
||||||
|
krb_net_read(fd, &len, sizeof(len));
|
||||||
|
len = ntohl(len);
|
||||||
|
krb_net_read(fd, data_buffer, len);
|
||||||
|
if(data_prot == prot_safe)
|
||||||
|
kerror = krb_rd_safe(data_buffer, len, &key,
|
||||||
|
&hisctladdr, &myctladdr, &m);
|
||||||
|
else
|
||||||
|
kerror = krb_rd_priv(data_buffer, len, schedule, &key,
|
||||||
|
&hisctladdr, &myctladdr, &m);
|
||||||
|
if(kerror){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memmove(data_buffer, m.app_data, m.app_length);
|
||||||
|
return m.app_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int krb4_getc(FILE *F)
|
||||||
|
{
|
||||||
|
static int bytes;
|
||||||
|
static int index;
|
||||||
|
if(bytes == 0){
|
||||||
|
bytes = krb4_recv(fileno(F));
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
if(bytes){
|
||||||
|
bytes--;
|
||||||
|
return data_buffer[index++];
|
||||||
|
}
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int krb4_read(int fd, char *data, int length)
|
||||||
|
{
|
||||||
|
static int left;
|
||||||
|
static int index;
|
||||||
|
static int eof;
|
||||||
|
int len = left;
|
||||||
|
int rx = 0;
|
||||||
|
|
||||||
|
if(eof){
|
||||||
|
eof = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(left){
|
||||||
|
if(length < len)
|
||||||
|
len = length;
|
||||||
|
memmove(data, data_buffer + index, len);
|
||||||
|
length -= len;
|
||||||
|
index += len;
|
||||||
|
rx += len;
|
||||||
|
left -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(length){
|
||||||
|
len = krb4_recv(fd);
|
||||||
|
if(len == 0){
|
||||||
|
if(rx)
|
||||||
|
eof = 1;
|
||||||
|
return rx;
|
||||||
|
}
|
||||||
|
if(len > length){
|
||||||
|
left = len - length;
|
||||||
|
len = index = length;
|
||||||
|
}
|
||||||
|
memmove(data, data_buffer, len);
|
||||||
|
length -= len;
|
||||||
|
data += len;
|
||||||
|
rx += len;
|
||||||
|
}
|
||||||
|
return rx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb4_encode(char *from, char *to, int length)
|
||||||
|
{
|
||||||
|
if(data_prot == prot_safe)
|
||||||
|
return krb_mk_safe(from, to, length, &key,
|
||||||
|
&myctladdr, &hisctladdr);
|
||||||
|
else
|
||||||
|
return krb_mk_priv(from, to, length, schedule, &key,
|
||||||
|
&myctladdr, &hisctladdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krb4_overhead(int len)
|
||||||
|
{
|
||||||
|
if(data_prot == prot_safe)
|
||||||
|
return 31;
|
||||||
|
else
|
||||||
|
return 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char p_buf[1024];
|
||||||
|
static int p_index;
|
||||||
|
|
||||||
|
int
|
||||||
|
sec_putc(int c, FILE *F)
|
||||||
|
{
|
||||||
|
if(data_prot){
|
||||||
|
if((c == '\n' && p_index) || p_index == sizeof(p_buf)){
|
||||||
|
sec_write(fileno(F), p_buf, p_index);
|
||||||
|
p_index = 0;
|
||||||
|
}
|
||||||
|
p_buf[p_index++] = c;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return putc(c, F);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sec_send(int fd, char *from, int length)
|
||||||
|
{
|
||||||
|
int bytes;
|
||||||
|
bytes = krb4_encode(from, data_buffer, length);
|
||||||
|
bytes = htonl(bytes);
|
||||||
|
krb_net_write(fd, &bytes, sizeof(bytes));
|
||||||
|
krb_net_write(fd, data_buffer, ntohl(bytes));
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sec_fflush(FILE *F)
|
||||||
|
{
|
||||||
|
if(data_prot){
|
||||||
|
if(index){
|
||||||
|
sec_write(fileno(F), p_buf, p_index);
|
||||||
|
p_index = 0;
|
||||||
|
}
|
||||||
|
sec_send(fileno(F), NULL, 0);
|
||||||
|
}
|
||||||
|
fflush(F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sec_write(int fd, char *data, int length)
|
||||||
|
{
|
||||||
|
int len = auth_pbsz;
|
||||||
|
int tx = 0;
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
if(data_prot == prot_clear)
|
||||||
|
return write(fd, data, length);
|
||||||
|
|
||||||
|
len -= krb4_overhead(len);
|
||||||
|
while(length){
|
||||||
|
if(length < len)
|
||||||
|
len = length;
|
||||||
|
sec_send(fd, data, len);
|
||||||
|
length -= len;
|
||||||
|
data += len;
|
||||||
|
tx += len;
|
||||||
|
}
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_auth(char *service, char *host, int checksum)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
CREDENTIALS cred;
|
||||||
|
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
|
||||||
|
strcpy(sname, service);
|
||||||
|
strcpy(inst, krb_get_phost(host));
|
||||||
|
strcpy(realm, krb_realmofhost(host));
|
||||||
|
ret = krb_mk_req(&krb4_adat, sname, inst, realm, checksum);
|
||||||
|
if(ret)
|
||||||
|
return ret;
|
||||||
|
strcpy(sname, service);
|
||||||
|
strcpy(inst, krb_get_phost(host));
|
||||||
|
strcpy(realm, krb_realmofhost(host));
|
||||||
|
ret = krb_get_cred(sname, inst, realm, &cred);
|
||||||
|
memmove(&key, &cred.session, sizeof(des_cblock));
|
||||||
|
des_key_sched(&key, schedule);
|
||||||
|
memset(&cred, 0, sizeof(cred));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
do_klogin(char *host)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *phost;
|
||||||
|
char *p, *q;
|
||||||
|
int len;
|
||||||
|
char adat[1024];
|
||||||
|
MSG_DAT msg_data;
|
||||||
|
int checksum;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
ret = command("AUTH KERBEROS_V4");
|
||||||
|
if(ret != CONTINUE){
|
||||||
|
if(code == 504){
|
||||||
|
fprintf(stderr, "Kerberos is not supported by the server.\n");
|
||||||
|
}else if(code == 534){
|
||||||
|
fprintf(stderr, "KERBEROS_V4 rejected as security mechanism.\n");
|
||||||
|
}else if(ret == ERROR)
|
||||||
|
fprintf(stderr, "The server doesn't understand the FTP "
|
||||||
|
"security extentions.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
checksum = getpid();
|
||||||
|
ret = do_auth("ftp", host, checksum);
|
||||||
|
if(ret == KDC_PR_UNKNOWN)
|
||||||
|
ret = do_auth("rcmd", host, checksum);
|
||||||
|
if(ret){
|
||||||
|
fprintf(stderr, "%s\n", krb_get_err_text(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
base64_encode(krb4_adat.dat, krb4_adat.length, &p);
|
||||||
|
ret = command("ADAT %s", p);
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
if(ret != COMPLETE){
|
||||||
|
fprintf(stderr, "Server didn't accept auth data.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = strstr(reply_string, "ADAT=");
|
||||||
|
if(!p){
|
||||||
|
fprintf(stderr, "Remote host didn't send adat reply.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p+=5;
|
||||||
|
len = base64_decode(p, adat);
|
||||||
|
if(len < 0){
|
||||||
|
fprintf(stderr, "Failed to decode base64 from server.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = krb_rd_safe(adat, len, &key,
|
||||||
|
&hisctladdr, &myctladdr, &msg_data);
|
||||||
|
if(ret){
|
||||||
|
fprintf(stderr, "Error reading reply from server: %s.",
|
||||||
|
krb_get_err_text(ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memmove(&tmp, msg_data.app_data, 4);
|
||||||
|
tmp = ntohl(tmp);
|
||||||
|
if(tmp - checksum != 1){
|
||||||
|
fprintf(stderr, "Bad checksum returned from server.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auth_complete = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int krb4_write_enc(FILE *F, char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *p;
|
||||||
|
char buf[1024];
|
||||||
|
char enc[1024];
|
||||||
|
vsprintf(buf, fmt, ap);
|
||||||
|
len = krb_mk_priv(buf, enc, strlen(buf), schedule, &key,
|
||||||
|
&myctladdr, &hisctladdr);
|
||||||
|
base64_encode(enc, len, &p);
|
||||||
|
|
||||||
|
fprintf(F, "ENC %s", p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int krb4_read_msg(char *s, int priv)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int ret;
|
||||||
|
char buf[1024];
|
||||||
|
MSG_DAT m;
|
||||||
|
int code;
|
||||||
|
|
||||||
|
len = base64_decode(s + 4, buf);
|
||||||
|
if(priv)
|
||||||
|
ret = krb_rd_priv(buf, len, schedule, &key,
|
||||||
|
&hisctladdr, &myctladdr, &m);
|
||||||
|
else
|
||||||
|
ret = krb_rd_safe(buf, len, &key, &myctladdr, &hisctladdr, &m);
|
||||||
|
if(ret){
|
||||||
|
fprintf(stderr, "%s\n", krb_get_err_text(ret));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.app_data[m.app_length] = 0;
|
||||||
|
if(m.app_data[3] == '-')
|
||||||
|
code = 0;
|
||||||
|
else
|
||||||
|
sscanf((char*)m.app_data, "%d", &code);
|
||||||
|
strncpy(s, (char*)m.app_data, strlen((char*)m.app_data));
|
||||||
|
|
||||||
|
s[m.app_length] = 0;
|
||||||
|
len = strlen(s);
|
||||||
|
if(s[len-1] == '\n')
|
||||||
|
s[len-1] = 0;
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
krb4_read_mic(char *s)
|
||||||
|
{
|
||||||
|
return krb4_read_msg(s, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
krb4_read_enc(char *s)
|
||||||
|
{
|
||||||
|
return krb4_read_msg(s, 1);
|
||||||
|
}
|
||||||
|
|
10
appl/ftp/ftp/krb4.h
Normal file
10
appl/ftp/ftp/krb4.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __KRB4_H__
|
||||||
|
#define __KRB4_H__
|
||||||
|
|
||||||
|
extern int auth_complete;
|
||||||
|
|
||||||
|
void sec_prot(int, char**);
|
||||||
|
|
||||||
|
void kauth(int, char **);
|
||||||
|
|
||||||
|
#endif /* __KRB4_H__ */
|
@@ -38,7 +38,7 @@
|
|||||||
#include "ftp_locl.h"
|
#include "ftp_locl.h"
|
||||||
|
|
||||||
#ifndef HAVE___PROGNAME
|
#ifndef HAVE___PROGNAME
|
||||||
char *__progname;
|
char *__progname = "ftp";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -55,10 +55,6 @@ main(int argc, char **argv)
|
|||||||
interactive = 1;
|
interactive = 1;
|
||||||
autologin = 1;
|
autologin = 1;
|
||||||
|
|
||||||
#ifndef HAVE___PROGNAME
|
|
||||||
__progname = argv[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "dgintv")) != EOF) {
|
while ((ch = getopt(argc, argv, "dgintv")) != EOF) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'd':
|
case 'd':
|
||||||
|
@@ -19,18 +19,18 @@ libdir = $(exec_prefix)/lib
|
|||||||
|
|
||||||
ATHENA = /usr/athena
|
ATHENA = /usr/athena
|
||||||
|
|
||||||
ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o auth.o krb4.o
|
ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o auth.o krb4.o kauth.o
|
||||||
|
|
||||||
all: ftpd
|
all: ftpd
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) -c $(CFLAGS) -I.. -I$(srcdir)/.. -I../common -I$(srcdir)/../common -I$(ATHENA)/include $(DEFS) $<
|
$(CC) -c $(CFLAGS) -I. -I$(srcdir) -I.. -I$(srcdir)/.. -I../common -I$(srcdir)/../common -I$(ATHENA)/include $(DEFS) $<
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
||||||
|
|
||||||
ftpd: $(ftpd_OBJS) ../common/libcommon.a
|
ftpd: $(ftpd_OBJS) ../common/libcommon.a
|
||||||
$(CC) -o ftpd $(ftpd_OBJS) ../common/libcommon.a -L$(ATHENA)/lib -lkrb -ldes
|
$(CC) -o ftpd $(ftpd_OBJS) ../common/libcommon.a -L$(ATHENA)/lib -lkafs -lkrb -ldes
|
||||||
|
|
||||||
ftpcmd.c: ftpcmd.y
|
ftpcmd.c: ftpcmd.y
|
||||||
$(YACC) $(YFLAGS) $<
|
$(YACC) $(YFLAGS) $<
|
||||||
|
@@ -12,18 +12,26 @@
|
|||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
|
|
||||||
static struct at auth_types [] = {
|
static struct at auth_types [] = {
|
||||||
{ "KERBEROS_V4", krb4_auth, krb4_adat, krb4_pbsz, krb4_prot, krb4_ccc,
|
{ "KERBEROS_V4", krb4_auth, krb4_adat, krb4_pbsz, krb4_prot, krb4_ccc,
|
||||||
krb4_mic, krb4_conf, krb4_enc, krb4_userok, krb4_vprintf },
|
krb4_mic, krb4_conf, krb4_enc, krb4_read, krb4_write, krb4_userok,
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
krb4_vprintf },
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct at *ct;
|
struct at *ct;
|
||||||
|
|
||||||
int data_protection;
|
int data_protection;
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
|
unsigned char *data_buffer;
|
||||||
int auth_complete;
|
int auth_complete;
|
||||||
|
|
||||||
|
|
||||||
|
char *protection_names[] = {
|
||||||
|
"clear", "safe",
|
||||||
|
"confidential", "private"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void auth_init(void)
|
void auth_init(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -33,99 +41,154 @@ int prot_level;
|
|||||||
|
|
||||||
void new_ftp_command(char *command)
|
void new_ftp_command(char *command)
|
||||||
{
|
{
|
||||||
ftp_command = command;
|
ftp_command = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_ftp_command(void)
|
void delete_ftp_command(void)
|
||||||
{
|
{
|
||||||
if(ftp_command){
|
if(ftp_command){
|
||||||
free(ftp_command);
|
free(ftp_command);
|
||||||
ftp_command = NULL;
|
ftp_command = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void auth(char *auth)
|
void auth(char *auth)
|
||||||
{
|
{
|
||||||
for(ct=auth_types; ct->name; ct++){
|
for(ct=auth_types; ct->name; ct++){
|
||||||
if(!strcmp(auth, ct->name)){
|
if(!strcasecmp(auth, ct->name)){
|
||||||
ct->auth(auth);
|
ct->auth(auth);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
reply(504, "%s is not a known security mechanism", auth);
|
||||||
reply(504, "%s is not a known security mechanism", auth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void adat(char *auth)
|
void adat(char *auth)
|
||||||
{
|
{
|
||||||
if(ct)
|
if(ct && !auth_complete)
|
||||||
ct->adat(auth);
|
ct->adat(auth);
|
||||||
else
|
else
|
||||||
reply(503, "Error, error");
|
reply(503, "You must (re)issue an AUTH first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pbsz(int size)
|
void pbsz(int size)
|
||||||
{
|
{
|
||||||
if(ct)
|
int old = buffer_size;
|
||||||
ct->pbsz(size);
|
if(ct && auth_complete)
|
||||||
else
|
ct->pbsz(size);
|
||||||
reply(503, "Error, error");
|
else
|
||||||
|
reply(503, "Incomplete security data exchange.");
|
||||||
|
if(buffer_size != old){
|
||||||
|
if(data_buffer)
|
||||||
|
free(data_buffer);
|
||||||
|
data_buffer = malloc(buffer_size + 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prot(char *pl)
|
void prot(char *pl)
|
||||||
{
|
{
|
||||||
if(ct)
|
int p = -1;
|
||||||
ct->prot(pl);
|
|
||||||
else
|
if(buffer_size == 0){
|
||||||
reply(503, "Error, error");
|
reply(503, "No protection buffer size negotiated.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcasecmp(pl, "C"))
|
||||||
|
p = prot_clear;
|
||||||
|
|
||||||
|
if(!strcasecmp(pl, "S"))
|
||||||
|
p = prot_safe;
|
||||||
|
|
||||||
|
if(!strcasecmp(pl, "E"))
|
||||||
|
p = prot_confidential;
|
||||||
|
|
||||||
|
if(!strcasecmp(pl, "P"))
|
||||||
|
p = prot_private;
|
||||||
|
|
||||||
|
if(p == -1){
|
||||||
|
reply(504, "Unrecognized protection level.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ct && auth_complete){
|
||||||
|
if(ct->prot(p)){
|
||||||
|
reply(536, "%s does not support %s protection.",
|
||||||
|
ct->name, protection_names[p]);
|
||||||
|
}else{
|
||||||
|
data_protection = p;
|
||||||
|
reply(200, "Data protection is %s.",
|
||||||
|
protection_names[data_protection]);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
reply(503, "Incomplete security data exchange.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ccc(void)
|
void ccc(void)
|
||||||
{
|
{
|
||||||
if(ct)
|
if(ct && auth_complete){
|
||||||
ct->ccc();
|
if(!ct->ccc())
|
||||||
else
|
prot_level = prot_clear;
|
||||||
reply(503, "Error, error");
|
}else
|
||||||
|
reply(503, "Incomplete security data exchange.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void mic(char *msg)
|
void mic(char *msg)
|
||||||
{
|
{
|
||||||
prot_level = prot_safe;
|
if(ct && auth_complete){
|
||||||
if(ct)
|
if(!ct->mic(msg))
|
||||||
ct->mic(msg);
|
prot_level = prot_safe;
|
||||||
else
|
}else
|
||||||
reply(500, "Command unrecognized");
|
reply(503, "Incomplete security data exchange.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void conf(char *msg)
|
void conf(char *msg)
|
||||||
{
|
{
|
||||||
prot_level = prot_confidential;
|
if(ct && auth_complete){
|
||||||
if(ct)
|
if(!ct->conf(msg))
|
||||||
ct->conf(msg);
|
prot_level = prot_confidential;
|
||||||
else
|
}else
|
||||||
reply(500, "Command unrecognized");
|
reply(503, "Incomplete security data exchange.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void enc(char *msg)
|
void enc(char *msg)
|
||||||
{
|
{
|
||||||
prot_level = prot_private;
|
if(ct && auth_complete){
|
||||||
if(ct)
|
if(!ct->enc(msg))
|
||||||
ct->enc(msg);
|
prot_level = prot_private;
|
||||||
else
|
}else
|
||||||
reply(500, "Command unrecognized");
|
reply(503, "Incomplete security data exchange.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int auth_read(int fd, void *data, int length)
|
||||||
|
{
|
||||||
|
if(ct && auth_complete && data_protection)
|
||||||
|
return ct->read(fd, data, length);
|
||||||
|
else
|
||||||
|
return read(fd, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int auth_write(int fd, void *data, int length)
|
||||||
|
{
|
||||||
|
if(ct && auth_complete && data_protection)
|
||||||
|
return ct->write(fd, data, length);
|
||||||
|
else
|
||||||
|
return write(fd, data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void auth_vprintf(const char *fmt, va_list ap)
|
void auth_vprintf(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
if(ct && auth_complete && prot_level){
|
if(ct && auth_complete && prot_level){
|
||||||
ct->vprintf(fmt, ap);
|
ct->vprintf(fmt, ap);
|
||||||
}else
|
}else
|
||||||
vprintf(fmt, ap);
|
vprintf(fmt, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void auth_printf(const char *fmt, ...)
|
void auth_printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
auth_vprintf(fmt, ap);
|
auth_vprintf(fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _AUTH_H_
|
#ifndef __AUTH_H__
|
||||||
#define _AUTH_H_
|
#define __AUTH_H__
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
@@ -8,27 +8,32 @@ struct at {
|
|||||||
int (*auth)(char*);
|
int (*auth)(char*);
|
||||||
int (*adat)(char*);
|
int (*adat)(char*);
|
||||||
int (*pbsz)(int);
|
int (*pbsz)(int);
|
||||||
int (*prot)(char*);
|
int (*prot)(int);
|
||||||
int (*ccc)(void);
|
int (*ccc)(void);
|
||||||
int (*mic)(char*);
|
int (*mic)(char*);
|
||||||
int (*conf)(char*);
|
int (*conf)(char*);
|
||||||
int (*enc)(char*);
|
int (*enc)(char*);
|
||||||
|
int (*read)(int, void*, int);
|
||||||
|
int (*write)(int, void*, int);
|
||||||
int (*userok)(char*);
|
int (*userok)(char*);
|
||||||
int (*vprintf)(const char*, va_list);
|
int (*vprintf)(const char*, va_list);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct at *ct;
|
extern struct at *ct;
|
||||||
|
|
||||||
enum protection_levels {
|
enum protection_levels {
|
||||||
prot_clear, prot_safe, prot_confidential, prot_private
|
prot_clear, prot_safe, prot_confidential, prot_private
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern char *protection_names[];
|
||||||
|
|
||||||
extern char *ftp_command;
|
extern char *ftp_command;
|
||||||
extern int prot_level;
|
extern int prot_level;
|
||||||
|
|
||||||
int data_protection;
|
extern int data_protection;
|
||||||
int buffer_size;
|
extern int buffer_size;
|
||||||
int auth_complete;
|
extern unsigned char *data_buffer;
|
||||||
|
extern int auth_complete;
|
||||||
|
|
||||||
void auth_init(void);
|
void auth_init(void);
|
||||||
|
|
||||||
@@ -41,9 +46,12 @@ void mic(char*);
|
|||||||
void conf(char*);
|
void conf(char*);
|
||||||
void enc(char*);
|
void enc(char*);
|
||||||
|
|
||||||
|
int auth_read(int, void*, int);
|
||||||
|
int auth_write(int, void*, int);
|
||||||
|
|
||||||
void auth_vprintf(const char *fmt, va_list ap);
|
void auth_vprintf(const char *fmt, va_list ap);
|
||||||
void auth_printf(const char *fmt, ...);
|
void auth_printf(const char *fmt, ...);
|
||||||
|
|
||||||
void new_ftp_command(char *command);
|
void new_ftp_command(char *command);
|
||||||
|
|
||||||
#endif /* _AUTH_H_ */
|
#endif /* __AUTH_H__ */
|
||||||
|
@@ -77,6 +77,8 @@ void upper(char *);
|
|||||||
void user(char *);
|
void user(char *);
|
||||||
void yyerror(char *);
|
void yyerror(char *);
|
||||||
|
|
||||||
|
void kauth(char *, char*);
|
||||||
|
|
||||||
extern struct sockaddr_in ctrl_addr, his_addr;
|
extern struct sockaddr_in ctrl_addr, his_addr;
|
||||||
extern char hostname[];
|
extern char hostname[];
|
||||||
|
|
||||||
@@ -102,5 +104,4 @@ extern int usedefault;
|
|||||||
extern int transflag;
|
extern int transflag;
|
||||||
extern char tmpline[];
|
extern char tmpline[];
|
||||||
|
|
||||||
|
|
||||||
#endif /* _EXTERN_H_ */
|
#endif /* _EXTERN_H_ */
|
||||||
|
@@ -107,6 +107,8 @@ char *fromname;
|
|||||||
AUTH ADAT PROT PBSZ CCC MIC
|
AUTH ADAT PROT PBSZ CCC MIC
|
||||||
CONF ENC
|
CONF ENC
|
||||||
|
|
||||||
|
KAUTH
|
||||||
|
|
||||||
LEXERR
|
LEXERR
|
||||||
|
|
||||||
%token <s> STRING
|
%token <s> STRING
|
||||||
@@ -475,6 +477,24 @@ cmd
|
|||||||
timeout);
|
timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| SITE SP KAUTH SP STRING CRLF
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
size_t s;
|
||||||
|
|
||||||
|
p = strpbrk($5, " \t");
|
||||||
|
if(p){
|
||||||
|
*p++ = 0;
|
||||||
|
s = strspn(p, " \t");
|
||||||
|
if(s >= 0)
|
||||||
|
kauth($5, p + s);
|
||||||
|
else
|
||||||
|
kauth($5, p);
|
||||||
|
}else
|
||||||
|
kauth($5, NULL);
|
||||||
|
free($5);
|
||||||
|
}
|
||||||
| STOU check_login SP pathname CRLF
|
| STOU check_login SP pathname CRLF
|
||||||
{
|
{
|
||||||
if ($2 && $4 != NULL)
|
if ($2 && $4 != NULL)
|
||||||
@@ -841,7 +861,7 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */
|
|||||||
{ "AUTH", AUTH, STR1, 1, "<sp> auth-type" },
|
{ "AUTH", AUTH, STR1, 1, "<sp> auth-type" },
|
||||||
{ "ADAT", ADAT, STR1, 1, "<sp> auth-data" },
|
{ "ADAT", ADAT, STR1, 1, "<sp> auth-data" },
|
||||||
{ "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" },
|
{ "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" },
|
||||||
{ "PROT", PROT, ARGS, 1, "<sp> prot-level" },
|
{ "PROT", PROT, STR1, 1, "<sp> prot-level" },
|
||||||
{ "CCC", CCC, ARGS, 1, "" },
|
{ "CCC", CCC, ARGS, 1, "" },
|
||||||
{ "MIC", MIC, STR1, 1, "<sp> integrity command" },
|
{ "MIC", MIC, STR1, 1, "<sp> integrity command" },
|
||||||
{ "CONF", CONF, STR1, 1, "<sp> confidentiality command" },
|
{ "CONF", CONF, STR1, 1, "<sp> confidentiality command" },
|
||||||
@@ -855,6 +875,9 @@ struct tab sitetab[] = {
|
|||||||
{ "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
|
{ "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
|
||||||
{ "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
|
{ "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
|
||||||
{ "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
|
{ "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
|
||||||
|
|
||||||
|
{ "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" },
|
||||||
|
|
||||||
{ NULL, 0, 0, 0, 0 }
|
{ NULL, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -867,9 +890,7 @@ static void toolong __P((int));
|
|||||||
static int yylex __P((void));
|
static int yylex __P((void));
|
||||||
|
|
||||||
static struct tab *
|
static struct tab *
|
||||||
lookup(p, cmd)
|
lookup(struct tab *p, char *cmd)
|
||||||
struct tab *p;
|
|
||||||
char *cmd;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
for (; p->name != NULL; p++)
|
for (; p->name != NULL; p++)
|
||||||
@@ -958,8 +979,7 @@ getline(char *s, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
toolong(signo)
|
toolong(int signo)
|
||||||
int signo;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
reply(421,
|
reply(421,
|
||||||
@@ -971,7 +991,7 @@ toolong(signo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
yylex()
|
yylex(void)
|
||||||
{
|
{
|
||||||
static int cpos, state;
|
static int cpos, state;
|
||||||
char *cp, *cp2;
|
char *cp, *cp2;
|
||||||
@@ -1189,8 +1209,7 @@ yylex()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
upper(s)
|
upper(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
while (*s != '\0') {
|
while (*s != '\0') {
|
||||||
if (islower(*s))
|
if (islower(*s))
|
||||||
@@ -1200,8 +1219,7 @@ upper(s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
copy(s)
|
copy(char *s)
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
@@ -1213,9 +1231,7 @@ copy(s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
help(ctab, s)
|
help(struct tab *ctab, char *s)
|
||||||
struct tab *ctab;
|
|
||||||
char *s;
|
|
||||||
{
|
{
|
||||||
struct tab *c;
|
struct tab *c;
|
||||||
int width, NCMDS;
|
int width, NCMDS;
|
||||||
@@ -1278,8 +1294,7 @@ help(ctab, s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sizecmd(filename)
|
sizecmd(char *filename)
|
||||||
char *filename;
|
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_L:
|
case TYPE_L:
|
||||||
|
@@ -226,23 +226,23 @@ curdir(void)
|
|||||||
|
|
||||||
static void conn_wait(void)
|
static void conn_wait(void)
|
||||||
{
|
{
|
||||||
int s, t;
|
int s, t;
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
int one = 1;
|
int one = 1;
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sin_port = htons(21);
|
sa.sin_port = htons(21);
|
||||||
sa.sin_addr.s_addr = INADDR_ANY;
|
sa.sin_addr.s_addr = INADDR_ANY;
|
||||||
bind(s, (struct sockaddr*)&sa, sizeof(sa));
|
bind(s, (struct sockaddr*)&sa, sizeof(sa));
|
||||||
listen(s, 5);
|
listen(s, 5);
|
||||||
t = accept(s, NULL, 0);
|
t = accept(s, NULL, 0);
|
||||||
close(s);
|
close(s);
|
||||||
dup2(t, 0);
|
dup2(t, 0);
|
||||||
dup2(t, 1);
|
dup2(t, 1);
|
||||||
if(t > 2)
|
if(t > 2)
|
||||||
close(t);
|
close(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -258,10 +258,16 @@ main(int argc, char **argv, char **envp)
|
|||||||
char *cp, line[LINE_MAX];
|
char *cp, line[LINE_MAX];
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
|
|
||||||
|
char tkfile[1024];
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
conn_wait();
|
conn_wait();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
sprintf(tkfile, "/tmp/ftp_%d", getpid());
|
||||||
|
setenv("KRBTKFILE", tkfile);
|
||||||
|
if(k_hasafs())
|
||||||
|
k_setpag();
|
||||||
/*
|
/*
|
||||||
* LOG_NDELAY sets up the logging connection immediately,
|
* LOG_NDELAY sets up the logging connection immediately,
|
||||||
* necessary for anonymous ftp's that chroot and can't do it later.
|
* necessary for anonymous ftp's that chroot and can't do it later.
|
||||||
@@ -988,6 +994,8 @@ send_data(FILE *instr, FILE *outstr, off_t blksize)
|
|||||||
{
|
{
|
||||||
int c, cnt, filefd, netfd;
|
int c, cnt, filefd, netfd;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
int i = 0;
|
||||||
|
char s[1024];
|
||||||
|
|
||||||
transflag++;
|
transflag++;
|
||||||
if (setjmp(urgcatch)) {
|
if (setjmp(urgcatch)) {
|
||||||
@@ -998,14 +1006,18 @@ send_data(FILE *instr, FILE *outstr, off_t blksize)
|
|||||||
|
|
||||||
case TYPE_A:
|
case TYPE_A:
|
||||||
while ((c = getc(instr)) != EOF) {
|
while ((c = getc(instr)) != EOF) {
|
||||||
byte_count++;
|
byte_count++;
|
||||||
if (c == '\n') {
|
if(i > 1022){
|
||||||
if (ferror(outstr))
|
auth_write(fileno(outstr), s, i);
|
||||||
goto data_err;
|
i = 0;
|
||||||
(void) putc('\r', outstr);
|
}
|
||||||
}
|
if(c == '\n')
|
||||||
(void) putc(c, outstr);
|
s[i++] = '\r';
|
||||||
|
s[i++] = c;
|
||||||
}
|
}
|
||||||
|
if(i)
|
||||||
|
auth_write(fileno(outstr), s, i);
|
||||||
|
auth_write(fileno(outstr), s, 0);
|
||||||
fflush(outstr);
|
fflush(outstr);
|
||||||
transflag = 0;
|
transflag = 0;
|
||||||
if (ferror(instr))
|
if (ferror(instr))
|
||||||
@@ -1025,8 +1037,9 @@ send_data(FILE *instr, FILE *outstr, off_t blksize)
|
|||||||
netfd = fileno(outstr);
|
netfd = fileno(outstr);
|
||||||
filefd = fileno(instr);
|
filefd = fileno(instr);
|
||||||
while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
|
while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
|
||||||
write(netfd, buf, cnt) == cnt)
|
auth_write(netfd, buf, cnt) == cnt)
|
||||||
byte_count += cnt;
|
byte_count += cnt;
|
||||||
|
auth_write(netfd, buf, 0); /* to end an encrypted stream */
|
||||||
transflag = 0;
|
transflag = 0;
|
||||||
(void)free(buf);
|
(void)free(buf);
|
||||||
if (cnt != 0) {
|
if (cnt != 0) {
|
||||||
@@ -1061,79 +1074,90 @@ file_err:
|
|||||||
static int
|
static int
|
||||||
receive_data(FILE *instr, FILE *outstr)
|
receive_data(FILE *instr, FILE *outstr)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int cnt, bare_lfs = 0;
|
int cnt, bare_lfs = 0;
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
transflag++;
|
transflag++;
|
||||||
if (setjmp(urgcatch)) {
|
if (setjmp(urgcatch)) {
|
||||||
transflag = 0;
|
transflag = 0;
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case TYPE_I:
|
||||||
|
case TYPE_L:
|
||||||
|
while ((cnt = auth_read(fileno(instr), buf, sizeof(buf))) > 0) {
|
||||||
|
if (write(fileno(outstr), buf, cnt) != cnt)
|
||||||
|
goto file_err;
|
||||||
|
byte_count += cnt;
|
||||||
}
|
}
|
||||||
switch (type) {
|
if (cnt < 0)
|
||||||
|
goto data_err;
|
||||||
|
transflag = 0;
|
||||||
|
return (0);
|
||||||
|
|
||||||
case TYPE_I:
|
case TYPE_E:
|
||||||
case TYPE_L:
|
reply(553, "TYPE E not implemented.");
|
||||||
while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
|
transflag = 0;
|
||||||
if (write(fileno(outstr), buf, cnt) != cnt)
|
return (-1);
|
||||||
goto file_err;
|
|
||||||
byte_count += cnt;
|
|
||||||
}
|
|
||||||
if (cnt < 0)
|
|
||||||
goto data_err;
|
|
||||||
transflag = 0;
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
case TYPE_E:
|
case TYPE_A:
|
||||||
reply(553, "TYPE E not implemented.");
|
{
|
||||||
transflag = 0;
|
char *p, *q;
|
||||||
return (-1);
|
int cr_flag = 0;
|
||||||
|
while ((cnt = auth_read(fileno(instr), buf+cr_flag, sizeof(buf))) > 0){
|
||||||
case TYPE_A:
|
byte_count += cnt;
|
||||||
while ((c = getc(instr)) != EOF) {
|
cr_flag = 0;
|
||||||
byte_count++;
|
for(p = buf, q = buf; p < buf + cnt;){
|
||||||
if (c == '\n')
|
if(*p == '\n')
|
||||||
bare_lfs++;
|
bare_lfs++;
|
||||||
while (c == '\r') {
|
if(*p == '\r')
|
||||||
if (ferror(outstr))
|
if(p == buf + cnt - 1){
|
||||||
goto data_err;
|
cr_flag = 1;
|
||||||
if ((c = getc(instr)) != '\n') {
|
p++;
|
||||||
(void) putc ('\r', outstr);
|
continue;
|
||||||
if (c == '\0' || c == EOF)
|
}else if(p[1] == '\n'){
|
||||||
goto contin2;
|
*q++ = '\n';
|
||||||
}
|
p += 2;
|
||||||
}
|
continue;
|
||||||
(void) putc(c, outstr);
|
}
|
||||||
contin2: ;
|
*q++ = *p++;
|
||||||
}
|
}
|
||||||
fflush(outstr);
|
fwrite(buf, q - buf, 1, outstr);
|
||||||
if (ferror(instr))
|
if(cr_flag)
|
||||||
goto data_err;
|
buf[0] = '\r';
|
||||||
if (ferror(outstr))
|
|
||||||
goto file_err;
|
|
||||||
transflag = 0;
|
|
||||||
if (bare_lfs) {
|
|
||||||
lreply(226,
|
|
||||||
"WARNING! %d bare linefeeds received in ASCII mode",
|
|
||||||
bare_lfs);
|
|
||||||
(void)printf(" File may not have transferred correctly.\r\n");
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
default:
|
|
||||||
reply(550, "Unimplemented TYPE %d in receive_data", type);
|
|
||||||
transflag = 0;
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
if(cr_flag)
|
||||||
|
putc('\r', outstr);
|
||||||
|
fflush(outstr);
|
||||||
|
if (ferror(instr))
|
||||||
|
goto data_err;
|
||||||
|
if (ferror(outstr))
|
||||||
|
goto file_err;
|
||||||
|
transflag = 0;
|
||||||
|
if (bare_lfs) {
|
||||||
|
lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n"
|
||||||
|
" File may not have transferred correctly.\r\n",
|
||||||
|
bare_lfs);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
reply(550, "Unimplemented TYPE %d in receive_data", type);
|
||||||
|
transflag = 0;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
data_err:
|
data_err:
|
||||||
transflag = 0;
|
transflag = 0;
|
||||||
perror_reply(426, "Data Connection");
|
perror_reply(426, "Data Connection");
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
file_err:
|
file_err:
|
||||||
transflag = 0;
|
transflag = 0;
|
||||||
perror_reply(452, "Error writing file");
|
perror_reply(452, "Error writing file");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1417,10 +1441,9 @@ dologout(int status)
|
|||||||
if (logged_in) {
|
if (logged_in) {
|
||||||
(void) seteuid((uid_t)0);
|
(void) seteuid((uid_t)0);
|
||||||
logwtmp(ttyline, "", "");
|
logwtmp(ttyline, "", "");
|
||||||
#if defined(KERBEROS)
|
dest_tkt();
|
||||||
if (!notickets && krbtkfile_env)
|
if(k_hasafs())
|
||||||
unlink(krbtkfile_env);
|
k_unlog();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/* beware of flushing buffers after a SIGPIPE */
|
/* beware of flushing buffers after a SIGPIPE */
|
||||||
_exit(status);
|
_exit(status);
|
||||||
|
175
appl/ftp/ftpd/kauth.c
Normal file
175
appl/ftp/ftpd/kauth.c
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <des.h>
|
||||||
|
#include <krb.h>
|
||||||
|
#include <kafs.h>
|
||||||
|
|
||||||
|
#include "extern.h"
|
||||||
|
#include "krb4.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
|
|
||||||
|
static KTEXT_ST cip;
|
||||||
|
static time_t local_time;
|
||||||
|
|
||||||
|
static char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
|
||||||
|
|
||||||
|
static int
|
||||||
|
save_tkt(char *user, char *instance, char *realm, void *arg,
|
||||||
|
key_proc_t key_proc, KTEXT *cipp)
|
||||||
|
{
|
||||||
|
local_time = time(0);
|
||||||
|
memmove(&cip, *cipp, sizeof(cip));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
store_ticket(KTEXT cip)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
des_cblock session;
|
||||||
|
char sname[SNAME_SZ];
|
||||||
|
char sinst[INST_SZ];
|
||||||
|
char srealm[REALM_SZ];
|
||||||
|
unsigned char lifetime;
|
||||||
|
unsigned char kvno;
|
||||||
|
KTEXT_ST tkt;
|
||||||
|
|
||||||
|
int kerror;
|
||||||
|
|
||||||
|
time_t kdc_time;
|
||||||
|
|
||||||
|
ptr = (char *) cip->dat;
|
||||||
|
|
||||||
|
/* extract session key */
|
||||||
|
memmove(session, ptr, 8);
|
||||||
|
ptr += 8;
|
||||||
|
|
||||||
|
if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
|
||||||
|
return(INTK_BADPW);
|
||||||
|
|
||||||
|
/* extract server's name */
|
||||||
|
strcpy(sname,ptr);
|
||||||
|
ptr += strlen(sname) + 1;
|
||||||
|
|
||||||
|
if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
|
||||||
|
return(INTK_BADPW);
|
||||||
|
|
||||||
|
/* extract server's instance */
|
||||||
|
strcpy(sinst, ptr);
|
||||||
|
ptr += strlen(sinst) + 1;
|
||||||
|
|
||||||
|
if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
|
||||||
|
return(INTK_BADPW);
|
||||||
|
|
||||||
|
/* extract server's realm */
|
||||||
|
strcpy(srealm,ptr);
|
||||||
|
ptr += strlen(srealm) + 1;
|
||||||
|
|
||||||
|
/* extract ticket lifetime, server key version, ticket length */
|
||||||
|
/* be sure to avoid sign extension on lifetime! */
|
||||||
|
lifetime = (unsigned char) ptr[0];
|
||||||
|
kvno = (unsigned char) ptr[1];
|
||||||
|
tkt.length = (unsigned char) ptr[2];
|
||||||
|
ptr += 3;
|
||||||
|
|
||||||
|
if ((tkt.length < 0) ||
|
||||||
|
((tkt.length + (ptr - (char *) cip->dat)) > cip->length))
|
||||||
|
return(INTK_BADPW);
|
||||||
|
|
||||||
|
/* extract ticket itself */
|
||||||
|
memmove(tkt.dat, ptr, tkt.length);
|
||||||
|
ptr += tkt.length;
|
||||||
|
|
||||||
|
/* Here is where the time should be verified against the KDC.
|
||||||
|
* Unfortunately everything is sent in host byte order (receiver
|
||||||
|
* makes wrong) , and at this stage there is no way for us to know
|
||||||
|
* which byteorder the KDC has. So we simply ignore the time,
|
||||||
|
* there are no security risks with this, the only thing that can
|
||||||
|
* happen is that we might receive a replayed ticket, which could
|
||||||
|
* at most be useless.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* check KDC time stamp */
|
||||||
|
memmove(&kdc_time, ptr, sizeof(kdc_time));
|
||||||
|
if (swap_bytes) swap_u_long(kdc_time);
|
||||||
|
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) {
|
||||||
|
return(RD_AP_TIME); /* XXX should probably be better
|
||||||
|
code */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* initialize ticket cache */
|
||||||
|
|
||||||
|
if (tf_create(TKT_FILE) != KSUCCESS)
|
||||||
|
return(INTK_ERR);
|
||||||
|
|
||||||
|
if (tf_put_pname(name) != KSUCCESS ||
|
||||||
|
tf_put_pinst(inst) != KSUCCESS) {
|
||||||
|
tf_close();
|
||||||
|
return(INTK_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kerror = tf_save_cred(sname, sinst, srealm, session, lifetime, kvno,
|
||||||
|
&tkt, local_time);
|
||||||
|
tf_close();
|
||||||
|
|
||||||
|
return(kerror);
|
||||||
|
}
|
||||||
|
|
||||||
|
void kauth(char *principal, char *ticket)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = kname_parse(name, inst, realm, principal);
|
||||||
|
if(ret){
|
||||||
|
reply(500, "Bad principal: %s.", krb_get_err_text(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(realm[0] == 0)
|
||||||
|
krb_get_lrealm(realm, 0);
|
||||||
|
|
||||||
|
if(ticket){
|
||||||
|
cip.length = base64_decode(ticket, &cip.dat);
|
||||||
|
if(cip.length == -1){
|
||||||
|
reply(500, "Failed to decode data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = store_ticket(&cip);
|
||||||
|
if(ret){
|
||||||
|
reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
|
||||||
|
memset(&cip, 0, sizeof(cip));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(k_hasafs())
|
||||||
|
k_afsklog(0, 0);
|
||||||
|
reply(200, "OK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb_get_in_tkt (name, inst, realm, "krbtgt", realm, 12,
|
||||||
|
NULL, save_tkt, NULL);
|
||||||
|
if(ret != INTK_BADPW){
|
||||||
|
reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
base64_encode(cip.dat, cip.length, &p);
|
||||||
|
reply(300, "P=%s%s%s@%s T=%s", name, *inst?".":"", inst, realm, p);
|
||||||
|
free(p);
|
||||||
|
memset(&cip, 0, sizeof(cip));
|
||||||
|
}
|
@@ -5,6 +5,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -20,176 +21,292 @@ static des_key_schedule schedule;
|
|||||||
|
|
||||||
int krb4_auth(char *auth)
|
int krb4_auth(char *auth)
|
||||||
{
|
{
|
||||||
auth_complete = 0;
|
auth_complete = 0;
|
||||||
reply(334, "Using authentication type %s; ADAT must follow", auth);
|
reply(334, "Using authentication type %s; ADAT must follow", auth);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_adat(char *auth)
|
int krb4_adat(char *auth)
|
||||||
{
|
{
|
||||||
KTEXT_ST tkt;
|
KTEXT_ST tkt;
|
||||||
char *p;
|
char *p;
|
||||||
int kerror;
|
int kerror;
|
||||||
u_int32_t cs;
|
u_int32_t cs;
|
||||||
char msg[35]; /* size of encrypted block */
|
char msg[35]; /* size of encrypted block */
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
char inst[INST_SZ];
|
char inst[INST_SZ];
|
||||||
|
|
||||||
memset(&tkt, 0, sizeof(tkt));
|
memset(&tkt, 0, sizeof(tkt));
|
||||||
tkt.length = base64_decode(auth, tkt.dat);
|
tkt.length = base64_decode(auth, tkt.dat);
|
||||||
|
|
||||||
strcpy(inst, "*");
|
if(tkt.length < 0){
|
||||||
kerror = krb_rd_req(&tkt, "ftp", inst, 0, &auth_dat, "");
|
reply(501, "Failed to decode base64 data.");
|
||||||
if(kerror == RD_AP_UNDEC){
|
return -1;
|
||||||
strcpy(inst, "*");
|
}
|
||||||
kerror = krb_rd_req(&tkt, "rcmd", inst, 0, &auth_dat, "");
|
|
||||||
}
|
k_getsockinst(0, inst);
|
||||||
|
kerror = krb_rd_req(&tkt, "ftp", inst, 0, &auth_dat, "");
|
||||||
|
if(kerror == RD_AP_UNDEC){
|
||||||
|
k_getsockinst(0, inst);
|
||||||
|
kerror = krb_rd_req(&tkt, "rcmd", inst, 0, &auth_dat, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kerror){
|
||||||
|
reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
des_key_sched(&auth_dat.session, schedule);
|
des_set_key(&auth_dat.session, schedule);
|
||||||
|
|
||||||
if(kerror != RD_AP_OK){
|
cs = htonl(auth_dat.checksum + 1);
|
||||||
reply(535, "%s", krb_err_txt[kerror]);
|
len = krb_mk_safe(&cs, msg, sizeof(cs), &auth_dat.session,
|
||||||
return 1;
|
&ctrl_addr, &his_addr);
|
||||||
}
|
if(len < 0){
|
||||||
|
reply(535, "Error creating reply: %s.", k_strerror(errno));
|
||||||
cs = htonl(auth_dat.checksum + 1);
|
return -1;
|
||||||
len = krb_mk_safe((u_char*)&cs, (u_char*)msg, sizeof(cs),
|
}
|
||||||
&auth_dat.session, &ctrl_addr, &his_addr);
|
base64_encode(msg, len, &p);
|
||||||
base64_encode((unsigned char*)msg, len, &p);
|
reply(235, "ADAT=%s", p);
|
||||||
reply(235, "ADAT=%s", p);
|
auth_complete = 1;
|
||||||
auth_complete = 1;
|
free(p);
|
||||||
free(p);
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_pbsz(int size)
|
int krb4_pbsz(int size)
|
||||||
{
|
{
|
||||||
buffer_size = size;
|
if(size > 1048576) /* XXX arbitrary number */
|
||||||
reply(200, "OK");
|
size = 1048576;
|
||||||
return 0;
|
buffer_size = size;
|
||||||
|
reply(200, "OK PBSZ=%d", buffer_size);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_prot(char *type)
|
int krb4_prot(int level)
|
||||||
{
|
{
|
||||||
if(!strcmp(type, "C")){
|
if(level == prot_confidential)
|
||||||
data_protection = prot_clear;
|
return -1;
|
||||||
}else if(!strcmp(type, "S")){
|
return 0;
|
||||||
data_protection = prot_safe;
|
|
||||||
}else if(!strcmp(type, "E")){
|
|
||||||
data_protection = prot_confidential;
|
|
||||||
}else if(!strcmp(type, "P")){
|
|
||||||
data_protection = prot_private;
|
|
||||||
}else{
|
|
||||||
reply(504, "Unrecognized protection level");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
reply(200, "OK");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_ccc(void)
|
int krb4_ccc(void)
|
||||||
{
|
{
|
||||||
reply(500, "Gurka");
|
reply(534, "Don't event think about it.");
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_mic(char *msg)
|
int krb4_mic(char *msg)
|
||||||
{
|
{
|
||||||
char *cmd = (char*)malloc(strlen(msg));
|
int len;
|
||||||
int len;
|
int kerror;
|
||||||
int kerror;
|
MSG_DAT m_data;
|
||||||
MSG_DAT m_data;
|
char *p;
|
||||||
char *p;
|
char *tmp, *cmd;
|
||||||
char tmp[1024];
|
|
||||||
unsigned char enc[1024];
|
|
||||||
|
|
||||||
len = base64_decode(msg, cmd);
|
cmd = strdup(msg);
|
||||||
kerror = krb_rd_safe(cmd, len, &auth_dat.session,
|
|
||||||
&ctrl_addr, &his_addr, &m_data);
|
len = base64_decode(msg, cmd);
|
||||||
sprintf(tmp, "%.*s\r\n", m_data.app_length, m_data.app_data);
|
if(len < 0){
|
||||||
new_ftp_command(strdup(tmp));
|
reply(501, "Failed to decode base 64 data.");
|
||||||
free(cmd);
|
free(cmd);
|
||||||
return 0;
|
return -1;
|
||||||
|
}
|
||||||
|
kerror = krb_rd_safe(cmd, len, &auth_dat.session,
|
||||||
|
&his_addr, &ctrl_addr, &m_data);
|
||||||
|
|
||||||
|
if(kerror){
|
||||||
|
reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
|
||||||
|
free(cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = strdup(msg);
|
||||||
|
sprintf(tmp, "%.*s", m_data.app_length, m_data.app_data);
|
||||||
|
if(!strstr(tmp, "\r\n"))
|
||||||
|
strcat(tmp, "\r\n");
|
||||||
|
new_ftp_command(tmp);
|
||||||
|
free(cmd);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_conf(char *msg)
|
int krb4_conf(char *msg)
|
||||||
{
|
{
|
||||||
char tmp[1024];
|
prot_level = prot_safe;
|
||||||
unsigned char enc[1024];
|
|
||||||
int len;
|
reply(537, "Protection level not supported.");
|
||||||
char *p;
|
return -1;
|
||||||
|
|
||||||
sprintf(tmp, "%d %s\r\n", 536,
|
|
||||||
"Requested PROT level not supported by mechanism");
|
|
||||||
len = krb_mk_safe((u_char*)tmp, (u_char*)enc, strlen(tmp), &auth_dat.session,
|
|
||||||
&ctrl_addr, &his_addr);
|
|
||||||
if(len > 0){
|
|
||||||
base64_encode(enc, len, &p);
|
|
||||||
fprintf(stdout, "631 %s\r\n", p);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_enc(char *msg)
|
int krb4_enc(char *msg)
|
||||||
{
|
{
|
||||||
char *cmd = (char*)malloc(strlen(msg));
|
int len;
|
||||||
int len;
|
int kerror;
|
||||||
int kerror;
|
MSG_DAT m_data;
|
||||||
MSG_DAT m_data;
|
char *p;
|
||||||
char *p;
|
char *tmp, *cmd;
|
||||||
|
|
||||||
char tmp[1024];
|
|
||||||
unsigned char enc[1024];
|
|
||||||
|
|
||||||
len = base64_decode(msg, cmd);
|
cmd = strdup(msg);
|
||||||
|
|
||||||
kerror = krb_rd_priv(cmd, len, schedule, &auth_dat.session,
|
len = base64_decode(msg, cmd);
|
||||||
&ctrl_addr, &his_addr, &m_data);
|
if(len < 0){
|
||||||
sprintf(tmp, "%.*s\r\n", m_data.app_length, m_data.app_data);
|
reply(501, "Failed to decode base 64 data.");
|
||||||
new_ftp_command(strdup(tmp));
|
free(cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kerror = krb_rd_priv(cmd, len, schedule, &auth_dat.session,
|
||||||
|
&his_addr, &ctrl_addr, &m_data);
|
||||||
|
|
||||||
free(cmd);
|
if(kerror){
|
||||||
return 0;
|
reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
|
||||||
|
free(cmd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = strdup(msg);
|
||||||
|
sprintf(tmp, "%.*s", m_data.app_length, m_data.app_data);
|
||||||
|
if(!strstr(tmp, "\r\n"))
|
||||||
|
strcat(tmp, "\r\n");
|
||||||
|
new_ftp_command(tmp);
|
||||||
|
free(cmd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int krb4_read(int fd, void *data, int length)
|
||||||
|
{
|
||||||
|
static int left;
|
||||||
|
static char *extra;
|
||||||
|
static int eof;
|
||||||
|
int len, bytes, tx = 0;
|
||||||
|
|
||||||
|
MSG_DAT m_data;
|
||||||
|
int kerror;
|
||||||
|
|
||||||
|
if(eof){ /* if we haven't reported an end-of-file, do so */
|
||||||
|
eof = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(left){
|
||||||
|
if(length > left)
|
||||||
|
bytes = left;
|
||||||
|
else
|
||||||
|
bytes = length;
|
||||||
|
memmove(data, extra, bytes);
|
||||||
|
left -= bytes;
|
||||||
|
if(left)
|
||||||
|
memmove(extra, extra + bytes, left);
|
||||||
|
else
|
||||||
|
free(extra);
|
||||||
|
length -= bytes;
|
||||||
|
tx += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(length){
|
||||||
|
krb_net_read(fd, &len, 4);
|
||||||
|
len = ntohl(len);
|
||||||
|
krb_net_read(fd, data_buffer, len);
|
||||||
|
if(data_protection == prot_safe)
|
||||||
|
kerror = krb_rd_safe(data_buffer, len, &auth_dat.session,
|
||||||
|
&his_addr, &ctrl_addr, &m_data);
|
||||||
|
else
|
||||||
|
kerror = krb_rd_priv(data_buffer, len, schedule, &auth_dat.session,
|
||||||
|
&his_addr, &ctrl_addr, &m_data);
|
||||||
|
|
||||||
|
if(kerror){
|
||||||
|
reply(400, "Failed to read data: %s.", krb_get_err_text(kerror));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = m_data.app_length;
|
||||||
|
if(bytes == 0){
|
||||||
|
if(tx) eof = 1;
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
if(bytes > length){
|
||||||
|
left = bytes - length;
|
||||||
|
bytes = length;
|
||||||
|
extra = malloc(left);
|
||||||
|
memmove(extra, m_data.app_data + bytes, left);
|
||||||
|
}
|
||||||
|
memmove((unsigned char*)data + tx, m_data.app_data, bytes);
|
||||||
|
tx += bytes;
|
||||||
|
length -= bytes;
|
||||||
|
}
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int krb4_write(int fd, void *data, int length)
|
||||||
|
{
|
||||||
|
int len, bytes, tx = 0;
|
||||||
|
|
||||||
|
len = buffer_size;
|
||||||
|
if(data_protection == prot_safe)
|
||||||
|
len -= 31; /* always 31 bytes overhead */
|
||||||
|
else
|
||||||
|
len -= 26; /* at most 26 bytes */
|
||||||
|
|
||||||
|
do{
|
||||||
|
if(length < len)
|
||||||
|
len = length;
|
||||||
|
if(data_protection == prot_safe)
|
||||||
|
bytes = krb_mk_safe(data, data_buffer+4, len, &auth_dat.session,
|
||||||
|
&ctrl_addr, &his_addr);
|
||||||
|
else
|
||||||
|
bytes = krb_mk_priv(data, data_buffer+4, len, schedule,
|
||||||
|
&auth_dat.session,
|
||||||
|
&ctrl_addr, &his_addr);
|
||||||
|
if(bytes == -1){
|
||||||
|
reply(535, "Failed to make packet: %s.", k_strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data_buffer[0] = (bytes >> 24) & 0xff;
|
||||||
|
data_buffer[1] = (bytes >> 16) & 0xff;
|
||||||
|
data_buffer[2] = (bytes >> 8) & 0xff;
|
||||||
|
data_buffer[3] = bytes & 0xff;
|
||||||
|
krb_net_write(fd, data_buffer, bytes+4);
|
||||||
|
length -= len;
|
||||||
|
data = (unsigned char*)data + len;
|
||||||
|
tx += len;
|
||||||
|
}while(length);
|
||||||
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int krb4_userok(char *name)
|
int krb4_userok(char *name)
|
||||||
{
|
{
|
||||||
if(!kuserok(&auth_dat, name)){
|
if(!kuserok(&auth_dat, name)){
|
||||||
do_login(232, name);
|
do_login(232, name);
|
||||||
}else{
|
}else{
|
||||||
reply(530, "User %s access denied.", name);
|
reply(530, "User %s access denied.", name);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int krb4_vprintf(const char *fmt, va_list ap)
|
int krb4_vprintf(const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char buf[10240];
|
char buf[10240]; /* XXX */
|
||||||
char *p;
|
char *p;
|
||||||
char *enc;
|
char *enc;
|
||||||
int code;
|
int code;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
vsprintf(buf, fmt, ap);
|
vsprintf(buf, fmt, ap);
|
||||||
enc = malloc(strlen(buf) + 31);
|
enc = malloc(strlen(buf) + 31);
|
||||||
if(prot_level == prot_safe){
|
if(prot_level == prot_safe){
|
||||||
len = krb_mk_safe((u_char*)buf, (u_char*)enc, strlen(buf), &auth_dat.session,
|
len = krb_mk_safe((u_char*)buf, (u_char*)enc, strlen(buf), &auth_dat.session,
|
||||||
&ctrl_addr, &his_addr);
|
&ctrl_addr, &his_addr);
|
||||||
code = 631;
|
code = 631;
|
||||||
}else if(prot_level == prot_private){
|
}else if(prot_level == prot_private){
|
||||||
len = krb_mk_priv((u_char*)buf, (u_char*)enc, strlen(buf), schedule,
|
len = krb_mk_priv((u_char*)buf, (u_char*)enc, strlen(buf), schedule,
|
||||||
&auth_dat.session, &ctrl_addr, &his_addr);
|
&auth_dat.session, &ctrl_addr, &his_addr);
|
||||||
code = 632;
|
code = 632;
|
||||||
}else{
|
}else{
|
||||||
len = 0; /* XXX */
|
len = 0; /* XXX */
|
||||||
code = 631;
|
code = 631;
|
||||||
}
|
}
|
||||||
base64_encode(enc, len, &p);
|
base64_encode(enc, len, &p);
|
||||||
fprintf(stdout, "%d %s\r\n", code, p);
|
fprintf(stdout, "%d %s\r\n", code, p);
|
||||||
free(enc);
|
free(enc);
|
||||||
free(p);
|
free(p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +1,21 @@
|
|||||||
#ifndef _KRB4_H_
|
#ifndef __KRB4_H__
|
||||||
#define _KRB4_H_
|
#define __KRB4_H__
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
extern int krb4_auth(char * auth);
|
int krb4_auth(char *auth);
|
||||||
extern int krb4_adat(char * auth);
|
int krb4_adat(char *auth);
|
||||||
extern int krb4_pbsz(int size);
|
int krb4_pbsz(int size);
|
||||||
extern int krb4_prot(char * type);
|
int krb4_prot(int level);
|
||||||
extern int krb4_ccc(void );
|
int krb4_ccc(void);
|
||||||
extern int krb4_mic(char * msg);
|
int krb4_mic(char *msg);
|
||||||
extern int krb4_conf(char * msg);
|
int krb4_conf(char *msg);
|
||||||
extern int krb4_enc(char * msg);
|
int krb4_enc(char *msg);
|
||||||
extern int krb4_userok(char *name);
|
|
||||||
extern int krb4_vprintf(const char *fmt, va_list ap);
|
|
||||||
|
|
||||||
#endif /* _KRB4_H_ */
|
int krb4_read(int fd, void *data, int length);
|
||||||
|
int krb4_write(int fd, void *data, int length);
|
||||||
|
|
||||||
|
int krb4_userok(char *name);
|
||||||
|
int krb4_vprintf(const char *fmt, va_list ap);
|
||||||
|
|
||||||
|
#endif /* __KRB4_H__ */
|
||||||
|
Reference in New Issue
Block a user