mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
a2c1623827
The biggest thing is the integration of Lukes new nmbd. Its still
largely untested, so we will really need some feedback
I've also added auto prototype generation and cleaned up a lot of
minor things as a result
(This used to be commit 0d8dcfa13c
)
491 lines
8.0 KiB
C
491 lines
8.0 KiB
C
/* vt_mode.c */
|
|
/*
|
|
support vtp-sessions
|
|
|
|
written by Christian A. Lademann <cal@zls.com>
|
|
*/
|
|
|
|
/*
|
|
02.05.95:cal:ported to samba-1.9.13
|
|
*/
|
|
|
|
#define __vt_mode_c__
|
|
|
|
|
|
/* #include <stdio.h> */
|
|
/* #include <fcntl.h> */
|
|
/* #include <sys/types.h> */
|
|
/* #include <unistd.h> */
|
|
/* #include <signal.h> */
|
|
/* #include <errno.h> */
|
|
/* #include <ctype.h> */
|
|
/* #include <utmp.h> */
|
|
/* #include <sys/param.h> */
|
|
/* #include <sys/ioctl.h> */
|
|
/* #include <stdlib.h> */
|
|
/* #include <string.h> */
|
|
|
|
#include "includes.h"
|
|
#include "vt_mode.h"
|
|
#include <utmp.h>
|
|
|
|
#ifdef SCO
|
|
extern char *strdup();
|
|
#endif
|
|
|
|
extern int Client;
|
|
|
|
#ifdef LINUX
|
|
# define HAS_VTY
|
|
#endif
|
|
|
|
#ifdef SCO
|
|
# define HAS_PTY
|
|
# define HAS_VTY
|
|
|
|
# include <sys/tty.h>
|
|
#endif
|
|
|
|
extern int DEBUGLEVEL;
|
|
extern char *InBuffer, *OutBuffer;
|
|
extern int done_become_user;
|
|
|
|
char master_name [64], slave_name [64];
|
|
int master, slave, i, o, e;
|
|
|
|
int ms_type = MS_NONE,
|
|
ms_poll = 0;
|
|
|
|
|
|
/*
|
|
VT_Check: test incoming packet for "vtp" or "iVT1\0"
|
|
*/
|
|
int VT_Check(char *buffer)
|
|
{
|
|
DEBUG(3,("Checking packet: <%10s...>\n", buffer+4));
|
|
if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5))
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_Start_utmp: prepare /etc/utmp for /bin/login
|
|
*/
|
|
int VT_Start_utmp(void)
|
|
{
|
|
struct utmp u, *v;
|
|
char *tt;
|
|
|
|
|
|
setutent();
|
|
|
|
strcpy(u.ut_line, VT_Line);
|
|
|
|
if((v = getutline(&u)) == NULL) {
|
|
if(strncmp(VT_Line, "tty", 3) == 0)
|
|
tt = VT_Line + 3;
|
|
else if(strlen(VT_Line) > 4)
|
|
tt = VT_Line + strlen(VT_Line) - 4;
|
|
else
|
|
tt = VT_Line;
|
|
|
|
strcpy(u.ut_id, tt);
|
|
u.ut_time = time((time_t*)0);
|
|
}
|
|
|
|
strcpy(u.ut_user, "LOGIN");
|
|
strcpy(u.ut_line, VT_Line);
|
|
u.ut_pid = getpid();
|
|
u.ut_type = LOGIN_PROCESS;
|
|
pututline(&u);
|
|
|
|
endutent();
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_Stop_utmp: prepare /etc/utmp for other processes
|
|
*/
|
|
int VT_Stop_utmp(void)
|
|
{
|
|
struct utmp u, *v;
|
|
|
|
|
|
if(VT_Line != NULL) {
|
|
setutent();
|
|
|
|
strcpy(u.ut_line, VT_Line);
|
|
|
|
if((v = getutline(&u)) != NULL) {
|
|
strcpy(v->ut_user, "");
|
|
v->ut_type = DEAD_PROCESS;
|
|
v->ut_time = time((time_t*)0);
|
|
pututline(v);
|
|
}
|
|
|
|
endutent();
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_AtExit: Things to do when the program exits
|
|
*/
|
|
void VT_AtExit(void)
|
|
{
|
|
if(VT_ChildPID > 0) {
|
|
kill(VT_ChildPID, SIGHUP);
|
|
(void)wait(NULL);
|
|
}
|
|
|
|
VT_Stop_utmp();
|
|
}
|
|
|
|
|
|
/*
|
|
VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died
|
|
*/
|
|
void VT_SigCLD(int sig)
|
|
{
|
|
if(wait(NULL) == VT_ChildPID)
|
|
VT_ChildDied = True;
|
|
else
|
|
signal(SIGCLD, VT_SigCLD);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_SigEXIT: signalhandler for signals that cause the process to exit
|
|
*/
|
|
void VT_SigEXIT(int sig)
|
|
{
|
|
VT_AtExit();
|
|
|
|
exit(1);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK
|
|
*/
|
|
int VT_Start(void)
|
|
{
|
|
char OutBuf [64], *X, *Y;
|
|
|
|
|
|
ms_type = MS_NONE;
|
|
master = slave = -1;
|
|
|
|
#ifdef HAS_VTY
|
|
#ifdef LINUX
|
|
# define MASTER_TMPL "/dev/pty "
|
|
# define SLAVE_TMPL "/dev/tty "
|
|
# define LETTER1 "pqrs"
|
|
# define POS1 8
|
|
# define LETTER2 "0123456789abcdef"
|
|
# define POS2 9
|
|
#endif
|
|
|
|
#ifdef SCO
|
|
# define MASTER_TMPL "/dev/ptyp_ "
|
|
# define SLAVE_TMPL "/dev/ttyp_ "
|
|
# define LETTER1 "0123456"
|
|
# define POS1 10
|
|
# define LETTER2 "0123456789abcdef"
|
|
# define POS2 11
|
|
#endif
|
|
|
|
if(ms_poll == MS_VTY || ms_poll == 0) {
|
|
strcpy(master_name, MASTER_TMPL);
|
|
strcpy(slave_name, SLAVE_TMPL);
|
|
|
|
for(X = LETTER1; *X && master < 0; X++)
|
|
for(Y = LETTER2; *Y && master < 0; Y++) {
|
|
master_name [POS1] = *X;
|
|
master_name [POS2] = *Y;
|
|
if((master = open(master_name, O_RDWR)) >= 0) {
|
|
slave_name [POS1] = *X;
|
|
slave_name [POS2] = *Y;
|
|
if((slave = open(slave_name, O_RDWR)) < 0)
|
|
close(master);
|
|
}
|
|
}
|
|
|
|
if(master >= 0 && slave >= 0)
|
|
ms_type = MS_VTY;
|
|
}
|
|
|
|
# undef MASTER_TMPL
|
|
# undef SLAVE_TMPL
|
|
# undef LETTER1
|
|
# undef LETTER2
|
|
# undef POS1
|
|
# undef POS2
|
|
#endif
|
|
|
|
|
|
#ifdef HAS_PTY
|
|
#ifdef SCO
|
|
# define MASTER_TMPL "/dev/ptyp%d"
|
|
# define SLAVE_TMPL "/dev/ttyp%d"
|
|
# define MIN_I 0
|
|
# define MAX_I 63
|
|
#endif
|
|
|
|
if(ms_poll == MS_PTY || ms_poll == 0) {
|
|
int i;
|
|
|
|
for(i = MIN_I; i <= MAX_I && master < 0; i++) {
|
|
sprintf(master_name, MASTER_TMPL, i);
|
|
if((master = open(master_name, O_RDWR)) >= 0) {
|
|
sprintf(slave_name, SLAVE_TMPL, i);
|
|
if((slave = open(slave_name, O_RDWR)) < 0)
|
|
close(master);
|
|
}
|
|
}
|
|
|
|
if(master >= 0 && slave >= 0)
|
|
ms_type = MS_PTY;
|
|
}
|
|
|
|
# undef MASTER_TMPL
|
|
# undef SLAVE_TMPL
|
|
# undef MIN_I
|
|
# undef MAX_I
|
|
#endif
|
|
|
|
|
|
if(! ms_type)
|
|
return(-1);
|
|
|
|
VT_Line = strdup(strrchr(slave_name, '/') + 1);
|
|
|
|
switch((VT_ChildPID = fork())) {
|
|
case -1:
|
|
return(-1);
|
|
break;
|
|
|
|
case 0:
|
|
#ifdef SCO
|
|
setsid();
|
|
#endif
|
|
close(0);
|
|
close(1);
|
|
close(2);
|
|
|
|
i = open(slave_name, O_RDWR);
|
|
o = open(slave_name, O_RDWR);
|
|
e = open(slave_name, O_RDWR);
|
|
|
|
#ifdef LINUX
|
|
setsid();
|
|
if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1)
|
|
exit(1);
|
|
#endif
|
|
#ifdef SCO
|
|
tcsetpgrp(0, getpid());
|
|
#endif
|
|
|
|
VT_Start_utmp();
|
|
|
|
system("stty sane");
|
|
execlp("/bin/login", "login", "-c", (char*)0);
|
|
exit(1);
|
|
break;
|
|
|
|
default:
|
|
VT_Mode = True;
|
|
VT_Status = VT_OPEN;
|
|
VT_ChildDied = False;
|
|
VT_Fd = master;
|
|
|
|
signal(SIGCLD, VT_SigCLD);
|
|
|
|
signal(SIGHUP, VT_SigEXIT);
|
|
signal(SIGTERM, VT_SigEXIT);
|
|
signal(SIGINT, VT_SigEXIT);
|
|
signal(SIGQUIT, VT_SigEXIT);
|
|
|
|
memset(OutBuf, 0, sizeof(OutBuf));
|
|
OutBuf [4] = 0x06;
|
|
_smb_setlen(OutBuf, 1);
|
|
|
|
send_smb(Client,OutBuf);
|
|
|
|
return(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
VT_Output: transport data from socket to pty
|
|
*/
|
|
int VT_Output(char *Buffer)
|
|
{
|
|
int i, len, nb;
|
|
|
|
|
|
if(VT_Status != VT_OPEN)
|
|
return(-1);
|
|
|
|
len = smb_len(Buffer);
|
|
|
|
nb = write(VT_Fd, Buffer + 4, len);
|
|
|
|
return((nb == len) ? 0 : -1);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_Input: transport data from pty to socket
|
|
*/
|
|
int VT_Input(char *Buffer,int Size)
|
|
{
|
|
int len;
|
|
|
|
|
|
if(VT_Status != VT_OPEN)
|
|
return(-1);
|
|
|
|
memset(Buffer, 0, Size);
|
|
len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size));
|
|
|
|
_smb_setlen(Buffer, len);
|
|
|
|
return(len + 4);
|
|
}
|
|
|
|
|
|
/*
|
|
VT_Process: main loop while in vt-mode
|
|
*/
|
|
void VT_Process(void)
|
|
{
|
|
static int trans_num = 0;
|
|
extern int Client;
|
|
int nread;
|
|
|
|
|
|
VT_Start();
|
|
|
|
atexit(VT_AtExit);
|
|
|
|
while (True) {
|
|
int32 len;
|
|
int msg_type;
|
|
int msg_flags;
|
|
int counter;
|
|
int last_keepalive=0;
|
|
struct fd_set si;
|
|
struct timeval to, *top;
|
|
int n, ret, t;
|
|
|
|
|
|
errno = 0;
|
|
t = SMBD_SELECT_LOOP*1000;
|
|
|
|
|
|
FD_ZERO(&si);
|
|
FD_SET(Client, &si);
|
|
|
|
FD_SET(VT_Fd, &si);
|
|
|
|
if(t >= 0) {
|
|
to.tv_sec = t / 1000;
|
|
to.tv_usec = t - (to.tv_sec * 1000);
|
|
|
|
top = &to;
|
|
} else
|
|
top = NULL;
|
|
|
|
if(VT_ChildDied)
|
|
goto leave_VT_Process;
|
|
|
|
n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top);
|
|
|
|
if(VT_ChildDied)
|
|
goto leave_VT_Process;
|
|
|
|
if(n == 0) {
|
|
int i;
|
|
time_t t;
|
|
BOOL allidle = True;
|
|
extern int keepalive;
|
|
|
|
counter += SMBD_SELECT_LOOP;
|
|
|
|
t = time(NULL);
|
|
|
|
if (keepalive && (counter-last_keepalive)>keepalive) {
|
|
if (!send_keepalive(Client))
|
|
goto leave_VT_Process;
|
|
last_keepalive = counter;
|
|
}
|
|
} else if(n > 0) {
|
|
counter = 0;
|
|
|
|
if(FD_ISSET(VT_Fd, &si)) {
|
|
/* got input from vt */
|
|
nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit()));
|
|
|
|
if(nread > 0)
|
|
send_smb(Client,OutBuffer);
|
|
}
|
|
|
|
if(FD_ISSET(Client, &si)) {
|
|
/* got input from socket */
|
|
|
|
if(receive_smb(Client,InBuffer, 0)) {
|
|
msg_type = CVAL(InBuffer,0);
|
|
msg_flags = CVAL(InBuffer,1);
|
|
|
|
len = smb_len(InBuffer);
|
|
|
|
DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
|
|
|
|
nread = len + 4;
|
|
|
|
DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
|
|
|
|
if(msg_type == 0)
|
|
VT_Output(InBuffer);
|
|
else {
|
|
nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit()));
|
|
|
|
if(nread > 0) {
|
|
if (nread != smb_len(OutBuffer) + 4) {
|
|
DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
|
|
nread,
|
|
smb_len(OutBuffer)));
|
|
} else
|
|
send_smb(Client,OutBuffer);
|
|
}
|
|
}
|
|
} else
|
|
if(errno == EBADF)
|
|
goto leave_VT_Process;
|
|
}
|
|
}
|
|
|
|
trans_num++;
|
|
}
|
|
|
|
leave_VT_Process:
|
|
/*
|
|
if(VT_ChildPID > 0)
|
|
kill(VT_ChildPID, SIGHUP);
|
|
|
|
VT_Stop_utmp(VT_Line);
|
|
return;
|
|
*/
|
|
close_sockets();
|
|
exit(0);
|
|
}
|