diff options
-rwxr-xr-x | src/nu_server.c | 83 | ||||
-rwxr-xr-x | src/nu_server.h | 5 |
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 | ||
12 | static void bailout( char *reason ); | 12 | static void bailout( char *reason ); |
13 | static void sigint( int reason ) { bailout( "User interrupt." ); } | 13 | static void sigint( int reason ) { bailout( "User interrupt." ); } |
@@ -35,7 +35,7 @@ static void netbios_read( SMB_HEADER **buf) { | |||
35 | static void netbios_write( SMB_HEADER *buf, | 35 | static 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[] = { | |||
58 | 0x0511, 0x0000, 0x0001, 0x0001, 0x0000, 0x0100, 0x0000, 0x0100, 0x0000, | 58 | 0x0511, 0x0000, 0x0001, 0x0001, 0x0000, 0x0100, 0x0000, 0x0100, 0x0000, |
59 | 0x0000, 0xC049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; | 59 | 0x0000, 0xC049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; |
60 | 60 | ||
61 | static SMB_STATUS handle_SMB_COM_NEGOTIATE( SMB_DATA *data ) { | 61 | static 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 | ||
71 | static const BYTE SMB_SESSION_SETUP_ANDX_bytes[] = { | 71 | static const BYTE SMB_COM_SESSION_SETUP_ANDX_bytes[] = { |
72 | 19,0,'O','S',0,'g','a','t','l','i','n','g',0,'g','a','t','l','i','n','g',0}; | 72 | 19,0,'O','S',0,'g','a','t','l','i','n','g',0,'g','a','t','l','i','n','g',0}; |
73 | static BYTE SMB_SESSION_SETUP_ANDX_params[] = { 4, 0, 0, 23, 0, 1, 0, 0, 0 }; | 73 | static BYTE SMB_COM_SESSION_SETUP_ANDX_params[] = { 4, 255, 0, 0, 0, 1, 0, 0, 0 }; |
74 | |||
75 | static 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 | |||
81 | static const BYTE SMB_COM_TREE_CONNECT_ANDX_bytes[] = { 8, 0, 'I', 'P', 'C', 0, 'I', 'P', 'C', 0 }; | ||
82 | static BYTE SMB_COM_TREE_CONNECT_ANDX_params[] = { 3, 255, 0, 0, 0, 0, 0 }; | ||
74 | 83 | ||
75 | static SMB_STATUS handle_SMB_SESSION_SETUP_ANDX( SMB_DATA *data ) { | 84 | static 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 | ||
80 | static‰int command_handler_match( const void *a, const void *b ) { return *(BYTE*)a - *(BYTE*)b; } | 90 | static 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*/ | ||
81 | static SMB_COMMAND_HANDLER command_handler[] = { | 94 | static 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 | ||
87 | static void child( ) { | 100 | static 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; | |||
4 | typedef int64_t QWORD; | 4 | typedef int64_t QWORD; |
5 | 5 | ||
6 | #include "nu_defines.h" | 6 | #include "nu_defines.h" |
7 | #define SMB_MAXREQUESTS 16 | ||
7 | 8 | ||
8 | typedef struct { | 9 | typedef struct { |
9 | BYTE netbios_command; | 10 | BYTE netbios_command; |
@@ -37,7 +38,7 @@ typedef struct { | |||
37 | } SMB_DATA; | 38 | } SMB_DATA; |
38 | 39 | ||
39 | typedef struct { | 40 | typedef 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; |