version 1.3, 1996/06/26 05:38:31 |
version 1.4, 1996/08/18 18:21:24 |
|
|
|
|
#define START_PORT 5120 /* arbitrary */ |
#define START_PORT 5120 /* arbitrary */ |
|
|
int getport __P((int *)); |
|
|
|
int |
int |
kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm, |
kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm, |
cred, schedule, msg_data, laddr, faddr, authopts) |
cred, schedule, msg_data, laddr, faddr, authopts) |
|
|
pid = getpid(); |
pid = getpid(); |
hp = gethostbyname(*ahost); |
hp = gethostbyname(*ahost); |
if (hp == NULL) { |
if (hp == NULL) { |
/* fprintf(stderr, "%s: unknown host\n", *ahost); */ |
herror(*ahost); |
return (-1); |
return (-1); |
} |
} |
|
|
host_save = malloc(strlen(hp->h_name) + 1); |
host_save = malloc(strlen(hp->h_name) + 1); |
strcpy(host_save, hp->h_name); |
strcpy(host_save, hp->h_name); |
*ahost = host_save; |
*ahost = host_save; |
|
|
#ifdef KERBEROS |
|
/* If realm is null, look up from table */ |
/* If realm is null, look up from table */ |
if (realm == NULL || realm[0] == '\0') |
if (realm == NULL || realm[0] == '\0') |
realm = krb_realmofhost(host_save); |
realm = krb_realmofhost(host_save); |
#endif /* KERBEROS */ |
|
|
|
oldmask = sigblock(sigmask(SIGURG)); |
oldmask = sigblock(sigmask(SIGURG)); |
for (;;) { |
for (;;) { |
s = getport(&lport); |
s = rresvport(&lport); |
if (s < 0) { |
if (s < 0) { |
if (errno == EAGAIN) |
if (errno == EAGAIN) |
fprintf(stderr, |
fprintf(stderr, |
|
|
return (-1); |
return (-1); |
} |
} |
fcntl(s, F_SETOWN, pid); |
fcntl(s, F_SETOWN, pid); |
|
bzero(&sin, sizeof sin); |
|
sin.sin_len = sizeof(struct sockaddr_in); |
sin.sin_family = hp->h_addrtype; |
sin.sin_family = hp->h_addrtype; |
#if defined(ultrix) || defined(sun) |
|
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); |
|
#else |
|
bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); |
|
#endif |
|
sin.sin_port = rport; |
sin.sin_port = rport; |
|
bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); |
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) |
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) |
break; |
break; |
(void) close(s); |
(void) close(s); |
|
|
timo *= 2; |
timo *= 2; |
continue; |
continue; |
} |
} |
#if !(defined(ultrix) || defined(sun)) |
|
if (hp->h_addr_list[1] != NULL) { |
if (hp->h_addr_list[1] != NULL) { |
int oerrno = errno; |
int oerrno = errno; |
|
|
|
|
errno = oerrno; |
errno = oerrno; |
perror(NULL); |
perror(NULL); |
hp->h_addr_list++; |
hp->h_addr_list++; |
bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, |
bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length); |
hp->h_length); |
|
fprintf(stderr, "Trying %s...\n", |
fprintf(stderr, "Trying %s...\n", |
inet_ntoa(sin.sin_addr)); |
inet_ntoa(sin.sin_addr)); |
continue; |
continue; |
} |
} |
#endif /* !(defined(ultrix) || defined(sun)) */ |
|
if (errno != ECONNREFUSED) |
if (errno != ECONNREFUSED) |
perror(hp->h_name); |
perror(hp->h_name); |
sigsetmask(oldmask); |
sigsetmask(oldmask); |
return (-1); |
return (-1); |
} |
} |
lport--; |
|
if (fd2p == 0) { |
if (fd2p == 0) { |
write(s, "", 1); |
write(s, "", 1); |
lport = 0; |
lport = 0; |
} else { |
} else { |
char num[8]; |
char num[8]; |
int s2 = getport(&lport), s3; |
int s2 = rresvport(&lport), s3; |
int len = sizeof(from); |
int len = sizeof(from); |
|
|
if (s2 < 0) { |
if (s2 < 0) { |
|
|
goto bad; |
goto bad; |
} |
} |
listen(s2, 1); |
listen(s2, 1); |
(void) sprintf(num, "%d", lport); |
(void) snprintf(num, sizeof(num), "%d", lport); |
if (write(s, num, strlen(num) + 1) != strlen(num) + 1) { |
if (write(s, num, strlen(num) + 1) != strlen(num) + 1) { |
perror("kcmd(write): setting up stderr"); |
perror("kcmd(write): setting up stderr"); |
(void) close(s2); |
(void) close(s2); |
status = -1; |
status = -1; |
goto bad; |
goto bad; |
} |
} |
|
again: |
s3 = accept(s2, (struct sockaddr *)&from, &len); |
s3 = accept(s2, (struct sockaddr *)&from, &len); |
|
s3 = accept(s2, (struct sockaddr *)&from, &len); |
|
/* |
|
* XXX careful for ftp bounce attacks. If discovered, shut them |
|
* down and check for the real auxiliary channel to connect. |
|
*/ |
|
if (from.sin_family == AF_INET && from.sin_port == htons(20)) { |
|
(void) close(s3); |
|
goto again; |
|
} |
(void) close(s2); |
(void) close(s2); |
if (s3 < 0) { |
if (s3 < 0) { |
perror("kcmd:accept"); |
perror("kcmd:accept"); |
|
|
goto bad; |
goto bad; |
} |
} |
*fd2p = s3; |
*fd2p = s3; |
from.sin_port = ntohs((u_short)from.sin_port); |
from.sin_port = ntohs(from.sin_port); |
if (from.sin_family != AF_INET || |
if (from.sin_family != AF_INET || |
from.sin_port >= IPPORT_RESERVED) { |
from.sin_port >= IPPORT_RESERVED || |
|
from.sin_port < IPPORT_RESERVED / 2) { |
fprintf(stderr, |
fprintf(stderr, |
"kcmd(socket): protocol failure in circuit setup.\n"); |
"kcmd(socket): protocol failure in circuit setup.\n"); |
status = -1; |
status = -1; |
|
|
goto bad2; |
goto bad2; |
} |
} |
} |
} |
#ifdef KERBEROS |
|
if ((status = krb_sendauth(authopts, s, ticket, service, *ahost, |
if ((status = krb_sendauth(authopts, s, ticket, service, *ahost, |
realm, (unsigned long) getpid(), msg_data, |
realm, (unsigned long) getpid(), msg_data, |
cred, schedule, |
cred, schedule, |
|
|
faddr, |
faddr, |
"KCMDV0.1")) != KSUCCESS) |
"KCMDV0.1")) != KSUCCESS) |
goto bad2; |
goto bad2; |
#endif /* KERBEROS */ |
|
|
|
(void) write(s, remuser, strlen(remuser)+1); |
(void) write(s, remuser, strlen(remuser)+1); |
(void) write(s, cmd, strlen(cmd)+1); |
(void) write(s, cmd, strlen(cmd)+1); |
|
|
(void) close(s); |
(void) close(s); |
sigsetmask(oldmask); |
sigsetmask(oldmask); |
return (status); |
return (status); |
} |
|
|
|
int |
|
getport(alport) |
|
int *alport; |
|
{ |
|
struct sockaddr_in sin; |
|
int s; |
|
|
|
sin.sin_family = AF_INET; |
|
sin.sin_addr.s_addr = INADDR_ANY; |
|
s = socket(AF_INET, SOCK_STREAM, 0); |
|
if (s < 0) |
|
return (-1); |
|
for (;;) { |
|
sin.sin_port = htons((u_short)*alport); |
|
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) |
|
return (s); |
|
if (errno != EADDRINUSE) { |
|
(void) close(s); |
|
return (-1); |
|
} |
|
(*alport)--; |
|
#ifdef ATHENA_COMPAT |
|
if (*alport == IPPORT_RESERVED/2) { |
|
#else |
|
if (*alport == IPPORT_RESERVED) { |
|
#endif |
|
(void) close(s); |
|
errno = EAGAIN; /* close */ |
|
return (-1); |
|
} |
|
} |
|
} |
} |