preliminary smb support
This commit is contained in:
parent
103048b2db
commit
f3cf2ac338
4
main.c
4
main.c
|
@ -277,6 +277,10 @@ int main(int argc, char **argv)
|
|||
{
|
||||
do_http(url, &components);
|
||||
}
|
||||
else if (components.schemeType == SCHEME_SMB)
|
||||
{
|
||||
do_smb(url, &components);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unsupported scheme.\n");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
CFLAGS += $(DEFINES) -v -w
|
||||
OBJS = main.o gopher.o url.o connection.o readline2.o scheme.o ftype.o \
|
||||
mime.o setftype.o s16debug.o common.o http.o http.utils.o \
|
||||
dictionary.o options.o time.o
|
||||
dictionary.o options.o time.o smb.o
|
||||
|
||||
gopher: $(OBJS)
|
||||
$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
|
||||
|
@ -28,6 +28,7 @@ options.o: options.c options.h
|
|||
gopher.o: gopher.c url.h connection.h options.h
|
||||
http.o: http.c url.h connection.h options.h
|
||||
http.utils.o: http.utils.c
|
||||
smb.o: smb.c smb.h url.h connection.h options.h
|
||||
|
||||
data.o: data.c data.h
|
||||
dictionary.o: dictionary.c dictionary.h
|
||||
|
|
|
@ -55,6 +55,7 @@ int CloseLoop(Connection *connection);
|
|||
#ifdef __url_h__
|
||||
int do_gopher(const char *url, URLComponents *components);
|
||||
int do_http(const char *url, URLComponents *components);
|
||||
int do_smb(const char *url, URLComponents *components);
|
||||
#endif
|
||||
|
||||
#ifdef __TYPES__
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
#pragma optimize 79
|
||||
#pragma noroot
|
||||
|
||||
#include <GSOS.h>
|
||||
#include <Memory.h>
|
||||
#include <MiscTool.h>
|
||||
#include <tcpip.h>
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "url.h"
|
||||
#include "connection.h"
|
||||
#include "readline2.h"
|
||||
#include "options.h"
|
||||
#include "s16debug.h"
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "smb.h"
|
||||
|
||||
static struct smb2_header_sync header;
|
||||
|
||||
|
||||
Handle read_response(Word ipid)
|
||||
{
|
||||
static srBuff sr;
|
||||
static rrBuff rb;
|
||||
|
||||
// read an smb response. Check the first 4 bytes for the message length.
|
||||
uint32_t size = 0;
|
||||
uint8_t nbthead[4];
|
||||
LongWord qtick;
|
||||
Word terr;
|
||||
|
||||
qtick = GetTick() + 30 * 60;
|
||||
for(;;)
|
||||
{
|
||||
|
||||
|
||||
TCPIPPoll();
|
||||
|
||||
terr = TCPIPStatusTCP(ipid, &sr);
|
||||
|
||||
if (sr.srRcvQueued >= 4) break;
|
||||
|
||||
|
||||
/*
|
||||
* the only reasonable error is if the connection is closing.
|
||||
* that's ok if there's still pending data (handled above)
|
||||
*/
|
||||
if (terr) return (Handle)0;
|
||||
|
||||
|
||||
if (GetTick() >= qtick)
|
||||
{
|
||||
fprintf(stderr, "Read timed out.\n");
|
||||
return (Handle)0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
terr = TCPIPReadTCP(ipid, 0, (Ref)&nbthead, 4, &rb);
|
||||
|
||||
if (nbthead[0] != 0) return (Handle)0;
|
||||
size = nbthead[3];
|
||||
size |= nbthead[2] << 8;
|
||||
size |= nbthead[1] << 16;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
|
||||
TCPIPPoll();
|
||||
|
||||
terr = TCPIPStatusTCP(ipid, &sr);
|
||||
|
||||
if (sr.srRcvQueued >= size) break;
|
||||
|
||||
if (GetTick() >= qtick)
|
||||
{
|
||||
fprintf(stderr, "Read timed out.\n");
|
||||
return (Handle)0;
|
||||
}
|
||||
|
||||
}
|
||||
terr = TCPIPReadTCP(ipid, 2, (Ref)0, size, &rb);
|
||||
|
||||
return rb.rrBuffHandle;
|
||||
|
||||
}
|
||||
|
||||
int negotiate(Word ipid)
|
||||
{
|
||||
static struct smb2_negotiate_request req;
|
||||
|
||||
static uint16_t dialects[] = { 0x0202 };
|
||||
|
||||
uint8_t nbthead[4];
|
||||
uint32_t size = 0;
|
||||
|
||||
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
|
||||
header.protocol_id = SMB2_MAGIC; // '\xfeSMB';
|
||||
header.structure_size = 64;
|
||||
header.command = SMB2_NEGOTIATE;
|
||||
|
||||
req.structure_size = 36;
|
||||
req.dialect_count = 1; // ?
|
||||
req.security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
|
||||
req.capabilities = 0;
|
||||
|
||||
//req.dialects[0] = 0x202; // smb 2.002
|
||||
|
||||
|
||||
// http://support.microsoft.com/kb/204279
|
||||
size = sizeof(header) + sizeof(req) + sizeof(dialects);
|
||||
nbthead[0] = 0;
|
||||
nbthead[1] = size >> 16;
|
||||
nbthead[2] = size >> 8;
|
||||
nbthead[3] = size;
|
||||
|
||||
TCPIPWriteTCP(ipid, (dataPtr)nbthead, sizeof(nbthead), false, false);
|
||||
TCPIPWriteTCP(ipid, (dataPtr)&header, sizeof(header), false, false);
|
||||
TCPIPWriteTCP(ipid, (dataPtr)&req, sizeof(req), false, false);
|
||||
TCPIPWriteTCP(ipid, (dataPtr)&dialects, sizeof(dialects), true, false);
|
||||
// push.
|
||||
|
||||
// read a response...
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int do_smb(char *url, URLComponents *components)
|
||||
{
|
||||
static Connection connection;
|
||||
LongWord qtick;
|
||||
|
||||
char *host;
|
||||
Word err;
|
||||
Word terr;
|
||||
Word ok;
|
||||
FILE *file;
|
||||
|
||||
if (!components->portNumber) components->portNumber = 445;
|
||||
|
||||
host = URLComponentGetCMalloc(url, components, URLComponentHost);
|
||||
|
||||
if (!host)
|
||||
{
|
||||
fprintf(stderr, "URL `%s': no host.", url);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ok = ConnectLoop(host, components->portNumber, &connection);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
free(host);
|
||||
if (file != stdout) fclose(file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ok = negotiate(connection.ipid);
|
||||
if (ok) return ok;
|
||||
|
||||
|
||||
qtick = GetTick() + 30 * 60;
|
||||
for(;;)
|
||||
{
|
||||
static srBuff sr;
|
||||
|
||||
TCPIPPoll();
|
||||
|
||||
terr = TCPIPStatusTCP(connection.ipid, &sr);
|
||||
|
||||
if (sr.srRcvQueued > 0) break;
|
||||
|
||||
|
||||
if (GetTick() >= qtick)
|
||||
{
|
||||
fprintf(stderr, "Read timed out.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CloseLoop(&connection);
|
||||
|
||||
free(host);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
#ifndef __SMB_H__
|
||||
#define __SMB_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SMB2_MAGIC 0x424d53fe
|
||||
|
||||
// commands
|
||||
enum {
|
||||
SMB2_NEGOTIATE = 0x0000,
|
||||
SMB2_SESSION_SETUP = 0x0001,
|
||||
SMB2_LOGOFF = 0x0002,
|
||||
SMB2_TREE_CONNECT = 0x0003,
|
||||
SMB2_TREE_DISCONNECT = 0x0004,
|
||||
SMB2_CREATE = 0x0005,
|
||||
SMB2_CLOSE = 0x0006,
|
||||
SMB2_FLUSH = 0x0007,
|
||||
SMB2_READ = 0x0008,
|
||||
SMB2_WRITE = 0x0009,
|
||||
SMB2_LOCK = 0x000A,
|
||||
SMB2_IOCTL = 0x000B,
|
||||
SMB2_CANCEL = 0x000C,
|
||||
SMB2_ECHO = 0x000D,
|
||||
SMB2_QUERY_DIRECTORY = 0x000E,
|
||||
SMB2_CHANGE_NOTIFY = 0x000F,
|
||||
SMB2_QUERY_INFO = 0x0010,
|
||||
SMB2_SET_INFO = 0x0011,
|
||||
SMB2_OPLOCK_BREAK = 0x0012
|
||||
};
|
||||
|
||||
// flags
|
||||
enum {
|
||||
SMB2_FLAGS_SERVER_TO_REDIR = 0x00000001,
|
||||
SMB2_FLAGS_ASYNC_COMMAND = 0x00000002,
|
||||
SMB2_FLAGS_RELATED_OPERATIONS = 0x00000004,
|
||||
SMB2_FLAGS_SIGNED = 0x00000008
|
||||
// integer overflow
|
||||
/*
|
||||
SMB2_FLAGS_DFS_OPERATIONS = 0x10000000,
|
||||
SMB2_FLAGS_REPLAY_OPERATION = 0x20000000
|
||||
*/
|
||||
};
|
||||
|
||||
#define SMB2_FLAGS_DFS_OPERATIONS 0x10000000
|
||||
#define SMB2_FLAGS_REPLAY_OPERATION 0x20000000
|
||||
|
||||
// symlink error response flags.
|
||||
enum {
|
||||
|
||||
SYMLINK_FLAG_RELATIVE = 0x00000001
|
||||
};
|
||||
|
||||
// negotiate flags
|
||||
enum {
|
||||
SMB2_NEGOTIATE_SIGNING_ENABLED = 0x0001,
|
||||
SMB2_NEGOTIATE_SIGNING_REQUIRED = 0x0002,
|
||||
|
||||
SMB2_GLOBAL_CAP_DFS = 0x00000001,
|
||||
SMB2_GLOBAL_CAP_LEASING = 0x00000002,
|
||||
SMB2_GLOBAL_CAP_LARGE_MTU = 0x00000004,
|
||||
SMB2_GLOBAL_CAP_MULTI_CHANNEL = 0x00000008,
|
||||
SMB2_GLOBAL_CAP_PERSISTENT_HANDLES = 0x00000010,
|
||||
SMB2_GLOBAL_CAP_DIRECTORY_LEASING = 0x00000020,
|
||||
SMB2_GLOBAL_CAP_ENCRYPTION = 0x00000040
|
||||
};
|
||||
|
||||
// session setup flags
|
||||
enum {
|
||||
SMB2_SESSION_FLAG_BINDING = 0x01
|
||||
};
|
||||
|
||||
// session setup response flags
|
||||
enum {
|
||||
SMB2_SESSION_FLAG_IS_GUEST = 0x0001,
|
||||
SMB2_SESSION_FLAG_IS_NULL = 0x0002,
|
||||
SMB2_SESSION_FLAG_ENCRYPT_DATA = 0x0004
|
||||
};
|
||||
|
||||
typedef struct smb2_header_sync {
|
||||
|
||||
uint32_t protocol_id;
|
||||
uint16_t structure_size;
|
||||
uint16_t credit_charge;
|
||||
uint32_t status;
|
||||
uint16_t command;
|
||||
uint16_t credit; // _request / _response
|
||||
uint32_t flags;
|
||||
uint32_t next_command;
|
||||
uint32_t message_id[2]; // uint64_t
|
||||
uint32_t reserved;
|
||||
uint32_t tree_id;
|
||||
uint32_t session_id[2]; // uint64_t
|
||||
uint8_t signature[16];
|
||||
|
||||
} smb2_header_sync;
|
||||
|
||||
typedef struct smb2_error_response {
|
||||
uint16_t structure_size;
|
||||
uint16_t reserved;
|
||||
uint32_t bytecount;
|
||||
//uint8_t error_data[1]; // variable.
|
||||
} smb2_error_response;
|
||||
|
||||
typedef struct smb2_negotiate_request {
|
||||
uint16_t structure_size;
|
||||
uint16_t dialect_count;
|
||||
uint16_t security_mode;
|
||||
uint16_t reserved;
|
||||
uint32_t capabilities;
|
||||
uint8_t client_guid[16];
|
||||
uint32_t client_start_time[2];
|
||||
//uint16_t dialects[1]; // variable sized.
|
||||
|
||||
} smb2_negotiate_request;
|
||||
|
||||
|
||||
|
||||
typedef struct smb2_negotiate_response {
|
||||
uint16_t structure_size;
|
||||
uint16_t security_mode;
|
||||
uint16_t dialect_revision;
|
||||
uint16_t reserved;
|
||||
uint8_t server_guid[16];
|
||||
uint32_t capabilities;
|
||||
uint32_t max_transact_size;
|
||||
uint32_t max_read_size;
|
||||
uint32_t max_write_size;
|
||||
uint32_t server_start_time[2];
|
||||
uint16_t security_buffer_offset;
|
||||
uint16_t security_buffer_length;
|
||||
uint32_t reserved2;
|
||||
//uint8_t buffer[1]; // variable
|
||||
} smb2_negotiate_response;
|
||||
|
||||
|
||||
typedef struct smb2_session_setup_request {
|
||||
uint16_t structure_size;
|
||||
uint8_t flags;
|
||||
uint8_t security_mode;
|
||||
uint32_t capabilities;
|
||||
uint32_t channel;
|
||||
uint16_t security_buffer_offset;
|
||||
uint16_t security_buffer_length;
|
||||
uint32_t previous_session_id[2];
|
||||
//uint8t_t buffer[1]; // variable
|
||||
|
||||
} smb2_sessions_setup_request;
|
||||
|
||||
|
||||
typedef struct smb2_session_setup_response {
|
||||
uint16_t structure_size;
|
||||
uint16_t session_flags;
|
||||
uint16_t security_buffer_offset;
|
||||
uint16_t security_buffer_length;
|
||||
//uint8t_t buffer[1]; // variable
|
||||
} smb2_session_setup_response;
|
||||
|
||||
typedef struct smb2_logoff_request {
|
||||
uint16_t structure_size;
|
||||
uint16_t reserved;
|
||||
} smb2_logoff_request;
|
||||
|
||||
typedef struct smb2_logoff_response {
|
||||
uint16_t structure_size;
|
||||
uint16_t reserved;
|
||||
} smb2_logoff_response;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue