1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*6236dae4SAndroid Build Coastguard Worker# -*- coding: utf-8 -*- 3*6236dae4SAndroid Build Coastguard Worker# 4*6236dae4SAndroid Build Coastguard Worker# Project ___| | | | _ \| | 5*6236dae4SAndroid Build Coastguard Worker# / __| | | | |_) | | 6*6236dae4SAndroid Build Coastguard Worker# | (__| |_| | _ <| |___ 7*6236dae4SAndroid Build Coastguard Worker# \___|\___/|_| \_\_____| 8*6236dae4SAndroid Build Coastguard Worker# 9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al. 10*6236dae4SAndroid Build Coastguard Worker# 11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which 12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms 13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html. 14*6236dae4SAndroid Build Coastguard Worker# 15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is 17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file. 18*6236dae4SAndroid Build Coastguard Worker# 19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied. 21*6236dae4SAndroid Build Coastguard Worker# 22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl 23*6236dae4SAndroid Build Coastguard Worker# 24*6236dae4SAndroid Build Coastguard Worker"""Server for testing SMB.""" 25*6236dae4SAndroid Build Coastguard Worker 26*6236dae4SAndroid Build Coastguard Workerfrom __future__ import (absolute_import, division, print_function, 27*6236dae4SAndroid Build Coastguard Worker unicode_literals) 28*6236dae4SAndroid Build Coastguard Worker 29*6236dae4SAndroid Build Coastguard Workerimport argparse 30*6236dae4SAndroid Build Coastguard Workerimport logging 31*6236dae4SAndroid Build Coastguard Workerimport os 32*6236dae4SAndroid Build Coastguard Workerimport signal 33*6236dae4SAndroid Build Coastguard Workerimport sys 34*6236dae4SAndroid Build Coastguard Workerimport tempfile 35*6236dae4SAndroid Build Coastguard Workerimport threading 36*6236dae4SAndroid Build Coastguard Worker 37*6236dae4SAndroid Build Coastguard Worker# Import our curl test data helper 38*6236dae4SAndroid Build Coastguard Workerfrom util import ClosingFileHandler, TestData 39*6236dae4SAndroid Build Coastguard Worker 40*6236dae4SAndroid Build Coastguard Workerif sys.version_info.major >= 3: 41*6236dae4SAndroid Build Coastguard Worker import configparser 42*6236dae4SAndroid Build Coastguard Workerelse: 43*6236dae4SAndroid Build Coastguard Worker import ConfigParser as configparser 44*6236dae4SAndroid Build Coastguard Worker 45*6236dae4SAndroid Build Coastguard Worker# impacket needs to be installed in the Python environment 46*6236dae4SAndroid Build Coastguard Workertry: 47*6236dae4SAndroid Build Coastguard Worker import impacket # noqa: F401 48*6236dae4SAndroid Build Coastguard Workerexcept ImportError: 49*6236dae4SAndroid Build Coastguard Worker sys.stderr.write( 50*6236dae4SAndroid Build Coastguard Worker 'Warning: Python package impacket is required for smb testing; ' 51*6236dae4SAndroid Build Coastguard Worker 'use pip or your package manager to install it\n') 52*6236dae4SAndroid Build Coastguard Worker sys.exit(1) 53*6236dae4SAndroid Build Coastguard Workerfrom impacket import smb as imp_smb 54*6236dae4SAndroid Build Coastguard Workerfrom impacket import smbserver as imp_smbserver 55*6236dae4SAndroid Build Coastguard Workerfrom impacket.nt_errors import (STATUS_ACCESS_DENIED, STATUS_NO_SUCH_FILE, 56*6236dae4SAndroid Build Coastguard Worker STATUS_SUCCESS) 57*6236dae4SAndroid Build Coastguard Worker 58*6236dae4SAndroid Build Coastguard Workerlog = logging.getLogger(__name__) 59*6236dae4SAndroid Build Coastguard WorkerSERVER_MAGIC = "SERVER_MAGIC" 60*6236dae4SAndroid Build Coastguard WorkerTESTS_MAGIC = "TESTS_MAGIC" 61*6236dae4SAndroid Build Coastguard WorkerVERIFIED_REQ = "verifiedserver" 62*6236dae4SAndroid Build Coastguard WorkerVERIFIED_RSP = "WE ROOLZ: {pid}\n" 63*6236dae4SAndroid Build Coastguard Worker 64*6236dae4SAndroid Build Coastguard Worker 65*6236dae4SAndroid Build Coastguard Workerclass ShutdownHandler(threading.Thread): 66*6236dae4SAndroid Build Coastguard Worker """ 67*6236dae4SAndroid Build Coastguard Worker Cleanly shut down the SMB server. 68*6236dae4SAndroid Build Coastguard Worker 69*6236dae4SAndroid Build Coastguard Worker This can only be done from another thread while the server is in 70*6236dae4SAndroid Build Coastguard Worker serve_forever(), so a thread is spawned here that waits for a shutdown 71*6236dae4SAndroid Build Coastguard Worker signal before doing its thing. Use in a with statement around the 72*6236dae4SAndroid Build Coastguard Worker serve_forever() call. 73*6236dae4SAndroid Build Coastguard Worker """ 74*6236dae4SAndroid Build Coastguard Worker 75*6236dae4SAndroid Build Coastguard Worker def __init__(self, server): 76*6236dae4SAndroid Build Coastguard Worker super(ShutdownHandler, self).__init__() 77*6236dae4SAndroid Build Coastguard Worker self.server = server 78*6236dae4SAndroid Build Coastguard Worker self.shutdown_event = threading.Event() 79*6236dae4SAndroid Build Coastguard Worker 80*6236dae4SAndroid Build Coastguard Worker def __enter__(self): 81*6236dae4SAndroid Build Coastguard Worker self.start() 82*6236dae4SAndroid Build Coastguard Worker signal.signal(signal.SIGINT, self._sighandler) 83*6236dae4SAndroid Build Coastguard Worker signal.signal(signal.SIGTERM, self._sighandler) 84*6236dae4SAndroid Build Coastguard Worker 85*6236dae4SAndroid Build Coastguard Worker def __exit__(self, *_): 86*6236dae4SAndroid Build Coastguard Worker # Call for shutdown just in case it wasn't done already 87*6236dae4SAndroid Build Coastguard Worker self.shutdown_event.set() 88*6236dae4SAndroid Build Coastguard Worker # Wait for thread, and therefore also the server, to finish 89*6236dae4SAndroid Build Coastguard Worker self.join() 90*6236dae4SAndroid Build Coastguard Worker # Uninstall our signal handlers 91*6236dae4SAndroid Build Coastguard Worker signal.signal(signal.SIGINT, signal.SIG_DFL) 92*6236dae4SAndroid Build Coastguard Worker signal.signal(signal.SIGTERM, signal.SIG_DFL) 93*6236dae4SAndroid Build Coastguard Worker # Delete any temporary files created by the server during its run 94*6236dae4SAndroid Build Coastguard Worker log.info("Deleting %d temporary file(s)", len(self.server.tmpfiles)) 95*6236dae4SAndroid Build Coastguard Worker for f in self.server.tmpfiles: 96*6236dae4SAndroid Build Coastguard Worker os.unlink(f) 97*6236dae4SAndroid Build Coastguard Worker 98*6236dae4SAndroid Build Coastguard Worker def _sighandler(self, _signum, _frame): 99*6236dae4SAndroid Build Coastguard Worker # Wake up the cleanup task 100*6236dae4SAndroid Build Coastguard Worker self.shutdown_event.set() 101*6236dae4SAndroid Build Coastguard Worker 102*6236dae4SAndroid Build Coastguard Worker def run(self): 103*6236dae4SAndroid Build Coastguard Worker # Wait for shutdown signal 104*6236dae4SAndroid Build Coastguard Worker self.shutdown_event.wait() 105*6236dae4SAndroid Build Coastguard Worker # Notify the server to shut down 106*6236dae4SAndroid Build Coastguard Worker self.server.shutdown() 107*6236dae4SAndroid Build Coastguard Worker 108*6236dae4SAndroid Build Coastguard Worker 109*6236dae4SAndroid Build Coastguard Workerdef smbserver(options): 110*6236dae4SAndroid Build Coastguard Worker """Start up a TCP SMB server that serves forever.""" 111*6236dae4SAndroid Build Coastguard Worker if options.pidfile: 112*6236dae4SAndroid Build Coastguard Worker pid = os.getpid() 113*6236dae4SAndroid Build Coastguard Worker # see tests/server/util.c function write_pidfile 114*6236dae4SAndroid Build Coastguard Worker if os.name == "nt": 115*6236dae4SAndroid Build Coastguard Worker pid += 65536 116*6236dae4SAndroid Build Coastguard Worker with open(options.pidfile, "w") as f: 117*6236dae4SAndroid Build Coastguard Worker f.write(str(pid)) 118*6236dae4SAndroid Build Coastguard Worker 119*6236dae4SAndroid Build Coastguard Worker # Here we write a mini config for the server 120*6236dae4SAndroid Build Coastguard Worker smb_config = configparser.ConfigParser() 121*6236dae4SAndroid Build Coastguard Worker smb_config.add_section("global") 122*6236dae4SAndroid Build Coastguard Worker smb_config.set("global", "server_name", "SERVICE") 123*6236dae4SAndroid Build Coastguard Worker smb_config.set("global", "server_os", "UNIX") 124*6236dae4SAndroid Build Coastguard Worker smb_config.set("global", "server_domain", "WORKGROUP") 125*6236dae4SAndroid Build Coastguard Worker smb_config.set("global", "log_file", "None") 126*6236dae4SAndroid Build Coastguard Worker smb_config.set("global", "credentials_file", "") 127*6236dae4SAndroid Build Coastguard Worker 128*6236dae4SAndroid Build Coastguard Worker # We need a share which allows us to test that the server is running 129*6236dae4SAndroid Build Coastguard Worker smb_config.add_section("SERVER") 130*6236dae4SAndroid Build Coastguard Worker smb_config.set("SERVER", "comment", "server function") 131*6236dae4SAndroid Build Coastguard Worker smb_config.set("SERVER", "read only", "yes") 132*6236dae4SAndroid Build Coastguard Worker smb_config.set("SERVER", "share type", "0") 133*6236dae4SAndroid Build Coastguard Worker smb_config.set("SERVER", "path", SERVER_MAGIC) 134*6236dae4SAndroid Build Coastguard Worker 135*6236dae4SAndroid Build Coastguard Worker # Have a share for tests. These files will be autogenerated from the 136*6236dae4SAndroid Build Coastguard Worker # test input. 137*6236dae4SAndroid Build Coastguard Worker smb_config.add_section("TESTS") 138*6236dae4SAndroid Build Coastguard Worker smb_config.set("TESTS", "comment", "tests") 139*6236dae4SAndroid Build Coastguard Worker smb_config.set("TESTS", "read only", "yes") 140*6236dae4SAndroid Build Coastguard Worker smb_config.set("TESTS", "share type", "0") 141*6236dae4SAndroid Build Coastguard Worker smb_config.set("TESTS", "path", TESTS_MAGIC) 142*6236dae4SAndroid Build Coastguard Worker 143*6236dae4SAndroid Build Coastguard Worker if not options.srcdir or not os.path.isdir(options.srcdir): 144*6236dae4SAndroid Build Coastguard Worker raise ScriptError("--srcdir is mandatory") 145*6236dae4SAndroid Build Coastguard Worker 146*6236dae4SAndroid Build Coastguard Worker test_data_dir = os.path.join(options.srcdir, "data") 147*6236dae4SAndroid Build Coastguard Worker 148*6236dae4SAndroid Build Coastguard Worker smb_server = TestSmbServer((options.host, options.port), 149*6236dae4SAndroid Build Coastguard Worker config_parser=smb_config, 150*6236dae4SAndroid Build Coastguard Worker test_data_directory=test_data_dir) 151*6236dae4SAndroid Build Coastguard Worker log.info("[SMB] setting up SMB server on port %s", options.port) 152*6236dae4SAndroid Build Coastguard Worker smb_server.processConfigFile() 153*6236dae4SAndroid Build Coastguard Worker 154*6236dae4SAndroid Build Coastguard Worker # Start a thread that cleanly shuts down the server on a signal 155*6236dae4SAndroid Build Coastguard Worker with ShutdownHandler(smb_server): 156*6236dae4SAndroid Build Coastguard Worker # This will block until smb_server.shutdown() is called 157*6236dae4SAndroid Build Coastguard Worker smb_server.serve_forever() 158*6236dae4SAndroid Build Coastguard Worker 159*6236dae4SAndroid Build Coastguard Worker return 0 160*6236dae4SAndroid Build Coastguard Worker 161*6236dae4SAndroid Build Coastguard Worker 162*6236dae4SAndroid Build Coastguard Workerclass TestSmbServer(imp_smbserver.SMBSERVER): 163*6236dae4SAndroid Build Coastguard Worker """ 164*6236dae4SAndroid Build Coastguard Worker Test server for SMB which subclasses the impacket SMBSERVER and provides 165*6236dae4SAndroid Build Coastguard Worker test functionality. 166*6236dae4SAndroid Build Coastguard Worker """ 167*6236dae4SAndroid Build Coastguard Worker 168*6236dae4SAndroid Build Coastguard Worker def __init__(self, 169*6236dae4SAndroid Build Coastguard Worker address, 170*6236dae4SAndroid Build Coastguard Worker config_parser=None, 171*6236dae4SAndroid Build Coastguard Worker test_data_directory=None): 172*6236dae4SAndroid Build Coastguard Worker imp_smbserver.SMBSERVER.__init__(self, 173*6236dae4SAndroid Build Coastguard Worker address, 174*6236dae4SAndroid Build Coastguard Worker config_parser=config_parser) 175*6236dae4SAndroid Build Coastguard Worker self.tmpfiles = [] 176*6236dae4SAndroid Build Coastguard Worker 177*6236dae4SAndroid Build Coastguard Worker # Set up a test data object so we can get test data later. 178*6236dae4SAndroid Build Coastguard Worker self.ctd = TestData(test_data_directory) 179*6236dae4SAndroid Build Coastguard Worker 180*6236dae4SAndroid Build Coastguard Worker # Override smbComNtCreateAndX so we can pretend to have files which 181*6236dae4SAndroid Build Coastguard Worker # don't exist. 182*6236dae4SAndroid Build Coastguard Worker self.hookSmbCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX, 183*6236dae4SAndroid Build Coastguard Worker self.create_and_x) 184*6236dae4SAndroid Build Coastguard Worker 185*6236dae4SAndroid Build Coastguard Worker def create_and_x(self, conn_id, smb_server, smb_command, recv_packet): 186*6236dae4SAndroid Build Coastguard Worker """ 187*6236dae4SAndroid Build Coastguard Worker Our version of smbComNtCreateAndX looks for special test files and 188*6236dae4SAndroid Build Coastguard Worker fools the rest of the framework into opening them as if they were 189*6236dae4SAndroid Build Coastguard Worker normal files. 190*6236dae4SAndroid Build Coastguard Worker """ 191*6236dae4SAndroid Build Coastguard Worker conn_data = smb_server.getConnectionData(conn_id) 192*6236dae4SAndroid Build Coastguard Worker 193*6236dae4SAndroid Build Coastguard Worker # Wrap processing in a try block which allows us to throw SmbError 194*6236dae4SAndroid Build Coastguard Worker # to control the flow. 195*6236dae4SAndroid Build Coastguard Worker try: 196*6236dae4SAndroid Build Coastguard Worker ncax_parms = imp_smb.SMBNtCreateAndX_Parameters( 197*6236dae4SAndroid Build Coastguard Worker smb_command["Parameters"]) 198*6236dae4SAndroid Build Coastguard Worker 199*6236dae4SAndroid Build Coastguard Worker path = self.get_share_path(conn_data, 200*6236dae4SAndroid Build Coastguard Worker ncax_parms["RootFid"], 201*6236dae4SAndroid Build Coastguard Worker recv_packet["Tid"]) 202*6236dae4SAndroid Build Coastguard Worker log.info("[SMB] Requested share path: %s", path) 203*6236dae4SAndroid Build Coastguard Worker 204*6236dae4SAndroid Build Coastguard Worker disposition = ncax_parms["Disposition"] 205*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] Requested disposition: %s", disposition) 206*6236dae4SAndroid Build Coastguard Worker 207*6236dae4SAndroid Build Coastguard Worker # Currently we only support reading files. 208*6236dae4SAndroid Build Coastguard Worker if disposition != imp_smb.FILE_OPEN: 209*6236dae4SAndroid Build Coastguard Worker raise SmbError(STATUS_ACCESS_DENIED, 210*6236dae4SAndroid Build Coastguard Worker "Only support reading files") 211*6236dae4SAndroid Build Coastguard Worker 212*6236dae4SAndroid Build Coastguard Worker # Check to see if the path we were given is actually a 213*6236dae4SAndroid Build Coastguard Worker # magic path which needs generating on the fly. 214*6236dae4SAndroid Build Coastguard Worker if path not in [SERVER_MAGIC, TESTS_MAGIC]: 215*6236dae4SAndroid Build Coastguard Worker # Pass the command onto the original handler. 216*6236dae4SAndroid Build Coastguard Worker return imp_smbserver.SMBCommands.smbComNtCreateAndX(conn_id, 217*6236dae4SAndroid Build Coastguard Worker smb_server, 218*6236dae4SAndroid Build Coastguard Worker smb_command, 219*6236dae4SAndroid Build Coastguard Worker recv_packet) 220*6236dae4SAndroid Build Coastguard Worker 221*6236dae4SAndroid Build Coastguard Worker flags2 = recv_packet["Flags2"] 222*6236dae4SAndroid Build Coastguard Worker ncax_data = imp_smb.SMBNtCreateAndX_Data(flags=flags2, 223*6236dae4SAndroid Build Coastguard Worker data=smb_command[ 224*6236dae4SAndroid Build Coastguard Worker "Data"]) 225*6236dae4SAndroid Build Coastguard Worker requested_file = imp_smbserver.decodeSMBString( 226*6236dae4SAndroid Build Coastguard Worker flags2, 227*6236dae4SAndroid Build Coastguard Worker ncax_data["FileName"]) 228*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] User requested file '%s'", requested_file) 229*6236dae4SAndroid Build Coastguard Worker 230*6236dae4SAndroid Build Coastguard Worker if path == SERVER_MAGIC: 231*6236dae4SAndroid Build Coastguard Worker fid, full_path = self.get_server_path(requested_file) 232*6236dae4SAndroid Build Coastguard Worker else: 233*6236dae4SAndroid Build Coastguard Worker assert path == TESTS_MAGIC 234*6236dae4SAndroid Build Coastguard Worker fid, full_path = self.get_test_path(requested_file) 235*6236dae4SAndroid Build Coastguard Worker 236*6236dae4SAndroid Build Coastguard Worker self.tmpfiles.append(full_path) 237*6236dae4SAndroid Build Coastguard Worker 238*6236dae4SAndroid Build Coastguard Worker resp_parms = imp_smb.SMBNtCreateAndXResponse_Parameters() 239*6236dae4SAndroid Build Coastguard Worker resp_data = "" 240*6236dae4SAndroid Build Coastguard Worker 241*6236dae4SAndroid Build Coastguard Worker # Simple way to generate a fid 242*6236dae4SAndroid Build Coastguard Worker if len(conn_data["OpenedFiles"]) == 0: 243*6236dae4SAndroid Build Coastguard Worker fakefid = 1 244*6236dae4SAndroid Build Coastguard Worker else: 245*6236dae4SAndroid Build Coastguard Worker fakefid = conn_data["OpenedFiles"].keys()[-1] + 1 246*6236dae4SAndroid Build Coastguard Worker resp_parms["Fid"] = fakefid 247*6236dae4SAndroid Build Coastguard Worker resp_parms["CreateAction"] = disposition 248*6236dae4SAndroid Build Coastguard Worker 249*6236dae4SAndroid Build Coastguard Worker if os.path.isdir(path): 250*6236dae4SAndroid Build Coastguard Worker resp_parms[ 251*6236dae4SAndroid Build Coastguard Worker "FileAttributes"] = imp_smb.SMB_FILE_ATTRIBUTE_DIRECTORY 252*6236dae4SAndroid Build Coastguard Worker resp_parms["IsDirectory"] = 1 253*6236dae4SAndroid Build Coastguard Worker else: 254*6236dae4SAndroid Build Coastguard Worker resp_parms["IsDirectory"] = 0 255*6236dae4SAndroid Build Coastguard Worker resp_parms["FileAttributes"] = ncax_parms["FileAttributes"] 256*6236dae4SAndroid Build Coastguard Worker 257*6236dae4SAndroid Build Coastguard Worker # Get this file's information 258*6236dae4SAndroid Build Coastguard Worker resp_info, error_code = imp_smbserver.queryPathInformation( 259*6236dae4SAndroid Build Coastguard Worker os.path.dirname(full_path), os.path.basename(full_path), 260*6236dae4SAndroid Build Coastguard Worker level=imp_smb.SMB_QUERY_FILE_ALL_INFO) 261*6236dae4SAndroid Build Coastguard Worker 262*6236dae4SAndroid Build Coastguard Worker if error_code != STATUS_SUCCESS: 263*6236dae4SAndroid Build Coastguard Worker raise SmbError(error_code, "Failed to query path info") 264*6236dae4SAndroid Build Coastguard Worker 265*6236dae4SAndroid Build Coastguard Worker resp_parms["CreateTime"] = resp_info["CreationTime"] 266*6236dae4SAndroid Build Coastguard Worker resp_parms["LastAccessTime"] = resp_info[ 267*6236dae4SAndroid Build Coastguard Worker "LastAccessTime"] 268*6236dae4SAndroid Build Coastguard Worker resp_parms["LastWriteTime"] = resp_info["LastWriteTime"] 269*6236dae4SAndroid Build Coastguard Worker resp_parms["LastChangeTime"] = resp_info[ 270*6236dae4SAndroid Build Coastguard Worker "LastChangeTime"] 271*6236dae4SAndroid Build Coastguard Worker resp_parms["FileAttributes"] = resp_info[ 272*6236dae4SAndroid Build Coastguard Worker "ExtFileAttributes"] 273*6236dae4SAndroid Build Coastguard Worker resp_parms["AllocationSize"] = resp_info[ 274*6236dae4SAndroid Build Coastguard Worker "AllocationSize"] 275*6236dae4SAndroid Build Coastguard Worker resp_parms["EndOfFile"] = resp_info["EndOfFile"] 276*6236dae4SAndroid Build Coastguard Worker 277*6236dae4SAndroid Build Coastguard Worker # Let's store the fid for the connection 278*6236dae4SAndroid Build Coastguard Worker # smbServer.log("Create file %s, mode:0x%x" % (pathName, mode)) 279*6236dae4SAndroid Build Coastguard Worker conn_data["OpenedFiles"][fakefid] = {} 280*6236dae4SAndroid Build Coastguard Worker conn_data["OpenedFiles"][fakefid]["FileHandle"] = fid 281*6236dae4SAndroid Build Coastguard Worker conn_data["OpenedFiles"][fakefid]["FileName"] = path 282*6236dae4SAndroid Build Coastguard Worker conn_data["OpenedFiles"][fakefid]["DeleteOnClose"] = False 283*6236dae4SAndroid Build Coastguard Worker 284*6236dae4SAndroid Build Coastguard Worker except SmbError as s: 285*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] SmbError hit: %s", s) 286*6236dae4SAndroid Build Coastguard Worker error_code = s.error_code 287*6236dae4SAndroid Build Coastguard Worker resp_parms = "" 288*6236dae4SAndroid Build Coastguard Worker resp_data = "" 289*6236dae4SAndroid Build Coastguard Worker 290*6236dae4SAndroid Build Coastguard Worker resp_cmd = imp_smb.SMBCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX) 291*6236dae4SAndroid Build Coastguard Worker resp_cmd["Parameters"] = resp_parms 292*6236dae4SAndroid Build Coastguard Worker resp_cmd["Data"] = resp_data 293*6236dae4SAndroid Build Coastguard Worker smb_server.setConnectionData(conn_id, conn_data) 294*6236dae4SAndroid Build Coastguard Worker 295*6236dae4SAndroid Build Coastguard Worker return [resp_cmd], None, error_code 296*6236dae4SAndroid Build Coastguard Worker 297*6236dae4SAndroid Build Coastguard Worker def get_share_path(self, conn_data, root_fid, tid): 298*6236dae4SAndroid Build Coastguard Worker conn_shares = conn_data["ConnectedShares"] 299*6236dae4SAndroid Build Coastguard Worker 300*6236dae4SAndroid Build Coastguard Worker if tid in conn_shares: 301*6236dae4SAndroid Build Coastguard Worker if root_fid > 0: 302*6236dae4SAndroid Build Coastguard Worker # If we have a rootFid, the path is relative to that fid 303*6236dae4SAndroid Build Coastguard Worker path = conn_data["OpenedFiles"][root_fid]["FileName"] 304*6236dae4SAndroid Build Coastguard Worker log.debug("RootFid present %s!" % path) 305*6236dae4SAndroid Build Coastguard Worker else: 306*6236dae4SAndroid Build Coastguard Worker if "path" in conn_shares[tid]: 307*6236dae4SAndroid Build Coastguard Worker path = conn_shares[tid]["path"] 308*6236dae4SAndroid Build Coastguard Worker else: 309*6236dae4SAndroid Build Coastguard Worker raise SmbError(STATUS_ACCESS_DENIED, 310*6236dae4SAndroid Build Coastguard Worker "Connection share had no path") 311*6236dae4SAndroid Build Coastguard Worker else: 312*6236dae4SAndroid Build Coastguard Worker raise SmbError(imp_smbserver.STATUS_SMB_BAD_TID, 313*6236dae4SAndroid Build Coastguard Worker "TID was invalid") 314*6236dae4SAndroid Build Coastguard Worker 315*6236dae4SAndroid Build Coastguard Worker return path 316*6236dae4SAndroid Build Coastguard Worker 317*6236dae4SAndroid Build Coastguard Worker def get_server_path(self, requested_filename): 318*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] Get server path '%s'", requested_filename) 319*6236dae4SAndroid Build Coastguard Worker 320*6236dae4SAndroid Build Coastguard Worker if requested_filename not in [VERIFIED_REQ]: 321*6236dae4SAndroid Build Coastguard Worker raise SmbError(STATUS_NO_SUCH_FILE, "Couldn't find the file") 322*6236dae4SAndroid Build Coastguard Worker 323*6236dae4SAndroid Build Coastguard Worker fid, filename = tempfile.mkstemp() 324*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] Created %s (%d) for storing '%s'", 325*6236dae4SAndroid Build Coastguard Worker filename, fid, requested_filename) 326*6236dae4SAndroid Build Coastguard Worker 327*6236dae4SAndroid Build Coastguard Worker contents = "" 328*6236dae4SAndroid Build Coastguard Worker 329*6236dae4SAndroid Build Coastguard Worker if requested_filename == VERIFIED_REQ: 330*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] Verifying server is alive") 331*6236dae4SAndroid Build Coastguard Worker pid = os.getpid() 332*6236dae4SAndroid Build Coastguard Worker # see tests/server/util.c function write_pidfile 333*6236dae4SAndroid Build Coastguard Worker if os.name == "nt": 334*6236dae4SAndroid Build Coastguard Worker pid += 65536 335*6236dae4SAndroid Build Coastguard Worker contents = VERIFIED_RSP.format(pid=pid).encode('utf-8') 336*6236dae4SAndroid Build Coastguard Worker 337*6236dae4SAndroid Build Coastguard Worker self.write_to_fid(fid, contents) 338*6236dae4SAndroid Build Coastguard Worker return fid, filename 339*6236dae4SAndroid Build Coastguard Worker 340*6236dae4SAndroid Build Coastguard Worker def write_to_fid(self, fid, contents): 341*6236dae4SAndroid Build Coastguard Worker # Write the contents to file descriptor 342*6236dae4SAndroid Build Coastguard Worker os.write(fid, contents) 343*6236dae4SAndroid Build Coastguard Worker os.fsync(fid) 344*6236dae4SAndroid Build Coastguard Worker 345*6236dae4SAndroid Build Coastguard Worker # Rewind the file to the beginning so a read gets us the contents 346*6236dae4SAndroid Build Coastguard Worker os.lseek(fid, 0, os.SEEK_SET) 347*6236dae4SAndroid Build Coastguard Worker 348*6236dae4SAndroid Build Coastguard Worker def get_test_path(self, requested_filename): 349*6236dae4SAndroid Build Coastguard Worker log.info("[SMB] Get reply data from 'test%s'", requested_filename) 350*6236dae4SAndroid Build Coastguard Worker 351*6236dae4SAndroid Build Coastguard Worker fid, filename = tempfile.mkstemp() 352*6236dae4SAndroid Build Coastguard Worker log.debug("[SMB] Created %s (%d) for storing test '%s'", 353*6236dae4SAndroid Build Coastguard Worker filename, fid, requested_filename) 354*6236dae4SAndroid Build Coastguard Worker 355*6236dae4SAndroid Build Coastguard Worker try: 356*6236dae4SAndroid Build Coastguard Worker contents = self.ctd.get_test_data(requested_filename).encode('utf-8') 357*6236dae4SAndroid Build Coastguard Worker self.write_to_fid(fid, contents) 358*6236dae4SAndroid Build Coastguard Worker return fid, filename 359*6236dae4SAndroid Build Coastguard Worker 360*6236dae4SAndroid Build Coastguard Worker except Exception: 361*6236dae4SAndroid Build Coastguard Worker log.exception("Failed to make test file") 362*6236dae4SAndroid Build Coastguard Worker raise SmbError(STATUS_NO_SUCH_FILE, "Failed to make test file") 363*6236dae4SAndroid Build Coastguard Worker 364*6236dae4SAndroid Build Coastguard Worker 365*6236dae4SAndroid Build Coastguard Workerclass SmbError(Exception): 366*6236dae4SAndroid Build Coastguard Worker def __init__(self, error_code, error_message): 367*6236dae4SAndroid Build Coastguard Worker super(SmbError, self).__init__(error_message) 368*6236dae4SAndroid Build Coastguard Worker self.error_code = error_code 369*6236dae4SAndroid Build Coastguard Worker 370*6236dae4SAndroid Build Coastguard Worker 371*6236dae4SAndroid Build Coastguard Workerclass ScriptRC(object): 372*6236dae4SAndroid Build Coastguard Worker """Enum for script return codes.""" 373*6236dae4SAndroid Build Coastguard Worker 374*6236dae4SAndroid Build Coastguard Worker SUCCESS = 0 375*6236dae4SAndroid Build Coastguard Worker FAILURE = 1 376*6236dae4SAndroid Build Coastguard Worker EXCEPTION = 2 377*6236dae4SAndroid Build Coastguard Worker 378*6236dae4SAndroid Build Coastguard Worker 379*6236dae4SAndroid Build Coastguard Workerclass ScriptError(Exception): 380*6236dae4SAndroid Build Coastguard Worker pass 381*6236dae4SAndroid Build Coastguard Worker 382*6236dae4SAndroid Build Coastguard Worker 383*6236dae4SAndroid Build Coastguard Workerdef get_options(): 384*6236dae4SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 385*6236dae4SAndroid Build Coastguard Worker 386*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--port", action="store", default=9017, 387*6236dae4SAndroid Build Coastguard Worker type=int, help="port to listen on") 388*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--host", action="store", default="127.0.0.1", 389*6236dae4SAndroid Build Coastguard Worker help="host to listen on") 390*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--verbose", action="store", type=int, default=0, 391*6236dae4SAndroid Build Coastguard Worker help="verbose output") 392*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--pidfile", action="store", 393*6236dae4SAndroid Build Coastguard Worker help="file name for the PID") 394*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--logfile", action="store", 395*6236dae4SAndroid Build Coastguard Worker help="file name for the log") 396*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--srcdir", action="store", help="test directory") 397*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--id", action="store", help="server ID") 398*6236dae4SAndroid Build Coastguard Worker parser.add_argument("--ipv4", action="store_true", default=0, 399*6236dae4SAndroid Build Coastguard Worker help="IPv4 flag") 400*6236dae4SAndroid Build Coastguard Worker 401*6236dae4SAndroid Build Coastguard Worker return parser.parse_args() 402*6236dae4SAndroid Build Coastguard Worker 403*6236dae4SAndroid Build Coastguard Worker 404*6236dae4SAndroid Build Coastguard Workerdef setup_logging(options): 405*6236dae4SAndroid Build Coastguard Worker """Set up logging from the command line options.""" 406*6236dae4SAndroid Build Coastguard Worker root_logger = logging.getLogger() 407*6236dae4SAndroid Build Coastguard Worker add_stdout = False 408*6236dae4SAndroid Build Coastguard Worker 409*6236dae4SAndroid Build Coastguard Worker formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s %(message)s") 410*6236dae4SAndroid Build Coastguard Worker 411*6236dae4SAndroid Build Coastguard Worker # Write out to a logfile 412*6236dae4SAndroid Build Coastguard Worker if options.logfile: 413*6236dae4SAndroid Build Coastguard Worker handler = ClosingFileHandler(options.logfile) 414*6236dae4SAndroid Build Coastguard Worker handler.setFormatter(formatter) 415*6236dae4SAndroid Build Coastguard Worker handler.setLevel(logging.DEBUG) 416*6236dae4SAndroid Build Coastguard Worker root_logger.addHandler(handler) 417*6236dae4SAndroid Build Coastguard Worker else: 418*6236dae4SAndroid Build Coastguard Worker # The logfile wasn't specified. Add a stdout logger. 419*6236dae4SAndroid Build Coastguard Worker add_stdout = True 420*6236dae4SAndroid Build Coastguard Worker 421*6236dae4SAndroid Build Coastguard Worker if options.verbose: 422*6236dae4SAndroid Build Coastguard Worker # Add a stdout logger as well in verbose mode 423*6236dae4SAndroid Build Coastguard Worker root_logger.setLevel(logging.DEBUG) 424*6236dae4SAndroid Build Coastguard Worker add_stdout = True 425*6236dae4SAndroid Build Coastguard Worker else: 426*6236dae4SAndroid Build Coastguard Worker root_logger.setLevel(logging.WARNING) 427*6236dae4SAndroid Build Coastguard Worker 428*6236dae4SAndroid Build Coastguard Worker if add_stdout: 429*6236dae4SAndroid Build Coastguard Worker stdout_handler = logging.StreamHandler(sys.stdout) 430*6236dae4SAndroid Build Coastguard Worker stdout_handler.setFormatter(formatter) 431*6236dae4SAndroid Build Coastguard Worker stdout_handler.setLevel(logging.DEBUG) 432*6236dae4SAndroid Build Coastguard Worker root_logger.addHandler(stdout_handler) 433*6236dae4SAndroid Build Coastguard Worker 434*6236dae4SAndroid Build Coastguard Worker 435*6236dae4SAndroid Build Coastguard Workerif __name__ == '__main__': 436*6236dae4SAndroid Build Coastguard Worker # Get the options from the user. 437*6236dae4SAndroid Build Coastguard Worker options = get_options() 438*6236dae4SAndroid Build Coastguard Worker 439*6236dae4SAndroid Build Coastguard Worker # Setup logging using the user options 440*6236dae4SAndroid Build Coastguard Worker setup_logging(options) 441*6236dae4SAndroid Build Coastguard Worker 442*6236dae4SAndroid Build Coastguard Worker # Run main script. 443*6236dae4SAndroid Build Coastguard Worker try: 444*6236dae4SAndroid Build Coastguard Worker rc = smbserver(options) 445*6236dae4SAndroid Build Coastguard Worker except Exception: 446*6236dae4SAndroid Build Coastguard Worker log.exception('Error in SMB server') 447*6236dae4SAndroid Build Coastguard Worker rc = ScriptRC.EXCEPTION 448*6236dae4SAndroid Build Coastguard Worker 449*6236dae4SAndroid Build Coastguard Worker if options.pidfile and os.path.isfile(options.pidfile): 450*6236dae4SAndroid Build Coastguard Worker os.unlink(options.pidfile) 451*6236dae4SAndroid Build Coastguard Worker 452*6236dae4SAndroid Build Coastguard Worker log.info("[SMB] Returning %d", rc) 453*6236dae4SAndroid Build Coastguard Worker sys.exit(rc) 454