summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/nu_server.c83
-rwxr-xr-xsrc/nu_server.h5
2 files changed, 56 insertions, 32 deletions
diff --git a/src/nu_server.c b/src/nu_server.c
index d79967c..1360ccb 100755
--- a/src/nu_server.c
+++ b/src/nu_server.c
@@ -7,7 +7,7 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <sys/ioctl.h> 8#include <sys/ioctl.h>
9 9
10#include "nu_header.h" 10#include "nu_server.h"
11 11
12static void bailout( char *reason ); 12static void bailout( char *reason );
13static void sigint( int reason ) { bailout( "User interrupt." ); } 13static void sigint( int reason ) { bailout( "User interrupt." ); }
@@ -35,7 +35,7 @@ static void netbios_read( SMB_HEADER **buf) {
35static void netbios_write( SMB_HEADER *buf, 35static void netbios_write( SMB_HEADER *buf,
36 SMB_DATA *data, 36 SMB_DATA *data,
37 int datacount ) { 37 int datacount ) {
38 struct iovec iov[1 + 2 * SMB_MAXREQUEST] = { {buf , sizeof(SMB_HEADER) } }; 38 struct iovec iov[1 + 2 * SMB_MAXREQUESTS] = { {buf , sizeof(SMB_HEADER) } };
39 int i, sizeout = sizeof( SMB_HEADER ); 39 int i, sizeout = sizeof( SMB_HEADER );
40 40
41 for( i=0; i < datacount; ++i ) 41 for( i=0; i < datacount; ++i )
@@ -45,11 +45,11 @@ static void netbios_write( SMB_HEADER *buf,
45 sizeout += iov[2+2*i].iov_len = 2 + data[i].bytes->ByteCount; 45 sizeout += iov[2+2*i].iov_len = 2 + data[i].bytes->ByteCount;
46 46
47 buf->netbios_command = buf->netbios_flags = 0; 47 buf->netbios_command = buf->netbios_flags = 0;
48 buf->netbios_size = htons( sizeout ); 48 buf->netbios_size = htons( sizeout - 4 );
49 buf->Flags = 0x88; 49 buf->Flags = 0x88;
50 buf->Flags2 = 0x4001; 50 buf->Flags2 = 0x4001;
51 51
52 if( writev( childsock, iov, 1 + 2 * datacount ) < sizeout + 4 ) 52 if( writev( childsock, iov, 1 + 2 * datacount ) < sizeout )
53 bailout( "Write failed." ); 53 bailout( "Write failed." );
54} 54}
55 55
@@ -58,49 +58,63 @@ static WORD SMB_COM_NEGOTIATE_params[] = {
580x0511, 0x0000, 0x0001, 0x0001, 0x0000, 0x0100, 0x0000, 0x0100, 0x0000, 580x0511, 0x0000, 0x0001, 0x0001, 0x0000, 0x0100, 0x0000, 0x0100, 0x0000,
590x0000, 0xC049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; 590x0000, 0xC049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
60 60
61static SMB_STATUS handle_SMB_COM_NEGOTIATE( SMB_DATA *data ) { 61static SMB_STATUS handle_SMB_COM_NEGOTIATE( SMB_HEADER *header, SMB_DATA *data ) {
62 struct timeval t; gettimeofday( &t, NULL ); 62 struct timeval t; gettimeofday( &t, NULL );
63 SMB_COM_NEGOTIATE_params[8] = getpid(); 63 SMB_COM_NEGOTIATE_params[8] = getpid();
64 SMB_COM_NEGOTIATE_params[9] = getppid(); 64 SMB_COM_NEGOTIATE_params[9] = getppid();
65 *(QWORD*)(SMB_COM_NEGOTIATE_params+12) = getnttime( &t ); 65 *(QWORD*)(SMB_COM_NEGOTIATE_params+12) = getnttime( &t );
66 66 data->params = (SMB_PARAMS*)SMB_COM_NEGOTIATE_params;
67 data->params = SMB_COM_NEGOTIATE_bytes; data->bytes = SMB_COM_NEGOTIATE_params; 67 data->bytes = (SMB_BYTES *)SMB_COM_NEGOTIATE_bytes;
68 return STATUS_SUCCESS; 68 return STATUS_SUCCESS;
69} 69}
70 70
71static const BYTE SMB_SESSION_SETUP_ANDX_bytes[] = { 71static const BYTE SMB_COM_SESSION_SETUP_ANDX_bytes[] = {
7219,0,'O','S',0,'g','a','t','l','i','n','g',0,'g','a','t','l','i','n','g',0}; 7219,0,'O','S',0,'g','a','t','l','i','n','g',0,'g','a','t','l','i','n','g',0};
73static BYTE SMB_SESSION_SETUP_ANDX_params[] = { 4, 0, 0, 23, 0, 1, 0, 0, 0 }; 73static BYTE SMB_COM_SESSION_SETUP_ANDX_params[] = { 4, 255, 0, 0, 0, 1, 0, 0, 0 };
74
75static SMB_STATUS handle_SMB_COM_SESSION_SETUP_ANDX( SMB_HEADER *header, SMB_DATA *data ) {
76 data->params = (SMB_PARAMS*)SMB_COM_SESSION_SETUP_ANDX_params;
77 data->bytes = (SMB_BYTES *)SMB_COM_SESSION_SETUP_ANDX_bytes;
78 return STATUS_SUCCESS;
79}
80
81static const BYTE SMB_COM_TREE_CONNECT_ANDX_bytes[] = { 8, 0, 'I', 'P', 'C', 0, 'I', 'P', 'C', 0 };
82static BYTE SMB_COM_TREE_CONNECT_ANDX_params[] = { 3, 255, 0, 0, 0, 0, 0 };
74 83
75static SMB_STATUS handle_SMB_SESSION_SETUP_ANDX( SMB_DATA *data ) { 84static SMB_STATUS handle_SMB_COM_TREE_CONNECT_ANDX( SMB_HEADER *header, SMB_DATA *data ){
76 data->params = SMB_SESSION_SETUP_ANDX_bytes; data->bytes = SMB_SESSION_SETUP_ANDX_params; 85 data->params = (SMB_PARAMS*)SMB_COM_TREE_CONNECT_ANDX_params;
86 data->bytes = (SMB_BYTES *)SMB_COM_TREE_CONNECT_ANDX_bytes;
77 return STATUS_SUCCESS; 87 return STATUS_SUCCESS;
78} 88}
79 89
80static‰int command_handler_match( const void *a, const void *b ) { return *(BYTE*)a - *(BYTE*)b; } 90static int command_handler_match(const void *a, const void *b ) { return *(BYTE*)a - *(BYTE*)b; }
91
92/* If you add command handlers, please insert them in the right position,
93 this list is sorted by command, for later bsearch*/
81static SMB_COMMAND_HANDLER command_handler[] = { 94static SMB_COMMAND_HANDLER command_handler[] = {
82 { { SMB_COM_NEGOTIATE, 0x00, handle_SMB_COM_NEGOTIATE }, 95 { SMB_COM_NEGOTIATE, 0x00, handle_SMB_COM_NEGOTIATE },
83 { SMB_COM_SESSION_SETUP_ANDX, 0x01, handle_SMB_COM_SESSION_SETUP_ANDX } 96 { SMB_COM_SESSION_SETUP_ANDX, 0x01, handle_SMB_COM_SESSION_SETUP_ANDX },
84 } 97 { SMB_COM_TREE_CONNECT_ANDX, 0x01, handle_SMB_COM_TREE_CONNECT_ANDX }
85}; 98};
86 99
87static void child( ) { 100static void child( ) {
88 SMB_HEADER *inpacket = NULL; 101 SMB_HEADER *inpacket = NULL;
102 DWORD netbios_ack = 0x00000082;
89 103
90 /* I should spare that code... */ 104 /* I should spare that code... */
91 if( mainsock != -1 ) { close( mainsock ); mainsock = -1; } 105 if( mainsock != -1 ) { close( mainsock ); mainsock = -1; }
92 106
93 /* Try to answer first netbios packet */ 107 /* Try to answer first netbios packet */
94 netbios_read( &inpacket ); 108 netbios_read( &inpacket );
95 if( inpacket->netbios_command++ != 0x81 ) 109 if( inpacket->netbios_command != 0x81 )
96 bailout( "No session request"); 110 bailout( "No session request");
97 write( childsock, inpacket, 4); 111 write( childsock, &netbios_ack, 4);
98 112
99 while( 1 ) { 113 while( 1 ) {
100 SMB_COMMAND cmd; 114 SMB_COMMAND cmd;
101 SMB_DATA requests[ 1 + SMB_MAXREQUESTS ]; 115 SMB_DATA requests[ 1 + SMB_MAXREQUESTS ];
102 SMB_STATUS status = STATUS_SUCCESS; 116 SMB_STATUS status = STATUS_SUCCESS;
103 WORD sizeout = sizeof( SMB_HEADER ); 117 WORD sizeout = sizeof( SMB_HEADER ) - 4;
104 int num_requests = 0; 118 int num_requests = 0;
105 119
106 netbios_read( &inpacket ); 120 netbios_read( &inpacket );
@@ -114,29 +128,38 @@ static void child( ) {
114 requests[ 0 ].params = (SMB_PARAMS*)(inpacket+1); 128 requests[ 0 ].params = (SMB_PARAMS*)(inpacket+1);
115 129
116 while( (status == STATUS_SUCCESS) && (cmd != 0xff) ) { 130 while( (status == STATUS_SUCCESS) && (cmd != 0xff) ) {
117 SMB_COMMAND_HANDLER *handler = (SMB_COMMAND_HANDLER*)bsearch( cmd, command_handler, 131 SMB_COMMAND_HANDLER *handler = (SMB_COMMAND_HANDLER*)bsearch( &cmd, command_handler,
118 sizeof(command_handler)/sizeof(*command_handler), sizeof(*command_handler), command_handler_match); 132 sizeof(command_handler)/sizeof(*command_handler), sizeof(*command_handler), command_handler_match);
119 133
120 requests[ num_request ].bytes = 2 + *((WORD*)requests[ num_request ].params) + (BYTE*)requests[ num_request ].params; 134 requests[ num_requests ].bytes =
135 (SMB_BYTES*)(((BYTE*)requests[ num_requests ].params) + *((WORD*)(requests[ num_requests ].params)) + 2);
136
121 if( handler ) { 137 if( handler ) {
122 if( handler->flags & SMB_COMMAND_FLAG_ANDX ) { 138 if( handler->flags & SMB_COMMAND_FLAG_ANDX ) {
123 cmd = ((BYTE*)requests[ num_requests ].params)[3]; 139 cmd = ((BYTE*)requests[ num_requests ].params)[1];
124 requests[ num_requests+1 ].params = ((BYTE*)inpacket) + ((WORD*)requests[ num_requests ].params)[2]; 140 requests[ num_requests+1 ].params = (SMB_PARAMS*)(((BYTE*)inpacket) + 4 + ((WORD*)requests[ num_requests ].params)[2]);
125 } 141 }
126 142
127 status = handler->handler( &requests( num_requests ) ); 143 /* <---------- Calling handler here -----> */
128 144 if( (status = handler->handler( inpacket, requests + num_requests )) != STATUS_SUCCESS )
129 if( (status == STATUS_SUCCESS) && (handler->flags & SMB_COMMAND_FLAG_ANDX) ) { 145 cmd = 0xff;
146 if( handler->flags & SMB_COMMAND_FLAG_ANDX ) {
130 sizeout += 3 + 2 * requests[ num_requests ].params->WordCount + requests[ num_requests ].bytes->ByteCount; 147 sizeout += 3 + 2 * requests[ num_requests ].params->WordCount + requests[ num_requests ].bytes->ByteCount;
131 ((WORD*)requests[ num_requests ].params)[2] = sizeout; 148 ((BYTE*)requests[ num_requests ].params)[1] = cmd,
132 ((BYTE*)requests[ num_requests ].params)[3] = cmd; 149 ((BYTE*)requests[ num_requests ].params)[3] = sizeout & 255,
133 } 150 ((BYTE*)requests[ num_requests ].params)[4] = sizeout >> 8;
151 } else
152 cmd = 0xff;
153
134 num_requests++; 154 num_requests++;
135 } else 155 } else {
156 if( num_requests )
157 ((BYTE*)requests[ num_requests-1 ].params)[1] = 0xff;
136 status = 0x00400002; 158 status = 0x00400002;
159 }
137 } 160 }
138 161
139 memcpy( inpacket->status, &status, 4 ); /* not aligned, maybe we might do a store DWORD on x86 */ 162 memcpy( inpacket->Status, &status, 4 ); /* not aligned, maybe we might do a store DWORD on x86 */
140 netbios_write( inpacket, requests, num_requests ); 163 netbios_write( inpacket, requests, num_requests );
141 } /* End main loop */ 164 } /* End main loop */
142} 165}
diff --git a/src/nu_server.h b/src/nu_server.h
index 0a2ecc2..4d6abaa 100755
--- a/src/nu_server.h
+++ b/src/nu_server.h
@@ -4,6 +4,7 @@ typedef unsigned long DWORD;
4typedef int64_t QWORD; 4typedef int64_t QWORD;
5 5
6#include "nu_defines.h" 6#include "nu_defines.h"
7#define SMB_MAXREQUESTS 16
7 8
8typedef struct { 9typedef struct {
9 BYTE netbios_command; 10 BYTE netbios_command;
@@ -37,7 +38,7 @@ typedef struct {
37} SMB_DATA; 38} SMB_DATA;
38 39
39typedef struct { 40typedef struct {
40 SMB_COMMAND cmd; 41 BYTE cmd;
41 SMB_COMMAND_FLAG flags; 42 SMB_COMMAND_FLAG flags;
42 SMB_STATUS (*handler)(SMB_DATA *data); 43 SMB_STATUS (*handler)(SMB_HEADER *header, SMB_DATA *data);
43} SMB_COMMAND_HANDLER; 44} SMB_COMMAND_HANDLER;