From c0e83b6e7a814a85b76ea22d6306b7027a3222f9 Mon Sep 17 00:00:00 2001 From: erdgeist <> Date: Mon, 1 Dec 2003 14:35:28 +0000 Subject: kick off --- bin/.cvsignore | 0 src/nu_header.h | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nu_server.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 260 insertions(+) create mode 100755 bin/.cvsignore create mode 100755 src/nu_header.h create mode 100755 src/nu_server.c diff --git a/bin/.cvsignore b/bin/.cvsignore new file mode 100755 index 0000000..e69de29 diff --git a/src/nu_header.h b/src/nu_header.h new file mode 100755 index 0000000..0afdbaf --- /dev/null +++ b/src/nu_header.h @@ -0,0 +1,144 @@ +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; + +typedef struct { + BYTE netbios_command; + BYTE netbios_flags; + WORD netbios_size; +/*BYTE Protocol[4]; Protocol identifier 0xFF,"SMB" */ + DWORD Protocol; /* For faster compare */ + BYTE Command; /* Command Code, look below */ + union { + struct { + BYTE ErrorClass; + BYTE Reserved; + WORD Error; + } DosError; + DWORD Status; + } Status; + BYTE Flags; + WORD Flags2; + union { + WORD Pad[6]; /* Ensure 12 bytes len */ + struct { + WORD PidHigh; + BYTE SecuritySignature[8]; + } Extra; + }; + WORD TreeID; + WORD ProcessID; + WORD UserID; + WORD MultiplexID; + BYTE WordCount; + WORD ParameterWords[0]; +} SMB_HEADER; + +typedef struct { + WORD ByteCount; + BYTE Buffer[0]; +} SMB_HEADER2; + +/* This is the protocol identifier, each smb + request must begin with this double word +*/ +#define SMB_HEADER_PROTOCOL_MAGIC 0xff534d42 + +/* These are all valid SMB requests known from the document + http://www.snia.org/tech_activities/CIFS/CIFS_TR-1p00_FINAL.pdf + + However, we only intend to implement the core smb command set, + also known as dialect "PC NETWORK PROGRAM 1.0" and still only + a read-only subset of this. +*/ + +enum { + SMB_COM_CREATE_DIRECTORY = 0x00, + SMB_COM_DELETE_DIRECTORY = 0x01, + SMB_COM_OPEN = 0x02, + SMB_COM_CREATE = 0x03, + SMB_COM_CLOSE = 0x04, + SMB_COM_FLUSH = 0x05, + SMB_COM_DELETE = 0x06, + SMB_COM_RENAME = 0x07, + SMB_COM_QUERY_INFORMATION = 0x08, + SMB_COM_SET_INFORMATION = 0x09, + SMB_COM_READ = 0x0A, + SMB_COM_WRITE = 0x0B, + SMB_COM_LOCK_BYTE_RANGE = 0x0C, + SMB_COM_UNLOCK_BYTE_RANGE = 0x0D, + SMB_COM_CREATE_TEMPORARY = 0x0E, + SMB_COM_CREATE_NEW = 0x0F, + + SMB_COM_CHECK_DIRECTORY = 0x10, + SMB_COM_PROCESS_EXIT = 0x11, + SMB_COM_SEEK = 0x12, + SMB_COM_LOCK_AND_READ = 0x13, + SMB_COM_WRITE_AND_UNLOCK = 0x14, + /* ... */ + SMB_COM_READ_RAW = 0x1A, + SMB_COM_READ_MPX = 0x1B, + SMB_COM_READ_MPX_SECONDARY = 0x1C, + SMB_COM_WRITE_RAW = 0x1D, + SMB_COM_WRITE_MPX = 0x1E, + SMB_COM_WRITE_MPX_SECONDARY = 0x1F, + + SMB_COM_WRITE_COMPLETE = 0x20, + SMB_COM_QUERY_SERVER = 0x21, + SMB_COM_SET_INFORMATION2 = 0x22, + SMB_COM_QUERY_INFORMATION2 = 0x23, + SMB_COM_LOCKING_ANDX = 0x24, + SMB_COM_TRANSACTION = 0x25, + SMB_COM_TRANSACTION_SECONDARY = 0x26, + SMB_COM_IOCTL = 0x27, + SMB_COM_IOCTL_SECONDARY = 0x28, + SMB_COM_COPY = 0x29, + SMB_COM_MOVE = 0x2A, + SMB_COM_ECHO = 0x2B, + SMB_COM_WRITE_AND_CLOSE = 0x2C, + SMB_COM_OPEN_ANDX = 0x2D, + SMB_COM_READ_ANDX = 0x2E, + SMB_COM_WRITE_ANDX = 0x2F, + + SMB_COM_NEW_FILE_SIZE = 0x30, + SMB_COM_CLOSE_AND_TREE_DISC = 0x31, + SMB_COM_TRANSACTION2 = 0x32, + SMB_COM_TRANSACTION2_SECONDARY = 0x33, + SMB_COM_FIND_CLOSE2 = 0x34, + SMB_COM_FIND_NOTIFY_CLOSE = 0x35, + /* ... */ + + SMB_COM_TREE_CONNECT = 0x70, + SMB_COM_TREE_DISCONNECT = 0x71, + SMB_COM_NEGOTIATE = 0x72, + SMB_COM_SESSION_SETUP_ANDX = 0x73, + SMB_COM_LOGOFF_ANDX = 0x74, + SMB_COM_TREE_CONNECT_ANDX = 0x75, + /* ... */ + + SMB_COM_QUERY_INFORMATION_DISK = 0x80, + SMB_COM_SEARCH = 0x81, + SMB_COM_FIND = 0x82, + SMB_COM_FIND_UNIQUE = 0x83, + SMB_COM_FIND_CLOSE = 0x84, + /* ... */ + + SMB_COM_NT_TRANSACT = 0xA0, + SMB_COM_NT_TRANSACT_SECONDARY = 0xA1, + SMB_COM_NT_CREATE_ANDX = 0xA2, + /* ... */ + SMB_COM_NT_CANCEL = 0xA4, + SMB_COM_NT_RENAME = 0xA5, + /* ... */ + + SMB_COM_OPEN_PRINT_FILE = 0xC0, + SMB_COM_WRITE_PRINT_FILE = 0xC1, + SMB_COM_CLOSE_PRINT_FILE = 0xC2, + SMB_COM_GET_PRINT_QUEUE = 0xC3, + /* ... */ + + SMB_COM_READ_BULK = 0xD8, + SMB_COM_WRITE_BULK = 0xD9, + SMB_COM_WRITE_BULK_DATA = 0xDA +} SMB_COMMAND; + diff --git a/src/nu_server.c b/src/nu_server.c new file mode 100755 index 0000000..942be1b --- /dev/null +++ b/src/nu_server.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include + +#include "nu_header.h" + +static void bailout( char *reason ); +static mainsock = -1; +static childsock = -1; + +static void netbios_read( SMB_HEADER **buf) { + BYTE bytes[4]; + ssize_t bytesread, bytestoread; + + if( read( childsock, bytes, 4) < 4 ) + bailout( "Short read." ); + bytestoread = htons(*(WORD*)(2+bytes)); + if( (*buf = (SMB_HEADER*)realloc( *buf, 4 + bytestoread )) == NULL) + bailout( "Out of memory"); + *(DWORD*)*buf = *(DWORD*)bytes; + bytesread = read( childsock, ((BYTE*)buf) + 4, bytestoread); + if( bytesread != bytestoread ) + bailout( "Short read." ); +} + +static void netbios_write( BYTE command, BYTE *buf, WORD size ) { + BYTE netbios_header[4] = { command, 0, size >> 8, size & 255 }; + if( write( childsock, netbios_header, 4 ) <= 0 || + write( childsock, buf, size ) < 0 ) + bailout( "Write failed." ); +} + +static void child( ) { + SMB_HEADER *inpacket = NULL; + DWORD bytesread; + + /* I should spare that code... */ + if( mainsock != -1 ) { close( mainsock ); mainsock = -1; } + + /* Try to answer first netbios packet */ + netbios_read( &inpacket ); + if( inpacket->netbios_command != 0x81 ) + bailout( "No session request"); + netbios_write( 0x82, NULL, 0 ); + + while( 1 ) { + netbios_read( &inpacket ); + if( inpacket->netbios_command != 0 ) + bailout( "Unhandled netbios command" ); + if( inpacket->Protocol != SMB_HEADER_PROTOCOL_MAGIC ) + bailout( "Protocol identifier mismatch"); + + switch( inpacket->Command ) { + case SMB_COM_NEGOTIATE: + { + BYTE outblock[5] = { 0xff,0,0,0,0 }; + netbios_write( 0, outblock, sizeof( outblock )); + break; + } + default: + { + fprintf( stderr, "Got message: %02X\n", inpacket->Command ); + break; + } + } + + } /* End main loop */ +} + +void sigint( int reason ) { bailout( "User interrupt." ); } + +int main() +{ + struct sockaddr_in sa; + int l=1; + + signal( SIGINT, sigint); + + bzero( &sa, sizeof( sa)); + sa.sin_family = PF_INET; + sa.sin_port = htons( 139 ); + sa.sin_addr.s_addr = INADDR_ANY; + + if( ( mainsock = socket( PF_INET, SOCK_STREAM, 0) ) == -1) + bailout( "Could not open socket"); + setsockopt( mainsock, SOL_SOCKET, SO_REUSEPORT, &l, sizeof(l)); + if( bind( mainsock, (struct sockaddr *)&sa, sizeof( sa)) != 0) + bailout( "Could not bind socket"); + if( listen( mainsock, 1024) != 0 ) + bailout( "Could not make socket listen"); + + while( 1 ) { + struct sockaddr otherend; + int size = sizeof( otherend ); + + if( ( childsock = accept( mainsock, &otherend, &size) ) == -1) + bailout( "Socket Broke."); + if (!fork()) child( ); + } +} + +/* Graceful exit. */ +static void bailout( char *reason) { + fputs( reason, stderr); + fputs( "\nCleaning up.\n", stderr); + if( mainsock != -1 ) + close( mainsock ); + if( childsock != -1 ) { + shutdown( childsock, SHUT_RDWR); + close( childsock ); + } + exit( 0 ); +} -- cgit v1.2.3