Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273/** * SMB2/3 Server - Main Entry Point * TypeScript implementation of SMB2/3 protocol server */
import { SMB2Server } from './server';import type { SMB2ServerConfig } from './protocol/types';import { SMB2_DIALECTS, SHARE_TYPE, SHARE_FLAGS, SHARE_CAPABILITIES, ACCESS_MASK} from './protocol/constants';import { Logger, setGlobalLogLevel } from './utils/logger';import { getEnvVar, getEnvNumber, getEnvBoolean, generateGuid } from './utils/helpers';
// Global loggerconst logger = new Logger('SMB2Main');
/** * Create default server configuration */function createDefaultConfig(): SMB2ServerConfig { return { serverGuid: generateGuid(), serverName: getEnvVar('SMB_SERVER_NAME', 'TypeScript-SMB-Server'), domainName: getEnvVar('SMB_DOMAIN_NAME'), workgroupName: getEnvVar('SMB_WORKGROUP_NAME', 'WORKGROUP'),
supportedDialects: [ SMB2_DIALECTS.SMB2_0_2, SMB2_DIALECTS.SMB2_1_0, SMB2_DIALECTS.SMB3_0_0, SMB2_DIALECTS.SMB3_0_2, SMB2_DIALECTS.SMB3_1_1, ],
requireMessageSigning: getEnvBoolean('SMB_REQUIRE_SIGNING', false), enableEncryption: getEnvBoolean('SMB_ENABLE_ENCRYPTION', false),
maxConnections: getEnvNumber('SMB_MAX_CONNECTIONS', 100), maxSessionsPerConnection: getEnvNumber('SMB_MAX_SESSIONS_PER_CONNECTION', 16), sessionTimeout: getEnvNumber('SMB_SESSION_TIMEOUT', 300000), // 5 minutes
maxTransactSize: getEnvNumber('SMB_MAX_TRANSACT_SIZE', 65536), maxReadSize: getEnvNumber('SMB_MAX_READ_SIZE', 65536), maxWriteSize: getEnvNumber('SMB_MAX_WRITE_SIZE', 65536),
// Default shares configuration shares: [ { name: 'Public', path: getEnvVar('SMB_SHARE_PATH', './shared'), shareType: SHARE_TYPE.DISK, shareFlags: SHARE_FLAGS.AUTO_CACHING | SHARE_FLAGS.ACCESS_BASED_DIRECTORY_ENUM, capabilities: SHARE_CAPABILITIES.DFS, maximalAccess: ACCESS_MASK.GENERIC_ALL, encryptData: false, cachingPolicy: 0, description: 'Public file share', accessControl: [], }, ],
// Default users configuration (empty - authentication disabled by default) users: [], };}
/** * Setup process event handlers */function setupProcessHandlers(server: SMB2Server): void { let isShuttingDown = false;
const gracefulShutdown = async (signal: string): Promise<void> => { if (isShuttingDown) { logger.warn('Force shutdown requested'); process.exit(1); }
isShuttingDown = true; logger.info(`Received ${signal}, shutting down gracefully...`);
try { await server.shutdown(); logger.info('Server shutdown complete'); process.exit(0); } catch (error) { logger.error('Error during shutdown:', error); process.exit(1); } };
// Handle graceful shutdown signals process.on('SIGINT', () => gracefulShutdown('SIGINT')); process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
// Handle uncaught exceptions process.on('uncaughtException', (error) => { logger.error('Uncaught exception:', error); gracefulShutdown('uncaughtException'); });
// Handle unhandled promise rejections process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled promise rejection:', { reason, promise }); gracefulShutdown('unhandledRejection'); });}
/** * Setup server event handlers */function setupServerHandlers(server: SMB2Server): void { // Connection events server.onEvent('connection:established', (event) => { logger.info(`New client connected: ${event.data.connection.clientAddress}`); });
server.onEvent('connection:closed', (event) => { logger.info(`Client disconnected: ${event.data.connectionId} (${event.data.reason})`); });
// Session events server.onEvent('session:established', (event) => { logger.info(`Session established: ${event.data.sessionId} for user ${event.data.userId}`); });
server.onEvent('session:closed', (event) => { logger.info(`Session closed: ${event.data.sessionId} (${event.data.reason})`); });
// Tree connect events server.onEvent('tree:connected', (event) => { logger.info(`Tree connected: ${event.data.shareName} (ID: ${event.data.treeConnectId})`); });
server.onEvent('tree:disconnected', (event) => { logger.info(`Tree disconnected: ${event.data.treeConnectId} (${event.data.reason})`); });
// File operation events server.onEvent('file:opened', (event) => { logger.debug(`File opened: ${event.data.fileName}`); });
server.onEvent('file:closed', (event) => { logger.debug(`File closed: ${event.data.fileName}`); });
server.onEvent('file:read', (event) => { logger.debug(`File read: ${event.data.fileName} (${event.data.bytes} bytes)`); });
server.onEvent('file:written', (event) => { logger.debug(`File written: ${event.data.fileName} (${event.data.bytes} bytes)`); });
// Error events server.onEvent('error', (event) => { logger.error('Server error:', event.data.error); });
server.onEvent('warning', (event) => { logger.warn('Server warning:', event.data); });}
/** * Main server startup function */async function startServer(): Promise<void> { try { // Set log level from environment const logLevel = getEnvVar('LOG_LEVEL', 'info') as any; setGlobalLogLevel(logLevel);
logger.info('Starting SMB2/3 Server...');
// Create server configuration const config = createDefaultConfig(); logger.info(`Server configuration:`); logger.info(` Server Name: ${config.serverName}`); logger.info(` Server GUID: ${config.serverGuid}`); logger.info(` Supported Dialects: ${config.supportedDialects.map(d => `0x${d.toString(16).toUpperCase()}`).join(', ')}`); logger.info(` Require Signing: ${config.requireMessageSigning}`); logger.info(` Enable Encryption: ${config.enableEncryption}`); logger.info(` Max Connections: ${config.maxConnections}`); logger.info(` Shares: ${config.shares.map(s => `${s.name} (${s.path})`).join(', ')}`);
// Create and configure server const server = new SMB2Server(config);
// Setup event handlers setupServerHandlers(server); setupProcessHandlers(server);
// Start server const port = getEnvNumber('SMB_PORT', 445); const hostname = getEnvVar('SMB_HOST');
await server.start(port, hostname);
logger.info('SMB2/3 Server started successfully!'); logger.info(`Listening on ${hostname || '0.0.0.0'}:${port}`); logger.info('Press Ctrl+C to shutdown');
// Log server stats periodically setInterval(() => { const stats = server.getStats(); logger.debug(`Server stats: ${stats.connections} connections, ${stats.sessions} sessions, uptime: ${Math.round(stats.uptime / 1000)}s`); }, 60000); // Every minute
} catch (error) { logger.error('Failed to start server:', error); process.exit(1); }}
/** * Display help information */function showHelp(): void { console.log(`SMB2/3 Server - TypeScript Implementation
Usage: npm start [options]
Environment Variables: LOG_LEVEL Set logging level (error, warn, info, debug) [default: info] SMB_PORT Server port [default: 445] SMB_HOST Server hostname/IP [default: 0.0.0.0] SMB_SERVER_NAME Server name [default: TypeScript-SMB-Server] SMB_DOMAIN_NAME Domain name [optional] SMB_WORKGROUP_NAME Workgroup name [default: WORKGROUP] SMB_REQUIRE_SIGNING Require message signing [default: false] SMB_ENABLE_ENCRYPTION Enable SMB encryption [default: false] SMB_MAX_CONNECTIONS Maximum concurrent connections [default: 100] SMB_MAX_SESSIONS_PER_CONNECTION Max sessions per connection [default: 16] SMB_SESSION_TIMEOUT Session timeout in ms [default: 300000] SMB_MAX_TRANSACT_SIZE Maximum transaction size [default: 65536] SMB_MAX_READ_SIZE Maximum read size [default: 65536] SMB_MAX_WRITE_SIZE Maximum write size [default: 65536] SMB_SHARE_PATH Default share path [default: ./shared]
Examples: npm start Start with default configuration LOG_LEVEL=debug npm start Start with debug logging SMB_PORT=8445 npm start Start on custom port
Note: Running on port 445 typically requires administrator/root privileges.`);}
// Check for help flagif (process.argv.includes('--help') || process.argv.includes('-h')) { showHelp(); process.exit(0);}
// Start the serverstartServer().catch((error) => { logger.error('Startup error:', error); process.exit(1);});
// Export for programmatic useexport { SMB2Server, createDefaultConfig };export * from './protocol/types';export * from './protocol/constants';