diff options
Diffstat (limited to 'source')
101 files changed, 0 insertions, 48543 deletions
diff --git a/source/.cvsignore b/source/.cvsignore deleted file mode 100644 index 9b7ea034be9..00000000000 --- a/source/.cvsignore +++ /dev/null @@ -1,12 +0,0 @@ -Makefile.RPM -makefile -makefile.sunos5 -nmbd -nmblookup -smbclient -smbd -smbpasswd -smbrun -smbstatus -testparm -testprns diff --git a/source/Makefile.RPM b/source/Makefile.RPM deleted file mode 100644 index ca17cce64ef..00000000000 --- a/source/Makefile.RPM +++ /dev/null @@ -1,663 +0,0 @@ -########################################################################### -# Makefile for Samba SMB client/server for unix -# Copyright Andrew Tridgell 1992-1996 -########################################################################### - -# The base manpages directory to put the man pages in -# Note: $(MANDIR)/man1, $(MANDIR)/man5 and $(MANDIR)/man8 must exist. -MANDIR = /usr/man - -# The directories to put things in. If you use multiple -# architectures or share the samba binaries across NFS then -# you will probably want to change this layout. -BASEDIR = /usr -BINDIR = $(BASEDIR)/bin -SBINDIR = $(BASEDIR)/sbin -LIBDIR = /etc -VARDIR = /var - -# The permissions to give the executables -INSTALLPERMS = 0755 - -# Add any optimisation or debugging flags here -# add -DSYSLOG for syslog support -# RPM_OPT_FLAGS is needed when building an RPM distribution package -# for RedHat Linux. -FLAGS1 = $(RPM_OPT_FLAGS) -#FLAGS1 = -O -LIBS1 = - -# You will need to use a ANSI C compiler. This means under SunOS 4 you can't -# use cc, instead you will have to use gcc. -CC = gcc - -# This may help with some versions of make -SHELL = /bin/sh - -# The following can be useful for compiling on multiple architectures -# just uncommment them putting the right directory in. -# srcdir=./ -# VPATH=$(srcdir) - -# set these to where to find various files -# These can be overridden by command line switches (see smbd(8)) -# or in smb.conf (see smb.conf(5)) -SMBLOGFILE = $(VARDIR)/log/log.smb -NMBLOGFILE = $(VARDIR)/log/log.nmb -CONFIGFILE = $(LIBDIR)/smb.conf -LMHOSTSFILE = $(LIBDIR)/lmhosts - -# the directory where lock files go -LOCKDIR = $(VARDIR)/lock/samba - -# set this to the default group you want your machine to appear in -# for browsing. This can also be set in nmbd (see nmbd(8)) -WORKGROUP = WORKGROUP - -# set this to the name of the default account, which is the one -# to use when no username or password is specified. This can be overridden -# in the runtime configuration file (see smb.conf(5)) -# NOTE: The account "nobody" may not be a good one as -# on many unixes it may not be able to print. Thus you -# might have to create a separate guest account that can print. -GUESTACCOUNT = nobody - -# where you are going to have the smbrun binary. This defaults to the -# install directory. This binary is needed for correct printing -# and magic script execution. This should be an absolute path! -# Also not that this should include the name "smbrun" on the end (the -# name of the executable) -SMBRUN = $(BINDIR)/smbrun - -# This is for PAM authentication. RedHat Linux uses PAM. -# If you use PAM, then uncomment the following lines: -PAM_FLAGS = -DUSE_PAM -PAM_LIBS = -ldl -lpam - -# This is for AFS authentication. If you use AFS then set AFS_BASE -# according to your system layout, and uncomment the other lines as well. -# AFS_BASE = /usr/afsws -# AFS_FLAGS = -DAFS_AUTH -I$(AFS_BASE)/include -# AFS_LIBDIR = $(AFS_BASE)/lib -# NOTE: You may need to add -laudit in the line below -# AFS_LIBS = -L$(AFS_LIBDIR) -L$(AFS_LIBDIR)/afs -lkauth -lprot -lubik \ -# -lauth -lrxkad -lsys -ldes -lrx -llwp -lcom_err \ -# $(AFS_LIBDIR)/afs/util.a - -# This is for DCE/DFS enablement. Uncomment this so that smbd can -# operate as an authenticated user identity to operate on files that -# live in the DCE Distributed Filesystem. -# DCE_BASE = /opt/dcelocal -# DCE_FLAGS = -I$(DCE_BASE)/include -# DCE_LIBDIR = -L$(DCE_BASE)/lib -# DCE_LIBS = - -# This is for SMB encrypted (lanman) passwords. -# you may wish to add -DREPLACE_GETPASS if your getpass() is limited -# to 8 chars -# DES_BASE=/usr/local/libdes -# DES_FLAGS= -I$(DES_BASE) -# DES_LIB= -L$(DES_BASE) -ldes -# PASSWD_FLAGS=-DUSE_LIBDES -DSMB_PASSWD=\"$(BINDIR)/smbpasswd\" -DSMB_PASSWD_FILE=\"$(BASEDIR)/private/smbpasswd\" - -###################################### -# VTP-Support -# -# uncomment the following two lines to enable VTP-Support -#VTP_FLAGS = -DWITH_VTP -#VTP_OBJ = vt_mode.o -###################################### - -###################################### -# WHICH AWK? awk is used for automatic prototype generation. GNU awk works -# where inferior awks don't. Sun is one manufacturer who supplies both -# a broken awk called 'awk' and a fixed one called 'nawk'. mkproto.awk will -# only work with the latter, and even that isn't as good as free GNU awk. -# -# Leave this uncommented; the OS-specific stuff will override it if required -AWK = awk -###################################### - -##################################### -# WHICH OPERATING SYSTEM? -# UNCOMMENT ONE OF THE SECTIONS BELOW -# MAKE SURE ONLY *ONE* IS UNCOMMENTED -# -# The following are additional flags that may apply -# -DNETGROUP if your machine supports yp netgroups -# -DSHADOW_PWD if you are using shadow passwords -# -DGETPWANAM if you wish to use getpwanam() call -# -DPWDAUTH if you have and want to use the pwdauth() call -# -DUFC_CRYPT if you want the fast crypt routine -# -DALLOW_CHANGE_PASSWORD if you want users to be able to set their password -# remotely (only works on some systems) -# -DQUOTAS for quota support in disk_free(). This probably only works -# on some systems. -# -DFAST_SHARE_MODES=1 if you want the fast shared memory instead of the -# slow description files for share mode locking. This -# requires the mmap() and lockf() system calls. -# -# NOTE: GETPWANAM & PWDAUTH are mutually exclusive, if you -# Define one, you should NOT define the other. -##################################### - -##################################### -# for the JAPANESE EXTENSION -# select filename's code set for KANJI/KANA in UNIX, -# apply the following flag -# -DKANJI=\"<code>\" -# <code> is select character code set for JAPAN. -# sjis: if your machine support SJIS -# euc: if your machine support EUC -# jis7: if your machine support JIS7 -# jis8: if your machine support JIS8 -# junet: if your machine support jis7 + junet rule -# hex: if your machine only support 7 bits ascii filename only -# convert to hexdecimal code preseeding ':'. -# see also README.jis -###################################### - - -# This is for SUNOS 4. Use the SUNOS5 entry for Solaris 2. -# Note that you cannot use Suns "cc" compiler -# as it's not an Ansi-C compiler. Get gcc or acc. -# Note that if you have adjunct passwords you may need the GETPWANAM -# or PWDAUTH option. There have been reports that using PWDAUTH may crash -# your pwdauthd server so GETPWANAM is preferable (and probably faster) -# contributed by Andrew.Tridgell@anu.edu.au -# FLAGSM = -DSUNOS4 -# LIBSM = -# AWK = nawk - -# Use this for Linux with shadow passwords -# contributed by Andrew.Tridgell@anu.edu.au -# add -DLINUX_BIGCRYPT is you have shadow passwords but don't have the -# right libraries and includes -# FLAGSM = -DLINUX -DSHADOW_PWD -# LIBSM = -lshadow - -# Use this for Linux without shadow passwords -# contributed by Andrew.Tridgell@anu.edu.au -# AXPROC defines DEC Alpha Processor -# FLAGSM = -DLINUX -DAXPROC -FLAGSM = -DLINUX -LIBSM = - -# Use this for Linux with quotas and without shadow passwords -# contributed by Andrew.Tridgell@anu.edu.au -# AXPROC defines DEC Alpha Processor -# FLAGSM = -DLINUX -DAXPROC -DQUOTAS -# FLAGSM = -DLINUX -DQUOTAS -# LIBSM = - -# Use this for Linux with quota and glibc2 -# contributed by xeno@mix.hive.no -# Tested on the 2.0.30 kernel and ext2fs filesystem. -# FLAGSM = -DLINUX -DQUOTAS -DNO_ASMSIGNALH -DGLIBC2 -# LIBSM = -L/lib/libc5-compat -lcrypt - -# This is for SUNOS5.4 and later (also known as Solaris 2.4 and later) -# contributed by Andrew.Tridgell@anu.edu.au -# FLAGSM = -DSUNOS5 -DSHADOW_PWD -DNETGROUP -# LIBSM = -lsocket -lnsl -# AWK = nawk - -# This is for SUNOS 5.2 and 5.3 (also known as Solaris 2.2 and 2.3) -# contributed by hdsi@newtech.net -# FLAGSM = -DSUNOS5 -DSHADOW_PWD -DNETGROUP -DNO_STRFTIME -# LIBSM = -lsocket -lnsl -# AWK = nawk - -# This is for UXP/DS -# contributed by dsfrost@oai6.yk.fujitsu.co.jp -# FLAGSM = -DSVR4 -DSHADOW_PWD -# LIBSM = -lsocket -lnsl - -# This is for SVR4 -# Contributed by mark@scot1.ucsalf.ac.uk -# FLAGSM = -DSVR4 -DSHADOW_PWD -DALLOW_CHANGE_PASSWORD -# LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb - - -# This is for the Motorola 88xxx/9xx range of machines -# Contributed by RPE@monnet.com -# FLAGSM = -DSVR4 -DSHADOW_PWD -DGETTIMEOFDAY1 -# LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb - - -# This is for UNIXWARE -# FLAGSM = -Xa -DSVR4 -DSHADOW_PWD -# LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb - - -# This is for ULTRIX. Add -DULTRIX_AUTH for Ultrix enhanced security. -# contributed by iversen@dsfys1.fi.uib.no -# FLAGSM = -DULTRIX -# LIBSM = - - -# This is for OSF1 (Alpha) -# contributed by errath@balu.kfunigraz.ac.at -# NOTE: You may need -warning_unresolved if you get unresolved symbols -# FLAGSM = -DOSF1 -# LIBSM = - -# This is for OSF1 with DCE/DFS -# contributed by Jim Doyle <doyle@oec.com> -# FLAGSM = -DOSF1 -DDFS_AUTH -DSIGCLD_IGNORE -DNO_SIGNAL_TEST -# LIBSM = -ldce -lpthreads -lmach -lc_r - -# This is for OSF1 (Alpha) with NIS and Fast Crypt -# contributed by David Gardiner <dgardine@cssip.edu.au> -# FLAGSM = -DOSF1 -DNETGROUP -DUFC_CRYPT -# LIBSM = - - -# This is for OSF1 (Alpha) V2.0 Enhanced Security -# contributed by Udo Linauer <ul@eacpc4.tuwien.ac.at> -# FLAGSM = -DOSF1 -DOSF1_ENH_SEC -# LIBSM = -lsecurity - - -# This is for AIX -# contributed by tomc@osi.curtin.edu.au -# FLAGSM = -DAIX -# LIBSM = - -# This is for AIX 3.2.5 with DCE/DFS -# contributed by Jim Doyle <doyle@oec.com> -# FLAGSM = -DAIX -DDFS_AUTH -DSIGCLD_IGNORE -DNO_SIGNAL_TEST -# LIBSM = -lc_r -ldce -lpthreads -# CC = cc_r - -# This is for BSDI -# contributed by tomh@metrics.com -# versions of BSDI prior to 2.0 may need to add -DUSE_F_FSIZE for -# disk usage stats to be correct -# FLAGSM = -DBSDI -# LIBSM = - - -# This is for NetBSD. Add -DNETBSD_1_0 if you are using 1.0 -# contributed by noses@oink.rhein.de -# FLAGSM = -DNETBSD -DSHADOW_PWD -# LIBSM = -lcrypt - - -# This is for SEQUENT. -# Contributed by fwk@ix.netcom.com (Frank Keeney) and -# rpwillia@Pentagon-EMH6.army.mil (Ray Williams) -# tested on DYNIX/ptx(R) V2.1.0 -# FLAGSM = -DSEQUENT -DSHADOW_PWD -DHAVE_TIMEZONE -# LIBSM = -lrpc -lsocket -lPW -linet -lnsl -lseq -lsec - - -# This is for SEQUENT PTX 4.1.x -# Contributed by bressler@iftccu.ca.boeing.com (Rick Bressler) -# based on Keeny and Williams contribution. -# tested on DYNIX/ptx(R) V4.1.3 -# FLAGSM = -DSEQUENT -DSHADOW_PWD -DHAVE_TIMEZONE -DPTX4 -# LIBSM = -lrpc -lsocket -lPW -lnsl -lseq -lsec - - -# This is for HP-UX. Note that some systems don't like the -Aa switch. -# contributed by Pasi.Kaara@atk.tpo.fi -# You will need -DREPLACE_GETPASS if you use smb encryption -# FLAGSM = -DHPUX -Aa -D_HPUX_SOURCE -D_POSIX_SOURCE -# LIBSM = - -# This is for HP-UX with DCE/DFS -# contributed by Jim Doyle <doyle@oec.com> -# FLAGSM = -DHPUX -Aa -D_HPUX_SOURCE -D_POSIX_SOURCE -DDFS_AUTH -D_REENTRANT -I/usr/include/reentrant -# LIBSM = -ldce -lM -lc_r - -# HP-UX 10.x Trusted System -# Contributed by David-Michael Lincke (dlincke@sgcl1.unisg.ch) -# FLAGSM = +O3 -Ae -DHPUX -DHPUX_10_TRUSTED -# LIBSM = -lsec - - -# This is for SGI. -# contributed by lpc@solomon.technet.sg (Michael Chua) -# FOR SGI IRIX 4.x.x, use the following line -# FLAGSM = -DSGI -DHAVE_TIMEZONE -# LIBSM = -lsun - -# FOR SGI IRIX 5.x.x, use this line instead -# FLAGSM = -DSGI5 -DSHADOW_PWD -DHAVE_TIMEZONE -# LIBSM = - - -# This is for FreeBSD -# contributed by kuku@acds.physik.rwth-aachen.de -# NOTE: You may need to add -DBSD44 if you have password problems -# FLAGSM = -DFreeBSD -# LIBSM = -lcrypt - - -# This is for NEXTSTEP Release 2.X -# No Posix. -# contributed by brad@cac.washington.edu (Brad Greer) -# FLAGSM = -DNEXT2 -# LIBSM = - -# This is for NEXTSTEP Release 3.0 and greater (including OPENSTEP for Mach). -# contributed by brad@cac.washington.edu (Brad Greer) -# additional configuration by pmarcos@next.com (Paul Marcos) -# For compiling n-way fat executables, you should append the appropriat -arch -# flags to the FLAGSM variable. Valid flags are: -# -arch m68k -# -arch i386 -# -arch hppa -# -arch sparc -# To compile 4-way fat, you would append -# -arch m68k -arch i386 -arch hppa -arch sparc -# FLAGSM = -DNEXT3_0 -# LIBSM = - - -# NOTE: ISC is also known as "INTERACTIVE" -# This is for Sunsoft ISC SVR3V4 running in POSIX mode -# contributed by pim@cti-software.nl (Pim Zandbergen) -# FLAGSM = -posix -D_SYSV3 -DISC -DSHADOW_PWD -# LIBSM = -lsec -lcrypt -linet - -# This is for Sunsoft ISC SVR3V4 running in iBCS2 mode -# contributed by pim@cti-software.nl (Pim Zandbergen) -# FLAGSM = -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_SYSV3\ -# -DISC -DSHADOW_PWD -DREPLACE_GETWD -DREPLACE_RENAME -# LIBSM = -lsec -lcrypt -linet -lcposix - - -# This is for A/UX 3.0 -# Contributed by root@dolphin.csudh.edu (Jon S. Stevens) -# FLAGSM = -DAUX -# LIBSM = - -# This is for Altos Series 386/1000 -# Contributed by cal@zls.com -# FLAGSM = -DALTOS -DHAS_RDCHK -# LIBSM = -lsocket -lxenix - - -#Note: The SCO entries require the libcrypt library. You can get it via -#anonymous ftp from ftp.sco.com:/SLS/lng225b.* or ftp.uu.net:/vendors/sco -# -# Use this for SCO with shadow passwords. Tested on "Open enterprise 3.0" -# SCO changes from Heinz Mauelshagen (mauelsha@ez.da.telekom.de) -# FLAGSM = -DSCO -DSHADOW_PWD -DNETGROUP -# LIBSM = -lyp -lrpc -lyp -lsec -lsocket -lcrypt_i -lintl - -# Use this for SCO with shadow passwords, without YP. -# Tested on "Open Enterprise Server 3.0" (John Owens john@micros.com) -# Also, use "CC = cc" above. -# FLAGSM = -DSCO -DSHADOW_PWD -# LIBSM = -lsec -lsocket -lcrypt_i - -# Use this for SCO with TCB passwords (default). -# Tested on "Open enterprise 3.0". Contributed by lance@fox.com. -# CC = cc -# FLAGSM = -DSCO -DSecureWare -# LIBSM = -lprot_s -lcrypt -lsocket -lm -lc_s - -# Use this for SCO Unix 3.2v2 (ODT 1.1) with TCB passwords (default). -# Contributed by Stephen.Rothwell@pd.necisa.oz.au -# N.B. this needs gcc -# FLAGSM = -DSCO -DSecureWare -DSCO3_2_2 -# LIBSM = -lprot -lcrypt_i -lsocket -lm -lintl - -# This is for the european distribution of SCO. -# Contributed by Urmet.Janes@gwhite.goodwin.ee -# FLAGSM = -DSCO -DSHADOW_PWD -# LIBSM = -lsec -lsocket /usr/lib/libcrypt_i.a -lintl - -# Use this for SCO OpenServer 5 with TCB passwords (default). -# contributed by Scott Michel <scottm@intime.intime.com> -# you may also like to add the -dy switch (recommended by Marnus van -# Niekerk, mvn@pixie.co.za) -# CC = cc -Xc -# FLAGSM = -DSCO -DSecureWare -DEVEREST -DUSE_MMAP -# LIBSM = -lprot -lcurses -lcrypt -lsocket -lPW -lm -lx -lc_s -lc - - -# This is for intergraph. -# contributed by cjkiick@flinx.b11.ingr.com -# modified by ttj@sknsws61.sjo.statkart.no -# FLAGSM = -DCLIX -D_INGR_EXTENSIONS=1 -# LIBSM = -lbsd -lc_s - -# This is for DGUX. -# Contributed by ross@augie.insci.com (Ross Andrus) -# FLAGSM = -DDGUX -# LIBSM = - -# This is for Apollo Domain/OS sr10.3 (systype = BSD4.3) -# Added 1994-07-08 Stephen C. Steel <steve@qv3donald.LeidenUniv.nl> -# additional patches by jmi@csd.cri.dk (John Mills) -# you may need the "-A ansi" switch to cc -# FLAGSM = -DAPOLLO -D_INCLUDE_BSD_SOURCE -D_INCLUDE_XOPEN_SOURCE -# LIBSM = - - -# RiscIX. -# contributed by Jim Barry <jim@ilp.com> and -# Charles Gay-Jones <charlie@ilp.com> -# FLAGSM = -DRiscIX -DNOSTRDUP -# LIBSM = - - -# This is for System V with some berkely extensions (Motorola 88k R32V3.2). -# contributed by tonyb@plaza.ds.adp.com (Tony D. Birnseth) -# FLAGSM = -DM88K_R3 -# LIBSM = -lgen -lbsd -lnsl - - -# This is for DNIX. -# contributed by Peter Olsson <pol@leissner.se> -# NOTE: You may need an updated libc.a from your vendor as older -# versions have broken mktime calls and no initgroups() call -# NOTE2: You may need -lpasswd if you use shadow passwords -# NOTE3: Please read the file DNIX.txt in the docs directory. It -# contains important information about uid handling under DNIX, you may -# need to patch your C library. -# FLAGSM = -DDNIX -I/usr/include/bsd -# LIBSM = -ln - - -# This is for Cray, Unicos 8.0 -# contributed by velo@sesun3.epfl.ch (Martin Ouwehand) -# FLAGSM = -DCRAY -U__STDC__ -DQUOTAS -# LIBSM = - -# This is for Convex -# contributed by Victor Balashov <balashov@cv.jinr.dubna.su> -# and Ulrich Hahn <ulrich.hahn@zdv.uni-tuebingen.de> -# FLAGSM= -DCONVEX -DSHADOW_PWD -# LIBSM= - -# This is for SMP_DC.OSx v1.1-94c079 on Pyramid S series -# contributed by jeffrey@itm.org -# FLAGSM = -DSOLARIS -DSHADOW_PWD -DBSD_COMP -# LIBSM = -lsocket -lnsl - -# This is for QNX 4.22 -# Contributed by eldo@invisa.satlink.net (Eldo Loguzzo) -# FLAGSM = -DQNX -DGUEST_SESSSETUP=1 -# LIBSM = - - -# This is for SONY NEWS, NEWS-OS 4.2.x -# contributed by sky@sm.sony.co.jp (Katushi Sato) -# FLAGSM = -DNEWS42 -DKANJI=\"sjis\" -# LIBSM = - - -# This is for SONY NEWS, NEWS-OS 6.1.x -# contributed by kobo@sm.sony.co.jp (Yoichi Kobori) -# FLAGSM = -Xa -DSVR4 -DNEWS61 -DSHADOW_PWD -DNETGROUP -DGETTIMEOFDAY1 -DKANJI=\"euc\"\ -D_SONYILS_H -# LIBSM = -lsocket -lnsl - - -# This is for OS/2 using EMX 0.9b -# Contributed by jasonr@pec.co.nz (Jason Rumney) -# FLAGSM = -DOS2 -# LIBSM = -Zexe -lsocket - - -# This is for LYNX 2.3.0 (gcc v2.6) -# Contributed by woelfel@hpe.fzk.de (Manfred Woelfel) -# FLAGSM = -DLYNX -DUFC_CRYPT -mposix -# LIBSM = -lbsd - - -# This is for MachTen (a unix like system for Macintoshes) -# contributed by Trevor Strohman (trev@figment.tenon.com) -# FLAGSM = -DMACHTEN -# LIBSM = - - -# RISCOs 5.0B -# contributed by John Agnew <johna@bfs.Unibol.COM> -# FLAGSM = -systype svr4 -std -DSVR4 -# LIBSM = -lsocket -lnsl -lc -L/usr/ucblib -lucb - - -# This is for B.O.S. (Bull Operating System) -# Contributed by koine@fileita.it -# FLAGSM = -DBOS -DNO_RESOURCEH -DUSE_WAITPID -# LIBSM = -linet - - -# This for Amiga using GCC and ixemul.library 43.0 or later. -# contributed by Rask Ingemann Lambertsen <rask@k4315.kampsax.dtu.dk> -# The binaries will support both AmiTCP and AS225R2 compatible -# protocol stacks because of the use of ixnet.library. -# Other protocol stacks will be supported automatically if -# support for them is added to ixnet.library. -# The binaries will have automatic stack extension :-) -# smbd must be run from inetd :-( -# FLAGSM = -DAMIGA -Dfork=vfork -mstackextend -# LIBSM = - - - -###################################################################### -# DON'T EDIT BELOW THIS LINE -###################################################################### - -CFLAGS1 = $(FLAGS1) -DSMBLOGFILE=\"$(SMBLOGFILE)\" -DNMBLOGFILE=\"$(NMBLOGFILE)\" -CFLAGS2 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DLMHOSTSFILE=\"$(LMHOSTSFILE)\" -CFLAGS3 = -DLOCKDIR=\"$(LOCKDIR)\" -DSMBRUN=\"$(SMBRUN)\" -CFLAGS4 = -DWORKGROUP=\"$(WORKGROUP)\" -DGUEST_ACCOUNT=\"$(GUESTACCOUNT)\" -CFLAGS5 = $(CFLAGS1) $(CFLAGS2) $(CFLAGS3) $(CFLAGS4) $(FLAGSM) $(AFS_FLAGS) -CFLAGS = $(CFLAGS5) $(PAM_FLAGS) $(DCE_FLAGS) $(DES_FLAGS) $(PASSWD_FLAGS) $(VTP_FLAGS) -LIBS = $(LIBS1) $(LIBSM) $(PAM_LIBS) $(DCE_LIBS) $(DES_LIB) - -SPROGS = smbd nmbd -PROGS1 = smbclient testparm testprns smbrun smbstatus smbpasswd -PROGS = $(PROGS1) nmblookup -SCRIPTS = smbtar addtosmbpass - -all : CHECK $(SPROGS) $(PROGS) - -CHECK : - @$(SHELL) $(srcdir)checkos.sh $(FLAGSM) - @echo "Using CFLAGS = $(CFLAGS)" - @echo "Using LIBS = $(LIBS)" - -INCLUDES1 = version.h local.h includes.h smb.h -INCLUDES2 = trans2.h -INCLUDES = $(INCLUDES1) $(INCLUDES2) - -UTILOBJ1 = util.o system.o charset.o kanji.o fault.o smbencrypt.o charcnv.o -UTILOBJ2 = $(UTILOBJ1) md4.o loadparm.o params.o pcap.o username.o time.o -UTILOBJ = $(UTILOBJ2) interface.o replace.o -PARAMOBJ = $(UTILOBJ) ufc.o smbpass.o access.o shmem.o -SMBDOBJ1 = $(PARAMOBJ) trans2.o pipes.o message.o dir.o printing.o locking.o -SMBDOBJ2 = ipc.o reply.o mangle.o chgpasswd.o password.o quotas.o uid.o -SMBDOBJ = predict.o $(SMBDOBJ1) $(SMBDOBJ2) $(VTP_OBJ) -NMBDOBJ1 = nmblib.o namepacket.o nameresp.o nmbsync.o nameannounce.o nameelect.o -NMBDOBJ2 = namedbresp.o namedbwork.o namedbserver.o namedbsubnet.o namedbname.o -NMBDOBJ3 = nameservresp.o nameservreply.o namelogon.o namebrowse.o namework.o nameserv.o clientutil.o -NMBDOBJ = $(UTILOBJ) $(NMBDOBJ1) $(NMBDOBJ2) $(NMBDOBJ3) -.SUFFIXES: -.SUFFIXES: .c .o .h - -.c.o: $(INCLUDES) - @echo Compiling $*.c - @$(CC) $(CFLAGS) -c $(srcdir)$*.c - -smbd: server.o $(SMBDOBJ) - @echo Linking smbd - @$(CC) $(CFLAGS) -o smbd server.o $(SMBDOBJ) $(LIBS) $(AFS_LIBS) - -smbrun: smbrun.o - @echo Linking smbrun - @$(CC) $(CFLAGS) -o smbrun smbrun.o $(LIBS) - -nmblookup: nmblookup.o namequery.o nmblib.o $(UTILOBJ) - @echo Linking nmblookup - @$(CC) $(CFLAGS) -o nmblookup nmblookup.o namequery.o nmblib.o $(UTILOBJ) $(LIBS) - -nmbd: nmbd.o $(NMBDOBJ) - @echo Linking nmbd - @$(CC) $(CFLAGS) -o nmbd nmbd.o $(NMBDOBJ) $(LIBS) - -smbclient: client.o clitar.o getsmbpass.o namequery.o nmblib.o $(UTILOBJ) - @echo Linking smbclient - @$(CC) $(CFLAGS) -o smbclient client.o clitar.o getsmbpass.o namequery.o nmblib.o $(UTILOBJ) $(LIBS) - -smbstatus: status.o $(PARAMOBJ) - @echo Linking smbstatus - @$(CC) $(CFLAGS) -o smbstatus status.o $(PARAMOBJ) $(LIBS) - -testparm: testparm.o $(PARAMOBJ) - @echo Linking testparm - @$(CC) $(CFLAGS) -o testparm testparm.o $(PARAMOBJ) $(LIBS) - -testprns: testprns.o $(PARAMOBJ) - @echo Linking testprns - @$(CC) $(CFLAGS) -o testprns testprns.o $(PARAMOBJ) $(LIBS) - -smbpasswd: smbpasswd.o getsmbpass.o $(PARAMOBJ) - @echo Linking smbpasswd - @$(CC) $(CFLAGS) -o smbpasswd smbpasswd.o getsmbpass.o $(PARAMOBJ) $(LIBS) - -install: installbin installman installscripts - -installbin: all - @$(SHELL) $(srcdir)installbin.sh $(INSTALLPERMS) $(BASEDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(SPROGS) - @$(SHELL) $(srcdir)installbin.sh $(INSTALLPERMS) $(BASEDIR) $(BINDIR) $(LIBDIR) $(VARDIR) $(PROGS) - -installscripts: - @$(SHELL) $(srcdir)installscripts.sh $(INSTALLPERMS) $(BINDIR) $(SCRIPTS) - -# revert to the previously installed version -revert: - @$(SHELL) $(srcdir)revert.sh $(SBINDIR) $(SPROGS) $(SCRIPTS) - @$(SHELL) $(srcdir)revert.sh $(BINDIR) $(PROGS) $(SCRIPTS) - -installman: - @$(SHELL) $(srcdir)installman.sh $(MANDIR) $(srcdir) - -uninstall: uninstallman uninstallbin uninstallscripts - -uninstallman: - @$(SHELL) $(srcdir)uninstallman.sh $(MANDIR) $(srcdir) - -uninstallbin: - @$(SHELL) $(srcdir)uninstallbin.sh $(INSTALLPERMS) $(BASEDIR) $(SBINDIR) $(LIBDIR) $(VARDIR) $(SPROGS) - @$(SHELL) $(srcdir)uninstallbin.sh $(INSTALLPERMS) $(BASEDIR) $(BINDIR) $(LIBDIR) $(VARDIR) $(PROGS) - -uninstallscripts: - @$(SHELL) $(srcdir)uninstallscripts.sh $(INSTALLPERMS) $(BINDIR) $(SCRIPTS) - -clean: - rm -f core *.o *~ $(PROGS) $(SPROGS) - -proto: - @$(SHELL) $(srcdir)checkos.sh $(FLAGSM) - $(AWK) -f mkproto.awk *.c > proto.h - -realclean: clean - diff --git a/source/change-log b/source/change-log deleted file mode 100644 index 42a27fe6f68..00000000000 --- a/source/change-log +++ /dev/null @@ -1,1878 +0,0 @@ -SUPERCEDED Change Log for Samba -^^^^^^^^^^ - -Unless otherwise attributed, all changes were made by -Andrew.Tridgell@anu.edu.au. All bugs to samba-bugs@samba.anu.edu.au. - -NOTE: THIS LOG IS IN CHRONOLOGICAL ORDER - -NOTE: From now on the cvs.log file will be used to give a complete log of -changes to samba. This change-log is now obsolete. - -1.5.00 announced to mailing list - -1.5.01 1/12/93 - - configuration through makefile only - - fixed silly bug that made the client not accept dir's from - the server - - tested and updated include files for ultrix, aix and solaris - - several things fixed thanks to pierson@ketje.enet.dec.com - who provided invaluable help and advice. - -1.5.02 1/12/93 - - added username option to services file so connection - as non guest from lanmanager is possible - - made server abort when it can't read/write on a socket - - added logging to client - -1.5.03 2/12/93 - - printing now works - - fixed a minor bug to do with hidden and system attributes - -1.5.04 2/12/93 - - added reduce_name() call to fill in security hole. - - cleanup up debug stuff a little - -1.5.05 2/12/93 - - fixed bug in reduce_name that affects services with base paths - that have a soft link in them. - -1.5.06 3/12/93 - - used the reserved server field in the search status to hold the - directory pointer. This allows lots of directories to be open - at once by clients without stuffing things up. - - preserved all the client reserved bytes in the search status - in case they actually use them. Hopefully this will fix the annoying - empty directory dir bug. (it does) - -1.5.07 3/12/93 - - fixed silly bug that caused volume ids to appear twice - - fixed a wrote-too-few bug in smb_send() - -1.5.08 3/12/93 - - did the SMBsearch properly. It can now handle recursive searches. - In order to keep the required dir info I encode the dirptr and - the current dir offset (from telldir) into 5 bytes by using a table - on the last 7 bits of the first byte. The first bit is always on - as this byte must by != 0 - This is all put in the "server reserved" search field. - -1.5.09 5/12/93 - - added a prototype nameserver. It's broken but can at least interpret - incoming packets. - - minor fixes to the server and client - - -1.5.10 5/12/93 - - fixed silly unsigned/signed char bug that made dosshell noot see all files - - added nmbd to Makefile - -1.5.11 6/12/93 - - made the volume label appear as the service name, rather than "Remote" - - made the nmbd actually work (a little) for lanman for dos - -1.5.12 7/12/93 - - fixed broadcasting in the nameserver - - the smbd now correctly sets the pid and uid - - nmbd now seems to work enough to satisfy the MS client. - - -1.5.13 7/12/93 - - fixed a silly bug that truncated filenames - - added -B option to nameserver to specify bcast address - - added -R option to nameserver to prevent name registering - - fixed minor read() bug. Does this fix the "cmp" bug? - -1.5.14 8/12/93 - - fixed a bug in send_login() in the client. Thanks to - tim.hudson@gslmail.mincom.oz.au for pointing this out. - - changed name_mangle() to pad to minimum of 32 bytes with spaces - - changed the returned buffer size in reply_connect() to not - count the 4 byte length field. This fixes the "can execute" bug - and the "comp" bug - - once again re-wrote the directory pointer handling code. - now "tree" works correctly - -1.5.15 9/12/93 - - fixed name mangle bug introduced in 1.5.14 which stopped - nameserver from working - -1.5.16 9/12/93 - - arrgh. another silly bug in name_mangle() causes the client to die. - - -1.5.17 13/12/93 - - some cosmetic cleanups to the code - - changed make_connection not to lower case the password (thanks - to bryan@alex.com) - - fixed accept() bug not initialising in_addrlen (thanks to - bogstad@cs.jhu.edu) - - fixed cd bug in client.c (thanks to joergs@toppoint.de) - - lots of fixes to the nameserver to read_socket and - associated routines. It should now correctly reply to the originating - address and use the correct broadcast. - (thanks to troyer@saifr00.ateng.az.honeywell.com) - - SVR4 patches from mark@scot1.ucsalf.ac.uk - - changed the default BUFFER_SIZE to 0xFFFF - -1.5.18 15/12/93 - - minor fix to reply_printqueue() to zero data buffer array. - - added print command to client. - - fixed minor bug in cmd_put() in client where a handle could - be closed without being previously opened. - - minor cleanups to the client - - minor solaris fixes from lonnie@itg.ti.com - - SYSV, shadow password and dfree() fixes from mark@scot1.ucsalf.ac.uk - - fixed reply_delete() to not delete read-only files - - fixed infinite loop in reply_delete on "del ." - Thanks to mark@scot1.ucsalf.ac.uk for pointing this out. - - posix mode definitions and changes from mark@scot1.ucsalf.ac.uk - - -1.5.19 18/12/93 - - another very minor fix to dfree(). - - minor change to SVR4 makefile entry from rossw@march.co.uk - - changed reply_open not to open directories, this fixes the - "copy .." bug pointed out by mark@scot1.ucsalf.ac.uk - - changed dos_mode() so it doesn't return hidden and system info - on directories. - - changed get_dir_entry() not to descend into proc/self under linux - control this with the DONT_DESCEND define in includes.h - - changed smb_setlen() to add in the SMB id. (thanks - to troyer@saifr00.ateng.az.honeywell.com) - - fixed minor bug in reply_dir() so it won't return a ACCESS_DENIED - when searching a directory that is unreadable - - removed second stat() from get_dir_entry() (speed up) - - made null searches close the dirptr (fixes big filesystem problem) - - fixed clean_name for cd .. (from magnus@axiom.se) - - -1.5.20 28/12/93 - - added debug statement in case of SMBcreate with volid set (leefi@microsoft.com) - - fixed a bug in dptr_close() so it sets the next_key to a better - value, this fixes a annoying dir bug - - LOTS of changes from jeremy@netcom.com (Jeremy Allison). This - makes it possible to at least connect to a NT server with the client - and also fixes up much of the socket/process code. This also includes - stuff for compiling on a sun386 - - got the client working with the Syntax server (a commercial - smb-based server). This required a few minor changes so the xmit - sizes were negotiated properly. - - added support for OSF1, tested on a DEC3000/400 alpha. - - fixed the ifconf support under ultrix - -1.5.21 31/12/93 - - minor cosmetic change to reduce_name() - - changes for HPUX from ppk@atk.tpo.fi (Pasi Kaara) - - minor fix to nameserver - - revamped configuration file format. It now takes a Windows-style - (.INI style) configuration file. See the file services for - full details of the format. New files: loadparm.c, loadparm.h, - params.c, params.h, testparm.c. Several changes to smb.h, local.h, - server.c, Makefile. The services structure is no longer visible - to the rest of the system. (Karl Auer) - - added ability to specify a print command on a per service basis - and globally via the configuration file. Also allows guest account - to be specified in the configuration file. Made appropriate changes - to server.c so that these data items are obtained from the config - module rather than from hardcoded strings (though the hardcoded - strings are still the source of the defaults). (Karl Auer) - - renamed old-style configuration file to services.old (Karl Auer) - - changed README to reflect new configuration details. (Karl Auer) - - removed an item from the bugs wishlist (now supplied!) (Karl Auer) - - protected smb.h against multiple compilation. (Karl Auer) - - protected local.h against multiple compilation. (Karl Auer) - - made config stuff do dynamic allocation - - added "homes" capability - - added create_mask to each service in config - -1.5.22 3/1/94 - - added "root dir" option for extra security - - added -n option to client (useful for OS/2) - - changed operation of -n to nameserver to be more useful - - patches from Jeremy Allison (jeremy@netcom.com) - fixing bug in set_message(), fixing up wait3() for SYSV, - making cd check the path in the client, allowing fetching to stdin - in client, and enhancing prompt in client to include directory. - - made the -D become_daemon() actually detach from the tty. This - may need tuning for different flavors of unix. - - added "dont descend" option to each service to prevent infinite - loops on recursive filesystems. - - updated README to add "running as a daemon" and a simple - smb.conf file. - - HP/UX fixes from ppk@atk.tpo.fi - - made lock calls only if opened with write enabled, as pointed out - by gadams@ddrive.demon.co.uk - -1.5.23 4/1/94 - - minor fix to logging of data in receive_smb(). It used to - miss the last 4 bytes of packets. - - added the pid,uid and mid fields to the negotiation phase of - the client. - - made client able to print from stdin - - added password on command line for client - - created a sample printcap input filter "smbprint" - - several fixes to client to work with OS/2 - - added mput, mget, prompt and lcd to client - -1.5.24 5/1/94 - - a resend of 1.5.23 as I managed to not include the new - prompt, mput and mget code. - -1.5.25 7/1/94 - - change -B on nameserver so it can override the broadcast address - - minor changes to printing in client so OS/2 server can handle it. - - fixed reply_access() where OK was not being initialised - - added "max xmit" to global parameters. - - changed create to open with O_RDWR instead of O_WRONLY - - added printmode command to client - - made help return extra help on a specified command in client - - fixed return code in chkpath - - added "recurse" and "lowercase" options to client - - fixed some error codes from server - - added -I option to client - - fix for become_daemon() for HPUX from ppk@atk.tpo.fi - - added "hosts allow" and "hosts deny" to server - - added keepalives to server - - added "access" feature to testparam - - NetBSD patches from sreiz@aie.nl - -1.5.26 8/1/94 - - changed semantics of hosts access code to do more sensible defaults - when either of "hosts allow" or "hosts deny" is blank - - added the SO_KEEPALIVE option to configurations of sockets in the - server - - made some of the SVAL fns into macros to keep fussy compilers from - complaining - - fixed several null pointer bugs in check_access(). These bugs - made 1.5.25 unuseable for many people. - - fixed null pointer reference of lp_dontdescend() - - reload services file after each new connection. - -1.5.27 11/1/94 - - fixed opening mode for reply_open() in server - - patches from Jeremy Allison (jeremy@netcom.com) to support the - "core+" protocol. The patches also inclued some other features, such - as a new read_with_timeout() call (used by SMBreadbraw), and auto - detection of the need to create a socket. - - changed the default KEEPALIVE value to 0, as it caused - problems with Lanmanager. - - added tar capability to client when getting files - - altered unix_mode() to return x bits for directories - - fixed bug in trim_string() - -1.5.28 12/1/94 - - cleaned up the debug levels a little so debug level 1 is a practical - level for general use - - fixed a bug in add_a_service() where a freed pointer was referenced. Thanks - to bryan@alex.com for finding the bug. - - fixed bug in time structure handling in server and client. Thanks to - bryan@alex.com for pointing out the bug. - - -1.5.29 15/1/94 - - fixed a silly bug in reply_open(). Thanks to - jeremy@netcom.com for pointing this out. - - fixed debug levels in client to be more sensible - - added raw read to client - - added -B option to client - - fixed several bugs in the client, mostly to do with the tar option - - added -E option to client - -1.5.30 16/1/94 - - added lots of prototypes so compilers don't complain - - fixed minor bug in reply_rename() (thanks to ppk@atk.tpo.fi) - - added more support for LANMAN1.0 protocol. - - added SESSION SETUP AND X call - - added READ AND X call - - added TREE CONNECT AND X call - - added support for setbuffer for HPUX (thanks to ppk@atk.tpo.fi) - -1.5.31 29/1/94 - - added support for user level security in smbclient eg: - smbclient "\\SERVER\SHARE" -U USERNAME%PASSWORD - - added error message decode as per SMB File Sharing - protocol extensions. (thanks to merik@blackadder.dsh.oz.au) - - added selection masks to smbclient that recurse down directory - tree. eg: mget *.* with recurse and mask *.c on will retrieve all - *.c files in the tree. - - patches for FreeBSD from kuku@acds.physik.rwth-aachen.de - - changed reduce_name() to trim ./ from front of strings and / from - back - - fixed a nasty bug in trim_string(). - - numerous small changes to lots of stuff that I didn't - document while I was doing them. Sorry :-( - - slightly updated sockspy - - - The following was done by Karl Auer (Karl.Auer@anu.edu.au) - - added processing in configuration file of a [printers] section. Allows - connection to any printer specified in /etc/printcap (or the file - specified in the global parameter 'printcap name'). - - added full processing of 'available' flag to configuration file. A - service can now be 'turned off' by specifying 'available = no'. Of - dubious utility. - - added 'printcap =' parameter to [global] section in the configuration - file. This allows the normal /etc/printcap to be bypassed when - checking printer names for dynamic printer connections via [printers]. - - added 'printer name =' parameters to both the [global] section and - services sections of the configuration file. This allows the printer - name only to be set, without having to specify an entire print - command. - - added some synonyms: 'writable' and 'write ok' have the opposite sense - to 'read only'. 'public' may be used instead of 'guest ok'. 'printer' - may be used instead of 'printer name'. 'printable' is the same as - 'print ok'. 'root' may be used instead of 'root dir' or 'root - directory'. - - added lots more detail to the sample configuration file to take - account of the above. - - many minor fixes to internal documentation in the configuration - sources. - - also - Man pages! - - -1.5.32 3/2/94 - - addition of smbd, smbclient and testparm man pages - from Karl Auer - - zombie process fix from lendecke@namu01.gwdg.de - - added capability to nmbd to serve names available - via gethostbyname(). - -1.5.33 3/2/94 - - fixed up getting of netmask so it works on more unix variants - - added -N option to nmbd - - changed GMT diff calculation. need to check it's right for - lots of OSes - - fixed a bug in read_and_X() and chain_reply() chaining now - seems to work correctly - -1.5.34 4/2/94 - - fixed bug in client that meant it couldn't get/put files from WfWg - - fixed a bug in the server that caused lpr to return -1 under sunos - - fixed a few errors in the hosts allow section of the - smb.conf.5 manual page and added examples - -1.5.35 6/2/1994 - - minor bugfix in reduce_name(). - - changed width of "size" in client during a dir - - patches for NEXT (among other things) from lendecke@namu01.gwdg.de - - added -a switch to server, and made default action to append - to log file - - added deadtime options to [global] section for timing out - dead connections to the smbd. - - HPUX changes from Pasi.Kaara@atk.tpo.fi - - made use of unsigned char more consistent - - changed the way of getting the default username and host in the - client - - made LANMAN1 default to on in the client, off in server. - Use -DLANMAN1=1 to make it on in both. - - lots of casts and cleanups for various operating systems - - changes to the Makefile from Karl to auto-instal the man pages - - added a short history of the project to the distribution - -1.5.36 15/2/94 - - fixed minor bug in Debug() (thanks to Pasi.Kaara@atk.tpo.fi) - - fixed bug in server.c so -a wasn't accepted. - - minor fixes to the client - - added hosts file to name server (-H option) - - added -G option for groups to nameserver - - cleanups and additions from Jeremy Allison, taking us - closer to LANMAN1.0. In particular the locking code was cleaned up - considerably. - -1.5.37 16/2/94 - - fixed bug introduced in 1.5.36 which disabled SMBcreate - -1.5.38 18/2/94 - - fixed get_broadcast() for ultrix (fix from iversen@dsfys1.fi.uib.no) - - added automatic group registration - - fixed bug in registration code - - made nmbd work better with WfWg, and probably others - - updated the man pages to include the new nmbd options. - - minor updates to the README - - fixed double log_out() in send_packet(). - - fixed bug in smbclient so that "dir" didn't work correctly - with pathworks - - possibly fixed bug in server that led to "abort retry ignore" from - pathworks client when doing a "dir". - - changed behaviour of smbclient login slightly, to try a - blank password in SMBtcon if the right password fails, and a - session setup has succeeded. Some clients seem to use a blank - one if a session setup has succeeded. - - ISC patches from imb@asstdc.scgt.oz.au - - the client now tries to do name registration using a unicast. - Let me know if this helps anyone. - - tried to add a "contributed" line to each OS in the Makefile. - -1.5.39 18/2/94 - - fixed silly C code that only worked with some compilers - - fixed another silly bug in nameserv.c that caused it to seg fault - -1.5.40 21/2/94 - - removed the from (IP) message so people don't worry about 0.0.0.0, - it's redundant anyway. - - changed the client so the crypt key isn't printed - - changed the structure of switch_message() to use a list of functions. - This improves the debug info. - - made SMBopen ignore supplied attribute as per X/Open spec - - made SMBopen fail if file doesn't exist in all cases. Let me know - if this breaks something. It is implied in the X/Open spec. This - fixes the pkzip bug. - - added dptr_demote() to replace dptr_close() to try and fix - pathworks dir bug. This has the potential disadvantage of - leaving lots of open file descriptors. - - changed mask_match to disallow two .s in a name - -1.5.41 2/3/94 - - added "dfree command" global option to smbd to support an - external "disk free" executable (typically a script). This gets - around the problem of getting disk free info reliably on lots - of systems. - - added ffirst and fclose to client - - simple SYSVR4 patch from mark@scot1.ucsalf.ac.uk - - added better uid/gid reporting for debugging purposes - - several changes to the logon procedure for the client, so hopefully - it will connect correctly to a wider range of servers. - - server should no longer crash if it can't open the debug - file (thanks to MGK@newton.npl.co.uk) - - added the THANKS file. - -1.5.42 6/3/94 - - lots of changes from Jeremy Allison, implementing more of - the LANMAN1.0 protocol, and fixing a few bugs. - - fixed delete bug, so hopefully wildcards are correct now - - pcap changes from Martin Kiff so non-aliased printers in - /etc/printcap are recognised - - wrote announce file ready for 1.6 - - re-wrote browse code in client (still doesn't work) - - updates to man-pages from Karl Auer - - made raw packet dumps mode 0600 and only if -dA is given - - changed socket code to use utility functions in util.c - -1.6.00 17/3/94 - - made server always return to original directory (rather than /) - - fixed bug in params.c that caused a seg fault if no parms in a - section - - minor clean ups for clean compile under solaris - - solaris fix for running from inetd from Karl Auer - - fixes for dfree() under solaris - - minor changes that might help BSDI - - changes to the Makefile, manual-pages and sample config file from - Karl Auer - - fixed dfree for Ultrix - -1.6.01 19/3/94 - - fixed setatr bug that allowed directories to be unusable - -1.6.02 27/3/94 - - added timestamps to connection message in log - - added idle timeout of 10 minutes to name server - - made HAVE_SYSCONF==0 the default in includes.h - - made the client not register by default - - ISC patches from imb@asstdc.scgt.oz.au - - GetWd() cache code from Martin Kiff - - rewrote the locking code in terms of fcntl() calls. - - fixed "can't delete directory" bug - - added code to close old dirptrs for duplicate searches - - removed exchange_uids() and the access() call and replaced them. - -1.6.03 28/3/94 - - tried to clean up the time handling a little (local vs gmt time) - - added debug level global to server config - - added protocol level global to server config - - added SMBecho command to server - - included Karl Auers SMBGuide in the distribution. - -1.6.04 31/3/94 - - fixed time zeroing bug in smb_close and smb_setatr - - re-wrote the username/password handling to be more flexible - - added "guest only" service setting to smb.conf - - updated man pages for new username/password handling - - fixed parse bug in reply_tconX - - improved error return code from tcon - - several changes to fix printing from WfWg - -1.6.05 2/4/94 - - changed the name of the whole package to Samba - - removed SMBexit call from client to stop exiting error message - - added interpret_addr() call to replace inet_addr() so - a hostname can be used whenever a IP is required - -1.6.06 8/4/94 - - added random tid choice to reduce problem of clients not - detecting a server disconnection. - - made client not report spurious time from CORE or COREPLUS server. - - minor HPUX fix from gunjkoa@dep.sa.gov.au - - turned off GETWD_CACHE until we track down a minor bug in it - -1.6.07: 10/4/94 - - added helpful error messages to connection failure in client. - - fixed problem with mput in client - - changed server to allow guest-only sesssetup messages with any - password. Control this with GUEST_SESSION_SETUP in local.h. - - minor change to session setup handling in make_connection() - - added check for right number of \s in the client. - - made the server not exit on last close if the deadtime is != 0 - - added malloc and realloc wrappers. enable them with -DWRAP_MALLOC=1 - - if smbd is started with a debug level of 10 or greater it creates - a log file ending in the process number - -1.6.08: 18/4/94 - - updated the THANKS file - - changes from marcel@fanout.et.tudelft.nl (Marcel Mol) for AMPM - times and error report on connect(). - - made the get_myname() routine discard any part after the first '.' - - added a wrapper for free from Martin Kiff - - added simpleminded code to handle trapdoor uid systems (untested) - - added Martin Kiffs "paranoid" getwd code. - - added default MAXPATHLEN if undefined of 1024 - - made get_broadcast() continue to get netmask if it can't get - broadcast (suggestion from Hannu Martikk) - - replaced fchmod() calls with chmod() to satisfy some unixes - - - -1.6.09: 4/5/94 - - changed perror() calls to strerror() in server.c - - fix for dfree on OSF1 from - Maximilian Errath (errath@balu.kfunigraz.ac.at) - - fixed server time reporting for protocol >= LANMAN1 - - fixed TimeDiff() for machines without TIMEZONE or TIMELOCAL - (thanks to Vesa S{rkel{ <vesku@rankki.kcl.fi>) - - added SYSV defs to AIX and HPUX to fix "memory" problem - (actually a signal problem). - - added version to client banner in log file - - Ultrix patches from Vesa S{rkel{ <vesku@rankki.kcl.fi> - - added ! command to client for executing shell commands - - fixed ERRnofids bug in server - - fixed name_equal bug - (thanks to cjkiick@flinx.b11.ingr.com (Chris Kiick)) - - wrapped gethostbyname() with Get_Hostbyname() to prevent - case sensitive problems on name lookups - - limit printer tmp filename to 14 chars - (from Paul Thomas Mahoney <ptm@xact1.xact.com>) - - added ability to understand 64 bit file times - (thanks to davidb@ndl.co.uk (David Boreham)) - - added Gwt_Pwnam() wrapper to cover server case-sensitivity - problems (suggestion from J.M.OConnor@massey.ac.nz (John O'Connor)) - - changed the setuid() calls to try and work for more systems - without breaking the ones it currently works for - - added version number to usage() - (suggestion from peter@prospect.anprod.csiro.au) - - added "security=" option for share or user level security - - allowed multiple usernames in "user=" field - - changed display method for recursive dorectory listings - - switched client to use long filenames where supported - - added speed reporting to client transfers - - several NT fixes to server from jra@vantive.com (Jeremy Allison) - - ISC fixes from ptm@xact.demon.co.uk (Paul Mahoney) - - fix to README from grif@cs.ucr.edu (Michael A. Griffith) - - default netmask and broadcast from Ian A Young <iay@threel.co.uk> - - changed default of is_locked() on fcntl() error. - - fixed bug in read_with_timeout() that could cause a runaway - smbd process. - - fixed findnext bug for long filenames in client - - changed default protocol level to LANMAN1 - - change default reported security level to SHARE. - - changed password_ok() so that if pwdauth() fails it tries - with standard crypt. - - added "translate" command to the client to do CR/LF translation - for printing, and add a form feed at the end. - (thanks to mh2620@sarek.sbc.com (Mark A. Horstman ) ) - - added "locking=yes/no" toggle for each service - - SCO unix patches from Heinz Mauelshagen (mauelsha@ez.da.telekom.de) - -1.6.10: 7/5/94 - - fixed important bug in readbraw/writebraw - - added -A option to client - - fixed delete bug on long filenames (untested). Thanks to - Stefan Wessels <SWESSELS@dos-lan.cs.up.ac.za> - - neatened up the byte swapping code - -1.6.11: 3/6/94 - - fixed bug in client in receive_trans2_response() that caused - some strange behaviour with LANMAN2. - - fixed some offset/alignment problems with lockingX (thanks to - Jeremy Allison) - - allow locking on O_RDONLY files. Thanks to Martin N Dey <mnd@netmgrs.co.uk> - - fixed del bug in client thanks to paulzn@olivetti.nl (Paul van der Zwan) - - fixed multiple user= bug thanks to MDGrosen@spectron.COM (Mark Grosen) - - added translate ability for all files. Thanks to mh2620@sarek.sbc.com (Mark A. Horstman ) - - mask out negative lock offsets. Thanks to bgm@atml.co.uk (Barry G Merrick) - - more attempts to get the structure alignment better for some machines - - cleaned up the machine dependencies a little - - ISC fixes from Paul Thomas Mahoney <ptm@xact1.xact.com> - - enabled printing with a SMBclose and SMBwrite for NT - thanks to jkf@frisky.Franz.COM (Sean Foderaro) - - SGI changes from Michael Chua <lpc@solomon.technet.sg> - - CLIX patches from cjkiick@ingr.com - - NEXT2 and NEXT3_0 patches from Brad Greer (brad@cac.washington.edu) - - BSDI changes from tomh@metrics.com (Tom Haapanen) - - SCO patches from John Owens (john@micros.com) - - fix psz bug in pcap.c (thanks to Karl Auer) - - added widelinks option (global and per service). Suggestion from - Karl Auer. Defaults to True. - - made locking able to be global or local (default is give by global) - - added check_name() to dir listings - - added "packet size" option to globals. default to 32767. This - "fixes" a WfWg bug (thanks to Karl Auer) - - fixes for getattrE and setattrE and minor fix in util.c from Jeremy Allison. - - Karl updated the man pages o be current - - disabled writebraw and readbraw until a possible bug can be investigated further - -1.7.00: 14/7/94 - - added session_users list, to overcome problem of missing usernames in SMBTconX. - - added term support to the client - - added "default service" - - fork for print so user is not root - - added name mangling to 8.3 (rudimentary) - - fixed bug in in_group() - - changed to use gid in place of egid - - fixed client connection to OS/2 (1.3 + lanman2.2) and long filenames - - added patches from mcochran@wellfeet.com (Marc Cochran) - these implement scope ids and fix some udp bugs. It means - the -L option to nmbd now works. - - made nmbd respond to incoming port rather than only 137 - - made wide links refuse .. components - - fixed "dir foo." bug to stop it showing "foo.???" - - improved name mangling (added stack) - - added valid FNUM check to most calls - - fixed important do_put bug in the client - - added magic scripts to the server - - re-enabled getwd_cache code - - added optional agressive password checking - - removed dptr_closepath from SMBsearch to try and stop "dos for loop" - bug - - DGUX patches from ross@augie.insci.com (ross andrus) - - updated the README and THANKS file. - - added node status request to -L option of nmbd - - stripped trailing spaces in mask_match() (thanks to mike hench hench@cae.uwm.edu) - - added COREPLUS style print queue reporting and "lpq command" - in globals. - - cleaned up date handling and fixed byte order dependancy on dates - in SMBgetattrE. - - cleaned up the password handling and added "password level" with - the possability of checking all case combinations up to N upper - case chars. - - changed to use recvfrom only on udp ports (fixed read raw!) - - added TCB password support for SCO (thanks to lance@fox.com) - - updated README, THANKS and announce files. - - fixed timezone reporting to be signed (thanks to noses@oink.rhein.de) - - disabled max packet as it could cause problems with WfWg (no longer - needed now readraw is "fixed") - - changed from creat() to open() in mktemp and mknew. - - changed umask handling - - sped up nmbd by making it cache names - - changed idle timeout on nmbd to 2 mins - - Netbsd changes from noses@oink.rhein.de - - released alpha2 - - added name timeout to nmbd - - changed bind port retry in nmbd - - added Limitations sections to README - - fixed two . in is_83() - - fixed compilations warnings in util.c (thanks to njw@cpsg.com.au) - - made [homes] honour multiple user list - - fixed mask match bug introduced in alpha1 - - added "mangled stack" option for stack size - - added mangled stack promotion - - released alpha3 - - netbsd-1.0 fix for statfs(). - - added null_string to util.c to reduce memory usage - - changed the way directory structures are put together - - added smbrun for system() requests - - changed maxmux to 0 in hope of avoiding mpx commands problem - - fixed zero response length for session keepalives - - removed called name from session users list - - added F_RDLCK support to try and handle locks on readonly files - - made directory creation honour the lowercase flag in client (thanks - to charlie@edina.demon.co.uk) - - made checksum for mangling independant of extension if extension is - lowercase - - added ability to rename files with different extension, preserving - root name - - released alpha4 - - better command line error checking in client - - changed all debug statements to new format - - fixed delete error code reporting - - released alpha5 - - added mangled name support to wildcard delete in server - - fixed mask bug in SMBsearch - - cleaned up prototypes - - released alpha6 - - fixed important bug in session_setup which made WfWg freeze - (maxmux was 0 - this bug was introduced in alpha4) - - released alpha7 - - two printing bug fixes thanks to bgm@atml.co.uk (Barry G Merrick) - - uid fix to smbrun (thanks to larry@witch.mitra.com) - - man page updates from Karl Auer - - FAQ file from Karl Auer - - released alpha8 - - fixed read-only flag in dos_mode() for non writeable services - - fixed error code reporting in open() and openX(). - - minor secureware fix from (thanks to lance@fox.com) - - released alpha9 - - casting cleanups for memcpy(). - - cleaned up error code names to be more consistant - -1.7.01: 17/7/94 - - minor man page fix from baeder@cadence.com (Scott Baeder) - - changed usage() error message in client - - made nmbd not exit if can't register own name - - made nmbd only register if running as a daemon - - fixed stdout problem in smbrun by closing stdin/stdout/stderr - - minor fix to lmhosts parsing - - -1.7.02: 20/7/94 - - made nmbd not call get_broadcast if both -B and -N are used (thanks - to Chris Woodrow <Chris.Woodrow@actrix.gen.nz>) - - disabled GETWD_CACHE again - - fixed INCLUDES list in Makefile to add version.h (thanks to - jimw@PE-Nelson.COM (Jim Watt)) - - made checkname do a become user if it hasn't already done so. - - added consistancy check to become_user(). - - removed mask extension expansion from SMBsearch - - small change to chkpth - - fix to snum select for lpq status (thanks to Rafi Sadowsky - rafi@tavor.openu.ac.il) - - changed daemon to is_daemon for NetBSD (thanks to noses@oink.rhein.de) - - removed STAFS3 stuff for NETBSD_1_0 - - -1.7.03: 29/7/94 - - updated docs for new distribution structure - - made getatr return 0 size for directories (thanks to Bernd Esser - esser@pib1.physik.uni-bonn.de) - - added valid dos filename checks from Stefan Wessels - (swessels@cs.up.ac.za) - - added trimming of . in hostnames to -S mode of nmbd - - removed become_user() and OPEN_CNUM calls. Now make them - in switch_message instead which simplifies a lot of code. - - added GETFNUM macro to make chain_fnum more consistant and - reliable. - - added flags to protocol structures to simplify CAN_WRITE and AS_USER - checking - - added getwd cache boolean option to globals - - added fclose() to lpq status routine thanks to - dgb900@durras.anu.edu.au (David Baldwin) - - added "only user" option, to limit connection usernames to those - in the user= line - - changed to badpath from badfile in chkpath despite specs (following - what WfWg does). This fixes "file not found" error in copy command. - Thanks to rwa@aber.ac.uk for pointing out the bug - - changes for apollo from Stephen C. Steel <steve@qv3donald.LeidenUniv.nl> - - more changes for Apollo from jmi@csd.cri.dk (John Mills) - - released alpha release - - added FTRUNCATE_CAN_EXTEND=0 as default to fix problem with word6. - Possibly not needed on many OSes? Thanks to Charlie Hussey - charlie@edina.demon.co.uk - - started adding max connections code - - much improved group handling contributed by - Ian Heath (ih@ecs.soton.ac.uk) - -1.7.04: 29/7/94 - - fixed one line bug in SMBopenX that got error code wrong. - -1.7.05: 2/8/94 - - added UNIXERROR() macro to get error code from unix errno. - - fixed lpq status for MSTCPB3 - - added @ option for user= line to lookup groups in group file - - added become_user optimisation and process timeout (thanks to - Jeanette Pauline Middelink (middelin@calvin.iaf.nl) - - added malloc optimisation in readbraw - - released alpha - - patches for OSF1 enhanced security from Udo Linauer <ul@eacpc4.tuwien.ac.at> - - made level 2 a more useful debug level (less guff) - - added "max connections" and "lock dir" options to allow - limiting of the number of connections to a service at one time. - - released alpha2 - - updated man pages - - released alpha3 - - added read prediction code for better read performance - - released alpha4 - - minor tuning to receive_smb() - - changed the order of mangled stack checking - - bug fix in read_predict(). - - released alpha5 - - minor search optimisation - - fixed keep alive bug in writebraw and in readbraw in the client - - released alpha6 - - disabled writeraw by default pending a bug fix - - added profiling code (off by default) - - minor delete tuning - - -1.7.06: 4/8/94 - - OSF1 crypt fix thanks to Udo Linauer <ul@eacpc4.tuwien.ac.at> - - ifdef'd EDQUOT in case you don't have it (thanks to Paul Blackman <ictinus@Lake.canberra.edu.au>) - - tidied up UNIXERROR stuff to work on more systems. - - made Makefile more sophisticated and added "make revert" - -1.7.07: 4/8/94 - - fixed one line fatal bug in receive_smb. Thanks to bruce@pixar.com - -1.7.08: 2/9/94 - - initgroups call for SCO from lance@fox.com - - code cleanups from cap@isac.hces.com (Simon Casady) - - use full pathname in print command construction - - ISC includes fix from Martin Tomes <mt00@ecl.etherm.co.uk> - - added GID_TYPE define to cope with ultrix. Thanks to - brad@cac.washington.edu - - added umask call to main in server - - fixed several minor problems with the max connections - code. Thanks to lehmann@klizix.mpi-stuttgart.mpg.de (Arno Lehmann). - - fixed filetime in writeclose. Thanks to Andreas Bahrdt - <100321.2431@compuserve.com> - - df fix for large disks from Andreas Bahrdt - - getpwanam support from horn@mickey.jsc.nasa.gov - - clean name change from Bernd Esser - <be@syli30.physik.uni-bonn.de> - - released alpha1 - - more locking changes to fix Excel problem - - released alpha3 - - another minor locking change - - smarter masking in the locking code. Excel now apparently works. - - minor FAQ updates - - changed max connections refusal error to access denied. - - added queue command to client to show the print queue - - changed some print queue reporting stuff - -1.8.0: 14/10/94 - - added international chars to valid_dos_char(). Thanks - to Daniel.Grandjean@dgr.epfl.ch - - volume label fix - - released alpha1 - - important off by 4 fix in the server - - readbraw size adaption in the client - - released alpha2 - - wait3 cast for NeXt fixed. Thanks to dbrandon@politics.tamu.edu. - - man page fix for max xmit. Thanks to mmoore@wexford (Mike Moore) - - is_8_3() fixes from Jochen Roderburg <Roderburg@rrz.Uni-Koeln.DE> - - list_match() fix from jkf@soton.ac.uk - - statfs3 fix for BSDI from dan@supra.com - - changed file open/close/read in server in preparation for mmap() - based IO. - - added mmap() support for reading files in the server. Optional - at compile time. Thanks to suggestion from Roger Binns <rogerb@x.co.uk> - - mmap bug fixes - - added __SAMBA__ name in nmbd - - major changes for support of lanman2 and long filenames from - Jeremy Allison (jeremy@netcom.com) - - lseek optimisation. Thanks to Linus Torvalds. - - released alpha4 - - date patches for lanman2 from Jeremy Allison - - added protocol aliases to handle WfWg (untested) - - allow for zero params or data in reply_trans2 - - small lanman2 patches from jeremy - - more prototype additions for clean compilation - - postscript patches from tim@fsg.com - - more lanman2 patches from Jeremy - - added null ioctl support - - kanji patches from fujita@ainix.isac.co.jp - - released alpha6 - - disallowed null password access (thanks to Birger Kraegelin krg@iitb.fhg.de) - - Makefile fix for ultrix from andrew@d2bsys.demon.co.uk (Andrew Stirling) - - added per-service mangled names - - totally re-vamped loadparm.c - - added "mangling char" parameter - - released alpha7 - - added "default case = lower|upper" service option - - change mangling char to a service parameter - - ultrix enhanced security patch from steven@gopher.dosli.govt.nz - - more changes to loadparm.c - - printer name always set in [printers] - - string_free() fix thanks to jef_iwaniw@pts.mot.com - - changed group handling to be faster and work for large numbers - of groups - - added dynamic gid_t type determination - - released alpha8 - - fixed become_user() problem for services with invalid - directories - - added "invalid users" list on per service basis - - fixed pointer problems in alpha8 (thanks to murnaghant@a1uproar.yuppy.rdgmts.MTS.dec.com) - - fixed some date setting problems - - trans2 fixes from jeremy to stop infinite directory listings of - long filenames - - "standard input" lpq patch from root@tlspu.demon.co.uk (Adrian Hungate) - - changed password checking to check session list and validated ids - before user list - - split off password functions into password.c - - added hosts equiv and rhosts code (thanks to Tim Murnaghan <murnaghant@a1uproar.yuppy.hhl.MTS.dec.com>) - - released alpha11 - - added "newer" command to the client - - attempt at aix trapdoor uid workaround - - released alpha12 - - minor trans2 bugfix - - added ufc crypt (fast crypt) support. Thanks to suggestion from - forrest d whitcher <fw@world.std.com> - - socket() fix for getting bcast and netmask thanks to - Brian.Onn@Canada.Sun.COM - - added beginnings of IPC and named pipe support in the server - - changed file structure a bit, creating reply.c - - finished print queue support for lanman1 - - changed default protocol to LANMAN2 - - released alpha13 - - logged IPC connects at a higher debug level - - added netgroup support to hosts equiv search - - disallowed root access though hosts.equiv (thanks to Colin.Dean@Smallworld.co.uk) - - kanji and password handling fixes from fujita@ainix.isac.co.jp - - several bug fixes for lanman and other things from - esser@pib1.physik.uni-bonn.de (Bernd Esser) - - updated man pages, README and announce files. - - released 1.8.00alpha1 - - reply_close() time change fix from Andreas Bahrdt <100321.2431@compuserve.com> - - added valid users list to compliment invalid users list. - - aix fixes from tomc@osi.curtin.edu.au (Tom Crawley) - - changed testparm output format - - support for getting time from the server (nearly untested) - - fixed device type error for wild device ???? - - fixed groups problem when in 0 groups - - more IPC fixups - - added support for "net view \\server" command to list - available services (like browsing) - - released 1.8.00alpha2 - - changed port choice for nmbd -L - - added -L option to client to view share list on a host - - bug fixes for NetShareEnum code - - added "server string" option - - changed default print file name to include remote machine name. - - added hooks for browsing in nmbd - - added browsing to nmbd - - freebsd fixed from Steve Sims SimsS@Infi.Net - - got rid of tell() - - added subnet browsing with the S option in lmhosts - - made smbd prime nmbd with a 1 byte dgram - - added REUSADDR to open_socket_in() thanks to peter@ifm.liu.se - - -1.8.01: 18/10/94 - - - auto add group "LANGROUP" if no group specified in nmbd - - made nmbd more responsive at startup - - lots of cleanups and consistancy checks - - added -C option to nmbd to set "machine comment". - - fixed postscript option - - force print_file in print_open() - - restructured the browsing a little - - casesignames fix for lanman-dos - - auto-load home directory from session setup - - changed to StrnCpy() for safety - - fixed "out of file descriptors" bug in the client (a WfWg bug?) - - -1.8.02: 22/10/94 - - fixed uppercase username problem - - added "hide dot files" option - - changed auto debug log in nmbd - - added LMHOSTS to Makefile - - added M flag in lmhosts to specify own netbios name - - added "load printers" option to auto-load all printers - - substitution of %p in lpq command - - substitution of %h and %v in server string and -C option of - nmbd - - string substitions substitute all occurances of a pattern - - added casesignames global option - - fix for man pages thanks to David Gardiner <dgardine@cssip.edu.au> - - changed debug options a bit - - added default for lpq command and lpr command - - changed default shell path to /bin/sh - - forced lpq under api to run as root - should speed things up - - added "group" option to force group of a connection - - added "read list" and "write list" options - - added max mux option - seems to fix NT browsing? - - added "mangled map" option thanks to - Martin.Tomes@uk.co.eurotherm.controls - - separated mangling functions into mangle.c - - allowed all dos chars in mangled names - - apollo changes from Helmut Buchsbaum <buc@eze22.siemens.co.at> - - password changing code from Bob Nance <Bob.Nance@niehs.nih.gov> - it doesn't quite work yet, but it's a start (disabled by default) - - -1.8.03: 25/10/94 - - made auto loaded services browsable as per default service - so you can hide homes but keep home directories. - - changed check_name() to handle "direct to network" printing - - auto 3 minute deadtime if all connections are closed. This - prevents restart when polling the print queue. - - fix for newer command in client from Rich-Hoesly@uai.com - - changed connection recording method - - added the program smbstatus - - changed timeout mechanism - - "null passwords" option from Pim Zandbergen <pim@cti-software.nl> - - made new files with casesignames=False set their case to the default - case. - - fixed problem of uppercasing first letter of printers in printcap - - debug level fixes in trans2 from jimw@PE-Nelson.COM (Jim Watt) - - made null printer default to lp - -1.8.04: 27/10/94 - - added OS2.txt from riiber@oslonett.no - - another "auto services" fix. A silly strtok() bug :-( - - fixed the status locking and max connections (broken in 1.8.03) - - released alpha1 - - added gets_slash so lines can be continued in smb.conf and - lmhosts - - browse list bugfix - - default to "load printers=yes" - - rewrote pcap.c - - intergraph bugfix from tarjeij@ulrik.uio.no - - changed properties flags in nmbd (to fix NT print browsing) - - allowed very long lines in printcap parsing. - -1.8.05: 28/10/94 - - lanman2 fix from Jeremy - -1.9.00: 22/1/95 - - only add home if not already there. - - added ulogoffX support - - PTR_DIFF() cleanups - - fixed a bug that caused STATUS..LCK to grow very large - - changed mangling to handle names ending in . a little better - - added "strip dot" option - - SGI and setgroups() fix from bill@sg25.npt.nuwc.navy.mil - - fixed password preservation in password_ok() (again?) - - unink fix from emer@vssad.enet.dec.com (Joel S. Emer) - - changed username part of spool filename to max 10 chars (from 6) - - magic script fix from beverly@datacube.com (Beverly Brown) - - reply_special() fix from Peter Brouwer <pb@apd.dec.com> - - stopped nmbd from listening on 138. It didn't seem to help much. - - clix fixes from ttj@sknsws61.sjo.statkart.no - - fixed select behaviour under Linux - - man page fix from Robin Cutshaw <robin@intercore.com> - - ISC block size fix from ralf@rbsoft.sdata.de (Ralf Beck) - - ISC fixes from Martin.Tomes@controls.eurotherm.co.uk - - attrib bit fix in smbclient (pointed out by Rich-Hoesly@uai.com) - - japanese extensions from fujita@ainix.isac.co.jp (Takashi - Fujita) and ouki@gssm.otuska.tsukuba.ac.jp. - - SCO patches from Stephen.Rothwell@pd.necisa.oz.au - - changed the system commands to redirect stderr - - changed default printername to service name for all print ops - - added ability to delete print queue entries - - added warning if you try to print without -P in smbclient - - INTERACTIVE patches from cardinal@settimo.italtel.it - - patch to handle spaces in group names from GJC@vax1.village.com - (GEORGE J. CARRETTE) - - lockingX fix from stefank@esi.COM.AU (Stefan Kjellberg) - - some fairly radical changes to filename handling. We can now - handle mixed case filenames properly - - released alpha2 - - added sysv printing support and improved bsd support - - changed the user that does print queues and lprm jobs - - return code support in the client from doylen@nbslib.isc-br.com (Doyle Nickless) - - added "strict locking" option. Defaults to no. - - - added -I switch to nmbd - - fixed DEV bug thanks to Dirk.DeWachter@rug.ac.be - - use pw_encrypt() for shadow passords in Linux (from begemot@begemot.iko.kharkov.ua (Dmitry Gorodchanin)) - - disabled read prediction by default - - added varient handling code to ipc.c for printQ and printDel. - - released alpha5 - - AUX patches from root@dolphin.csudh.edu - - struct timeval fix from gkb1@york.ac.uk - - patches to merge ISC and INTERACTIVE from pim@cti-software.nl - - changed to "printing =" - - fixed problem with long print queues. - - fixed node status request in nmbd to go to non bcast - - made default path in services /tmp if not specified - - added %u in passwd program - - fixed up the password changing code for Linux - - no guest sess setup when user level security - - changed timeouts to kill dirptrs so cdroms can be unmounted - - added auto-reload of smb.conf if changed - - added SIGHUP to reload the config files - - added -M option to nmbd to search for a master browser - - added support for continue bit in trans2findnext - - changed to dynamic strings in some more structures - - changed default deadtime to 30 minutes - - cleaned up the memory swapping code a bit - - updated the man pages somewhat - - added %m and %u in the "path=" of services - - released alpha6 - - simple testing and fixups for solaris, sunos, aix, ultrix and - osf/1 (this is all I have access to). - - fixed chdir bug - - added hashing to cnum selection - - released alpha7 - - fixed printing bug - - reduced chance of "hung" smbd with dead client - - fixed do_match() bug (recently introduced) - - released alpha8 - - nameserver fix from W.J.M.vGeest@et.tudelft.nl (W.J.M. van Geest) - - rewrote readbraw to try and overlap reads with writes - - client optimisations - - rewrote getwd cache and enabled it by default - - added partial smb packet reads (hopefully faster writes) - - added log file and log level options (with subs) - - added "read size" option - - tried setting some more socket options - - can use subs in "config file=" and will auto-reload - - added "include" options, with some subs - - finally got print manager working with NT - - auto-respond in nmbd to non-broadcast (auto WINS server, no -A - needed) - - released alpha10 - - auto-delet unused services when reloading - - fixed auto-deletion - - fixed long names in printing - - fixed double loading of services file - - added printer file name support - - reformatted man pages for better www conversion - - renamed to 1.9.00. - - added support for RNetServerGetInfo and NetWkstaGetInfo API's - - updated the docs a bit - - released alpha1 - - added -M - - - changed nmbd announce interval to 10 mins in outgoing packets - - hopefully fixed idle timeout reconnects - - strupper all command lines in nmbd - - added %a substitution for "remote architecture" - - added "Samba" protocol (same as lanman2) - - added "security = SERVER" - - released alpha2 - - lowercase password fix - - fixed connect path length bug (thanks to JOHN YTSENG - <jtseng@cory.EECS.Berkeley.EDU>) - - added subs on "password server". - - fixed printing filename bug from smbclient - - disk quotas and hpux printing support from Dirk.DeWachter@rug.ac.be - - Makefile patches from pappinm@ayr_srv2.nth.dpi.qld.gov.au - - AFS patches from Mike Allard (mgrmja@nextwork.rose-hulman.edu) - - fixed grp name = server name problem - - man page updates from Charlie Brady (charlieb@budge.apana.org.au) - - fixed file search bug by adding "finished" flag - - added "max log size". Suggestion from Mark Hastings <mark.hastings@gain.com> - - released alpha3 - - changed the read/write routines to handle partial read/writes - - released alpha4 - - changed "guest account" to per-service - - changed so "guest ok" allows access to the guest account, - not the "user=" line - - changed default readsize to 2048 - - try bind to 137 in nmbd if possible - - added server lookup to -L option in smbclient (gets list of servers) - - added -M switch to smbclient for sending winpopup messages - - released alpha5 - - FAQ updates from Paul Blackman ictinus@lake.canberra.edu.au - -1.9.01: 23/1/95 - - changed comment in print Q info to service rather than server comment - - fixed smbclient -L to NT when in user level security mode - - hopefully finally fixed NT print manager problems - - added informative messages during smbclient -M - - added node status replies to nmbd - - changed the lock offset fixup calculation to be more friendly - to dumb lockd daemons. - - added sigbus and sigsegv handlers to catch any silly errors and - print a message - - added message receipt to smbd and "message command =" option - -1.9.02: 25/1/95 - - added argv/argc mangling for people who start the server the - wrong way. - - some man page updates - - added "revalidate" option - - added hosts allow/deny access check to messaging access - - added timeouts in the client - - added check for existance of smbrun binary - - man page updates from Colin.Dean@Smallworld.co.uk - - freebsd patches from dfr@render.com - - added mask sanity check in SMBsearch - - added more useful substitutions (%S, %P, %I and %T) - - added "exec =" option to execute commands on each connection - -1.9.03: 13/3/95 - - added "socket options" option - - close base fd's (0,1 and 2) - - use dup(0) for inetd operation - - better detection of is_daemon - - hopefully finally fixed silly put bug that gave the wrong - date on files. - - fixed segv in readbraw bug - - added improved checing for invalid (or null) print file name - - several patches from ad@papyrus.hamburg.com (Andreas Degert) - - fixed slow logout bug in smbclient - - fixed automounter problems - - added subs on lock dir - - BSDI patch from John.Terpstra@Aquasoft.com.au - - added separate nmb and smb logfile entries in the Makefile - - fixed return code error in open calls - - added simple status display of printer in lpq parsing - - rewrote the directory handling to avoid seekdir (added dir.c) - - added uid=65535 check (thanks to grant@gear.torque.net) - - enhanced transfer_file() to add header (used in readbraw) - - reply_special bugfix from ferret@pc8871.seqeb.gov.au - - added HAVE_PATHCONF - - RiscIX patches from Jim Barry <jim@ilp.com> and - Charles Gay-Jones <charlie@ilp.com> - - CLIX patches from ttj@sknsws61.sjo.statkart.no - - fixed aix lpq parser from kvintus@acd.com - - added substitutions to "include=" - - M88K_S3 patches from tonyb@plaza.ds.adp.com (Tony D. Birnseth) - - fixed mangled stack problem - - added code to handle broken readdir() setups on solaris - - initgroups() fix from jarit@to.icl.fi - - dgux dfree fix from listwork@cloud9.net - - dnix support from Peter Olsson <pol@leissner.se> - - getgrgid() patch from tpg@bailey.com (Tom Gall) - - Makefile patch from obrien@Sea.Legent.com (David O'Brien) - - password changing fixes from Dirk.DeWachter@rug.ac.be - - minor man page updates - - tried to enhance the read prediction code a little bit - -1.9.04: 16/3/95 - - a bit better handling of global include lists - - fixed GSTRING bug in loadparm.c (affected "socket options =") - - fixed broken lpq parsing code (recent bug). - Thanks to Dirk.DeWachter@rug.ac.be - -1.9.05: 20/3/95 - - improved mget in client to take multiple arguments and default - to *.* - - socket option fixes for both nmbd and smbd - - changed the byteorder handling scheme to be more portable (and - faster) - - lint cleanups from kast@kcs.planet.net (Robert Kast) - - added crude segv, sigbus and sighup recovery to nmbd - - rewrote lanman2_match to be closer to NT and WfWg behaviour - - Cray support from velo@sesun3.epfl.ch (Martin Ouwehand) - - "admin users" patch from Tim Leamy <tcleamy@ucdavis.edu> - - released alpha1 - - added samba.7 man page - - no chdir when doing non AS_USER protocols - - become_guest() returns true in trapdoor uid system - - added more sophisticated segv/sigbus reporting (Linux only) - - released alpha2 - - minor code cleanups (output of -Wall) - - smbprint fix from James Dryfoos <dryfoos@ll.mit.edu> - - improved testparm a little - - updated INSTALL.txt a little - - -1.9.06: 21/3/95 - - added %S substitution to users, valid users and invalid - users. This is useful for [homes]. - - split off printing routines into printing.c and more dir - commands into dir.c - - postexec patch from jpm@gin.Mens.DE (Jan-Piet Mens) - - smbstatus updates from jpm@gin.Mens.DE (Jan-Piet Mens) - - reload sighup after use - - fixed name ptr offset bug - - added %f in print commands - - fixed byte ordering in nmbd which caused browsing to fail in - 1.9.05 - -1.9.07: 22/3/95 - - important directory listing fix - - allowed path= in [homes] section - - printer status patches from Dirk.DeWachter@rug.ac.be - -1.9.08: 24/3/95 - - fixed . and .. in root dir for lanman2 - - better default comment in [homes] - - added time stamping to directory entries - - check directory access at connection time - - rlimit code from loebach@homer.atria.com (Thomas M. Loebach) - - fixed home dir default comment - - totally rewrote dptr handling to overcome a persistant bug - - added [globals] as well as [global] - -1.9.09: 30/3/95 - - fixed static string bug in nmbd - - better null password handling - - split CFLAGS in Makefile - - fixed typo in smbclient messaging - - made home dir not inherit path from [global] - - standard input printing patch from xiao@ic.ac.uk - - added O_CREAT to all print opens (bug in Win95) - - use /proc for process_exists under Linux and solaris - - fixed another segv problem in readbraw - - fixed volume label problem - - lots of changes to try and support the NT1 protocol - - released alpha1 - - fixed session setup bug with NT in NT1 protocol - - released alpha2 - - fixed "get" bug in smbclient that affected NT3.5 - - added SO_KEEPALIVE as a default socket option in smbd - - changed some error codes to match those that NT 3.5 produces - - updated trans2 with some new calls for Win95 and WinNT (better - long file support) - - released alpha3 - - fixed "nmbd -D -b" timeouts - - added IS_LONG_NAME flag to getattr in NT1 - - added the NT qfileinfo trans2 commands - - merged qpathinfo with qfileinfo - - changed idling technique to try and be more friendly to - clients - - merged setfileinfo with setpathinfo and updated them with the NT fns - - improved read prediction a lot - - added read prediction to readbraw - - improved fault reporting (last packet dump) - -1.9.10: 30/3/95 - - fixed read prediction+readbraw bug for read/write files - -1.9.11: 9/4/95 - - fixed trans2 qpathinfo bug - - fixed bug with % in service name when doing print queue requests - - default readsize now 16K - - minor read prediction changes - - fixed status initialisation in print queue reporting - - fixed const compile problem for hpux - - minor SMBread fix from Volker Lendecke <lendecke@namu01.gwdg.de> - - removed space after -P in print commands (for fussy systems) - - disabled level2 of setfilepathinfo - - changed to a single read dir model, saving all dir names in - the Dir structure - - disabled NT protocols in the client due to reported problems - - fixed QUERY_FS_VOLUME_INFO which caused Win95 to hang on drive - properties - - minor lseek bug fix - - fixed up keepalives - - new timezone handling code (hopefully better!) - from steve@qv3pluto.LeidenUniv.nl - - BSDI interface patch from jrb@csi.compuserve.com - - gettimeofday changes from Roger Binns <rogerb@x.co.uk> - - added smbrun option - - added "root preexec" and "root postexec" options - -1.9.12: 12/4/95 - - hopefully fixed some recently introduced NT problems - - fixed a unlink error code problem - - minor testparm fix - - fixed silly error messages about comments in config files - - added "valid chars" option for other languages - -1.9.13: 28/4/95 - - patches from David O'Brien (obrien@Sea.Legent.com) improving the - netgroup suport, and adding the "map archive" option, as well as - other minor cleanups. - - tried to add info level 3 and 4 support for OS/2 - - default deadtime set to 0 as in docs - - cleaned up the trans2 code a little - - cleaned up the Makefile a little - - added charset.c and charset.h - - expanded "valid chars" option to handle case mapping - - lots of changes to try and get timezones right - - released alpha1 - - win95 fixups - - released alpha2 - - added %H substitution (gives home directory) - - nameserv.c cleanups and minor bug fixes - - redid the browse hook logic - - fixed daylight saving time offset for logfile messages - - added name cacheing to nmbd - - added send counts to node status in nmbd - - added STRICT_TIMEZONES compile time option (very computationally - expensive) - - removed the partial read code - - cleaned up the permission checking a lot - - added share modes (DENY_READ, DENY_WRITE, DENY_ALL, DENY_NONE, - DENY_FCB and DENY_DOS) - - added "share modes" option - - cleaned up the file open calls - - released alpha4 - - fixed important one line bug in open_file() - - trans2 client fix from lendecke@namu01.gwdg.de - - netgroup patche from David O'Brien (obrien@Sea.Legent.com) - - case sensitive fix from lenneis@statrix2.wu-wien.ac.at (Joerg Lenneis) - - got long filenames working from Win95 dos prompt - - added "workgroup=" option - - added "username map" option including multiple maps, group maps etc - - fixed password server for NT1 protocol and made it more robust - - changed unix_mode() to add IWUSR to read-only directories. This - is much closer to what clients expect. - - added preservation of unused permission bits when a chmod() is - called from a client. - - made static those fns that could be - - fixed typo in access.c (thanks to Andrew J Cole - <A.J.Cole@cbl.leeds.ac.uk>) - - added %d substitution for process id - (thanks to lenneis@statrix2.wu-wien.ac.at (Joerg Lenneis)) - - changed share error code to ERRbadshare - - added locked files list to smbstatus if share modes is enabled - - changed DENY_DOS to allow read by other tasks - - added shared_pending checks to server - - preserverd all possible permission bits during a chmod, and - fixed a trans2 chmod bug - - open /dev/null to use up first 3 fds, in an attempt to stop rogue - library routines from causing havoc - - fixed NT username problem when in server security - - added "force user" and "force group" options - - cleaned up some of the IPC calls a bit - - added writeraw to the client and cleaned up write raw in the server - - osf1 big-crypt bugfix from Udo Linauer <ul@eacpc4.tuwien.ac.at> - - hopefully better disk-full checking - - next uid bugfix from patrick@graphics.cornell.edu - - changed share modes so lock directory doesn't need to be world - writeable - - enabled write-raw by default - - added server_info() in client - - added level checks in some ipc calls - - added defines for the important timeouts in local.h - - added print queue deletion to smbclient (untested) - - removed the sysconf() calls - - optimised writebraw a bit - - fixed some file deletion problems - - added total_data check for extended attribs in trans2 (for OS/2) - - fixed broadcast reply bug in nmbd - - added careful core dumping code - - added faster password level searches (suggestion - by lydick@cvpsun104.csc.ti.com (Dan Lydick)) - - -1.9.14: 22/9/95 - - fixed up level 3 and 4 trans2 requests for OS/2 - - minor optimisations in a few places - - cleaned up the closing of low fds a bit - - added SO_REUSEADDR to socket as a daemon - - override aDIR bit for directories in dos_chmod() - - SGI5 fixes from ymd@biosym.com (Yuri Diomin) - - bsize sanity check and removed sunos force to 1k - - force the create mode to be at least 0700 - - SCO and freebsd include changes from Peter Olsson - <pol@leissner.se> - - check with FQDN in access.c (thanks to Arne Ansper <arne@ioc.ee>) - - default broadcast for dnix from Peter Olsson <pol@leissner.se> - - solaris patches from Ronald Guilmette <rfg@segfault.us.com> - - added EXDEV handling - - small AFS Makefile patch from mgrlhc@nextwork.rose-hulman.edu - - hopefully fixed the Win95 dates to work in other than my - timezone - - attempted alignment fixups (to speed up memcpy) - - added some DCE/DFS support (thanks to Jim Doyle <doyle@oec.com>) - - added fix so that root doesn't have special privilages to open - readonly files for writing (but admin users do). This fixes the MS - office install problem. - - fixed trans2 response bug in client - - got dual names working for NT - - enabled lock_and_read in NT protocol - - added %L macro for "local machine" - - changed dfree reporting to use "sectors per unit" - - fixed "not enough memory" bug in MS print manger by limiting - share name length in share enum. - - "short preserve case" option from Rabin Ezra (rabin@acm.org) - - added archive option to client - - changed openX in client to be able to open hidden and system files - - added "sync always" option - - rewrote writebmpx and readbmpx - - added auto string_sub_basic to all loadparm strings - - lots of nmbd fixups (add registration, refresh etc) - - released alpha1 - - added smbtar patches from Ricky Poulten (poultenr@logica.co.uk) - - added a lpq cache and the "lpq cache time" option - - released alpha 2 - - sun includes fix from Kimmo Suominen <kim@deshaw.com> - - change nmbd -L lookup type to workstation from server - - added min print space option - - added user and group names to smbstatus (thanks to - davide.migliavacca@inferentia.it) - - fixed %f in print command bug (thanks to huver@amgraf.com) - - added wildcard support to SMBmv - - misc patches from David Elm (delm@hookup.net) - - changed default of "share modes" to yes - - changed default of "status" to yes - - aix qconfig parsing from Jean-Pierre.Boulard@univ-rennes1.fr - - more long_date fixups - - added wildcards to nmbd - - extensive changes to ipc.c and miscellaneous other changes - from ad@papyrus.hamburg.com (Andreas Degert). Should especially - help OS/2 users - - added name release to nmbd - - relesed alpha4 - - fixed "SOLARIS" to SUNOS5 in Makefile - - several minor fixups to get it to compile on aix, osf1, ultrix, - solaris and sunos - - released alpha5 - - minor bug fixes and cleanups in ipc.c - - fixed "only user" bug - - changed lpq to report guest queue entries as sesssetup_user to - allow for deletion by windows - - released alpha6 - - added __SAMBA__ as type 0 in nmbd (was type 20) - - fixed null print job bug - - added 8 char warnings to testparm and smbclient - - changed to 8 char limit for names in pcap.c - - added linked list of config files to detect all date changes - that require a reload - - simplified pcap guessing heuristics - - added space trimming to the name mapping - - updated Get_Pwnam to add allow_change field for username mapping - - fixed MemMove bug (thanks to mass@tanner.com (Massimo - Sivilotti)) - - released alpha7 - - rewrote MemMove to be a little more efficient - - ipc va_arg bug fix from djg@tas.com (Dave Gesswein) - - added check for illegal chars in long filenames - - fixed name cache init bug in nmbd - - Convex patches from Victor Balashov <balashov@cv.jinr.dubna.su> - - timestring() bugfix from staale@spacetec.no - - changed %H to give path of forced user if one is set - - added quoting to smbclient to allow spaces in filenames - - convex and other patches from Ulrich Hahn - <ulrich.hahn@zdv.uni-tuebingen.de> - - released alpha8 - - fixed rename directory bug - - nmbd wins fix from Maximilian Errath <errath@balu.kfunigraz.ac.at> - - client and AFS changes + password.c reorganisation + "more" and - "pwd" commands in client from Todd j. Derr (tjd@smi.med.pitt.edu) - - fixed several nmbd bugs - - released alpha9 - - fixed another "cd" bug in smbclient - - password encryption from Jeremy Allison - - added "passwd chat" option and chat interpretation code - - added "smb passwd file" option - - released alpha10 - - cleaned up chgpasswd.c a little - - portability changes to the encryption handling code - - added password encryption to smbclient - - fixed a share level security encryption bug - - added "ENCRYPTION.txt" document - - released alpha11 - - added code to detect a password server loop - - fixed typo in chkpath in client.c that broken cd (again) - - LINUX_BIGCRYPT from marsj@ida.liu.se - - AFS password fixup from jbushey@primenet.com (Jeffrey G. Bushey) - - iso/8859-1 charcnv patches from Dan.Oscarsson@malmo.trab.se - - strtok/user_in_list fix from roderich@nodebonn.muc.bmw.de - - NETGROUP patches from J.W.Schilperoort@research.ptt.nl - - trim_string patch from J.W.Schilperoort@research.ptt.nl - - fixed problem with files with no extension getting mixed up - - ipc bugfix for print job deletion from Rainer Leberle <rleberle@auspex.de> - - released alpha12 - - pwlen fix in NETGROUP from Andrew J Cole <A.J.Cole@cbl.leeds.ac.uk> - - lots of uid and encryption changes from Jeremy Allison. WinDD - should now work. - - released alpha13 - - fixed max_xmit bug in client - - select fix in server (fixed critical drive errors under ISC) - - released alpha14 - - wildcard fix from Jeremy - - changes to make IPC code more robust - - small select loop change to reduce cleaning of share files - - vtp, altos and mktime patches from Christian A. Lademann - <cal@zls.com> - - EEXIST bugfix in server.c - - changed mangled map to apply in all cases - - released alpha15 - - fixed fcb open permissions (should mean apps know when a file is - read only) - - released alpha16 - - client help formatting fix and docs fix from Peter Jones - <thanatos@drealm.org> - - added a directory cache - - use /proc whenever possible for pid detection - - TCSANOW fix in getsmbpasswd from roderich@nodebonn.muc.bmw.de - - fixed default printing mode for sysv systems - - make client always expand mask - - more minor IPC fixups - - pyramid makefile entry from jeffrey@itm.org - - client fixups for passlen, maxvcs and session redirect from - Charles Hoch <hoch@hplcgh.hpl.hp.com> - - finally fixed important IPC bug (varargs bug with int16) - - quota patches from Dirk.DeWachter@rug.ac.be - - print queue cache changes (per service) and print queue priority - additions from Dirk.DeWachter@rug.ac.be - - new japanese patches (incomplete) from - fujita@ainix.isac.co.jp (Takashi Fujita) - - moved a lot more functions into system.c via wrappers - - changed a lot of the connection refused error codes to be more - informative (or at least different) - - released alpha17 - - changed error return code from cannor chdir() in make_connection - - fixed realloc() bug in printing.c - - fixed invalid username bug in sesssetupX - - released alpha18 - - made default service change name to asked for service (idea - from Ian McEwan <ijm@doc.ic.ac.uk>) - - fixed "guest only" bug - - sambatar patches from Ricky - - printing.c patches from Dirk.DeWachter@rug.ac.be - - rewrote become_user() - - sunos5 patch from Niels.Baggesen@uni-c.dk - - more japanese extensions patches from fujita@ainix.isac.co.jp - - released alpha20 - - added force_user to conn struct - - -1.9.15: 14/11/95 - - removed bcast override from workgroup announce in nmbd - - aix patch, added NO_SYSMOUNTH, from - lionel leston <102624.346@compuserve.com> - - quick fix in lp_string() to try and stop some core dumps - - added uid cache in connections structure - to make user level security faster - - changed dos_mode() to show read-only on read-only shares only if - user w bit not set - - added check to stop exit_server() looping - - core dump fix in string_sub() - - fix client bug for long dirs in NT1 mode. - Thanks to Erwin Authried (erwin@ws1.atv.tuwien.ac.at) - - switched to a safer (but probably slower) readbraw implementation - - released p1 - - readbraw fix from Stefaan.Eeckels@eunet.lu - - fixed groups bug when user is in 1 group - - fixed NT1 dir bug - - changed default protocol in client to NT1 - - changed trans2 to not return both names in long listing if long - name is 8.3 - - made stat of "" return RONLY if not writeable drive - - wrapped strcpy() to stop nulls propogating (hack) - - made rename and unlink look at share locks on file - - clitar memory leak fix from jjm@jjm.com - - added -p option to smbstatus to list smbd processes - - added rename to the client - - released p2 - - fixed SMBmv for case where the destination exists - - man page patch from michal@ellpspace.math.ualberta.ca (Michal Jaegermann) - - once again redid the time handling, but finally explained what - is going on, this is written up in TIME.txt. The "kludge-GMT" used - by NT is a bastard and led to a lot of the confusion - - kanji patch from fujita@ainix.isac.co.jp (Takashi Fujita) - - is08859-1 patches from eauth@mail.cso.co.at - - starting rewriting nmbd, new nmbd is nmbd2, old one still around - for time being - - released p3 - - rewrote more of nmbd2 to use new structures - - CLIX patches from Jason.J.Faultless@bechtel.btx400.co.uk - - DirCacheFlush() bugfix from Michael Joosten - <joost@ori.cadlab.de>. This bug explains a lot of the crashes. - - fixed a bug in ChDir() that caused reversion to / in some - situations - - ipc fix from Magnus Hyllander <mhy@os.se> - - released p4 - - smbpasswd fix from Jeremy - - compilation fixes from Magnus Hyllander <mhy@os.se> - - added NetServerEnum to ipc.c (needed for master browser stuff) - - Makefile fix from Gunther Mayer <gmayer@physik.uni-kl.de> - - cleanups for clean compile on several OSes - - added browse mastering code - - started integration with smb.conf for nmbd2 - - released p5 - - fixed death_time (should be t+ttl*3) - - fixed non-removal of dead servers - - added smbstatus -u patch from oskarh@spornet.is (Oskar Hannesson) - - NETGROUP fix from J.W.Schilperoort@research.kpn.com - - select and NO_SETGROUPS patches from lennylim@netcom.com (Lenny - Lim) - - added LINKS_READ_ONLY define in dos_mode() for LM/X - compatability - - "dir a.c" bug fixed thanks to roderich@nodebonn.muc.bmw.de - (Roderich Schupp) - - job cancel fix in client from peo@mtek.chalmers.se - - changed nmbd2 to nmbd - - fixed "dir a*" under trans2 lookups - - added StrnCaseCmp() - - updated docs a bit for new browsing stuff - - updated INSTALL.txt - - hopefully fixed server level security with WfWg - -1.9.15 (patches): - - major/minor fix for solaris from Jeroen Schipper - <Jeroen.Schipper@let.ruu.nl> - - fixed critical bug in directory listings - - released p1 - - fixed one of the causes of "out of memory" while browsing - - fixed manpage install script (Paul Blackman) - - added DNS failures to name cache - - fixed writebmpx bug (affects OS/2) - - misc OS/2 fixes, mostly for EA handling - - added SMBcopy - - added "max ttl" option - - arch detection patch from Bas Laarhoven <bas@vimec.nl> - - released p2 - - another OS/2 fix - the level 4 getpathinfo for EAs - - added "alternate permissions" option - - changed client to parse destination names into name + domain - - fixed problem with PrimaryGroup and lmhosts loading - - added domain master ability to nmbd - - added "domain master" option - - added "domain controller" option and code - - pwd fix to client from Erik Devriendt (de@te6.siemens.be) - - fixed problem in smbmv that led to ar not working in mks - - added transs2 - - released p3 - - updated email addresses - - fix for innetgr from Olaf Seibert (rhialto@polder.ubc.kun.nl) - - client translate fix from bandc@dircon.co.uk - - netbsd bcast fix from from Olaf Seibert (rhialto@polder.ubc.kun.nl) - - syslog code from Alex Nash <alex@fa.tca.com> - - strip dot fix from Arne Ansper <arne@ioc.ee> - - added addtosmbpass + man page from - michal@ellpspace.math.ualberta.ca (Michal Jaegermann) - - pcap fix for AIX from Jon Christiansen <jchristi@sctcorp.com> - - fixed servertype bug in remote announcements - - fixed up illegal name checks (should also be faster) - - kanji patches from fujita@ainix.isac.co.jp (Takashi Fujita) - - fixed bug handling non-encrypted passwords - - released p4 - - fixed makefile for addtosmbpass - - DCE/DFS fixes from John Brezak (brezak@ch.hp.com) - - client patch for partial command matching from Andrew Wiseman - <bandc@dircon.co.uk> - - made is_8_3() handle full paths - - rewrote open_file_shared() with help from Charles Hoch - <hoch@hplcgh.hpl.hp.com> - - changed syslog to handle interactive programs - - fixed syslog problem with full path in argv[0] - - illegal name fixup for kanji from fujita@ainix.isac.co.jp - - fixed server level security to allow fallback to encryption - - changed reply_read() and reply_lockread() to ignore clients - smb_bufsize in order to handle broken lanman clients - - fixed NT wildcard problem with old style programs - - man page patches from "John M. Sellens" - <jmsellen@watdragon.uwaterloo.ca> - - partially documented the "character set" option - - changed default for MAXDIR to 64 - - changed default DPTR idle time to 120 - - released p5 - - QNX patches from eldo@invisa.satlink.net (Eldo Loguzzo) - - made nmbd use the "max log size" option and changed log handling - code a bit - - sunos patches, remote protocol (%R) addition and arch detection - changes to stop compiler warning from Timothy Hunt <tim@fsg.com> - - fixed become_user() bug that led to incorrect permissions in - some situations. - - released p6 - - is_8_3() fix from Charles Hoch <hoch@hplcgh.hpl.hp.com> - - nmblib bugfix from gmk@mhcnet.att.com (George Kull) - - aix pcap fix from Jon Christiansen <jchristi@sctcorp.com> - - added explicit sig_pipe() in server.c - - added domain logins option (not fully implemented) - - added HAVE_GMTOFF code - - got rid of PM_MAXLINE - - minor client fix from goggi@eflir (Garðar Georg Nielsen) - - added SIGCLD_IGNORE for HPUX (from Tor Lillqvist - <tml@hemuli.tte.vtt.fi>) - - OSF/1 lpq patch from scooter@GENE.COM (Scooter Morris) - - NeXT patches from pmarcos@next.com (Paul Marcos) - - dstdiff patch to stop infinite loop from Erwin Authried (eauth@cso.co.at) - - password server option can now take a list of password servers - - patches to let samba run on OS/2 from Jason Rumney <jasonr@pec.co.nz> - - added domain logon and logon script suport - - SCO openserver 5 patches from Scott Michel <scottm@intime.intime.com> - - Makefile changes from Marty Leisner <leisner@sdsp.mc.xerox.com> - - chgpasswd changes from Roman Dumych <roman@nyxis.unibase.com> - for SVR4 - - GUEST_SESSSETUP change from David.Chappell@mail.cc.trincoll.edu - - released p7 - - moved SO_REUSEADDR before bind() (thanks to Thomas Bellman - <tbe@ivab.se>) - - added more flexible GUEST_SESSSETUP to local.h and restored - pre-p7 behaviour as default - - released p8 - -1.9.16: - - Makefile fix from Marty Leisner <leisner@sdsp.mc.xerox.com> - - added %g and %G substitutions - - changed IDLE_CLOSED_TIMEOUT to 60 - - fixed the "admin user" status in domain logons - - hpux 10 "trusted security" patches from David-Michael Lincke - (dlincke@sgcl1.unisg.ch) - - added nmb lookups to client from Adrian Hill <Adrian.Hill@softimage.co.uk> - - svr4 pause/resume printing patch from Brendan O'Dea (bod@tyndall.com.au) - - fixed master announcement thanks to Luke Leighton <rah14@dial.pipex.com> - - changed srcdir usage in Makefile to be friendly to more systems - - NT4 alignment patches from Jeremy Allison (jra@vantive.com) - - updated share mode code for new spec - - minor client bugfix (for smbclient '\\\') - - fix for level 260 when magling disabled. From Martin Tomes - <Martin.Tomes@ecl.etherm.co.uk> - - SMBtranss2 fix for OS/2 from Jeremy Allison - - profiles fixup from Timm Wetzel <twetzel@cage.mpibpc.gwdg.de> - - man page updates from Dirk.DeWachter@rug.ac.be - - nmbsync fix from Andy Whitcroft <andy@soi.city.ac.uk> - - Lynx patches from Manfred Woelfel <woelfel@hpesco1.fzk.de> - - new smbtar stuff from Ricky - - changed to share mode DENY_NONE for tar - - fixed -D option of smbclient when in tar mode - - added aARCH to open modes - - added code to cope with select/read errors - - fixed blank browse entries after smb.conf reread - - integrated new browse stuff from Luke into ipc.c - - added workgroup list to smbclient -L - - improved archive attribute handling in close_file() and - write_file() - - smbtar fixes from Martin.Kraemer@mch.sni.de - - Linux quota patch from xeno@mix.hsv.no - - try to work around NT passlen2 problem in session setup - - released alpha1 - -NOTE: From now on the cvs.log file will be used to give a complete log of -changes to samba. This change-log is now obsolete. - - -========== -todo: - - -64 bit longs and IP addresses may give problems with unsigned longs? - -set archive bit whenever file is modified?? - -fix man page dates - -reply only to own workgroup in server enum - -patch to compile with g++ and possibly solaris c++ - -nmbd needs to keep browse list uptodate by talking to the master if it loses -an election as others may still think its a valid backup and use it to get -lists. - -leftover lock files can end up belonging to non-smbd processes after a reboot. - -hosts allow in nmbd - -hosts allow cache - -add password command in smbclient - -drag long filename to samba under os/2 gives short name - -document max ttl option - -dup/close 0 for getopt? - -implement SMBmove ?? - -add option to print more info about locked files (full path, share name -etc) - -very slow listing CD, perhaps because of order of stat and readdir or add -masking to opendir? - -protocol drop back in client to avoid openX etc. - -handle exported fat drives to a long filename capable client - -add check for existance of lpq commands etc (use stat?) - -get rid of the silly +4 and -4 by removing NBT stuff - -write-only shares - -document cnvchar stuff - -allow smbd to serve user and group lists to win95 - -document homes behaviour with WinDD - -add "hide file = *.o" "hide dir = .Foo*" "show file = xx*" type options. - -ALLOW_PASSWORD_CHANGE only compiles/works on some systems - -weird foooooooo/open.exe bug on NT - -%a detection can't detect Win95 versus WinNT - -reverse mangled maps, so (*.html *.htm) works for new files. - -install problems with w95. could be some sort of race? - -more efficient Files[] structure to handle thousands of open files - -lpd stuff: - Tony Aiuto (tony@ics.com) - -make max disk size local - diff --git a/source/client/client.c b/source/client/client.c deleted file mode 100644 index c7e00c45150..00000000000 --- a/source/client/client.c +++ /dev/null @@ -1,4870 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB client - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifdef SYSLOG -#undef SYSLOG -#endif - -#include "includes.h" - -#ifndef REGISTER -#define REGISTER 0 -#endif - -pstring cur_dir = "\\"; -pstring cd_path = ""; -pstring service=""; -pstring desthost=""; -extern pstring myname; -pstring password = ""; -pstring username=""; -pstring workgroup=""; -char *cmdstr=""; -BOOL got_pass = False; -BOOL connect_as_printer = False; -BOOL connect_as_ipc = False; -extern struct in_addr ipzero; - -char cryptkey[8]; -BOOL doencrypt=False; - -extern pstring user_socket_options; - -/* 30 second timeout on most commands */ -#define CLIENT_TIMEOUT (30*1000) -#define SHORT_TIMEOUT (5*1000) - -/* value for unused fid field in trans2 secondary request */ -#define FID_UNUSED (0xFFFF) - -int name_type = 0x20; - -int max_protocol = PROTOCOL_NT1; - - -time_t newer_than = 0; -int archive_level = 0; - -extern pstring debugf; -extern int DEBUGLEVEL; - -BOOL translation = False; - - -static BOOL send_trans_request(char *outbuf,int trans, - char *name,int fid,int flags, - char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup, - int mdata,int mparam,int msetup); -static BOOL receive_trans_response(char *inbuf,int trans, - int *data_len,int *param_len, - char **data,char **param); -static int interpret_long_filename(int level,char *p,file_info *finfo); -static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir); -static int interpret_short_filename(char *p,file_info *finfo); -static BOOL call_api(int prcnt,int drcnt, - int mprcnt,int mdrcnt, - int *rprcnt,int *rdrcnt, - char *param,char *data, - char **rparam,char **rdata); - - -/* clitar bits insert */ -extern int blocksize; -extern BOOL tar_inc; -extern BOOL tar_reset; -/* clitar bits end */ - - -int cnum = 0; -int pid = 0; -int gid = 0; -int uid = 0; -int mid = 0; -int myumask = 0755; - -int max_xmit = BUFFER_SIZE; - -extern pstring scope; - -BOOL prompt = True; - -int printmode = 1; - -BOOL recurse = False; -BOOL lowercase = False; - -BOOL have_ip = False; - -struct in_addr dest_ip; - -#define SEPARATORS " \t\n\r" - -BOOL abort_mget = True; - -extern int Protocol; - -BOOL readbraw_supported = False; -BOOL writebraw_supported = False; - -pstring fileselection = ""; - -extern file_info def_finfo; - -/* timing globals */ -int get_total_size = 0; -int get_total_time_ms = 0; -int put_total_size = 0; -int put_total_time_ms = 0; - - -extern int Client; - -#define USENMB - -#ifdef KANJI -extern int coding_system; -#define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False)) -#define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True)) -static BOOL -setup_term_code (char *code) -{ - int new; - new = interpret_coding_system (code, UNKNOWN_CODE); - if (new != UNKNOWN_CODE) { - coding_system = new; - return True; - } - return False; -} -#else -#define CNV_LANG(s) dos2unix_format(s,False) -#define CNV_INPUT(s) unix2dos_format(s,True) -#endif - -/**************************************************************************** -setup basics in a outgoing packet -****************************************************************************/ -void setup_pkt(char *outbuf) -{ - SSVAL(outbuf,smb_pid,pid); - SSVAL(outbuf,smb_uid,uid); - SSVAL(outbuf,smb_mid,mid); - if (Protocol > PROTOCOL_COREPLUS) - { - SCVAL(outbuf,smb_flg,0x8); - SSVAL(outbuf,smb_flg2,0x1); - } -} - -/**************************************************************************** -write to a local file with CR/LF->LF translation if appropriate. return the -number taken from the buffer. This may not equal the number written. -****************************************************************************/ -static int writefile(int f, char *b, int n) -{ - int i; - - if (!translation) - return(write(f,b,n)); - - i = 0; - while (i < n) - { - if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') - { - b++;i++; - } - if (write(f, b, 1) != 1) - { - break; - } - b++; - i++; - } - - return(i); -} - -/**************************************************************************** - read from a file with LF->CR/LF translation if appropriate. return the - number read. read approx n bytes. -****************************************************************************/ -static int readfile(char *b, int size, int n, FILE *f) -{ - int i; - int c; - - if (!translation || (size != 1)) - return(fread(b,size,n,f)); - - i = 0; - while (i < n) - { - if ((c = getc(f)) == EOF) - { - break; - } - - if (c == '\n') /* change all LFs to CR/LF */ - { - b[i++] = '\r'; - n++; - } - - b[i++] = c; - } - - return(i); -} - - -/**************************************************************************** -read from a file with print translation. return the number read. read approx n -bytes. -****************************************************************************/ -static int printread(FILE *f,char *b,int n) -{ - int i; - - i = readfile(b,1, n-1,f); -#if FORMFEED - if (feof(f) && i>0) - b[i++] = '\014'; -#endif - - return(i); -} - -/**************************************************************************** -check for existance of a dir -****************************************************************************/ -static BOOL chkpath(char *path,BOOL report) -{ - fstring path2; - pstring inbuf,outbuf; - char *p; - - strcpy(path2,path); - trim_string(path2,NULL,"\\"); - if (!*path2) *path2 = '\\'; - - bzero(outbuf,smb_size); - set_message(outbuf,0,4 + strlen(path2),True); - SCVAL(outbuf,smb_com,SMBchkpth); - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,path2); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (report && CVAL(inbuf,smb_rcls) != 0) - DEBUG(2,("chkpath: %s\n",smb_errstr(inbuf))); - - return(CVAL(inbuf,smb_rcls) == 0); -} - - -/**************************************************************************** -send a message -****************************************************************************/ -static void send_message(char *inbuf,char *outbuf) -{ - int total_len = 0; - - char *p; - int grp_id; - - /* send a SMBsendstrt command */ - bzero(outbuf,smb_size); - set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = SMBsendstrt; - SSVAL(outbuf,smb_tid,cnum); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,username); - p = skip_string(p,1); - *p++ = 4; - strcpy(p,desthost); - p = skip_string(p,1); - - set_message(outbuf,0,PTR_DIFF(p,smb_buf(outbuf)),False); - - send_smb(Client,outbuf); - - - if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - { - printf("SMBsendstrt failed. (%s)\n",smb_errstr(inbuf)); - return; - } - - grp_id = SVAL(inbuf,smb_vwv0); - - printf("Connected. Type your message, ending it with a Control-D\n"); - - while (!feof(stdin) && total_len < 1600) - { - int maxlen = MIN(1600 - total_len,127); - pstring msg; - int l=0; - int c; - - bzero(msg,smb_size); - - for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) - { - if (c == '\n') - msg[l++] = '\r'; - msg[l] = c; - } - - CVAL(outbuf,smb_com) = SMBsendtxt; - - set_message(outbuf,1,l+3,True); - - SSVAL(outbuf,smb_vwv0,grp_id); - - p = smb_buf(outbuf); - *p = 1; - SSVAL(p,1,l); - memcpy(p+3,msg,l); - - send_smb(Client,outbuf); - - - if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - { - printf("SMBsendtxt failed (%s)\n",smb_errstr(inbuf)); - return; - } - - total_len += l; - } - - if (total_len >= 1600) - printf("the message was truncated to 1600 bytes "); - else - printf("sent %d bytes ",total_len); - - printf("(status was %d-%d)\n",CVAL(inbuf,smb_rcls),SVAL(inbuf,smb_err)); - - CVAL(outbuf,smb_com) = SMBsendend; - set_message(outbuf,1,0,False); - SSVAL(outbuf,smb_vwv0,grp_id); - - send_smb(Client,outbuf); - - - if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - { - printf("SMBsendend failed (%s)\n",smb_errstr(inbuf)); - return; - } -} - - - -/**************************************************************************** -check the space on a device -****************************************************************************/ -static void do_dskattr(void) -{ - pstring inbuf,outbuf; - - bzero(outbuf,smb_size); - set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = SMBdskattr; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - DEBUG(0,("Error in dskattr: %s\n",smb_errstr(inbuf))); - - DEBUG(0,("\n\t\t%d blocks of size %d. %d blocks available\n", - SVAL(inbuf,smb_vwv0), - SVAL(inbuf,smb_vwv1)*SVAL(inbuf,smb_vwv2), - SVAL(inbuf,smb_vwv3))); -} - -/**************************************************************************** -show cd/pwd -****************************************************************************/ -static void cmd_pwd(void) -{ - DEBUG(0,("Current directory is %s",CNV_LANG(service))); - DEBUG(0,("%s\n",CNV_LANG(cur_dir))); -} - - -/**************************************************************************** -change directory - inner section -****************************************************************************/ -static void do_cd(char *newdir) -{ - char *p = newdir; - pstring saved_dir; - pstring dname; - - /* Save the current directory in case the - new directory is invalid */ - strcpy(saved_dir, cur_dir); - if (*p == '\\') - strcpy(cur_dir,p); - else - strcat(cur_dir,p); - if (*(cur_dir+strlen(cur_dir)-1) != '\\') { - strcat(cur_dir, "\\"); - } - dos_clean_name(cur_dir); - strcpy(dname,cur_dir); - strcat(cur_dir,"\\"); - dos_clean_name(cur_dir); - - if (!strequal(cur_dir,"\\")) - if (!chkpath(dname,True)) - strcpy(cur_dir,saved_dir); - - strcpy(cd_path,cur_dir); -} - -/**************************************************************************** -change directory -****************************************************************************/ -static void cmd_cd(char *inbuf,char *outbuf) -{ - fstring buf; - - if (next_token(NULL,buf,NULL)) - do_cd(buf); - else - DEBUG(0,("Current directory is %s\n",CNV_LANG(cur_dir))); -} - - -/**************************************************************************** - display info about a file - ****************************************************************************/ -static void display_finfo(file_info *finfo) -{ - time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ - DEBUG(0,(" %-30s%7.7s%10d %s", - CNV_LANG(finfo->name), - attrib_string(finfo->mode), - finfo->size, - asctime(LocalTime(&t)))); -} - - -/**************************************************************************** - do a directory listing, calling fn on each file found. Use the TRANSACT2 - call for long filenames - ****************************************************************************/ -static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) -{ - int max_matches = 512; - int info_level = Protocol<PROTOCOL_NT1?1:260; /* NT uses 260, OS/2 uses 2. Both accept 1. */ - char *p; - pstring mask; - file_info finfo; - int i; - char *dirlist = NULL; - int dirlist_len = 0; - int total_received = 0; - BOOL First = True; - char *resp_data=NULL; - char *resp_param=NULL; - int resp_data_len = 0; - int resp_param_len=0; - - int ff_resume_key = 0; - int ff_searchcount=0; - int ff_eos=0; - int ff_lastname=0; - int ff_dir_handle=0; - int loop_count = 0; - - uint16 setup; - pstring param; - - strcpy(mask,Mask); - - while (ff_eos == 0) - { - loop_count++; - if (loop_count > 200) - { - DEBUG(0,("ERROR: Looping in FIND_NEXT??\n")); - break; - } - - if (First) - { - setup = TRANSACT2_FINDFIRST; - SSVAL(param,0,attribute); /* attribute */ - SSVAL(param,2,max_matches); /* max count */ - SSVAL(param,4,8+4+2); /* resume required + close on end + continue */ - SSVAL(param,6,info_level); - SIVAL(param,8,0); - strcpy(param+12,mask); - } - else - { - setup = TRANSACT2_FINDNEXT; - SSVAL(param,0,ff_dir_handle); - SSVAL(param,2,max_matches); /* max count */ - SSVAL(param,4,info_level); - SIVAL(param,6,ff_resume_key); /* ff_resume_key */ - SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ - strcpy(param+12,mask); - - DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", - ff_dir_handle,ff_resume_key,ff_lastname,mask)); - } - /* ??? original code added 1 pad byte after param */ - - send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, - NULL,param,&setup, - 0,12+strlen(mask)+1,1, - BUFFER_SIZE,10,0); - - if (!receive_trans_response(inbuf,SMBtrans2, - &resp_data_len,&resp_param_len, - &resp_data,&resp_param)) - { - DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf))); - break; - } - - /* parse out some important return info */ - p = resp_param; - if (First) - { - ff_dir_handle = SVAL(p,0); - ff_searchcount = SVAL(p,2); - ff_eos = SVAL(p,4); - ff_lastname = SVAL(p,8); - } - else - { - ff_searchcount = SVAL(p,0); - ff_eos = SVAL(p,2); - ff_lastname = SVAL(p,6); - } - - if (ff_searchcount == 0) - break; - - /* point to the data bytes */ - p = resp_data; - - /* we might need the lastname for continuations */ - if (ff_lastname > 0) - { - switch(info_level) - { - case 260: - ff_resume_key =0; - StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname); - /* strcpy(mask,p+ff_lastname+94); */ - break; - case 1: - strcpy(mask,p + ff_lastname + 1); - ff_resume_key = 0; - break; - } - } - else - strcpy(mask,""); - - /* and add them to the dirlist pool */ - dirlist = Realloc(dirlist,dirlist_len + resp_data_len); - - if (!dirlist) - { - DEBUG(0,("Failed to expand dirlist\n")); - break; - } - - /* put in a length for the last entry, to ensure we can chain entries - into the next packet */ - { - char *p2; - for (p2=p,i=0;i<(ff_searchcount-1);i++) - p2 += interpret_long_filename(info_level,p2,NULL); - SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p)); - } - - /* grab the data for later use */ - memcpy(dirlist+dirlist_len,p,resp_data_len); - dirlist_len += resp_data_len; - - total_received += ff_searchcount; - - if (resp_data) free(resp_data); resp_data = NULL; - if (resp_param) free(resp_param); resp_param = NULL; - - DEBUG(3,("received %d entries (eos=%d resume=%d)\n", - ff_searchcount,ff_eos,ff_resume_key)); - - First = False; - } - - if (!fn) - for (p=dirlist,i=0;i<total_received;i++) - { - p += interpret_long_filename(info_level,p,&finfo); - display_finfo(&finfo); - } - - for (p=dirlist,i=0;i<total_received;i++) - { - p += interpret_long_filename(info_level,p,&finfo); - dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,True); - } - - /* free up the dirlist buffer */ - if (dirlist) free(dirlist); - return(total_received); -} - - -/**************************************************************************** - do a directory listing, calling fn on each file found - ****************************************************************************/ -static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) -{ - char *p; - int received = 0; - BOOL first = True; - char status[21]; - int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE; - int num_received = 0; - int i; - char *dirlist = NULL; - pstring mask; - file_info finfo; - - finfo = def_finfo; - - bzero(status,21); - - strcpy(mask,Mask); - - while (1) - { - bzero(outbuf,smb_size); - if (first) - set_message(outbuf,2,5 + strlen(mask),True); - else - set_message(outbuf,2,5 + 21,True); - -#if FFIRST - if (Protocol >= PROTOCOL_LANMAN1) - CVAL(outbuf,smb_com) = SMBffirst; - else -#endif - CVAL(outbuf,smb_com) = SMBsearch; - - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,num_asked); - SSVAL(outbuf,smb_vwv1,attribute); - - p = smb_buf(outbuf); - *p++ = 4; - - if (first) - strcpy(p,mask); - else - strcpy(p,""); - p += strlen(p) + 1; - - *p++ = 5; - if (first) - SSVAL(p,0,0); - else - { - SSVAL(p,0,21); - p += 2; - memcpy(p,status,21); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - received = SVAL(inbuf,smb_vwv0); - - DEBUG(5,("dir received %d\n",received)); - - DEBUG(6,("errstr=%s\n",smb_errstr(inbuf))); - - if (received <= 0) break; - - first = False; - - dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE); - - if (!dirlist) - return 0; - - p = smb_buf(inbuf) + 3; - - memcpy(dirlist+num_received*DIR_STRUCT_SIZE, - p,received*DIR_STRUCT_SIZE); - - memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21); - - num_received += received; - - if (CVAL(inbuf,smb_rcls) != 0) break; - } - -#if FFIRST - if (!first && Protocol >= PROTOCOL_LANMAN1) - { - bzero(outbuf,smb_size); - CVAL(outbuf,smb_com) = SMBfclose; - - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - - strcpy(p,""); - p += strlen(p) + 1; - - *p++ = 5; - SSVAL(p,0,21); - p += 2; - memcpy(p,status,21); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf))); - } -#endif - - if (!fn) - for (p=dirlist,i=0;i<num_received;i++) - { - p += interpret_short_filename(p,&finfo); - display_finfo(&finfo); - } - - for (p=dirlist,i=0;i<num_received;i++) - { - p += interpret_short_filename(p,&finfo); - dir_action(inbuf,outbuf,attribute,&finfo,recurse_dir,fn,False); - } - - if (dirlist) free(dirlist); - return(num_received); -} - - - -/**************************************************************************** - do a directory listing, calling fn on each file found - ****************************************************************************/ -void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) -{ - DEBUG(5,("do_dir(%s,%x,%s)\n",Mask,attribute,BOOLSTR(recurse_dir))); - if (Protocol >= PROTOCOL_LANMAN2) - { - if (do_long_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir) > 0) - return; - } - - expand_mask(Mask,False); - do_short_dir(inbuf,outbuf,Mask,attribute,fn,recurse_dir); - return; -} - -/******************************************************************* - decide if a file should be operated on - ********************************************************************/ -static BOOL do_this_one(file_info *finfo) -{ - if (finfo->mode & aDIR) return(True); - - if (newer_than && finfo->mtime < newer_than) - return(False); - - if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) - return(False); - - return(True); -} - - -/***************************************************************************** - Convert a character pointer in a call_api() response to a form we can use. - This function contains code to prevent core dumps if the server returns - invalid data. -*****************************************************************************/ -static char *fix_char_ptr(unsigned int datap, unsigned int converter, char *rdata, int rdrcnt) -{ -if( datap == 0 ) /* turn NULL pointers */ - { /* into zero length strings */ - return ""; - } -else - { - unsigned int offset = datap - converter; - - if( offset >= rdrcnt ) - { - DEBUG(1,("bad char ptr: datap=%u, converter=%u, rdata=%u, rdrcnt=%d>", datap, converter, (unsigned)rdata, rdrcnt)); - return "<ERROR>"; - } - else - { - return &rdata[offset]; - } - } -} - -/**************************************************************************** -interpret a short filename structure -The length of the structure is returned -****************************************************************************/ -static int interpret_short_filename(char *p,file_info *finfo) -{ - finfo->mode = CVAL(p,21); - - /* this date is converted to GMT by make_unix_date */ - finfo->ctime = make_unix_date(p+22); - finfo->mtime = finfo->atime = finfo->ctime; - finfo->size = IVAL(p,26); - strcpy(finfo->name,p+30); - - return(DIR_STRUCT_SIZE); -} - -/**************************************************************************** -interpret a long filename structure - this is mostly guesses at the moment -The length of the structure is returned -The structure of a long filename depends on the info level. 260 is used -by NT and 2 is used by OS/2 -****************************************************************************/ -static int interpret_long_filename(int level,char *p,file_info *finfo) -{ - if (finfo) - memcpy(finfo,&def_finfo,sizeof(*finfo)); - - switch (level) - { - case 1: /* OS/2 understands this */ - if (finfo) - { - /* these dates are converted to GMT by make_unix_date */ - finfo->ctime = make_unix_date2(p+4); - finfo->atime = make_unix_date2(p+8); - finfo->mtime = make_unix_date2(p+12); - finfo->size = IVAL(p,16); - finfo->mode = CVAL(p,24); - strcpy(finfo->name,p+27); - } - return(28 + CVAL(p,26)); - - case 2: /* this is what OS/2 uses mostly */ - if (finfo) - { - /* these dates are converted to GMT by make_unix_date */ - finfo->ctime = make_unix_date2(p+4); - finfo->atime = make_unix_date2(p+8); - finfo->mtime = make_unix_date2(p+12); - finfo->size = IVAL(p,16); - finfo->mode = CVAL(p,24); - strcpy(finfo->name,p+31); - } - return(32 + CVAL(p,30)); - - /* levels 3 and 4 are untested */ - case 3: - if (finfo) - { - /* these dates are probably like the other ones */ - finfo->ctime = make_unix_date2(p+8); - finfo->atime = make_unix_date2(p+12); - finfo->mtime = make_unix_date2(p+16); - finfo->size = IVAL(p,20); - finfo->mode = CVAL(p,28); - strcpy(finfo->name,p+33); - } - return(SVAL(p,4)+4); - - case 4: - if (finfo) - { - /* these dates are probably like the other ones */ - finfo->ctime = make_unix_date2(p+8); - finfo->atime = make_unix_date2(p+12); - finfo->mtime = make_unix_date2(p+16); - finfo->size = IVAL(p,20); - finfo->mode = CVAL(p,28); - strcpy(finfo->name,p+37); - } - return(SVAL(p,4)+4); - - case 260: /* NT uses this, but also accepts 2 */ - if (finfo) - { - int ret = SVAL(p,0); - int namelen; - p += 4; /* next entry offset */ - p += 4; /* fileindex */ - - /* these dates appear to arrive in a weird way. It seems to - be localtime plus the serverzone given in the initial - connect. This is GMT when DST is not in effect and one - hour from GMT otherwise. Can this really be right?? - - I suppose this could be called kludge-GMT. Is is the GMT - you get by using the current DST setting on a different - localtime. It will be cheap to calculate, I suppose, as - no DST tables will be needed */ - - finfo->ctime = interpret_long_date(p); p += 8; - finfo->atime = interpret_long_date(p); p += 8; - finfo->mtime = interpret_long_date(p); p += 8; p += 8; - finfo->size = IVAL(p,0); p += 8; - p += 8; /* alloc size */ - finfo->mode = CVAL(p,0); p += 4; - namelen = IVAL(p,0); p += 4; - p += 4; /* EA size */ - p += 2; /* short name len? */ - p += 24; /* short name? */ - StrnCpy(finfo->name,p,namelen); - return(ret); - } - return(SVAL(p,0)); - } - - DEBUG(1,("Unknown long filename format %d\n",level)); - return(SVAL(p,0)); -} - - - - -/**************************************************************************** - act on the files in a dir listing - ****************************************************************************/ -static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir) -{ - - if (!((finfo->mode & aDIR) == 0 && *fileselection && - !mask_match(finfo->name,fileselection,False,False)) && - !(recurse_dir && (strequal(finfo->name,".") || - strequal(finfo->name,"..")))) - { - if (recurse_dir && (finfo->mode & aDIR)) - { - pstring mask2; - pstring sav_dir; - strcpy(sav_dir,cur_dir); - strcat(cur_dir,finfo->name); - strcat(cur_dir,"\\"); - strcpy(mask2,cur_dir); - - if (!fn) - DEBUG(0,("\n%s\n",CNV_LANG(cur_dir))); - - strcat(mask2,"*"); - - if (longdir) - do_long_dir(inbuf,outbuf,mask2,attribute,fn,True); - else - do_dir(inbuf,outbuf,mask2,attribute,fn,True); - - strcpy(cur_dir,sav_dir); - } - else - { - if (fn && do_this_one(finfo)) - fn(finfo); - } - } -} - - -/**************************************************************************** - receive a SMB trans or trans2 response allocating the necessary memory - ****************************************************************************/ -static BOOL receive_trans_response(char *inbuf,int trans, - int *data_len,int *param_len, - char **data,char **param) -{ - int total_data=0; - int total_param=0; - int this_data,this_param; - - *data_len = *param_len = 0; - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - show_msg(inbuf); - - /* sanity check */ - if (CVAL(inbuf,smb_com) != trans) - { - DEBUG(0,("Expected %s response, got command 0x%02x\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); - return(False); - } - if (CVAL(inbuf,smb_rcls) != 0) - return(False); - - /* parse out the lengths */ - total_data = SVAL(inbuf,smb_tdrcnt); - total_param = SVAL(inbuf,smb_tprcnt); - - /* allocate it */ - *data = Realloc(*data,total_data); - *param = Realloc(*param,total_param); - - while (1) - { - this_data = SVAL(inbuf,smb_drcnt); - this_param = SVAL(inbuf,smb_prcnt); - if (this_data) - memcpy(*data + SVAL(inbuf,smb_drdisp), - smb_base(inbuf) + SVAL(inbuf,smb_droff), - this_data); - if (this_param) - memcpy(*param + SVAL(inbuf,smb_prdisp), - smb_base(inbuf) + SVAL(inbuf,smb_proff), - this_param); - *data_len += this_data; - *param_len += this_param; - - /* parse out the total lengths again - they can shrink! */ - total_data = SVAL(inbuf,smb_tdrcnt); - total_param = SVAL(inbuf,smb_tprcnt); - - if (total_data <= *data_len && total_param <= *param_len) - break; - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - show_msg(inbuf); - - /* sanity check */ - if (CVAL(inbuf,smb_com) != trans) - { - DEBUG(0,("Expected %s response, got command 0x%02x\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); - return(False); - } - if (CVAL(inbuf,smb_rcls) != 0) - return(False); - } - - return(True); -} - - -/**************************************************************************** - get a directory listing - ****************************************************************************/ -static void cmd_dir(char *inbuf,char *outbuf) -{ - int attribute = aDIR | aSYSTEM | aHIDDEN; - pstring mask; - fstring buf; - char *p=buf; - - strcpy(mask,cur_dir); - if(mask[strlen(mask)-1]!='\\') - strcat(mask,"\\"); - - if (next_token(NULL,buf,NULL)) - { - if (*p == '\\') - strcpy(mask,p); - else - strcat(mask,p); - } - else { - strcat(mask,"*"); - } - - do_dir(inbuf,outbuf,mask,attribute,NULL,recurse); - - do_dskattr(); -} - - - -/**************************************************************************** - get a file from rname to lname - ****************************************************************************/ -static void do_get(char *rname,char *lname,file_info *finfo1) -{ - int handle=0,fnum; - uint32 nread=0; - char *p; - BOOL newhandle = False; - char *inbuf,*outbuf; - file_info finfo; - BOOL close_done = False; - BOOL ignore_close_error = False; - char *dataptr=NULL; - int datalen=0; - - struct timeval tp_start; - GetTimeOfDay(&tp_start); - - if (finfo1) - finfo = *finfo1; - else - finfo = def_finfo; - - if (lowercase) - strlower(lname); - - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - bzero(outbuf,smb_size); - set_message(outbuf,15,1 + strlen(rname),True); - - CVAL(outbuf,smb_com) = SMBopenX; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,1); - SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4)); - SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN); - SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN); - SSVAL(outbuf,smb_vwv8,1); - - p = smb_buf(outbuf); - strcpy(p,rname); - p = skip_string(p,1); - - /* do a chained openX with a readX? */ -#if 1 - if (finfo.size > 0) - { - DEBUG(3,("Chaining readX wth openX\n")); - SSVAL(outbuf,smb_vwv0,SMBreadX); - SSVAL(outbuf,smb_vwv1,smb_offset(p,outbuf)); - bzero(p,200); - p -= smb_wct; - SSVAL(p,smb_wct,10); - SSVAL(p,smb_vwv0,0xFF); - SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size)); - SSVAL(p,smb_vwv9,MIN(BUFFER_SIZE,finfo.size)); - smb_setlen(outbuf,smb_len(outbuf)+11*2+1); - } -#endif - - if(!strcmp(lname,"-")) - handle = fileno(stdout); - else - { - handle = creat(lname,0644); - newhandle = True; - } - if (handle < 0) - { - DEBUG(0,("Error opening local file %s\n",lname)); - free(inbuf);free(outbuf); - return; - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - if (CVAL(inbuf,smb_rcls) == ERRSRV && - SVAL(inbuf,smb_err) == ERRnoresource && - reopen_connection(inbuf,outbuf)) - { - do_get(rname,lname,finfo1); - return; - } - DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname))); - if(newhandle) - close(handle); - free(inbuf);free(outbuf); - return; - } - - strcpy(finfo.name,rname); - - if (!finfo1) - { - finfo.mode = SVAL(inbuf,smb_vwv3); - /* these times arrive as LOCAL time, using the DST offset - corresponding to that time, we convert them to GMT */ - finfo.mtime = make_unix_date3(inbuf+smb_vwv4); - finfo.atime = finfo.ctime = finfo.mtime; - finfo.size = IVAL(inbuf,smb_vwv6); - } - - DEBUG(3,("file %s attrib 0x%X\n",CNV_LANG(finfo.name),finfo.mode)); - - fnum = SVAL(inbuf,smb_vwv2); - - /* we might have got some data from a chained readX */ - if (SVAL(inbuf,smb_vwv0) == SMBreadX) - { - p = (smb_base(inbuf)+SVAL(inbuf,smb_vwv1)) - smb_wct; - datalen = SVAL(p,smb_vwv5); - dataptr = smb_base(inbuf) + SVAL(p,smb_vwv6); - } - else - { - dataptr = NULL; - datalen = 0; - } - - - DEBUG(2,("getting file %s of size %d bytes as %s ", - CNV_LANG(finfo.name), - finfo.size, - lname)); - - while (nread < finfo.size && !close_done) - { - int method = -1; - static BOOL can_chain_close = True; - - p=NULL; - - DEBUG(3,("nread=%d max_xmit=%d fsize=%d\n",nread,max_xmit,finfo.size)); - - /* 3 possible read types. readbraw if a large block is required. - readX + close if not much left and read if neither is supported */ - - /* we might have already read some data from a chained readX */ - if (dataptr && datalen>0) - method=3; - - /* if we can finish now then readX+close */ - if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && - ((finfo.size - nread) < - (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300)))) - method = 0; - - /* if we support readraw then use that */ - if (method<0 && readbraw_supported) - method = 1; - - /* if we can then use readX */ - if (method<0 && (Protocol >= PROTOCOL_LANMAN1)) - method = 2; - - switch (method) - { - /* use readX */ - case 0: - case 2: - if (method == 0) - close_done = True; - - /* use readX + close */ - bzero(outbuf,smb_size); - set_message(outbuf,10,0,True); - CVAL(outbuf,smb_com) = SMBreadX; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - if (close_done) - { - CVAL(outbuf,smb_vwv0) = SMBclose; - SSVAL(outbuf,smb_vwv1,smb_offset(smb_buf(outbuf),outbuf)); - } - else - CVAL(outbuf,smb_vwv0) = 0xFF; - - SSVAL(outbuf,smb_vwv2,fnum); - SIVAL(outbuf,smb_vwv3,nread); - SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread)); - SSVAL(outbuf,smb_vwv6,0); - SIVAL(outbuf,smb_vwv7,0); - SSVAL(outbuf,smb_vwv9,MIN(BUFFER_SIZE,finfo.size-nread)); - - if (close_done) - { - p = smb_buf(outbuf); - bzero(p,9); - - CVAL(p,0) = 3; - SSVAL(p,1,fnum); - SIVALS(p,3,-1); - - /* now set the total packet length */ - smb_setlen(outbuf,smb_len(outbuf)+9); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf))); - break; - } - - if (close_done && - SVAL(inbuf,smb_vwv0) != SMBclose) - { - /* NOTE: WfWg sometimes just ignores the chained - command! This seems to break the spec? */ - DEBUG(3,("Rejected chained close?\n")); - close_done = False; - can_chain_close = False; - ignore_close_error = True; - } - - datalen = SVAL(inbuf,smb_vwv5); - dataptr = smb_base(inbuf) + SVAL(inbuf,smb_vwv6); - break; - - /* use readbraw */ - case 1: - { - static int readbraw_size = BUFFER_SIZE; - - extern int Client; - bzero(outbuf,smb_size); - set_message(outbuf,8,0,True); - CVAL(outbuf,smb_com) = SMBreadbraw; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - SSVAL(outbuf,smb_vwv0,fnum); - SIVAL(outbuf,smb_vwv1,nread); - SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size)); - SSVAL(outbuf,smb_vwv4,0); - SIVALS(outbuf,smb_vwv5,-1); - send_smb(Client,outbuf); - - /* Now read the raw data into the buffer and write it */ - if(read_smb_length(Client,inbuf,0) == -1) { - DEBUG(0,("Failed to read length in readbraw\n")); - exit(1); - } - - /* Even though this is not an smb message, smb_len - returns the generic length of an smb message */ - datalen = smb_len(inbuf); - - if (datalen == 0) - { - /* we got a readbraw error */ - DEBUG(4,("readbraw error - reducing size\n")); - readbraw_size = (readbraw_size * 9) / 10; - - if (readbraw_size < max_xmit) - { - DEBUG(0,("disabling readbraw\n")); - readbraw_supported = False; - } - - dataptr=NULL; - continue; - } - - if(read_data(Client,inbuf,datalen) != datalen) { - DEBUG(0,("Failed to read data in readbraw\n")); - exit(1); - } - dataptr = inbuf; - } - break; - - case 3: - /* we've already read some data with a chained readX */ - break; - - default: - /* use plain read */ - bzero(outbuf,smb_size); - set_message(outbuf,5,0,True); - CVAL(outbuf,smb_com) = SMBread; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread)); - SIVAL(outbuf,smb_vwv2,nread); - SSVAL(outbuf,smb_vwv4,finfo.size - nread); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf))); - break; - } - - datalen = SVAL(inbuf,smb_vwv0); - dataptr = smb_buf(inbuf) + 3; - break; - } - - if (writefile(handle,dataptr,datalen) != datalen) - { - DEBUG(0,("Error writing local file\n")); - break; - } - - nread += datalen; - if (datalen == 0) - { - DEBUG(0,("Error reading file %s. Got %d bytes\n",CNV_LANG(rname),nread)); - break; - } - - dataptr=NULL; - datalen=0; - } - - - - if (!close_done) - { - bzero(outbuf,smb_size); - set_message(outbuf,3,0,True); - CVAL(outbuf,smb_com) = SMBclose; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SIVALS(outbuf,smb_vwv1,-1); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf))); - if(newhandle) - close(handle); - free(inbuf);free(outbuf); - return; - } - } - - if(newhandle) - close(handle); - - if (archive_level >= 2 && (finfo.mode & aARCH)) { - bzero(outbuf,smb_size); - set_message(outbuf,8,strlen(rname)+4,True); - CVAL(outbuf,smb_com) = SMBsetatr; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH)); - SIVALS(outbuf,smb_vwv1,0); - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,rname); - p += strlen(p)+1; - *p++ = 4; - *p = 0; - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - } - - { - struct timeval tp_end; - int this_time; - - GetTimeOfDay(&tp_end); - this_time = - (tp_end.tv_sec - tp_start.tv_sec)*1000 + - (tp_end.tv_usec - tp_start.tv_usec)/1000; - get_total_time_ms += this_time; - get_total_size += finfo.size; - - DEBUG(1,("(%g kb/s) (average %g kb/s)\n", - finfo.size / (1.024*this_time + 1.0e-4), - get_total_size / (1.024*get_total_time_ms))); - } - - free(inbuf);free(outbuf); -} - - -/**************************************************************************** - get a file - ****************************************************************************/ -static void cmd_get(void) -{ - pstring lname; - pstring rname; - char *p; - - strcpy(rname,cur_dir); - strcat(rname,"\\"); - - p = rname + strlen(rname); - - if (!next_token(NULL,p,NULL)) { - DEBUG(0,("get <filename>\n")); - return; - } - strcpy(lname,p); - dos_clean_name(rname); - - next_token(NULL,lname,NULL); - - do_get(rname,lname,NULL); -} - - -/**************************************************************************** - do a mget operation on one file - ****************************************************************************/ -static void do_mget(file_info *finfo) -{ - pstring rname; - pstring quest; - - if (strequal(finfo->name,".") || strequal(finfo->name,"..")) - return; - - if (abort_mget) - { - DEBUG(0,("mget aborted\n")); - return; - } - - if (finfo->mode & aDIR) - sprintf(quest,"Get directory %s? ",CNV_LANG(finfo->name)); - else - sprintf(quest,"Get file %s? ",CNV_LANG(finfo->name)); - - if (prompt && !yesno(quest)) return; - - if (finfo->mode & aDIR) - { - pstring saved_curdir; - pstring mget_mask; - char *inbuf,*outbuf; - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - strcpy(saved_curdir,cur_dir); - - strcat(cur_dir,finfo->name); - strcat(cur_dir,"\\"); - - unix_format(finfo->name); - { - if (lowercase) - strlower(finfo->name); - - if (!directory_exist(finfo->name,NULL) && - sys_mkdir(finfo->name,0777) != 0) - { - DEBUG(0,("failed to create directory %s\n",CNV_LANG(finfo->name))); - strcpy(cur_dir,saved_curdir); - free(inbuf);free(outbuf); - return; - } - - if (sys_chdir(finfo->name) != 0) - { - DEBUG(0,("failed to chdir to directory %s\n",CNV_LANG(finfo->name))); - strcpy(cur_dir,saved_curdir); - free(inbuf);free(outbuf); - return; - } - } - - strcpy(mget_mask,cur_dir); - strcat(mget_mask,"*"); - - do_dir((char *)inbuf,(char *)outbuf, - mget_mask,aSYSTEM | aHIDDEN | aDIR,do_mget,False); - chdir(".."); - strcpy(cur_dir,saved_curdir); - free(inbuf);free(outbuf); - } - else - { - strcpy(rname,cur_dir); - strcat(rname,finfo->name); - do_get(rname,finfo->name,finfo); - } -} - -/**************************************************************************** -view the file using the pager -****************************************************************************/ -static void cmd_more(void) -{ - fstring rname,lname,tmpname,pager_cmd; - char *pager; - - strcpy(rname,cur_dir); - strcat(rname,"\\"); - sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid()); - strcpy(lname,tmpname); - - if (!next_token(NULL,rname+strlen(rname),NULL)) { - DEBUG(0,("more <filename>\n")); - return; - } - dos_clean_name(rname); - - do_get(rname,lname,NULL); - - pager=getenv("PAGER"); - sprintf(pager_cmd,"%s %s",(pager? pager:PAGER), tmpname); - system(pager_cmd); - unlink(tmpname); -} - - - -/**************************************************************************** -do a mget command -****************************************************************************/ -static void cmd_mget(char *inbuf,char *outbuf) -{ - int attribute = aSYSTEM | aHIDDEN; - pstring mget_mask; - fstring buf; - char *p=buf; - - *mget_mask = 0; - - if (recurse) - attribute |= aDIR; - - abort_mget = False; - - while (next_token(NULL,p,NULL)) - { - strcpy(mget_mask,cur_dir); - if(mget_mask[strlen(mget_mask)-1]!='\\') - strcat(mget_mask,"\\"); - - if (*p == '\\') - strcpy(mget_mask,p); - else - strcat(mget_mask,p); - do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False); - } - - if (! *mget_mask) - { - strcpy(mget_mask,cur_dir); - if(mget_mask[strlen(mget_mask)-1]!='\\') - strcat(mget_mask,"\\"); - strcat(mget_mask,"*"); - do_dir((char *)inbuf,(char *)outbuf,mget_mask,attribute,do_mget,False); - } -} - -/**************************************************************************** -make a directory of name "name" -****************************************************************************/ -static BOOL do_mkdir(char *name) -{ - char *p; - char *inbuf,*outbuf; - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return False; - } - - bzero(outbuf,smb_size); - set_message(outbuf,0,2 + strlen(name),True); - - CVAL(outbuf,smb_com) = SMBmkdir; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,name); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s making remote directory %s\n", - smb_errstr(inbuf),CNV_LANG(name))); - - free(inbuf);free(outbuf); - return(False); - } - - free(inbuf);free(outbuf); - return(True); -} - - -/**************************************************************************** - make a directory - ****************************************************************************/ -static void cmd_mkdir(char *inbuf,char *outbuf) -{ - pstring mask; - fstring buf; - char *p=buf; - - strcpy(mask,cur_dir); - - if (!next_token(NULL,p,NULL)) - { - if (!recurse) - DEBUG(0,("mkdir <dirname>\n")); - return; - } - strcat(mask,p); - - if (recurse) - { - pstring ddir; - pstring ddir2; - *ddir2 = 0; - - strcpy(ddir,mask); - trim_string(ddir,".",NULL); - p = strtok(ddir,"/\\"); - while (p) - { - strcat(ddir2,p); - if (!chkpath(ddir2,False)) - { - do_mkdir(ddir2); - } - strcat(ddir2,"\\"); - p = strtok(NULL,"/\\"); - } - } - else - do_mkdir(mask); -} - - -/******************************************************************* - write to a file using writebraw - ********************************************************************/ -static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n) -{ - extern int Client; - pstring inbuf; - - bzero(outbuf,smb_size); - bzero(inbuf,smb_size); - set_message(outbuf,Protocol>PROTOCOL_COREPLUS?12:10,0,True); - - CVAL(outbuf,smb_com) = SMBwritebraw; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,n); - SIVAL(outbuf,smb_vwv3,pos); - SSVAL(outbuf,smb_vwv7,1); - - send_smb(Client,outbuf); - - if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - return(0); - - _smb_setlen(buf-4,n); /* HACK! XXXX */ - - if (write_socket(Client,buf-4,n+4) != n+4) - return(0); - - if (!receive_smb(Client,inbuf,CLIENT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) { - DEBUG(0,("Error writing remote file (2)\n")); - return(0); - } - return(SVAL(inbuf,smb_vwv0)); -} - - - -/******************************************************************* - write to a file - ********************************************************************/ -static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n) -{ - pstring inbuf; - - if (writebraw_supported && n > (max_xmit-200)) - return(smb_writeraw(outbuf,fnum,pos,buf,n)); - - bzero(outbuf,smb_size); - bzero(inbuf,smb_size); - set_message(outbuf,5,n + 3,True); - - CVAL(outbuf,smb_com) = SMBwrite; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,n); - SIVAL(outbuf,smb_vwv2,pos); - SSVAL(outbuf,smb_vwv4,0); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,n); - - memcpy(smb_buf(outbuf)+3,buf,n); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) { - DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf))); - return(0); - } - return(SVAL(inbuf,smb_vwv0)); -} - - - -/**************************************************************************** - put a single file - ****************************************************************************/ -static void do_put(char *rname,char *lname,file_info *finfo) -{ - int fnum; - FILE *f; - int nread=0; - char *p; - char *inbuf,*outbuf; - time_t close_time = finfo->mtime; - char *buf=NULL; - static int maxwrite=0; - - struct timeval tp_start; - GetTimeOfDay(&tp_start); - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - bzero(outbuf,smb_size); - set_message(outbuf,3,2 + strlen(rname),True); - - if (finfo->mtime == 0 || finfo->mtime == -1) - finfo->mtime = finfo->atime = finfo->ctime = time(NULL); - - CVAL(outbuf,smb_com) = SMBcreate; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,finfo->mode); - put_dos_date3(outbuf,smb_vwv1,finfo->mtime); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,rname); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname))); - - free(inbuf);free(outbuf);if (buf) free(buf); - return; - } - - f = fopen(lname,"r"); - - if (!f) - { - DEBUG(0,("Error opening local file %s\n",lname)); - free(inbuf);free(outbuf); - return; - } - - - fnum = SVAL(inbuf,smb_vwv0); - if (finfo->size < 0) - finfo->size = file_size(lname); - - DEBUG(1,("putting file %s of size %d bytes as %s ",lname,finfo->size,CNV_LANG(rname))); - - if (!maxwrite) - maxwrite = writebraw_supported?MAX(max_xmit,BUFFER_SIZE):(max_xmit-200); - - while (nread < finfo->size) - { - int n = maxwrite; - int ret; - - n = MIN(n,finfo->size - nread); - - buf = (char *)Realloc(buf,n+4); - - fseek(f,nread,SEEK_SET); - if ((n = readfile(buf+4,1,n,f)) < 1) - { - DEBUG(0,("Error reading local file\n")); - break; - } - - ret = smb_writefile(outbuf,fnum,nread,buf+4,n); - - if (n != ret) { - if (!maxwrite) { - DEBUG(0,("Error writing file\n")); - break; - } else { - maxwrite /= 2; - continue; - } - } - - nread += n; - } - - - - bzero(outbuf,smb_size); - set_message(outbuf,3,0,True); - CVAL(outbuf,smb_com) = SMBclose; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - put_dos_date3(outbuf,smb_vwv1,close_time); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf),CNV_LANG(rname))); - fclose(f); - free(inbuf);free(outbuf); - if (buf) free(buf); - return; - } - - - fclose(f); - free(inbuf);free(outbuf); - if (buf) free(buf); - - { - struct timeval tp_end; - int this_time; - - GetTimeOfDay(&tp_end); - this_time = - (tp_end.tv_sec - tp_start.tv_sec)*1000 + - (tp_end.tv_usec - tp_start.tv_usec)/1000; - put_total_time_ms += this_time; - put_total_size += finfo->size; - - DEBUG(1,("(%g kb/s) (average %g kb/s)\n", - finfo->size / (1.024*this_time + 1.0e-4), - put_total_size / (1.024*put_total_time_ms))); - } -} - - - -/**************************************************************************** - put a file - ****************************************************************************/ -static void cmd_put(void) -{ - pstring lname; - pstring rname; - fstring buf; - char *p=buf; - file_info finfo; - finfo = def_finfo; - - strcpy(rname,cur_dir); - strcat(rname,"\\"); - - - if (!next_token(NULL,p,NULL)) - { - DEBUG(0,("put <filename>\n")); - return; - } - strcpy(lname,p); - - if (next_token(NULL,p,NULL)) - strcat(rname,p); - else - strcat(rname,lname); - - dos_clean_name(rname); - - { - struct stat st; - if (!file_exist(lname,&st)) { - DEBUG(0,("%s does not exist\n",lname)); - return; - } - finfo.mtime = st.st_mtime; - } - - do_put(rname,lname,&finfo); -} - -/**************************************************************************** - seek in a directory/file list until you get something that doesn't start with - the specified name - ****************************************************************************/ -static BOOL seek_list(FILE *f,char *name) -{ - pstring s; - while (!feof(f)) - { - if (fscanf(f,"%s",s) != 1) return(False); - trim_string(s,"./",NULL); - if (strncmp(s,name,strlen(name)) != 0) - { - strcpy(name,s); - return(True); - } - } - - return(False); -} - - -/**************************************************************************** - set the file selection mask - ****************************************************************************/ -static void cmd_select(void) -{ - strcpy(fileselection,""); - next_token(NULL,fileselection,NULL); -} - - -/**************************************************************************** - mput some files - ****************************************************************************/ -static void cmd_mput(void) -{ - pstring lname; - pstring rname; - file_info finfo; - fstring buf; - char *p=buf; - - finfo = def_finfo; - - - while (next_token(NULL,p,NULL)) - { - struct stat st; - pstring cmd; - pstring tmpname; - FILE *f; - - sprintf(tmpname,"%s/ls.smb.%d",tmpdir(),(int)getpid()); - if (recurse) - sprintf(cmd,"find . -name \"%s\" -print > %s",p,tmpname); - else - sprintf(cmd,"/bin/ls %s > %s",p,tmpname); - system(cmd); - - f = fopen(tmpname,"r"); - if (!f) continue; - - while (!feof(f)) - { - pstring quest; - - if (fscanf(f,"%s",lname) != 1) break; - trim_string(lname,"./",NULL); - - again1: - - /* check if it's a directory */ - if (directory_exist(lname,&st)) - { - if (!recurse) continue; - sprintf(quest,"Put directory %s? ",lname); - if (prompt && !yesno(quest)) - { - strcat(lname,"/"); - if (!seek_list(f,lname)) - break; - goto again1; - } - - strcpy(rname,cur_dir); - strcat(rname,lname); - if (!chkpath(rname,False) && !do_mkdir(rname)) { - strcat(lname,"/"); - if (!seek_list(f,lname)) - break; - goto again1; - } - - continue; - } - else - { - sprintf(quest,"Put file %s? ",lname); - if (prompt && !yesno(quest)) continue; - - strcpy(rname,cur_dir); - strcat(rname,lname); - } - dos_format(rname); - - /* null size so do_put knows to ignore it */ - finfo.size = -1; - - /* set the date on the file */ - finfo.mtime = st.st_mtime; - - do_put(rname,lname,&finfo); - } - fclose(f); - unlink(tmpname); - } -} - -/**************************************************************************** - cancel a print job - ****************************************************************************/ -static void do_cancel(int job) -{ - char *rparam = NULL; - char *rdata = NULL; - char *p; - int rdrcnt,rprcnt; - pstring param; - - bzero(param,sizeof(param)); - - p = param; - SSVAL(p,0,81); /* DosPrintJobDel() */ - p += 2; - strcpy(p,"W"); - p = skip_string(p,1); - strcpy(p,""); - p = skip_string(p,1); - SSVAL(p,0,job); - p += 2; - - if (call_api(PTR_DIFF(p,param),0, - 6,1000, - &rprcnt,&rdrcnt, - param,NULL, - &rparam,&rdata)) - { - int res = SVAL(rparam,0); - - if (!res) - printf("Job %d cancelled\n",job); - else - printf("Error %d calcelling job %d\n",res,job); - return; - } - else - printf("Server refused cancel request\n"); - - if (rparam) free(rparam); - if (rdata) free(rdata); - - return; -} - - -/**************************************************************************** - cancel a print job - ****************************************************************************/ -static void cmd_cancel(char *inbuf,char *outbuf ) -{ - fstring buf; - int job; - - if (!connect_as_printer) - { - DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n")); - DEBUG(0,("Trying to cancel print jobs without -P may fail\n")); - } - - if (!next_token(NULL,buf,NULL)) { - printf("cancel <jobid> ...\n"); - return; - } - do { - job = atoi(buf); - do_cancel(job); - } while (next_token(NULL,buf,NULL)); -} - - -/**************************************************************************** - get info on a file - ****************************************************************************/ -static void cmd_stat(char *inbuf,char *outbuf) -{ - fstring buf; - pstring param; - char *resp_data=NULL; - char *resp_param=NULL; - int resp_data_len = 0; - int resp_param_len=0; - char *p; - uint16 setup = TRANSACT2_QPATHINFO; - - if (!next_token(NULL,buf,NULL)) { - printf("stat <file>\n"); - return; - } - - bzero(param,6); - SSVAL(param,0,4); /* level */ - p = param+6; - strcpy(p,cur_dir); - strcat(p,buf); - - send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, - NULL,param,&setup, - 0,6 + strlen(p)+1,1, - BUFFER_SIZE,2,0); - - receive_trans_response(inbuf,SMBtrans2, - &resp_data_len,&resp_param_len, - &resp_data,&resp_param); - - if (resp_data) free(resp_data); resp_data = NULL; - if (resp_param) free(resp_param); resp_param = NULL; -} - - -/**************************************************************************** - print a file - ****************************************************************************/ -static void cmd_print(char *inbuf,char *outbuf ) -{ - int fnum; - FILE *f = NULL; - uint32 nread=0; - pstring lname; - pstring rname; - char *p; - - if (!connect_as_printer) - { - DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n")); - DEBUG(0,("Trying to print without -P may fail\n")); - } - - if (!next_token(NULL,lname,NULL)) - { - DEBUG(0,("print <filename>\n")); - return; - } - - strcpy(rname,lname); - p = strrchr(rname,'/'); - if (p) - { - pstring tname; - strcpy(tname,p+1); - strcpy(rname,tname); - } - - if ((int)strlen(rname) > 14) - rname[14] = 0; - - if (strequal(lname,"-")) - { - f = stdin; - strcpy(rname,"stdin"); - } - - dos_clean_name(rname); - - bzero(outbuf,smb_size); - set_message(outbuf,2,2 + strlen(rname),True); - - CVAL(outbuf,smb_com) = SMBsplopen; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0); - SSVAL(outbuf,smb_vwv1,printmode); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,rname); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s opening printer for %s\n",smb_errstr(inbuf),CNV_LANG(rname))); - return; - } - - if (!f) - f = fopen(lname,"r"); - if (!f) - { - DEBUG(0,("Error opening local file %s\n",lname)); - return; - } - - - fnum = SVAL(inbuf,smb_vwv0); - - DEBUG(1,("printing file %s as %s\n",lname,CNV_LANG(rname))); - - while (!feof(f)) - { - int n; - - bzero(outbuf,smb_size); - set_message(outbuf,1,3,True); - - /* for some strange reason the OS/2 print server can't handle large - packets when printing. weird */ - n = MIN(1024,max_xmit-(smb_len(outbuf)+4)); - - if (translation) - n = printread(f,smb_buf(outbuf)+3,(int)(0.95*n)); - else - n = readfile(smb_buf(outbuf)+3,1,n,f); - if (n <= 0) - { - DEBUG(0,("read gave %d\n",n)); - break; - } - - smb_setlen(outbuf,smb_len(outbuf) + n); - - CVAL(outbuf,smb_com) = SMBsplwr; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,n+3); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,n); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s printing remote file\n",smb_errstr(inbuf))); - break; - } - - nread += n; - } - - DEBUG(2,("%d bytes printed\n",nread)); - - bzero(outbuf,smb_size); - set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBsplclose; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s closing print file\n",smb_errstr(inbuf))); - if (f != stdin) - fclose(f); - return; - } - - if (f != stdin) - fclose(f); -} - -/**************************************************************************** -show a print queue - this is deprecated as it uses the old smb that -has limited support - the correct call is the cmd_p_queue_4() after this. -****************************************************************************/ -static void cmd_queue(char *inbuf,char *outbuf ) -{ - int count; - char *p; - - bzero(outbuf,smb_size); - set_message(outbuf,2,0,True); - - CVAL(outbuf,smb_com) = SMBsplretq; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */ - SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */ - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s obtaining print queue\n",smb_errstr(inbuf))); - return; - } - - count = SVAL(inbuf,smb_vwv0); - p = smb_buf(inbuf) + 3; - if (count <= 0) - { - DEBUG(0,("No entries in the print queue\n")); - return; - } - - { - char status[20]; - - DEBUG(0,("Job Name Size Status\n")); - - while (count--) - { - switch (CVAL(p,4)) - { - case 0x01: sprintf(status,"held or stopped"); break; - case 0x02: sprintf(status,"printing"); break; - case 0x03: sprintf(status,"awaiting print"); break; - case 0x04: sprintf(status,"in intercept"); break; - case 0x05: sprintf(status,"file had error"); break; - case 0x06: sprintf(status,"printer error"); break; - default: sprintf(status,"unknown"); break; - } - - DEBUG(0,("%-6d %-16.16s %-9d %s\n", - SVAL(p,5),p+12,IVAL(p,7),status)); - p += 28; - } - } - -} - - -/**************************************************************************** -show information about a print queue -****************************************************************************/ -static void cmd_p_queue_4(char *inbuf,char *outbuf ) -{ - char *rparam = NULL; - char *rdata = NULL; - char *p; - int rdrcnt, rprcnt; - pstring param; - int result_code=0; - - if (!connect_as_printer) - { - DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n")); - DEBUG(0,("Trying to print without -P may fail\n")); - } - - bzero(param,sizeof(param)); - - p = param; - SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */ - p += 2; - strcpy(p,"zWrLeh"); /* parameter description? */ - p = skip_string(p,1); - strcpy(p,"WWzWWDDzz"); /* returned data format */ - p = skip_string(p,1); - strcpy(p,strrchr(service,'\\')+1); /* name of queue */ - p = skip_string(p,1); - SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */ - SSVAL(p,2,1000); /* size of bytes of returned data buffer */ - p += 4; - strcpy(p,""); /* subformat */ - p = skip_string(p,1); - - DEBUG(1,("Calling DosPrintJobEnum()...\n")); - if( call_api(PTR_DIFF(p,param), 0, - 10, 4096, - &rprcnt, &rdrcnt, - param, NULL, - &rparam, &rdata) ) - { - int converter; - result_code = SVAL(rparam,0); - converter = SVAL(rparam,2); /* conversion factor */ - - DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) )); - - if (result_code == 0) /* if no error, */ - { - int i; - uint16 JobId; - uint16 Priority; - uint32 Size; - char *UserName; - char *JobName; - char *JobTimeStr; - time_t JobTime; - char PrinterName[20]; - - strcpy(PrinterName,strrchr(service,'\\')+1); /* name of queue */ - strlower(PrinterName); /* in lower case */ - - p = rdata; /* received data */ - for( i = 0; i < SVAL(rparam,4); ++i) - { - JobId = SVAL(p,0); - Priority = SVAL(p,2); - UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt); - strlower(UserName); - Priority = SVAL(p,2); - JobTime = make_unix_date3( p + 12); - JobTimeStr = asctime(LocalTime( &JobTime)); - Size = IVAL(p,16); - JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt); - - - printf("%s-%u %s priority %u %s %s %u bytes\n", - PrinterName, JobId, UserName, - Priority, JobTimeStr, JobName, Size); - -#if 0 /* DEBUG code */ - printf("Job Id: \"%u\"\n", SVAL(p,0)); - printf("Priority: \"%u\"\n", SVAL(p,2)); - - printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) ); - printf("Position: \"%u\"\n", SVAL(p,8)); - printf("Status: \"%u\"\n", SVAL(p,10)); - - JobTime = make_unix_date3( p + 12); - printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime))); - printf("date: \"%u\"\n", SVAL(p,12)); - - printf("Size: \"%u\"\n", SVAL(p,16)); - printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) ); - printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) ); -#endif /* DEBUG CODE */ - p += 28; - } - } - } - else /* call_api() failed */ - { - printf("Failed, error = %d\n", result_code); - } - - /* If any parameters or data were returned, free the storage. */ - if(rparam) free(rparam); - if(rdata) free(rdata); - - return; -} - -/**************************************************************************** -show information about a print queue -****************************************************************************/ -static void cmd_qinfo(char *inbuf,char *outbuf ) -{ - char *rparam = NULL; - char *rdata = NULL; - char *p; - int rdrcnt, rprcnt; - pstring param; - int result_code=0; - - bzero(param,sizeof(param)); - - p = param; - SSVAL(p,0,70); /* API function number 70 (DosPrintQGetInfo) */ - p += 2; - strcpy(p,"zWrLh"); /* parameter description? */ - p = skip_string(p,1); - strcpy(p,"zWWWWzzzzWWzzl"); /* returned data format */ - p = skip_string(p,1); - strcpy(p,strrchr(service,'\\')+1); /* name of queue */ - p = skip_string(p,1); - SSVAL(p,0,3); /* API function level 3, just queue info, no job info */ - SSVAL(p,2,1000); /* size of bytes of returned data buffer */ - p += 4; - strcpy(p,""); /* subformat */ - p = skip_string(p,1); - - DEBUG(1,("Calling DosPrintQueueGetInfo()...\n")); - if( call_api(PTR_DIFF(p,param), 0, - 10, 4096, - &rprcnt, &rdrcnt, - param, NULL, - &rparam, &rdata) ) - { - int converter; - result_code = SVAL(rparam,0); - converter = SVAL(rparam,2); /* conversion factor */ - - DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) )); - - if (result_code == 0) /* if no error, */ - { - p = rdata; /* received data */ - - printf("Name: \"%s\"\n", fix_char_ptr(SVAL(p,0), converter, rdata, rdrcnt) ); - printf("Priority: %u\n", SVAL(p,4) ); - printf("Start time: %u\n", SVAL(p,6) ); - printf("Until time: %u\n", SVAL(p,8) ); - printf("Seperator file: \"%s\"\n", fix_char_ptr(SVAL(p,12), converter, rdata, rdrcnt) ); - printf("Print processor: \"%s\"\n", fix_char_ptr(SVAL(p,16), converter, rdata, rdrcnt) ); - printf("Parameters: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) ); - printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) ); - printf("Status: %u\n", SVAL(p,28) ); - printf("Jobs: %u\n", SVAL(p,30) ); - printf("Printers: \"%s\"\n", fix_char_ptr(SVAL(p,32), converter, rdata, rdrcnt) ); - printf("Drivername: \"%s\"\n", fix_char_ptr(SVAL(p,36), converter, rdata, rdrcnt) ); - - /* Dump the driver data */ - { - int count, x, y, c; - char *ddptr; - - ddptr = rdata + SVAL(p,40) - converter; - if( SVAL(p,40) == 0 ) {count = 0;} else {count = IVAL(ddptr,0);} - printf("Driverdata: size=%d, version=%u\n", count, IVAL(ddptr,4) ); - - for(x=8; x < count; x+=16) - { - for(y=0; y < 16; y++) - { - if( (x+y) < count ) - printf("%2.2X ", CVAL(ddptr,(x+y)) ); - else - fputs(" ", stdout); - } - for(y=0; y < 16 && (x+y) < count; y++) - { - c = CVAL(ddptr,(x+y)); - if(isprint(c)) - fputc(c, stdout); - else - fputc('.', stdout); - } - fputc('\n', stdout); - } - } - - } - } - else /* call_api() failed */ - { - printf("Failed, error = %d\n", result_code); - } - - /* If any parameters or data were returned, free the storage. */ - if(rparam) free(rparam); - if(rdata) free(rdata); - - return; -} - -/**************************************************************************** -delete some files -****************************************************************************/ -static void do_del(file_info *finfo) -{ - char *p; - char *inbuf,*outbuf; - pstring mask; - - strcpy(mask,cur_dir); - strcat(mask,finfo->name); - - if (finfo->mode & aDIR) - return; - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - bzero(outbuf,smb_size); - set_message(outbuf,1,2 + strlen(mask),True); - - CVAL(outbuf,smb_com) = SMBunlink; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,mask); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - DEBUG(0,("%s deleting remote file %s\n",smb_errstr(inbuf),CNV_LANG(mask))); - - free(inbuf);free(outbuf); - -} - -/**************************************************************************** -delete some files -****************************************************************************/ -static void cmd_del(char *inbuf,char *outbuf ) -{ - pstring mask; - fstring buf; - int attribute = aSYSTEM | aHIDDEN; - - if (recurse) - attribute |= aDIR; - - strcpy(mask,cur_dir); - - if (!next_token(NULL,buf,NULL)) - { - DEBUG(0,("del <filename>\n")); - return; - } - strcat(mask,buf); - - do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_del,False); -} - - -/**************************************************************************** -remove a directory -****************************************************************************/ -static void cmd_rmdir(char *inbuf,char *outbuf ) -{ - pstring mask; - fstring buf; - char *p; - - strcpy(mask,cur_dir); - - if (!next_token(NULL,buf,NULL)) - { - DEBUG(0,("rmdir <dirname>\n")); - return; - } - strcat(mask,buf); - - bzero(outbuf,smb_size); - set_message(outbuf,0,2 + strlen(mask),True); - - CVAL(outbuf,smb_com) = SMBrmdir; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,mask); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s removing remote directory file %s\n",smb_errstr(inbuf),CNV_LANG(mask))); - return; - } - -} - -/**************************************************************************** -rename some files -****************************************************************************/ -static void cmd_rename(char *inbuf,char *outbuf ) -{ - pstring src,dest; - fstring buf,buf2; - char *p; - - strcpy(src,cur_dir); - strcpy(dest,cur_dir); - - if (!next_token(NULL,buf,NULL) || !next_token(NULL,buf2,NULL)) - { - DEBUG(0,("rename <src> <dest>\n")); - return; - } - strcat(src,buf); - strcat(dest,buf2); - - bzero(outbuf,smb_size); - set_message(outbuf,1,4 + strlen(src) + strlen(dest),True); - - CVAL(outbuf,smb_com) = SMBmv; - SSVAL(outbuf,smb_tid,cnum); - SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,src); - p = skip_string(p,1); - *p++ = 4; - strcpy(p,dest); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s renaming files\n",smb_errstr(inbuf))); - return; - } - -} - - -/**************************************************************************** -toggle the prompt flag -****************************************************************************/ -static void cmd_prompt(void) -{ - prompt = !prompt; - DEBUG(2,("prompting is now %s\n",prompt?"on":"off")); -} - - -/**************************************************************************** -set the newer than time -****************************************************************************/ -static void cmd_newer(void) -{ - fstring buf; - BOOL ok; - struct stat sbuf; - - ok = next_token(NULL,buf,NULL); - if (ok && (sys_stat(buf,&sbuf) == 0)) - { - newer_than = sbuf.st_mtime; - DEBUG(1,("Getting files newer than %s", - asctime(LocalTime(&newer_than)))); - } - else - newer_than = 0; - - if (ok && newer_than == 0) - DEBUG(0,("Error setting newer-than time\n")); -} - -/**************************************************************************** -set the archive level -****************************************************************************/ -static void cmd_archive(void) -{ - fstring buf; - - if (next_token(NULL,buf,NULL)) { - archive_level = atoi(buf); - } else - DEBUG(0,("Archive level is %d\n",archive_level)); -} - -/**************************************************************************** -toggle the lowercaseflag -****************************************************************************/ -static void cmd_lowercase(void) -{ - lowercase = !lowercase; - DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off")); -} - - - - -/**************************************************************************** -toggle the recurse flag -****************************************************************************/ -static void cmd_recurse(void) -{ - recurse = !recurse; - DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off")); -} - -/**************************************************************************** -toggle the translate flag -****************************************************************************/ -static void cmd_translate(void) -{ - translation = !translation; - DEBUG(2,("CR/LF<->LF and print text translation now %s\n", - translation?"on":"off")); -} - - -/**************************************************************************** -do a printmode command -****************************************************************************/ -static void cmd_printmode(void) -{ - fstring buf; - fstring mode; - - if (next_token(NULL,buf,NULL)) - { - if (strequal(buf,"text")) - printmode = 0; - else - { - if (strequal(buf,"graphics")) - printmode = 1; - else - printmode = atoi(buf); - } - } - - switch(printmode) - { - case 0: - strcpy(mode,"text"); - break; - case 1: - strcpy(mode,"graphics"); - break; - default: - sprintf(mode,"%d",printmode); - break; - } - - DEBUG(2,("the printmode is now %s\n",mode)); -} - -/**************************************************************************** -do the lcd command -****************************************************************************/ -static void cmd_lcd(void) -{ - fstring buf; - pstring d; - - if (next_token(NULL,buf,NULL)) - sys_chdir(buf); - DEBUG(2,("the local directory is now %s\n",GetWd(d))); -} - - -/**************************************************************************** -send a session request -****************************************************************************/ -static BOOL send_session_request(char *inbuf,char *outbuf) -{ - fstring dest; - char *p; - int len = 4; - /* send a session request (RFC 8002) */ - - strcpy(dest,desthost); - p = strchr(dest,'.'); - if (p) *p = 0; - - /* put in the destination name */ - p = outbuf+len; - name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */ - len += name_len(p); - - /* and my name */ - p = outbuf+len; - name_mangle(myname,p,0); - len += name_len(p); - - /* setup the packet length */ - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(Client,outbuf); - DEBUG(5,("Sent session request\n")); - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */ - { - /* For information, here is the response structure. - * We do the byte-twiddling to for portability. - struct RetargetResponse{ - unsigned char type; - unsigned char flags; - int16 length; - int32 ip_addr; - int16 port; - }; - */ - extern int Client; - int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9); - /* SESSION RETARGET */ - putip((char *)&dest_ip,inbuf+4); - - close_sockets(); - Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT); - if (Client == -1) - return False; - - DEBUG(3,("Retargeted\n")); - - set_socket_options(Client,user_socket_options); - - /* Try again */ - return send_session_request(inbuf,outbuf); - } /* C. Hoch 9/14/95 End */ - - - if (CVAL(inbuf,0) != 0x82) - { - int ecode = CVAL(inbuf,4); - DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n", - CVAL(inbuf,0),ecode,myname,desthost)); - switch (ecode) - { - case 0x80: - DEBUG(0,("Not listening on called name\n")); - DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); - DEBUG(0,("You may find the -I option useful for this\n")); - break; - case 0x81: - DEBUG(0,("Not listening for calling name\n")); - DEBUG(0,("Try to connect as another name (instead of %s)\n",myname)); - DEBUG(0,("You may find the -n option useful for this\n")); - break; - case 0x82: - DEBUG(0,("Called name not present\n")); - DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); - DEBUG(0,("You may find the -I option useful for this\n")); - break; - case 0x83: - DEBUG(0,("Called name present, but insufficient resources\n")); - DEBUG(0,("Perhaps you should try again later?\n")); - break; - default: - DEBUG(0,("Unspecified error 0x%X\n",ecode)); - DEBUG(0,("Your server software is being unfriendly\n")); - break; - } - return(False); - } - return(True); -} - -static struct { - int prot; - char *name; -} prots[] = { - {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, - {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, - {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, - {PROTOCOL_LANMAN1,"LANMAN1.0"}, - {PROTOCOL_LANMAN2,"LM1.2X002"}, - {PROTOCOL_LANMAN2,"Samba"}, - {PROTOCOL_NT1,"NT LM 0.12"}, - {PROTOCOL_NT1,"NT LANMAN 1.0"}, - {-1,NULL} -}; - - -/**************************************************************************** -send a login command -****************************************************************************/ -static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup) -{ - BOOL was_null = (!inbuf && !outbuf); - int sesskey=0; - time_t servertime = 0; - extern int serverzone; - int sec_mode=0; - int crypt_len; - int max_vcs=0; - char *pass = NULL; - pstring dev; - char *p; - int numprots; - int tries=0; - - if (was_null) - { - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - } - -#if AJT - if (strstr(service,"IPC$")) connect_as_ipc = True; -#endif - - strcpy(dev,"A:"); - if (connect_as_printer) - strcpy(dev,"LPT1:"); - if (connect_as_ipc) - strcpy(dev,"IPC"); - - - if (start_session && !send_session_request(inbuf,outbuf)) - { - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - bzero(outbuf,smb_size); - - /* setup the protocol strings */ - { - int plength; - - for (plength=0,numprots=0; - prots[numprots].name && prots[numprots].prot<=max_protocol; - numprots++) - plength += strlen(prots[numprots].name)+2; - - set_message(outbuf,0,plength,True); - - p = smb_buf(outbuf); - for (numprots=0; - prots[numprots].name && prots[numprots].prot<=max_protocol; - numprots++) - { - *p++ = 2; - strcpy(p,prots[numprots].name); - p += strlen(p) + 1; - } - } - - CVAL(outbuf,smb_com) = SMBnegprot; - setup_pkt(outbuf); - - CVAL(smb_buf(outbuf),0) = 2; - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - show_msg(inbuf); - - if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots)) - { - DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n", - myname,desthost,smb_errstr(inbuf))); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - Protocol = prots[SVAL(inbuf,smb_vwv0)].prot; - - - if (Protocol < PROTOCOL_NT1) { - sec_mode = SVAL(inbuf,smb_vwv1); - max_xmit = SVAL(inbuf,smb_vwv2); - sesskey = IVAL(inbuf,smb_vwv6); - serverzone = SVALS(inbuf,smb_vwv10)*60; - /* this time is converted to GMT by make_unix_date */ - servertime = make_unix_date(inbuf+smb_vwv8); - if (Protocol >= PROTOCOL_COREPLUS) { - readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0); - writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0); - } - crypt_len = smb_buflen(inbuf); - memcpy(cryptkey,smb_buf(inbuf),8); - DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3))); - max_vcs = SVAL(inbuf,smb_vwv4); - DEBUG(3,("max vcs %d\n",max_vcs)); - DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5))); - } else { - /* NT protocol */ - sec_mode = CVAL(inbuf,smb_vwv1); - max_xmit = IVAL(inbuf,smb_vwv3+1); - sesskey = IVAL(inbuf,smb_vwv7+1); - serverzone = SVALS(inbuf,smb_vwv15+1)*60; - /* this time arrives in real GMT */ - servertime = interpret_long_date(inbuf+smb_vwv11+1); - crypt_len = CVAL(inbuf,smb_vwv16+1); - memcpy(cryptkey,smb_buf(inbuf),8); - if (IVAL(inbuf,smb_vwv9+1) & 1) - readbraw_supported = writebraw_supported = True; - DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); - max_vcs = SVAL(inbuf,smb_vwv2+1); - DEBUG(3,("max vcs %d\n",max_vcs)); - DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); - DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); - } - - DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); - DEBUG(3,("max xmt %d\n",max_xmit)); - DEBUG(3,("Got %d byte crypt key\n",crypt_len)); - DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); - - doencrypt = ((sec_mode & 2) != 0); - - if (servertime) { - static BOOL done_time = False; - if (!done_time) { - DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n", - asctime(LocalTime(&servertime)), - -(double)(serverzone/3600.0))); - done_time = True; - } - } - - get_pass: - - if (got_pass) - pass = password; - else - pass = (char *)getpass("Password: "); - - /* use a blank username for the 2nd try with a blank password */ - if (tries++ && !*pass) - *username = 0; - - if (Protocol >= PROTOCOL_LANMAN1 && use_setup) - { - fstring pword; - int passlen = strlen(pass)+1; - strcpy(pword,pass); - -#ifdef SMB_PASSWD - if (doencrypt && *pass) { - DEBUG(3,("Using encrypted passwords\n")); - passlen = 24; - SMBencrypt(pass,cryptkey,pword); - } -#else - doencrypt = False; -#endif - - /* if in share level security then don't send a password now */ - if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} - - /* send a session setup command */ - bzero(outbuf,smb_size); - - if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,10,1 + strlen(username) + passlen,True); - CVAL(outbuf,smb_com) = SMBsesssetupX; - setup_pkt(outbuf); - - CVAL(outbuf,smb_vwv0) = 0xFF; - SSVAL(outbuf,smb_vwv2,max_xmit); - SSVAL(outbuf,smb_vwv3,2); - SSVAL(outbuf,smb_vwv4,max_vcs-1); - SIVAL(outbuf,smb_vwv5,sesskey); - SSVAL(outbuf,smb_vwv7,passlen); - p = smb_buf(outbuf); - memcpy(p,pword,passlen); - p += passlen; - strcpy(p,username); - } else { - if (!doencrypt) passlen--; - /* for Win95 */ - set_message(outbuf,13,0,True); - CVAL(outbuf,smb_com) = SMBsesssetupX; - setup_pkt(outbuf); - - CVAL(outbuf,smb_vwv0) = 0xFF; - SSVAL(outbuf,smb_vwv2,BUFFER_SIZE); - SSVAL(outbuf,smb_vwv3,2); - SSVAL(outbuf,smb_vwv4,getpid()); - SIVAL(outbuf,smb_vwv5,sesskey); - SSVAL(outbuf,smb_vwv7,passlen); - SSVAL(outbuf,smb_vwv8,0); - p = smb_buf(outbuf); - memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7); - strcpy(p,username);p = skip_string(p,1); - strcpy(p,workgroup);p = skip_string(p,1); - strcpy(p,"Unix");p = skip_string(p,1); - strcpy(p,"Samba");p = skip_string(p,1); - set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - show_msg(inbuf); - - if (CVAL(inbuf,smb_rcls) != 0) - { - if (! *pass && - ((CVAL(inbuf,smb_rcls) == ERRDOS && - SVAL(inbuf,smb_err) == ERRnoaccess) || - (CVAL(inbuf,smb_rcls) == ERRSRV && - SVAL(inbuf,smb_err) == ERRbadpw))) - { - got_pass = False; - DEBUG(3,("resending login\n")); - goto get_pass; - } - - DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n", - username,myname,desthost,smb_errstr(inbuf))); - DEBUG(0,("You might find the -U, -W or -n options useful\n")); - DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n")); - DEBUG(0,("Some servers also insist on uppercase-only passwords\n")); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - if (Protocol >= PROTOCOL_NT1) { - char *domain,*os,*lanman; - p = smb_buf(inbuf); - os = p; - lanman = skip_string(os,1); - domain = skip_string(lanman,1); - if (*domain || *os || *lanman) - DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman)); - } - - /* use the returned uid from now on */ - if (SVAL(inbuf,smb_uid) != uid) - DEBUG(3,("Server gave us a UID of %d. We gave %d\n", - SVAL(inbuf,smb_uid),uid)); - uid = SVAL(inbuf,smb_uid); - } - - /* now we've got a connection - send a tcon message */ - bzero(outbuf,smb_size); - - if (strncmp(service,"\\\\",2) != 0) - { - DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n")); - DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n")); - } - - - again2: - - { - int passlen = strlen(pass)+1; - fstring pword; - strcpy(pword,pass); - -#ifdef SMB_PASSWD - if (doencrypt && *pass) { - passlen=24; - SMBencrypt(pass,cryptkey,pword); - } -#endif - - /* if in user level security then don't send a password now */ - if ((sec_mode & 1)) { - strcpy(pword, ""); passlen=1; - } - - if (Protocol <= PROTOCOL_COREPLUS) { - set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True); - CVAL(outbuf,smb_com) = SMBtcon; - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 0x04; - strcpy(p, service); - p = skip_string(p,1); - *p++ = 0x04; - memcpy(p,pword,passlen); - p += passlen; - *p++ = 0x04; - strcpy(p, dev); - } - else { - set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True); - CVAL(outbuf,smb_com) = SMBtconX; - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv3,passlen); - - p = smb_buf(outbuf); - memcpy(p,pword,passlen); - p += passlen; - strcpy(p,service); - p = skip_string(p,1); - strcpy(p,dev); - } - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - /* trying again with a blank password */ - if (CVAL(inbuf,smb_rcls) != 0 && - (int)strlen(pass) > 0 && - !doencrypt && - Protocol >= PROTOCOL_LANMAN1) - { - DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf))); - strcpy(pass,""); - goto again2; - } - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf))); - DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n")); - DEBUG(0,("Some servers insist that these be in uppercase\n")); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - - if (Protocol <= PROTOCOL_COREPLUS) { - max_xmit = SVAL(inbuf,smb_vwv0); - - cnum = SVAL(inbuf,smb_vwv1); - } - else { - max_xmit = MIN(max_xmit,BUFFER_SIZE-4); - if (max_xmit <= 0) - max_xmit = BUFFER_SIZE - 4; - - cnum = SVAL(inbuf,smb_tid); - } - - DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); - - if (was_null) - { - free(inbuf); - free(outbuf); - } - return True; -} - - -/**************************************************************************** -send a logout command -****************************************************************************/ -static void send_logout(void ) -{ - pstring inbuf,outbuf; - - bzero(outbuf,smb_size); - set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = SMBtdis; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,SHORT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf))); - } - - -#ifdef STATS - stats_report(); -#endif - exit(0); -} - - - -/**************************************************************************** -call a remote api -****************************************************************************/ -static BOOL call_api(int prcnt,int drcnt, - int mprcnt,int mdrcnt, - int *rprcnt,int *rdrcnt, - char *param,char *data, - char **rparam,char **rdata) -{ - static char *inbuf=NULL; - static char *outbuf=NULL; - - if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, - data,param,NULL, - drcnt,prcnt,0, - mdrcnt,mprcnt,0); - - return (receive_trans_response(inbuf,SMBtrans, - rdrcnt,rprcnt, - rdata,rparam)); -} - -/**************************************************************************** - send a SMB trans or trans2 request - ****************************************************************************/ -static BOOL send_trans_request(char *outbuf,int trans, - char *name,int fid,int flags, - char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup, - int mdata,int mparam,int msetup) -{ - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - char *outdata,*outparam; - pstring inbuf; - char *p; - - this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam)); - - bzero(outbuf,smb_size); - set_message(outbuf,14+lsetup,0,True); - CVAL(outbuf,smb_com) = trans; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3); - outdata = outparam+this_lparam; - - /* primary request */ - SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ - SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ - SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */ - SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */ - SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */ - SSVAL(outbuf,smb_flags,flags); /* flags */ - SIVAL(outbuf,smb_timeout,0); /* timeout */ - SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */ - SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */ - SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */ - SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */ - SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */ - for (i=0;i<lsetup;i++) /* setup[] */ - SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]); - p = smb_buf(outbuf); - if (trans==SMBtrans) - strcpy(p,name); /* name[] */ - else - { - *p++ = 0; /* put in a null smb_name */ - *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */ - } - if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); - if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); - set_message(outbuf,14+lsetup, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False); - - show_msg(outbuf); - send_smb(Client,outbuf); - - if (this_ldata < ldata || this_lparam < lparam) - { - /* receive interim response */ - if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s request failed (%s)\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf))); - return(False); - } - - tot_data = this_ldata; - tot_param = this_lparam; - - while (tot_data < ldata || tot_param < lparam) - { - this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam)); - - set_message(outbuf,trans==SMBtrans?8:9,0,True); - CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2; - - outparam = smb_buf(outbuf); - outdata = outparam+this_lparam; - - /* secondary request */ - SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ - SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ - SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */ - SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */ - SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */ - SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */ - SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */ - SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */ - if (trans==SMBtrans2) - SSVAL(outbuf,smb_sfid,fid); /* fid */ - if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); - if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); - set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data += this_ldata; - tot_param += this_lparam; - } - } - - return(True); -} - -/**************************************************************************** -try and browse available connections on a host -****************************************************************************/ -static BOOL browse_host(BOOL sort) -{ -#ifdef NOSTRCASECMP -#define strcasecmp StrCaseCmp -#endif - extern int strcasecmp(); - - char *rparam = NULL; - char *rdata = NULL; - char *p; - int rdrcnt,rprcnt; - pstring param; - int count = -1; - - /* now send a SMBtrans command with api RNetShareEnum */ - p = param; - SSVAL(p,0,0); /* api number */ - p += 2; - strcpy(p,"WrLeh"); - p = skip_string(p,1); - strcpy(p,"B13BWz"); - p = skip_string(p,1); - SSVAL(p,0,1); - SSVAL(p,2,BUFFER_SIZE); - p += 4; - - if (call_api(PTR_DIFF(p,param),0, - 1024,BUFFER_SIZE, - &rprcnt,&rdrcnt, - param,NULL, - &rparam,&rdata)) - { - int res = SVAL(rparam,0); - int converter=SVAL(rparam,2); - int i; - BOOL long_share_name=False; - - if (res == 0) - { - count=SVAL(rparam,4); - p = rdata; - - if (count > 0) - { - printf("\n\tSharename Type Comment\n"); - printf("\t--------- ---- -------\n"); - } - - if (sort) - qsort(p,count,20,QSORT_CAST strcasecmp); - - for (i=0;i<count;i++) - { - char *sname = p; - int type = SVAL(p,14); - int comment_offset = IVAL(p,16) & 0xFFFF; - fstring typestr; - *typestr=0; - - switch (type) - { - case STYPE_DISKTREE: - strcpy(typestr,"Disk"); break; - case STYPE_PRINTQ: - strcpy(typestr,"Printer"); break; - case STYPE_DEVICE: - strcpy(typestr,"Device"); break; - case STYPE_IPC: - strcpy(typestr,"IPC"); break; - } - - printf("\t%-15.15s%-10.10s%s\n", - sname, - typestr, - comment_offset?rdata+comment_offset-converter:""); - - if (strlen(sname)>8) long_share_name=True; - - p += 20; - } - - if (long_share_name) { - printf("\nNOTE: There were share names longer than 8 chars.\nOn older clients these may not be accessible or may give browsing errors\n"); - } - } - } - - if (rparam) free(rparam); - if (rdata) free(rdata); - - return(count>0); -} - - -/**************************************************************************** -get some server info -****************************************************************************/ -static void server_info() -{ - char *rparam = NULL; - char *rdata = NULL; - char *p; - int rdrcnt,rprcnt; - pstring param; - - bzero(param,sizeof(param)); - - p = param; - SSVAL(p,0,63); /* NetServerGetInfo()? */ - p += 2; - strcpy(p,"WrLh"); - p = skip_string(p,1); - strcpy(p,"zzzBBzz"); - p = skip_string(p,1); - SSVAL(p,0,10); /* level 10 */ - SSVAL(p,2,1000); - p += 6; - - if (call_api(PTR_DIFF(p,param),0, - 6,1000, - &rprcnt,&rdrcnt, - param,NULL, - &rparam,&rdata)) - { - int res = SVAL(rparam,0); - int converter=SVAL(rparam,2); - - if (res == 0) - { - p = rdata; - - printf("\nServer=[%s] User=[%s] Workgroup=[%s] Domain=[%s]\n", - rdata+SVAL(p,0)-converter, - rdata+SVAL(p,4)-converter, - rdata+SVAL(p,8)-converter, - rdata+SVAL(p,14)-converter); - } - } - - if (rparam) free(rparam); - if (rdata) free(rdata); - - return; -} - - -/**************************************************************************** -try and browse available connections on a host -****************************************************************************/ -static BOOL list_servers(char *wk_grp) -{ - char *rparam = NULL; - char *rdata = NULL; - int rdrcnt,rprcnt; - char *p,*svtype_p; - pstring param; - int uLevel = 1; - int count = 0; - BOOL ok = False; - BOOL generic_request = False; - - - if (strequal(wk_grp,"WORKGROUP")) { - /* we won't specify a workgroup */ - generic_request = True; - } - - /* now send a SMBtrans command with api ServerEnum? */ - p = param; - SSVAL(p,0,0x68); /* api number */ - p += 2; - - strcpy(p,generic_request?"WrLehDO":"WrLehDz"); - p = skip_string(p,1); - - strcpy(p,"B16BBDz"); - - p = skip_string(p,1); - SSVAL(p,0,uLevel); - SSVAL(p,2,0x2000); /* buf length */ - p += 4; - - svtype_p = p; - p += 4; - - if (!generic_request) { - strcpy(p, wk_grp); - p = skip_string(p,1); - } - - /* first ask for a list of servers in this workgroup */ - SIVAL(svtype_p,0,SV_TYPE_ALL); - - if (call_api(PTR_DIFF(p+4,param),0, - 8,10000, - &rprcnt,&rdrcnt, - param,NULL, - &rparam,&rdata)) - { - int res = SVAL(rparam,0); - int converter=SVAL(rparam,2); - int i; - - if (res == 0) { - char *p2 = rdata; - count=SVAL(rparam,4); - - if (count > 0) { - printf("\n\nThis machine has a browse list:\n"); - printf("\n\tServer Comment\n"); - printf("\t--------- -------\n"); - } - - for (i=0;i<count;i++) { - char *sname = p2; - int comment_offset = IVAL(p2,22) & 0xFFFF; - printf("\t%-16.16s %s\n", - sname, - comment_offset?rdata+comment_offset-converter:""); - - ok=True; - p2 += 26; - } - } - } - - if (rparam) {free(rparam); rparam = NULL;} - if (rdata) {free(rdata); rdata = NULL;} - - /* now ask for a list of workgroups */ - SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM); - - if (call_api(PTR_DIFF(p+4,param),0, - 8,10000, - &rprcnt,&rdrcnt, - param,NULL, - &rparam,&rdata)) - { - int res = SVAL(rparam,0); - int converter=SVAL(rparam,2); - int i; - - if (res == 0) { - char *p2 = rdata; - count=SVAL(rparam,4); - - if (count > 0) { - printf("\n\nThis machine has a workgroup list:\n"); - printf("\n\tWorkgroup Master\n"); - printf("\t--------- -------\n"); - } - - for (i=0;i<count;i++) { - char *sname = p2; - int comment_offset = IVAL(p2,22) & 0xFFFF; - printf("\t%-16.16s %s\n", - sname, - comment_offset?rdata+comment_offset-converter:""); - - ok=True; - p2 += 26; - } - } - } - - if (rparam) free(rparam); - if (rdata) free(rdata); - - return(ok); -} - - -/* This defines the commands supported by this client */ -struct -{ - char *name; - void (*fn)(); - char *description; -} commands[] = -{ - {"ls",cmd_dir,"<mask> list the contents of the current directory"}, - {"dir",cmd_dir,"<mask> list the contents of the current directory"}, - {"lcd",cmd_lcd,"[directory] change/report the local current working directory"}, - {"cd",cmd_cd,"[directory] change/report the remote directory"}, - {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)"}, - {"get",cmd_get,"<remote name> [local name] get a file"}, - {"mget",cmd_mget,"<mask> get all the matching files"}, - {"put",cmd_put,"<local name> [remote name] put a file"}, - {"mput",cmd_mput,"<mask> put all matching files"}, - {"rename",cmd_rename,"<src> <dest> rename some files"}, - {"more",cmd_more,"<remote name> view a remote file with your pager"}, - {"mask",cmd_select,"<mask> mask all filenames against this"}, - {"del",cmd_del,"<mask> delete all matching files"}, - {"rm",cmd_del,"<mask> delete all matching files"}, - {"mkdir",cmd_mkdir,"<directory> make a directory"}, - {"md",cmd_mkdir,"<directory> make a directory"}, - {"rmdir",cmd_rmdir,"<directory> remove a directory"}, - {"rd",cmd_rmdir,"<directory> remove a directory"}, - {"pq",cmd_p_queue_4,"enumerate the print queue"}, - {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"}, - {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"}, - {"translate",cmd_translate,"toggle text translation for printing"}, - {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get"}, - {"print",cmd_print,"<file name> print a file"}, - {"printmode",cmd_printmode,"<graphics or text> set the print mode"}, - {"queue",cmd_queue,"show the print queue"}, - {"qinfo",cmd_qinfo,"show print queue information"}, - {"cancel",cmd_cancel,"<jobid> cancel a print queue entry"}, - {"stat",cmd_stat,"<file> get info on a file (experimental!)"}, - {"quit",send_logout,"logoff the server"}, - {"q",send_logout,"logoff the server"}, - {"exit",send_logout,"logoff the server"}, - {"newer",cmd_newer,"<file> only mget files newer than the specified local file"}, - {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"}, - {"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" }, - {"blocksize",cmd_block,"blocksize <number> (default 20)" }, - {"tarmode",cmd_tarmode, - "<full|inc|reset|noreset> tar's behaviour towards archive bits" }, - {"setmode",cmd_setmode,"filename <setmode string> change modes of file"}, - {"help",cmd_help,"[command] give help on a command"}, - {"?",cmd_help,"[command] give help on a command"}, - {"!",NULL,"run a shell command on the local system"}, - {"",NULL,NULL} -}; - - -/******************************************************************* - lookup a command string in the list of commands, including - abbreviations - ******************************************************************/ -static int process_tok(fstring tok) -{ - int i = 0, matches = 0; - int cmd=0; - int tok_len = strlen(tok); - - while (commands[i].fn != NULL) - { - if (strequal(commands[i].name,tok)) - { - matches = 1; - cmd = i; - break; - } - else if (strnequal(commands[i].name, tok, tok_len+1)) - { - matches++; - cmd = i; - } - i++; - } - - if (matches == 0) - return(-1); - else if (matches == 1) - return(cmd); - else - return(-2); -} - -/**************************************************************************** -help -****************************************************************************/ -void cmd_help(void) -{ - int i=0,j; - fstring buf; - - if (next_token(NULL,buf,NULL)) - { - if ((i = process_tok(buf)) >= 0) - DEBUG(0,("HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description)); - } - else - while (commands[i].description) - { - for (j=0; commands[i].description && (j<5); j++) { - DEBUG(0,("%-15s",commands[i].name)); - i++; - } - DEBUG(0,("\n")); - } -} - -/**************************************************************************** -open the client sockets -****************************************************************************/ -static BOOL open_sockets(int port ) -{ - static int last_port; - char *host; - pstring service2; - extern int Client; -#ifdef USENMB - BOOL failed = True; -#endif - - if (port == 0) port=last_port; - last_port=port; - - strupper(service); - - if (*desthost) - { - host = desthost; - } - else - { - strcpy(service2,service); - host = strtok(service2,"\\/"); - if (!host) { - DEBUG(0,("Badly formed host name\n")); - return(False); - } - strcpy(desthost,host); - } - - if (*myname == 0) { - get_myname(myname,NULL); - } - strupper(myname); - - DEBUG(3,("Opening sockets\n")); - - if (!have_ip) - { - struct hostent *hp; - - if ((hp = Get_Hostbyname(host))) { - putip((char *)&dest_ip,(char *)hp->h_addr); - failed = False; - } else { -#ifdef USENMB - /* Try and resolve the name with the netbios server */ - int bcast; - - if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3, - interpret_addr(lp_socket_address()))) != -1) { - set_socket_options(bcast, "SO_BROADCAST"); - - if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip), - &dest_ip,0)) { - failed = False; - } - close (bcast); - } -#endif - if (failed) { - DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host)); - return False; - } - } - } - - Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT); - if (Client == -1) - return False; - - DEBUG(3,("Connected\n")); - - set_socket_options(Client,user_socket_options); - - return True; -} - -/**************************************************************************** -wait for keyboard activity, swallowing network packets -****************************************************************************/ -#ifdef CLIX -static char wait_keyboard(char *buffer) -#else -static void wait_keyboard(char *buffer) -#endif -{ - fd_set fds; - int selrtn; - struct timeval timeout; - -#ifdef CLIX - int delay = 0; -#endif - - while (1) - { - extern int Client; - FD_ZERO(&fds); - FD_SET(Client,&fds); -#ifndef CLIX - FD_SET(fileno(stdin),&fds); -#endif - - timeout.tv_sec = 20; - timeout.tv_usec = 0; -#ifdef CLIX - timeout.tv_sec = 0; -#endif - selrtn = sys_select(&fds,&timeout); - -#ifndef CLIX - if (FD_ISSET(fileno(stdin),&fds)) - return; -#else - { - char ch; - int f_flags; - int readret; - - f_flags = fcntl(fileno(stdin), F_GETFL, 0); - fcntl( fileno(stdin), F_SETFL, f_flags | O_NONBLOCK); - readret = read_data( fileno(stdin), &ch, 1); - fcntl(fileno(stdin), F_SETFL, f_flags); - if (readret == -1) - { - if (errno != EAGAIN) - { - /* should crash here */ - DEBUG(1,("readchar stdin failed\n")); - } - } - else if (readret != 0) - { - return ch; - } - } -#endif - if (FD_ISSET(Client,&fds)) - receive_smb(Client,buffer,0); - -#ifdef CLIX - delay++; - if (delay > 100000) - { - delay = 0; - chkpath("\\",False); - } -#else - chkpath("\\",False); -#endif - } -} - - -/**************************************************************************** -close and open the connection again -****************************************************************************/ -BOOL reopen_connection(char *inbuf,char *outbuf) -{ - static int open_count=0; - - open_count++; - - if (open_count>5) return(False); - - DEBUG(1,("Trying to re-open connection\n")); - - set_message(outbuf,0,0,True); - SCVAL(outbuf,smb_com,SMBtdis); - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,SHORT_TIMEOUT); - - close_sockets(); - if (!open_sockets(0)) return(False); - - return(send_login(inbuf,outbuf,True,True)); -} - -/**************************************************************************** - process commands from the client -****************************************************************************/ -static BOOL process(char *base_directory) -{ - extern FILE *dbf; - pstring line; - char *cmd; - - char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return(False); - - bzero(OutBuffer,smb_size); - - if (!send_login(InBuffer,OutBuffer,True,True)) - return(False); - - if (*base_directory) do_cd(base_directory); - - cmd = cmdstr; - if (cmd[0] != '\0') while (cmd[0] != '\0') - { - char *p; - fstring tok; - int i; - - if ((p = strchr(cmd, ';')) == 0) - { - strncpy(line, cmd, 999); - line[1000] = '\0'; - cmd += strlen(cmd); - } - else - { - if (p - cmd > 999) p = cmd + 999; - strncpy(line, cmd, p - cmd); - line[p - cmd] = '\0'; - cmd = p + 1; - } - - /* input language code to internal one */ - CNV_INPUT (line); - - /* and get the first part of the command */ - { - char *ptr = line; - if (!next_token(&ptr,tok,NULL)) continue; - } - - if ((i = process_tok(tok)) >= 0) - commands[i].fn(InBuffer,OutBuffer); - else if (i == -2) - DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok))); - else - DEBUG(0,("%s: command not found\n",CNV_LANG(tok))); - } - else while (!feof(stdin)) - { - fstring tok; - int i; - - bzero(OutBuffer,smb_size); - - /* display a prompt */ - DEBUG(1,("smb: %s> ", CNV_LANG(cur_dir))); - fflush(dbf); - -#ifdef CLIX - line[0] = wait_keyboard(InBuffer); - /* this might not be such a good idea... */ - if ( line[0] == EOF) - break; -#else - wait_keyboard(InBuffer); -#endif - - /* and get a response */ -#ifdef CLIX - fgets( &line[1],999, stdin); -#else - if (!fgets(line,1000,stdin)) - break; -#endif - - /* input language code to internal one */ - CNV_INPUT (line); - - /* special case - first char is ! */ - if (*line == '!') - { - system(line + 1); - continue; - } - - /* and get the first part of the command */ - { - char *ptr = line; - if (!next_token(&ptr,tok,NULL)) continue; - } - - if ((i = process_tok(tok)) >= 0) - commands[i].fn(InBuffer,OutBuffer); - else if (i == -2) - DEBUG(0,("%s: command abbreviation ambiguous\n",CNV_LANG(tok))); - else - DEBUG(0,("%s: command not found\n",CNV_LANG(tok))); - } - - send_logout(); - return(True); -} - - -/**************************************************************************** -usage on the program -****************************************************************************/ -static void usage(char *pname) -{ - DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ", - pname)); - -#ifdef KANJI - DEBUG(0,("[-t termcode] ")); -#endif /* KANJI */ - - DEBUG(0,("\nVersion %s\n",VERSION)); - DEBUG(0,("\t-p port listen on the specified port\n")); - DEBUG(0,("\t-d debuglevel set the debuglevel\n")); - DEBUG(0,("\t-l log basename. Basename for log/debug files\n")); - DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n")); - DEBUG(0,("\t-N don't ask for a password\n")); - DEBUG(0,("\t-P connect to service as a printer\n")); - DEBUG(0,("\t-M host send a winpopup message to the host\n")); - DEBUG(0,("\t-m max protocol set the max protocol level\n")); - DEBUG(0,("\t-L host get a list of shares available on a host\n")); - DEBUG(0,("\t-I dest IP use this IP to connect to\n")); - DEBUG(0,("\t-E write messages to stderr instead of stdout\n")); - DEBUG(0,("\t-U username set the network username\n")); - DEBUG(0,("\t-W workgroup set the workgroup name\n")); - DEBUG(0,("\t-c command string execute semicolon separated commands\n")); -#ifdef KANJI - DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n")); -#endif /* KANJI */ - DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n")); - DEBUG(0,("\t-D directory start from directory\n")); - DEBUG(0,("\n")); -} - -/**************************************************************************** - main program -****************************************************************************/ - int main(int argc,char *argv[]) -{ - fstring base_directory; - char *pname = argv[0]; - int port = SMB_PORT; - int opt; - extern FILE *dbf; - extern char *optarg; - extern int optind; - pstring query_host; - BOOL message = False; - extern char tar_type; - static pstring servicesf = CONFIGFILE; - - *query_host = 0; - *base_directory = 0; - - DEBUGLEVEL = 2; - - setup_logging(pname,True); - - TimeInit(); - charset_initialise(0); - - pid = getpid(); - uid = getuid(); - gid = getgid(); - mid = pid + 100; - myumask = umask(0); - umask(myumask); - - if (getenv("USER")) - { - strcpy(username,getenv("USER")); - strupper(username); - } - - if (*username == 0 && getenv("LOGNAME")) - { - strcpy(username,getenv("LOGNAME")); - strupper(username); - } - - if (argc < 2) - { - usage(pname); - exit(1); - } - - if (*argv[1] != '-') - { - - strcpy(service,argv[1]); - /* Convert any '/' characters in the service name to '\' characters */ - string_replace( service, '/','\\'); - argc--; - argv++; - - if (count_chars(service,'\\') < 3) - { - usage(pname); - printf("\n%s: Not enough '\\' characters in service\n",service); - exit(1); - } - -/* - if (count_chars(service,'\\') > 3) - { - usage(pname); - printf("\n%s: Too many '\\' characters in service\n",service); - exit(1); - } - */ - - if (argc > 1 && (*argv[1] != '-')) - { - got_pass = True; - strcpy(password,argv[1]); - memset(argv[1],'X',strlen(argv[1])); - argc--; - argv++; - } - } - -#ifdef KANJI - setup_term_code (KANJI); -#endif - while ((opt = - getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF) - switch (opt) - { - case 'm': - max_protocol = interpret_protocol(optarg,max_protocol); - break; - case 'O': - strcpy(user_socket_options,optarg); - break; - case 'M': - name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */ - strcpy(desthost,optarg); - strupper(desthost); - message = True; - break; - case 'B': - iface_set_default(NULL,optarg,NULL); - break; - case 'D': - strcpy(base_directory,optarg); - break; - case 'T': - if (!tar_parseargs(argc, argv, optarg, optind)) { - usage(pname); - exit(1); - } - break; - case 'i': - strcpy(scope,optarg); - break; - case 'L': - got_pass = True; - strcpy(query_host,optarg); - break; - case 'U': - { - char *p; - strcpy(username,optarg); - if ((p=strchr(username,'%'))) - { - *p = 0; - strcpy(password,p+1); - got_pass = True; - memset(strchr(optarg,'%')+1,'X',strlen(password)); - } - } - - break; - case 'W': - strcpy(workgroup,optarg); - break; - case 'E': - dbf = stderr; - break; - case 'I': - { - dest_ip = *interpret_addr2(optarg); - if (zero_ip(dest_ip)) exit(1); - have_ip = True; - } - break; - case 'n': - strcpy(myname,optarg); - break; - case 'N': - got_pass = True; - break; - case 'P': - connect_as_printer = True; - break; - case 'd': - if (*optarg == 'A') - DEBUGLEVEL = 10000; - else - DEBUGLEVEL = atoi(optarg); - break; - case 'l': - sprintf(debugf,"%s.client",optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 'c': - cmdstr = optarg; - got_pass = True; - break; - case 'h': - usage(pname); - exit(0); - break; - case 's': - strcpy(servicesf, optarg); - break; - case 't': -#ifdef KANJI - if (!setup_term_code (optarg)) { - DEBUG(0, ("%s: unknown terminal code name\n", optarg)); - usage (pname); - exit (1); - } -#endif - break; - default: - usage(pname); - exit(1); - } - - if (!tar_type && !*query_host && !*service && !message) - { - usage(pname); - exit(1); - } - - - DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION)); - - if (!lp_load(servicesf,True)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); - } - - if (*workgroup == 0) - strcpy(workgroup,lp_workgroup()); - - load_interfaces(); - get_myname(*myname?NULL:myname,NULL); - strupper(myname); - - if (tar_type) { - recurse=True; - - if (open_sockets(port)) { - char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - int ret; - - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return(1); - - bzero(OutBuffer,smb_size); - if (!send_login(InBuffer,OutBuffer,True,True)) - return(False); - - if (*base_directory) do_cd(base_directory); - - ret=process_tar(InBuffer, OutBuffer); - - send_logout(); - close_sockets(); - return(ret); - } else - return(1); - } - - if (*query_host) - { - int ret = 0; - sprintf(service,"\\\\%s\\IPC$",query_host); - strupper(service); - connect_as_ipc = True; - if (open_sockets(port)) - { -#if 0 - *username = 0; -#endif - if (!send_login(NULL,NULL,True,True)) - return(1); - - server_info(); - if (!browse_host(True)) { - sleep(1); - browse_host(True); - } - if (!list_servers(workgroup)) { - sleep(1); - list_servers(workgroup); - } - - send_logout(); - close_sockets(); - } - - return(ret); - } - - if (message) - { - int ret = 0; - if (open_sockets(port)) - { - pstring inbuf,outbuf; - bzero(outbuf,smb_size); - if (!send_session_request(inbuf,outbuf)) - return(1); - - send_message(inbuf,outbuf); - - close_sockets(); - } - - return(ret); - } - - if (open_sockets(port)) - { - if (!process(base_directory)) - { - close_sockets(); - return(1); - } - close_sockets(); - } - else - return(1); - - return(0); -} - - -/* error code stuff - put together by Merik Karman - merik@blackadder.dsh.oz.au */ - -typedef struct -{ - char *name; - int code; - char *message; -} err_code_struct; - -/* Dos Error Messages */ -err_code_struct dos_msgs[] = { - {"ERRbadfunc",1,"Invalid function."}, - {"ERRbadfile",2,"File not found."}, - {"ERRbadpath",3,"Directory invalid."}, - {"ERRnofids",4,"No file descriptors available"}, - {"ERRnoaccess",5,"Access denied."}, - {"ERRbadfid",6,"Invalid file handle."}, - {"ERRbadmcb",7,"Memory control blocks destroyed."}, - {"ERRnomem",8,"Insufficient server memory to perform the requested function."}, - {"ERRbadmem",9,"Invalid memory block address."}, - {"ERRbadenv",10,"Invalid environment."}, - {"ERRbadformat",11,"Invalid format."}, - {"ERRbadaccess",12,"Invalid open mode."}, - {"ERRbaddata",13,"Invalid data."}, - {"ERR",14,"reserved."}, - {"ERRbaddrive",15,"Invalid drive specified."}, - {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."}, - {"ERRdiffdevice",17,"Not same device."}, - {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, - {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, - {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, - {"ERRbadpipe",230,"Pipe invalid."}, - {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, - {"ERRpipeclosing",232,"Pipe close in progress."}, - {"ERRnotconnected",233,"No process on other end of pipe."}, - {"ERRmoredata",234,"There is more data to be returned."}, - {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"}, - {NULL,-1,NULL}}; - -/* Server Error Messages */ -err_code_struct server_msgs[] = { - {"ERRerror",1,"Non-specific error code."}, - {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, - {"ERRbadtype",3,"reserved."}, - {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, - {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."}, - {"ERRinvnetname",6,"Invalid network name in tree connect."}, - {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, - {"ERRqfull",49,"Print queue full (files) -- returned by open print file."}, - {"ERRqtoobig",50,"Print queue full -- no space."}, - {"ERRqeof",51,"EOF on print queue dump."}, - {"ERRinvpfid",52,"Invalid print file FID."}, - {"ERRsmbcmd",64,"The server did not recognize the command received."}, - {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."}, - {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."}, - {"ERRreserved",68,"reserved."}, - {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, - {"ERRreserved",70,"reserved."}, - {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."}, - {"ERRpaused",81,"Server is paused."}, - {"ERRmsgoff",82,"Not receiving messages."}, - {"ERRnoroom",83,"No room to buffer message."}, - {"ERRrmuns",87,"Too many remote user names."}, - {"ERRtimeout",88,"Operation timed out."}, - {"ERRnoresource",89,"No resources currently available for request."}, - {"ERRtoomanyuids",90,"Too many UIDs active on this session."}, - {"ERRbaduid",91,"The UID is not known as a valid ID on this session."}, - {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."}, - {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."}, - {"ERRcontmpx",252,"Continue in MPX mode."}, - {"ERRreserved",253,"reserved."}, - {"ERRreserved",254,"reserved."}, - {"ERRnosupport",0xFFFF,"Function not supported."}, - {NULL,-1,NULL}}; - -/* Hard Error Messages */ -err_code_struct hard_msgs[] = { - {"ERRnowrite",19,"Attempt to write on write-protected diskette."}, - {"ERRbadunit",20,"Unknown unit."}, - {"ERRnotready",21,"Drive not ready."}, - {"ERRbadcmd",22,"Unknown command."}, - {"ERRdata",23,"Data error (CRC)."}, - {"ERRbadreq",24,"Bad request structure length."}, - {"ERRseek",25 ,"Seek error."}, - {"ERRbadmedia",26,"Unknown media type."}, - {"ERRbadsector",27,"Sector not found."}, - {"ERRnopaper",28,"Printer out of paper."}, - {"ERRwrite",29,"Write fault."}, - {"ERRread",30,"Read fault."}, - {"ERRgeneral",31,"General failure."}, - {"ERRbadshare",32,"A open conflicts with an existing open."}, - {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - {"ERRwrongdisk",34,"The wrong disk was found in a drive."}, - {"ERRFCBUnavail",35,"No FCBs are available to process request."}, - {"ERRsharebufexc",36,"A sharing buffer has been exceeded."}, - {NULL,-1,NULL}}; - - -struct -{ - int code; - char *class; - err_code_struct *err_msgs; -} err_classes[] = { - {0,"SUCCESS",NULL}, - {0x01,"ERRDOS",dos_msgs}, - {0x02,"ERRSRV",server_msgs}, - {0x03,"ERRHRD",hard_msgs}, - {0x04,"ERRXOS",NULL}, - {0xE1,"ERRRMX1",NULL}, - {0xE2,"ERRRMX2",NULL}, - {0xE3,"ERRRMX3",NULL}, - {0xFF,"ERRCMD",NULL}, - {-1,NULL,NULL}}; - - -/**************************************************************************** -return a SMB error string from a SMB buffer -****************************************************************************/ -char *smb_errstr(char *inbuf) -{ - static pstring ret; - int class = CVAL(inbuf,smb_rcls); - int num = SVAL(inbuf,smb_err); - int i,j; - - for (i=0;err_classes[i].class;i++) - if (err_classes[i].code == class) - { - if (err_classes[i].err_msgs) - { - err_code_struct *err = err_classes[i].err_msgs; - for (j=0;err[j].name;j++) - if (num == err[j].code) - { - if (DEBUGLEVEL > 0) - sprintf(ret,"%s - %s (%s)",err_classes[i].class, - err[j].name,err[j].message); - else - sprintf(ret,"%s - %s",err_classes[i].class,err[j].name); - return ret; - } - } - - sprintf(ret,"%s - %d",err_classes[i].class,num); - return ret; - } - - sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num); - return(ret); -} diff --git a/source/client/clientutil.c b/source/client/clientutil.c deleted file mode 100644 index d1407332ff0..00000000000 --- a/source/client/clientutil.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB client - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifdef SYSLOG -#undef SYSLOG -#endif - -#include "includes.h" - -#ifndef REGISTER -#define REGISTER 0 -#endif - -pstring service=""; -pstring desthost=""; -extern pstring myname; -pstring password = ""; -pstring username=""; -pstring workgroup=WORKGROUP; -BOOL got_pass = False; -BOOL connect_as_printer = False; -BOOL connect_as_ipc = False; - -char cryptkey[8]; -BOOL doencrypt=False; - -extern pstring user_socket_options; - -/* 30 second timeout on most commands */ -#define CLIENT_TIMEOUT (30*1000) -#define SHORT_TIMEOUT (5*1000) - -int name_type = 0x20; - -int max_protocol = PROTOCOL_NT1; - -BOOL readbraw_supported = False; -BOOL writebraw_supported = False; - -extern int DEBUGLEVEL; - -int cnum = 0; -int pid = 0; -int gid = 0; -int uid = 0; -int mid = 0; - -int max_xmit = BUFFER_SIZE; - -BOOL have_ip = False; - -struct in_addr dest_ip; - -extern int Protocol; - -extern int Client; - - -/**************************************************************************** -setup basics in a outgoing packet -****************************************************************************/ -void cli_setup_pkt(char *outbuf) -{ - SSVAL(outbuf,smb_pid,pid); - SSVAL(outbuf,smb_uid,uid); - SSVAL(outbuf,smb_mid,mid); - if (Protocol > PROTOCOL_CORE) - { - SCVAL(outbuf,smb_flg,0x8); - SSVAL(outbuf,smb_flg2,0x1); - } -} - -/**************************************************************************** - receive a SMB trans or trans2 response allocating the necessary memory - ****************************************************************************/ -BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, - int *param_len, char **data,char **param) -{ - int total_data=0; - int total_param=0; - int this_data,this_param; - - *data_len = *param_len = 0; - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - show_msg(inbuf); - - /* sanity check */ - if (CVAL(inbuf,smb_com) != trans) - { - DEBUG(0,("Expected %s response, got command 0x%02x\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); - return(False); - } - if (CVAL(inbuf,smb_rcls) != 0) - return(False); - - /* parse out the lengths */ - total_data = SVAL(inbuf,smb_tdrcnt); - total_param = SVAL(inbuf,smb_tprcnt); - - /* allocate it */ - *data = Realloc(*data,total_data); - *param = Realloc(*param,total_param); - - while (1) - { - this_data = SVAL(inbuf,smb_drcnt); - this_param = SVAL(inbuf,smb_prcnt); - if (this_data) - memcpy(*data + SVAL(inbuf,smb_drdisp), - smb_base(inbuf) + SVAL(inbuf,smb_droff), - this_data); - if (this_param) - memcpy(*param + SVAL(inbuf,smb_prdisp), - smb_base(inbuf) + SVAL(inbuf,smb_proff), - this_param); - *data_len += this_data; - *param_len += this_param; - - /* parse out the total lengths again - they can shrink! */ - total_data = SVAL(inbuf,smb_tdrcnt); - total_param = SVAL(inbuf,smb_tprcnt); - - if (total_data <= *data_len && total_param <= *param_len) - break; - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - show_msg(inbuf); - - /* sanity check */ - if (CVAL(inbuf,smb_com) != trans) - { - DEBUG(0,("Expected %s response, got command 0x%02x\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); - return(False); - } - if (CVAL(inbuf,smb_rcls) != 0) - return(False); - } - - return(True); -} - -/**************************************************************************** -send a session request -****************************************************************************/ -BOOL cli_send_session_request(char *inbuf, char *outbuf) -{ - fstring dest; - char *p; - int len = 4; - /* send a session request (RFC 8002) */ - - strcpy(dest,desthost); - p = strchr(dest,'.'); - if (p) *p = 0; - - /* put in the destination name */ - p = outbuf+len; - name_mangle(dest,p,name_type); - len += name_len(p); - - /* and my name */ - p = outbuf+len; - name_mangle(myname,p,0); - len += name_len(p); - - /* setup the packet length */ - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(Client,outbuf); - DEBUG(5,("Sent session request\n")); - - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */ - { - /* For information, here is the response structure. - * We do the byte-twiddling to for portability. - struct RetargetResponse{ - unsigned char type; - unsigned char flags; - int16 length; - int32 ip_addr; - int16 port; - }; - */ - extern int Client; - int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9); - /* SESSION RETARGET */ - putip((char *)&dest_ip,inbuf+4); - - close_sockets(); - Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); - if (Client == -1) - return False; - - DEBUG(5,("Retargeted\n")); - - set_socket_options(Client,user_socket_options); - - /* Try again */ - return cli_send_session_request(inbuf,outbuf); - } /* C. Hoch 9/14/95 End */ - - - if (CVAL(inbuf,0) != 0x82) - { - int ecode = CVAL(inbuf,4); - DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n", - CVAL(inbuf,0),ecode,myname,desthost)); - switch (ecode) - { - case 0x80: - DEBUG(0,("Not listening on called name\n")); - DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); - DEBUG(0,("You may find the -I option useful for this\n")); - break; - case 0x81: - DEBUG(0,("Not listening for calling name\n")); - DEBUG(0,("Try to connect as another name (instead of %s)\n",myname)); - DEBUG(0,("You may find the -n option useful for this\n")); - break; - case 0x82: - DEBUG(0,("Called name not present\n")); - DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); - DEBUG(0,("You may find the -I option useful for this\n")); - break; - case 0x83: - DEBUG(0,("Called name present, but insufficient resources\n")); - DEBUG(0,("Perhaps you should try again later?\n")); - break; - default: - DEBUG(0,("Unspecified error 0x%X\n",ecode)); - DEBUG(0,("Your server software is being unfriendly\n")); - break; - } - return(False); - } - return(True); -} - - -static struct { - int prot; - char *name; - } -prots[] = - { - {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, - {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, - {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, - {PROTOCOL_LANMAN1,"LANMAN1.0"}, - {PROTOCOL_LANMAN2,"LM1.2X002"}, - {PROTOCOL_LANMAN2,"Samba"}, - {PROTOCOL_NT1,"NT LM 0.12"}, - {PROTOCOL_NT1,"NT LANMAN 1.0"}, - {-1,NULL} - }; - -/**************************************************************************** -send a login command -****************************************************************************/ -BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup) -{ - BOOL was_null = (!inbuf && !outbuf); - int sesskey=0; - time_t servertime = 0; - extern int serverzone; - int sec_mode=0; - int crypt_len; - int max_vcs=0; - char *pass = NULL; - pstring dev; - char *p; - int numprots; - - if (was_null) - { - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - } - - strcpy(dev,"A:"); - if (connect_as_printer) - strcpy(dev,"LPT1:"); - if (connect_as_ipc) - strcpy(dev,"IPC"); - - - if (start_session && !cli_send_session_request(inbuf,outbuf)) - { - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - bzero(outbuf,smb_size); - - /* setup the protocol strings */ - { - int plength; - - for (plength=0,numprots=0; - prots[numprots].name && prots[numprots].prot<=max_protocol; - numprots++) - plength += strlen(prots[numprots].name)+2; - - set_message(outbuf,0,plength,True); - - p = smb_buf(outbuf); - for (numprots=0; - prots[numprots].name && prots[numprots].prot<=max_protocol; - numprots++) - { - *p++ = 2; - strcpy(p,prots[numprots].name); - p += strlen(p) + 1; - } - } - - CVAL(outbuf,smb_com) = SMBnegprot; - cli_setup_pkt(outbuf); - - CVAL(smb_buf(outbuf),0) = 2; - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - show_msg(inbuf); - - if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots)) - { - DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n", - myname,desthost,smb_errstr(inbuf))); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - Protocol = prots[SVAL(inbuf,smb_vwv0)].prot; - - - if (Protocol < PROTOCOL_NT1) { - sec_mode = SVAL(inbuf,smb_vwv1); - max_xmit = SVAL(inbuf,smb_vwv2); - sesskey = IVAL(inbuf,smb_vwv6); - serverzone = SVALS(inbuf,smb_vwv10)*60; - /* this time is converted to GMT by make_unix_date */ - servertime = make_unix_date(inbuf+smb_vwv8); - if (Protocol >= PROTOCOL_COREPLUS) { - readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0); - writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0); - } - crypt_len = smb_buflen(inbuf); - memcpy(cryptkey,smb_buf(inbuf),8); - DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv3))); - max_vcs = SVAL(inbuf,smb_vwv4); - DEBUG(5,("max vcs %d\n",max_vcs)); - DEBUG(5,("max blk %d\n",SVAL(inbuf,smb_vwv5))); - } else { - /* NT protocol */ - sec_mode = CVAL(inbuf,smb_vwv1); - max_xmit = IVAL(inbuf,smb_vwv3+1); - sesskey = IVAL(inbuf,smb_vwv7+1); - serverzone = SVALS(inbuf,smb_vwv15+1)*60; - /* this time arrives in real GMT */ - servertime = interpret_long_date(inbuf+smb_vwv11+1); - crypt_len = CVAL(inbuf,smb_vwv16+1); - memcpy(cryptkey,smb_buf(inbuf),8); - if (IVAL(inbuf,smb_vwv9+1) & 1) - readbraw_supported = writebraw_supported = True; - DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); - max_vcs = SVAL(inbuf,smb_vwv2+1); - DEBUG(5,("max vcs %d\n",max_vcs)); - DEBUG(5,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); - DEBUG(5,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); - } - - DEBUG(5,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); - DEBUG(5,("max xmt %d\n",max_xmit)); - DEBUG(5,("Got %d byte crypt key\n",crypt_len)); - DEBUG(5,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); - - doencrypt = ((sec_mode & 2) != 0); - - if (servertime) { - static BOOL done_time = False; - if (!done_time) { - DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n", - asctime(LocalTime(&servertime)), - -(double)(serverzone/3600.0))); - done_time = True; - } - } - - get_pass: - - if (got_pass) - pass = password; - else - pass = (char *)getpass("Password: "); - - if (Protocol >= PROTOCOL_LANMAN1 && use_setup) - { - fstring pword; - int passlen = strlen(pass)+1; - strcpy(pword,pass); - -#ifdef SMB_PASSWD - if (doencrypt && *pass) { - DEBUG(5,("Using encrypted passwords\n")); - passlen = 24; - SMBencrypt(pass,cryptkey,pword); - } -#else - doencrypt = False; -#endif - - /* if in share level security then don't send a password now */ - if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} - - /* send a session setup command */ - bzero(outbuf,smb_size); - - if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,10,1 + strlen(username) + passlen,True); - CVAL(outbuf,smb_com) = SMBsesssetupX; - cli_setup_pkt(outbuf); - - CVAL(outbuf,smb_vwv0) = 0xFF; - SSVAL(outbuf,smb_vwv2,max_xmit); - SSVAL(outbuf,smb_vwv3,2); - SSVAL(outbuf,smb_vwv4,max_vcs-1); - SIVAL(outbuf,smb_vwv5,sesskey); - SSVAL(outbuf,smb_vwv7,passlen); - p = smb_buf(outbuf); - memcpy(p,pword,passlen); - p += passlen; - strcpy(p,username); - } else { - if (!doencrypt) passlen--; - /* for Win95 */ - set_message(outbuf,13,0,True); - CVAL(outbuf,smb_com) = SMBsesssetupX; - cli_setup_pkt(outbuf); - - CVAL(outbuf,smb_vwv0) = 0xFF; - SSVAL(outbuf,smb_vwv2,BUFFER_SIZE); - SSVAL(outbuf,smb_vwv3,2); - SSVAL(outbuf,smb_vwv4,getpid()); - SIVAL(outbuf,smb_vwv5,sesskey); - SSVAL(outbuf,smb_vwv7,passlen); - SSVAL(outbuf,smb_vwv8,0); - p = smb_buf(outbuf); - memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7); - strcpy(p,username);p = skip_string(p,1); - strcpy(p,workgroup);p = skip_string(p,1); - strcpy(p,"Unix");p = skip_string(p,1); - strcpy(p,"Samba");p = skip_string(p,1); - set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - show_msg(inbuf); - - if (CVAL(inbuf,smb_rcls) != 0) - { - if (! *pass && - ((CVAL(inbuf,smb_rcls) == ERRDOS && - SVAL(inbuf,smb_err) == ERRnoaccess) || - (CVAL(inbuf,smb_rcls) == ERRSRV && - SVAL(inbuf,smb_err) == ERRbadpw))) - { - got_pass = False; - DEBUG(5,("resending login\n")); - goto get_pass; - } - - DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n", - username,myname,desthost,smb_errstr(inbuf))); - DEBUG(0,("You might find the -U or -n options useful\n")); - DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n")); - DEBUG(0,("Some servers also insist on uppercase-only passwords\n")); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - if (Protocol >= PROTOCOL_NT1) { - char *domain,*os,*lanman; - p = smb_buf(inbuf); - os = p; - lanman = skip_string(os,1); - domain = skip_string(lanman,1); - if (*domain || *os || *lanman) - DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman)); - } - - /* use the returned uid from now on */ - if (SVAL(inbuf,smb_uid) != uid) - DEBUG(5,("Server gave us a UID of %d. We gave %d\n", - SVAL(inbuf,smb_uid),uid)); - uid = SVAL(inbuf,smb_uid); - } - - /* now we've got a connection - send a tcon message */ - bzero(outbuf,smb_size); - - if (strncmp(service,"\\\\",2) != 0) - { - DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n")); - DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n")); - } - - - again2: - - { - int passlen = strlen(pass)+1; - fstring pword; - strcpy(pword,pass); - -#ifdef SMB_PASSWD - if (doencrypt && *pass) { - passlen=24; - SMBencrypt(pass,cryptkey,pword); - } -#endif - - /* if in user level security then don't send a password now */ - if ((sec_mode & 1)) { - strcpy(pword, ""); passlen=1; - } - - set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True); - CVAL(outbuf,smb_com) = SMBtconX; - cli_setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv3,passlen); - - p = smb_buf(outbuf); - memcpy(p,pword,passlen); - p += passlen; - strcpy(p,service); - p = skip_string(p,1); - strcpy(p,dev); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - /* trying again with a blank password */ - if (CVAL(inbuf,smb_rcls) != 0 && - (int)strlen(pass) > 0 && - !doencrypt && - Protocol >= PROTOCOL_LANMAN1) - { - DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf))); - strcpy(pass,""); - goto again2; - } - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf))); - DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n")); - DEBUG(0,("Some servers insist that these be in uppercase\n")); - if (was_null) - { - free(inbuf); - free(outbuf); - } - return(False); - } - - - max_xmit = MIN(max_xmit,BUFFER_SIZE-4); - if (max_xmit <= 0) - max_xmit = BUFFER_SIZE - 4; - - cnum = SVAL(inbuf,smb_tid); - - DEBUG(5,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); - - if (was_null) - { - free(inbuf); - free(outbuf); - } - return True; -} - - -/**************************************************************************** -send a logout command -****************************************************************************/ -void cli_send_logout(void) -{ - pstring inbuf,outbuf; - - bzero(outbuf,smb_size); - set_message(outbuf,0,0,True); - CVAL(outbuf,smb_com) = SMBtdis; - SSVAL(outbuf,smb_tid,cnum); - cli_setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,SHORT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf))); - } - - -#ifdef STATS - stats_report(); -#endif - exit(0); -} - - - -/**************************************************************************** -call a remote api -****************************************************************************/ -BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, - int *rdrcnt, char *param,char *data, char **rparam,char **rdata) -{ - static char *inbuf=NULL; - static char *outbuf=NULL; - - if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - cli_send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, - data,param,NULL, - drcnt,prcnt,0, - mdrcnt,mprcnt,0); - - return (cli_receive_trans_response(inbuf,SMBtrans, - rdrcnt,rprcnt, - rdata,rparam)); -} - -/**************************************************************************** - send a SMB trans or trans2 request - ****************************************************************************/ -BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags, - char *data,char *param,uint16 *setup, int ldata,int lparam, - int lsetup,int mdata,int mparam,int msetup) -{ - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - char *outdata,*outparam; - pstring inbuf; - char *p; - - this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam)); - - bzero(outbuf,smb_size); - set_message(outbuf,14+lsetup,0,True); - CVAL(outbuf,smb_com) = trans; - SSVAL(outbuf,smb_tid,cnum); - cli_setup_pkt(outbuf); - - outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3); - outdata = outparam+this_lparam; - - /* primary request */ - SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ - SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ - SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */ - SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */ - SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */ - SSVAL(outbuf,smb_flags,flags); /* flags */ - SIVAL(outbuf,smb_timeout,0); /* timeout */ - SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */ - SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */ - SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */ - SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */ - SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */ - for (i=0;i<lsetup;i++) /* setup[] */ - SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]); - p = smb_buf(outbuf); - if (trans==SMBtrans) - strcpy(p,name); /* name[] */ - else - { - *p++ = 0; /* put in a null smb_name */ - *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */ - } - if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); - if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); - set_message(outbuf,14+lsetup, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False); - - show_msg(outbuf); - send_smb(Client,outbuf); - - if (this_ldata < ldata || this_lparam < lparam) - { - /* receive interim response */ - if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s request failed (%s)\n", - trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf))); - return(False); - } - - tot_data = this_ldata; - tot_param = this_lparam; - - while (tot_data < ldata || tot_param < lparam) - { - this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam)); - - set_message(outbuf,trans==SMBtrans?8:9,0,True); - CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2; - - outparam = smb_buf(outbuf); - outdata = outparam+this_lparam; - - /* secondary request */ - SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ - SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ - SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */ - SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */ - SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */ - SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */ - SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */ - SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */ - if (trans==SMBtrans2) - SSVAL(outbuf,smb_sfid,fid); /* fid */ - if (this_lparam) /* param[] */ - memcpy(outparam,param,this_lparam); - if (this_ldata) /* data[] */ - memcpy(outdata,data,this_ldata); - set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */ - PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data += this_ldata; - tot_param += this_lparam; - } - } - - return(True); -} - - -/**************************************************************************** -open the client sockets -****************************************************************************/ -BOOL cli_open_sockets(int port) -{ - static int last_port; - char *host; - pstring service2; - extern int Client; - - if (port == 0) port=last_port; - last_port=port; - - strupper(service); - - if (*desthost) - { - host = desthost; - } - else - { - strcpy(service2,service); - host = strtok(service2,"\\/"); - strcpy(desthost,host); - } - - DEBUG(5,("Opening sockets\n")); - - if (*myname == 0) - get_myname(myname,NULL); - strupper(myname); - - if (!have_ip) - { - struct hostent *hp; - - if ((hp = Get_Hostbyname(host)) == 0) - { - DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host)); - return False; - } - - putip((char *)&dest_ip,(char *)hp->h_addr); - } - - Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); - if (Client == -1) - return False; - - DEBUG(5,("Connected\n")); - - set_socket_options(Client,user_socket_options); - - return True; -} - -/**************************************************************************** -close and open the connection again -****************************************************************************/ -BOOL cli_reopen_connection(char *inbuf,char *outbuf) -{ - static int open_count=0; - - open_count++; - - if (open_count>5) return(False); - - DEBUG(1,("Trying to re-open connection\n")); - - set_message(outbuf,0,0,True); - SCVAL(outbuf,smb_com,SMBtdis); - SSVAL(outbuf,smb_tid,cnum); - cli_setup_pkt(outbuf); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,SHORT_TIMEOUT); - - close_sockets(); - if (!cli_open_sockets(0)) return(False); - - return(cli_send_login(inbuf,outbuf,True,True)); -} - -/* error code stuff - put together by Merik Karman - merik@blackadder.dsh.oz.au */ - -typedef struct -{ - char *name; - int code; - char *message; -} err_code_struct; - -/* Dos Error Messages */ -err_code_struct dos_msgs[] = { - {"ERRbadfunc",1,"Invalid function."}, - {"ERRbadfile",2,"File not found."}, - {"ERRbadpath",3,"Directory invalid."}, - {"ERRnofids",4,"No file descriptors available"}, - {"ERRnoaccess",5,"Access denied."}, - {"ERRbadfid",6,"Invalid file handle."}, - {"ERRbadmcb",7,"Memory control blocks destroyed."}, - {"ERRnomem",8,"Insufficient server memory to perform the requested function."}, - {"ERRbadmem",9,"Invalid memory block address."}, - {"ERRbadenv",10,"Invalid environment."}, - {"ERRbadformat",11,"Invalid format."}, - {"ERRbadaccess",12,"Invalid open mode."}, - {"ERRbaddata",13,"Invalid data."}, - {"ERR",14,"reserved."}, - {"ERRbaddrive",15,"Invalid drive specified."}, - {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."}, - {"ERRdiffdevice",17,"Not same device."}, - {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, - {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, - {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, - {"ERRbadpipe",230,"Pipe invalid."}, - {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, - {"ERRpipeclosing",232,"Pipe close in progress."}, - {"ERRnotconnected",233,"No process on other end of pipe."}, - {"ERRmoredata",234,"There is more data to be returned."}, - {NULL,-1,NULL}}; - -/* Server Error Messages */ -err_code_struct server_msgs[] = { - {"ERRerror",1,"Non-specific error code."}, - {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, - {"ERRbadtype",3,"reserved."}, - {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, - {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."}, - {"ERRinvnetname",6,"Invalid network name in tree connect."}, - {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, - {"ERRqfull",49,"Print queue full (files) -- returned by open print file."}, - {"ERRqtoobig",50,"Print queue full -- no space."}, - {"ERRqeof",51,"EOF on print queue dump."}, - {"ERRinvpfid",52,"Invalid print file FID."}, - {"ERRsmbcmd",64,"The server did not recognize the command received."}, - {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."}, - {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."}, - {"ERRreserved",68,"reserved."}, - {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, - {"ERRreserved",70,"reserved."}, - {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."}, - {"ERRpaused",81,"Server is paused."}, - {"ERRmsgoff",82,"Not receiving messages."}, - {"ERRnoroom",83,"No room to buffer message."}, - {"ERRrmuns",87,"Too many remote user names."}, - {"ERRtimeout",88,"Operation timed out."}, - {"ERRnoresource",89,"No resources currently available for request."}, - {"ERRtoomanyuids",90,"Too many UIDs active on this session."}, - {"ERRbaduid",91,"The UID is not known as a valid ID on this session."}, - {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."}, - {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."}, - {"ERRcontmpx",252,"Continue in MPX mode."}, - {"ERRreserved",253,"reserved."}, - {"ERRreserved",254,"reserved."}, - {"ERRnosupport",0xFFFF,"Function not supported."}, - {NULL,-1,NULL}}; - -/* Hard Error Messages */ -err_code_struct hard_msgs[] = { - {"ERRnowrite",19,"Attempt to write on write-protected diskette."}, - {"ERRbadunit",20,"Unknown unit."}, - {"ERRnotready",21,"Drive not ready."}, - {"ERRbadcmd",22,"Unknown command."}, - {"ERRdata",23,"Data error (CRC)."}, - {"ERRbadreq",24,"Bad request structure length."}, - {"ERRseek",25 ,"Seek error."}, - {"ERRbadmedia",26,"Unknown media type."}, - {"ERRbadsector",27,"Sector not found."}, - {"ERRnopaper",28,"Printer out of paper."}, - {"ERRwrite",29,"Write fault."}, - {"ERRread",30,"Read fault."}, - {"ERRgeneral",31,"General failure."}, - {"ERRbadshare",32,"A open conflicts with an existing open."}, - {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, - {"ERRwrongdisk",34,"The wrong disk was found in a drive."}, - {"ERRFCBUnavail",35,"No FCBs are available to process request."}, - {"ERRsharebufexc",36,"A sharing buffer has been exceeded."}, - {NULL,-1,NULL}}; - - -struct -{ - int code; - char *class; - err_code_struct *err_msgs; -} err_classes[] = { - {0,"SUCCESS",NULL}, - {0x01,"ERRDOS",dos_msgs}, - {0x02,"ERRSRV",server_msgs}, - {0x03,"ERRHRD",hard_msgs}, - {0x04,"ERRXOS",NULL}, - {0xE1,"ERRRMX1",NULL}, - {0xE2,"ERRRMX2",NULL}, - {0xE3,"ERRRMX3",NULL}, - {0xFF,"ERRCMD",NULL}, - {-1,NULL,NULL}}; - - -/**************************************************************************** -return a SMB error string from a SMB buffer -****************************************************************************/ -char *smb_errstr(char *inbuf) -{ - static pstring ret; - int class = CVAL(inbuf,smb_rcls); - int num = SVAL(inbuf,smb_err); - int i,j; - - for (i=0;err_classes[i].class;i++) - if (err_classes[i].code == class) - { - if (err_classes[i].err_msgs) - { - err_code_struct *err = err_classes[i].err_msgs; - for (j=0;err[j].name;j++) - if (num == err[j].code) - { - if (DEBUGLEVEL > 0) - sprintf(ret,"%s - %s (%s)",err_classes[i].class, - err[j].name,err[j].message); - else - sprintf(ret,"%s - %s",err_classes[i].class,err[j].name); - return ret; - } - } - - sprintf(ret,"%s - %d",err_classes[i].class,num); - return ret; - } - - sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num); - return(ret); -} diff --git a/source/client/clitar.c b/source/client/clitar.c deleted file mode 100644 index cd819ad21fa..00000000000 --- a/source/client/clitar.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Tar Extensions - Copyright (C) Ricky Poulten 1995 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -#include "includes.h" -#include "clitar.h" - -extern BOOL recurse; - -#define SEPARATORS " \t\n\r" -extern int DEBUGLEVEL; -extern int Client; - -/* These defines are for the do_setrattr routine, to indicate - * setting and reseting of file attributes in the function call */ -#define ATTRSET 1 -#define ATTRRESET 0 - -static int attribute = aDIR | aSYSTEM | aHIDDEN; - -#ifndef CLIENT_TIMEOUT -#define CLIENT_TIMEOUT (30*1000) -#endif - -static char *tarbuf; -static int tp, ntarf, tbufsiz; -/* Incremental mode */ -BOOL tar_inc=False; -/* Reset archive bit */ -BOOL tar_reset=False; -/* Include / exclude mode (true=include, false=exclude) */ -BOOL tar_excl=True; -char tar_type='\0'; -static char **cliplist=NULL; -static int clipn=0; - -extern file_info def_finfo; -extern BOOL lowercase; -extern int cnum; -extern BOOL readbraw_supported; -extern int max_xmit; -extern pstring cur_dir; -extern int get_total_time_ms; -extern int get_total_size; -extern int Protocol; - -int blocksize=20; -int tarhandle; - -static void writetarheader(); -static void do_atar(); -static void do_tar(); -static void oct_it(); -static void fixtarname(); -static int dotarbuf(); -static void dozerobuf(); -static void dotareof(); -static void initarbuf(); -static int do_setrattr(); - -/* restore functions */ -static long readtarheader(); -static long unoct(); -static void do_tarput(); -static void unfixtarname(); - -/* - * tar specific utitlities - */ - -/**************************************************************************** -Write a tar header to buffer -****************************************************************************/ -static void writetarheader(int f, char *aname, int size, time_t mtime, - char *amode) -{ - union hblock hb; - int i, chk, l; - char *jp; - - memset(hb.dummy, 0, sizeof(hb.dummy)); - - l=strlen(aname); - if (l >= NAMSIZ) - { - DEBUG(0, ("tar file %s name length exceeds NAMSIZ\n", aname)); - } - - /* use l + 1 to do the null too */ - fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1); - - if (lowercase) - strlower(hb.dbuf.name); - - /* write out a "standard" tar format header */ - - hb.dbuf.name[NAMSIZ-1]='\0'; - strcpy(hb.dbuf.mode, amode); - oct_it(0L, 8, hb.dbuf.uid); - oct_it(0L, 8, hb.dbuf.gid); - oct_it((long) size, 13, hb.dbuf.size); - oct_it((long) mtime, 13, hb.dbuf.mtime); - memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); - hb.dbuf.linkflag='0'; - memset(hb.dbuf.linkname, 0, NAMSIZ); - - for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++); - - oct_it((long) chk, 8, hb.dbuf.chksum); - hb.dbuf.chksum[6] = '\0'; - - (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy)); -} - -/**************************************************************************** -Read a tar header into a hblock structure, and validate -***************************************************************************/ -static long readtarheader(union hblock *hb, file_info *finfo, char *prefix) -{ - long chk, fchk; - int i; - char *jp; - - /* - * read in a "standard" tar format header - we're not that interested - * in that many fields, though - */ - - /* check the checksum */ - for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++); - - if (chk == 0) - return chk; - - /* compensate for blanks in chksum header */ - for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;) - chk-=(0xFF & *jp++); - - chk += ' ' * sizeof(hb->dbuf.chksum); - - fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum)); - - DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n", - chk, fchk, hb->dbuf.chksum)); - - if (fchk != chk) - { - DEBUG(0, ("checksums don't match %d %d\n", fchk, chk)); - return -1; - } - - strcpy(finfo->name, prefix); - - /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */ - unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name, - strlen(hb->dbuf.name) + 1); - -/* can't handle links at present */ - if (hb->dbuf.linkflag != '0') { - if (hb->dbuf.linkflag == 0) { - DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n", - finfo->name)); - } else { - DEBUG(0, ("this tar file appears to contain some kind of link - ignoring\n")); - return -2; - } - } - - if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) - || (*(finfo->name+strlen(finfo->name)-1) == '\\')) - { - finfo->mode=aDIR; - } - else - finfo->mode=0; /* we don't care about mode at the moment, we'll - * just make it a regular file */ - /* - * Bug fix by richard@sj.co.uk - * - * REC: restore times correctly (as does tar) - * We only get the modification time of the file; set the creation time - * from the mod. time, and the access time to current time - */ - finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8); - finfo->atime = time(NULL); - finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size)); - - return True; -} - -/**************************************************************************** -Write out the tar buffer to tape or wherever -****************************************************************************/ -static int dotarbuf(int f, char *b, int n) -{ - int fail=1, writ=n; - - /* This routine and the next one should be the only ones that do write()s */ - if (tp + n >= tbufsiz) - { - int diff; - - diff=tbufsiz-tp; - memcpy(tarbuf + tp, b, diff); - fail=fail && (1+write(f, tarbuf, tbufsiz)); - n-=diff; - b+=diff; - tp=0; - - while (n >= tbufsiz) - { - fail=fail && (1 + write(f, b, tbufsiz)); - n-=tbufsiz; - b+=tbufsiz; - } - } - if (n>0) { - memcpy(tarbuf+tp, b, n); - tp+=n; - } - - return(fail ? writ : 0); -} - -/**************************************************************************** -Write a zeros to buffer / tape -****************************************************************************/ -static void dozerobuf(int f, int n) -{ - /* short routine just to write out n zeros to buffer - - * used to round files to nearest block - * and to do tar EOFs */ - - if (n+tp >= tbufsiz) - { - memset(tarbuf+tp, 0, tbufsiz-tp); - write(f, tarbuf, tbufsiz); - memset(tarbuf, 0, (tp+=n-tbufsiz)); - } - else - { - memset(tarbuf+tp, 0, n); - tp+=n; - } -} - -/**************************************************************************** -Malloc tape buffer -****************************************************************************/ -static void initarbuf() -{ - /* initialize tar buffer */ - tbufsiz=blocksize*TBLOCK; - tarbuf=malloc(tbufsiz); - - /* reset tar buffer pointer and tar file counter */ - tp=0; ntarf=0; -} - -/**************************************************************************** -Write two zero blocks at end of file -****************************************************************************/ -static void dotareof(int f) -{ - struct stat stbuf; - /* Two zero blocks at end of file, write out full buffer */ - - (void) dozerobuf(f, TBLOCK); - (void) dozerobuf(f, TBLOCK); - - if (fstat(f, &stbuf) == -1) - { - DEBUG(0, ("Couldn't stat file handle\n")); - return; - } - - /* Could be a pipe, in which case S_ISREG should fail, - * and we should write out at full size */ - if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz); -} - -/**************************************************************************** -(Un)mangle DOS pathname, make nonabsolute -****************************************************************************/ -static void fixtarname(char *tptr, char *fp, int l) -{ - /* add a '.' to start of file name, convert from ugly dos \'s in path - * to lovely unix /'s :-} */ - - *tptr++='.'; -#ifdef KANJI - while (l > 0) { - if (is_shift_jis (*fp)) { - *tptr++ = *fp++; - *tptr++ = *fp++; - l -= 2; - } else if (is_kana (*fp)) { - *tptr++ = *fp++; - l--; - } else if (*fp == '\\') { - *tptr++ = '/'; - fp++; - l--; - } else { - *tptr++ = *fp++; - l--; - } - } -#else - while (l--) { *tptr=(*fp == '\\') ? '/' : *fp; tptr++; fp++; } -#endif -} - -/**************************************************************************** -Convert from decimal to octal string -****************************************************************************/ -static void oct_it (register long value, register int ndgs, register char *p) -{ - /* Converts long to octal string, pads with leading zeros */ - - /* skip final null, but do final space */ - --ndgs; - p[--ndgs] = ' '; - - /* Loop does at least one digit */ - do { - p[--ndgs] = '0' + (char) (value & 7); - value >>= 3; - } - while (ndgs > 0 && value != 0); - - /* Do leading zeros */ - while (ndgs > 0) - p[--ndgs] = '0'; -} - -/**************************************************************************** -Convert from octal string to long -***************************************************************************/ -static long unoct(char *p, int ndgs) -{ - long value=0; - /* Converts octal string to long, ignoring any non-digit */ - - while (--ndgs) - { - if (isdigit(*p)) - value = (value << 3) | (long) (*p - '0'); - - p++; - } - - return value; -} - -/**************************************************************************** -Compare two strings in a slash insensitive way -***************************************************************************/ -int strslashcmp(char *s1,char *s2) -{ - while(*s1 && *s2 && - (*s1 == *s2 - || tolower(*s1) == tolower(*s2) - || (*s1 == '\\' && *s2=='/') - || (*s1 == '/' && *s2=='\\'))) { - s1++; s2++; - } - - return *s1-*s2; -} - -/* - * general smb utility functions - */ -/**************************************************************************** -Set DOS file attributes -***************************************************************************/ -static int do_setrattr(char *fname, int attr, int setit) -{ - /* - * First get the existing attribs from existing file - */ - char *inbuf,*outbuf; - char *p; - pstring name; - int fattr; - - strcpy(name,fname); - strcpy(fname,"\\"); - strcat(fname,name); - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return False; - } - - /* send an smb getatr message */ - - memset(outbuf,0,smb_size); - set_message(outbuf,0,2 + strlen(fname),True); - CVAL(outbuf,smb_com) = SMBgetatr; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,fname); - p += (strlen(fname)+1); - - *p++ = 4; - *p++ = 0; - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - DEBUG(5,("getatr: %s\n",smb_errstr(inbuf))); - else - { - DEBUG(5,("\nattr 0x%X time %d size %d\n", - (int)CVAL(inbuf,smb_vwv0), - SVAL(inbuf,smb_vwv1), - SVAL(inbuf,smb_vwv3))); - } - - fattr=CVAL(inbuf,smb_vwv0); - - /* combine found attributes with bits to be set or reset */ - - attr=setit ? (fattr | attr) : (fattr & ~attr); - - /* now try and set attributes by sending smb reset message */ - - /* clear out buffer and start again */ - memset(outbuf,0,smb_size); - set_message(outbuf,8,4 + strlen(fname),True); - CVAL(outbuf,smb_com) = SMBsetatr; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,attr); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,fname); - p += (strlen(fname)+1); - - *p++ = 4; - *p++ = 0; - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s setting attributes on file %s\n", - smb_errstr(inbuf), fname)); - free(inbuf);free(outbuf); - return(False); - } - - free(inbuf);free(outbuf); - return(True); -} - -/**************************************************************************** -Create a file on a share -***************************************************************************/ -static BOOL smbcreat(file_info finfo, int *fnum, char *inbuf, char *outbuf) -{ - char *p; - /* *must* be called with buffer ready malloc'ed */ - /* open remote file */ - - memset(outbuf,0,smb_size); - set_message(outbuf,3,2 + strlen(finfo.name),True); - CVAL(outbuf,smb_com) = SMBcreate; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,finfo.mode); - put_dos_date3(outbuf,smb_vwv1,finfo.mtime); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,finfo.name); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf), - finfo.name)); - return 0; - } - - *fnum = SVAL(inbuf,smb_vwv0); - return True; -} - -/**************************************************************************** -Write a file to a share -***************************************************************************/ -static BOOL smbwrite(int fnum, int n, int low, int high, int left, - char *bufferp, char *inbuf, char *outbuf) -{ - /* *must* be called with buffer ready malloc'ed */ - - memset(outbuf,0,smb_size); - set_message(outbuf,5,n + 3,True); - - memcpy(smb_buf(outbuf)+3, bufferp, n); - - set_message(outbuf,5,n + 3, False); - CVAL(outbuf,smb_com) = SMBwrite; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,n); - SIVAL(outbuf,smb_vwv2,low); - SSVAL(outbuf,smb_vwv4,left); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,n); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s writing remote file\n",smb_errstr(inbuf))); - return False; - } - - if (n != SVAL(inbuf,smb_vwv0)) - { - DEBUG(0,("Error: only wrote %d bytes out of %d\n", - SVAL(inbuf,smb_vwv0), n)); - return False; - } - - return True; -} - -/**************************************************************************** -Close a file on a share -***************************************************************************/ -static BOOL smbshut(file_info finfo, int fnum, char *inbuf, char *outbuf) -{ - /* *must* be called with buffer ready malloc'ed */ - - memset(outbuf,0,smb_size); - set_message(outbuf,3,0,True); - CVAL(outbuf,smb_com) = SMBclose; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - put_dos_date3(outbuf,smb_vwv1,finfo.mtime); - - DEBUG(3,("Setting date to %s (0x%X)", - asctime(LocalTime(&finfo.mtime)), - finfo.mtime)); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s closing remote file %s\n",smb_errstr(inbuf), - finfo.name)); - return False; - } - - return True; -} - -/**************************************************************************** -Verify existence of path on share -***************************************************************************/ -static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf) -{ - char *p; - - memset(outbuf,0,smb_size); - set_message(outbuf,0,4 + strlen(fname),True); - CVAL(outbuf,smb_com) = SMBchkpth; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,fname); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - DEBUG(5,("smbchkpath: %s\n",smb_errstr(inbuf))); - - return(CVAL(inbuf,smb_rcls) == 0); -} - -/**************************************************************************** -Make a directory on share -***************************************************************************/ -static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf) -{ - /* *must* be called with buffer ready malloc'ed */ - char *p; - - memset(outbuf,0,smb_size); - set_message(outbuf,0,2 + strlen(fname),True); - - CVAL(outbuf,smb_com) = SMBmkdir; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - strcpy(p,fname); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("%s making remote directory %s\n", - smb_errstr(inbuf),fname)); - return(False); - } - - return(True); -} - -/**************************************************************************** -Ensure a remote path exists (make if necessary) -***************************************************************************/ -static BOOL ensurepath(char *fname, char *inbuf, char *outbuf) -{ - /* *must* be called with buffer ready malloc'ed */ - /* ensures path exists */ - - pstring partpath, ffname; - char *p=fname, *basehack; - - *partpath = 0; - - /* fname copied to ffname so can strtok */ - - strcpy(ffname, fname); - - /* do a `basename' on ffname, so don't try and make file name directory */ - if ((basehack=strrchr(ffname, '\\')) == NULL) - return True; - else - *basehack='\0'; - - p=strtok(ffname, "\\"); - - while (p) - { - strcat(partpath, p); - - if (!smbchkpath(partpath, inbuf, outbuf)) { - if (!smbmkdir(partpath, inbuf, outbuf)) - { - DEBUG(0, ("Error mkdirhiering\n")); - return False; - } - else - DEBUG(3, ("mkdirhiering %s\n", partpath)); - - } - - strcat(partpath, "\\"); - p = strtok(NULL,"/\\"); - } - - return True; -} - -int padit(char *buf, int bufsize, int padsize) -{ - int berr= 0; - int bytestowrite; - - DEBUG(0, ("Padding with %d zeros\n", padsize)); - memset(buf, 0, bufsize); - while( !berr && padsize > 0 ) { - bytestowrite= MIN(bufsize, padsize); - berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite; - padsize -= bytestowrite; - } - - return berr; -} - -/* - * smbclient functions - */ -/**************************************************************************** -append one remote file to the tar file -***************************************************************************/ -static void do_atar(char *rname,char *lname,file_info *finfo1) -{ - int fnum; - uint32 nread=0; - char *p; - char *inbuf,*outbuf; - file_info finfo; - BOOL close_done = False; - BOOL shallitime=True; - BOOL ignore_close_error = False; - char *dataptr=NULL; - int datalen=0; - - struct timeval tp_start; - GetTimeOfDay(&tp_start); - - if (finfo1) - finfo = *finfo1; - else - finfo = def_finfo; - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - memset(outbuf,0,smb_size); - set_message(outbuf,15,1 + strlen(rname),True); - - CVAL(outbuf,smb_com) = SMBopenX; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,1); - SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4)); - SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN); - SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN); - SSVAL(outbuf,smb_vwv8,1); - - p = smb_buf(outbuf); - strcpy(p,rname); - p = skip_string(p,1); - - dos_clean_name(rname); - - /* do a chained openX with a readX? */ - if (finfo.size > 0) - { - SSVAL(outbuf,smb_vwv0,SMBreadX); - SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4); - memset(p,0,200); - p -= smb_wct; - SSVAL(p,smb_wct,10); - SSVAL(p,smb_vwv0,0xFF); - SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size)); - SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size)); - smb_setlen(outbuf,smb_len(outbuf)+11*2+1); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - if (CVAL(inbuf,smb_rcls) == ERRSRV && - SVAL(inbuf,smb_err) == ERRnoresource && - reopen_connection(inbuf,outbuf)) - { - do_atar(rname,lname,finfo1); - free(inbuf);free(outbuf); - return; - } - - DEBUG(0,("%s opening remote file %s\n",smb_errstr(inbuf),rname)); - free(inbuf);free(outbuf); - return; - } - - strcpy(finfo.name,rname); - if (!finfo1) - { - finfo.mode = SVAL(inbuf,smb_vwv3); - finfo.size = IVAL(inbuf,smb_vwv4); - finfo.mtime = make_unix_date3(inbuf+smb_vwv6); - finfo.atime = finfo.ctime = finfo.mtime; - } - - DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode)); - - fnum = SVAL(inbuf,smb_vwv2); - - if (tar_inc && !(finfo.mode & aARCH)) - { - DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name)); - shallitime=0; - } - else - { - if (SVAL(inbuf,smb_vwv0) == SMBreadX) - { - p = (inbuf+4+SVAL(inbuf,smb_vwv1)) - smb_wct; - datalen = SVAL(p,smb_vwv5); - dataptr = inbuf + 4 + SVAL(p,smb_vwv6); - } - else - { - dataptr = NULL; - datalen = 0; - } - - DEBUG(1,("getting file %s of size %d bytes as a tar file %s", - finfo.name, - finfo.size, - lname)); - - /* write a tar header, don't bother with mode - just set to 100644 */ - writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0"); - - while (nread < finfo.size && !close_done) - { - int method = -1; - static BOOL can_chain_close=True; - - p=NULL; - - DEBUG(3,("nread=%d\n",nread)); - - /* 3 possible read types. readbraw if a large block is required. - readX + close if not much left and read if neither is supported */ - - /* we might have already read some data from a chained readX */ - if (dataptr && datalen>0) - method=3; - - /* if we can finish now then readX+close */ - if (method<0 && can_chain_close && (Protocol >= PROTOCOL_LANMAN1) && - ((finfo.size - nread) < - (max_xmit - (2*smb_size + 13*SIZEOFWORD + 300)))) - method = 0; - - /* if we support readraw then use that */ - if (method<0 && readbraw_supported) - method = 1; - - /* if we can then use readX */ - if (method<0 && (Protocol >= PROTOCOL_LANMAN1)) - method = 2; - - - switch (method) - { - /* use readX */ - case 0: - case 2: - if (method == 0) - close_done = True; - - /* use readX + close */ - memset(outbuf,0,smb_size); - set_message(outbuf,10,0,True); - CVAL(outbuf,smb_com) = SMBreadX; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - if (close_done) - { - CVAL(outbuf,smb_vwv0) = SMBclose; - SSVAL(outbuf,smb_vwv1,PTR_DIFF(smb_buf(outbuf),outbuf) - 4); - } - else - CVAL(outbuf,smb_vwv0) = 0xFF; - - - SSVAL(outbuf,smb_vwv2,fnum); - SIVAL(outbuf,smb_vwv3,nread); - SSVAL(outbuf,smb_vwv5,MIN(max_xmit-200,finfo.size - nread)); - SSVAL(outbuf,smb_vwv6,0); - SIVAL(outbuf,smb_vwv7,0); - SSVAL(outbuf,smb_vwv9,MIN(0xFFFF,finfo.size-nread)); - - if (close_done) - { - p = smb_buf(outbuf); - memset(p,0,9); - - CVAL(p,0) = 3; - SSVAL(p,1,fnum); - SIVALS(p,3,-1); - - /* now set the total packet length */ - smb_setlen(outbuf,smb_len(outbuf)+9); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf))); - break; - } - - if (close_done && - SVAL(inbuf,smb_vwv0) != SMBclose) - { - /* NOTE: WfWg sometimes just ignores the chained - command! This seems to break the spec? */ - DEBUG(3,("Rejected chained close?\n")); - close_done = False; - can_chain_close = False; - ignore_close_error = True; - } - - datalen = SVAL(inbuf,smb_vwv5); - dataptr = inbuf + 4 + SVAL(inbuf,smb_vwv6); - break; - - - /* use readbraw */ - case 1: - { - static int readbraw_size = 0xFFFF; - - extern int Client; - memset(outbuf,0,smb_size); - set_message(outbuf,8,0,True); - CVAL(outbuf,smb_com) = SMBreadbraw; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - SSVAL(outbuf,smb_vwv0,fnum); - SIVAL(outbuf,smb_vwv1,nread); - SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size)); - SSVAL(outbuf,smb_vwv4,0); - SIVALS(outbuf,smb_vwv5,-1); - send_smb(Client,outbuf); - - /* Now read the raw data into the buffer and write it */ - if(read_smb_length(Client,inbuf,0) == -1) { - DEBUG(0,("Failed to read length in readbraw\n")); - exit(1); - } - - /* Even though this is not an smb message, smb_len - returns the generic length of an smb message */ - datalen = smb_len(inbuf); - - if (datalen == 0) - { - /* we got a readbraw error */ - DEBUG(4,("readbraw error - reducing size\n")); - readbraw_size = (readbraw_size * 9) / 10; - - if (readbraw_size < max_xmit) - { - DEBUG(0,("disabling readbraw\n")); - readbraw_supported = False; - } - - dataptr=NULL; - continue; - } - - if(read_data(Client,inbuf,datalen) != datalen) { - DEBUG(0,("Failed to read data in readbraw\n")); - exit(1); - } - dataptr = inbuf; - } - break; - - case 3: - /* we've already read some data with a chained readX */ - break; - - default: - /* use plain read */ - memset(outbuf,0,smb_size); - set_message(outbuf,5,0,True); - CVAL(outbuf,smb_com) = SMBread; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread)); - SIVAL(outbuf,smb_vwv2,nread); - SSVAL(outbuf,smb_vwv4,finfo.size - nread); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("Error %s reading remote file\n",smb_errstr(inbuf))); - break; - } - - datalen = SVAL(inbuf,smb_vwv0); - dataptr = smb_buf(inbuf) + 3; - break; - } - - - /* add received bits of file to buffer - dotarbuf will - * write out in 512 byte intervals */ - if (dotarbuf(tarhandle,dataptr,datalen) != datalen) - { - DEBUG(0,("Error writing local file\n")); - break; - } - - nread += datalen; - if (datalen == 0) - { - DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname)); - break; - } - - dataptr=NULL; - datalen=0; - } - - /* pad tar file with zero's if we couldn't get entire file */ - if (nread < finfo.size) - { - DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread)); - if (padit(inbuf, BUFFER_SIZE, finfo.size - nread)) - DEBUG(0,("Error writing local file\n")); - } - - /* round tar file to nearest block */ - if (finfo.size % TBLOCK) - dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK)); - - ntarf++; - } - - if (!close_done) - { - memset(outbuf,0,smb_size); - set_message(outbuf,3,0,True); - CVAL(outbuf,smb_com) = SMBclose; - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,fnum); - SIVALS(outbuf,smb_vwv1,-1); - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0) - { - DEBUG(0,("Error %s closing remote file\n",smb_errstr(inbuf))); - free(inbuf);free(outbuf); - return; - } - } - - if (shallitime) - { - struct timeval tp_end; - int this_time; - - /* if shallitime is true then we didn't skip */ - if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET); - - GetTimeOfDay(&tp_end); - this_time = - (tp_end.tv_sec - tp_start.tv_sec)*1000 + - (tp_end.tv_usec - tp_start.tv_usec)/1000; - get_total_time_ms += this_time; - get_total_size += finfo.size; - - /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */ - DEBUG(1,("(%g kb/s) (average %g kb/s)\n", - finfo.size / MAX(0.001, (1.024*this_time)), - get_total_size / MAX(0.001, (1.024*get_total_time_ms)))); - } - - free(inbuf);free(outbuf); -} - -/**************************************************************************** -Append single file to tar file (or not) -***************************************************************************/ -static void do_tar(file_info *finfo) -{ - pstring rname; - - if (strequal(finfo->name,".") || strequal(finfo->name,"..")) - return; - - /* Is it on the exclude list ? */ - if (!tar_excl && clipn) { - pstring exclaim; - - strcpy(exclaim, cur_dir); - *(exclaim+strlen(exclaim)-1)='\0'; - - if (clipfind(cliplist, clipn, exclaim)) { - DEBUG(3,("Skipping directory %s\n", exclaim)); - return; - } - - strcat(exclaim, "\\"); - strcat(exclaim, finfo->name); - - if (clipfind(cliplist, clipn, exclaim)) { - DEBUG(3,("Skipping file %s\n", exclaim)); - return; - } - } - - if (finfo->mode & aDIR) - { - pstring saved_curdir; - pstring mtar_mask; - char *inbuf,*outbuf; - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - strcpy(saved_curdir,cur_dir); - - strcat(cur_dir,finfo->name); - strcat(cur_dir,"\\"); - - /* write a tar directory, don't bother with mode - just set it to - * 40755 */ - writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0"); - strcpy(mtar_mask,cur_dir); - strcat(mtar_mask,"*"); - - do_dir((char *)inbuf,(char *)outbuf,mtar_mask,attribute,do_tar,recurse); - strcpy(cur_dir,saved_curdir); - free(inbuf);free(outbuf); - } - else - { - strcpy(rname,cur_dir); - strcat(rname,finfo->name); - do_atar(rname,finfo->name,finfo); - } -} - -/**************************************************************************** -Convert from UNIX to DOS file names -***************************************************************************/ -static void unfixtarname(char *tptr, char *fp, int l) -{ - /* remove '.' from start of file name, convert from unix /'s to - * dos \'s in path. Kill any absolute path names. - */ - - if (*fp == '.') fp++; - if (*fp == '\\' || *fp == '/') fp++; - -#ifdef KANJI - while (l > 0) { - if (is_shift_jis (*fp)) { - *tptr++ = *fp++; - *tptr++ = *fp++; - l -= 2; - } else if (is_kana (*fp)) { - *tptr++ = *fp++; - l--; - } else if (*fp == '/') { - *tptr++ = '\\'; - fp++; - l--; - } else { - *tptr++ = *fp++; - l--; - } - } -#else - while (l--) { *tptr=(*fp == '/') ? '\\' : *fp; tptr++; fp++; } -#endif -} - -static void do_tarput() -{ - file_info finfo; - int nread=0, bufread; - char *inbuf,*outbuf; - int fsize=0; - int fnum; - struct timeval tp_start; - BOOL tskip=False; /* We'll take each file as it comes */ - - GetTimeOfDay(&tp_start); - - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - - if (!inbuf || !outbuf) - { - DEBUG(0,("out of memory\n")); - return; - } - - /* - * Must read in tbufsiz dollops - */ - - /* These should be the only reads in clitar.c */ - while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) { - char *bufferp, *endofbuffer; - int chunk; - - /* Code to handle a short read. - * We always need a TBLOCK full of stuff - */ - if (bufread % TBLOCK) { - int lchunk=TBLOCK-(bufread % TBLOCK); - int lread; - - /* It's a shorty - a short read that is */ - DEBUG(3, ("Short read, read %d so far (need %d)\n", bufread, lchunk)); - - while ((lread=read(tarhandle, tarbuf+bufread, lchunk))>0) { - bufread+=lread; - if (!(lchunk-=lread)) break; - } - - /* If we've reached EOF then that must be a short file */ - if (lread<=0) break; - } - - bufferp=tarbuf; - endofbuffer=tarbuf+bufread; - - if (tskip) { - if (fsize<bufread) { - tskip=False; - bufferp+=fsize; - fsize=0; - } else { - if (fsize==bufread) tskip=False; - fsize-=bufread; - continue; - } - } - - do { - if (!fsize) - { - switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) - { - case -2: /* something dodgy but not fatal about this */ - DEBUG(0, ("skipping %s...\n", finfo.name)); - bufferp+=TBLOCK; /* header - like a link */ - continue; - case -1: - DEBUG(0, ("abandoning restore\n")); - free(inbuf); free(outbuf); - return; - case 0: /* chksum is zero - we assume that one all zero - *header block will do for eof */ - DEBUG(0, - ("total of %d tar files restored to share\n", ntarf)); - free(inbuf); free(outbuf); - return; - default: - break; - } - - tskip=clipn - && (clipfind(cliplist, clipn, finfo.name) ^ tar_excl); - if (tskip) { - bufferp+=TBLOCK; - if (finfo.mode & aDIR) - continue; - else if ((fsize=finfo.size) % TBLOCK) { - fsize+=TBLOCK-(fsize%TBLOCK); - } - if (fsize<endofbuffer-bufferp) { - bufferp+=fsize; - fsize=0; - continue; - } else { - fsize-=endofbuffer-bufferp; - break; - } - } - - if (finfo.mode & aDIR) - { - if (!smbchkpath(finfo.name, inbuf, outbuf) - && !smbmkdir(finfo.name, inbuf, outbuf)) - { - DEBUG(0, ("abandoning restore\n")); - free(inbuf); free(outbuf); - return; - } - else - { - bufferp+=TBLOCK; - continue; - } - } - - fsize=finfo.size; - - if (ensurepath(finfo.name, inbuf, outbuf) - && !smbcreat(finfo, &fnum, inbuf, outbuf)) - { - DEBUG(0, ("abandoning restore\n")); - free(inbuf);free(outbuf); - return; - } - - DEBUG(0,("restore tar file %s of size %d bytes\n", - finfo.name,finfo.size)); - - nread=0; - if ((bufferp+=TBLOCK) >= endofbuffer) break; - } /* if (!fsize) */ - - /* write out the file in chunk sized chunks - don't - * go past end of buffer though */ - chunk=(fsize-nread < endofbuffer - bufferp) - ? fsize - nread : endofbuffer - bufferp; - - while (chunk > 0) { - int minichunk=MIN(chunk, max_xmit-200); - - if (!smbwrite(fnum, /* file descriptor */ - minichunk, /* n */ - nread, /* offset low */ - 0, /* offset high - not implemented */ - fsize-nread, /* left - only hint to server */ - bufferp, - inbuf, - outbuf)) - { - DEBUG(0, ("Error writing remote file\n")); - free(inbuf); free(outbuf); - return; - } - DEBUG(5, ("chunk writing fname=%s fnum=%d nread=%d minichunk=%d chunk=%d size=%d\n", finfo.name, fnum, nread, minichunk, chunk, fsize)); - - bufferp+=minichunk; nread+=minichunk; - chunk-=minichunk; - } - - if (nread>=fsize) - { - if (!smbshut(finfo, fnum, inbuf, outbuf)) - { - DEBUG(0, ("Error closing remote file\n")); - free(inbuf);free(outbuf); - return; - } - if (fsize % TBLOCK) bufferp+=TBLOCK - (fsize % TBLOCK); - DEBUG(5, ("bufferp is now %d (psn=%d)\n", - (long) bufferp, (long)(bufferp - tarbuf))); - ntarf++; - fsize=0; - } - } while (bufferp < endofbuffer); - } - - DEBUG(0, ("premature eof on tar file ?\n")); - DEBUG(0,("total of %d tar files restored to share\n", ntarf)); - - free(inbuf); free(outbuf); -} - -/* - * samba interactive commands - */ - -/**************************************************************************** -Blocksize command -***************************************************************************/ -void cmd_block(void) -{ - fstring buf; - int block; - - if (!next_token(NULL,buf,NULL)) - { - DEBUG(0, ("blocksize <n>\n")); - return; - } - - block=atoi(buf); - if (block < 0 || block > 65535) - { - DEBUG(0, ("blocksize out of range")); - return; - } - - blocksize=block; - DEBUG(1,("blocksize is now %d\n", blocksize)); -} - -/**************************************************************************** -command to set incremental / reset mode -***************************************************************************/ -void cmd_tarmode(void) -{ - fstring buf; - - while (next_token(NULL,buf,NULL)) { - if (strequal(buf, "full")) - tar_inc=False; - else if (strequal(buf, "inc")) - tar_inc=True; - else if (strequal(buf, "reset")) - tar_reset=True; - else if (strequal(buf, "noreset")) - tar_reset=False; - else DEBUG(0, ("tarmode: unrecognised option %s\n", buf)); - } - - DEBUG(0, ("tarmode is now %s, %s\n", - tar_inc ? "incremental" : "full", - tar_reset ? "reset" : "noreset")); -} - -/**************************************************************************** -Feeble attrib command -***************************************************************************/ -void cmd_setmode(void) -{ - char *q; - fstring buf; - pstring fname; - int attra[2]; - int direct=1; - - attra[0] = attra[1] = 0; - - if (!next_token(NULL,buf,NULL)) - { - DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n")); - return; - } - - strcpy(fname, cur_dir); - strcat(fname, buf); - - while (next_token(NULL,buf,NULL)) { - q=buf; - - while(*q) - switch (*q++) { - case '+': direct=1; - break; - case '-': direct=0; - break; - case 'r': attra[direct]|=aRONLY; - break; - case 'h': attra[direct]|=aHIDDEN; - break; - case 's': attra[direct]|=aSYSTEM; - break; - case 'a': attra[direct]|=aARCH; - break; - default: DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n")); - return; - } - } - - if (attra[ATTRSET]==0 && attra[ATTRRESET]==0) - { - DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n")); - return; - } - - DEBUG(1, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET])); - (void) do_setrattr(fname, attra[ATTRSET], ATTRSET); - (void) do_setrattr(fname, attra[ATTRRESET], ATTRRESET); -} - -/**************************************************************************** -Principal command for creating / extracting -***************************************************************************/ -void cmd_tar(char *inbuf, char *outbuf) -{ - fstring buf; - char **argl; - int argcl; - - if (!next_token(NULL,buf,NULL)) - { - DEBUG(0,("tar <c|x>[IXbga] <filename>\n")); - return; - } - - argl=toktocliplist(&argcl, NULL); - if (!tar_parseargs(argcl, argl, buf, 0)) - return; - - process_tar(inbuf, outbuf); - - free(argl); -} - -/**************************************************************************** -Command line (option) version -***************************************************************************/ -int process_tar(char *inbuf, char *outbuf) -{ - initarbuf(); - switch(tar_type) { - case 'x': - do_tarput(); - free(tarbuf); - close(tarhandle); - break; - case 'r': - case 'c': - if (clipn && tar_excl) { - int i; - pstring tarmac; - - for (i=0; i<clipn; i++) { - DEBUG(0,("arg %d = %s\n", i, cliplist[i])); - - if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') { - *(cliplist[i]+strlen(cliplist[i])-1)='\0'; - } - - if (strrchr(cliplist[i], '\\')) { - pstring saved_dir; - - strcpy(saved_dir, cur_dir); - - if (*cliplist[i]=='\\') { - strcpy(tarmac, cliplist[i]); - } else { - strcpy(tarmac, cur_dir); - strcat(tarmac, cliplist[i]); - } - strcpy(cur_dir, tarmac); - *(strrchr(cur_dir, '\\')+1)='\0'; - - do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse); - strcpy(cur_dir,saved_dir); - } else { - strcpy(tarmac, cur_dir); - strcat(tarmac, cliplist[i]); - do_dir((char *)inbuf,(char *)outbuf,tarmac,attribute,do_tar,recurse); - } - } - } else { - pstring mask; - strcpy(mask,cur_dir); - strcat(mask,"\\*"); - do_dir((char *)inbuf,(char *)outbuf,mask,attribute,do_tar,recurse); - } - - if (ntarf) dotareof(tarhandle); - close(tarhandle); - free(tarbuf); - - DEBUG(0, ("tar: dumped %d tar files\n", ntarf)); - break; - } - - return(0); -} - -/**************************************************************************** -Find a token (filename) in a clip list -***************************************************************************/ -int clipfind(char **aret, int ret, char *tok) -{ - if (aret==NULL) return 0; - - /* ignore leading slashes or dots in token */ - while(strchr("/\\.", *tok)) tok++; - - while(ret--) { - char *pkey=*aret++; - - /* ignore leading slashes or dots in list */ - while(strchr("/\\.", *pkey)) pkey++; - - if (!strslashcmp(pkey, tok)) return 1; - } - - return 0; -} - -/**************************************************************************** -Parse tar arguments. Sets tar_type, tar_excl, etc. -***************************************************************************/ -int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind) -{ - char tar_clipfl='\0'; - - /* Reset back to defaults - could be from interactive version - * reset mode and archive mode left as they are though - */ - tar_type='\0'; - tar_excl=True; - - while (*Optarg) - switch(*Optarg++) { - case 'c': - tar_type='c'; - break; - case 'x': - if (tar_type=='c') { - printf("Tar must be followed by only one of c or x.\n"); - return 0; - } - tar_type='x'; - break; - case 'b': - if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) { - DEBUG(0,("Option b must be followed by valid blocksize\n")); - return 0; - } else { - Optind++; - } - break; - case 'g': - tar_inc=True; - break; - case 'N': - if (Optind>=argc) { - DEBUG(0,("Option N must be followed by valid file name\n")); - return 0; - } else { - struct stat stbuf; - extern time_t newer_than; - - if (sys_stat(argv[Optind], &stbuf) == 0) { - newer_than = stbuf.st_mtime; - DEBUG(1,("Getting files newer than %s", - asctime(LocalTime(&newer_than)))); - Optind++; - } else { - DEBUG(0,("Error setting newer-than time\n")); - return 0; - } - } - break; - case 'a': - tar_reset=True; - break; - case 'I': - if (tar_clipfl) { - DEBUG(0,("Only one of I,X must be specified\n")); - return 0; - } - tar_clipfl='I'; - break; - case 'X': - if (tar_clipfl) { - DEBUG(0,("Only one of I,X must be specified\n")); - return 0; - } - tar_clipfl='X'; - break; - default: - DEBUG(0,("Unknown tar option\n")); - return 0; - } - - if (!tar_type) { - printf("Option T must be followed by one of c or x.\n"); - return 0; - } - - tar_excl=tar_clipfl!='X'; - if (Optind+1<argc) { - cliplist=argv+Optind+1; - clipn=argc-Optind-1; - } - if (Optind>=argc || !strcmp(argv[Optind], "-")) { - /* Sets tar handle to either 0 or 1, as appropriate */ - tarhandle=(tar_type=='c'); - } else { - if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1) - || (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0)) - { - DEBUG(0,("Error opening local file %s\n",argv[Optind])); - return(0); - } - } - - return 1; -} diff --git a/source/include/byteorder.h b/source/include/byteorder.h deleted file mode 100644 index a55789a4036..00000000000 --- a/source/include/byteorder.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB Byte handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This file implements macros for machine independent short and - int manipulation - -Here is a description of this file that I emailed to the samba list once: - -> I am confused about the way that byteorder.h works in Samba. I have -> looked at it, and I would have thought that you might make a distinction -> between LE and BE machines, but you only seem to distinguish between 386 -> and all other architectures. -> -> Can you give me a clue? - -sure. - -The distinction between 386 and other architectures is only there as -an optimisation. You can take it out completely and it will make no -difference. The routines (macros) in byteorder.h are totally byteorder -independent. The 386 optimsation just takes advantage of the fact that -the x86 processors don't care about alignment, so we don't have to -align ints on int boundaries etc. If there are other processors out -there that aren't alignment sensitive then you could also define -CAREFUL_ALIGNMENT=0 on those processors as well. - -Ok, now to the macros themselves. I'll take a simple example, say we -want to extract a 2 byte integer from a SMB packet and put it into a -type called uint16 that is in the local machines byte order, and you -want to do it with only the assumption that uint16 is _at_least_ 16 -bits long (this last condition is very important for architectures -that don't have any int types that are 2 bytes long) - -You do this: - -#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) -#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) -#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) - -then to extract a uint16 value at offset 25 in a buffer you do this: - -char *buffer = foo_bar(); -uint16 xx = SVAL(buffer,25); - -We are using the byteoder independence of the ANSI C bitshifts to do -the work. A good optimising compiler should turn this into efficient -code, especially if it happens to have the right byteorder :-) - -I know these macros can be made a bit tidier by removing some of the -casts, but you need to look at byteorder.h as a whole to see the -reasoning behind them. byteorder.h defines the following macros: - -SVAL(buf,pos) - extract a 2 byte SMB value -IVAL(buf,pos) - extract a 4 byte SMB value -SVALS(buf,pos) signed version of SVAL() -IVALS(buf,pos) signed version of IVAL() - -SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer -SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer -SSVALS(buf,pos,val) - signed version of SSVAL() -SIVALS(buf,pos,val) - signed version of SIVAL() - -RSVAL(buf,pos) - like SVAL() but for NMB byte ordering -RIVAL(buf,pos) - like IVAL() but for NMB byte ordering -RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering -RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering - -it also defines lots of intermediate macros, just ignore those :-) - -*/ - -#undef CAREFUL_ALIGNMENT - -/* we know that the 386 can handle misalignment and has the "right" - byteorder */ -#ifdef __i386__ -#define CAREFUL_ALIGNMENT 0 -#endif - -#ifndef CAREFUL_ALIGNMENT -#define CAREFUL_ALIGNMENT 1 -#endif - -#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) -#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) -#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val)) - - -#if CAREFUL_ALIGNMENT -#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) -#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) -#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) -#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) -#define SVALS(buf,pos) ((int16)SVAL(buf,pos)) -#define IVALS(buf,pos) ((int32)IVAL(buf,pos)) -#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val))) -#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val))) -#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) -#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val))) -#else -/* this handles things for architectures like the 386 that can handle - alignment errors */ -/* - WARNING: This section is dependent on the length of int16 and int32 - being correct -*/ -#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos))) -#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos))) -#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos))) -#define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos))) -#define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val)) -#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val)) -#define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val)) -#define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val)) -#endif - - -/* now the reverse routines - these are used in nmb packets (mostly) */ -#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) -#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) - -#define RSVAL(buf,pos) SREV(SVAL(buf,pos)) -#define RIVAL(buf,pos) IREV(IVAL(buf,pos)) -#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) -#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) diff --git a/source/include/charset.h b/source/include/charset.h deleted file mode 100644 index 25544fb6215..00000000000 --- a/source/include/charset.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Character set handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef CHARSET_C - -extern char *dos_char_map; -extern char *upper_char_map; -extern char *lower_char_map; -extern void add_char_string(char *s); -extern void charset_initialise(int); - -#ifdef toupper -#undef toupper -#endif - -#ifdef tolower -#undef tolower -#endif - -#ifdef isupper -#undef isupper -#endif - -#ifdef islower -#undef islower -#endif - -#ifdef isdoschar -#undef isdoschar -#endif - -#ifdef isspace -#undef isspace -#endif - -#define toupper(c) (upper_char_map[(c&0xff)] & 0xff) -#define tolower(c) (lower_char_map[(c&0xff)] & 0xff) -#define isupper(c) ((c&0xff) != tolower(c&0xff)) -#define islower(c) ((c&0xff) != toupper(c&0xff)) -#define isdoschar(c) (dos_char_map[(c&0xff)] != 0) -#define isspace(c) ((c)==' ' || (c) == '\t') - -/* this is used to determine if a character is safe to use in - something that may be put on a command line */ -#define issafe(c) (isalnum((c&0xff)) || strchr("-._",c)) -#endif - diff --git a/source/include/clitar.h b/source/include/clitar.h deleted file mode 100644 index 2305fceeec7..00000000000 --- a/source/include/clitar.h +++ /dev/null @@ -1,17 +0,0 @@ - -#define TBLOCK 512 -#define NAMSIZ 100 -union hblock { - char dummy[TBLOCK]; - struct header { - char name[NAMSIZ]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char chksum[8]; - char linkflag; - char linkname[NAMSIZ]; - } dbuf; -}; diff --git a/source/include/includes.h b/source/include/includes.h deleted file mode 100644 index 7403fc4b641..00000000000 --- a/source/include/includes.h +++ /dev/null @@ -1,1256 +0,0 @@ -#ifndef _INCLUDES_H -#define _INCLUDES_H -/* - Unix SMB/Netbios implementation. - Version 1.9. - Machine customisation and include handling - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - This file does all the #includes's. This makes it easier to - port to a new unix. Hopefully a port will only have to edit the Makefile - and add a section for the new unix below. -*/ - - -/* the first OS dependent section is to setup what includes will be used. - the main OS dependent section comes later on -*/ - -#ifdef ALTOS -#define NO_UTIMEH -#endif - -#ifdef MIPS -#define POSIX_H -#define NO_UTIMEH -#endif - -#ifdef sun386 -#define NO_UTIMEH -#endif - -#ifdef NEXT2 -#define NO_UTIMEH -#endif - -#ifdef NEXT3_0 -#define NO_UTIMEH -#define NO_UNISTDH -#endif - -#ifdef APOLLO -#define NO_UTIMEH -#define NO_SYSMOUNTH -#define NO_UNISTDH -#endif - -#ifdef AIX -#define NO_SYSMOUNTH -#endif - -#ifdef M88K_R3 -#define SVR3H -#define NO_RESOURCEH -#endif - -#ifdef DNIX -#define NO_SYSMOUNTH -#define NO_NETIFH -#define NO_RESOURCEH -#define PRIME_NMBD 0 -#define NO_SETGROUPS -#endif - - -#ifdef ISC -#define SYSSTREAMH -#define NO_RESOURCEH -#endif - -#ifdef QNX -#define NO_RESOURCEH -#define NO_SYSMOUNTH -#define USE_MMAP 1 -#ifdef __386__ - #define __i386__ -#endif -#endif - -#ifdef NEWS42 -#define NO_UTIMEH -#define NO_STRFTIME -#define NO_UTIMBUF -#define REPLACE_MKTIME -#define NO_TM_NAME -#endif - -#ifdef OS2 -#define NO_SYSMOUNTH -#define NO_NETIFH -#endif - -#ifdef LYNX -#define NO_SYSMOUNTH -#endif - - -#if (defined(SHADOW_PWD)||defined(OSF1_ENH_SEC)||defined(SecureWare)||defined(PWDAUTH)) -#define PASSWORD_LENGTH 16 -#endif - -/* here is the general includes section - with some ifdefs generated - by the previous section -*/ -#include "local.h" -#include <stdio.h> -#ifdef POSIX_STDLIBH -#include <posix/stdlib.h> -#else -#include <stdlib.h> -#endif -#include <ctype.h> -#include <time.h> -#ifndef NO_UTIMEH -#include <utime.h> -#endif -#include <sys/types.h> - -#ifdef SVR3H -#include <sys/statfs.h> -#include <sys/stream.h> -#include <netinet/types.h> -#include <netinet/ether.h> -#include <netinet/ip_if.h> -#endif - -#include <sys/socket.h> -#ifdef AXPROC -#include <termio.h> -#endif -#include <sys/ioctl.h> -#include <stddef.h> -#ifdef POSIX_H -#include <posix/utime.h> -#include <bsd/sys/time.h> -#include <bsd/netinet/in.h> -#else -#include <sys/time.h> -#include <netinet/in.h> -#endif -#include <netdb.h> -#include <signal.h> -#include <errno.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <grp.h> -#ifndef NO_RESOURCEH -#include <sys/resource.h> -#endif -#ifndef NO_SYSMOUNTH -#include <sys/mount.h> -#endif -#include <pwd.h> -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif -#ifndef NO_UNISTDH -#include <unistd.h> -#endif -#include <sys/wait.h> -#ifdef SYSSTREAMH -#include <sys/stream.h> -#endif -#ifndef NO_NETIFH -#ifdef POSIX_H -#include <bsd/net/if.h> -#else -#include <net/if.h> -#endif -#endif - -#if defined(GETPWANAM) -#include <sys/types.h> -#include <sys/label.h> -#include <sys/audit.h> -#include <pwdadj.h> -#endif - -#if defined(SHADOW_PWD) && !defined(NETBSD) && !defined(FreeBSD) && !defined(CONVEX) -#include <shadow.h> -#endif - -#ifdef SYSLOG -#include <syslog.h> -#endif - - - -/*************************************************************************** -Here come some platform specific sections -***************************************************************************/ - - -#ifdef LINUX -#include <arpa/inet.h> -#include <dirent.h> -#include <string.h> -#include <sys/vfs.h> -#include <netinet/in.h> -#ifndef NO_ASMSIGNALH -#include <asm/signal.h> -#endif -#define SIGNAL_CAST (__sighandler_t) -#define USE_GETCWD -#define USE_SETSID -#define HAVE_BZERO -#define HAVE_MEMMOVE -#define USE_SIGPROCMASK -#define USE_WAITPID -#if 0 -/* SETFS disabled until we can check on some bug reports */ -#if _LINUX_C_LIB_VERSION_MAJOR >= 5 -#define USE_SETFS -#endif -#endif -#ifdef SHADOW_PWD -#if _LINUX_C_LIB_VERSION_MAJOR < 5 -#ifndef crypt -#define crypt pw_encrypt -#endif -#endif -#endif -#endif - -#ifdef SUNOS4 -#define SIGNAL_CAST (void (*)(int)) -#include <netinet/tcp.h> -#include <dirent.h> -#include <sys/acct.h> -#include <sys/vfs.h> -#include <string.h> -#include <errno.h> -#include <sys/wait.h> -#include <signal.h> -/* #include <termios.h> */ -#ifdef sun386 -#define NO_STRFTIME -#define NO_UTIMBUF -#define mktime timelocal -typedef unsigned short mode_t; -#else -#include <utime.h> -#define NO_STRERROR -#endif -#ifndef REPLACE_GETPASS -#define REPLACE_GETPASS -#endif -#ifndef BSD_TERMIO -#define BSD_TERMIO -#endif -#ifndef USE_SIGPROCMASK -#define USE_SIGPROCMASK -#endif -#ifndef USE_WAITPID -#define USE_WAITPID -#endif -/* SunOS doesn't have POSIX atexit */ -#define atexit on_exit -#endif - - -#ifdef SUNOS5 -#include <fcntl.h> -#include <dirent.h> -#include <sys/acct.h> -#include <sys/statfs.h> -#include <sys/statvfs.h> -#include <sys/filio.h> -#include <sys/sockio.h> -#include <netinet/in_systm.h> -#include <netinet/tcp.h> -#include <netinet/ip.h> -#include <string.h> -#include <arpa/inet.h> -#include <rpcsvc/ypclnt.h> -#include <termios.h> -#ifndef USE_LIBDES -#include <crypt.h> -#endif /* USE_LIBDES */ -extern int gettimeofday (struct timeval *, void *); -extern int gethostname (char *name, int namelen); -extern int innetgr (const char *, const char *, const char *, const char *); -#define USE_SETVBUF -#define SIGNAL_CAST (void (*)(int)) -#ifndef SYSV -#define SYSV -#endif -#define USE_WAITPID -#define REPLACE_STRLEN -#define USE_STATVFS -#define USE_GETCWD -#define USE_SETSID -#define REPLACE_GETPASS -#define USE_SIGPROCMASK -#endif - - -#ifdef ULTRIX -#include <strings.h> -#include <nfs/nfs_clnt.h> -#include <nfs/vfs.h> -#include <netinet/tcp.h> -#ifdef ULTRIX_AUTH -#include <auth.h> -#endif -char *getwd(char *); -#define NOSTRDUP -#ifdef __STDC__ -#define SIGNAL_CAST (void(*)(int)) -#endif -#define USE_DIRECT -#define USE_WAITPID -#endif - -#ifdef SGI -#include <netinet/tcp.h> -#include <sys/statfs.h> -#include <string.h> -#include <signal.h> -#ifndef SYSV -#define SYSV -#endif -#define SIGNAL_CAST (void (*)()) -#define STATFS4 -#define USE_WAITPID -#define USE_DIRECT -#define USE_SETSID -#endif - -#ifdef SGI5 -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <sys/statvfs.h> -#include <string.h> -#include <signal.h> -#include <dirent.h> -#define USE_WAITPID -#define NETGROUP -#ifndef SYSV -#define SYSV -#endif -#define SIGNAL_CAST (void (*)()) -#define USE_STATVFS -#define USE_WAITPID -#define USE_SETSID -#endif - - -#ifdef MIPS -#include <bsd/net/soioctl.h> -#include <string.h> -#include <dirent.h> -#include <fcntl.h> -#include <sys/statfs.h> -#include <sys/wait.h> -#include <sys/termio.h> -#define SIGNAL_CAST (void (*)()) -typedef int mode_t; -extern struct group *getgrnam(); -extern struct passwd *getpwnam(); -#define STATFS4 -#define NO_STRERROR -#define REPLACE_STRSTR -#endif /* MIPS */ - - - -#ifdef DGUX -#include <string.h> -#include <dirent.h> -#include <sys/statfs.h> -#include <sys/statvfs.h> -#include <fcntl.h> -#include <termios.h> -#define SYSV -#define USE_WAITPID -#define SIGNAL_CAST (void (*)(int)) -#define STATFS4 -#define USE_GETCWD -#endif - - -#ifdef SVR4 -#include <string.h> -#include <sys/dir.h> -#include <dirent.h> -#include <sys/statfs.h> -#include <sys/statvfs.h> -#include <sys/vfs.h> -#include <sys/filio.h> -#include <fcntl.h> -#include <sys/sockio.h> -#include <netinet/tcp.h> -#include <stropts.h> -#include <termios.h> -#define SYSV -#define USE_WAITPID -#define SIGNAL_CAST (void (*)(int)) -#define USE_STATVFS -#define USE_GETCWD -#define USE_SETSID -#endif - - -#ifdef OSF1 -#include <termios.h> -#include <strings.h> -#include <dirent.h> -char *getwd(char *); -char *mktemp(char *); /* No standard include */ -#include <netinet/in.h> -#include <arpa/inet.h> /* both for inet_ntoa */ -#define SIGNAL_CAST ( void (*) (int) ) -#define STATFS3 -#define USE_F_FSIZE -#define USE_SETSID -#include <netinet/tcp.h> -#ifdef OSF1_ENH_SEC -#include <pwd.h> -#include <sys/types.h> -#include <sys/security.h> -#include <prot.h> -#include <unistd.h> -#define PASSWORD_LENGTH 16 -#define NEED_AUTH_PARAMETERS -#endif /* OSF1_ENH_SEC */ -#endif - - -#ifdef CLIX -#include <dirent.h> -#define SIGNAL_CAST (void (*)()) -#include <sys/fcntl.h> -#include <sys/statfs.h> -#include <string.h> -#define NO_EID -#define USE_WAITPID -#define STATFS4 -#define NO_FSYNC -#define USE_GETCWD -#define USE_SETSID -#define REPLACE_GETPASS -#define NO_GETRLIMIT -#endif /* CLIX */ - - - -#ifdef BSDI -#include <string.h> -#include <netinet/tcp.h> -#define SIGNAL_CAST (void (*)()) -#define USE_DIRECT -#endif - - -#ifdef NETBSD -#include <strings.h> -#include <netinet/tcp.h> -/* you may not need this */ -#define NO_GETSPNAM -#define SIGNAL_CAST (void (*)()) -#define USE_DIRECT -#define REPLACE_INNETGR -#endif - - - -#ifdef FreeBSD -#include <arpa/inet.h> -#include <strings.h> -#include <netinet/tcp.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#define SIGNAL_CAST (void (*)()) -#define USE_SETVBUF -#define USE_SETSID -#define USE_GETCWD -#define USE_WAITPID -#define USE_DIRECT -#define HAVE_MEMMOVE -#define HAVE_BZERO -#define HAVE_GETTIMEOFDAY -#define HAVE_PATHCONF -#define HAVE_GETGRNAM 1 -#endif - - - -#ifdef AIX -#include <strings.h> -#include <sys/dir.h> -#include <sys/select.h> -#include <dirent.h> -#include <sys/statfs.h> -#include <sys/vfs.h> -#include <sys/id.h> -#include <sys/priv.h> -#include <netinet/tcp.h> -#include <locale.h> -#define SYSV -#define USE_WAITPID -#define USE_SIGBLOCK -#define SIGNAL_CAST (void (*)()) -#define DEFAULT_PRINTING PRINT_AIX -/* we undef this because sys/param.h is broken in aix. uggh. */ -#undef MAXHOSTNAMELEN -#endif - - -#ifdef HPUX -#include <string.h> -#include <dirent.h> -#include <fcntl.h> -#include <sys/vfs.h> -#include <sys/types.h> -#include <sys/termios.h> -#include <netinet/tcp.h> -#ifdef HPUX_10_TRUSTED -#include <hpsecurity.h> -#include <prot.h> -#define NEED_AUTH_PARAMETERS -#endif -#define SIGNAL_CAST (void (*)(__harg)) -#define SELECT_CAST (int *) -#define SYSV -#define USE_WAITPID -#define WAIT3_CAST2 (int *) -#define USE_GETCWD -#define USE_SETSID -#define USE_SETRES -#define DEFAULT_PRINTING PRINT_HPUX -#define SIGCLD_IGNORE -#endif - - -#ifdef SEQUENT -#include <signal.h> -#include <string.h> -#include <dirent.h> -#include <sys/types.h> -#include <sys/statfs.h> -#include <sys/stat.h> -#include <sys/buf.h> -#include <sys/socket.h> -#include <unistd.h> -#include <fcntl.h> -#define SIGNAL_CAST (void (*)(int)) -#define USE_WAITPID -#define USE_GETCWD -#define NO_EID -#define STATFS4 -#define USE_DIRECT -#ifdef PTX4 -#undef USE_DIRECT -#endif -#endif - - - -#ifdef SEQUENT_PTX4 -#include <string.h> -#include <sys/dir.h> -#include <dirent.h> -#include <sys/statfs.h> -#include <sys/statvfs.h> -#include <sys/vfs.h> -#include <fcntl.h> -#include <sys/sockio.h> -#include <netinet/tcp.h> -#include <stropts.h> -#include <termios.h> -#define SYSV -#define USE_WAITPID -#define SIGNAL_CAST (void (*)(int)) -#define USE_STATVFS -#define USE_GETCWD -#ifndef seteuid -#define seteuid(uid) setreuid(-1,uid) -#endif -#ifndef setegid -#define setegid(gid) setregid(-1,gid) -#endif -#endif - - -#ifdef NEXT2 -#include <sys/types.h> -#include <strings.h> -#include <dirent.h> -#include <sys/vfs.h> -#define bzero(b,len) memset(b,0,len) -#define mode_t int -#define NO_UTIMBUF -#include <libc.h> -#define NOSTRDUP -#define USE_DIRECT -#define USE_WAITPID -#endif - - -#ifdef NEXT3_0 -#include <strings.h> -#include <sys/dir.h> -#include <sys/vfs.h> -#define bzero(b,len) memset(b,0,len) -#define NO_UTIMBUF -#include <libc.h> -#define NOSTRDUP -#define USE_DIRECT -#define mode_t int -#define GID_TYPE int -#define gid_t int -#define pid_t int -#define SIGNAL_CAST (void (*)(int)) -#define WAIT3_CAST1 (union wait *) -#define HAVE_GMTOFF -#endif - - - -#ifdef APOLLO -#include <string.h> -#include <fcntl.h> -#include <sys/statfs.h> -#define NO_UTIMBUF -#define USE_DIRECT -#define USE_GETCWD -#define SIGNAL_CAST (void (*)()) -#define HAVE_FCNTL_LOCK 0 -#define HAVE_GETTIMEOFDAY -#define STATFS4 -#endif - - - -#ifdef SCO -#include <sys/netinet/tcp.h> -#include <sys/netinet/in_systm.h> -#include <sys/netinet/ip.h> -#include <dirent.h> -#include <string.h> -#include <fcntl.h> -#include <sys/statfs.h> -#include <sys/stropts.h> -#include <limits.h> -#include <locale.h> -#ifdef EVEREST -#include <unistd.h> -#endif -#ifdef NETGROUP -#include <rpcsvc/ypclnt.h> -#endif -#ifdef SecureWare -#include <sys/security.h> -#include <sys/audit.h> -#include <prot.h> -#define crypt bigcrypt -#endif -#ifndef EVEREST - #define ftruncate(f,l) syscall(0x0a28,f,l) -#endif -#define SIGNAL_CAST (void (*)(int)) -#define USE_WAITPID -#define USE_GETCWD -#define USE_SETSID -#ifdef SCO3_2_2 -#define NO_EID -#else -#ifndef EVEREST -#define USE_IFREQ -#endif -#endif -#define STATFS4 -#define NO_FSYNC -#ifndef EVEREST -#define NO_INITGROUPS -#endif -#define HAVE_PATHCONF -#define NO_GETRLIMIT -#endif - - - -/* Definitions for RiscIX */ -#ifdef RiscIX -#define SIGNAL_CAST (void (*)(int)) -#include <sys/dirent.h> -#include <sys/acct.h> -#include <sys/vfs.h> -#include <string.h> -#include <utime.h> -#include <signal.h> -#define HAVE_GETTIMEOFDAY -#define NOSTRCASECMP -#define NOSTRDUP -#endif - - - -#ifdef ISC -#include <net/errno.h> -#include <string.h> -#include <sys/dir.h> -#include <dirent.h> -#include <sys/statfs.h> -#include <fcntl.h> -#include <sys/sioctl.h> -#include <stropts.h> -#include <limits.h> -#include <netinet/tcp.h> -#define FIONREAD FIORDCHK -#define SYSV -#define USE_WAITPID -#define SIGNAL_CAST (void (*)(int)) -#define USE_GETCWD -#define USE_SETSID -#define USE_IFREQ -#define NO_FTRUNCATE -#define STATFS4 -#define NO_FSYNC -#endif - - - -#ifdef AUX -#include <fstab.h> -#include <string.h> -#include <dirent.h> -#include <sys/vfs.h> -#include <fcntl.h> -#include <termios.h> -#define SYSV -#define USE_WAITPID -#define SIGNAL_CAST (void (*)(int)) -char *strdup (char *); -#define USE_GETCWD -#endif - - -#ifdef M88K_R3 -#include <string.h> -#include <dirent.h> -#include <fcntl.h> -#include <termios.h> -#define STATFS4 -#define SYSV -#define USE_WAITPID -#define SIGNAL_CAST (void (*)(int)) -char *strdup (char *); -#define USE_GETCWD -#define NO_FSYNC -#define NO_EID -#endif - - -#ifdef DNIX -#include <dirent.h> -#include <string.h> -#include <fcntl.h> -#include <sys/statfs.h> -#include <sys/stropts.h> -#define NO_GET_BROADCAST -#define USE_WAITPID -#define USE_GETCWD -#define USE_SETSID -#define STATFS4 -#define NO_EID -#define PF_INET AF_INET -#define NO_STRERROR -#define ftruncate(f,l) chsize(f,l) -#endif /* DNIX */ - -#ifdef CONVEX -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <dirent.h> -#include <string.h> -#include <sys/vfs.h> -#include <fcntl.h> -#define DONT_REINSTALL_SIG -#define USE_SIGBLOCK -#define USE_WAITPID -#define SIGNAL_CAST (_SigFunc_Ptr_t) -#define NO_GETSPNAM -#define HAVE_MEMMOVE -extern char *mktemp(char *); -extern int fsync(int); -extern int seteuid(uid_t); -extern int setgroups(int, int *); -extern int initgroups(char *, int); -extern int statfs(char *, struct statfs *); -extern int setegid(gid_t); -extern int getopt(int, char *const *, const char *); -extern int chroot(char *); -extern int gettimeofday(struct timeval *, struct timezone *); -extern int gethostname(char *, int); -extern char *crypt(char *, char *); -extern char *getpass(char *); -#endif - - -#ifdef CRAY -#define MAXPATHLEN 1024 -#include <dirent.h> -#include <string.h> -#include <fcntl.h> -#include <sys/statfs.h> -#define SIGNAL_CAST (void (*)(int)) -#define SIGCLD_IGNORE -#define HAVE_FCNTL_LOCK 1 -#define USE_SETSID -#define STATFS4 -#endif - - -#ifdef ALTOS -#include <unistd.h> -#include <string.h> -#include <dirent.h> -#include <sys/fcntl.h> -#include <sys/statfs.h> -#define const -#define uid_t int -#define gid_t int -#define mode_t int -#define ptrdiff_t int -#define HAVE_GETGRNAM 0 -#define NO_EID -#define NO_FSYNC -#define NO_FTRUNCATE -#define NO_GETRLIMIT -#define NO_INITGROUPS -#define NO_SELECT -#define NO_SETGROUPS -#define NO_STRERROR -#define NO_STRFTIME -#define NO_TM_NAME -#define NO_UTIMEH -#define NOSTRCASECMP -#define REPLACE_MKTIME -#define REPLACE_RENAME -#define REPLACE_STRSTR -#define STATFS4 -#define USE_GETCWD -#endif - -#ifdef QNX -#define STATFS4 -#include <sys/statfs.h> -#include <sys/select.h> -#include <signal.h> -#include <sys/dir.h> -#define SIGNAL_CAST (void (*)()) -#define USE_WAITPID -#define NO_INITGROUPS -#define NO_SETGROUPS -#define HAVE_TIMEZONE -#define USE_GETCWD -#define USE_SETSID -#define HAVE_FCNTL_LOCK 1 -#define DEFAULT_PRINTING PRINT_QNX -#endif - - -#ifdef NEWS42 -#include <string.h> -#include <dirent.h> -#include <sys/vfs.h> -#include <sys/timeb.h> -typedef int mode_t; -#endif - -#ifdef OS2 -#include <dirent.h> -#include <sys/statfs.h> -#include <string.h> -#include <limits.h> -#define SIGNAL_CAST (void (*)()) -#define HAVE_FCNTL_LOCK 0 -#define USE_WAITPID -#define NO_GET_BROADCAST -#define NO_EID -#define NO_SETGROUPS -#define NO_INITGROUPS -#define NO_CRYPT -#define NO_STATFS -#define NO_CHROOT -#define NO_CHOWN -#define strcasecmp stricmp -#define strncasecmp strnicmp -#endif - - -#ifdef LYNX -#define SIGNAL_CAST (void (*)()) -#define WAIT3_CAST1 (union wait *) -#define STATFS4 -#include <fcntl.h> -#include <resource.h> -#include <stat.h> -#include <string.h> -#include <dirent.h> -#include <sys/statfs.h> -#define USE_GETCWD -#define USE_GETSID -#endif - - -#ifdef BOS -#define SIGNAL_CAST (void (*)(int)) -#include <string.h> -#include <sys/dir.h> -#include <sys/select.h> -#include <dirent.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/statfs.h> -#include <sys/bsdioctl.h> -#endif - -#ifdef AMIGA -#include <arpa/inet.h> -#include <dirent.h> -#include <string.h> -#include <netinet/tcp.h> -#include <sys/acct.h> -#include <sys/fcntl.h> -#include <sys/filio.h> -#include <sys/sockio.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <sys/termios.h> -#include <limits.h> -#include <sys/timeb.h> - -#define SIGNAL_CAST (void (*)(int)) -#define USE_GETCWD -#define HAVE_BZERO -#define HAVE_MEMMOVE -#define USE_SIGPROCMASK -#define USE_WAITPID -#define USE_DIRECT -#define USE_F_FSIZE -#define HAVE_FCNTL_LOCK 0 -#define HAVE_GETTIMEOFDAY -#define HAVE_PATHCONF - -#define HAVE_NO_PROC -#define NO_FORK_DEBUG -#define HAVE_FORK 0 -#define HAVE_VFORK 1 -#endif - - -/******************************************************************* -end of the platform specific sections -********************************************************************/ - -#if defined(USE_MMAP) || defined(FAST_SHARE_MODES) -#include <sys/mman.h> -#endif - -#ifdef SecureWare -#define NEED_AUTH_PARAMETERS -#endif - -#ifdef REPLACE_GETPASS -extern char *getsmbpass(char *); -#define getpass(s) getsmbpass(s) -#endif - -#ifdef REPLACE_INNETGR -#define innetgr(group,host,user,dom) InNetGr(group,host,user,dom) -#endif - -#ifndef FD_SETSIZE -#define FD_SETSIZE 255 -#endif - -#ifndef __STDC__ -#define const -#endif - -/* Now for some other grungy stuff */ -#ifdef NO_GETSPNAM -struct spwd { /* fake shadow password structure */ - char *sp_pwdp; -}; -#endif - -#ifndef HAVE_BZERO -#ifndef bzero -#define bzero(p,s) memset(p,0,s) -#endif -#endif - -#ifndef HAVE_MEMMOVE -#ifndef memmove -#define memmove(d,s,n) MemMove(d,s,n) -#endif -#endif - -#ifdef USE_DIRECT -#include <sys/dir.h> -#endif - -/* some unixes have ENOTTY instead of TIOCNOTTY */ -#ifndef TIOCNOTTY -#ifdef ENOTTY -#define TIOCNOTTY ENOTTY -#endif -#endif - -#ifndef SIGHUP -#define SIGHUP 1 -#endif - -/* if undefined then use bsd or sysv printing */ -#ifndef DEFAULT_PRINTING -#ifdef SYSV -#define DEFAULT_PRINTING PRINT_SYSV -#else -#define DEFAULT_PRINTING PRINT_BSD -#endif -#endif - - -#ifdef AFS_AUTH -#include <afs/stds.h> -#include <afs/kautils.h> -#endif - -#ifdef DFS_AUTH -#include <dce/dce_error.h> -#include <dce/sec_login.h> -#endif - -#ifdef NO_UTIMBUF -struct utimbuf { - time_t actime; - time_t modtime; -}; -#endif - -#ifdef NO_STRERROR -#ifndef strerror -extern char *sys_errlist[]; -#define strerror(i) sys_errlist[i] -#endif -#endif - -#ifndef perror -#define perror(m) printf("%s: %s\n",m,strerror(errno)) -#endif - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 255 -#endif - -#include "version.h" -#include "smb.h" -#include "nameserv.h" -#include "proto.h" -#include "byteorder.h" - -#include "kanji.h" -#include "charset.h" - -#ifndef S_IFREG -#define S_IFREG 0100000 -#endif - -#ifndef S_ISREG -#define S_ISREG(x) ((S_IFREG & x)!=0) -#endif - -#ifndef S_ISDIR -#define S_ISDIR(x) ((S_IFDIR & x)!=0) -#endif - -#ifdef UFC_CRYPT -#define crypt ufc_crypt -#endif - -#ifdef REPLACE_STRLEN -#define strlen(s) Strlen(s) -#endif - -#ifdef REPLACE_STRSTR -#define strstr(s,p) Strstr(s,p) -#endif - -#ifdef REPLACE_MKTIME -#define mktime(t) Mktime(t) -#endif - -#ifndef NGROUPS_MAX -#define NGROUPS_MAX 128 -#endif - -#ifndef EDQUOT -#define EDQUOT ENOSPC -#endif - -#ifndef HAVE_GETGRNAM -#define HAVE_GETGRNAM 1 -#endif - -#ifndef SOL_TCP -#define SOL_TCP 6 -#endif - -/* default to using ftruncate workaround as this is safer than assuming -it works and getting lots of bug reports */ -#ifndef FTRUNCATE_CAN_EXTEND -#define FTRUNCATE_CAN_EXTEND 0 -#endif - -/* maybe this unix doesn't separate RD and WR locks? */ -#ifndef F_RDLCK -#define F_RDLCK F_WRLCK -#endif - -#ifndef ENOTSOCK -#define ENOTSOCK EINVAL -#endif - -#ifndef SIGCLD -#define SIGCLD SIGCHLD -#endif - -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - -#ifndef HAVE_FCNTL_LOCK -#define HAVE_FCNTL_LOCK 1 -#endif - -#ifndef WAIT3_CAST2 -#define WAIT3_CAST2 (struct rusage *) -#endif - -#ifndef WAIT3_CAST1 -#define WAIT3_CAST1 (int *) -#endif - -#ifndef QSORT_CAST -#define QSORT_CAST (int (*)()) -#endif - -/* this is a rough check to see if this machine has a lstat() call. - it is not guaranteed to work */ -#if !(defined(S_ISLNK) || defined(S_IFLNK)) -#define lstat stat -#endif - -/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ -#ifndef errno -extern int errno; -#endif - - -#ifdef NO_EID -#define geteuid() getuid() -#define getegid() getgid() -#define seteuid(x) setuid(x) -#define setegid(x) setgid(x) -#endif - - -#if (HAVE_FCNTL_LOCK == 0) -/* since there is no locking available, system includes */ -/* for DomainOS 10.4 do not contain any of the following */ -/* #define's. So, to satisfy the compiler, add these */ -/* #define's, although they arn't really necessary. */ -#define F_GETLK 0 -#define F_SETLK 0 -#define F_WRLCK 0 -#define F_UNLCK 0 -#endif /* HAVE_FCNTL_LOCK == 0 */ - -#ifdef NOSTRCASECMP -#define strcasecmp(s1,s2) StrCaseCmp(s1,s2) -#define strncasecmp(s1,s2,n) StrnCaseCmp(s1,s2,n) -#endif - -#ifndef strcpy -#define strcpy(dest,src) StrCpy(dest,src) -#endif - - -/* possibly wrap the malloc calls */ -#if WRAP_MALLOC - -/* undo the old malloc def if necessary */ -#ifdef malloc -#define xx_old_malloc malloc -#undef malloc -#endif - -#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__) - -/* undo the old realloc def if necessary */ -#ifdef realloc -#define xx_old_realloc realloc -#undef realloc -#endif - -#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__) - -/* undo the old free def if necessary */ -#ifdef free -#define xx_old_free free -#undef free -#endif - -#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__) - -/* and the malloc prototypes */ -void *malloc_wrapped(int,char *,int); -void *realloc_wrapped(void *,int,char *,int); -void free_wrapped(void *,char *,int); - -#endif - - -#if WRAP_MEMCPY -/* undo the old memcpy def if necessary */ -#ifdef memcpy -#define xx_old_memcpy memcpy -#undef memcpy -#endif - -#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__) -void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line); -#endif - -#endif diff --git a/source/include/kanji.h b/source/include/kanji.h deleted file mode 100644 index ee3ba7e09a6..00000000000 --- a/source/include/kanji.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Kanji Extensions - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Adding for Japanese language by <fujita@ainix.isac.co.jp> 1994.9.5 - and extend coding system to EUC/SJIS/JIS/HEX at 1994.10.11 - and add all jis codes sequence at 1995.8.16 - Notes: Hexadecimal code by <ohki@gssm.otuka.tsukuba.ac.jp> -*/ -#ifndef _KANJI_H_ -#define _KANJI_H_ - -#ifdef KANJI - -/* FOR SHIFT JIS CODE */ -#define is_shift_jis(c) \ - ((0x81 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0x9f) \ - || (0xe0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xef)) -#define is_shift_jis2(c) \ - (0x40 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xfc \ - && ((unsigned char) (c)) != 0x7f) -#define is_kana(c) ((0xa0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0xdf)) - -#ifdef _KANJI_C_ -/* FOR EUC CODE */ -#define euc_kana (0x8e) -#define is_euc_kana(c) (((unsigned char) (c)) == euc_kana) -#define is_euc(c) (0xa0 < ((unsigned char) (c)) && ((unsigned char) (c)) < 0xff) - -/* FOR JIS CODE */ -/* default jis third shift code, use for output */ -#ifndef JIS_KSO -#define JIS_KSO 'B' -#endif -#ifndef JIS_KSI -#define JIS_KSI 'J' -#endif -/* in: \E$B or \E$@ */ -/* out: \E(J or \E(B or \E(H */ -#define jis_esc (0x1b) -#define jis_so (0x0e) -#define jis_so1 ('$') -#define jis_so2 ('B') -#define jis_si (0x0f) -#define jis_si1 ('(') -#define jis_si2 ('J') -#define is_esc(c) (((unsigned char) (c)) == jis_esc) -#define is_so1(c) (((unsigned char) (c)) == jis_so1) -#define is_so2(c) (((unsigned char) (c)) == jis_so2 || ((unsigned char) (c)) == '@') -#define is_si1(c) (((unsigned char) (c)) == jis_si1) -#define is_si2(c) (((unsigned char) (c)) == jis_si2 || ((unsigned char) (c)) == 'B' \ - || ((unsigned char) (c)) == 'H') -#define is_so(c) (((unsigned char) (c)) == jis_so) -#define is_si(c) (((unsigned char) (c)) == jis_si) -#define junet_kana1 ('(') -#define junet_kana2 ('I') -#define is_juk1(c) (((unsigned char) (c)) == junet_kana1) -#define is_juk2(c) (((unsigned char) (c)) == junet_kana2) - -#define _KJ_ROMAN (0) -#define _KJ_KANJI (1) -#define _KJ_KANA (2) - -/* FOR HEX */ -#define HEXTAG ':' -#define hex2bin(x) \ - ( ((int) '0' <= ((int) (x)) && ((int) (x)) <= (int)'9')? \ - (((int) (x))-(int)'0'): \ - ((int) 'a'<= ((int) (x)) && ((int) (x))<= (int) 'f')? \ - (((int) (x)) - (int)'a'+10): \ - (((int) (x)) - (int)'A'+10) ) -#define bin2hex(x) \ - ( (((int) (x)) >= 10)? (((int) (x))-10 + (int) 'a'): (((int) (x)) + (int) '0') ) - -#else /* not _KANJI_C_ */ - -extern char* (*_dos_to_unix) (const char *str, BOOL overwrite); -extern char* (*_unix_to_dos) (const char *str, BOOL overwrite); - -#define unix_to_dos (*_unix_to_dos) -#define dos_to_unix (*_dos_to_unix) - -extern char *sj_strtok (char *s1, const char *s2); -extern char *sj_strchr (const char *s, int c); -extern char *sj_strrchr (const char *s, int c); -extern char *sj_strstr (const char *s1, const char *s2); - -#define strchr sj_strchr -#define strrchr sj_strrchr -#define strstr sj_strstr -#define strtok sj_strtok - -#endif /* _KANJI_C_ */ - -#define UNKNOWN_CODE (-1) -#define SJIS_CODE (0) -#define EUC_CODE (1) -#define JIS7_CODE (2) -#define JIS8_CODE (3) -#define JUNET_CODE (4) -#define HEX_CODE (5) -#define CAP_CODE (6) -#define DOSV_CODE SJIS_CODE - -int interpret_coding_system (char *str, int def); - -#else - -#define unix_to_dos(x,y) unix2dos_format(x,y) -#define dos_to_unix(x,y) dos2unix_format(x,y) - -#endif /* not KANJI */ - -#endif /* _KANJI_H_ */ diff --git a/source/include/local.h b/source/include/local.h deleted file mode 100644 index 01eac556525..00000000000 --- a/source/include/local.h +++ /dev/null @@ -1,162 +0,0 @@ -/* local definitions for file server */ -#ifndef _LOCAL_H -#define _LOCAL_H - -/* This defines the section name in the configuration file that will contain */ -/* global parameters - that is, parameters relating to the whole server, not */ -/* just services. This name is then reserved, and may not be used as a */ -/* a service name. It will default to "global" if not defined here. */ -#define GLOBAL_NAME "global" -#define GLOBAL_NAME2 "globals" - -/* This defines the section name in the configuration file that will - refer to the special "homes" service */ -#define HOMES_NAME "homes" - -/* This defines the section name in the configuration file that will - refer to the special "printers" service */ -#define PRINTERS_NAME "printers" - -/* This defines the name of the printcap file. It is MOST UNLIKELY that - this will change BUT! Specifying a file with the format of a printcap - file but containing only a subset of the printers actually in your real - printcap file is a quick-n-dirty way to allow dynamic access to a subset - of available printers. -*/ -#define PRINTCAP_NAME "/etc/printcap" - -/* set these to define the limits of the server. NOTE These are on a - per-client basis. Thus any one machine can't connect to more than - MAX_CONNECTIONS services, but any number of machines may connect at - one time. */ -#define MAX_CONNECTIONS 127 -#define MAX_OPEN_FILES 100 - -/* the max number of connections that the smbstatus program will show */ -#define MAXSTATUS 1000 - -/* max number of directories open at once */ -/* note that with the new directory code this no longer requires a - file handle per directory, but large numbers do use more memory */ -#define MAXDIR 64 - -#define WORDMAX 0xFFFF - - -/* separators for lists */ -#define LIST_SEP " \t,;:\n\r" - -#ifndef LOCKDIR -/* this should have been set in the Makefile */ -#define LOCKDIR "/tmp/samba" -#endif - -/* this is where browse lists are kept in the lock dir */ -#define SERVER_LIST "browse.dat" - -/* shall guest entries in printer queues get changed to user entries, - so they can be deleted using the windows print manager? */ -#define LPQ_GUEST_TO_USER - -/* shall filenames with illegal chars in them get mangled in long - filename listings? */ -#define MANGLE_LONG_FILENAMES - -/* define this if you want to stop spoofing with .. and soft links - NOTE: This also slows down the server considerably */ -#define REDUCE_PATHS - -/* the size of the directory cache */ -#define DIRCACHESIZE 20 - -/* what type of filesystem do we want this to show up as in a NT file - manager window? */ -#define FSTYPE_STRING "Samba" - -/* do you want smbd to send a 1 byte packet to nmbd to trigger it to start - when smbd starts? */ -#ifndef PRIME_NMBD -#define PRIME_NMBD 1 -#endif - -/* do you want session setups at user level security with a invalid - password to be rejected or allowed in as guest? WinNT rejects them - but it can be a pain as it means "net view" needs to use a password - - You have 3 choices: - - GUEST_SESSSETUP = 0 means session setups with an invalid password - are rejected. - - GUEST_SESSSETUP = 1 means session setups with an invalid password - are rejected, unless the username does not exist, in which case it - is treated as a guest login - - GUEST_SESSSETUP = 2 means session setups with an invalid password - are treated as a guest login - - Note that GUEST_SESSSETUP only has an effect in user or server - level security. - */ -#ifndef GUEST_SESSSETUP -#define GUEST_SESSSETUP 0 -#endif - -/* the default pager to use for the client "more" command. Users can - override this with the PAGER environment variable */ -#ifndef PAGER -#define PAGER "more" -#endif - -/* the size of the uid cache used to reduce valid user checks */ -#define UID_CACHE_SIZE 4 - -/* the following control timings of various actions. Don't change - them unless you know what you are doing. These are all in seconds */ -#define DEFAULT_SMBD_TIMEOUT (60*60*24*7) -#define SMBD_RELOAD_CHECK (10) -#define SHARE_MODES_CHECK (10) -#define SHARE_MODES_CLEAN (300) -#define IDLE_CLOSED_TIMEOUT (60) -#define DPTR_IDLE_TIMEOUT (120) -#define SMBD_SELECT_LOOP (10) -#define NMBD_SELECT_LOOP (10) -#define BROWSE_INTERVAL (60) -#define REGISTRATION_INTERVAL (10*60) -#define NMBD_INETD_TIMEOUT (120) -#define NMBD_MAX_TTL (24*60*60) -#define LPQ_LOCK_TIMEOUT (5) - -/* the following are in milliseconds */ -#define LOCK_RETRY_TIMEOUT (100) - -/* do you want to dump core (carefully!) when an internal error is - encountered? Samba will be careful to make the core file only - accessible to root */ -#define DUMP_CORE 1 - -/* what is the longest significant password available on your system? - Knowing this speeds up password searches a lot */ -#ifndef PASSWORD_LENGTH -#define PASSWORD_LENGTH 8 -#endif - -#define SMB_ALIGNMENT 1 - - -/* shall we support browse requests via a FIFO to nmbd? */ -#define ENABLE_FIFO 1 - -/* keep the password server open, this uses up a aocket, but is needed - by many apps */ -#define KEEP_PASSWORD_SERVER_OPEN 1 - -/* how long to wait for a socket connect to happen */ -#define LONG_CONNECT_TIMEOUT 30 -#define SHORT_CONNECT_TIMEOUT 5 - - -/* the directory to sit in when idle */ -/* #define IDLE_DIR "/" */ - -#endif diff --git a/source/include/nameserv.h b/source/include/nameserv.h deleted file mode 100644 index ae59f952524..00000000000 --- a/source/include/nameserv.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios header - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl()) - -/* NTAS uses 2, NT uses 1, WfWg uses 0 */ -#define MAINTAIN_LIST 2 -#define ELECTION_VERSION 1 - -#define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */ -#define MIN_DGRAM_SIZE 12 - -#define NMB_QUERY 0x20 -#define NMB_STATUS 0x21 - -#define NMB_REG 0x05 /* see rfc1002.txt 4.2.2,3,5,6,7,8 */ -#define NMB_REG_REFRESH 0x09 /* see rfc1002.txt 4.2.4 */ -#define NMB_REL 0x06 /* see rfc1002.txt 4.2.9,10,11 */ -#define NMB_WAIT_ACK 0x07 /* see rfc1002.txt 4.2.16 */ -/* XXXX what about all the other types?? 0x1, 0x2, 0x3, 0x4, 0x8? */ - -#define FIND_SELF 0x01 -#define FIND_WINS 0x02 -#define FIND_LOCAL 0x04 - -/* NetBIOS flags */ -#define NB_GROUP 0x80 -#define NB_PERM 0x02 -#define NB_ACTIVE 0x04 -#define NB_CONFL 0x08 -#define NB_DEREG 0x10 -#define NB_BFLAG 0x00 /* broadcast node type */ -#define NB_PFLAG 0x20 /* point-to-point node type */ -#define NB_MFLAG 0x40 /* mixed bcast & p-p node type */ -#define NB_HFLAG 0x60 /* microsoft 'hybrid' node type */ -#define NB_FLGMSK 0x60 - -#define REFRESH_TIME (15*60) -#define NAME_POLL_REFRESH_TIME (5*60) -#define NAME_POLL_INTERVAL 15 - -/* NetBIOS flag identifier */ -#define NAME_PERMANENT(p) ((p) & NB_PERM) -#define NAME_ACTIVE(p) ((p) & NB_ACTIVE) -#define NAME_CONFLICT(p) ((p) & NB_CONFL) -#define NAME_DEREG(p) ((p) & NB_DEREG) -#define NAME_GROUP(p) ((p) & NB_GROUP) - -#define NAME_BFLAG(p) (((p) & NB_FLGMSK) == NB_BFLAG) -#define NAME_PFLAG(p) (((p) & NB_FLGMSK) == NB_PFLAG) -#define NAME_MFLAG(p) (((p) & NB_FLGMSK) == NB_MFLAG) -#define NAME_HFLAG(p) (((p) & NB_FLGMSK) == NB_HFLAG) - -/* server type identifiers */ -#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER) -#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER) -#define AM_DOMMST(work) (work->ServerType & SV_TYPE_DOMAIN_MASTER) -#define AM_DOMMEM(work) (work->ServerType & SV_TYPE_DOMAIN_MEMBER) - -/* microsoft browser NetBIOS name */ -#define MSBROWSE "\001\002__MSBROWSE__\002" - -/* mail slots */ -#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE" -#define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON" - -enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL}; -enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3}; -enum packet_type {NMB_PACKET, DGRAM_PACKET}; - -enum master_state -{ - MST_POTENTIAL, - MST_BACK, - MST_MSB, - MST_BROWSER -}; - -enum domain_state -{ - DOMAIN_NONE, - DOMAIN_WAIT, - DOMAIN_MST -}; - -enum logon_state -{ - LOGON_NONE, - LOGON_WAIT, - LOGON_SRV -}; - -enum state_type -{ - NAME_STATUS_DOM_SRV_CHK, - NAME_STATUS_SRV_CHK, - NAME_REGISTER_CHALLENGE, - NAME_REGISTER, - NAME_RELEASE, - NAME_QUERY_CONFIRM, - NAME_QUERY_ANNOUNCE_HOST, - NAME_QUERY_SYNC_LOCAL, - NAME_QUERY_SYNC_REMOTE, - NAME_QUERY_DOM_SRV_CHK, - NAME_QUERY_SRV_CHK, - NAME_QUERY_FIND_MST, - NAME_QUERY_MST_CHK, - NAME_QUERY_DOMAIN -}; - -/* a netbios name structure */ -struct nmb_name { - char name[17]; - char scope[64]; - int name_type; -}; - -/* a netbios flags + ip address structure */ -/* this is used for multi-homed systems and for internet group names */ -struct nmb_ip -{ - struct in_addr ip; /* ip address of host that owns this name */ - uint16 nb_flags; /* netbios flags */ -}; - -/* this is the structure used for the local netbios name list */ -struct name_record -{ - struct name_record *next; - struct name_record *prev; - - struct nmb_name name; /* the netbios name */ - struct nmb_ip *ip_flgs; /* the ip + flags */ - int num_ips; /* number of ip+flags entries */ - - enum name_source source; /* where the name came from */ - - time_t death_time; /* time record must be removed (do not remove if 0) */ - time_t refresh_time; /* time record should be refreshed */ -}; - -struct subnet_record; - -/* browse and backup server cache for synchronising browse list */ -struct browse_cache_record -{ - struct browse_cache_record *next; - struct browse_cache_record *prev; - - pstring name; - int type; - pstring group; - struct in_addr ip; - time_t sync_time; - BOOL synced; - BOOL local; - struct subnet_record *subnet; -}; - -/* this is used to hold the list of servers in my domain, and is */ -/* contained within lists of domains */ -struct server_record -{ - struct server_record *next; - struct server_record *prev; - - struct server_info_struct serv; - time_t death_time; -}; - -/* a workgroup structure. it contains a list of servers */ -struct work_record -{ - struct work_record *next; - struct work_record *prev; - - struct server_record *serverlist; - - /* stage of development from non-local-master up to local-master browser */ - enum master_state mst_state; - - /* stage of development from non-domain-master to domain master browser */ - enum domain_state dom_state; - - /* stage of development from non-logon-server to logon server */ - enum logon_state log_state; - - /* work group info */ - fstring work_group; - int token; /* used when communicating with backup browsers */ - int ServerType; - - /* announce info */ - time_t lastannounce_time; - int announce_interval; - BOOL needannounce; - - - /* election info */ - BOOL RunningElection; - BOOL needelection; - int ElectionCount; - uint32 ElectionCriterion; -}; - -/* initiated name queries recorded in this list to track any responses... */ -/* sadly, we need to group everything together. i suppose that if this - gets unwieldy, then a union ought to be considered. oh for c++... */ -struct response_record -{ - struct response_record *next; - struct response_record *prev; - - uint16 response_id; - enum state_type state; - - int fd; - int quest_type; - struct nmb_name name; - int nb_flags; - time_t ttl; - - int server_type; - fstring my_name; - fstring my_comment; - - BOOL bcast; - BOOL recurse; - struct in_addr send_ip; - struct in_addr reply_to_ip; - - int num_msgs; - - time_t repeat_time; - time_t repeat_interval; - int repeat_count; -}; - -/* a subnet structure. it contains a list of workgroups and netbios names*/ - -/* note that a subnet of 255.255.255.255 contains all the WINS netbios names. - all communication from such nodes are on a non-broadcast basis: they - are point-to-point (P nodes) or mixed point-to-point and broadcast - (M nodes). M nodes use point-to-point as a preference, and will use - broadcasting for certain activities, or will resort to broadcasting as a - last resort, if the WINS server fails (users of wfwg will notice that their - machine often freezes for 30 seconds at a time intermittently, if the WINS - server is down). - - B nodes will have their own, totally separate subnet record, with their - own netbios name set. these do NOT interact with other subnet records' - netbios names, INCLUDING the WINS one (with an ip "address", so called, - of 255.255.255.255) - - there is a separate response list for each subnet record. in the case of - the 255.255.255.255 subnet record (WINS), the WINS server will be able to - use this to poll (infrequently!) each of its entries, to ensure that the - names are still in use. - XXXX this polling is a planned feature for a really over-cautious WINS server -*/ - -struct subnet_record -{ - struct subnet_record *next; - struct subnet_record *prev; - - struct work_record *workgrouplist; /* list of workgroups */ - struct name_record *namelist; /* list of netbios names */ - struct response_record *responselist; /* list of responses expected */ - - struct in_addr bcast_ip; - struct in_addr mask_ip; - struct in_addr myip; -}; - -/* a resource record */ -struct res_rec { - struct nmb_name rr_name; - int rr_type; - int rr_class; - int ttl; - int rdlength; - char rdata[MAX_DGRAM_SIZE]; -}; - -/* define a nmb packet. */ -struct nmb_packet -{ - struct { - int name_trn_id; - int opcode; - BOOL response; - struct { - BOOL bcast; - BOOL recursion_available; - BOOL recursion_desired; - BOOL trunc; - BOOL authoritative; - } nm_flags; - int rcode; - int qdcount; - int ancount; - int nscount; - int arcount; - } header; - - struct { - struct nmb_name question_name; - int question_type; - int question_class; - } question; - - struct res_rec *answers; - struct res_rec *nsrecs; - struct res_rec *additional; -}; - - -/* a datagram - this normally contains SMB data in the data[] array */ -struct dgram_packet { - struct { - int msg_type; - struct { - enum node_type node_type; - BOOL first; - BOOL more; - } flags; - int dgm_id; - struct in_addr source_ip; - int source_port; - int dgm_length; - int packet_offset; - } header; - struct nmb_name source_name; - struct nmb_name dest_name; - int datasize; - char data[MAX_DGRAM_SIZE]; -}; - -/* define a structure used to queue packets. this will be a linked - list of nmb packets */ -struct packet_struct -{ - struct packet_struct *next; - struct packet_struct *prev; - struct in_addr ip; - int port; - int fd; - time_t timestamp; - enum packet_type packet_type; - union { - struct nmb_packet nmb; - struct dgram_packet dgram; - } packet; -}; - - -/* ids for netbios packet types */ -#define ANN_HostAnnouncement 1 -#define ANN_AnnouncementRequest 2 -#define ANN_Election 8 -#define ANN_GetBackupListReq 9 -#define ANN_GetBackupListResp 10 -#define ANN_BecomeBackup 11 -#define ANN_DomainAnnouncement 12 -#define ANN_MasterAnnouncement 13 -#define ANN_ResetBrowserState 14 -#define ANN_LocalMasterAnnouncement 15 - - -/* broadcast packet announcement intervals, in minutes */ - -/* attempt to add domain logon and domain master names */ -#define CHECK_TIME_ADD_DOM_NAMES 5 - -/* search for master browsers of workgroups samba knows about, - except default */ -#define CHECK_TIME_MST_BROWSE 5 - -/* request backup browser announcements from other servers */ -#define CHECK_TIME_ANNOUNCE_BACKUP 15 - -/* request host announcements from other servers: min and max of interval */ -#define CHECK_TIME_MIN_HOST_ANNCE 3 -#define CHECK_TIME_MAX_HOST_ANNCE 12 - -/* announce as master to WINS server and any Primary Domain Controllers */ -#define CHECK_TIME_MST_ANNOUNCE 15 - -/* do all remote announcements this often */ -#define REMOTE_ANNOUNCE_INTERVAL 180 - -#define DFLT_SERVER_TYPE (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | \ - (lp_time_server() ? SV_TYPE_TIME_SOURCE : 0) | \ - SV_TYPE_SERVER_UNIX | \ - SV_TYPE_PRINTQ_SERVER | SV_TYPE_SERVER_NT | \ - SV_TYPE_NT ) - -/* Macro's to enumerate subnets either with or without - the WINS subnet. */ - -extern struct subnet_record *subnetlist; -extern struct subnet_record *wins_subnet; - -#define FIRST_SUBNET subnetlist -#define NEXT_SUBNET_EXCLUDING_WINS(x) ((x)->next) -#define NEXT_SUBNET_INCLUDING_WINS(x) ( ((x) == wins_subnet) ? NULL : \ - (((x)->next == NULL) ? wins_subnet : \ - (x)->next)) - diff --git a/source/include/trans2.h b/source/include/trans2.h deleted file mode 100644 index 70285358bc4..00000000000 --- a/source/include/trans2.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-1997 - - Extensively modified by Andrew Tridgell, 1995 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _TRANS2_H_ -#define _TRANS2_H_ - -/* Define the structures needed for the trans2 calls. */ - -/******************************************************* - For DosFindFirst/DosFindNext - level 1 - -MAXFILENAMELEN = 255; -FDATE == uint16 -FTIME == uint16 -ULONG == uint32 -USHORT == uint16 - -typedef struct _FILEFINDBUF { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 FDATE fdateCreation; -2 FTIME ftimeCreation; -4 FDATE fdateLastAccess; -6 FTIME ftimeLastAccess; -8 FDATE fdateLastWrite; -10 FTIME ftimeLastWrite; -12 ULONG cbFile file length in bytes -16 ULONG cbFileAlloc size of file allocation unit -20 USHORT attrFile -22 UCHAR cchName length of name to follow (not including zero) -23 UCHAR achName[MAXFILENAMELEN]; Null terminated name -} FILEFINDBUF; -*********************************************************/ - -#define l1_fdateCreation 0 -#define l1_fdateLastAccess 4 -#define l1_fdateLastWrite 8 -#define l1_cbFile 12 -#define l1_cbFileAlloc 16 -#define l1_attrFile 20 -#define l1_cchName 22 -#define l1_achName 23 - -/********************************************************** -For DosFindFirst/DosFindNext - level 2 - -typedef struct _FILEFINDBUF2 { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 FDATE fdateCreation; -2 FTIME ftimeCreation; -4 FDATE fdateLastAccess; -6 FTIME ftimeLastAccess; -8 FDATE fdateLastWrite; -10 FTIME ftimeLastWrite; -12 ULONG cbFile file length in bytes -16 ULONG cbFileAlloc size of file allocation unit -20 USHORT attrFile -22 ULONG cbList Extended attribute list (always 0) -26 UCHAR cchName length of name to follow (not including zero) -27 UCHAR achName[MAXFILENAMELEN]; Null terminated name -} FILEFINDBUF2; -*************************************************************/ - -#define l2_fdateCreation 0 -#define l2_fdateLastAccess 4 -#define l2_fdateLastWrite 8 -#define l2_cbFile 12 -#define l2_cbFileAlloc 16 -#define l2_attrFile 20 -#define l2_cbList 22 -#define l2_cchName 26 -#define l2_achName 27 - - -/********************************************************** -For DosFindFirst/DosFindNext - level 260 - -typedef struct _FILEFINDBUF260 { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 ULONG NextEntryOffset; -4 ULONG FileIndex; -8 LARGE_INTEGER CreationTime; -16 LARGE_INTEGER LastAccessTime; -24 LARGE_INTEGER LastWriteTime; -32 LARGE_INTEGER ChangeTime; -40 LARGE_INTEGER EndOfFile; -48 LARGE_INTEGER AllocationSize; -56 ULONG FileAttributes; -60 ULONG FileNameLength; -64 ULONG EaSize; -68 CHAR ShortNameLength; -70 UNICODE ShortName[12]; -94 UNICODE FileName[]; -*************************************************************/ - -#define l260_achName 94 - - -/********************************************************** -For DosQueryPathInfo/DosQueryFileInfo/DosSetPathInfo/ -DosSetFileInfo - level 1 - -typedef struct _FILESTATUS { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 FDATE fdateCreation; -2 FTIME ftimeCreation; -4 FDATE fdateLastAccess; -6 FTIME ftimeLastAccess; -8 FDATE fdateLastWrite; -10 FTIME ftimeLastWrite; -12 ULONG cbFile file length in bytes -16 ULONG cbFileAlloc size of file allocation unit -20 USHORT attrFile -} FILESTATUS; -*************************************************************/ - -/* Use the l1_ defines from DosFindFirst */ - -/********************************************************** -For DosQueryPathInfo/DosQueryFileInfo/DosSetPathInfo/ -DosSetFileInfo - level 2 - -typedef struct _FILESTATUS2 { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 FDATE fdateCreation; -2 FTIME ftimeCreation; -4 FDATE fdateLastAccess; -6 FTIME ftimeLastAccess; -8 FDATE fdateLastWrite; -10 FTIME ftimeLastWrite; -12 ULONG cbFile file length in bytes -16 ULONG cbFileAlloc size of file allocation unit -20 USHORT attrFile -22 ULONG cbList Length of EA's (0) -} FILESTATUS2; -*************************************************************/ - -/* Use the l2_ #defines from DosFindFirst */ - -/********************************************************** -For DosQFSInfo/DosSetFSInfo - level 1 - -typedef struct _FSALLOCATE { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 ULONG idFileSystem id of file system -4 ULONG cSectorUnit number of sectors per allocation unit -8 ULONG cUnit number of allocation units -12 ULONG cUnitAvail Available allocation units -16 USHORT cbSector bytes per sector -} FSALLOCATE; -*************************************************************/ - -#define l1_idFileSystem 0 -#define l1_cSectorUnit 4 -#define l1_cUnit 8 -#define l1_cUnitAvail 12 -#define l1_cbSector 16 - -/********************************************************** -For DosQFSInfo/DosSetFSInfo - level 2 - -typedef struct _FSINFO { -Byte offset Type name description --------------+-------+-------------------+-------------- -0 FDATE vol_fdateCreation -2 FTIME vol_ftimeCreation -4 UCHAR vol_cch length of volume name (excluding NULL) -5 UCHAR vol_szVolLabel[12] volume name -} FSINFO; -*************************************************************/ - -#define SMB_QUERY_FS_LABEL_INFO 0x101 -#define SMB_QUERY_FS_VOLUME_INFO 0x102 -#define SMB_QUERY_FS_SIZE_INFO 0x103 -#define SMB_QUERY_FS_DEVICE_INFO 0x104 -#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105 - - -#define l2_vol_fdateCreation 0 -#define l2_vol_cch 4 -#define l2_vol_szVolLabel 5 - - -#define SMB_QUERY_FILE_BASIC_INFO 0x101 -#define SMB_QUERY_FILE_STANDARD_INFO 0x102 -#define SMB_QUERY_FILE_EA_INFO 0x103 -#define SMB_QUERY_FILE_NAME_INFO 0x104 -#define SMB_QUERY_FILE_ALLOCATION_INFO 0x105 -#define SMB_QUERY_FILE_END_OF_FILEINFO 0x106 -#define SMB_QUERY_FILE_ALL_INFO 0x107 -#define SMB_QUERY_FILE_ALT_NAME_INFO 0x108 -#define SMB_QUERY_FILE_STREAM_INFO 0x109 - -#define SMB_FIND_FILE_DIRECTORY_INFO 0x101 -#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 -#define SMB_FIND_FILE_NAMES_INFO 0x103 -#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 - -#define SMB_SET_FILE_BASIC_INFO 0x101 -#define SMB_SET_FILE_DISPOSITION_INFO 0x102 -#define SMB_SET_FILE_ALLOCATION_INFO 0x103 -#define SMB_SET_FILE_END_OF_FILE_INFO 0x104 - -#define DIRLEN_GUESS (45+MAX(l1_achName,l2_achName)) - -/* NT uses a FILE_ATTRIBUTE_NORMAL when no other attributes - are set. */ - -#define NT_FILE_ATTRIBUTE_NORMAL 0x80 - -/* Function prototypes */ - - -int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize); - -int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize); - -#endif - - - diff --git a/source/include/version.h b/source/include/version.h deleted file mode 100644 index 37e26dd65ee..00000000000 --- a/source/include/version.h +++ /dev/null @@ -1 +0,0 @@ -#define VERSION "1.9.17alpha3" diff --git a/source/include/vt_mode.h b/source/include/vt_mode.h deleted file mode 100644 index 85b481122ee..00000000000 --- a/source/include/vt_mode.h +++ /dev/null @@ -1,48 +0,0 @@ -/* vt_mode.h */ -/* -support vtp-sessions - -written by Christian A. Lademann <cal@zls.com> -*/ - -/* -02.05.95:cal:ported to samba-1.9.13 -*/ - -#ifndef __vt_mode_h__ -# define __vt_mode_h__ - -# define VT_CLOSED 0 -# define VT_OPEN 1 - -# define MS_NONE 0 -# define MS_PTY 1 -# define MS_STREAM 2 -# define MS_VTY 3 - -# define VT_MAXREAD 32 - - -# undef EXTERN - -# ifndef __vt_mode_c__ -# define EXTERN extern -# define DEFAULT(v) -# else -# define EXTERN -# define DEFAULT(v) =(v) -# endif - - EXTERN int VT_Status DEFAULT(VT_CLOSED), - VT_Fd DEFAULT(-1), - VT_ChildPID DEFAULT(-1); - - EXTERN BOOL VT_Mode DEFAULT(False), - VT_ChildDied DEFAULT(False); - - EXTERN char *VT_Line DEFAULT(NULL); - -# undef EXTERN - - -#endif /* __vt_mode_h__ */ diff --git a/source/internals.doc b/source/internals.doc deleted file mode 100644 index 971f2567388..00000000000 --- a/source/internals.doc +++ /dev/null @@ -1,212 +0,0 @@ -internals.txt, 8 May 1996 -Written by David Chappell <David.Chappell@mail.trincoll.edu>. - -This document describes some of the internal functions which must be -understood by anyone wishing to add features to Samba. - - - - - -============================================================================= -This section describes the macros defined in byteorder.h. These macros -are used extensively in the Samba code. - ------------------------------------------------------------------------------ -CVAL(buf,pos) - -returns the byte at offset pos within buffer buf as an unsigned character. - ------------------------------------------------------------------------------ -PVAL(buf,pos) - -returns the value of CVAL(buf,pos) cast to type unsigned integer. - ------------------------------------------------------------------------------ -SCVAL(buf,pos,val) - -sets the byte at offset pos within buffer buf to value val. - ------------------------------------------------------------------------------ -SVAL(buf,pos) - -returns the value of the unsigned short (16 bit) little-endian integer at -offset pos within buffer buf. An integer of this type is sometimes -refered to as "USHORT". - ------------------------------------------------------------------------------ -IVAL(buf,pos) - -returns the value of the unsigned 32 bit little-endian integer at offset -pos within buffer buf. - ------------------------------------------------------------------------------ -SVALS(buf,pos) - -returns the value of the signed short (16 bit) little-endian integer at -offset pos within buffer buf. - ------------------------------------------------------------------------------ -IVALS(buf,pos) - -returns the value of the signed 32 bit little-endian integer at offset pos -within buffer buf. - ------------------------------------------------------------------------------ -SSVAL(buf,pos,val) - -sets the unsigned short (16 bit) little-endian integer at offset pos within -buffer buf to value val. - ------------------------------------------------------------------------------ -SIVAL(buf,pos,val) - -sets the unsigned 32 bit little-endian integer at offset pos within buffer -buf to the value val. - ------------------------------------------------------------------------------ -SSVALS(buf,pos,val) - -sets the short (16 bit) signed little-endian integer at offset pos within -buffer buf to the value val. - ------------------------------------------------------------------------------ -SIVALS(buf,pos,val) - -sets the signed 32 bit little-endian integer at offset pos withing buffer -buf to the value val. - ------------------------------------------------------------------------------ -RSVAL(buf,pos) - -returns the value of the unsigned short (16 bit) big-endian integer at -offset pos within buffer buf. - ------------------------------------------------------------------------------ -RIVAL(buf,pos) - -returns the value of the unsigned 32 bit big-endian integer at offset -pos within buffer buf. - ------------------------------------------------------------------------------ -RSSVAL(buf,pos,val) - -sets the value of the unsigned short (16 bit) big-endian integer at -offset pos within buffer buf to value val. -refered to as "USHORT". - ------------------------------------------------------------------------------ -RSIVAL(buf,pos,val) - -sets the value of the unsigned 32 bit big-endian integer at offset -pos within buffer buf to value val. - - - - - -============================================================================= -This section describes the functions need to make a LAN Manager RPC call. -This information had been obtained by examining the Samba code and the LAN -Manager 2.0 API documentation. It should not be considered entirely -reliable. - ------------------------------------------------------------------------------ -call_api(int prcnt, int drcnt, int mprcnt, int mdrcnt, - char *param, char *data, char **rparam, char **rdata); - -This function is defined in client.c. It uses an SMB transaction to call a -remote api. - -The parameters are as follows: - -prcnt: the number of bytes of parameters begin sent. -drcnt: the number of bytes of data begin sent. -mprcnt: the maximum number of bytes of parameters which should be returned -mdrcnt: the maximum number of bytes of data which should be returned -param: a pointer to the parameters to be sent. -data: a pointer to the data to be sent. -rparam: a pointer to a pointer which will be set to point to the returned - paramters. The caller of call_api() must deallocate this memory. -rdata: a pointer to a pointer which will be set to point to the returned - data. The caller of call_api() must deallocate this memory. - ------------------------------------------------------------------------------ -These are the parameters which you ought to send, in the order of their -appearance in the parameter block: - -* An unsigned 16 bit integer API number. You should set this value with -SSVAL(). I do not know where these numbers are described. - -* An ASCIIZ string describing the parameters to the API function as defined -in the LAN Manager documentation. The first parameter, which is the server -name, is ommited. This string is based uppon the API function as described -in the manual, not the data which is actually passed. - -* An ASCIIZ string describing the data structure which ought to be returned. - -* Any parameters which appear in the function call, as defined in the LAN -Manager API documentation, after the "Server" and up to and including the -"uLevel" parameters. - -* An unsigned 16 bit integer which gives the size in bytes of the buffer we -will use to receive the returned array of data structures. Presumably this -should be the same as mdrcnt. This value should be set with SSVAL(). - -* An ASCIIZ string describing substructures which should be returned. If no -substructures apply, this string is of zero length. - ------------------------------------------------------------------------------ -The code in client.c always calls call_api() with no data. It is unclear -when a non-zero length data buffer would be sent. - ------------------------------------------------------------------------------ -The returned parameters (pointed to by rparam), in their order of appearance -are: - -* An unsigned 16 bit integer which contains the API function's return code. -This value should be read with SVAL(). - -* An adjustment which tells the amount by which pointers in the returned -data should be adjusted. This value should be read with SVAL(). Basically, -the address of the start of the returned data buffer should have the returned -pointer value added to it and then have this value subtracted from it in -order to obtain the currect offset into the returned data buffer. - -* A count of the number of elements in the array of structures returned. -It is also possible that this may sometimes be the number of bytes returned. - ------------------------------------------------------------------------------ -When call_api() returns, rparam points to the returned parameters. The -first if these is the result code. It will be zero if the API call -suceeded. This value by be read with "SVAL(rparam,0)". - -The second parameter may be read as "SVAL(rparam,2)". It is a 16 bit offset -which indicates what the base address of the returned data buffer was when -it was built on the server. It should be used to correct pointer before -use. - -The returned data buffer contains the array of returned data structures. -Note that all pointers must be adjusted before use. The function -fix_char_ptr() in client.c can be used for this purpose. - -The third parameter (which may be read as "SVAL(rparam,4)") has something to -do with indicating the amount of data returned or possibly the amount of -data which can be returned if enough buffer space is allowed. - ------------------------------------------------------------------------------ -Certain data structures are described by means of ASCIIz strings containing -code characters. These are the code characters: - -W a type byte little-endian unsigned integer -N a count of substructures which follow -D a four byte little-endian unsigned integer -B a byte (with optional count expressed as trailing ASCII digits) -z a four byte offset to a NULL terminated string -l a four byte offset to non-string user data -b an offset to data (with count expressed as trailing ASCII digits) -r pointer to returned data buffer??? -L length in bytes of returned data buffer??? -h number of bytes of information available??? - ----------------------------------------------------------------------------- diff --git a/source/lib/access.c b/source/lib/access.c deleted file mode 100644 index 599cb5ca7e3..00000000000 --- a/source/lib/access.c +++ /dev/null @@ -1,289 +0,0 @@ -/* -This module is an adaption of code from the tcpd-1.4 package written -by Wietse Venema, Eindhoven University of Technology, The Netherlands. - -The code is used here with permission. - -The code has been considerably changed from the original. Bug reports -should be sent to samba-bugs@samba.anu.edu.au -*/ - -#include "includes.h" - -#define ALLOW_PURE_ADDRESSES - -extern int DEBUGLEVEL; - -#ifndef INADDR_NONE -#define INADDR_NONE ((uint32)~0) -#endif - - -#define Good True -#define Bad False - -#define CLIENT_MATCH client_match - -/* Delimiters for lists of daemons or clients. */ - -static char sep[] = ", \t"; - -/* Constants to be used in assignments only, not in comparisons... */ - -#define YES 1 -#define NO 0 -#define FAIL (-1) - -/* Forward declarations. */ -static int list_match(char *list,char *item, int (*match_fn)()); -static int client_match(char *tok,char *item); -static int string_match(char *tok,char *s); -static int masked_match(char *tok, char *slash, char *s); - -/* Size of logical line buffer. */ -#define BUFLEN 2048 - -/* return true if access should be allowed to a service*/ -BOOL check_access(int snum) -{ - char *denyl,*allowl; - BOOL ret = False; - - denyl = lp_hostsdeny(snum); - if (denyl) denyl = strdup(denyl); - - allowl = lp_hostsallow(snum); - if (allowl) allowl = strdup(allowl); - - if ((!denyl || *denyl==0) && (!allowl || *allowl==0)) - ret = True; - - if (!ret) - { - if (allow_access(denyl,allowl,client_name(),client_addr())) - { - if (snum >= 0) - DEBUG(2,("Allowed connection from %s (%s) to %s\n", - client_name(),client_addr(), - lp_servicename(snum))); - ret = True; - } - else - if (snum >= 0) - DEBUG(0,("Denied connection from %s (%s) to %s\n", - client_name(),client_addr(), - lp_servicename(snum))); - } - - if (denyl) free(denyl); - if (allowl) free(allowl); - return(ret); -} - - -/* return true if access should be allowed */ -BOOL allow_access(char *deny_list,char *allow_list,char *cname,char *caddr) -{ - char *client[2]; - - client[0] = cname; - client[1] = caddr; - - /* if theres no deny list and no allow list then allow access */ - if ((!deny_list || *deny_list == 0) && (!allow_list || *allow_list == 0)) - return(True); - - /* if there is an allow list but no deny list then allow only hosts - on the allow list */ - if (!deny_list || *deny_list == 0) - return(list_match(allow_list,(char *)client,CLIENT_MATCH)); - - /* if theres a deny list but no allow list then allow - all hosts not on the deny list */ - if (!allow_list || *allow_list == 0) - return(!list_match(deny_list,(char *)client,CLIENT_MATCH)); - - /* if there are both type of list then allow all hosts on the allow list */ - if (list_match(allow_list,(char *)client,CLIENT_MATCH)) - return (True); - - /* if there are both type of list and it's not on the allow then - allow it if its not on the deny */ - if (list_match(deny_list,(char *)client,CLIENT_MATCH)) - return (False); - - return (True); -} - -/* list_match - match an item against a list of tokens with exceptions */ -/* (All modifications are marked with the initials "jkf") */ -static int list_match(char *list,char *item, int (*match_fn)()) -{ - char *tok; - char *listcopy; /* jkf */ - int match = NO; - - /* - * jkf@soton.ac.uk -- 31 August 1994 -- Stop list_match() - * overwriting the list given as its first parameter. - */ - - /* jkf -- can get called recursively with NULL list */ - listcopy = (list == 0) ? (char *)0 : strdup(list); - - /* - * Process tokens one at a time. We have exhausted all possible matches - * when we reach an "EXCEPT" token or the end of the list. If we do find - * a match, look for an "EXCEPT" list and recurse to determine whether - * the match is affected by any exceptions. - */ - - for (tok = strtok(listcopy, sep); tok ; tok = strtok(NULL, sep)) { - if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ - break; - if ((match = (*match_fn) (tok, item))) /* YES or FAIL */ - break; - } - /* Process exceptions to YES or FAIL matches. */ - - if (match != NO) { - while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT")) - /* VOID */ ; - if (tok == 0 || list_match((char *) 0, item, match_fn) == NO) { - if (listcopy != 0) free(listcopy); /* jkf */ - return (match); - } - } - - if (listcopy != 0) free(listcopy); /* jkf */ - return (NO); -} - - -/* client_match - match host name and address against token */ -static int client_match(char *tok,char *item) -{ - char **client = (char **)item; - int match; - - /* - * Try to match the address first. If that fails, try to match the host - * name if available. - */ - - if ((match = string_match(tok, client[1])) == 0) - if (client[0][0] != 0) - match = string_match(tok, client[0]); - return (match); -} - -/* string_match - match string against token */ -static int string_match(char *tok,char *s) -{ - int tok_len; - int str_len; - char *cut; - - /* - * Return YES if a token has the magic value "ALL". Return FAIL if the - * token is "FAIL". If the token starts with a "." (domain name), return - * YES if it matches the last fields of the string. If the token has the - * magic value "LOCAL", return YES if the string does not contain a "." - * character. If the token ends on a "." (network number), return YES if - * it matches the first fields of the string. If the token begins with a - * "@" (netgroup name), return YES if the string is a (host) member of - * the netgroup. Return YES if the token fully matches the string. If the - * token is a netnumber/netmask pair, return YES if the address is a - * member of the specified subnet. - */ - - if (tok[0] == '.') { /* domain: match last fields */ - if ((str_len = strlen(s)) > (tok_len = strlen(tok)) - && strcasecmp(tok, s + str_len - tok_len) == 0) - return (YES); - } else if (tok[0] == '@') { /* netgroup: look it up */ -#ifdef NETGROUP - static char *mydomain = NULL; - char *hostname = NULL; - BOOL netgroup_ok = False; - - if (!mydomain) yp_get_default_domain(&mydomain); - - if (!mydomain) { - DEBUG(0,("Unable to get default yp domain.\n")); - return NO; - } - if (!(hostname = strdup(s))) { - DEBUG(1,("out of memory for strdup!\n")); - return NO; - } - - netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain); - - DEBUG(5,("looking for %s of domain %s in netgroup %s gave %s\n", - hostname, - mydomain, - tok+1, - BOOLSTR(netgroup_ok))); - -#ifdef NETGROUP_INSECURE - /* if you really want netgroups that match non qualified names - then define NETGROUP_INSECURE. It can, however, be a big - security hole */ - { - char *clnt_domain; - if (!netgroup_ok && (clnt_domain=strchr(hostname,'.'))) { - *clnt_domain++ = '\0'; - netgroup_ok = innetgr(tok + 1, hostname, (char *) 0, mydomain); - } - } -#endif - - free(hostname); - - if (netgroup_ok) return(YES); -#else - DEBUG(0,("access: netgroup support is not configured\n")); - return (NO); -#endif - } else if (strcasecmp(tok, "ALL") == 0) { /* all: match any */ - return (YES); - } else if (strcasecmp(tok, "FAIL") == 0) { /* fail: match any */ - return (FAIL); - } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ - if (strchr(s, '.') == 0 && strcasecmp(s, "unknown") != 0) - return (YES); - } else if (!strcasecmp(tok, s)) { /* match host name or address */ - return (YES); - } else if (tok[(tok_len = strlen(tok)) - 1] == '.') { /* network */ - if (strncmp(tok, s, tok_len) == 0) - return (YES); - } else if ((cut = strchr(tok, '/')) != 0) { /* netnumber/netmask */ - if (isdigit(s[0]) && masked_match(tok, cut, s)) - return (YES); - } - return (NO); -} - -/* masked_match - match address against netnumber/netmask */ -static int masked_match(char *tok, char *slash, char *s) -{ - uint32 net; - uint32 mask; - uint32 addr; - - if ((addr = interpret_addr(s)) == INADDR_NONE) - return (NO); - *slash = 0; - net = interpret_addr(tok); - *slash = '/'; - if (net == INADDR_NONE || (mask = interpret_addr(slash + 1)) == INADDR_NONE) { - DEBUG(0,("access: bad net/mask access control: %s", tok)); - return (NO); - } - return ((addr & mask) == net); -} - - - - diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c deleted file mode 100644 index 6be455c47b2..00000000000 --- a/source/lib/charcnv.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Character set conversion Extensions - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ -#include "includes.h" -#define CTRLZ 26 -extern int DEBUGLEVEL; - -static char cvtbuf[1024]; - -static BOOL mapsinited = 0; - -static char unix2dos[256]; -static char dos2unix[256]; - -static void initmaps() { - int k; - - for (k = 0; k < 256; k++) unix2dos[k] = k; - for (k = 0; k < 256; k++) dos2unix[k] = k; - - mapsinited = True; -} - -static void update_map(char * str) { - char *p; - - for (p = str; *p; p++) { - if (p[1]) { - unix2dos[(unsigned char)*p] = p[1]; - dos2unix[(unsigned char)p[1]] = *p; - p++; - } - } -} - -static void init_iso8859_1() { - - int i; - if (!mapsinited) initmaps(); - - /* Do not map undefined characters to some accidental code */ - for (i = 128; i < 256; i++) - { - unix2dos[i] = CTRLZ; - dos2unix[i] = CTRLZ; - } - -/* MSDOS Code Page 850 -> ISO-8859 */ -update_map("\240\377\241\255\242\275\243\234\244\317\245\276\246\335\247\365"); -update_map("\250\371\251\270\252\246\253\256\254\252\255\360\256\251\257\356"); -update_map("\260\370\261\361\262\375\263\374\264\357\265\346\266\364\267\372"); -update_map("\270\367\271\373\272\247\273\257\274\254\275\253\276\363\277\250"); -update_map("\300\267\301\265\302\266\303\307\304\216\305\217\306\222\307\200"); -update_map("\310\324\311\220\312\322\313\323\314\336\315\326\316\327\317\330"); -update_map("\320\321\321\245\322\343\323\340\324\342\325\345\326\231\327\236"); -update_map("\330\235\331\353\332\351\333\352\334\232\335\355\336\350\337\341"); -update_map("\340\205\341\240\342\203\343\306\344\204\345\206\346\221\347\207"); -update_map("\350\212\351\202\352\210\353\211\354\215\355\241\356\214\357\213"); -update_map("\360\320\361\244\362\225\363\242\364\223\365\344\366\224\367\366"); -update_map("\370\233\371\227\372\243\373\226\374\201\375\354\376\347\377\230"); - -} - -/* Init for eastern european languages. May need more work ? */ - -static void init_iso8859_2() { - - int i; - if (!mapsinited) initmaps(); - - /* Do not map undefined characters to some accidental code */ - for (i = 128; i < 256; i++) - { - unix2dos[i] = CTRLZ; - dos2unix[i] = CTRLZ; - } - -update_map("\241\244\306\217\312\250\243\235\321\343\323\340\246\227\254\215"); -update_map("\257\275\261\245\346\206\352\251\263\210\361\344\363\242\266\230"); -update_map("\274\253\277\276"); -} - -/* - * Convert unix to dos - */ -char *unix2dos_format(char *str,BOOL overwrite) -{ - char *p; - char *dp; - - if (!mapsinited) initmaps(); - if (overwrite) { - for (p = str; *p; p++) *p = unix2dos[(unsigned char)*p]; - return str; - } else { - for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = unix2dos[(unsigned char)*p]; - *dp = 0; - return cvtbuf; - } -} - -/* - * Convert dos to unix - */ -char *dos2unix_format(char *str, BOOL overwrite) -{ - char *p; - char *dp; - - if (!mapsinited) initmaps(); - if (overwrite) { - for (p = str; *p; p++) *p = dos2unix[(unsigned char)*p]; - return str; - } else { - for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = dos2unix[(unsigned char)*p]; - *dp = 0; - return cvtbuf; - } -} - - -/* - * Interpret character set. - */ -int interpret_character_set(char *str, int def) -{ - - if (strequal (str, "iso8859-1")) { - init_iso8859_1(); - } else if (strequal (str, "iso8859-2")) { - init_iso8859_2(); - } else { - DEBUG(0,("unrecognized character set\n")); - } - return def; -} diff --git a/source/lib/charset.c b/source/lib/charset.c deleted file mode 100644 index f066b9a4728..00000000000 --- a/source/lib/charset.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Character set handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#define CHARSET_C -#include "includes.h" - -extern int DEBUGLEVEL; - -/* - * Codepage definitions. - */ - -/* lower->upper mapping for IBM Code Page 850 - MS-DOS Latin 1 */ -unsigned char cp_850[][4] = { -/* dec col/row oct hex description */ -/* 133 08/05 205 85 a grave */ -/* 183 11/07 267 B7 A grave */ {0x85,0xB7,1,1}, -/* 160 10/00 240 A0 a acute */ -/* 181 11/05 265 B5 A acute */ {0xA0,0xB5,1,1}, -/* 131 08/03 203 83 a circumflex */ -/* 182 11/06 266 B6 A circumflex */ {0x83,0xB6,1,1}, -/* 198 12/06 306 C6 a tilde */ -/* 199 12/07 307 C7 A tilde */ {0xC6,0xC7,1,1}, -/* 132 08/04 204 84 a diaeresis */ -/* 142 08/14 216 8E A diaeresis */ {0x84,0x8E,1,1}, -/* 134 08/06 206 86 a ring */ -/* 143 08/15 217 8F A ring */ {0x86,0x8F,1,1}, -/* 145 09/01 221 91 ae diphthong */ -/* 146 09/02 222 92 AE diphthong */ {0x91,0x92,1,1}, -/* 135 08/07 207 87 c cedilla */ -/* 128 08/00 200 80 C cedilla */ {0x87,0x80,1,1}, -/* 138 08/10 212 8A e grave */ -/* 212 13/04 324 D4 E grave */ {0x8A,0xD4,1,1}, -/* 130 08/02 202 82 e acute */ -/* 144 09/00 220 90 E acute */ {0x82,0x90,1,1}, -/* 136 08/08 210 88 e circumflex */ -/* 210 13/02 322 D2 E circumflex */ {0x88,0xD2,1,1}, -/* 137 08/09 211 89 e diaeresis */ -/* 211 13/03 323 D3 E diaeresis */ {0x89,0xD3,1,1}, -/* 141 08/13 215 8D i grave */ -/* 222 13/14 336 DE I grave */ {0x8D,0xDE,1,1}, -/* 161 10/01 241 A1 i acute */ -/* 214 13/06 326 D6 I acute */ {0xA1,0xD6,1,1}, -/* 140 08/12 214 8C i circumflex */ -/* 215 13/07 327 D7 I circumflex */ {0x8C,0xD7,1,1}, -/* 139 08/11 213 8B i diaeresis */ -/* 216 13/08 330 D8 I diaeresis */ {0x8B,0xD8,1,1}, -/* 208 13/00 320 D0 Icelandic eth */ -/* 209 13/01 321 D1 Icelandic Eth */ {0xD0,0xD1,1,1}, -/* 164 10/04 244 A4 n tilde */ -/* 165 10/05 245 A5 N tilde */ {0xA4,0xA5,1,1}, -/* 149 09/05 225 95 o grave */ -/* 227 14/03 343 E3 O grave */ {0x95,0xE3,1,1}, -/* 162 10/02 242 A2 o acute */ -/* 224 14/00 340 E0 O acute */ {0xA2,0xE0,1,1}, -/* 147 09/03 223 93 o circumflex */ -/* 226 14/02 342 E2 O circumflex */ {0x93,0xE2,1,1}, -/* 228 14/04 344 E4 o tilde */ -/* 229 14/05 345 E5 O tilde */ {0xE4,0xE5,1,1}, -/* 148 09/04 224 94 o diaeresis */ -/* 153 09/09 231 99 O diaeresis */ {0x94,0x99,1,1}, -/* 155 09/11 233 9B o slash */ -/* 157 09/13 235 9D O slash */ {0x9B,0x9D,1,1}, -/* 151 09/07 227 97 u grave */ -/* 235 14/11 353 EB U grave */ {0x97,0xEB,1,1}, -/* 163 10/03 243 A3 u acute */ -/* 233 14/09 351 E9 U acute */ {0xA3,0xE9,1,1}, -/* 150 09/06 226 96 u circumflex */ -/* 234 14/10 352 EA U circumflex */ {0x96,0xEA,1,1}, -/* 129 08/01 201 81 u diaeresis */ -/* 154 09/10 232 9A U diaeresis */ {0x81,0x9A,1,1}, -/* 236 14/12 354 EC y acute */ -/* 237 14/13 355 ED Y acute */ {0xEC,0xED,1,1}, -/* 231 14/07 347 E7 Icelandic thorn */ -/* 232 14/08 350 E8 Icelandic Thorn */ {0xE7,0xE8,1,1}, - - {0x9C,0,0,0}, /* Pound */ - {0,0,0,0} -}; - -/* lower->upper mapping for IBM Code Page 437 - MS-DOS Latin US */ -unsigned char cp_437[][4] = { -/* 135 08/07 207 87 c cedilla */ -/* 128 08/00 200 80 C cedilla */ {0x87,0x80,1,1}, -/* 129 08/01 201 81 u diaeresis */ -/* 154 09/10 232 9A U diaeresis */ {0x81,0x9A,1,1}, -/* 130 08/02 202 82 e acute */ -/* 144 09/00 220 90 E acute */ {0x82,0x90,1,1}, -/* 131 08/03 203 83 a circumflex */ {0x83,0x41,1,0}, -/* 132 08/04 204 84 a diaeresis */ -/* 142 08/14 216 8E A diaeresis */ {0x84,0x8E,1,1}, -/* 133 08/05 205 85 a grave */ {0x85,0x41,1,0}, -/* 134 08/06 206 86 a ring */ {0x86,0x8F,1,1}, -/* 136 08/08 210 88 e circumflex */ {0x88,0x45,1,0}, -/* 137 08/09 211 89 e diaeresis */ {0x89,0x45,1,0}, -/* 138 08/10 212 8A e grave */ {0x8A,0x45,1,0}, -/* 139 08/11 213 8B i diaeresis */ {0x8B,0x49,1,0}, -/* 140 08/12 214 8C i circumflex */ {0x8C,0x49,1,0}, -/* 141 08/13 215 8D i grave */ {0x8D,0x49,1,0}, -/* 145 09/01 221 91 ae diphthong */ -/* 146 09/02 222 92 AE diphthong */ {0x91,0x92,1,1}, -/* 147 09/03 223 93 o circumflex */ {0x93,0x4F,1,0}, -/* 148 09/04 224 94 o diaeresis */ -/* 153 09/09 231 99 O diaeresis */ {0x94,0x99,1,1}, -/* 149 09/05 225 95 o grave */ {0x95,0x4F,1,0}, -/* 150 09/06 226 96 u circumflex */ {0x96,0x55,1,0}, -/* 151 09/07 227 97 u grave */ {0x97,0x55,1,0}, -/* 152 ??/?? 201 98 u diaeresis */ - {0x9B,0,0,0}, /* Cent */ - {0x9C,0,0,0}, /* Pound */ - {0x9D,0,0,0}, /* Yen */ -/* 160 10/00 240 A0 a acute */ {0xA0,0x41,1,0}, -/* 161 10/01 241 A1 i acute */ {0xA1,0x49,1,0}, -/* 162 10/02 242 A2 o acute */ {0xA2,0x4F,1,0}, -/* 163 10/03 243 A3 u acute */ {0xA3,0x55,1,0}, -/* 164 10/04 244 A4 n tilde */ -/* 165 10/05 245 A5 N tilde */ {0xA4,0xA5,1,1}, -/* Punctuation... */ - {0xA8,0,0,0}, - {0xAD,0,0,0}, - {0xAE,0,0,0}, - {0xAF,0,0,0}, -/* Greek character set */ - {0xE0,0,0,0}, - {0xE1,0,0,0}, - {0xE2,0,0,0}, - {0xE3,0,0,0}, - {0xE4,0,0,0}, - {0xE5,0,0,0}, - {0xE6,0,0,0}, - {0xE7,0,0,0}, - {0xE8,0,0,0}, - {0xE9,0,0,0}, - {0xEA,0,0,0}, - {0xEB,0,0,0}, - {0xEC,0,0,0}, - {0xED,0,0,0}, - {0xEE,0,0,0}, - {0xEF,0,0,0}, - {0,0,0,0} -}; - -char xx_dos_char_map[256]; -char xx_upper_char_map[256]; -char xx_lower_char_map[256]; - -char *dos_char_map = xx_dos_char_map; -char *upper_char_map = xx_upper_char_map; -char *lower_char_map = xx_lower_char_map; - -/* - * This code has been extended to deal with ascynchronous mappings - * like MS-DOS Latin US (Code page 437) where things like : - * a acute are capitalized to 'A', but the reverse mapping - * must not hold true. This allows the filename case insensitive - * matching in do_match() to work, as the DOS/Win95/NT client - * uses 'A' as a mask to match against characters like a acute. - * This is the meaning behind the parameters that allow a - * mapping from lower to upper, but not upper to lower. - */ - -static void add_dos_char(int lower, BOOL map_lower_to_upper, - int upper, BOOL map_upper_to_lower) -{ - lower &= 0xff; - upper &= 0xff; - DEBUG(6,("Adding chars 0x%x 0x%x (l->u = %s) (u->l = %s)\n",lower,upper, - map_lower_to_upper ? "True" : "False", - map_upper_to_lower ? "True" : "False")); - if (lower) dos_char_map[lower] = 1; - if (upper) dos_char_map[upper] = 1; - if (lower && upper) { - if(map_upper_to_lower) - lower_char_map[upper] = (char)lower; - if(map_lower_to_upper) - upper_char_map[lower] = (char)upper; - } -} - -/**************************************************************************** -initialise the charset arrays -****************************************************************************/ -void charset_initialise(int client_codepage) -{ - int i; - unsigned char (*cp)[4]; - -#ifdef LC_ALL - /* include <locale.h> in includes.h if available for OS */ - /* we take only standard 7-bit ASCII definitions from ctype */ - setlocale(LC_ALL,"C"); -#endif - - for (i= 0;i<=255;i++) { - dos_char_map[i] = 0; - } - - for (i=0;i<=127;i++) { - if (isalnum((char)i) || strchr("._^$~!#%&-{}()@'`",(char)i)) - add_dos_char(i,0,False,False); - } - - for (i=0; i<=255; i++) { - char c = (char)i; - upper_char_map[i] = lower_char_map[i] = c; - if (isupper(c)) lower_char_map[i] = tolower(c); - if (islower(c)) upper_char_map[i] = toupper(c); - } - - if(client_codepage != -1) - DEBUG(6,("charset_initialise: client code page = %d\n", client_codepage)); - - /* - * Known client codepages - these can be added to. - */ - switch(client_codepage) - { - case 850: - cp = cp_850; - break; - case 437: - cp = cp_437; - break; - case -1: /* pre-initialize call so that toupper/tolower work - before smb.conf is read. */ - cp = NULL; - break; - default: - /* Default charset - currently 850 */ - DEBUG(6,("charset_initialise: Using default client codepage %d\n", 850)); - cp = cp_850; - break; - - } - - if(cp) - { - for(i = 0; (cp[i][0] != '\0') && (cp[i][1] != '\0'); i++) - add_dos_char(cp[i][0], (BOOL)cp[i][2], cp[i][1], (BOOL)cp[i][3]); - } -} - -/******************************************************************* -add characters depending on a string passed by the user -********************************************************************/ -void add_char_string(char *s) -{ - char *extra_chars = (char *)strdup(s); - char *t; - if (!extra_chars) return; - - for (t=strtok(extra_chars," \t\r\n"); t; t=strtok(NULL," \t\r\n")) { - char c1=0,c2=0; - int i1=0,i2=0; - if (isdigit(*t) || (*t)=='-') { - sscanf(t,"%i:%i",&i1,&i2); - add_dos_char(i1,True,i2,True); - } else { - sscanf(t,"%c:%c",&c1,&c2); - add_dos_char(c1,True,c2, True); - } - } - - free(extra_chars); -} diff --git a/source/lib/fault.c b/source/lib/fault.c deleted file mode 100644 index 61715a4f225..00000000000 --- a/source/lib/fault.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Critical Fault handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -extern int DEBUGLEVEL; - - -static void (*cont_fn)(); - - -/******************************************************************* -report a fault -********************************************************************/ -static void fault_report(int sig) -{ - DEBUG(0,("===============================================================\n")); - DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)getpid(),VERSION)); - DEBUG(0,("\nPlease read the file BUGS.txt in the distribution\n")); - DEBUG(0,("===============================================================\n")); - -#if AJT - ajt_panic(); -#endif - - if (cont_fn) - { - fault_setup(cont_fn); - cont_fn(NULL); -#ifdef SIGSEGV - signal(SIGSEGV,SIGNAL_CAST SIG_DFL); -#endif -#ifdef SIGBUS - signal(SIGBUS,SIGNAL_CAST SIG_DFL); -#endif - return; /* this should cause a core dump */ - } - exit(1); -} - -/**************************************************************************** -catch serious errors -****************************************************************************/ -static void sig_fault(int sig) -{ - fault_report(sig); -} - -/******************************************************************* -setup our fault handlers -********************************************************************/ -void fault_setup(void (*fn)()) -{ - cont_fn = fn; - -#ifdef SIGSEGV - signal(SIGSEGV,SIGNAL_CAST sig_fault); -#endif -#ifdef SIGBUS - signal(SIGBUS,SIGNAL_CAST sig_fault); -#endif -} - - - diff --git a/source/lib/getsmbpass.c b/source/lib/getsmbpass.c deleted file mode 100644 index 7ee8c187885..00000000000 --- a/source/lib/getsmbpass.c +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. -This file is part of the GNU C Library. - -The GNU C Library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -The GNU C Library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with the GNU C Library; see the file COPYING.LIB. If -not, write to the Free Software Foundation, Inc., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -/* Modified to use with samba by Jeremy Allison, 8th July 1995. */ - -#include "includes.h" - -#ifdef REPLACE_GETPASS - -#ifdef SYSV_TERMIO - -/* SYSTEM V TERMIO HANDLING */ - -static struct termio t; - -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -#ifndef TCSAFLUSH -#define TCSAFLUSH 1 -#endif - -#ifndef TCSANOW -#define TCSANOW 0 -#endif - - int tcgetattr(int fd, struct termio *t) -{ - return ioctl(fd, TCGETA, t); -} - - int tcsetattr(int fd, int flags, const struct termio *t) -{ - if(flags & TCSAFLUSH) - ioctl(fd, TCFLSH, TCIOFLUSH); - return ioctl(fd, TCSETS, t); -} - -#else /* SYSV_TERMIO */ -#ifdef BSD_TERMIO - -/* BSD TERMIO HANDLING */ - -static struct sgttyb t; - -#define ECHO_IS_ON(t) ((t).sg_flags & ECHO) -#define TURN_ECHO_OFF(t) ((t).sg_flags &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).sg_flags |= ECHO) - -#ifndef TCSAFLUSH -#define TCSAFLUSH 1 -#endif - -#ifndef TCSANOW -#define TCSANOW 0 -#endif - - int tcgetattr(int fd, struct sgttyb *t) -{ - return ioctl(fd, TIOCGETP, (char *)t); -} - - int tcsetattr(int fd, int flags, const struct sgttyb *t) -{ - return ioctl(fd, TIOCSETP, (char *)t); -} - -#else /* BSD_TERMIO */ - -/* POSIX TERMIO HANDLING */ -#define ECHO_IS_ON(t) ((t).c_lflag & ECHO) -#define TURN_ECHO_OFF(t) ((t).c_lflag &= ~ECHO) -#define TURN_ECHO_ON(t) ((t).c_lflag |= ECHO) - -static struct termios t; -#endif /* BSD_TERMIO */ -#endif /* SYSV_TERMIO */ - -char *getsmbpass(char *prompt) -{ - FILE *in, *out; - int echo_off; - static char buf[256]; - static size_t bufsize = sizeof(buf); - size_t nread; - - /* Catch problematic signals */ - signal(SIGINT, SIGNAL_CAST SIG_IGN); - - /* Try to write to and read from the terminal if we can. - If we can't open the terminal, use stderr and stdin. */ - - in = fopen ("/dev/tty", "w+"); - if (in == NULL) - { - in = stdin; - out = stderr; - } - else - out = in; - - setvbuf(in, NULL, _IONBF, 0); - - /* Turn echoing off if it is on now. */ - - if (tcgetattr (fileno (in), &t) == 0) - { - if (ECHO_IS_ON(t)) - { - TURN_ECHO_OFF(t); - echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; - TURN_ECHO_ON(t); - } - else - echo_off = 0; - } - else - echo_off = 0; - - /* Write the prompt. */ - fputs (prompt, out); - fflush (out); - - /* Read the password. */ - buf[0] = 0; - fgets(buf, bufsize, in); - nread = strlen(buf); - if (buf[nread - 1] == '\n') - buf[nread - 1] = '\0'; - - /* Restore echoing. */ - if (echo_off) - (void) tcsetattr (fileno (in), TCSANOW, &t); - - if (in != stdin) - /* We opened the terminal; now close it. */ - fclose (in); - - /* Catch problematic signals */ - signal(SIGINT, SIGNAL_CAST SIG_DFL); - - printf("\n"); - return buf; -} - -#else - - void getsmbpasswd_dummy() {;} -#endif diff --git a/source/lib/interface.c b/source/lib/interface.c deleted file mode 100644 index 444d511426b..00000000000 --- a/source/lib/interface.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - multiple interface handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - -struct in_addr ipzero; -struct in_addr wins_ip; -static struct in_addr default_ip; -static struct in_addr default_bcast; -static struct in_addr default_nmask; -static BOOL got_ip=False; -static BOOL got_bcast=False; -static BOOL got_nmask=False; - -struct interface *local_interfaces = NULL; - -struct interface *last_iface; - -/**************************************************************************** -calculate the default netmask for an address -****************************************************************************/ -static void default_netmask(struct in_addr *inm, struct in_addr *iad) -{ - uint32 ad = ntohl(iad->s_addr); - uint32 nm; - /* - ** Guess a netmask based on the class of the IP address given. - */ - if ( (ad & 0x80000000) == 0 ) { - /* class A address */ - nm = 0xFF000000; - } else if ( (ad & 0xC0000000) == 0x80000000 ) { - /* class B address */ - nm = 0xFFFF0000; - } else if ( (ad & 0xE0000000) == 0xC0000000 ) { - /* class C address */ - nm = 0xFFFFFF00; - } else { - /* class D or E; netmask doesn't make much sense - guess 4 bits */ - nm = 0xFFFFFFF0; - } - inm->s_addr = htonl(nm); -} - - -/**************************************************************************** - get the broadcast address for our address -(troyer@saifr00.ateng.az.honeywell.com) -****************************************************************************/ -static void get_broadcast(struct in_addr *if_ipaddr, - struct in_addr *if_bcast, - struct in_addr *if_nmask) -{ - BOOL found = False; -#ifndef NO_GET_BROADCAST - int sock = -1; /* AF_INET raw socket desc */ - char buff[1024]; - struct ifreq *ifr=NULL; - int i; - -#if defined(EVEREST) - int n_interfaces; - struct ifconf ifc; - struct ifreq *ifreqs; -#elif defined(USE_IFREQ) - struct ifreq ifreq; - struct strioctl strioctl; - struct ifconf *ifc; -#else - struct ifconf ifc; -#endif -#endif - - /* get a default netmask and broadcast */ - default_netmask(if_nmask, if_ipaddr); - -#ifndef NO_GET_BROADCAST - /* Create a socket to the INET kernel. */ -#if USE_SOCKRAW - if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0) -#else - if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0) -#endif - { - DEBUG(0,( "Unable to open socket to get broadcast address\n")); - return; - } - - /* Get a list of the configured interfaces */ -#ifdef EVEREST - /* This is part of SCO Openserver 5: The ioctls are no longer part - if the lower level STREAMS interface glue. They are now real - ioctl calls */ - - if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) { - DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno))); - } else { - DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces)); - - ifc.ifc_len = sizeof(struct ifreq) * n_interfaces; - ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len); - - if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) - DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno))); - else { - ifr = ifc.ifc_req; - - for (i = 0; i < n_interfaces; ++i) { - if (if_ipaddr->s_addr == - ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) { - found = True; - break; - } - } - } - } -#elif defined(USE_IFREQ) - ifc = (struct ifconf *)buff; - ifc->ifc_len = BUFSIZ - sizeof(struct ifconf); - strioctl.ic_cmd = SIOCGIFCONF; - strioctl.ic_dp = (char *)ifc; - strioctl.ic_len = sizeof(buff); - if (ioctl(sock, I_STR, &strioctl) < 0) { - DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno))); - } else { - ifr = (struct ifreq *)ifc->ifc_req; - - /* Loop through interfaces, looking for given IP address */ - for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { - if (if_ipaddr->s_addr == - (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { - found = True; - break; - } - } - } -#elif defined(__FreeBSD__) || defined(NETBSD) || defined(AMIGA) - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { - DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); - } else { - ifr = ifc.ifc_req; - /* Loop through interfaces, looking for given IP address */ - i = ifc.ifc_len; - while (i > 0) { - if (if_ipaddr->s_addr == - (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { - found = True; - break; - } - i -= ifr->ifr_addr.sa_len + IFNAMSIZ; - ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ); - } - } -#else - ifc.ifc_len = sizeof(buff); - ifc.ifc_buf = buff; - if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { - DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno))); - } else { - ifr = ifc.ifc_req; - - /* Loop through interfaces, looking for given IP address */ - for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) { -#ifdef BSDI - if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break; -#endif - if (if_ipaddr->s_addr == - (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) { - found = True; - break; - } - } - } -#endif - - if (!found) { - DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr))); - } else { - /* Get the netmask address from the kernel */ -#ifdef USE_IFREQ - ifreq = *ifr; - - strioctl.ic_cmd = SIOCGIFNETMASK; - strioctl.ic_dp = (char *)&ifreq; - strioctl.ic_len = sizeof(struct ifreq); - if (ioctl(sock, I_STR, &strioctl) < 0) - DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno))); - else - *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; -#else - if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0) - DEBUG(0,("SIOCGIFNETMASK failed\n")); - else - *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; -#endif - - DEBUG(4,("Netmask for %s = %s\n", ifr->ifr_name, - inet_ntoa(*if_nmask))); - } - - /* Close up shop */ - (void) close(sock); - -#endif - - /* sanity check on the netmask */ - { - uint32 nm = ntohl(if_nmask->s_addr); - if ((nm >> 24) != 0xFF) { - DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask))); - default_netmask(if_nmask, if_ipaddr); - } - } - - /* derive the broadcast assuming a 1's broadcast, as this is what - all MS operating systems do, we have to comply even if the unix - box is setup differently */ - { - uint32 ad = ntohl(if_ipaddr->s_addr); - uint32 nm = ntohl(if_nmask->s_addr); - uint32 bc = (ad & nm) | (0xffffffff & ~nm); - if_bcast->s_addr = htonl(bc); - } - - DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast))); -} /* get_broadcast */ - - - -/**************************************************************************** -load a list of network interfaces -****************************************************************************/ -static void interpret_interfaces(char *s, struct interface **interfaces, - char *description) -{ - char *ptr = s; - fstring token; - struct interface *iface; - struct in_addr ip; - - ipzero = *interpret_addr2("0.0.0.0"); - wins_ip = *interpret_addr2("255.255.255.255"); - - while (next_token(&ptr,token,NULL)) { - /* parse it into an IP address/netmasklength pair */ - char *p = strchr(token,'/'); - if (p) *p = 0; - - ip = *interpret_addr2(token); - - /* maybe we already have it listed */ - { - struct interface *i; - for (i=(*interfaces);i;i=i->next) - if (ip_equal(ip,i->ip)) break; - if (i) continue; - } - - iface = (struct interface *)malloc(sizeof(*iface)); - if (!iface) return; - - iface->ip = ip; - - if (p) { - if (strlen(p+1)>2) - iface->nmask = *interpret_addr2(p+1); - else - iface->nmask.s_addr = htonl(~((1<<(32-atoi(p+1)))-1)); - } else { - default_netmask(&iface->nmask,&iface->ip); - } - iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr; - iface->next = NULL; - - if (!(*interfaces)) { - (*interfaces) = iface; - } else { - last_iface->next = iface; - } - last_iface = iface; - DEBUG(1,("Added %s ip=%s ",description,inet_ntoa(iface->ip))); - DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask))); - } - - if (*interfaces) return; - - /* setup a default interface */ - iface = (struct interface *)malloc(sizeof(*iface)); - if (!iface) return; - - iface->next = NULL; - - if (got_ip) { - iface->ip = default_ip; - } else { - get_myname(NULL,&iface->ip); - } - - if (got_bcast) { - iface->bcast = default_bcast; - } else { - get_broadcast(&iface->ip,&iface->bcast,&iface->nmask); - } - - if (got_nmask) { - iface->nmask = default_nmask; - iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr; - } - - if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) { - DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip))); - } - - iface->next = NULL; - (*interfaces) = last_iface = iface; - - DEBUG(1,("Added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask))); -} - - -/**************************************************************************** -load the remote and local interfaces -****************************************************************************/ -void load_interfaces(void) -{ - /* add the machine's interfaces to local interface structure*/ - interpret_interfaces(lp_interfaces(), &local_interfaces,"interface"); -} - - -/**************************************************************************** - override the defaults - **************************************************************************/ -void iface_set_default(char *ip,char *bcast,char *nmask) -{ - if (ip) { - got_ip = True; - default_ip = *interpret_addr2(ip); - } - - if (bcast) { - got_bcast = True; - default_bcast = *interpret_addr2(bcast); - } - - if (nmask) { - got_nmask = True; - default_nmask = *interpret_addr2(nmask); - } -} - - -/**************************************************************************** - check if an IP is one of mine - **************************************************************************/ -BOOL ismyip(struct in_addr ip) -{ - struct interface *i; - for (i=local_interfaces;i;i=i->next) - if (ip_equal(i->ip,ip)) return True; - return False; -} - -/**************************************************************************** - check if a bcast is one of mine - **************************************************************************/ -BOOL ismybcast(struct in_addr bcast) -{ - struct interface *i; - for (i=local_interfaces;i;i=i->next) - if (ip_equal(i->bcast,bcast)) return True; - return False; -} - -/**************************************************************************** - how many interfaces do we have - **************************************************************************/ -int iface_count(void) -{ - int ret = 0; - struct interface *i; - - for (i=local_interfaces;i;i=i->next) - ret++; - return ret; -} - -/**************************************************************************** - return IP of the Nth interface - **************************************************************************/ -struct in_addr *iface_n_ip(int n) -{ - struct interface *i; - - for (i=local_interfaces;i && n;i=i->next) - n--; - - if (i) return &i->ip; - return NULL; -} - -static struct interface *iface_find(struct in_addr ip) -{ - struct interface *i; - if (zero_ip(ip)) return local_interfaces; - - for (i=local_interfaces;i;i=i->next) - if (same_net(i->ip,ip,i->nmask)) return i; - - return local_interfaces; -} - -/* these 3 functions return the ip/bcast/nmask for the interface - most appropriate for the given ip address */ - -struct in_addr *iface_bcast(struct in_addr ip) -{ - return(&iface_find(ip)->bcast); -} - -struct in_addr *iface_nmask(struct in_addr ip) -{ - return(&iface_find(ip)->nmask); -} - -struct in_addr *iface_ip(struct in_addr ip) -{ - return(&iface_find(ip)->ip); -} - - - diff --git a/source/lib/kanji.c b/source/lib/kanji.c deleted file mode 100644 index 479763fd406..00000000000 --- a/source/lib/kanji.c +++ /dev/null @@ -1,894 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Kanji Extensions - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Adding for Japanese language by <fujita@ainix.isac.co.jp> 1994.9.5 - and extend coding system to EUC/SJIS/JIS/HEX at 1994.10.11 - and add all jis codes sequence type at 1995.8.16 - Notes: Hexadecimal code by <ohki@gssm.otuka.tsukuba.ac.jp> -*/ -#ifdef KANJI - -#define _KANJI_C_ -#include "includes.h" - -/* coding system keep in */ -int coding_system = SJIS_CODE; - -/* jis si/so sequence */ -char jis_kso = JIS_KSO; -char jis_ksi = JIS_KSI; -char hex_tag = HEXTAG; - -/******************************************************************* - SHIFT JIS functions -********************************************************************/ -/******************************************************************* - search token from S1 separated any char of S2 - S1 contain SHIFT JIS chars. -********************************************************************/ -char * -sj_strtok (char *s1, const char *s2) -{ - static char *s = NULL; - char *q; - if (!s1) { - if (!s) { - return NULL; - } - s1 = s; - } - for (q = s1; *s1; ) { - if (is_shift_jis (*s1)) { - s1 += 2; - } else if (is_kana (*s1)) { - s1++; - } else { - char *p = strchr (s2, *s1); - if (p) { - if (s1 != q) { - s = s1 + 1; - *s1 = '\0'; - return q; - } - q = s1 + 1; - } - s1++; - } - } - s = NULL; - if (*q) { - return q; - } - return NULL; -} - -/******************************************************************* - search string S2 from S1 - S1 contain SHIFT JIS chars. -********************************************************************/ -char * -sj_strstr (const char *s1, const char *s2) -{ - register int len = strlen ((char *) s2); - if (!*s2) - return (char *) s1; - for (;*s1;) { - if (*s1 == *s2) { - if (strncmp (s1, s2, len) == 0) - return (char *) s1; - } - if (is_shift_jis (*s1)) { - s1 += 2; - } else { - s1++; - } - } - return 0; -} - -/******************************************************************* - Search char C from beginning of S. - S contain SHIFT JIS chars. -********************************************************************/ -char * -sj_strchr (const char *s, int c) -{ - for (; *s; ) { - if (*s == c) - return (char *) s; - if (is_shift_jis (*s)) { - s += 2; - } else { - s++; - } - } - return 0; -} - -/******************************************************************* - Search char C end of S. - S contain SHIFT JIS chars. -********************************************************************/ -char * -sj_strrchr (const char *s, int c) -{ - register char *q; - - for (q = 0; *s; ) { - if (*s == c) { - q = (char *) s; - } - if (is_shift_jis (*s)) { - s += 2; - } else { - s++; - } - } - return q; -} - -/******************************************************************* - Code conversion -********************************************************************/ -/* convesion buffer */ -static char cvtbuf[1024]; - -/******************************************************************* - EUC <-> SJIS -********************************************************************/ -static int -euc2sjis (register int hi, register int lo) -{ - if (hi & 1) - return ((hi / 2 + (hi < 0xdf ? 0x31 : 0x71)) << 8) | - (lo - (lo >= 0xe0 ? 0x60 : 0x61)); - else - return ((hi / 2 + (hi < 0xdf ? 0x30 : 0x70)) << 8) | (lo - 2); -} - -static int -sjis2euc (register int hi, register int lo) -{ - if (lo >= 0x9f) - return ((hi * 2 - (hi >= 0xe0 ? 0xe0 : 0x60)) << 8) | (lo + 2); - else - return ((hi * 2 - (hi >= 0xe0 ? 0xe1 : 0x61)) << 8) | - (lo + (lo >= 0x7f ? 0x60 : 0x61)); -} - -/******************************************************************* - Convert FROM contain SHIFT JIS codes to EUC codes - return converted buffer -********************************************************************/ -static char * -sj_to_euc (const char *from, BOOL overwrite) -{ - register char *out; - char *save; - - save = (char *) from; - for (out = cvtbuf; *from;) { - if (is_shift_jis (*from)) { - int code = sjis2euc ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } else if (is_kana (*from)) { - *out++ = euc_kana; - *out++ = *from++; - } else { - *out++ = *from++; - } - } - *out = 0; - if (overwrite) { - strcpy((char *) save, (char *) cvtbuf); - return (char *) save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - Convert FROM contain EUC codes to SHIFT JIS codes - return converted buffer -********************************************************************/ -static char * -euc_to_sj (const char *from, BOOL overwrite) -{ - register char *out; - char *save; - - save = (char *) from; - for (out = cvtbuf; *from; ) { - if (is_euc (*from)) { - int code = euc2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } else if (is_euc_kana (*from)) { - *out++ = from[1]; - from += 2; - } else { - *out++ = *from++; - } - } - *out = 0; - if (overwrite) { - strcpy(save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - JIS7,JIS8,JUNET <-> SJIS -********************************************************************/ -static int -sjis2jis (register int hi, register int lo) -{ - if (lo >= 0x9f) - return ((hi * 2 - (hi >= 0xe0 ? 0x160 : 0xe0)) << 8) | (lo - 0x7e); - else - return ((hi * 2 - (hi >= 0xe0 ? 0x161 : 0xe1)) << 8) | - (lo - (lo >= 0x7f ? 0x20 : 0x1f)); -} - -static int -jis2sjis (register int hi, register int lo) -{ - if (hi & 1) - return ((hi / 2 + (hi < 0x5f ? 0x71 : 0xb1)) << 8) | - (lo + (lo >= 0x60 ? 0x20 : 0x1f)); - else - return ((hi / 2 + (hi < 0x5f ? 0x70 : 0xb0)) << 8) | (lo + 0x7e); -} - -/******************************************************************* - Convert FROM contain JIS codes to SHIFT JIS codes - return converted buffer -********************************************************************/ -static char * -jis8_to_sj (const char *from, BOOL overwrite) -{ - register char *out; - register int shifted; - char *save; - - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from;) { - if (is_esc (*from)) { - if (is_so1 (from[1]) && is_so2 (from[2])) { - shifted = _KJ_KANJI; - from += 3; - } else if (is_si1 (from[1]) && is_si2 (from[2])) { - shifted = _KJ_ROMAN; - from += 3; - } else { /* sequence error */ - goto normal; - } - } else { - normal: - switch (shifted) { - default: - case _KJ_ROMAN: - *out++ = *from++; - break; - case _KJ_KANJI: - { - int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } - break; - } - } - } - *out = 0; - if (overwrite) { - strcpy (save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - Convert FROM contain SHIFT JIS codes to JIS codes - return converted buffer -********************************************************************/ -static char * -sj_to_jis8 (const char *from, BOOL overwrite) -{ - register char *out; - register int shifted; - char *save; - - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from; ) { - if (is_shift_jis (*from)) { - int code; - switch (shifted) { - case _KJ_ROMAN: /* to KANJI */ - *out++ = jis_esc; - *out++ = jis_so1; - *out++ = jis_kso; - shifted = _KJ_KANJI; - break; - } - code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } else { - switch (shifted) { - case _KJ_KANJI: /* to ROMAN/KANA */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - shifted = _KJ_ROMAN; - break; - } - *out++ = *from++; - } - } - switch (shifted) { - case _KJ_KANJI: /* to ROMAN/KANA */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - shifted = _KJ_ROMAN; - break; - } - *out = 0; - if (overwrite) { - strcpy (save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - Convert FROM contain 7 bits JIS codes to SHIFT JIS codes - return converted buffer -********************************************************************/ -static char * -jis7_to_sj (const char *from, BOOL overwrite) -{ - register char *out; - register int shifted; - char *save; - - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from;) { - if (is_esc (*from)) { - if (is_so1 (from[1]) && is_so2 (from[2])) { - shifted = _KJ_KANJI; - from += 3; - } else if (is_si1 (from[1]) && is_si2 (from[2])) { - shifted = _KJ_ROMAN; - from += 3; - } else { /* sequence error */ - goto normal; - } - } else if (is_so (*from)) { - shifted = _KJ_KANA; /* to KANA */ - from++; - } else if (is_si (*from)) { - shifted = _KJ_ROMAN; /* to ROMAN */ - from++; - } else { - normal: - switch (shifted) { - default: - case _KJ_ROMAN: - *out++ = *from++; - break; - case _KJ_KANJI: - { - int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } - break; - case _KJ_KANA: - *out++ = ((int) from[0]) + 0x80; - break; - } - } - } - *out = 0; - if (overwrite) { - strcpy (save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - Convert FROM contain SHIFT JIS codes to 7 bits JIS codes - return converted buffer -********************************************************************/ -static char * -sj_to_jis7 (const char *from, BOOL overwrite) -{ - register char *out; - register int shifted; - char *save; - - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from; ) { - if (is_shift_jis (*from)) { - int code; - switch (shifted) { - case _KJ_KANA: - *out++ = jis_si; /* to ROMAN and through down */ - case _KJ_ROMAN: /* to KANJI */ - *out++ = jis_esc; - *out++ = jis_so1; - *out++ = jis_kso; - shifted = _KJ_KANJI; - break; - } - code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } else if (is_kana (from[0])) { - switch (shifted) { - case _KJ_KANJI: /* to ROMAN */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - case _KJ_ROMAN: /* to KANA */ - *out++ = jis_so; - shifted = _KJ_KANA; - break; - } - *out++ = ((int) *from++) - 0x80; - } else { - switch (shifted) { - case _KJ_KANA: - *out++ = jis_si; /* to ROMAN */ - shifted = _KJ_ROMAN; - break; - case _KJ_KANJI: /* to ROMAN */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - shifted = _KJ_ROMAN; - break; - } - *out++ = *from++; - } - } - switch (shifted) { - case _KJ_KANA: - *out++ = jis_si; /* to ROMAN */ - break; - case _KJ_KANJI: /* to ROMAN */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_ksi; - break; - } - *out = 0; - if (overwrite) { - strcpy (save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - Convert FROM contain 7 bits JIS(junet) codes to SHIFT JIS codes - return converted buffer -********************************************************************/ -static char * -junet_to_sj (const char *from, BOOL overwrite) -{ - register char *out; - register int shifted; - char *save; - - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from;) { - if (is_esc (*from)) { - if (is_so1 (from[1]) && is_so2 (from[2])) { - shifted = _KJ_KANJI; - from += 3; - } else if (is_si1 (from[1]) && is_si2 (from[2])) { - shifted = _KJ_ROMAN; - from += 3; - } else if (is_juk1(from[1]) && is_juk2 (from[2])) { - shifted = _KJ_KANA; - from += 3; - } else { /* sequence error */ - goto normal; - } - } else { - normal: - switch (shifted) { - default: - case _KJ_ROMAN: - *out++ = *from++; - break; - case _KJ_KANJI: - { - int code = jis2sjis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } - break; - case _KJ_KANA: - *out++ = ((int) from[0]) + 0x80; - break; - } - } - } - *out = 0; - if (overwrite) { - strcpy (save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - Convert FROM contain SHIFT JIS codes to 7 bits JIS(junet) codes - return converted buffer -********************************************************************/ -static char * -sj_to_junet (const char *from, BOOL overwrite) -{ - register char *out; - register int shifted; - char *save; - - shifted = _KJ_ROMAN; - save = (char *) from; - for (out = cvtbuf; *from; ) { - if (is_shift_jis (*from)) { - int code; - switch (shifted) { - case _KJ_KANA: - case _KJ_ROMAN: /* to KANJI */ - *out++ = jis_esc; - *out++ = jis_so1; - *out++ = jis_so2; - shifted = _KJ_KANJI; - break; - } - code = sjis2jis ((int) from[0] & 0xff, (int) from[1] & 0xff); - *out++ = (code >> 8) & 0xff; - *out++ = code; - from += 2; - } else if (is_kana (from[0])) { - switch (shifted) { - case _KJ_KANJI: /* to ROMAN */ - case _KJ_ROMAN: /* to KANA */ - *out++ = jis_esc; - *out++ = junet_kana1; - *out++ = junet_kana2; - shifted = _KJ_KANA; - break; - } - *out++ = ((int) *from++) - 0x80; - } else { - switch (shifted) { - case _KJ_KANA: - case _KJ_KANJI: /* to ROMAN */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_si2; - shifted = _KJ_ROMAN; - break; - } - *out++ = *from++; - } - } - switch (shifted) { - case _KJ_KANA: - case _KJ_KANJI: /* to ROMAN */ - *out++ = jis_esc; - *out++ = jis_si1; - *out++ = jis_si2; - break; - } - *out = 0; - if (overwrite) { - strcpy (save, (char *) cvtbuf); - return save; - } else { - return cvtbuf; - } -} - -/******************************************************************* - HEX <-> SJIS -********************************************************************/ -/* ":xx" -> a byte */ -static char * -hex_to_sj (const char *from, BOOL overwrite) -{ - char *sp, *dp; - - sp = (char *) from; - dp = cvtbuf; - while (*sp) { - if (*sp == hex_tag && isxdigit (sp[1]) && isxdigit (sp[2])) { - *dp++ = (hex2bin (sp[1])<<4) | (hex2bin (sp[2])); - sp += 3; - } else - *dp++ = *sp++; - } - *dp = '\0'; - if (overwrite) { - strcpy ((char *) from, (char *) cvtbuf); - return (char *) from; - } else { - return cvtbuf; - } -} - -/******************************************************************* - kanji/kana -> ":xx" -********************************************************************/ -static char * -sj_to_hex (const char *from, BOOL overwrite) -{ - unsigned char *sp, *dp; - - sp = (unsigned char*) from; - dp = (unsigned char*) cvtbuf; - while (*sp) { - if (is_kana(*sp)) { - *dp++ = hex_tag; - *dp++ = bin2hex (((*sp)>>4)&0x0f); - *dp++ = bin2hex ((*sp)&0x0f); - sp++; - } else if (is_shift_jis (*sp) && is_shift_jis2 (sp[1])) { - *dp++ = hex_tag; - *dp++ = bin2hex (((*sp)>>4)&0x0f); - *dp++ = bin2hex ((*sp)&0x0f); - sp++; - *dp++ = hex_tag; - *dp++ = bin2hex (((*sp)>>4)&0x0f); - *dp++ = bin2hex ((*sp)&0x0f); - sp++; - } else - *dp++ = *sp++; - } - *dp = '\0'; - if (overwrite) { - strcpy ((char *) from, (char *) cvtbuf); - return (char *) from; - } else { - return cvtbuf; - } -} - -/******************************************************************* - kanji/kana -> ":xx" -********************************************************************/ -static char * -sj_to_cap (const char *from, BOOL overwrite) -{ - unsigned char *sp, *dp; - - sp = (unsigned char*) from; - dp = (unsigned char*) cvtbuf; - while (*sp) { - if (*sp >= 0x80) { - *dp++ = hex_tag; - *dp++ = bin2hex (((*sp)>>4)&0x0f); - *dp++ = bin2hex ((*sp)&0x0f); - sp++; - } else { - *dp++ = *sp++; - } - } - *dp = '\0'; - if (overwrite) { - strcpy ((char *) from, (char *) cvtbuf); - return (char *) from; - } else { - return cvtbuf; - } -} - -/******************************************************************* - sj to sj -********************************************************************/ -static char * -sj_to_sj (const char *from, BOOL overwrite) -{ - if (!overwrite) { - strcpy (cvtbuf, (char *) from); - return cvtbuf; - } else { - return (char *) from; - } -} - -/************************************************************************ - conversion: - _dos_to_unix _unix_to_dos -************************************************************************/ - -char* (*_dos_to_unix) (const char *str, BOOL overwrite) = sj_to_sj; -char* (*_unix_to_dos) (const char *str, BOOL overwrite) = sj_to_sj; - -static int -setup_string_function (int codes) -{ - switch (codes) { - default: - case SJIS_CODE: - _dos_to_unix = sj_to_sj; - _unix_to_dos = sj_to_sj; - - break; - - case EUC_CODE: - _dos_to_unix = sj_to_euc; - _unix_to_dos = euc_to_sj; - break; - - case JIS7_CODE: - _dos_to_unix = sj_to_jis7; - _unix_to_dos = jis7_to_sj; - break; - - case JIS8_CODE: - _dos_to_unix = sj_to_jis8; - _unix_to_dos = jis8_to_sj; - break; - - case JUNET_CODE: - _dos_to_unix = sj_to_junet; - _unix_to_dos = junet_to_sj; - break; - - case HEX_CODE: - _dos_to_unix = sj_to_hex; - _unix_to_dos = hex_to_sj; - break; - - case CAP_CODE: - _dos_to_unix = sj_to_cap; - _unix_to_dos = hex_to_sj; - break; - } - return codes; -} - -/* - * Interpret coding system. - */ -int interpret_coding_system(char *str, int def) -{ - int codes = def; - - if (strequal (str, "sjis")) { - codes = SJIS_CODE; - } else if (strequal (str, "euc")) { - codes = EUC_CODE; - } else if (strequal (str, "cap")) { - codes = CAP_CODE; - hex_tag = HEXTAG; - } else if (strequal (str, "hex")) { - codes = HEX_CODE; - hex_tag = HEXTAG; - } else if (strncasecmp (str, "hex", 3)) { - codes = HEX_CODE; - hex_tag = (str[3] ? str[3] : HEXTAG); - } else if (strequal (str, "j8bb")) { - codes = JIS8_CODE; - jis_kso = 'B'; - jis_ksi = 'B'; - } else if (strequal (str, "j8bj") || strequal (str, "jis8")) { - codes = JIS8_CODE; - jis_kso = 'B'; - jis_ksi = 'J'; - } else if (strequal (str, "j8bh")) { - codes = JIS8_CODE; - jis_kso = 'B'; - jis_ksi = 'H'; - } else if (strequal (str, "j8@b")) { - codes = JIS8_CODE; - jis_kso = '@'; - jis_ksi = 'B'; - } else if (strequal (str, "j8@j")) { - codes = JIS8_CODE; - jis_kso = '@'; - jis_ksi = 'J'; - } else if (strequal (str, "j8@h")) { - codes = JIS8_CODE; - jis_kso = '@'; - jis_ksi = 'H'; - } else if (strequal (str, "j7bb")) { - codes = JIS7_CODE; - jis_kso = 'B'; - jis_ksi = 'B'; - } else if (strequal (str, "j7bj") || strequal (str, "jis7")) { - codes = JIS7_CODE; - jis_kso = 'B'; - jis_ksi = 'J'; - } else if (strequal (str, "j7bh")) { - codes = JIS7_CODE; - jis_kso = 'B'; - jis_ksi = 'H'; - } else if (strequal (str, "j7@b")) { - codes = JIS7_CODE; - jis_kso = '@'; - jis_ksi = 'B'; - } else if (strequal (str, "j7@j")) { - codes = JIS7_CODE; - jis_kso = '@'; - jis_ksi = 'J'; - } else if (strequal (str, "j7@h")) { - codes = JIS7_CODE; - jis_kso = '@'; - jis_ksi = 'H'; - } else if (strequal (str, "jubb")) { - codes = JUNET_CODE; - jis_kso = 'B'; - jis_ksi = 'B'; - } else if (strequal (str, "jubj") || strequal (str, "junet")) { - codes = JUNET_CODE; - jis_kso = 'B'; - jis_ksi = 'J'; - } else if (strequal (str, "jubh")) { - codes = JUNET_CODE; - jis_kso = 'B'; - jis_ksi = 'H'; - } else if (strequal (str, "ju@b")) { - codes = JUNET_CODE; - jis_kso = '@'; - jis_ksi = 'B'; - } else if (strequal (str, "ju@j")) { - codes = JUNET_CODE; - jis_kso = '@'; - jis_ksi = 'J'; - } else if (strequal (str, "ju@h")) { - codes = JUNET_CODE; - jis_kso = '@'; - jis_ksi = 'H'; - } - return setup_string_function (codes); -} -#else - int kanji_dummy_procedure(void) -{return 0;} -#endif /* KANJI */ diff --git a/source/lib/md4.c b/source/lib/md4.c deleted file mode 100644 index bdff075c7e7..00000000000 --- a/source/lib/md4.c +++ /dev/null @@ -1,299 +0,0 @@ -#ifdef SMB_PASSWD -/* - This code is from rfc1186. -*/ - - /* - ** ******************************************************************** - ** md4.c -- Implementation of MD4 Message Digest Algorithm ** - ** Updated: 2/16/90 by Ronald L. Rivest ** - ** (C) 1990 RSA Data Security, Inc. ** - ** ******************************************************************** - */ - - /* - ** To use MD4: - ** -- Include md4.h in your program - ** -- Declare an MDstruct MD to hold the state of the digest - ** computation. - ** -- Initialize MD using MDbegin(&MD) - ** -- For each full block (64 bytes) X you wish to process, call - ** MDupdate(&MD,X,512) - ** (512 is the number of bits in a full block.) - ** -- For the last block (less than 64 bytes) you wish to process, - ** MDupdate(&MD,X,n) - ** where n is the number of bits in the partial block. A partial - ** block terminates the computation, so every MD computation - ** should terminate by processing a partial block, even if it - ** has n = 0. - ** -- The message digest is available in MD.buffer[0] ... - ** MD.buffer[3]. (Least-significant byte of each word - ** should be output first.) - ** -- You can print out the digest using MDprint(&MD) - */ - - /* Implementation notes: - ** This implementation assumes that ints are 32-bit quantities. - ** If the machine stores the least-significant byte of an int in the - ** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST - ** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST - ** should be set to FALSE. Note that on machines with LOWBYTEFIRST - ** FALSE the routine MDupdate modifies has a side-effect on its input - ** array (the order of bytes in each word are reversed). If this is - ** undesired a call to MDreverse(X) can reverse the bytes of X back - ** into order after each call to MDupdate. - */ - -#define TRUE 1 -#define FALSE 0 - - /* Compile-time includes - */ - -#include <stdio.h> -#include "md4.h" - -#define uchar unsigned char -#define int16 unsigned short -#define uint32 unsigned int - -#include "byteorder.h" - - /* Compile-time declarations of MD4 "magic constants". - */ -#define I0 0x67452301 /* Initial values for MD buffer */ -#define I1 0xefcdab89 -#define I2 0x98badcfe -#define I3 0x10325476 -#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */ -#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */ - /* C2 and C3 are from Knuth, The Art of Programming, Volume 2 - ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley. - ** Table 2, page 660. - */ - -#define fs1 3 /* round 1 shift amounts */ -#define fs2 7 -#define fs3 11 -#define fs4 19 -#define gs1 3 /* round 2 shift amounts */ -#define gs2 5 -#define gs3 9 -#define gs4 13 -#define hs1 3 /* round 3 shift amounts */ -#define hs2 9 -#define hs3 11 -#define hs4 15 - - /* Compile-time macro declarations for MD4. - ** Note: The "rot" operator uses the variable "tmp". - ** It assumes tmp is declared as unsigned int, so that the >> - ** operator will shift in zeros rather than extending the sign bit. - */ -#define f(X,Y,Z) ((X&Y) | ((~X)&Z)) -#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z)) -#define h(X,Y,Z) (X^Y^Z) -#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S))) -#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s) -#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s) -#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s) - - /* MDprint(MDp) - ** Print message digest buffer MDp as 32 hexadecimal digits. - ** Order is from low-order byte of buffer[0] to high-order byte of - ** buffer[3]. - ** Each byte is printed with high-order hexadecimal digit first. - ** This is a user-callable routine. - */ - void - MDprint(MDp) - MDptr MDp; - { int i,j; - for (i=0;i<4;i++) - for (j=0;j<32;j=j+8) - printf("%02x",(MDp->buffer[i]>>j) & 0xFF); - } - - /* MDbegin(MDp) - ** Initialize message digest buffer MDp. - ** This is a user-callable routine. - */ - void - MDbegin(MDp) - MDptr MDp; - { int i; - MDp->buffer[0] = I0; - MDp->buffer[1] = I1; - MDp->buffer[2] = I2; - MDp->buffer[3] = I3; - for (i=0;i<8;i++) MDp->count[i] = 0; - MDp->done = 0; - } - - /* MDreverse(X) - ** Reverse the byte-ordering of every int in X. - ** Assumes X is an array of 16 ints. - ** The macro revx reverses the byte-ordering of the next word of X. - */ - void MDreverse(X) - unsigned int *X; - { register unsigned int t; - register unsigned int i; - - for(i = 0; i < 16; i++) { - t = X[i]; - SIVAL(X,i*4,t); - } - } - - /* MDblock(MDp,X) - ** Update message digest buffer MDp->buffer using 16-word data block X. - ** Assumes all 16 words of X are full of data. - ** Does not update MDp->count. - ** This routine is not user-callable. - */ - static void - MDblock(MDp,X) - MDptr MDp; - unsigned int *X; - { - register unsigned int tmp, A, B, C, D; - MDreverse(X); - A = MDp->buffer[0]; - B = MDp->buffer[1]; - C = MDp->buffer[2]; - D = MDp->buffer[3]; - /* Update the message digest buffer */ - ff(A , B , C , D , 0 , fs1); /* Round 1 */ - ff(D , A , B , C , 1 , fs2); - ff(C , D , A , B , 2 , fs3); - ff(B , C , D , A , 3 , fs4); - ff(A , B , C , D , 4 , fs1); - ff(D , A , B , C , 5 , fs2); - ff(C , D , A , B , 6 , fs3); - ff(B , C , D , A , 7 , fs4); - ff(A , B , C , D , 8 , fs1); - ff(D , A , B , C , 9 , fs2); - ff(C , D , A , B , 10 , fs3); - ff(B , C , D , A , 11 , fs4); - ff(A , B , C , D , 12 , fs1); - ff(D , A , B , C , 13 , fs2); - ff(C , D , A , B , 14 , fs3); - ff(B , C , D , A , 15 , fs4); - gg(A , B , C , D , 0 , gs1); /* Round 2 */ - gg(D , A , B , C , 4 , gs2); - gg(C , D , A , B , 8 , gs3); - gg(B , C , D , A , 12 , gs4); - gg(A , B , C , D , 1 , gs1); - gg(D , A , B , C , 5 , gs2); - gg(C , D , A , B , 9 , gs3); - gg(B , C , D , A , 13 , gs4); - gg(A , B , C , D , 2 , gs1); - gg(D , A , B , C , 6 , gs2); - gg(C , D , A , B , 10 , gs3); - gg(B , C , D , A , 14 , gs4); - gg(A , B , C , D , 3 , gs1); - gg(D , A , B , C , 7 , gs2); - gg(C , D , A , B , 11 , gs3); - gg(B , C , D , A , 15 , gs4); - hh(A , B , C , D , 0 , hs1); /* Round 3 */ - hh(D , A , B , C , 8 , hs2); - hh(C , D , A , B , 4 , hs3); - hh(B , C , D , A , 12 , hs4); - hh(A , B , C , D , 2 , hs1); - hh(D , A , B , C , 10 , hs2); - hh(C , D , A , B , 6 , hs3); - hh(B , C , D , A , 14 , hs4); - hh(A , B , C , D , 1 , hs1); - hh(D , A , B , C , 9 , hs2); - hh(C , D , A , B , 5 , hs3); - hh(B , C , D , A , 13 , hs4); - hh(A , B , C , D , 3 , hs1); - hh(D , A , B , C , 11 , hs2); - hh(C , D , A , B , 7 , hs3); - hh(B , C , D , A , 15 , hs4); - MDp->buffer[0] += A; - MDp->buffer[1] += B; - MDp->buffer[2] += C; - MDp->buffer[3] += D; - } - - /* MDupdate(MDp,X,count) - ** Input: MDp -- an MDptr - ** X -- a pointer to an array of unsigned characters. - ** count -- the number of bits of X to use. - ** (if not a multiple of 8, uses high bits of last byte.) - ** Update MDp using the number of bits of X given by count. - ** This is the basic input routine for an MD4 user. - ** The routine completes the MD computation when count < 512, so - ** every MD computation should end with one call to MDupdate with a - ** count less than 512. A call with count 0 will be ignored if the - ** MD has already been terminated (done != 0), so an extra call with - ** count 0 can be given as a "courtesy close" to force termination - ** if desired. - */ - void - MDupdate(MDp,X,count) - MDptr MDp; - unsigned char *X; - unsigned int count; - { unsigned int i, tmp, bit, byte, mask; - unsigned char XX[64]; - unsigned char *p; - /* return with no error if this is a courtesy close with count - ** zero and MDp->done is true. - */ - if (count == 0 && MDp->done) return; - /* check to see if MD is already done and report error */ - if (MDp->done) - { printf("\nError: MDupdate MD already done."); return; } - /* Add count to MDp->count */ - tmp = count; - p = MDp->count; - while (tmp) - { tmp += *p; - *p++ = tmp; - tmp = tmp >> 8; - } - /* Process data */ - if (count == 512) - { /* Full block of data to handle */ - MDblock(MDp,(unsigned int *)X); - } - else if (count > 512) /* Check for count too large */ - { printf("\nError: MDupdate called with illegal count value %d." - ,count); - return; - } - else /* partial block -- must be last block so finish up */ - { /* Find out how many bytes and residual bits there are */ - byte = count >> 3; - bit = count & 7; - /* Copy X into XX since we need to modify it */ - for (i=0;i<=byte;i++) XX[i] = X[i]; - for (i=byte+1;i<64;i++) XX[i] = 0; - /* Add padding '1' bit and low-order zeros in last byte */ - mask = 1 << (7 - bit); - XX[byte] = (XX[byte] | mask) & ~( mask - 1); - /* If room for bit count, finish up with this block */ - if (byte <= 55) - { for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; - MDblock(MDp,(unsigned int *)XX); - } - else /* need to do two blocks to finish up */ - { MDblock(MDp,(unsigned int *)XX); - for (i=0;i<56;i++) XX[i] = 0; - for (i=0;i<8;i++) XX[56+i] = MDp->count[i]; - MDblock(MDp,(unsigned int *)XX); - } - /* Set flag saying we're done with MD computation */ - MDp->done = 1; - } - } - - /* - ** End of md4.c - */ -#else - void md4_dummy() {;} -#endif diff --git a/source/lib/replace.c b/source/lib/replace.c deleted file mode 100644 index 67c18a15237..00000000000 --- a/source/lib/replace.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - replacement routines for broken systems - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - - - void replace_dummy(void) -{} - -#ifdef REPLACE_STRLEN -/**************************************************************************** -a replacement strlen() that returns int for solaris -****************************************************************************/ - int Strlen(char *s) -{ - int ret=0; - if (!s) return(0); - while (*s++) ret++; - return(ret); -} -#endif - -#ifdef NO_FTRUNCATE - /******************************************************************* -ftruncate for operating systems that don't have it -********************************************************************/ - int ftruncate(int f,long l) -{ - struct flock fl; - - fl.l_whence = 0; - fl.l_len = 0; - fl.l_start = l; - fl.l_type = F_WRLCK; - return fcntl(f, F_FREESP, &fl); -} -#endif - - -#ifdef REPLACE_STRSTR -/**************************************************************************** -Mips version of strstr doesn't seem to work correctly. -There is a #define in includes.h to redirect calls to this function. -****************************************************************************/ -char *Strstr(char *s, char *p) -{ - int len = strlen(p); - - while ( *s != '\0' ) { - if ( strncmp(s, p, len) == 0 ) - return s; - s++; - } - - return NULL; -} -#endif /* REPLACE_STRSTR */ - - -#ifdef REPLACE_MKTIME -/******************************************************************* -a mktime() replacement for those who don't have it - contributed by -C.A. Lademann <cal@zls.com> -********************************************************************/ -#define MINUTE 60 -#define HOUR 60*MINUTE -#define DAY 24*HOUR -#define YEAR 365*DAY -time_t Mktime(struct tm *t) -{ - struct tm *u; - time_t epoch = 0; - int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, - y, m, i; - - if(t->tm_year < 70) - return((time_t)-1); - - epoch = (t->tm_year - 70) * YEAR + - (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY; - - y = t->tm_year; - m = 0; - - for(i = 0; i < t->tm_mon; i++) { - epoch += mon [m] * DAY; - if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) - epoch += DAY; - - if(++m > 11) { - m = 0; - y++; - } - } - - epoch += (t->tm_mday - 1) * DAY; - epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; - - if((u = localtime(&epoch)) != NULL) { - t->tm_sec = u->tm_sec; - t->tm_min = u->tm_min; - t->tm_hour = u->tm_hour; - t->tm_mday = u->tm_mday; - t->tm_mon = u->tm_mon; - t->tm_year = u->tm_year; - t->tm_wday = u->tm_wday; - t->tm_yday = u->tm_yday; - t->tm_isdst = u->tm_isdst; -#ifndef NO_TM_NAME - memcpy(t->tm_name, u->tm_name, LTZNMAX); -#endif - } - - return(epoch); -} -#endif /* REPLACE_MKTIME */ - - - -#ifdef REPLACE_RENAME -/* Rename a file. (from libiberty in GNU binutils) */ - int rename (zfrom, zto) - const char *zfrom; - const char *zto; -{ - if (link (zfrom, zto) < 0) - { - if (errno != EEXIST) - return -1; - if (unlink (zto) < 0 - || link (zfrom, zto) < 0) - return -1; - } - return unlink (zfrom); -} -#endif - - -#ifdef REPLACE_INNETGR -/* - * Search for a match in a netgroup. This replaces it on broken systems. - */ -int InNetGr(char *group,char *host,char *user,char *dom) -{ - char *hst, *usr, *dm; - - setnetgrent(group); - while (getnetgrent(&hst, &usr, &dm)) - if (((host == 0) || (hst == 0) || !strcmp(host, hst)) && - ((user == 0) || (usr == 0) || !strcmp(user, usr)) && - ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) { - endnetgrent(); - return (1); - } - endnetgrent(); - return (0); -} -#endif - - - -#ifdef NO_INITGROUPS -#include <sys/types.h> -#include <limits.h> -#include <grp.h> - -#ifndef NULL -#define NULL (void *)0 -#endif - -/**************************************************************************** - some systems don't have an initgroups call -****************************************************************************/ - int initgroups(char *name,gid_t id) -{ -#ifdef NO_SETGROUPS - /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ - return(0); -#else - gid_t grouplst[NGROUPS_MAX]; - int i,j; - struct group *g; - char *gr; - - grouplst[0] = id; - i = 1; - while (i < NGROUPS_MAX && - ((g = (struct group *)getgrent()) != (struct group *)NULL)) - { - if (g->gr_gid == id) - continue; - j = 0; - gr = g->gr_mem[0]; - while (gr && (*gr != (char)NULL)) { - if (strcmp(name,gr) == 0) { - grouplst[i] = g->gr_gid; - i++; - gr = (char *)NULL; - break; - } - gr = g->gr_mem[++j]; - } - } - endgrent(); - return(setgroups(i,grouplst)); -#endif -} -#endif - - -#if (defined(SecureWare) && defined(SCO)) -/* This is needed due to needing the nap() function but we don't want - to include the Xenix libraries since that will break other things... - BTW: system call # 0x0c28 is the same as calling nap() */ -long nap(long milliseconds) { - return syscall(0x0c28, milliseconds); -} -#endif - - - -#if WRAP_MALLOC - -/* undo the wrapping temporarily */ -#undef malloc -#undef realloc -#undef free - -/**************************************************************************** -wrapper for malloc() to catch memory errors -****************************************************************************/ -void *malloc_wrapped(int size,char *file,int line) -{ -#ifdef xx_old_malloc - void *res = xx_old_malloc(size); -#else - void *res = malloc(size); -#endif - DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n", - file,line, - size,(unsigned int)res)); - return(res); -} - -/**************************************************************************** -wrapper for realloc() to catch memory errors -****************************************************************************/ -void *realloc_wrapped(void *ptr,int size,char *file,int line) -{ -#ifdef xx_old_realloc - void *res = xx_old_realloc(ptr,size); -#else - void *res = realloc(ptr,size); -#endif - DEBUG(3,("Realloc\n")); - DEBUG(3,("free called from %s(%d) with ptr=0x%X\n", - file,line, - (unsigned int)ptr)); - DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n", - file,line, - size,(unsigned int)res)); - return(res); -} - -/**************************************************************************** -wrapper for free() to catch memory errors -****************************************************************************/ -void free_wrapped(void *ptr,char *file,int line) -{ -#ifdef xx_old_free - xx_old_free(ptr); -#else - free(ptr); -#endif - DEBUG(3,("free called from %s(%d) with ptr=0x%X\n", - file,line,(unsigned int)ptr)); - return; -} - -/* and re-do the define for spots lower in this file */ -#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__) -#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__) -#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__) - -#endif - - -#if WRAP_MEMCPY -#undef memcpy -/******************************************************************* -a wrapper around memcpy for diagnostic purposes -********************************************************************/ -void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line) -{ - if (l>64 && (((int)d)%4) != (((int)s)%4)) - DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line)); -#ifdef xx_old_memcpy - return(xx_old_memcpy(d,s,l)); -#else - return(memcpy(d,s,l)); -#endif -} -#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__) -#endif - diff --git a/source/lib/system.c b/source/lib/system.c deleted file mode 100644 index ea86e9ccaab..00000000000 --- a/source/lib/system.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Samba system utilities - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - -/* - The idea is that this file will eventually have wrappers around all - important system calls in samba. The aims are: - - - to enable easier porting by putting OS dependent stuff in here - - - to allow for hooks into other "pseudo-filesystems" - - - to allow easier integration of things like the japanese extensions - - - to support the philosophy of Samba to expose the features of - the OS within the SMB model. In general whatever file/printer/variable - expansions/etc make sense to the OS should be acceptable to Samba. -*/ - - -/******************************************************************* -this replaces the normal select() system call -return if some data has arrived on one of the file descriptors -return -1 means error -********************************************************************/ -#ifdef NO_SELECT -static int pollfd(int fd) -{ - int r=0; - -#ifdef HAS_RDCHK - r = rdchk(fd); -#elif defined(TCRDCHK) - (void)ioctl(fd, TCRDCHK, &r); -#else - (void)ioctl(fd, FIONREAD, &r); -#endif - - return(r); -} - -int sys_select(fd_set *fds,struct timeval *tval) -{ - fd_set fds2; - int counter=0; - int found=0; - - FD_ZERO(&fds2); - - while (1) - { - int i; - for (i=0;i<255;i++) { - if (FD_ISSET(i,fds) && pollfd(i)>0) { - found++; - FD_SET(i,&fds2); - } - } - - if (found) { - memcpy((void *)fds,(void *)&fds2,sizeof(fds2)); - return(found); - } - - if (tval && tval->tv_sec < counter) return(0); - sleep(1); - counter++; - } -} - -#else -int sys_select(fd_set *fds,struct timeval *tval) -{ - struct timeval t2; - int selrtn; - - do { - if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2)); - errno = 0; - selrtn = select(255,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL); - } while (selrtn<0 && errno == EINTR); - - return(selrtn); -} -#endif - - -/******************************************************************* -just a unlink wrapper -********************************************************************/ -int sys_unlink(char *fname) -{ - return(unlink(dos_to_unix(fname,False))); -} - - -/******************************************************************* -a simple open() wrapper -********************************************************************/ -int sys_open(char *fname,int flags,int mode) -{ - return(open(dos_to_unix(fname,False),flags,mode)); -} - - -/******************************************************************* -a simple opendir() wrapper -********************************************************************/ -DIR *sys_opendir(char *dname) -{ - return(opendir(dos_to_unix(dname,False))); -} - - -/******************************************************************* -and a stat() wrapper -********************************************************************/ -int sys_stat(char *fname,struct stat *sbuf) -{ - return(stat(dos_to_unix(fname,False),sbuf)); -} - -/******************************************************************* -The wait() calls vary between systems -********************************************************************/ -int sys_waitpid(pid_t pid,int *status,int options) -{ -#ifdef USE_WAITPID - return waitpid(pid,status,options); -#else /* USE_WAITPID */ - return wait4(pid, status, options, NULL); -#endif /* USE_WAITPID */ -} - -/******************************************************************* -don't forget lstat() -********************************************************************/ -int sys_lstat(char *fname,struct stat *sbuf) -{ - return(lstat(dos_to_unix(fname,False),sbuf)); -} - - -/******************************************************************* -mkdir() gets a wrapper -********************************************************************/ -int sys_mkdir(char *dname,int mode) -{ - return(mkdir(dos_to_unix(dname,False),mode)); -} - - -/******************************************************************* -do does rmdir() -********************************************************************/ -int sys_rmdir(char *dname) -{ - return(rmdir(dos_to_unix(dname,False))); -} - - -/******************************************************************* -I almost forgot chdir() -********************************************************************/ -int sys_chdir(char *dname) -{ - return(chdir(dos_to_unix(dname,False))); -} - - -/******************************************************************* -now for utime() -********************************************************************/ -int sys_utime(char *fname,struct utimbuf *times) -{ - return(utime(dos_to_unix(fname,False),times)); -} - -/********************************************************* -for rename across filesystems Patch from Warren Birnbaum -<warrenb@hpcvscdp.cv.hp.com> -**********************************************************/ - -static int -copy_reg (const char *source, const char *dest) -{ - struct stat source_stats; - int ifd; - int full_write(); - int safe_read(); - int ofd; - char *buf; - int len; /* Number of bytes read into `buf'. */ - - lstat (source, &source_stats); - if (!S_ISREG (source_stats.st_mode)) - { - return 1; - } - - if (unlink (dest) && errno != ENOENT) - { - return 1; - } - - if((ifd = open (source, O_RDONLY, 0)) < 0) - { - return 1; - } - if((ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) - { - close (ifd); - return 1; - } - - if((buf = malloc( COPYBUF_SIZE )) == NULL) - { - close (ifd); - close (ofd); - unlink (dest); - return 1; - } - - while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0) - { - if (write_data(ofd, buf, len) < 0) - { - close (ifd); - close (ofd); - unlink (dest); - free(buf); - return 1; - } - } - free(buf); - if (len < 0) - { - close (ifd); - close (ofd); - unlink (dest); - return 1; - } - - if (close (ifd) < 0) - { - close (ofd); - return 1; - } - if (close (ofd) < 0) - { - return 1; - } - - /* chown turns off set[ug]id bits for non-root, - so do the chmod last. */ - - /* Try to copy the old file's modtime and access time. */ - { - struct utimbuf tv; - - tv.actime = source_stats.st_atime; - tv.modtime = source_stats.st_mtime; - if (utime (dest, &tv)) - { - return 1; - } - } - - /* Try to preserve ownership. For non-root it might fail, but that's ok. - But root probably wants to know, e.g. if NFS disallows it. */ - if (chown (dest, source_stats.st_uid, source_stats.st_gid) - && (errno != EPERM)) - { - return 1; - } - - if (chmod (dest, source_stats.st_mode & 07777)) - { - return 1; - } - unlink (source); - return 0; -} - -/******************************************************************* -for rename() -********************************************************************/ -int sys_rename(char *from, char *to) -{ - int rcode; - pstring zfrom, zto; - - strcpy (zfrom, dos_to_unix (from, False)); - strcpy (zto, dos_to_unix (to, False)); - rcode = rename (zfrom, zto); - - if (errno == EXDEV) - { - /* Rename across filesystems needed. */ - rcode = copy_reg (zfrom, zto); - } - return rcode; -} - -/******************************************************************* -for chmod -********************************************************************/ -int sys_chmod(char *fname,int mode) -{ - return(chmod(dos_to_unix(fname,False),mode)); -} - -/******************************************************************* -chown isn't used much but OS/2 doesn't have it -********************************************************************/ -int sys_chown(char *fname,int uid,int gid) -{ -#ifdef NO_CHOWN - DEBUG(1,("Warning - chown(%s,%d,%d) not done\n",fname,uid,gid)); -#else - return(chown(fname,uid,gid)); -#endif -} - -/******************************************************************* -os/2 also doesn't have chroot -********************************************************************/ -int sys_chroot(char *dname) -{ -#ifdef NO_CHROOT - DEBUG(1,("Warning - chroot(%s) not done\n",dname)); -#else - return(chroot(dname)); -#endif -} - -/************************************************************************** -A wrapper for gethostbyname() that tries avoids looking up hostnames -in the root domain, which can cause dial-on-demand links to come up for no -apparent reason. -****************************************************************************/ -struct hostent *sys_gethostbyname(char *name) -{ - char query[256], hostname[256]; - char *domain; - - /* Does this name have any dots in it? If so, make no change */ - - if (strchr(name, '.')) - return(gethostbyname(name)); - - /* Get my hostname, which should have domain name - attached. If not, just do the gethostname on the - original string. - */ - - gethostname(hostname, sizeof(hostname) - 1); - hostname[sizeof(hostname) - 1] = 0; - if ((domain = strchr(hostname, '.')) == NULL) - return(gethostbyname(name)); - - /* Attach domain name to query and do modified query. - If names too large, just do gethostname on the - original string. - */ - - if((strlen(name) + strlen(domain)) >= sizeof(query)) - return(gethostbyname(name)); - - sprintf(query, "%s%s", name, domain); - return(gethostbyname(query)); -} - diff --git a/source/lib/time.c b/source/lib/time.c deleted file mode 100644 index d16552b61e2..00000000000 --- a/source/lib/time.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - time handling functions - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -/* - This stuff was largely rewritten by Paul Eggert <eggert@twinsun.com> - in May 1996 - */ - - -int serverzone=0; -int extra_time_offset = 0; - -extern int DEBUGLEVEL; - -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif - -#ifndef TIME_T_MIN -#define TIME_T_MIN ((time_t)0 < (time_t) -1 ? (time_t) 0 \ - : ~ (time_t) 0 << (sizeof (time_t) * CHAR_BIT - 1)) -#endif -#ifndef TIME_T_MAX -#define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN) -#endif - - - -/******************************************************************* -a gettimeofday wrapper -********************************************************************/ -void GetTimeOfDay(struct timeval *tval) -{ -#ifdef GETTIMEOFDAY1 - gettimeofday(tval); -#else - gettimeofday(tval,NULL); -#endif -} - -#define TM_YEAR_BASE 1900 - -/******************************************************************* -yield the difference between *A and *B, in seconds, ignoring leap seconds -********************************************************************/ -static int tm_diff(struct tm *a, struct tm *b) -{ - int ay = a->tm_year + (TM_YEAR_BASE - 1); - int by = b->tm_year + (TM_YEAR_BASE - 1); - int intervening_leap_days = - (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400); - int years = ay - by; - int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday); - int hours = 24*days + (a->tm_hour - b->tm_hour); - int minutes = 60*hours + (a->tm_min - b->tm_min); - int seconds = 60*minutes + (a->tm_sec - b->tm_sec); - return seconds; -} - -/******************************************************************* - return the UTC offset in seconds west of UTC - ******************************************************************/ -static int TimeZone(time_t t) -{ - struct tm tm_utc = *(gmtime(&t)); - return tm_diff(&tm_utc,localtime(&t)); -} - - -/******************************************************************* -init the time differences -********************************************************************/ -void TimeInit(void) -{ - serverzone = TimeZone(time(NULL)); - DEBUG(4,("Serverzone is %d\n",serverzone)); -} - - -/******************************************************************* -return the same value as TimeZone, but it should be more efficient. - -We keep a table of DST offsets to prevent calling localtime() on each -call of this function. This saves a LOT of time on many unixes. - -Updated by Paul Eggert <eggert@twinsun.com> -********************************************************************/ -static int TimeZoneFaster(time_t t) -{ - static struct dst_table {time_t start,end; int zone;} *dst_table = NULL; - static int table_size = 0; - int i; - int zone = 0; - - if (t == 0) t = time(NULL); - - /* Tunis has a 8 day DST region, we need to be careful ... */ -#define MAX_DST_WIDTH (365*24*60*60) -#define MAX_DST_SKIP (7*24*60*60) - - for (i=0;i<table_size;i++) - if (t >= dst_table[i].start && t <= dst_table[i].end) break; - - if (i<table_size) { - zone = dst_table[i].zone; - } else { - time_t low,high; - - zone = TimeZone(t); - dst_table = (struct dst_table *)Realloc(dst_table, - sizeof(dst_table[0])*(i+1)); - if (!dst_table) { - table_size = 0; - } else { - table_size++; - - dst_table[i].zone = zone; - dst_table[i].start = dst_table[i].end = t; - - /* no entry will cover more than 6 months */ - low = t - MAX_DST_WIDTH/2; - if (t < low) - low = TIME_T_MIN; - - high = t + MAX_DST_WIDTH/2; - if (high < t) - high = TIME_T_MAX; - - /* widen the new entry using two bisection searches */ - while (low+60*60 < dst_table[i].start) { - if (dst_table[i].start - low > MAX_DST_SKIP*2) - t = dst_table[i].start - MAX_DST_SKIP; - else - t = low + (dst_table[i].start-low)/2; - if (TimeZone(t) == zone) - dst_table[i].start = t; - else - low = t; - } - - while (high-60*60 > dst_table[i].end) { - if (high - dst_table[i].end > MAX_DST_SKIP*2) - t = dst_table[i].end + MAX_DST_SKIP; - else - t = high - (high-dst_table[i].end)/2; - if (TimeZone(t) == zone) - dst_table[i].end = t; - else - high = t; - } -#if 0 - DEBUG(1,("Added DST entry from %s ", - asctime(localtime(&dst_table[i].start)))); - DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)), - dst_table[i].zone)); -#endif - } - } - return zone; -} - -/**************************************************************************** - return the UTC offset in seconds west of UTC, adjusted for extra time offset - **************************************************************************/ -int TimeDiff(time_t t) -{ - return TimeZoneFaster(t) + 60*extra_time_offset; -} - - -/**************************************************************************** - return the UTC offset in seconds west of UTC, adjusted for extra time - offset, for a local time value. If ut = lt + LocTimeDiff(lt), then - lt = ut - TimeDiff(ut), but the converse does not necessarily hold near - daylight savings transitions because some local times are ambiguous. - LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions. - +**************************************************************************/ -static int LocTimeDiff(time_t lte) -{ - time_t lt = lte - 60*extra_time_offset; - int d = TimeZoneFaster(lt); - time_t t = lt + d; - - /* if overflow occurred, ignore all the adjustments so far */ - if (((lte < lt) ^ (extra_time_offset < 0)) | ((t < lt) ^ (d < 0))) - t = lte; - - /* now t should be close enough to the true UTC to yield the right answer */ - return TimeDiff(t); -} - - -/**************************************************************************** -try to optimise the localtime call, it can be quite expenive on some machines -****************************************************************************/ -struct tm *LocalTime(time_t *t) -{ - time_t t2 = *t; - - t2 -= TimeDiff(t2); - - return(gmtime(&t2)); -} - - -#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60)) - -/**************************************************************************** -interpret an 8 byte "filetime" structure to a time_t -It's originally in "100ns units since jan 1st 1601" - -It appears to be kludge-GMT (at least for file listings). This means -its the GMT you get by taking a localtime and adding the -serverzone. This is NOT the same as GMT in some cases. This routine -converts this to real GMT. -****************************************************************************/ -time_t interpret_long_date(char *p) -{ - double d; - time_t ret; - uint32 tlow,thigh; - tlow = IVAL(p,0); - thigh = IVAL(p,4); - - if (thigh == 0) return(0); - - d = ((double)thigh)*4.0*(double)(1<<30); - d += (tlow&0xFFF00000); - d *= 1.0e-7; - - /* now adjust by 369 years to make the secs since 1970 */ - d -= TIME_FIXUP_CONSTANT; - - if (!(TIME_T_MIN <= d && d <= TIME_T_MAX)) - return(0); - - ret = (time_t)(d+0.5); - - /* this takes us from kludge-GMT to real GMT */ - ret -= serverzone; - ret += LocTimeDiff(ret); - - return(ret); -} - - -/**************************************************************************** -put a 8 byte filetime from a time_t -This takes real GMT as input and converts to kludge-GMT -****************************************************************************/ -void put_long_date(char *p,time_t t) -{ - uint32 tlow,thigh; - double d; - - if (t==0) { - SIVAL(p,0,0); SIVAL(p,4,0); - return; - } - - /* this converts GMT to kludge-GMT */ - t -= TimeDiff(t) - serverzone; - - d = (double) (t); - - d += TIME_FIXUP_CONSTANT; - - d *= 1.0e7; - - thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30)))); - tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30)); - - SIVAL(p,0,tlow); - SIVAL(p,4,thigh); -} - - -/**************************************************************************** -check if it's a null mtime -****************************************************************************/ -static BOOL null_mtime(time_t mtime) -{ - if (mtime == 0 || mtime == 0xFFFFFFFF || mtime == (time_t)-1) - return(True); - return(False); -} - -/******************************************************************* - create a 16 bit dos packed date -********************************************************************/ -static uint16 make_dos_date1(time_t unixdate,struct tm *t) -{ - uint16 ret=0; - ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1); - ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5)); - return(ret); -} - -/******************************************************************* - create a 16 bit dos packed time -********************************************************************/ -static uint16 make_dos_time1(time_t unixdate,struct tm *t) -{ - uint16 ret=0; - ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3)); - ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5)); - return(ret); -} - -/******************************************************************* - create a 32 bit dos packed date/time from some parameters - This takes a GMT time and returns a packed localtime structure -********************************************************************/ -static uint32 make_dos_date(time_t unixdate) -{ - struct tm *t; - uint32 ret=0; - - t = LocalTime(&unixdate); - - ret = make_dos_date1(unixdate,t); - ret = ((ret&0xFFFF)<<16) | make_dos_time1(unixdate,t); - - return(ret); -} - -/******************************************************************* -put a dos date into a buffer (time/date format) -This takes GMT time and puts local time in the buffer -********************************************************************/ -void put_dos_date(char *buf,int offset,time_t unixdate) -{ - uint32 x = make_dos_date(unixdate); - SIVAL(buf,offset,x); -} - -/******************************************************************* -put a dos date into a buffer (date/time format) -This takes GMT time and puts local time in the buffer -********************************************************************/ -void put_dos_date2(char *buf,int offset,time_t unixdate) -{ - uint32 x = make_dos_date(unixdate); - x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); - SIVAL(buf,offset,x); -} - -/******************************************************************* -put a dos 32 bit "unix like" date into a buffer. This routine takes -GMT and converts it to LOCAL time before putting it (most SMBs assume -localtime for this sort of date) -********************************************************************/ -void put_dos_date3(char *buf,int offset,time_t unixdate) -{ - if (!null_mtime(unixdate)) - unixdate -= TimeDiff(unixdate); - SIVAL(buf,offset,unixdate); -} - -/******************************************************************* - interpret a 32 bit dos packed date/time to some parameters -********************************************************************/ -static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second) -{ - uint32 p0,p1,p2,p3; - - p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; - p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF; - - *second = 2*(p0 & 0x1F); - *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3); - *hour = (p1>>3)&0xFF; - *day = (p2&0x1F); - *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1; - *year = ((p3>>1)&0xFF) + 80; -} - -/******************************************************************* - create a unix date (int GMT) from a dos date (which is actually in - localtime) -********************************************************************/ -time_t make_unix_date(void *date_ptr) -{ - uint32 dos_date=0; - struct tm t; - time_t ret; - - dos_date = IVAL(date_ptr,0); - - if (dos_date == 0) return(0); - - interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon, - &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec); - t.tm_isdst = -1; - - /* mktime() also does the local to GMT time conversion for us */ - ret = mktime(&t); - - return(ret); -} - -/******************************************************************* -like make_unix_date() but the words are reversed -********************************************************************/ -time_t make_unix_date2(void *date_ptr) -{ - uint32 x,x2; - - x = IVAL(date_ptr,0); - x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16); - SIVAL(&x,0,x2); - - return(make_unix_date((void *)&x)); -} - -/******************************************************************* - create a unix GMT date from a dos date in 32 bit "unix like" format - these generally arrive as localtimes, with corresponding DST - ******************************************************************/ -time_t make_unix_date3(void *date_ptr) -{ - time_t t = IVAL(date_ptr,0); - if (!null_mtime(t)) - t += LocTimeDiff(t); - return(t); -} - -/**************************************************************************** -set the time on a file -****************************************************************************/ -BOOL set_filetime(char *fname,time_t mtime) -{ - struct utimbuf times; - - if (null_mtime(mtime)) return(True); - - times.modtime = times.actime = mtime; - - if (sys_utime(fname,×)) { - DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno))); - } - - return(True); -} - - -/**************************************************************************** - return the date and time as a string -****************************************************************************/ -char *timestring(void ) -{ - static char TimeBuf[100]; - time_t t = time(NULL); - struct tm *tm = LocalTime(&t); - -#ifdef NO_STRFTIME - strcpy(TimeBuf, asctime(tm)); -#elif defined(CLIX) || defined(CONVEX) - strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",tm); -#elif defined(AMPM) - strftime(TimeBuf,100,"%D %r",tm); -#elif defined(TZ_TIME) - { - int zone = TimeDiff(t); - int absZoneMinutes = (zone<0 ? -zone : zone) / 60; - size_t len = strftime(TimeBuf,sizeof(TimeBuf)-6,"%D %T",tm); - sprintf(TimeBuf+len," %c%02d%02d", - zone<0?'+':'-',absZoneMinutes/60,absZoneMinutes%60); - } -#else - strftime(TimeBuf,100,"%D %T",tm); -#endif - return(TimeBuf); -} - diff --git a/source/lib/ufc.c b/source/lib/ufc.c deleted file mode 100644 index 67b0c6920a4..00000000000 --- a/source/lib/ufc.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - This bit of code was derived from the UFC-crypt package which - carries the following copyright - - Modified for use by Samba by Andrew Tridgell, October 1994 - - Note that this routine is only faster on some machines. Under Linux 1.1.51 - libc 4.5.26 I actually found this routine to be slightly slower. - - Under SunOS I found a huge speedup by using these routines - (a factor of 20 or so) - - Warning: I've had a report from Steve Kennedy <steve@gbnet.org> - that this crypt routine may sometimes get the wrong answer. Only - use UFC_CRYT if you really need it. - -*/ - -#ifdef UFC_CRYPT - -/* - * UFC-crypt: ultra fast crypt(3) implementation - * - * Copyright (C) 1991, 1992, Free Software Foundation, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * @(#)crypt_util.c 2.31 02/08/92 - * - * Support routines - * - */ -#include "includes.h" - - -#ifndef long32 -#define long32 int32 -#endif - -#ifndef long64 -#define long64 int64 -#endif - -#ifndef ufc_long -#define ufc_long unsigned -#endif - -#ifndef _UFC_64_ -#define _UFC_32_ -#endif - -/* - * Permutation done once on the 56 bit - * key derived from the original 8 byte ASCII key. - */ -static int pc1[56] = { - 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, - 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 -}; - -/* - * How much to rotate each 28 bit half of the pc1 permutated - * 56 bit key before using pc2 to give the i' key - */ -static int rots[16] = { - 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 -}; - -/* - * Permutation giving the key - * of the i' DES round - */ -static int pc2[48] = { - 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 -}; - -/* - * The E expansion table which selects - * bits from the 32 bit intermediate result. - */ -static int esel[48] = { - 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 -}; -static int e_inverse[64]; - -/* - * Permutation done on the - * result of sbox lookups - */ -static int perm32[32] = { - 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, - 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 -}; - -/* - * The sboxes - */ -static int sbox[8][4][16]= { - { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, - { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, - { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, - { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } - }, - - { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, - { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, - { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, - { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } - }, - - { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, - { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, - { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, - { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } - }, - - { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, - { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, - { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, - { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } - }, - - { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, - { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, - { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, - { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } - }, - - { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, - { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 }, - { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 }, - { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } - }, - - { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, - { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 }, - { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 }, - { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } - }, - - { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, - { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 }, - { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 }, - { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } - } -}; - -/* - * This is the final - * permutation matrix - */ -static int final_perm[64] = { - 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 -}; - -/* - * The 16 DES keys in BITMASK format - */ -#ifdef _UFC_32_ -long32 _ufc_keytab[16][2]; -#endif - -#ifdef _UFC_64_ -long64 _ufc_keytab[16]; -#endif - - -#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') -#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') - -/* Macro to set a bit (0..23) */ -#define BITMASK(i) ( (1<<(11-(i)%12+3)) << ((i)<12?16:0) ) - -/* - * sb arrays: - * - * Workhorses of the inner loop of the DES implementation. - * They do sbox lookup, shifting of this value, 32 bit - * permutation and E permutation for the next round. - * - * Kept in 'BITMASK' format. - */ - -#ifdef _UFC_32_ -long32 _ufc_sb0[8192], _ufc_sb1[8192], _ufc_sb2[8192], _ufc_sb3[8192]; -static long32 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3}; -#endif - -#ifdef _UFC_64_ -long64 _ufc_sb0[4096], _ufc_sb1[4096], _ufc_sb2[4096], _ufc_sb3[4096]; -static long64 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3}; -#endif - -/* - * eperm32tab: do 32 bit permutation and E selection - * - * The first index is the byte number in the 32 bit value to be permuted - * - second - is the value of this byte - * - third - selects the two 32 bit values - * - * The table is used and generated internally in init_des to speed it up - */ -static ufc_long eperm32tab[4][256][2]; - -/* - * do_pc1: permform pc1 permutation in the key schedule generation. - * - * The first index is the byte number in the 8 byte ASCII key - * - second - - the two 28 bits halfs of the result - * - third - selects the 7 bits actually used of each byte - * - * The result is kept with 28 bit per 32 bit with the 4 most significant - * bits zero. - */ -static ufc_long do_pc1[8][2][128]; - -/* - * do_pc2: permform pc2 permutation in the key schedule generation. - * - * The first index is the septet number in the two 28 bit intermediate values - * - second - - - septet values - * - * Knowledge of the structure of the pc2 permutation is used. - * - * The result is kept with 28 bit per 32 bit with the 4 most significant - * bits zero. - */ -static ufc_long do_pc2[8][128]; - -/* - * efp: undo an extra e selection and do final - * permutation giving the DES result. - * - * Invoked 6 bit a time on two 48 bit values - * giving two 32 bit longs. - */ -static ufc_long efp[16][64][2]; - -static unsigned char bytemask[8] = { - 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 -}; - -static ufc_long longmask[32] = { - 0x80000000, 0x40000000, 0x20000000, 0x10000000, - 0x08000000, 0x04000000, 0x02000000, 0x01000000, - 0x00800000, 0x00400000, 0x00200000, 0x00100000, - 0x00080000, 0x00040000, 0x00020000, 0x00010000, - 0x00008000, 0x00004000, 0x00002000, 0x00001000, - 0x00000800, 0x00000400, 0x00000200, 0x00000100, - 0x00000080, 0x00000040, 0x00000020, 0x00000010, - 0x00000008, 0x00000004, 0x00000002, 0x00000001 -}; - - -/* - * Silly rewrite of 'bzero'. I do so - * because some machines don't have - * bzero and some don't have memset. - */ - -static void clearmem(start, cnt) - char *start; - int cnt; - { while(cnt--) - *start++ = '\0'; - } - -static int initialized = 0; - -/* lookup a 6 bit value in sbox */ - -#define s_lookup(i,s) sbox[(i)][(((s)>>4) & 0x2)|((s) & 0x1)][((s)>>1) & 0xf]; - -/* - * Initialize unit - may be invoked directly - * by fcrypt users. - */ - -static void ufc_init_des() - { int comes_from_bit; - int bit, sg; - ufc_long j; - ufc_long mask1, mask2; - - /* - * Create the do_pc1 table used - * to affect pc1 permutation - * when generating keys - */ - for(bit = 0; bit < 56; bit++) { - comes_from_bit = pc1[bit] - 1; - mask1 = bytemask[comes_from_bit % 8 + 1]; - mask2 = longmask[bit % 28 + 4]; - for(j = 0; j < 128; j++) { - if(j & mask1) - do_pc1[comes_from_bit / 8][bit / 28][j] |= mask2; - } - } - - /* - * Create the do_pc2 table used - * to affect pc2 permutation when - * generating keys - */ - for(bit = 0; bit < 48; bit++) { - comes_from_bit = pc2[bit] - 1; - mask1 = bytemask[comes_from_bit % 7 + 1]; - mask2 = BITMASK(bit % 24); - for(j = 0; j < 128; j++) { - if(j & mask1) - do_pc2[comes_from_bit / 7][j] |= mask2; - } - } - - /* - * Now generate the table used to do combined - * 32 bit permutation and e expansion - * - * We use it because we have to permute 16384 32 bit - * longs into 48 bit in order to initialize sb. - * - * Looping 48 rounds per permutation becomes - * just too slow... - * - */ - - clearmem((char*)eperm32tab, sizeof(eperm32tab)); - - for(bit = 0; bit < 48; bit++) { - ufc_long mask1,comes_from; - - comes_from = perm32[esel[bit]-1]-1; - mask1 = bytemask[comes_from % 8]; - - for(j = 256; j--;) { - if(j & mask1) - eperm32tab[comes_from / 8][j][bit / 24] |= BITMASK(bit % 24); - } - } - - /* - * Create the sb tables: - * - * For each 12 bit segment of an 48 bit intermediate - * result, the sb table precomputes the two 4 bit - * values of the sbox lookups done with the two 6 - * bit halves, shifts them to their proper place, - * sends them through perm32 and finally E expands - * them so that they are ready for the next - * DES round. - * - */ - for(sg = 0; sg < 4; sg++) { - int j1, j2; - int s1, s2; - - for(j1 = 0; j1 < 64; j1++) { - s1 = s_lookup(2 * sg, j1); - for(j2 = 0; j2 < 64; j2++) { - ufc_long to_permute, inx; - - s2 = s_lookup(2 * sg + 1, j2); - to_permute = ((s1 << 4) | s2) << (24 - 8 * sg); - -#ifdef _UFC_32_ - inx = ((j1 << 6) | j2) << 1; - sb[sg][inx ] = eperm32tab[0][(to_permute >> 24) & 0xff][0]; - sb[sg][inx+1] = eperm32tab[0][(to_permute >> 24) & 0xff][1]; - sb[sg][inx ] |= eperm32tab[1][(to_permute >> 16) & 0xff][0]; - sb[sg][inx+1] |= eperm32tab[1][(to_permute >> 16) & 0xff][1]; - sb[sg][inx ] |= eperm32tab[2][(to_permute >> 8) & 0xff][0]; - sb[sg][inx+1] |= eperm32tab[2][(to_permute >> 8) & 0xff][1]; - sb[sg][inx ] |= eperm32tab[3][(to_permute) & 0xff][0]; - sb[sg][inx+1] |= eperm32tab[3][(to_permute) & 0xff][1]; -#endif -#ifdef _UFC_64_ - inx = ((j1 << 6) | j2); - sb[sg][inx] = - ((long64)eperm32tab[0][(to_permute >> 24) & 0xff][0] << 32) | - (long64)eperm32tab[0][(to_permute >> 24) & 0xff][1]; - sb[sg][inx] |= - ((long64)eperm32tab[1][(to_permute >> 16) & 0xff][0] << 32) | - (long64)eperm32tab[1][(to_permute >> 16) & 0xff][1]; - sb[sg][inx] |= - ((long64)eperm32tab[2][(to_permute >> 8) & 0xff][0] << 32) | - (long64)eperm32tab[2][(to_permute >> 8) & 0xff][1]; - sb[sg][inx] |= - ((long64)eperm32tab[3][(to_permute) & 0xff][0] << 32) | - (long64)eperm32tab[3][(to_permute) & 0xff][1]; -#endif - } - } - } - - /* - * Create an inverse matrix for esel telling - * where to plug out bits if undoing it - */ - for(bit=48; bit--;) { - e_inverse[esel[bit] - 1 ] = bit; - e_inverse[esel[bit] - 1 + 32] = bit + 48; - } - - /* - * create efp: the matrix used to - * undo the E expansion and effect final permutation - */ - clearmem((char*)efp, sizeof efp); - for(bit = 0; bit < 64; bit++) { - int o_bit, o_long; - ufc_long word_value, mask1, mask2; - int comes_from_f_bit, comes_from_e_bit; - int comes_from_word, bit_within_word; - - /* See where bit i belongs in the two 32 bit long's */ - o_long = bit / 32; /* 0..1 */ - o_bit = bit % 32; /* 0..31 */ - - /* - * And find a bit in the e permutated value setting this bit. - * - * Note: the e selection may have selected the same bit several - * times. By the initialization of e_inverse, we only look - * for one specific instance. - */ - comes_from_f_bit = final_perm[bit] - 1; /* 0..63 */ - comes_from_e_bit = e_inverse[comes_from_f_bit]; /* 0..95 */ - comes_from_word = comes_from_e_bit / 6; /* 0..15 */ - bit_within_word = comes_from_e_bit % 6; /* 0..5 */ - - mask1 = longmask[bit_within_word + 26]; - mask2 = longmask[o_bit]; - - for(word_value = 64; word_value--;) { - if(word_value & mask1) - efp[comes_from_word][word_value][o_long] |= mask2; - } - } - initialized++; - } - -/* - * Process the elements of the sb table permuting the - * bits swapped in the expansion by the current salt. - */ - -#ifdef _UFC_32_ -static void shuffle_sb(k, saltbits) - long32 *k; - ufc_long saltbits; - { ufc_long j; - long32 x; - for(j=4096; j--;) { - x = (k[0] ^ k[1]) & (long32)saltbits; - *k++ ^= x; - *k++ ^= x; - } - } -#endif - -#ifdef _UFC_64_ -static void shuffle_sb(k, saltbits) - long64 *k; - ufc_long saltbits; - { ufc_long j; - long64 x; - for(j=4096; j--;) { - x = ((*k >> 32) ^ *k) & (long64)saltbits; - *k++ ^= (x << 32) | x; - } - } -#endif - -/* - * Setup the unit for a new salt - * Hopefully we'll not see a new salt in each crypt call. - */ - -static unsigned char current_salt[3] = "&&"; /* invalid value */ -static ufc_long current_saltbits = 0; -static int direction = 0; - -static void setup_salt(char *s1) - { ufc_long i, j, saltbits; - unsigned char *s2 = (unsigned char *)s1; - - if(!initialized) - ufc_init_des(); - - if(s2[0] == current_salt[0] && s2[1] == current_salt[1]) - return; - current_salt[0] = s2[0]; current_salt[1] = s2[1]; - - /* - * This is the only crypt change to DES: - * entries are swapped in the expansion table - * according to the bits set in the salt. - */ - saltbits = 0; - for(i = 0; i < 2; i++) { - long c=ascii_to_bin(s2[i]); - if(c < 0 || c > 63) - c = 0; - for(j = 0; j < 6; j++) { - if((c >> j) & 0x1) - saltbits |= BITMASK(6 * i + j); - } - } - - /* - * Permute the sb table values - * to reflect the changed e - * selection table - */ - shuffle_sb(_ufc_sb0, current_saltbits ^ saltbits); - shuffle_sb(_ufc_sb1, current_saltbits ^ saltbits); - shuffle_sb(_ufc_sb2, current_saltbits ^ saltbits); - shuffle_sb(_ufc_sb3, current_saltbits ^ saltbits); - - current_saltbits = saltbits; - } - -static void ufc_mk_keytab(key) - char *key; - { ufc_long v1, v2, *k1; - int i; -#ifdef _UFC_32_ - long32 v, *k2 = &_ufc_keytab[0][0]; -#endif -#ifdef _UFC_64_ - long64 v, *k2 = &_ufc_keytab[0]; -#endif - - v1 = v2 = 0; k1 = &do_pc1[0][0][0]; - for(i = 8; i--;) { - v1 |= k1[*key & 0x7f]; k1 += 128; - v2 |= k1[*key++ & 0x7f]; k1 += 128; - } - - for(i = 0; i < 16; i++) { - k1 = &do_pc2[0][0]; - - v1 = (v1 << rots[i]) | (v1 >> (28 - rots[i])); - v = k1[(v1 >> 21) & 0x7f]; k1 += 128; - v |= k1[(v1 >> 14) & 0x7f]; k1 += 128; - v |= k1[(v1 >> 7) & 0x7f]; k1 += 128; - v |= k1[(v1 ) & 0x7f]; k1 += 128; - -#ifdef _UFC_32_ - *k2++ = v; - v = 0; -#endif -#ifdef _UFC_64_ - v <<= 32; -#endif - - v2 = (v2 << rots[i]) | (v2 >> (28 - rots[i])); - v |= k1[(v2 >> 21) & 0x7f]; k1 += 128; - v |= k1[(v2 >> 14) & 0x7f]; k1 += 128; - v |= k1[(v2 >> 7) & 0x7f]; k1 += 128; - v |= k1[(v2 ) & 0x7f]; - - *k2++ = v; - } - - direction = 0; - } - -/* - * Undo an extra E selection and do final permutations - */ - -ufc_long *_ufc_dofinalperm(l1, l2, r1, r2) - ufc_long l1,l2,r1,r2; - { ufc_long v1, v2, x; - static ufc_long ary[2]; - - x = (l1 ^ l2) & current_saltbits; l1 ^= x; l2 ^= x; - x = (r1 ^ r2) & current_saltbits; r1 ^= x; r2 ^= x; - - v1=v2=0; l1 >>= 3; l2 >>= 3; r1 >>= 3; r2 >>= 3; - - v1 |= efp[15][ r2 & 0x3f][0]; v2 |= efp[15][ r2 & 0x3f][1]; - v1 |= efp[14][(r2 >>= 6) & 0x3f][0]; v2 |= efp[14][ r2 & 0x3f][1]; - v1 |= efp[13][(r2 >>= 10) & 0x3f][0]; v2 |= efp[13][ r2 & 0x3f][1]; - v1 |= efp[12][(r2 >>= 6) & 0x3f][0]; v2 |= efp[12][ r2 & 0x3f][1]; - - v1 |= efp[11][ r1 & 0x3f][0]; v2 |= efp[11][ r1 & 0x3f][1]; - v1 |= efp[10][(r1 >>= 6) & 0x3f][0]; v2 |= efp[10][ r1 & 0x3f][1]; - v1 |= efp[ 9][(r1 >>= 10) & 0x3f][0]; v2 |= efp[ 9][ r1 & 0x3f][1]; - v1 |= efp[ 8][(r1 >>= 6) & 0x3f][0]; v2 |= efp[ 8][ r1 & 0x3f][1]; - - v1 |= efp[ 7][ l2 & 0x3f][0]; v2 |= efp[ 7][ l2 & 0x3f][1]; - v1 |= efp[ 6][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 6][ l2 & 0x3f][1]; - v1 |= efp[ 5][(l2 >>= 10) & 0x3f][0]; v2 |= efp[ 5][ l2 & 0x3f][1]; - v1 |= efp[ 4][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 4][ l2 & 0x3f][1]; - - v1 |= efp[ 3][ l1 & 0x3f][0]; v2 |= efp[ 3][ l1 & 0x3f][1]; - v1 |= efp[ 2][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 2][ l1 & 0x3f][1]; - v1 |= efp[ 1][(l1 >>= 10) & 0x3f][0]; v2 |= efp[ 1][ l1 & 0x3f][1]; - v1 |= efp[ 0][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 0][ l1 & 0x3f][1]; - - ary[0] = v1; ary[1] = v2; - return ary; - } - -/* - * crypt only: convert from 64 bit to 11 bit ASCII - * prefixing with the salt - */ - -static char *output_conversion(v1, v2, salt) - ufc_long v1, v2; - char *salt; - { static char outbuf[14]; - int i, s; - - outbuf[0] = salt[0]; - outbuf[1] = salt[1] ? salt[1] : salt[0]; - - for(i = 0; i < 5; i++) - outbuf[i + 2] = bin_to_ascii((v1 >> (26 - 6 * i)) & 0x3f); - - s = (v2 & 0xf) << 2; - v2 = (v2 >> 2) | ((v1 & 0x3) << 30); - - for(i = 5; i < 10; i++) - outbuf[i + 2] = bin_to_ascii((v2 >> (56 - 6 * i)) & 0x3f); - - outbuf[12] = bin_to_ascii(s); - outbuf[13] = 0; - - return outbuf; - } - -/* - * UNIX crypt function - */ - -ufc_long *_ufc_doit(ufc_long , ufc_long, ufc_long, ufc_long, ufc_long); - -char *ufc_crypt(char *key,char *salt) - { ufc_long *s; - char ktab[9]; - - /* - * Hack DES tables according to salt - */ - setup_salt(salt); - - /* - * Setup key schedule - */ - clearmem(ktab, sizeof ktab); - StrnCpy(ktab, key, 8); - ufc_mk_keytab(ktab); - - /* - * Go for the 25 DES encryptions - */ - s = _ufc_doit((ufc_long)0, (ufc_long)0, - (ufc_long)0, (ufc_long)0, (ufc_long)25); - - /* - * And convert back to 6 bit ASCII - */ - return output_conversion(s[0], s[1], salt); - } - - -#ifdef _UFC_32_ - -/* - * 32 bit version - */ - -extern long32 _ufc_keytab[16][2]; -extern long32 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[]; - -#define SBA(sb, v) (*(long32*)((char*)(sb)+(v))) - -static ufc_long *_ufc_doit(l1, l2, r1, r2, itr) - ufc_long l1, l2, r1, r2, itr; - { int i; - long32 s, *k; - - while(itr--) { - k = &_ufc_keytab[0][0]; - for(i=8; i--; ) { - s = *k++ ^ r1; - l1 ^= SBA(_ufc_sb1, s & 0xffff); l2 ^= SBA(_ufc_sb1, (s & 0xffff)+4); - l1 ^= SBA(_ufc_sb0, s >>= 16); l2 ^= SBA(_ufc_sb0, (s) +4); - s = *k++ ^ r2; - l1 ^= SBA(_ufc_sb3, s & 0xffff); l2 ^= SBA(_ufc_sb3, (s & 0xffff)+4); - l1 ^= SBA(_ufc_sb2, s >>= 16); l2 ^= SBA(_ufc_sb2, (s) +4); - - s = *k++ ^ l1; - r1 ^= SBA(_ufc_sb1, s & 0xffff); r2 ^= SBA(_ufc_sb1, (s & 0xffff)+4); - r1 ^= SBA(_ufc_sb0, s >>= 16); r2 ^= SBA(_ufc_sb0, (s) +4); - s = *k++ ^ l2; - r1 ^= SBA(_ufc_sb3, s & 0xffff); r2 ^= SBA(_ufc_sb3, (s & 0xffff)+4); - r1 ^= SBA(_ufc_sb2, s >>= 16); r2 ^= SBA(_ufc_sb2, (s) +4); - } - s=l1; l1=r1; r1=s; s=l2; l2=r2; r2=s; - } - return _ufc_dofinalperm(l1, l2, r1, r2); - } - -#endif - -#ifdef _UFC_64_ - -/* - * 64 bit version - */ - -extern long64 _ufc_keytab[16]; -extern long64 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[]; - -#define SBA(sb, v) (*(long64*)((char*)(sb)+(v))) - -static ufc_long *_ufc_doit(l1, l2, r1, r2, itr) - ufc_long l1, l2, r1, r2, itr; - { int i; - long64 l, r, s, *k; - - l = (((long64)l1) << 32) | ((long64)l2); - r = (((long64)r1) << 32) | ((long64)r2); - - while(itr--) { - k = &_ufc_keytab[0]; - for(i=8; i--; ) { - s = *k++ ^ r; - l ^= SBA(_ufc_sb3, (s >> 0) & 0xffff); - l ^= SBA(_ufc_sb2, (s >> 16) & 0xffff); - l ^= SBA(_ufc_sb1, (s >> 32) & 0xffff); - l ^= SBA(_ufc_sb0, (s >> 48) & 0xffff); - - s = *k++ ^ l; - r ^= SBA(_ufc_sb3, (s >> 0) & 0xffff); - r ^= SBA(_ufc_sb2, (s >> 16) & 0xffff); - r ^= SBA(_ufc_sb1, (s >> 32) & 0xffff); - r ^= SBA(_ufc_sb0, (s >> 48) & 0xffff); - } - s=l; l=r; r=s; - } - - l1 = l >> 32; l2 = l & 0xffffffff; - r1 = r >> 32; r2 = r & 0xffffffff; - return _ufc_dofinalperm(l1, l2, r1, r2); - } - -#endif - - -#else - int ufc_dummy_procedure(void) -{return 0;} -#endif diff --git a/source/lib/username.c b/source/lib/username.c deleted file mode 100644 index b8d152c83fd..00000000000 --- a/source/lib/username.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Username handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -extern int DEBUGLEVEL; - - -/**************************************************************************** -get a users home directory. tries as-is then lower case -****************************************************************************/ -char *get_home_dir(char *user) -{ - static struct passwd *pass; - - pass = Get_Pwnam(user,False); - - if (!pass) return(NULL); - return(pass->pw_dir); -} - - -/******************************************************************* -map a username from a dos name to a unix name by looking in the username -map -********************************************************************/ -void map_username(char *user) -{ - static int depth=0; - static BOOL initialised=False; - static fstring last_from,last_to; - FILE *f; - char *s; - char *mapfile = lp_username_map(); - if (!*mapfile || depth) return; - - if (!*user) return; - - if (!initialised) { - *last_from = *last_to = 0; - initialised = True; - } - - if (strequal(user,last_to)) return; - - if (strequal(user,last_from)) { - DEBUG(3,("Mapped user %s to %s\n",user,last_to)); - strcpy(user,last_to); - return; - } - - f = fopen(mapfile,"r"); - if (!f) { - DEBUG(0,("can't open username map %s\n",mapfile)); - return; - } - - DEBUG(4,("Scanning username map %s\n",mapfile)); - - depth++; - - for (; (s=fgets_slash(NULL,80,f)); free(s)) { - char *unixname = s; - char *dosname = strchr(unixname,'='); - - if (!dosname) continue; - *dosname++ = 0; - - while (isspace(*unixname)) unixname++; - if (!*unixname || strchr("#;",*unixname)) continue; - - { - int l = strlen(unixname); - while (l && isspace(unixname[l-1])) { - unixname[l-1] = 0; - l--; - } - } - - if (strchr(dosname,'*') || user_in_list(user,dosname)) { - DEBUG(3,("Mapped user %s to %s\n",user,unixname)); - StrnCpy(last_from,user,sizeof(last_from)-1); - sscanf(unixname,"%s",user); - StrnCpy(last_to,user,sizeof(last_to)-1); - } - } - - fclose(f); - - depth--; -} - -/**************************************************************************** -internals of Get_Pwnam wrapper -****************************************************************************/ -static struct passwd *_Get_Pwnam(char *s) -{ - struct passwd *ret; - - ret = getpwnam(s); - if (ret) - { -#ifdef GETPWANAM - struct passwd_adjunct *pwret; - pwret = getpwanam(s); - if (pwret) - { - free(ret->pw_passwd); - ret->pw_passwd = pwret->pwa_passwd; - } -#endif - - } - - return(ret); -} - - -/**************************************************************************** -a wrapper for getpwnam() that tries with all lower and all upper case -if the initial name fails. Also tried with first letter capitalised -Note that this changes user! -****************************************************************************/ -struct passwd *Get_Pwnam(char *user,BOOL allow_change) -{ - fstring user2; - - struct passwd *ret; - - if (!user || !(*user)) - return(NULL); - - StrnCpy(user2,user,sizeof(user2)-1); - - if (!allow_change) { - user = &user2[0]; - } - - map_username(user); - - ret = _Get_Pwnam(user); - if (ret) return(ret); - - strlower(user); - ret = _Get_Pwnam(user); - if (ret) return(ret); - - strupper(user); - ret = _Get_Pwnam(user); - if (ret) return(ret); - - /* try with first letter capitalised */ - if (strlen(user) > 1) - strlower(user+1); - ret = _Get_Pwnam(user); - if (ret) return(ret); - - if (allow_change) - strcpy(user,user2); - - return(NULL); -} - - -/**************************************************************************** -check if a user is in a user list -****************************************************************************/ -BOOL user_in_list(char *user,char *list) -{ - pstring tok; - char *p=list; - - while (next_token(&p,tok,LIST_SEP)) - { - if (strequal(user,tok)) - return(True); - -#ifdef NETGROUP - if (*tok == '@') - { - static char *mydomain = NULL; - if (mydomain == 0) - yp_get_default_domain(&mydomain); - - if(mydomain == 0) - { - DEBUG(5,("Unable to get default yp domain\n")); - } - else - { - - DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", - user, mydomain, &tok[1])); - DEBUG(5,("innetgr is %s\n", - innetgr(&tok[1], (char *) 0, user, mydomain) - ? "TRUE" : "FALSE")); - - if (innetgr(&tok[1], (char *)0, user, mydomain)) - return (True); - } - } -#endif - - -#if HAVE_GETGRNAM - if (*tok == '@') - { - struct group *gptr; - char **member; - struct passwd *pass = Get_Pwnam(user,False); - - if (pass) { - gptr = getgrgid(pass->pw_gid); - if (gptr && strequal(gptr->gr_name,&tok[1])) - return(True); - } - - gptr = (struct group *)getgrnam(&tok[1]); - - if (gptr) - { - member = gptr->gr_mem; - while (member && *member) - { - if (strequal(*member,user)) - return(True); - member++; - } - } - } -#endif - } - return(False); -} - - diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c deleted file mode 100644 index 55f70be1222..00000000000 --- a/source/libsmb/namequery.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - name query routines - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - -extern pstring scope; -extern int DEBUGLEVEL; - - -/**************************************************************************** -interpret a node status response -****************************************************************************/ -static void _interpret_node_status(char *p, char *master,char *rname) -{ - int numnames = CVAL(p,0); - DEBUG(1,("received %d names\n",numnames)); - - if (rname) *rname = 0; - if (master) *master = 0; - - p += 1; - while (numnames--) - { - char qname[17]; - int type; - fstring flags; - int i; - *flags = 0; - StrnCpy(qname,p,15); - type = CVAL(p,15); - p += 16; - - strcat(flags, (p[0] & 0x80) ? "<GROUP> " : " "); - if ((p[0] & 0x60) == 0x00) strcat(flags,"B "); - if ((p[0] & 0x60) == 0x20) strcat(flags,"P "); - if ((p[0] & 0x60) == 0x40) strcat(flags,"M "); - if ((p[0] & 0x60) == 0x60) strcat(flags,"H "); - if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> "); - if (p[0] & 0x08) strcat(flags,"<CONFLICT> "); - if (p[0] & 0x04) strcat(flags,"<ACTIVE> "); - if (p[0] & 0x02) strcat(flags,"<PERMANENT> "); - - if (master && !*master && type == 0x1d) { - StrnCpy(master,qname,15); - trim_string(master,NULL," "); - } - - if (rname && !*rname && type == 0x20 && !(p[0]&0x80)) { - StrnCpy(rname,qname,15); - trim_string(rname,NULL," "); - } - - for (i = strlen( qname) ; --i >= 0 ; ) { - if (!isprint(qname[i])) qname[i] = '.'; - } - DEBUG(1,("\t%-15s <%02x> - %s\n",qname,type,flags)); - p+=2; - } - DEBUG(1,("num_good_sends=%d num_good_receives=%d\n", - IVAL(p,20),IVAL(p,24))); -} - - -/**************************************************************************** - do a netbios name status query on a host - - the "master" parameter is a hack used for finding workgroups. - **************************************************************************/ -BOOL name_status(int fd,char *name,int name_type,BOOL recurse, - struct in_addr to_ip,char *master,char *rname, - void (*fn)()) -{ - BOOL found=False; - int retries = 2; - int retry_time = 5000; - struct timeval tval; - struct packet_struct p; - struct packet_struct *p2; - struct nmb_packet *nmb = &p.packet.nmb; - static int name_trn_id = 0; - - bzero((char *)&p,sizeof(p)); - - if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + - (getpid()%(unsigned)100); - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; - - nmb->header.name_trn_id = name_trn_id; - nmb->header.opcode = 0; - nmb->header.response = False; - nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.recursion_available = False; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = False; - nmb->header.rcode = 0; - nmb->header.qdcount = 1; - nmb->header.ancount = 0; - nmb->header.nscount = 0; - nmb->header.arcount = 0; - - make_nmb_name(&nmb->question.question_name,name,name_type,scope); - - nmb->question.question_type = 0x21; - nmb->question.question_class = 0x1; - - p.ip = to_ip; - p.port = NMB_PORT; - p.fd = fd; - p.timestamp = time(NULL); - p.packet_type = NMB_PACKET; - - GetTimeOfDay(&tval); - - if (!send_packet(&p)) - return(False); - - retries--; - - while (1) - { - struct timeval tval2; - GetTimeOfDay(&tval2); - if (TvalDiff(&tval,&tval2) > retry_time) { - if (!retries) break; - if (!found && !send_packet(&p)) - return False; - GetTimeOfDay(&tval); - retries--; - } - - if ((p2=receive_packet(fd,NMB_PACKET,90))) - { - struct nmb_packet *nmb2 = &p2->packet.nmb; - debug_nmb_packet(p2); - - if (nmb->header.name_trn_id != nmb2->header.name_trn_id || - !nmb2->header.response) { - /* its not for us - maybe deal with it later */ - if (fn) - fn(p2); - else - free_packet(p2); - continue; - } - - if (nmb2->header.opcode != 0 || - nmb2->header.nm_flags.bcast || - nmb2->header.rcode || - !nmb2->header.ancount || - nmb2->answers->rr_type != 0x21) { - /* XXXX what do we do with this? could be a redirect, but - we'll discard it for the moment */ - free_packet(p2); - continue; - } - - _interpret_node_status(&nmb2->answers->rdata[0], master,rname); - free_packet(p2); - return(True); - } - } - - - DEBUG(0,("No status response (this is not unusual)\n")); - - return(False); -} - - -/**************************************************************************** - do a netbios name query to find someones IP - ****************************************************************************/ -BOOL name_query(int fd,char *name,int name_type, - BOOL bcast,BOOL recurse, - struct in_addr to_ip, struct in_addr *ip,void (*fn)()) -{ - BOOL found=False; - int retries = 3; - int retry_time = bcast?250:2000; - struct timeval tval; - struct packet_struct p; - struct packet_struct *p2; - struct nmb_packet *nmb = &p.packet.nmb; - static int name_trn_id = 0; - - bzero((char *)&p,sizeof(p)); - - if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) + - (getpid()%(unsigned)100); - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; - - nmb->header.name_trn_id = name_trn_id; - nmb->header.opcode = 0; - nmb->header.response = False; - nmb->header.nm_flags.bcast = bcast; - nmb->header.nm_flags.recursion_available = False; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = False; - nmb->header.rcode = 0; - nmb->header.qdcount = 1; - nmb->header.ancount = 0; - nmb->header.nscount = 0; - nmb->header.arcount = 0; - - make_nmb_name(&nmb->question.question_name,name,name_type,scope); - - nmb->question.question_type = 0x20; - nmb->question.question_class = 0x1; - - p.ip = to_ip; - p.port = NMB_PORT; - p.fd = fd; - p.timestamp = time(NULL); - p.packet_type = NMB_PACKET; - - GetTimeOfDay(&tval); - - if (!send_packet(&p)) - return(False); - - retries--; - - while (1) - { - struct timeval tval2; - GetTimeOfDay(&tval2); - if (TvalDiff(&tval,&tval2) > retry_time) { - if (!retries) break; - if (!found && !send_packet(&p)) - return False; - GetTimeOfDay(&tval); - retries--; - } - - if ((p2=receive_packet(fd,NMB_PACKET,90))) - { - struct nmb_packet *nmb2 = &p2->packet.nmb; - debug_nmb_packet(p2); - - if (nmb->header.name_trn_id != nmb2->header.name_trn_id || - !nmb2->header.response) { - /* its not for us - maybe deal with it later - (put it on the queue?) */ - if (fn) - fn(p2); - else - free_packet(p2); - continue; - } - - if (nmb2->header.opcode != 0 || - nmb2->header.nm_flags.bcast || - nmb2->header.rcode || - !nmb2->header.ancount) { - /* XXXX what do we do with this? could be a redirect, but - we'll discard it for the moment */ - free_packet(p2); - continue; - } - - if (ip) { - putip((char *)ip,&nmb2->answers->rdata[2]); - DEBUG(fn?3:2,("Got a positive name query response from %s", - inet_ntoa(p2->ip))); - DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip))); - } - found=True; retries=0; - free_packet(p2); - if (fn) break; - } - } - - return(found); -} diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c deleted file mode 100644 index bc967bdacb4..00000000000 --- a/source/libsmb/nmblib.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios library routines - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - -int num_good_sends = 0; -int num_good_receives = 0; -extern pstring scope; -extern pstring myname; -extern struct in_addr ipzero; - -static struct opcode_names { - const char *nmb_opcode_name; - int opcode; -} nmb_header_opcode_names[] = { - { "Query", 0 }, - {"Registration", 5 }, - {"Release", 6 }, - {"WACK", 7 }, - {"refresh", 8 }, - {0, -1 } -}; - -/**************************************************************************** - * Lookup a nmb opcode name. - ****************************************************************************/ - -const char *lookup_opcode_name( int opcode ) -{ - struct opcode_names *op_namep; - int i; - - for(i = 0; nmb_header_opcode_names[i].nmb_opcode_name != 0; i++) { - op_namep = &nmb_header_opcode_names[i]; - if(opcode == op_namep->opcode) - return op_namep->nmb_opcode_name; - } - return "<unknown opcode>"; -} - -/**************************************************************************** - print out a res_rec structure - ****************************************************************************/ -static void debug_nmb_res_rec(struct res_rec *res, char *hdr) -{ - int i, j; - - DEBUG(4,(" %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d\n", - hdr, - namestr(&res->rr_name), - res->rr_type, - res->rr_class, - res->ttl)); - - if (res->rdlength == 0 || res->rdata == NULL) return; - - for (i = 0; i < res->rdlength; i+= 16) - { - DEBUG(4, (" %s %3x char ", hdr, i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = res->rdata[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= res->rdlength) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= res->rdlength) break; - DEBUG(4, ("%02X", (unsigned char)res->rdata[i+j])); - } - - DEBUG(4, ("\n")); - } -} - -/**************************************************************************** - process a nmb packet - ****************************************************************************/ -void debug_nmb_packet(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - - DEBUG(4,("nmb packet from %s header: id=%d opcode=%s(%d) response=%s\n", - inet_ntoa(p->ip), - nmb->header.name_trn_id, - lookup_opcode_name(nmb->header.opcode), - nmb->header.opcode,BOOLSTR(nmb->header.response))); - DEBUG(4,(" header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n", - BOOLSTR(nmb->header.nm_flags.bcast), - BOOLSTR(nmb->header.nm_flags.recursion_available), - BOOLSTR(nmb->header.nm_flags.recursion_desired), - BOOLSTR(nmb->header.nm_flags.trunc), - BOOLSTR(nmb->header.nm_flags.authoritative))); - DEBUG(4,(" header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n", - nmb->header.rcode, - nmb->header.qdcount, - nmb->header.ancount, - nmb->header.nscount, - nmb->header.arcount)); - - if (nmb->header.qdcount) - { - DEBUG(4,(" question: q_name=%s q_type=%d q_class=%d\n", - namestr(&nmb->question.question_name), - nmb->question.question_type, - nmb->question.question_class)); - } - - if (nmb->answers && nmb->header.ancount) - { - debug_nmb_res_rec(nmb->answers,"answers"); - } - if (nmb->nsrecs && nmb->header.nscount) - { - debug_nmb_res_rec(nmb->nsrecs,"nsrecs"); - } - if (nmb->additional && nmb->header.arcount) - { - debug_nmb_res_rec(nmb->additional,"additional"); - } -} - -/******************************************************************* - handle "compressed" name pointers - ******************************************************************/ -static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length, - BOOL *got_pointer,int *ret) -{ - int loop_count=0; - - while ((ubuf[*offset] & 0xC0) == 0xC0) { - if (!*got_pointer) (*ret) += 2; - (*got_pointer)=True; - (*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1]; - if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) { - return(False); - } - } - return(True); -} - -/******************************************************************* - parse a nmb name from "compressed" format to something readable - return the space taken by the name, or 0 if the name is invalid - ******************************************************************/ -static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name) -{ - int m,n=0; - unsigned char *ubuf = (unsigned char *)inbuf; - int ret = 0; - BOOL got_pointer=False; - - if (length - offset < 2) return(0); - - /* handle initial name pointers */ - if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0); - - m = ubuf[offset]; - - if (!m) return(0); - if ((m & 0xC0) || offset+m+2 > length) return(0); - - bzero((char *)name,sizeof(*name)); - - /* the "compressed" part */ - if (!got_pointer) ret += m + 2; - offset++; - while (m) { - unsigned char c1,c2; - c1 = ubuf[offset++]-'A'; - c2 = ubuf[offset++]-'A'; - if ((c1 & 0xF0) || (c2 & 0xF0)) return(0); - name->name[n++] = (c1<<4) | c2; - m -= 2; - } - name->name[n] = 0; - - if (n==16) { - /* parse out the name type, - its always in the 16th byte of the name */ - name->name_type = name->name[15]; - - /* remove trailing spaces */ - name->name[15] = 0; - n = 14; - while (n && name->name[n]==' ') name->name[n--] = 0; - } - - /* now the domain parts (if any) */ - n = 0; - while ((m=ubuf[offset])) { - /* we can have pointers within the domain part as well */ - if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret)) return(0); - - if (!got_pointer) ret += m+1; - if (n) name->scope[n++] = '.'; - if (m+2+offset>length || n+m+1>sizeof(name->scope)) return(0); - offset++; - while (m--) name->scope[n++] = (char)ubuf[offset++]; - } - name->scope[n++] = 0; - - return(ret); -} - - -/******************************************************************* - put a compressed nmb name into a buffer. return the length of the - compressed name - - compressed names are really weird. The "compression" doubles the - size. The idea is that it also means that compressed names conform - to the doman name system. See RFC1002. - ******************************************************************/ -static int put_nmb_name(char *buf,int offset,struct nmb_name *name) -{ - int ret,m; - fstring buf1; - char *p; - - if (name->name[0] == '*') { - /* special case for wildcard name */ - bzero(buf1,20); - buf1[0] = '*'; - } else { - sprintf(buf1,"%-15.15s%c",name->name,name->name_type); - } - - buf[offset] = 0x20; - - ret = 34; - - for (m=0;m<16;m++) { - buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF); - buf[offset+2+2*m] = 'A' + (buf1[m]&0xF); - } - offset += 33; - - buf[offset] = 0; - - if (name->scope[0]) { - /* XXXX this scope handling needs testing */ - ret += strlen(name->scope) + 1; - strcpy(&buf[offset+1],name->scope); - - p = &buf[offset+1]; - while ((p = strchr(p,'.'))) { - buf[offset] = PTR_DIFF(p,&buf[offset]); - offset += buf[offset]; - p = &buf[offset+1]; - } - buf[offset] = strlen(&buf[offset+1]); - } - - return(ret); -} - -/******************************************************************* - useful for debugging messages - ******************************************************************/ -char *namestr(struct nmb_name *n) -{ - static int i=0; - static fstring ret[4]; - char *p = ret[i]; - - if (!n->scope[0]) - sprintf(p,"%s(%x)",n->name,n->name_type); - else - sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope); - - i = (i+1)%4; - return(p); -} - -/******************************************************************* - allocate and parse some resource records - ******************************************************************/ -static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length, - struct res_rec **recs, int count) -{ - int i; - *recs = (struct res_rec *)malloc(sizeof(**recs)*count); - if (!*recs) return(False); - - bzero(*recs,sizeof(**recs)*count); - - for (i=0;i<count;i++) { - int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name); - (*offset) += l; - if (!l || (*offset)+10 > length) { - free(*recs); - return(False); - } - (*recs)[i].rr_type = RSVAL(inbuf,(*offset)); - (*recs)[i].rr_class = RSVAL(inbuf,(*offset)+2); - (*recs)[i].ttl = RIVAL(inbuf,(*offset)+4); - (*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8); - (*offset) += 10; - if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) || - (*offset)+(*recs)[i].rdlength > length) { - free(*recs); - return(False); - } - memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength); - (*offset) += (*recs)[i].rdlength; - } - return(True); -} - -/******************************************************************* - put a resource record into a packet - ******************************************************************/ -static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count) -{ - int ret=0; - int i; - - for (i=0;i<count;i++) { - int l = put_nmb_name(buf,offset,&recs[i].rr_name); - offset += l; - ret += l; - RSSVAL(buf,offset,recs[i].rr_type); - RSSVAL(buf,offset+2,recs[i].rr_class); - RSIVAL(buf,offset+4,recs[i].ttl); - RSSVAL(buf,offset+8,recs[i].rdlength); - memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength); - offset += 10+recs[i].rdlength; - ret += 10+recs[i].rdlength; - } - - return(ret); -} - -/******************************************************************* - parse a dgram packet. Return False if the packet can't be parsed - or is invalid for some reason, True otherwise - - this is documented in section 4.4.1 of RFC1002 - ******************************************************************/ -static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram) -{ - int offset; - int flags; - - bzero((char *)dgram,sizeof(*dgram)); - - if (length < 14) return(False); - - dgram->header.msg_type = CVAL(inbuf,0); - flags = CVAL(inbuf,1); - dgram->header.flags.node_type = (enum node_type)((flags>>2)&3); - if (flags & 1) dgram->header.flags.more = True; - if (flags & 2) dgram->header.flags.first = True; - dgram->header.dgm_id = RSVAL(inbuf,2); - putip((char *)&dgram->header.source_ip,inbuf+4); - dgram->header.source_port = RSVAL(inbuf,8); - dgram->header.dgm_length = RSVAL(inbuf,10); - dgram->header.packet_offset = RSVAL(inbuf,12); - - offset = 14; - - if (dgram->header.msg_type == 0x10 || - dgram->header.msg_type == 0x11 || - dgram->header.msg_type == 0x12) { - offset += parse_nmb_name(inbuf,offset,length,&dgram->source_name); - offset += parse_nmb_name(inbuf,offset,length,&dgram->dest_name); - } - - if (offset >= length || (length-offset > sizeof(dgram->data))) - return(False); - - dgram->datasize = length-offset; - memcpy(dgram->data,inbuf+offset,dgram->datasize); - - return(True); -} - - -/******************************************************************* - parse a nmb packet. Return False if the packet can't be parsed - or is invalid for some reason, True otherwise - ******************************************************************/ -static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb) -{ - int nm_flags,offset; - - bzero((char *)nmb,sizeof(*nmb)); - - if (length < 12) return(False); - - /* parse the header */ - nmb->header.name_trn_id = RSVAL(inbuf,0); - - DEBUG(10,("parse_nmb: packet id = %d\n", nmb->header.name_trn_id)); - - nmb->header.opcode = (CVAL(inbuf,2) >> 3) & 0xF; - nmb->header.response = ((CVAL(inbuf,2)>>7)&1)?True:False; - nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4); - nmb->header.nm_flags.bcast = (nm_flags&1)?True:False; - nmb->header.nm_flags.recursion_available = (nm_flags&8)?True:False; - nmb->header.nm_flags.recursion_desired = (nm_flags&0x10)?True:False; - nmb->header.nm_flags.trunc = (nm_flags&0x20)?True:False; - nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False; - nmb->header.rcode = CVAL(inbuf,3) & 0xF; - nmb->header.qdcount = RSVAL(inbuf,4); - nmb->header.ancount = RSVAL(inbuf,6); - nmb->header.nscount = RSVAL(inbuf,8); - nmb->header.arcount = RSVAL(inbuf,10); - - if (nmb->header.qdcount) { - offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name); - if (!offset) return(False); - - if (length - (12+offset) < 4) return(False); - nmb->question.question_type = RSVAL(inbuf,12+offset); - nmb->question.question_class = RSVAL(inbuf,12+offset+2); - - offset += 12+4; - } else { - offset = 12; - } - - /* and any resource records */ - if (nmb->header.ancount && - !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers, - nmb->header.ancount)) - return(False); - - if (nmb->header.nscount && - !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs, - nmb->header.nscount)) - return(False); - - if (nmb->header.arcount && - !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional, - nmb->header.arcount)) - return(False); - - return(True); -} - -/******************************************************************* - free up any resources associated with an nmb packet - ******************************************************************/ -void free_nmb_packet(struct nmb_packet *nmb) -{ - if (nmb->answers) free(nmb->answers); - if (nmb->nsrecs) free(nmb->nsrecs); - if (nmb->additional) free(nmb->additional); -} - -/******************************************************************* - free up any resources associated with a packet - ******************************************************************/ -void free_packet(struct packet_struct *packet) -{ - if (packet->packet_type == NMB_PACKET) - free_nmb_packet(&packet->packet.nmb); - free(packet); -} - -/******************************************************************* - read a packet from a socket and parse it, returning a packet ready - to be used or put on the queue. This assumes a UDP socket - ******************************************************************/ -struct packet_struct *read_packet(int fd,enum packet_type packet_type) -{ - extern struct in_addr lastip; - extern int lastport; - struct packet_struct *packet; - char buf[MAX_DGRAM_SIZE]; - int length; - BOOL ok=False; - - length = read_udp_socket(fd,buf,sizeof(buf)); - if (length < MIN_DGRAM_SIZE) return(NULL); - - packet = (struct packet_struct *)malloc(sizeof(*packet)); - if (!packet) return(NULL); - - packet->next = NULL; - packet->prev = NULL; - packet->ip = lastip; - packet->port = lastport; - packet->fd = fd; - packet->timestamp = time(NULL); - packet->packet_type = packet_type; - switch (packet_type) - { - case NMB_PACKET: - ok = parse_nmb(buf,length,&packet->packet.nmb); - break; - - case DGRAM_PACKET: - ok = parse_dgram(buf,length,&packet->packet.dgram); - break; - } - if (!ok) { - DEBUG(10,("parse_nmb: discarding packet id = %d\n", - packet->packet.nmb.header.name_trn_id)); - free(packet); - return(NULL); - } - - num_good_receives++; - - DEBUG(5,("%s received a packet of len %d from (%s) port %d\n", - timestring(),length,inet_ntoa(packet->ip),packet->port)); - - return(packet); -} - - -/******************************************************************* - send a udp packet on a already open socket - ******************************************************************/ -static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port) -{ - BOOL ret; - struct sockaddr_in sock_out; - - /* set the address and port */ - bzero((char *)&sock_out,sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)&ip); - sock_out.sin_port = htons( port ); - sock_out.sin_family = AF_INET; - - DEBUG(5,("%s sending a packet of len %d to (%s) on port %d\n", - timestring(),len,inet_ntoa(ip),port)); - - ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, - sizeof(sock_out)) >= 0); - - if (!ret) - DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n", - inet_ntoa(ip),port,strerror(errno))); - - if (ret) - num_good_sends++; - - return(ret); -} - -/******************************************************************* - build a dgram packet ready for sending - - XXXX This currently doesn't handle packets too big for one - datagram. It should split them and use the packet_offset, more and - first flags to handle the fragmentation. Yuck. - ******************************************************************/ -static int build_dgram(char *buf,struct packet_struct *p) -{ - struct dgram_packet *dgram = &p->packet.dgram; - unsigned char *ubuf = (unsigned char *)buf; - int offset=0; - - /* put in the header */ - ubuf[0] = dgram->header.msg_type; - ubuf[1] = (((int)dgram->header.flags.node_type)<<2); - if (dgram->header.flags.more) ubuf[1] |= 1; - if (dgram->header.flags.first) ubuf[1] |= 2; - RSSVAL(ubuf,2,dgram->header.dgm_id); - putip(ubuf+4,(char *)&dgram->header.source_ip); - RSSVAL(ubuf,8,dgram->header.source_port); - RSSVAL(ubuf,12,dgram->header.packet_offset); - - offset = 14; - - if (dgram->header.msg_type == 0x10 || - dgram->header.msg_type == 0x11 || - dgram->header.msg_type == 0x12) { - offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name); - offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name); - } - - memcpy(ubuf+offset,dgram->data,dgram->datasize); - offset += dgram->datasize; - - /* automatically set the dgm_length */ - dgram->header.dgm_length = offset; - RSSVAL(ubuf,10,dgram->header.dgm_length); - - return(offset); -} - -/******************************************************************* - build a nmb name - ******************************************************************/ -void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope) -{ - strcpy(n->name,name); - strupper(n->name); - n->name_type = type; - strcpy(n->scope,this_scope); -} - - -/******************************************************************* - build a nmb packet ready for sending - - XXXX this currently relies on not being passed something that expands - to a packet too big for the buffer. Eventually this should be - changed to set the trunc bit so the receiver can request the rest - via tcp (when that becomes supported) - ******************************************************************/ -static int build_nmb(char *buf,struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - unsigned char *ubuf = (unsigned char *)buf; - int offset=0; - - /* put in the header */ - RSSVAL(ubuf,offset,nmb->header.name_trn_id); - ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3; - if (nmb->header.response) ubuf[offset+2] |= (1<<7); - if (nmb->header.nm_flags.authoritative && - nmb->header.response) ubuf[offset+2] |= 0x4; - if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2; - if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1; - if (nmb->header.nm_flags.recursion_available && - nmb->header.response) ubuf[offset+3] |= 0x80; - if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10; - ubuf[offset+3] |= (nmb->header.rcode & 0xF); - - RSSVAL(ubuf,offset+4,nmb->header.qdcount); - RSSVAL(ubuf,offset+6,nmb->header.ancount); - RSSVAL(ubuf,offset+8,nmb->header.nscount); - RSSVAL(ubuf,offset+10,nmb->header.arcount); - - offset += 12; - if (nmb->header.qdcount) { - /* XXXX this doesn't handle a qdcount of > 1 */ - offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name); - RSSVAL(ubuf,offset,nmb->question.question_type); - RSSVAL(ubuf,offset+2,nmb->question.question_class); - offset += 4; - } - - if (nmb->header.ancount) - offset += put_res_rec((char *)ubuf,offset,nmb->answers, - nmb->header.ancount); - - if (nmb->header.nscount) - offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs, - nmb->header.nscount); - - if (nmb->header.arcount) - offset += put_res_rec((char *)ubuf,offset,nmb->additional, - nmb->header.arcount); - - return(offset); -} - - -/******************************************************************* - send a packet_struct - ******************************************************************/ -BOOL send_packet(struct packet_struct *p) -{ - char buf[1024]; - int len=0; - - bzero(buf,sizeof(buf)); - - switch (p->packet_type) - { - case NMB_PACKET: - len = build_nmb(buf,p); - break; - - case DGRAM_PACKET: - len = build_dgram(buf,p); - break; - } - - if (!len) return(False); - - return(send_udp(p->fd,buf,len,p->ip,p->port)); -} - -/**************************************************************************** - receive a packet with timeout on a open UDP filedescriptor - The timeout is in milliseconds - ***************************************************************************/ -struct packet_struct *receive_packet(int fd,enum packet_type type,int t) -{ - fd_set fds; - struct timeval timeout; - - FD_ZERO(&fds); - FD_SET(fd,&fds); - timeout.tv_sec = t/1000; - timeout.tv_usec = 1000*(t%1000); - - sys_select(&fds,&timeout); - - if (FD_ISSET(fd,&fds)) - return(read_packet(fd,type)); - - return(NULL); -} - - diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c deleted file mode 100644 index 8bb21cfed20..00000000000 --- a/source/libsmb/smbencrypt.c +++ /dev/null @@ -1,196 +0,0 @@ -#ifdef SMB_PASSWD -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1997 - Modified by Jeremy Allison 1995. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "des.h" -#include "md4.h" - -extern int DEBUGLEVEL; - -#include "byteorder.h" - -void str_to_key(uchar *str,uchar *key) -{ - void des_set_odd_parity(des_cblock *); - int i; - - key[0] = str[0]>>1; - key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); - key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); - key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); - key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); - key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); - key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); - key[7] = str[6]&0x7F; - for (i=0;i<8;i++) { - key[i] = (key[i]<<1); - } - des_set_odd_parity((des_cblock *)key); -} - -void D1(uchar *k, uchar *d, uchar *out) -{ - des_key_schedule ks; - des_cblock deskey; - - str_to_key(k,(uchar *)deskey); -#ifdef __FreeBSD__ - des_set_key(&deskey,ks); -#else /* __FreeBSD__ */ - des_set_key((des_cblock *)deskey,ks); -#endif /* __FreeBsd */ - des_ecb_encrypt((des_cblock *)d,(des_cblock *)out, ks, DES_DECRYPT); -} - -void E1(uchar *k, uchar *d, uchar *out) -{ - des_key_schedule ks; - des_cblock deskey; - - str_to_key(k,(uchar *)deskey); -#ifdef __FreeBSD__ - des_set_key(&deskey,ks); -#else /* __FreeBsd__ */ - des_set_key((des_cblock *)deskey,ks); -#endif /* __FreeBsd__ */ - des_ecb_encrypt((des_cblock *)d,(des_cblock *)out, ks, DES_ENCRYPT); -} - -void E_P16(uchar *p14,uchar *p16) -{ - uchar sp7[7]; - /* the following constant makes us compatible with other - implementations. Note that publishing this constant does not reduce the - security of the encryption mechanism */ - uchar sp8[] = {0xAA,0xD3,0xB4,0x35,0xB5,0x14,0x4,0xEE}; - uchar x[8]; - - memset(sp7,'\0',7); - - D1(sp7, sp8, x); - E1(p14, x, p16); - E1(p14+7, x, p16+8); -} - -void E_P24(uchar *p21, uchar *c8, uchar *p24) -{ - E1(p21, c8, p24); - E1(p21+7, c8, p24+8); - E1(p21+14, c8, p24+16); -} - - -/* - This implements the X/Open SMB password encryption - It takes a password, a 8 byte "crypt key" and puts 24 bytes of - encrypted password into p24 */ -void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24) -{ - uchar p14[15], p21[21]; - - memset(p21,'\0',21); - memset(p14,'\0',14); - StrnCpy((char *)p14,(char *)passwd,14); - - strupper((char *)p14); - E_P16(p14, p21); - E_P24(p21, c8, p24); -} - -/* Routines for Windows NT MD4 Hash functions. */ -static int _my_wcslen(int16 *str) -{ - int len = 0; - while(*str++ != 0) - len++; - return len; -} - -/* - * Convert a string into an NT UNICODE string. - * Note that regardless of processor type - * this must be in intel (little-endian) - * format. - */ - -static int _my_mbstowcs(int16 *dst, uchar *src, int len) -{ - int i; - int16 val; - - for(i = 0; i < len; i++) { - val = *src; - SSVAL(dst,0,val); - dst++; - src++; - if(val == 0) - break; - } - return i; -} - -/* - * Creates the MD4 Hash of the users password in NT UNICODE. - */ - -void E_md4hash(uchar *passwd, uchar *p16) -{ - int i, len; - int16 wpwd[129]; - MDstruct MD; - - /* Password cannot be longer than 128 characters */ - len = strlen((char *)passwd); - if(len > 128) - len = 128; - /* Password must be converted to NT unicode */ - _my_mbstowcs( wpwd, passwd, len); - wpwd[len] = 0; /* Ensure string is null terminated */ - /* Calculate length in bytes */ - len = _my_wcslen(wpwd) * sizeof(int16); - - MDbegin(&MD); - for(i = 0; i + 64 <= len; i += 64) - MDupdate(&MD,wpwd + (i/2), 512); - MDupdate(&MD,wpwd + (i/2),(len-i)*8); - SIVAL(p16,0,MD.buffer[0]); - SIVAL(p16,4,MD.buffer[1]); - SIVAL(p16,8,MD.buffer[2]); - SIVAL(p16,12,MD.buffer[3]); -} - -/* Does the NT MD4 hash then des encryption. */ - -void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24) -{ - uchar p21[21]; - - memset(p21,'\0',21); - - E_md4hash(passwd, p21); - E_P24(p21, c8, p24); -} - -#else - void smbencrypt_dummy(void){} -#endif diff --git a/source/locking/locking.c b/source/locking/locking.c deleted file mode 100644 index 64dc207cb7d..00000000000 --- a/source/locking/locking.c +++ /dev/null @@ -1,1247 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Locking functions - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 12 aug 96: Erik.Devriendt@te6.siemens.be - added support for shared memory implementation of share mode locking - - May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode - locking to deal with multiple share modes per open file. -*/ - -#include "includes.h" -extern int DEBUGLEVEL; -extern connection_struct Connections[]; -extern files_struct Files[]; - -/**************************************************************************** - utility function called to see if a file region is locked -****************************************************************************/ -BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset) -{ - int snum = SNUM(cnum); - - if (count == 0) - return(False); - - if (!lp_locking(snum) || !lp_strict_locking(snum)) - return(False); - - return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count, - (Files[fnum].can_write?F_WRLCK:F_RDLCK))); -} - - -/**************************************************************************** - utility function called by locking requests -****************************************************************************/ -BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) -{ - BOOL ok = False; - - if (!lp_locking(SNUM(cnum))) - return(True); - - if (count == 0) { - *eclass = ERRDOS; - *ecode = ERRnoaccess; - return False; - } - - if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) - ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count, - (Files[fnum].can_write?F_WRLCK:F_RDLCK)); - - if (!ok) { - *eclass = ERRDOS; - *ecode = ERRlock; - return False; - } - return True; /* Got lock */ -} - - -/**************************************************************************** - utility function called by unlocking requests -****************************************************************************/ -BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode) -{ - BOOL ok = False; - - if (!lp_locking(SNUM(cnum))) - return(True); - - if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum)) - ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,F_UNLCK); - - if (!ok) { - *eclass = ERRDOS; - *ecode = ERRlock; - return False; - } - return True; /* Did unlock */ -} - -#ifdef FAST_SHARE_MODES -/******************************************************************* - initialize the shared memory for share_mode management - ******************************************************************/ -BOOL start_share_mode_mgmt(void) -{ - pstring shmem_file_name; - - strcpy(shmem_file_name,lp_lockdir()); - if (!directory_exist(shmem_file_name,NULL)) - mkdir(shmem_file_name,0755); - trim_string(shmem_file_name,"","/"); - if (!*shmem_file_name) return(False); - strcat(shmem_file_name, "/SHARE_MEM_FILE"); - return smb_shm_open(shmem_file_name, lp_shmem_size()); -} - - -/******************************************************************* - deinitialize the shared memory for share_mode management - ******************************************************************/ -BOOL stop_share_mode_mgmt(void) -{ - return smb_shm_close(); -} - -/******************************************************************* - lock a hash bucket entry in shared memory for share_mode management - ******************************************************************/ -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) -{ - return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode)); -} - -/******************************************************************* - unlock a hash bucket entry in shared memory for share_mode management - ******************************************************************/ -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) -{ - return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode)); -} - -/******************************************************************* -get all share mode entries in shared memory for a dev/inode pair. -********************************************************************/ -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares) -{ - smb_shm_offset_t *mode_array; - unsigned int hash_entry = HASH_ENTRY(dev, inode); - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *entry_scanner_p; - share_mode_entry *entry_prev_p; - int num_entries; - int num_entries_copied; - BOOL found = False; - min_share_mode_entry *share_array = (min_share_mode_entry *)0; - - *old_shares = 0; - - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return 0; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - if(mode_array[hash_entry] == NULL_OFFSET) - { - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry)); - return 0; - } - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *)smb_shm_offset2addr( - file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \ -file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry)); - return (0); - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \ -record due to old locking version %d for file dev = %d, inode = %d in hash \ -bucket %d",file_scanner_p->locking_version, dev, inode, hash_entry)); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - return (0); - } - - /* Allocate the old_shares array */ - num_entries = file_scanner_p->num_share_mode_entries; - if(num_entries) - { - *old_shares = share_array = (min_share_mode_entry *) - malloc(num_entries * sizeof(min_share_mode_entry)); - if(*old_shares == 0) - { - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n")); - return 0; - } - } - - num_entries_copied = 0; - - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - while(entry_scanner_p) - { - int pid = entry_scanner_p->pid; - - if (pid && !process_exists(pid)) - { - /* Delete this share mode entry */ - share_mode_entry *delete_entry_p = entry_scanner_p; - - if(entry_prev_p == entry_scanner_p) - { - /* We are at start of list */ - file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry; - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - } - else - { - entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry; - entry_scanner_p = (share_mode_entry*) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - /* Decrement the number of share mode entries on this share mode record */ - file_scanner_p->num_share_mode_entries -= 1; - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ -for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, - dev, inode, hash_entry)); - return 0; - } - - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \ -it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \ -bucket (number of entries now = %d)\n", - pid, entry_scanner_p->share_mode, dev, inode, hash_entry, - file_scanner_p->num_share_mode_entries)); - - smb_shm_free(smb_shm_addr2offset(delete_entry_p)); - } - else - { - /* This is a valid share mode entry and the process that - created it still exists. Copy it into the output array. - */ - share_array[num_entries_copied].pid = entry_scanner_p->pid; - share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode; - memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time, - sizeof(struct timeval)); - num_entries_copied++; - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \ -record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid)); - entry_prev_p = entry_scanner_p; - entry_scanner_p = (share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - } - - /* If no valid share mode entries were found then this record shouldn't exist ! */ - if(num_entries_copied == 0) - { - DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ -hash bucket %d has a share mode record but no entries - deleting\n", - dev, inode, hash_entry)); - if(*old_shares) - free((char *)old_shares); - *old_shares = 0; - - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - } - - DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \ -hash bucket %d returning %d entries\n", dev, inode, hash_entry, - num_entries_copied)); - - return(num_entries_copied); -} - -/******************************************************************* -del the share mode of a file. -********************************************************************/ -void del_share_mode(share_lock_token token, int fnum) -{ - uint32 dev, inode; - smb_shm_offset_t *mode_array; - unsigned int hash_entry; - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *entry_scanner_p; - share_mode_entry *entry_prev_p; - BOOL found = False; - int pid = getpid(); - - dev = Files[fnum].fd_ptr->dev; - inode = Files[fnum].fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - if(mode_array[hash_entry] == NULL_OFFSET) - { - DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n", - hash_entry)); - return; - } - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \ -inode %d in hash bucket %d\n", dev, inode, hash_entry)); - return; - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \ -record due to old locking version %d for file dev %d, inode %d hash bucket %d\n", - file_scanner_p->locking_version, dev, inode, hash_entry )); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - return; - } - - found = False; - entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - entry_prev_p = entry_scanner_p; - while(entry_scanner_p) - { - if( (pid == entry_scanner_p->pid) && - (memcmp(&entry_scanner_p->time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) - { - found = True; - break; - } - else - { - entry_prev_p = entry_scanner_p; - entry_scanner_p = (share_mode_entry *) - smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry); - } - } - - if (found) - { - /* Decrement the number of entries in the record. */ - file_scanner_p->num_share_mode_entries -= 1; - - DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \ -Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n", - dev, inode, hash_entry, file_scanner_p->num_share_mode_entries)); - if(entry_prev_p == entry_scanner_p) - /* We are at start of list */ - file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry; - else - entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry; - smb_shm_free(smb_shm_addr2offset(entry_scanner_p)); - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ -for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, - dev, inode, hash_entry)); - return; - } - - /* If we deleted the last share mode entry then remove the share mode record. */ - if(file_scanner_p->num_share_mode_entries == 0) - { - DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \ -record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); - if(file_prev_p == file_scanner_p) - mode_array[hash_entry] = file_scanner_p->next_offset; - else - file_prev_p->next_offset = file_scanner_p->next_offset; - smb_shm_free(smb_shm_addr2offset(file_scanner_p)); - } - } - else - { - DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \ -dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); - } -} - -/******************************************************************* -set the share mode of a file. Return False on fail, True on success. -********************************************************************/ -BOOL set_share_mode(share_lock_token token, int fnum) -{ - files_struct *fs_p = &Files[fnum]; - int32 dev, inode; - smb_shm_offset_t *mode_array; - unsigned int hash_entry; - share_mode_record *file_scanner_p; - share_mode_record *file_prev_p; - share_mode_entry *new_entry_p; - smb_shm_offset_t new_entry_offset; - BOOL found = False; - - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; - - hash_entry = HASH_ENTRY(dev, inode); - if(hash_entry > lp_shmem_hash_size() ) - { - DEBUG(0, - ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \ -(max = %d)\n", - hash_entry, lp_shmem_hash_size() )); - return False; - } - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]); - file_prev_p = file_scanner_p; - - while(file_scanner_p) - { - if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) ) - { - found = True; - break; - } - else - { - file_prev_p = file_scanner_p ; - file_scanner_p = (share_mode_record *) - smb_shm_offset2addr(file_scanner_p->next_offset); - } - } - - if(!found) - { - /* We must create a share_mode_record */ - share_mode_record *new_mode_p = NULL; - smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) + - strlen(fs_p->name) + 1); - if(new_offset == NULL_OFFSET) - { - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n")); - return False; - } - new_mode_p = smb_shm_offset2addr(new_offset); - new_mode_p->locking_version = LOCKING_VERSION; - new_mode_p->st_dev = dev; - new_mode_p->st_ino = inode; - new_mode_p->num_share_mode_entries = 0; - new_mode_p->share_mode_entries = NULL_OFFSET; - strcpy(new_mode_p->file_name, fs_p->name); - - /* Chain onto the start of the hash chain (in the hope we will be used first). */ - new_mode_p->next_offset = mode_array[hash_entry]; - mode_array[hash_entry] = new_offset; - - file_scanner_p = new_mode_p; - - DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \ -inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry)); - } - - /* Now create the share mode entry */ - new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry)); - if(new_entry_offset == NULL_OFFSET) - { - smb_shm_offset_t delete_offset = mode_array[hash_entry]; - DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n")); - /* Unlink the damaged record */ - mode_array[hash_entry] = file_scanner_p->next_offset; - /* And delete it */ - smb_shm_free( delete_offset ); - return False; - } - - new_entry_p = smb_shm_offset2addr(new_entry_offset); - - new_entry_p->pid = getpid(); - new_entry_p->share_mode = fs_p->share_mode; - memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval)); - - /* Chain onto the share_mode_record */ - new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries; - file_scanner_p->share_mode_entries = new_entry_offset; - - /* PARANOIA TEST */ - if(file_scanner_p->num_share_mode_entries < 0) - { - DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \ -for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries, - dev, inode, hash_entry)); - return False; - } - - /* Increment the share_mode_entries counter */ - file_scanner_p->num_share_mode_entries += 1; - - DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \ -0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid, - file_scanner_p->num_share_mode_entries)); - - return(True); -} - -#else /* FAST_SHARE_MODES */ - -/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */ - -/******************************************************************* - name a share file - ******************************************************************/ -static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name) -{ - strcpy(name,lp_lockdir()); - standard_sub(cnum,name); - trim_string(name,"","/"); - if (!*name) return(False); - name += strlen(name); - - sprintf(name,"/share.%u.%u",dev,inode); - return(True); -} - -/******************************************************************* - lock a share mode file. - ******************************************************************/ -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok) -{ - pstring fname; - int fd; - - *ptok = (share_lock_token)-1; - - if(!share_name(cnum, dev, inode, fname)) - return False; - - { - int old_umask; - unbecome_user(); - old_umask = umask(0); -#ifdef SECURE_SHARE_MODES - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600); -#else /* SECURE_SHARE_MODES */ - fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0644); -#endif /* SECURE_SHARE_MODES */ - umask(old_umask); - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("lock_share_entry: Can't become connected user!\n")); - close(fd); - return False; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("lock_share_entry: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - close(fd); - return False; - } - } - - /* At this point we have an open fd to the share mode file. - Lock the first byte exclusively to signify a lock. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - close(fd); - return False; - } - - *ptok = (share_lock_token)fd; - return True; -} - -/******************************************************************* - unlock a share mode file. - ******************************************************************/ -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token) -{ - int fd = (int)token; - int ret = True; - - /* token is the fd of the open share mode file. */ - /* Unlock the first byte. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n", - strerror(errno))); - ret = False; - } - - close((int)token); - return ret; -} - -/******************************************************************* -Force a share file to be deleted. -********************************************************************/ - -static int delete_share_file( int cnum, char *fname ) -{ - unbecome_user(); - if(unlink(fname) != 0) - { - DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n", - fname, strerror(errno))); - } - - DEBUG(5,("delete_share_file: Deleted share file %s\n", fname)); - - if(!become_user(cnum,Connections[cnum].vuid)) - { - DEBUG(0,("delete_share_file: Can't become connected user!\n")); - return -1; - } - /* We need to change directory back to the connection root. */ - if (ChDir(Connections[cnum].connectpath) != 0) - { - DEBUG(0,("delete_share_file: Can't change directory to %s (%s)\n", - Connections[cnum].connectpath, strerror(errno))); - return -1; - } - return 0; -} - -/******************************************************************* -Read a share file into a buffer. -********************************************************************/ - -static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file) -{ - struct stat sb; - char *buf; - int size; - - *out = 0; - *p_new_file = False; - - if(fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - fname, strerror(errno))); - return -1; - } - - if(sb.st_size == 0) - { - *p_new_file = True; - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc(sb.st_size)) == NULL) - { - DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size)); - return -1; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return -1; - } - - if (IVAL(buf,0) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= 10; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, 8); - - /* The remaining size must be a multiple of 16 - error if not. */ - if((size % 16) != 0) - { - DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - *out = buf; - return 0; -} - -/******************************************************************* -get all share mode entries in a share file for a dev/inode pair. -********************************************************************/ -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares) -{ - int fd = (int)token; - pstring fname; - int i; - int num_entries; - int num_entries_copied; - int newsize; - min_share_mode_entry *share_array; - char *buf = 0; - char *base = 0; - BOOL new_file; - - *old_shares = 0; - - /* Read the share file header - this is of the form: - 0 - locking version. - 4 - number of share mode entries. - 8 - 2 byte name length - [n bytes] file name (zero terminated). - - Followed by <n> share mode entries of the form : - - 0 - tv_sec - 4 - tv_usec - 8 - share_mode - 12 - pid - - */ - - share_name(cnum, dev, inode, fname); - - if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n", - fname)); - return 0; - } - - if(new_file == True) - return 0; - - num_entries = IVAL(buf,4); - - DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return 0; - } - - if(num_entries) - { - *old_shares = share_array = (min_share_mode_entry *) - malloc(num_entries * sizeof(min_share_mode_entry)); - if(*old_shares == 0) - { - DEBUG(0,("get_share_modes: malloc fail !\n")); - return 0; - } - } - else - { - /* No entries - just delete the file. */ - DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return 0; - } - - num_entries_copied = 0; - base = buf + 10 + SVAL(buf,8); - - for( i = 0; i < num_entries; i++) - { - int pid; - char *p = base + (i*16); - - pid = IVAL(p,12); - - if(!process_exists(pid)) - { - DEBUG(0,("get_share_modes: process %d no longer exists and \ -it left a share mode entry with mode 0x%X in share file %s\n", - pid, IVAL(p,8), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,0); - share_array[num_entries_copied].time.tv_usec = IVAL(p,4); - share_array[num_entries_copied].share_mode = IVAL(p,8); - share_array[num_entries_copied].pid = pid; - - num_entries_copied++; - } - - if(num_entries_copied == 0) - { - /* Delete the whole file. */ - DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n", - fname)); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - delete_share_file(cnum, fname); - return 0; - } - - /* If we deleted some entries we need to re-write the whole number of - share mode entries back into the file. */ - - if(num_entries_copied != num_entries) - { - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - - SIVAL(buf, 4, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*16); - - SIVAL(p,12,share_array[i].pid); - SIVAL(p,8,share_array[i].share_mode); - SIVAL(p,0,share_array[i].time.tv_sec); - SIVAL(p,4,share_array[i].time.tv_usec); - } - - newsize = (base - buf) + (16*num_entries_copied); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: get_share_modes: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize)!= 0) - { - DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(*old_shares) - free((char *)*old_shares); - *old_shares = 0; - if(buf) - free(buf); - return 0; - } - } - - if(buf) - free(buf); - - DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname, - num_entries_copied)); - - return num_entries_copied; -} - -/******************************************************************* -del a share mode from a share mode file. -********************************************************************/ -void del_share_mode(share_lock_token token, int fnum) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int newsize; - int i; - files_struct *fs_p = &Files[fnum]; - int pid; - BOOL deleted = False; - BOOL new_file; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0) - { - DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n", - fname)); - return; - } - - if(new_file == True) - { - DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n", - fname)); - delete_share_file(fs_p->cnum, fname); - return; - } - - num_entries = IVAL(buf,4); - - DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - delete it. - */ - - base = buf + 10 + SVAL(buf,8); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*16); - - if((IVAL(p,0) != fs_p->open_time.tv_sec) || (IVAL(p,4) != fs_p->open_time.tv_usec) || - (IVAL(p,8) != fs_p->share_mode) || (IVAL(p,12) != pid)) - continue; - - DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n", - i, num_entries, fname)); - - /* Remove this entry. */ - if(i != num_entries - 1) - memcpy(p, p + 16, (num_entries - i - 1)*16); - - deleted = True; - break; - } - - if(!deleted) - { - DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return; - } - - num_entries--; - SIVAL(buf,4, num_entries); - - if(num_entries == 0) - { - /* Deleted the last entry - remove the file. */ - DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum,fname); - return; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - - newsize = (base - buf) + (16*num_entries); - if(write(fd, buf, newsize) != newsize) - { - DEBUG(0,("ERROR: del_share_mode: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return; - } - /* Now truncate the file at this point. */ - if(ftruncate(fd, newsize) != 0) - { - DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, newsize, strerror(errno))); - if(buf) - free(buf); - return; - } -} - -/******************************************************************* -set the share mode of a file -********************************************************************/ -BOOL set_share_mode(share_lock_token token,int fnum) -{ - files_struct *fs_p = &Files[fnum]; - pstring fname; - int fd = (int)token; - int pid = (int)getpid(); - struct stat sb; - char *buf; - int num_entries; - int header_size; - char *p; - - share_name(fs_p->cnum, fs_p->fd_ptr->dev, - fs_p->fd_ptr->inode, fname); - - if(fstat(fd, &sb) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n", - fname)); - return False; - } - - /* Sanity check for file contents (if it's not a new share file). */ - if(sb.st_size != 0) - { - int size = sb.st_size; - - /* Allocate space for the file plus one extra entry */ - if((buf = (char *)malloc(sb.st_size + 16)) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb.st_size + 16)); - return False; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: Failed to reset position \ -to 0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n", - fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (IVAL(buf,0) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - size -= (10 + SVAL(buf, 8)); /* Remove the header */ - - /* The remaining size must be a multiple of 16 - error if not. */ - if((size % 16) != 0) - { - DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \ -deleting it.\n", fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - } - else - { - /* New file - just use a single_entry. */ - if((buf = (char *)malloc(10 + strlen(fs_p->name) + 1 + 16)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,0,LOCKING_VERSION); - SIVAL(buf,4,0); - SSVAL(buf,8,strlen(fs_p->name) + 1); - strcpy(buf + 10, fs_p->name); - } - - num_entries = IVAL(buf,4); - header_size = 10 + SVAL(buf,8); - p = buf + header_size + (num_entries * 16); - SIVAL(p,0,fs_p->open_time.tv_sec); - SIVAL(p,4,fs_p->open_time.tv_usec); - SIVAL(p,8,fs_p->share_mode); - SIVAL(p,12,pid); - - num_entries++; - - SIVAL(buf,4,num_entries); - - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \ -0 for share file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - if (write(fd,buf,header_size + (num_entries*16)) != (header_size + (num_entries*16))) - { - DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \ -deleting it (%s).\n",fname, strerror(errno))); - delete_share_file(fs_p->cnum, fname); - if(buf) - free(buf); - return False; - } - - /* Now truncate the file at this point - just for safety. */ - if(ftruncate(fd, header_size + (16*num_entries))!= 0) - { - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (16*num_entries), strerror(errno))); - if(buf) - free(buf); - return False; - } - - if(buf) - free(buf); - - DEBUG(3,("set_share_mode: Created share file %s with \ -mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid)); - - return True; -} -#endif /* FAST_SHARE_MODES */ diff --git a/source/locking/shmem.c b/source/locking/shmem.c deleted file mode 100644 index f3f84ec8c36..00000000000 --- a/source/locking/shmem.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Shared memory functions - Copyright (C) Erik Devriendt 1996-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - - -#ifdef FAST_SHARE_MODES - - -extern int DEBUGLEVEL; - - -#define SMB_SHM_MAGIC 0x53484100 -/* = "SHM" in hex */ - -#define SMB_SHM_VERSION 2 - -/* WARNING : offsets are used because mmap() does not guarantee that all processes have the - shared memory mapped to the same address */ - -struct SmbShmHeader -{ - int smb_shm_magic; - int smb_shm_version; - int total_size; /* in bytes */ - BOOL consistent; - smb_shm_offset_t first_free_off; - smb_shm_offset_t userdef_off; /* a userdefined offset. can be used to store root of tree or list */ - struct { /* a cell is a range of bytes of sizeof(struct SmbShmBlockDesc) size */ - int cells_free; - int cells_used; - int cells_system; /* number of cells used as allocated block descriptors */ - } statistics; -}; - -#define SMB_SHM_NOT_FREE_OFF (-1) -struct SmbShmBlockDesc -{ - smb_shm_offset_t next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */ - int size; /* user size in BlockDescSize units */ -}; - -#define EOList_Addr (struct SmbShmBlockDesc *)( 0 ) -#define EOList_Off (NULL_OFFSET) - -#define CellSize sizeof(struct SmbShmBlockDesc) - -/* HeaderSize aligned on 8 byte boundary */ -#define AlignedHeaderSize ((sizeof(struct SmbShmHeader)+7) & ~7) - -static int smb_shm_fd = -1; -static pstring smb_shm_processreg_name = ""; - -static struct SmbShmHeader *smb_shm_header_p = (struct SmbShmHeader *)0; -static int smb_shm_times_locked = 0; - -static BOOL smb_shm_initialize_called = False; - -static BOOL smb_shm_global_lock(void) -{ - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_global_lock : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - smb_shm_times_locked++; - - if(smb_shm_times_locked > 1) - { - DEBUG(5,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked)); - return True; - } - - /* Do an exclusive wait lock on the first byte of the file */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %d\n",errno)); - smb_shm_times_locked--; - return False; - } - - return True; - -} - -static BOOL smb_shm_global_unlock(void) -{ - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_global_unlock : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - if(smb_shm_times_locked == 0) - { - DEBUG(0,("ERROR smb_shm_global_unlock : shmem not locked\n",smb_shm_fd)); - return False; - } - - smb_shm_times_locked--; - - if(smb_shm_times_locked > 0) - { - DEBUG(5,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked)); - return True; - } - - /* Do a wait unlock on the first byte of the file */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False) - { - DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %d\n",errno)); - smb_shm_times_locked++; - return False; - } - - return True; - -} - -/* - * Function to create the hash table for the share mode entries. Called - * when smb shared memory is global locked. - */ - -BOOL smb_shm_create_hash_table( unsigned int size ) -{ - size *= sizeof(smb_shm_offset_t); - - smb_shm_global_lock(); - smb_shm_header_p->userdef_off = smb_shm_alloc( size ); - - if(smb_shm_header_p->userdef_off == NULL_OFFSET) - { - DEBUG(0,("smb_shm_create_hash_table: Failed to create hash table of size %d\n",size)); - smb_shm_global_unlock(); - return False; - } - - /* Clear hash buckets. */ - memset( smb_shm_offset2addr(smb_shm_header_p->userdef_off), '\0', size); - smb_shm_global_unlock(); - return True; -} - -static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *other_processes) -{ - int smb_shm_processes_fd = -1; - int nb_read; - pid_t other_pid; - int seek_back = -sizeof(other_pid); - int free_slot = -1; - int erased_slot; - -#ifndef SECURE_SHARE_MODES - smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666); -#else /* SECURE_SHARE_MODES */ - smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0600); -#endif /* SECURE_SHARE_MODES */ - if ( smb_shm_processes_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %d\n",errno)); - return False; - } - - *other_processes = False; - - while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) - { - if(other_pid) - { - if(process_exists(other_pid)) - *other_processes = True; - else - { - /* erase old pid */ - DEBUG(5,("smb_shm_register_process : erasing stale record for pid %d (seek_back = %d)\n", - other_pid, seek_back)); - other_pid = (pid_t)0; - erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); - write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)); - if(free_slot < 0) - free_slot = erased_slot; - } - } - else - if(free_slot < 0) - free_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); - } - if (nb_read < 0) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %d\n",errno)); - close(smb_shm_processes_fd); - return False; - } - - if(free_slot < 0) - free_slot = lseek(smb_shm_processes_fd, 0, SEEK_END); - - DEBUG(5,("smb_shm_register_process : writing record for pid %d at offset %d\n",pid,free_slot)); - lseek(smb_shm_processes_fd, free_slot, SEEK_SET); - if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0) - { - DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %d\n",errno)); - close(smb_shm_processes_fd); - return False; - } - - close(smb_shm_processes_fd); - - return True; -} - -static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid) -{ - int old_umask; - int smb_shm_processes_fd = -1; - int nb_read; - pid_t other_pid; - int seek_back = -sizeof(other_pid); - int erased_slot; - BOOL found = False; - - - old_umask = umask(0); - smb_shm_processes_fd = open(processreg_file, O_RDWR); - umask(old_umask); - if ( smb_shm_processes_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %d\n",errno)); - return False; - } - - while ((nb_read = read(smb_shm_processes_fd, &other_pid, sizeof(other_pid))) > 0) - { - DEBUG(5,("smb_shm_unregister_process : read record for pid %d\n",other_pid)); - if(other_pid == pid) - { - /* erase pid */ - DEBUG(5,("smb_shm_unregister_process : erasing record for pid %d (seek_val = %d)\n", - other_pid, seek_back)); - other_pid = (pid_t)0; - erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR); - if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %d\n",errno)); - close(smb_shm_processes_fd); - return False; - } - - found = True; - break; - } - } - if (nb_read < 0) - { - DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %d\n",errno)); - close(smb_shm_processes_fd); - return False; - } - - if(!found) - { - DEBUG(0,("ERROR smb_shm_unregister_process : couldn't find pid %d in file %s\n",pid,processreg_file)); - close(smb_shm_processes_fd); - return False; - } - - - close(smb_shm_processes_fd); - - return True; -} - - -static BOOL smb_shm_validate_header(int size) -{ - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_validate_header : shmem not mapped\n")); - return False; - } - - if(smb_shm_header_p->smb_shm_magic != SMB_SHM_MAGIC) - { - DEBUG(0,("ERROR smb_shm_validate_header : bad magic\n")); - return False; - } - if(smb_shm_header_p->smb_shm_version != SMB_SHM_VERSION) - { - DEBUG(0,("ERROR smb_shm_validate_header : bad version %X\n",smb_shm_header_p->smb_shm_version)); - return False; - } - - if(smb_shm_header_p->total_size != size) - { - DEBUG(0,("ERROR smb_shm_validate_header : shmem size mismatch (old = %d, new = %d)\n",smb_shm_header_p->total_size,size)); - return False; - } - - if(!smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_validate_header : shmem not consistent\n")); - return False; - } - return True; -} - -static BOOL smb_shm_initialize(int size) -{ - struct SmbShmBlockDesc * first_free_block_p; - - DEBUG(5,("smb_shm_initialize : initializing shmem file of size %d\n",size)); - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_initialize : shmem not mapped\n")); - return False; - } - - smb_shm_header_p->smb_shm_magic = SMB_SHM_MAGIC; - smb_shm_header_p->smb_shm_version = SMB_SHM_VERSION; - smb_shm_header_p->total_size = size; - smb_shm_header_p->first_free_off = AlignedHeaderSize; - smb_shm_header_p->userdef_off = NULL_OFFSET; - - first_free_block_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - first_free_block_p->next = EOList_Off; - first_free_block_p->size = ( size - AlignedHeaderSize - CellSize ) / CellSize ; - - smb_shm_header_p->statistics.cells_free = first_free_block_p->size; - smb_shm_header_p->statistics.cells_used = 0; - smb_shm_header_p->statistics.cells_system = 1; - - smb_shm_header_p->consistent = True; - - smb_shm_initialize_called = True; - - return True; -} - -static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p ) -{ - struct SmbShmBlockDesc *next_p; - - /* Check if head_p and head_p->next are neighbors and if so join them */ - if ( head_p == EOList_Addr ) return ; - if ( head_p->next == EOList_Off ) return ; - - next_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(head_p->next); - if ( ( head_p + head_p->size + 1 ) == next_p) - { - head_p->size += next_p->size +1 ; /* adapt size */ - head_p->next = next_p->next ; /* link out */ - - smb_shm_header_p->statistics.cells_free += 1; - smb_shm_header_p->statistics.cells_system -= 1; - } -} - - - -BOOL smb_shm_open( char *file_name, int size) -{ - int filesize; - BOOL created_new = False; - BOOL other_processes = True; - int old_umask; - - DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size)); - - old_umask = umask(0); -#ifndef SECURE_SHARE_MODES - smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0666); -#else /* SECURE_SHARE_MODES */ - smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0600); -#endif /* SECURE_SHARE_MODE */ - umask(old_umask); - if ( smb_shm_fd < 0 ) - { - DEBUG(0,("ERROR smb_shm_open : open failed with code %d\n",errno)); - return False; - } - - if (!smb_shm_global_lock()) - { - DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n")); - return False; - } - - if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0) - { - DEBUG(0,("ERROR smb_shm_open : lseek failed with code %d\n",errno)); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - /* return the file offset to 0 to save on later seeks */ - lseek(smb_shm_fd,0,SEEK_SET); - - if (filesize == 0) - { - /* we just created a new one */ - created_new = True; - } - - /* to find out if some other process is already mapping the file, - we use a registration file containing the processids of the file mapping processes - */ - - /* construct processreg file name */ - strcpy(smb_shm_processreg_name, file_name); - strcat(smb_shm_processreg_name, ".processes"); - - if (! smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes)) - { - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - if (created_new || !other_processes) - { - /* we just created a new one, or are the first opener, lets set it size */ - if( ftruncate(smb_shm_fd, size) <0) - { - DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %d\n",errno)); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - /* paranoia */ - lseek(smb_shm_fd,0,SEEK_SET); - - filesize = size; - } - - if (size != filesize ) - { - /* the existing file has a different size and we are not the first opener. - Since another process is still using it, we will use the file size */ - DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size)); - size = filesize; - } - - smb_shm_header_p = (struct SmbShmHeader *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, smb_shm_fd, 0); - /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */ - if (smb_shm_header_p == (struct SmbShmHeader *)(-1)) - { - DEBUG(0,("ERROR smb_shm_open : mmap failed with code %d\n",errno)); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - - if (created_new || !other_processes) - { - smb_shm_initialize(size); - /* Create the hash buckets for the share file entries. */ - smb_shm_create_hash_table( lp_shmem_hash_size() ); - } - else if (!smb_shm_validate_header(size) ) - { - /* existing file is corrupt, samba admin should remove it by hand */ - DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n")); - munmap((caddr_t)smb_shm_header_p, size); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - close(smb_shm_fd); - return False; - } - - smb_shm_global_unlock(); - return True; - -} - - -BOOL smb_shm_close( void ) -{ - - if(smb_shm_initialize_called == False) - return True; - - DEBUG(5,("smb_shm_close\n")); - if(smb_shm_times_locked > 0) - DEBUG(0,("WARNING smb_shm_close : shmem was still locked %d times\n",smb_shm_times_locked));; - if ((smb_shm_header_p != NULL) && - (munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0)) - { - DEBUG(0,("ERROR smb_shm_close : munmap failed with code %d\n",errno)); - } - - smb_shm_global_lock(); - DEBUG(5,("calling smb_shm_unregister_process(%s, %d)\n", smb_shm_processreg_name, getpid())); - smb_shm_unregister_process(smb_shm_processreg_name, getpid()); - smb_shm_global_unlock(); - - close(smb_shm_fd); - - smb_shm_fd = -1; - smb_shm_processreg_name[0] = '\0'; - - smb_shm_header_p = (struct SmbShmHeader *)0; - smb_shm_times_locked = 0; - - return True; -} - -smb_shm_offset_t smb_shm_alloc(int size) -{ - unsigned num_cells ; - struct SmbShmBlockDesc *scanner_p; - struct SmbShmBlockDesc *prev_p; - struct SmbShmBlockDesc *new_p; - smb_shm_offset_t result_offset; - - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n")); - return NULL_OFFSET; - } - - smb_shm_global_lock(); - - if( !smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n")); - smb_shm_global_unlock(); - return NULL_OFFSET; - } - - - /* calculate the number of cells */ - num_cells = (size + CellSize -1) / CellSize; - - /* set start of scan */ - prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - scanner_p = prev_p ; - - /* scan the free list to find a matching free space */ - while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) ) - { - prev_p = scanner_p; - scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); - } - - /* at this point scanner point to a block header or to the end of the list */ - if ( scanner_p == EOList_Addr ) - { - DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size)); - smb_shm_global_unlock(); - return (NULL_OFFSET); - } - - /* going to modify shared mem */ - smb_shm_header_p->consistent = False; - - /* if we found a good one : scanner == the good one */ - if ( scanner_p->size <= num_cells + 2 ) - { - /* there is no use in making a new one, it will be too small anyway - * we will link out scanner - */ - if ( prev_p == scanner_p ) - { - smb_shm_header_p->first_free_off = scanner_p->next ; - } - else - { - prev_p->next = scanner_p->next ; - } - smb_shm_header_p->statistics.cells_free -= scanner_p->size; - smb_shm_header_p->statistics.cells_used += scanner_p->size; - } - else - { - /* Make a new one */ - new_p = scanner_p + 1 + num_cells; - new_p->size = scanner_p->size - num_cells - 1; - new_p->next = scanner_p->next; - scanner_p->size = num_cells; - scanner_p->next = smb_shm_addr2offset(new_p); - - if ( prev_p != scanner_p ) - { - prev_p->next = smb_shm_addr2offset(new_p) ; - } - else - { - smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ; - } - smb_shm_header_p->statistics.cells_free -= num_cells+1; - smb_shm_header_p->statistics.cells_used += num_cells; - smb_shm_header_p->statistics.cells_system += 1; - } - - result_offset = smb_shm_addr2offset( &(scanner_p[1]) ); - scanner_p->next = SMB_SHM_NOT_FREE_OFF ; - - /* end modification of shared mem */ - smb_shm_header_p->consistent = True; - - DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset )); - - smb_shm_global_unlock(); - return ( result_offset ); -} - - - -BOOL smb_shm_free(smb_shm_offset_t offset) -{ - struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */ - struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */ - struct SmbShmBlockDesc *prev_p ; /* holds previous in the list */ - - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n")); - return False; - } - - smb_shm_global_lock(); - - if( !smb_shm_header_p->consistent) - { - DEBUG(0,("ERROR smb_shm_free : shmem not consistent\n")); - smb_shm_global_unlock(); - return False; - } - - header_p = ( (struct SmbShmBlockDesc *)smb_shm_offset2addr(offset) - 1); /* make pointer to header of block */ - - if (header_p->next != SMB_SHM_NOT_FREE_OFF) - { - DEBUG(0,("ERROR smb_shm_free : bad offset (%d)\n",offset)); - smb_shm_global_unlock(); - return False; - } - - /* find a place in the free_list to put the header in */ - - /* set scanner and previous pointer to start of list */ - prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off); - scanner_p = prev_p ; - - while ( ( scanner_p != EOList_Addr) && (scanner_p < header_p) ) /* while we didn't scan past its position */ - { - prev_p = scanner_p ; - scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next); - } - - smb_shm_header_p->consistent = False; - - DEBUG(6,("smb_shm_free : freeing %d bytes at offset %d\n",header_p->size*CellSize,offset)); - - if ( scanner_p == prev_p ) - { - smb_shm_header_p->statistics.cells_free += header_p->size; - smb_shm_header_p->statistics.cells_used -= header_p->size; - - /* we must free it at the beginning of the list */ - smb_shm_header_p->first_free_off = smb_shm_addr2offset(header_p); /* set the free_list_pointer to this block_header */ - - /* scanner is the one that was first in the list */ - header_p->next = smb_shm_addr2offset(scanner_p); - smb_shm_solve_neighbors( header_p ); /* if neighbors then link them */ - - smb_shm_header_p->consistent = True; - smb_shm_global_unlock(); - return True; - } - else - { - smb_shm_header_p->statistics.cells_free += header_p->size; - smb_shm_header_p->statistics.cells_used -= header_p->size; - - prev_p->next = smb_shm_addr2offset(header_p); - header_p->next = smb_shm_addr2offset(scanner_p); - smb_shm_solve_neighbors(header_p) ; - smb_shm_solve_neighbors(prev_p) ; - - smb_shm_header_p->consistent = True; - smb_shm_global_unlock(); - return True; - } -} - -smb_shm_offset_t smb_shm_get_userdef_off(void) -{ - if (!smb_shm_header_p) - return NULL_OFFSET; - else - return smb_shm_header_p->userdef_off; -} - -BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off) -{ - if (!smb_shm_header_p) - return False; - else - smb_shm_header_p->userdef_off = userdef_off; - return True; -} - -void * smb_shm_offset2addr(smb_shm_offset_t offset) -{ - if (offset == NULL_OFFSET ) - return (void *)(0); - - if (!smb_shm_header_p) - return (void *)(0); - - return (void *)((char *)smb_shm_header_p + offset ); -} - -smb_shm_offset_t smb_shm_addr2offset(void *addr) -{ - if (!addr) - return NULL_OFFSET; - - if (!smb_shm_header_p) - return NULL_OFFSET; - - return (smb_shm_offset_t)((char *)addr - (char *)smb_shm_header_p); -} - -/******************************************************************* - Lock a particular hash bucket entry. - ******************************************************************/ - -BOOL smb_shm_lock_hash_entry( unsigned int entry) -{ - int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t))); - - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - if(entry >= lp_shmem_hash_size()) - { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : hash entry size too big (%d)\n", entry)); - return False; - } - - /* Do an exclusive wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_WRLCK) == False) - { - DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %d\n",errno)); - return False; - } - - DEBUG(9,("smb_shm_lock_hash_entry: locked hash bucket %d\n", entry)); - return True; -} - -/******************************************************************* - Unlock a particular hash bucket entry. - ******************************************************************/ - -BOOL smb_shm_unlock_hash_entry( unsigned int entry ) -{ - int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t))); - - if (smb_shm_fd < 0) - { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : bad smb_shm_fd (%d)\n",smb_shm_fd)); - return False; - } - - if(entry >= lp_shmem_hash_size()) - { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : hash entry size too big (%d)\n", entry)); - return False; - } - - /* Do a wait lock on the 4 byte region mapping into this entry */ - if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_UNLCK) == False) - { - DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %d\n",errno)); - return False; - } - - DEBUG(9,("smb_shm_unlock_hash_entry: unlocked hash bucket %d\n", entry)); - return True; -} - -/******************************************************************* - Gather statistics on shared memory usage. - ******************************************************************/ - -BOOL smb_shm_get_usage(int *bytes_free, - int *bytes_used, - int *bytes_overhead) -{ - if( !smb_shm_header_p ) - { - /* not mapped yet */ - DEBUG(0,("ERROR smb_shm_free : shmem not mapped\n")); - return False; - } - *bytes_free = smb_shm_header_p->statistics.cells_free * CellSize; - *bytes_used = smb_shm_header_p->statistics.cells_used * CellSize; - *bytes_overhead = smb_shm_header_p->statistics.cells_system * CellSize + AlignedHeaderSize; - - return True; -} - -#else /* FAST_SHARE_MODES */ - int shmem_dummy_procedure(void) -{return 0;} -#endif /* FAST_SHARE_MODES */ diff --git a/source/md4.h b/source/md4.h deleted file mode 100644 index 3f60d75fe3c..00000000000 --- a/source/md4.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - This code is from rfc1186. -*/ - - /* - ** ******************************************************************** - ** md4.h -- Header file for implementation of ** - ** MD4 Message Digest Algorithm ** - ** Updated: 2/13/90 by Ronald L. Rivest ** - ** (C) 1990 RSA Data Security, Inc. ** - ** ******************************************************************** - */ - - /* MDstruct is the data structure for a message digest computation. - */ - typedef struct { - unsigned int buffer[4]; /* Holds 4-word result of MD computation */ - unsigned char count[8]; /* Number of bits processed so far */ - unsigned int done; /* Nonzero means MD computation finished */ - } MDstruct, *MDptr; - - /* MDbegin(MD) - - - - ** Input: MD -- an MDptr - ** Initialize the MDstruct prepatory to doing a message digest - ** computation. - */ - extern void MDbegin(); - - /* MDupdate(MD,X,count) - ** Input: MD -- an MDptr - ** X -- a pointer to an array of unsigned characters. - ** count -- the number of bits of X to use (an unsigned int). - ** Updates MD using the first "count" bits of X. - ** The array pointed to by X is not modified. - ** If count is not a multiple of 8, MDupdate uses high bits of - ** last byte. - ** This is the basic input routine for a user. - ** The routine terminates the MD computation when count < 512, so - ** every MD computation should end with one call to MDupdate with a - ** count less than 512. Zero is OK for a count. - */ - extern void MDupdate(); - - /* MDprint(MD) - ** Input: MD -- an MDptr - ** Prints message digest buffer MD as 32 hexadecimal digits. - ** Order is from low-order byte of buffer[0] to high-order byte - ** of buffer[3]. - ** Each byte is printed with high-order hexadecimal digit first. - */ - extern void MDprint(); - - /* - ** End of md4.h - */ diff --git a/source/nameannounce.c b/source/nameannounce.c deleted file mode 100644 index 6e7e445e4b1..00000000000 --- a/source/nameannounce.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - -*/ - -#include "includes.h" - -#define TEST_CODE - -extern int DEBUGLEVEL; -extern BOOL CanRecurse; - -extern struct in_addr ipzero; - -extern pstring myname; -extern fstring myworkgroup; - -extern int ClientDGRAM; -extern int ClientNMB; - -/* this is our domain/workgroup/server database */ -extern struct subnet_record *subnetlist; - -extern int updatecount; -extern int workgroup_count; - -extern struct in_addr wins_ip; - -extern pstring scope; - -/**************************************************************************** - send a announce request to the local net - **************************************************************************/ -void announce_request(struct work_record *work, struct in_addr ip) -{ - pstring outbuf; - char *p; - - if (!work) return; - - work->needannounce = True; - - DEBUG(2,("sending announce request to %s for workgroup %s\n", - inet_ntoa(ip),work->work_group)); - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - CVAL(p,0) = ANN_AnnouncementRequest; - p++; - - CVAL(p,0) = work->token; /* (local) unique workgroup token id */ - p++; - StrnCpy(p,myname,16); - strupper(p); - p = skip_string(p,1); - - /* XXXX note: if we sent the announcement request to 0x1d instead - of 0x1e, then we could get the master browser to announce to - us instead of the members of the workgroup. wha-hey! */ - - send_mailslot_reply(False, BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip)); -} - - -/**************************************************************************** - request an announcement - **************************************************************************/ -void do_announce_request(char *info, char *to_name, int announce_type, - int from, - int to, struct in_addr dest_ip) -{ - pstring outbuf; - char *p; - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - CVAL(p,0) = announce_type; - p++; - - DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n", - announce_type, info, inet_ntoa(dest_ip),to_name,to)); - - StrnCpy(p,info,16); - strupper(p); - p = skip_string(p,1); - - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - myname,to_name,from,to,dest_ip,*iface_ip(dest_ip)); -} - - -/**************************************************************************** - find a server responsible for a workgroup, and sync browse lists - control ends up back here via response_name_query. - **************************************************************************/ -void sync_server(enum state_type state, char *serv_name, char *work_name, - int name_type, - struct subnet_record *d, - struct in_addr ip) -{ - /* with a domain master we can get the whole list (not local only list) */ - BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK); - - add_browser_entry(serv_name, name_type, work_name, 0, d, ip, local_only); - - if (state == NAME_STATUS_DOM_SRV_CHK) - { - /* announce ourselves as a master browser to serv_name */ - do_announce_request(myname, serv_name, ANN_MasterAnnouncement, - 0x20, 0, ip); - } -} - - -/**************************************************************************** - send a host announcement packet - **************************************************************************/ -void do_announce_host(int command, - char *from_name, int from_type, struct in_addr from_ip, - char *to_name , int to_type , struct in_addr to_ip, - time_t announce_interval, - char *server_name, int server_type, char *server_comment) -{ - pstring outbuf; - char *p; - - bzero(outbuf,sizeof(outbuf)); - p = outbuf+1; - - /* command type */ - CVAL(outbuf,0) = command; - - /* announcement parameters */ - CVAL(p,0) = updatecount; - SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ - - StrnCpy(p+5,server_name,16); - strupper(p+5); - - CVAL(p,21) = MAJOR_VERSION; /* major version */ - CVAL(p,22) = MINOR_VERSION; /* minor version */ - - SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - /* browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT)*/ - SSVAL(p,27,BROWSER_ELECTION_VERSION); - SSVAL(p,29,BROWSER_CONSTANT); /* browse signature */ - - strcpy(p+31,server_comment); - p += 31; - p = skip_string(p,1); - - debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); - - /* send the announcement */ - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - from_name, to_name, - from_type, to_type, - to_ip, from_ip); -} - - -/**************************************************************************** -announce all samba's server entries as 'gone'. -****************************************************************************/ -void announce_my_servers_removed(void) -{ - struct subnet_record *d; - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - if (!strequal(myname,s->serv.name)) continue; - announce_server(d, work, s->serv.name, s->serv.comment, 0, 0); - } - } - } -} - - -/**************************************************************************** - announce a server entry - ****************************************************************************/ -void announce_server(struct subnet_record *d, struct work_record *work, - char *name, char *comment, time_t ttl, int server_type) -{ - /* domain type cannot have anything in it that might confuse - a client into thinking that the domain is in fact a server. - (SV_TYPE_SERVER_UNIX, for example) - */ - uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; - BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip); - - if (wins_iface && server_type != 0) - { - /* wins pseudo-ip interface */ - if (!AM_MASTER(work)) - { - /* non-master announce by unicast to the domain - master */ - if (!lp_wins_support() && *lp_wins_server()) - { - /* look up the domain master with the WINS server */ - queue_netbios_pkt_wins(ClientNMB,NMB_QUERY, - NAME_QUERY_ANNOUNCE_HOST, - work->work_group,0x1b,0,ttl*1000, - server_type,name,comment, - False, True, ipzero, d->bcast_ip); - } - else - { - /* we are the WINS server, but not the domain master. */ - /* XXXX we need to look up the domain master in our - WINS database list, and do_announce_host(). maybe - we could do a name query on the unsuspecting domain - master just to make sure it's awake. */ - } - } - - /* XXXX any other kinds of announcements we need to consider here? - e.g local master browsers... no. local master browsers do - local master announcements to their domain master. they even - use WINS lookup of the domain master if another wins server - is being used! - */ - } - else - { - if (AM_MASTER(work)) - { - DEBUG(3,("sending local master announce to %s for %s(1e)\n", - inet_ntoa(d->bcast_ip),work->work_group)); - - do_announce_host(ANN_LocalMasterAnnouncement, - name , 0x00, d->myip, - work->work_group, 0x1e, d->bcast_ip, - ttl, - name, server_type, comment); - - DEBUG(3,("sending domain announce to %s for %s\n", - inet_ntoa(d->bcast_ip),work->work_group)); - - /* XXXX should we do a domain-announce-kill? */ - if (server_type != 0) - { - do_announce_host(ANN_DomainAnnouncement, - name , 0x00, d->myip, - MSBROWSE, 0x01, d->bcast_ip, - ttl, - work->work_group, server_type ? domain_type : 0, - name); - } - } - else - { - DEBUG(3,("sending host announce to %s for %s(1d)\n", - inet_ntoa(d->bcast_ip),work->work_group)); - - do_announce_host(ANN_HostAnnouncement, - name , 0x00, d->myip, - work->work_group, 0x1d, d->bcast_ip, - ttl, - name, server_type, comment); - } - } -} - -/**************************************************************************** - construct a host announcement unicast - **************************************************************************/ -void announce_host(time_t t) -{ - struct subnet_record *d; - pstring comment; - char *my_name; - - StrnCpy(comment, lp_serverstring(), 43); - - my_name = *myname ? myname : "NoName"; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) - { - uint32 stype = work->ServerType; - struct server_record *s; - BOOL announce = False; - - /* must work on the code that does announcements at up to - 30 seconds later if a master browser sends us a request - announce. - */ - - if (work->needannounce) { - /* drop back to a max 3 minute announce - this is to prevent a - single lost packet from stuffing things up for too long */ - work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); - work->lastannounce_time = t - (work->announce_interval+1); - } - - /* announce every minute at first then progress to every 12 mins */ - if (work->lastannounce_time && - (t - work->lastannounce_time) < work->announce_interval) - continue; - - if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) - work->announce_interval += 60; - - work->lastannounce_time = t; - - for (s = work->serverlist; s; s = s->next) { - if (strequal(myname, s->serv.name)) { - announce = True; - break; - } - } - - if (announce) { - announce_server(d,work,my_name,comment, - work->announce_interval,stype); - } - - if (work->needannounce) - { - work->needannounce = False; - break; - /* sorry: can't do too many announces. do some more later */ - } - } - } -} - -/* Announce timer. Moved into global static so it can be reset - when a machine becomes a master browser. */ -static time_t announce_timer_last=0; - -/**************************************************************************** - Reset the announce_timer so that a master browser announce will be done - immediately. - ****************************************************************************/ - -void reset_announce_timer() -{ - announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60); -} - -/**************************************************************************** - announce myself as a master to all other domain master browsers. - - this actually gets done in search_and_sync_workgroups() via the - NAME_QUERY_DOM_SRV_CHK command, if there is a response from the - name query initiated here. see response_name_query() - **************************************************************************/ -void announce_master(time_t t) -{ - struct subnet_record *d; - struct work_record *work; - BOOL am_master = False; /* are we a master of some sort? :-) */ - - if (!announce_timer_last) announce_timer_last = t; - if (t-announce_timer_last < CHECK_TIME_MST_ANNOUNCE * 60) - { - DEBUG(10,("announce_master: t (%d) - last(%d) < %d\n", - t, announce_timer_last, CHECK_TIME_MST_ANNOUNCE * 60 )); - return; - } - - if(wins_subnet == NULL) - { - DEBUG(10,("announce_master: no wins subnet, ignoring.\n")); - return; - } - - announce_timer_last = t; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - am_master = True; - DEBUG(4,( "announce_master: am_master = %d for \ -workgroup %s\n", am_master, work->work_group)); - } - } - } - - if (!am_master) return; /* only proceed if we are a master browser */ - - /* Note that we don't do this if we are domain master browser - and that we *only* do this on the WINS subnet. */ - - /* Try and find our workgroup on the WINS subnet */ - work = find_workgroupstruct(wins_subnet, myworkgroup, False); - - if (work) - { - char *name; - int type; - -#if 0 /* I don't think this option should be used for this purpose. - JRA. - */ - if (*lp_domain_controller()) - { - /* the domain controller option is used to manually specify - the domain master browser to sync with - */ - - /* XXXX i'm not sure we should be using the domain controller - option for this purpose. - */ - - name = lp_domain_controller(); - type = 0x20; - } - else -#endif /* REMOVE SUSPECT CODE. */ - { - /* assume that the domain master browser we want to sync - with is our own domain. - */ - name = work->work_group; - type = 0x1b; - } - - /* check the existence of a dmb for this workgroup, and if - one exists at the specified ip, sync with it and announce - ourselves as a master browser to it - */ - - if (!lp_wins_support() && *lp_wins_server() ) - { - DEBUG(4, ("Local Announce: find %s<%02x> from WINS server %s\n", - name, type, lp_wins_server())); - - queue_netbios_pkt_wins(ClientNMB, - NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, - name, type, 0,0,0, - work->work_group,NULL, - False, True, ipzero, ipzero); - } - else if(lp_wins_support()) - { - /* We are the WINS server - query ourselves for the dmb name. */ - - struct nmb_name netb_name; - struct subnet_record *d = 0; - struct name_record *nr = 0; - - make_nmb_name(&netb_name, name, type, scope); - - if ((nr = find_name_search(&d, &netb_name, FIND_WINS, ipzero)) == 0) - { - DEBUG(0, ("announce_master: unable to find domain master browser for workgroup %s \ -in our own WINS database.\n", work->work_group)); - return; - } - - /* Check that this isn't one of our addresses (ie. we are not domain master - ourselves) */ - if(ismyip(nr->ip_flgs[0].ip) || ip_equal(nr->ip_flgs[0].ip, ipzero)) - { - DEBUG(4, ("announce_master: domain master ip found (%s) for workgroup %s \ -is one of our interfaces.\n", work->work_group, inet_ntoa(nr->ip_flgs[0].ip) )); - return; - } - - /* Issue a NAME_STATUS_DOM_SRV_CHK immediately - short circuit the - NAME_QUERY_DOM_SRV_CHK which is done only if we are talking to a - remote WINS server. */ - - DEBUG(4, ("announce_master: doing name status for %s<%02x> to domain master ip %s \ -for workgroup %s\n", name, type, inet_ntoa(nr->ip_flgs[0].ip), work->work_group )); - - queue_netbios_packet(wins_subnet, ClientNMB, - NMB_QUERY,NAME_STATUS_DOM_SRV_CHK, - name, type, 0,0,0, - work->work_group,NULL, - False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip); - } - - } -} - -/**************************************************************************** - do all the "remote" announcements. These are used to put ourselves - on a remote browse list. They are done blind, no checking is done to - see if there is actually a browse master at the other end. - **************************************************************************/ -void announce_remote(time_t t) -{ - char *s,*ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - char *comment,*workgroup; - int stype = DFLT_SERVER_TYPE; - - if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL) - return; - - last_time = t; - - s = lp_remote_announce(); - if (!*s) return; - - comment = lp_serverstring(); - workgroup = myworkgroup; - - for (ptr=s; next_token(&ptr,s2,NULL); ) { - /* the entries are of the form a.b.c.d/WORKGROUP with - WORKGROUP being optional */ - char *wgroup; - - wgroup = strchr(s2,'/'); - if (wgroup) *wgroup++ = 0; - if (!wgroup || !*wgroup) - wgroup = workgroup; - - addr = *interpret_addr2(s2); - - do_announce_host(ANN_HostAnnouncement,myname,0x20,*iface_ip(addr), - wgroup,0x1e,addr, - REMOTE_ANNOUNCE_INTERVAL, - myname,stype,comment); - } - -} diff --git a/source/nameannounce.doc b/source/nameannounce.doc deleted file mode 100644 index e04a59209a1..00000000000 --- a/source/nameannounce.doc +++ /dev/null @@ -1,265 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.2 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: nameannounce.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created - - 0.1 - 22jul96 : Andrew.Tridgell@anu.edu.au - tridge's comments on first revision - - 0.2 - 05aug96 : lkcl@pires.co.uk - actioned tridge comments about pdc -> domain master - documented NAME_QUERY_ANNOUNCE_HOST - -*/ - - -this module deals with announcements: the sending of announcement requests -and the sending of announcements either to refresh other servers' records -or as a response to announcement requests. - - -/************************************************************************* - announce_master() - *************************************************************************/ - -this function is responsible for announcing samba as a master browser -to all known domain masters. - -this announcement is sent out at CHECK_TIME_MST_ANNOUNCE minute -intervals, only if samba is a master browser on one or more of -its local interfaces. - -if no domain controller has been specified (lp_domain_controller()) -samba goes through its list of servers looking for domain master -browsers. when it finds one (other than itself) it will either -initiate a NAME_QUERY_PDC_SRV_CHK by broadcast or with a WINS -server. this will result in a NAME_STATUS_PDC_SRV_CHK, which -will result in a sync browse list and an announcement -ANN_MasterAnnounce being sent (see sync_server()). - -if a domain controller has been specified, samba will search for -a domain master browser for its workgroup (either by directed -packet or by broadcast if it cannot resolve the domain controller -name using DNS), which results in the same action as listed above. - ------------- -NOTE FROM TRIDGE: - -PDC in the above should really be DMB (domain master browser). They -might be separate entities. - -I also propose a simpler scheme :-) - -If a DMB is not configured with lp_domain_controller() (perhaps -renamed to lp_domain_master()?) then just don't do master -announcements. Remember that most peoples networks are very simple and -don't need DMB capabilities. Those that do need them will have more -complex network topologies and they really need to choose themselves -which box will act as the "hub" for netbios name resolution. Doing it -via name queries will just lead to lag and propogation delays, because -if two parts of the net choose different DMBs then the data will be -very slow to propoogate. - -If a DMB is configured then just send the master announcemnt to that -box! Thats all that needs to be done. Just send a udp 138 packet and -forget it. If the recipient is indeed a DMB (as it should be if the -config file is correct) then it should initiate a browse list sync -with us at some later time, but that is take care of by smbd and nmbd -doesn't even need to know it happened. - -Additionally, if a DMB is configured we need to sync our workgroup -list and server list with them occasionally. Note that this is only -time a non-DMB should do a browse sync, and it should only do it with -a DMB. Essentially WAN based netbios is just a simple star. There is a -DMB in the centre, and the individual master browsers for each subnet -talk to it, but never talk to each other. If they start talking to -each other then the network load will go as the square of the number -of machines, which will result in meltdown :-) -------------- - - -/************************************************************************* - announce_host() - *************************************************************************/ - -this complex-looking function is responsible for announcing samba's -existence to other servers by broadcast. the actual announcement -is carried out by announce_server(). - -the time period between samba's announcement will stretch from one -minute to twelve minutes by one minute. if samba has received an -announce request from a master browser, then it should answer at -any random interval between zero and thirty seconds after the -request is received. this is to ensure that the master browser -does not get overloaded with responses! - - -/************************************************************************* - announce_server() - *************************************************************************/ - -this function is responsible for sending announcement packets. -these packets are received by other servers, which will then -update their records accordingly: what services we have, our -name, our comment field and our time to live (to name a few). - -if samba is a non-master then we need to see if there is a -domain master (on a remote subnet) that we need to announce to -it. - -if samba is not the WINS server (and it is using another -WINS server) then we need to do a name query to the WINS -server to ask it what the domain controller is. this is done -using a samba 'state' NAME_QUERY_ANNOUNCE_HOST, which passes -sufficient information on to be able to carry out the -host announcement using a unicasted do_announce_host() if and -when a reply comes back. if there is no reply to the name query, -this is not necessarily an error - there may genuinely be no -domain master currently up and running for samba's workgroup. - -if samba is a WINS server, then samba will need to look up the -domain controller for its workgroup in its WINS records. an -over-cautious samba could carry out a name query on that -domain controller to make sure that it is alive and that samba's -WINS records are up-to-date. in any event, it will send a unicast -do_announce_host() to inform the domain master browser, if one -exists, of samba's server status. - -if we are a master browser, then using do_announce_host() we -must send a broadcast announcement on the local interface -notifying members of that workgroup that we are their master -browser, and another announcement indicating to all backup -browsers and master browsers that we are a master browser. - -(note: if another master browser receives this broadcasted -announcement and thinks that it is also the master browser -for this workgroup, it stops being a master browser and forces -an election). - -if we are not a master browser, then we send a broacast -announcement notifying the master browser that we are a member -of its workgroup, on the local interface. - - -/************************************************************************* - remove_my_servers() - *************************************************************************/ - -this function is responsible for informing other servers that -samba is about to go down. it announces, on all subnets, that -samba's time to live is zero and that it has no services. - - -/************************************************************************* - do_announce_host() - *************************************************************************/ - -this function is responsible for sending out an announcement -MAILSLOT browse packet. it contains information such as the -time to live, name of the server, services that the server -offers etc. - -the format of this MAILSLOT browse packet is described in -draft-heizer-cifs-v1-spec-00.txt 3.9.50.4.1 page 165-6. - - -/************************************************************************* - announce_backup() - *************************************************************************/ - -this function is responsible for getting master browsers and domain -controllers to send us lists of backup servers. this is done by -sending an ANN_GetBackupListReq browse mailslot. - -the local master browser, or domain master browser, should respond -with an ANN_GetBackupListResp browse mailslot containing the list -of backup servers. - --------------- -NOTE FROM TRIDGE: I don't see why nmbd should ever send one of -these. The only reason I can see for any part of Samba sending one of -these is if we implement it in smbclient. - -This packet is used to request a list of backup master browsers from -the master browser. It is used by clients (not servers!) to spread the -browse load over more than one server. The only server that needs to -know what the list of backups is is the master browser, and as it is -also responsible for generating this list it will never ask anyone -else for it. --------------- - - -/************************************************************************* - sync_server() - *************************************************************************/ - -this function is responsible for initiating a sync browse list -sequence and, if necessary, carrying out an ANN_MasterAnnouncement -to the domain master browser (that we are also sync'ing browse lists -with). - -see nameservresp.c:response_name_status_check(). - - -/************************************************************************* - announce_request() - *************************************************************************/ - -this function is responsible for sending an announcement request to -another server. this server should respond with an announcement. - -if the announce request is sent to WORKGROUP(0x1e) then members of -the workgroup will respond (with ANN_HostAnnounce packets) - -if the announce request is sent to WORKGROUP(0x1d) then the master -browser of the workgroup should respond (ANN_LocalMasterAnnounce). -this is untested. - -if the announce request is sent to ^1^2__MSBROWSE__^2(0x1) then -(and this is pure speculation), all backup browsers and master -browsers should respond with ANN_DomainAnnounce packets. -this is untested. - ------------ -NOTE FROM TRIDGE: - -I had great trouble getting machines to actually respond to this -packet. Either we have the format wrong or MS chose not to implement -it. - -Not implementing it doesn't break anything, it just means a new master -browser won't get a complete server list as quickly. - -Also note that this packet should be used as little as possible as it -could easily cause meltdown if too many servers used it. Imagine a -dozen samba servers on a net all sending this packet! You will get 244 -responses all within 30 seconds. now imagine 50 samba servers .... - -So I think we should restrict ourselves to sending this packet only if -we are already the master browser for a workgroup. We could send a -single "announce request" when we become the master, just to prime our -server lists. From then on the normal announce cycles should take care -of keeping it uptodate. ------------ - diff --git a/source/namebrowse.c b/source/namebrowse.c deleted file mode 100644 index 1dd293d27be..00000000000 --- a/source/namebrowse.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - -*/ - -#include "includes.h" -#include "smb.h" - -extern int ClientNMB; - -extern int DEBUGLEVEL; - -extern struct in_addr wins_ip; - -/* this is our browse master/backup cache database */ -static struct browse_cache_record *browserlist = NULL; - - -/*************************************************************************** - add a browser into the list - **************************************************************************/ -static void add_browse_cache(struct browse_cache_record *b) -{ - struct browse_cache_record *b2; - - if (!browserlist) - { - browserlist = b; - b->prev = NULL; - b->next = NULL; - return; - } - - for (b2 = browserlist; b2->next; b2 = b2->next) ; - - b2->next = b; - b->next = NULL; - b->prev = b2; -} - - -/******************************************************************* - remove old browse entries - ******************************************************************/ -void expire_browse_cache(time_t t) -{ - struct browse_cache_record *b; - struct browse_cache_record *nextb; - - /* expire old entries in the serverlist */ - for (b = browserlist; b; b = nextb) - { - if (b->synced && b->sync_time < t) - { - DEBUG(3,("Removing dead cached browser %s\n",b->name)); - nextb = b->next; - - if (b->prev) b->prev->next = b->next; - if (b->next) b->next->prev = b->prev; - - if (browserlist == b) browserlist = b->next; - - free(b); - } - else - { - nextb = b->next; - } - } -} - -/**************************************************************************** - add a browser entry - ****************************************************************************/ -struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, - time_t ttl, struct subnet_record *d, - struct in_addr ip, BOOL local) -{ - BOOL newentry=False; - - struct browse_cache_record *b; - - /* search for the entry: if it's already in the cache, update that entry */ - for (b = browserlist; b; b = b->next) - { - if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break; - } - - if (b && b->synced) - { - /* entries get left in the cache for a while. this stops sync'ing too - often if the network is large */ - DEBUG(4, ("browser %s %s %s already sync'd at time %d\n", - b->name, b->group, inet_ntoa(b->ip), b->sync_time)); - return NULL; - } - - if (!b) - { - newentry = True; - b = (struct browse_cache_record *)malloc(sizeof(*b)); - - if (!b) return(NULL); - - bzero((char *)b,sizeof(*b)); - } - - /* update the entry */ - ttl = time(NULL)+ttl; - - StrnCpy(b->name ,name,sizeof(b->name )-1); - StrnCpy(b->group,wg ,sizeof(b->group)-1); - strupper(b->name); - strupper(b->group); - - b->ip = ip; - b->type = type; - b->local = local; /* local server list sync or complete sync required */ - b->subnet = d; - - if (newentry || ttl < b->sync_time) - b->sync_time = ttl; - - if (newentry) - { - b->synced = False; - add_browse_cache(b); - - DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n", - wg, name, type, inet_ntoa(ip),ttl)); - } - else - { - DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n", - wg, name, type, inet_ntoa(ip),ttl)); - } - - return(b); -} - - -/**************************************************************************** -find a server responsible for a workgroup, and sync browse lists -**************************************************************************/ -static void start_sync_browse_entry(struct browse_cache_record *b) -{ - struct subnet_record *d = b->subnet; - struct work_record *work; - - /* Check panic conditions - these should not be true. */ - if(b->subnet != wins_subnet) { - DEBUG(0, - ("start_sync_browse_entry: ERROR sync requested on non-WINS subnet.\n")); - return; - } - - if (!(work = find_workgroupstruct(d, b->group, False))) { - DEBUG(0, ("start_sync_browse_entry: failed to get a \ -workgroup for a browse cache entry workgroup %s, server %s\n", - b->group, b->name)); - return; - } - - DEBUG(4, ("start_sync_browse_entry: Initiating %s sync with %s<0x20>, \ -workgroup %s\n", - b->local ? "local" : "remote", b->name, b->group)); - - /* first check whether the server we intend to sync with exists. if it - doesn't, the server must have died. o dear. */ - - /* see response_netbios_packet() or expire_netbios_response_entries() */ - /* We cheat here by using the my_comment field of the response_record - struct as the workgroup name we are going to do the sync for. - This is because the reply packet doesn't include the workgroup, but - we need it when the reply comes back. - */ - queue_netbios_packet(d,ClientNMB,NMB_QUERY, - b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, - b->name,0x20,0,0,0,NULL,b->group, - False,False,b->ip,b->ip); - - b->synced = True; -} - - -/**************************************************************************** - search through browser list for an entry to sync with - **************************************************************************/ -void do_browser_lists(time_t t) -{ - struct browse_cache_record *b; - static time_t last = 0; - - if (t-last < 20) - { - DEBUG(9,("do_browser_lists: returning due to t(%d) - last(%d) < 20\n", - t, last)); - return; /* don't do too many of these at once! */ - /* XXXX equally this period should not be too long - the server may die in the intervening gap */ - } - last = t; - - /* pick any entry in the list, preferably one whose time is up */ - for (b = browserlist; b && b->next; b = b->next) - { - if (b->sync_time < t && b->synced == False) break; - } - - if (b && !b->synced) - { - /* sync with the selected entry then remove some dead entries */ - DEBUG(4,("do_browser_lists: Initiating sync with %s, workgroup %s\n", - b->name, b->group)); - start_sync_browse_entry(b); - } - else - { - DEBUG(9, ("do_browser_lists: no entries to sync.\n")); - } - - expire_browse_cache(t - 60); -} - diff --git a/source/namebrowse.doc b/source/namebrowse.doc deleted file mode 100644 index 82713d85708..00000000000 --- a/source/namebrowse.doc +++ /dev/null @@ -1,149 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.1 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namebrowse.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created - - 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au - tridge's comments on first revision -*/ - -this module deals with queueing servers that samba must sync browse -lists with. it will always issue a name query immediately before -actually carrying out the NetServerEnum call, to ensure that time -is not wasted by a remote server's failure. - -this module was created to minimise the amount of NetServerEnum calls -that samba may be asked to perform, by maintaining the name of a server -for up to a minute after the NetServerEnum call was issued, and -disallowing further NetServerEnum calls to this remote server until -the entry is removed. - -samba can ask for a NetServerEnum call to be issued to grab a remote -server's list of servers and workgroups either in its capacity as -a domain master browser, as a local master browser. - -samba does not deal with becoming a backup master browser properly -at present. - -------------- -NOTE FROM TRIDGE: - -Yes, samba can send these either in its capacity as a DMB or as a -MB. There are only two situations: - -- If samba is a DMB then it should sync with the "local only" bit set -with any master browser that has sent it a "master announce". - -- if samba is not a DMB then it can only sync with the DMB, and should -not set the "local only" bit. - -Note that samba should never sync with other non-DMB servers when it -is not a DMB. - -Try to do a sync under any other circumstances is dangerous without a -multi-threaded nmbd. I have a print server at home that knows some SMB -and NBT, but if you try to sync browse lists with it then it clogs up, -and also clogs up nmbd while it times out the connection. If we -follow the above two rules then we can't get into this sort of -trouble as: - -- if we are a DMB and a master browser sends us a "master announce" -then it is expecting to receive a NetServerEnum SMB connection soon, -and must be capabable of handling it. - -- if we are not a DMB then we will only sync with the DMB, which must -be capable of doing this stuff or things are really in a mess :-) --------------- - - -/************************************************************************* - do_browser_lists() - *************************************************************************/ - -this function is responsible for finding an appropriate entry in the -sync browser cache, initiating a name query (which results in a -NetServerEnum call if there is a positive response), and then -removing all entries that have been actioned and have been around -for over a minute. - - -/************************************************************************* - start_sync_browse_entry() - *************************************************************************/ - -this function is responsible for initiating a name query. if a -positive response is received, then this will result in a -NetServerEnum api call. - -samba will only initiate this process if it is a master browser -for this workgroup. - ------------ -NOTE FROM TRIDGE: - -I'd actually prefer to skip the name query completely if we can -resolve the DMBs name via gethostbyname(). For the name query to work -we either have to have WINS working, or we need to know the broadcast -address of the network that the DMB is on. This makes us too dependent -on too many thing being right. - -If the gethostbyname() fails then sure, go for a normal name query, -but if it works then we have saved ourselves a lot of trouble and -gained a lot of robustness. - -This is best handled by a generic "resolve netbios name" routine that -tries DNS first then resorts to WINS or bcast if that fails. It also -needs to cache the results. -------------- - - -/************************************************************************* - add_browser_entry() - *************************************************************************/ - -this function is responsible for adding a browser into the list of -servers to sync browse lists with. if the server entry has already -been added and syncing browse lists has already been initiated, it -will not be added again. - - -/************************************************************************* - expire_browse_cache() - *************************************************************************/ - -this function is responsible for removing entries that have had the -sync browse list initiated (whether that succeeded or not is beyond -this function's scope) and have been in the cache for a while. - - -/************************************************************************* - add_browse_entry() - *************************************************************************/ - -this function is responsible for adding a new entry into the list -of servers to sync browse lists with at some point in the near future. - - - - diff --git a/source/nameconf.c b/source/nameconf.c deleted file mode 100644 index 8f33419b9ac..00000000000 --- a/source/nameconf.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) David Chappell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 30 July 96: David.Chappell@mail.trincoll.edu - Expanded multiple workgroup domain master browser support. - -*/ - -/* -** nameconf.c -** These functions dispense information from smbbrowse.conf. -** -** -*/ - -#include "includes.h" -extern int DEBUGLEVEL; - -extern fstring myworkgroup; - -#if 0 -struct smbbrowse_parms - { - char *name; - BOOL (*reader)(char *string, void *toset); - } smbbrowse_table[] = -{ - {"preferred master", NULL}, - {"local master", NULL}, - {"domain master", NULL} -} ; -#endif - -/* -** Structure for the list of workgroups from smbbrowse.conf. This -** structure should only be manipulated thru the functions in this file. -** That is why it is not defined in a header file. -*/ -struct smbbrowse -{ - char work_name[16]; /* workgroup name */ - char browsing_alias[16]; /* alias for our role in this workgroup */ - struct server_identity *my_names; /* a list of server name we should appear here as */ - BOOL should_workgroup_member; /* should we try to become a member of this workgroup? */ - BOOL should_local_master; /* should we try to become a master browser? */ - BOOL should_domain_master; /* should we try to become the domain master browser? */ -} ; - -/* The whole list */ -static struct smbbrowse *smbbrowse_workgroups = (struct smbbrowse*)NULL; - -/* The size of the list */ -static int array_size = 0; - -/* The next available space in the list */ -static int nexttoken = 0; - -int get_num_workgroups(void) -{ - return nexttoken; -} - -/* -** This makes a new workgroup structure, possibly taking an -** old one as a model. -*/ -static struct smbbrowse *new_workgroup(struct smbbrowse *model, - char *workgroup_name, - char *default_name) -{ - struct smbbrowse *new; - - if( ! (array_size > nexttoken) ) - { - array_size += 10; - smbbrowse_workgroups = (struct smbbrowse*)realloc(smbbrowse_workgroups, - array_size * sizeof(struct smbbrowse)); - } - - new = &smbbrowse_workgroups[nexttoken]; - - if(model != (struct smbbrowse *)NULL ) - memcpy(new, model, sizeof(struct smbbrowse)); - else - memset(new, 0, sizeof(struct smbbrowse)); - - StrnCpy(new->work_name, workgroup_name, 15); - strupper(new->work_name); - - if (strequal(myworkgroup, workgroup_name)) - StrnCpy(new->browsing_alias, default_name, 15); - else - sprintf(new->browsing_alias, "%.14s%x", default_name, nexttoken); - strupper(new->browsing_alias); - - DEBUG(4,("wg: %s alias: %s token: %x\n", - new->work_name, new->browsing_alias, nexttoken)); - - nexttoken++; - return new; -} - -/* -** If fed a workgroup name, this function returns its token number. -** If the workgroup does not exist a new token is assigned unless -** new workgroups are not allowed. -*/ -int conf_workgroup_name_to_token(char *workgroup_name,char *default_name) -{ - int idx; - - /* Look for an existing instance. */ - for(idx=0; idx < nexttoken; idx++) - { - if(strequal(workgroup_name, smbbrowse_workgroups[idx].work_name)) - { - return idx; - } - } - - /* See if creating new ones in admissable. */ - for(idx=0; idx < nexttoken; idx++) - { - if(strequal("*", smbbrowse_workgroups[idx].work_name)) - { - struct smbbrowse *w = new_workgroup(&smbbrowse_workgroups[idx], - workgroup_name, default_name); - w->should_workgroup_member = False; - - return (nexttoken - 1); - } - } - - /* Not allowed */ - DEBUG(4, ("refusing to allow new workgroup\n")); - return -1; -} - -/* -** This is a workgroups array bounds checker. -*/ -static int range_check(int token) -{ - if(token < 0 || token >= nexttoken) - { - DEBUG(0, ("range_check(): failed\n")); - return True; - } - - return False; -} - -/* -** Given a token, return the name. -*/ -char *conf_workgroup_name(int token) -{ - if(range_check(token)) - return (char*)NULL; - - return smbbrowse_workgroups[token].work_name; -} - -/* -** Given a token, return True if we should try -** to become a master browser. -*/ -int conf_should_workgroup_member(int token) - { - - if(range_check(token)) - return False; - - return smbbrowse_workgroups[token].should_workgroup_member; - } - -/* -** Given a token, return True if we should try -** to become a master browser. -*/ -int conf_should_local_master(int token) - { - if(range_check(token)) - return False; - - return smbbrowse_workgroups[token].should_local_master; - } - -/* -** Given a token, return True if we should try -** to become a domain master browser. -*/ -int conf_should_domain_master(int token) - { - if(range_check(token)) - return False; - - return smbbrowse_workgroups[token].should_domain_master; - } - -/* -** Given a token, return the name. -*/ -char *conf_browsing_alias(int token) - { - if(range_check(token)) - return (char*)NULL; - - return smbbrowse_workgroups[token].browsing_alias; - } - -/* -** Return the server comment which should be used with the -** browsing alias. -*/ -char *conf_browsing_alias_comment(int token) -{ - if(range_check(token)) - return (char*) NULL; - - return "Browser"; - } - -/* -** Given an alias name for this server, return the name of the workgroup -** for which it is the browsing alias. -*/ -char *conf_alias_to_workgroup(char *alias) -{ - int x; - - DEBUG(4,("alias_to_workgroup: %s", alias)); - - for(x=0; x < nexttoken; x++) - { - DEBUG(4,("%s ", smbbrowse_workgroups[x].browsing_alias)); - - if(strequal(alias, smbbrowse_workgroups[x].browsing_alias)) - { - DEBUG(4,("OK\n")); - return smbbrowse_workgroups[x].work_name; - } - } - DEBUG(4,("not found\n")); - return (char*)NULL; -} - -/* -** Given an alias name for this server, return the name of the workgroup -** for which it is the browsing alias. -*/ -int conf_alias_to_token(char *alias) -{ - int x; - - for(x=0; x < nexttoken; x++) - { - if(strequal(alias, smbbrowse_workgroups[x].browsing_alias)) - { - return x; - } - } - return -1; -} - -/* -** Since there is no smbbrowse.conf file, we will fill in -** the structures with information from the smb.conf file. -*/ -static void default_smbbrowse_conf(char *default_name) -{ - struct smbbrowse *w; - - /* The workgroup specified in smb.conf */ - w = new_workgroup((struct smbbrowse *)NULL, myworkgroup, default_name); - w->should_local_master = lp_preferred_master(); - w->should_domain_master = lp_domain_master(); - w->should_workgroup_member = True; - - /* default action: allow any new workgroup to be added */ - w = new_workgroup((struct smbbrowse *)NULL, "*", default_name); - w->should_local_master = False; - w->should_domain_master = False; - w->should_workgroup_member = False; -} - -/* -** This function is called from main(). -*/ -void read_smbbrowse_conf(char *default_name) -{ - FILE *f = fopen(BROWSEFILE,"r"); - if (f) - { - while (!feof(f)) - { - pstring line; - char *ptr; - int count = 0; - - pstring work_name; - struct smbbrowse *w; - - if (!fgets_slash(line,sizeof(pstring),f)) continue; - - if (*line == '#') continue; - - strcpy(work_name,""); - - ptr = line; - - if (next_token(&ptr, work_name, NULL)) ++count; - - if (count <= 0) continue; - - w = new_workgroup((struct smbbrowse *)NULL, work_name, default_name); - w->should_local_master = lp_local_master(); - w->should_domain_master = lp_domain_master(); - w->should_workgroup_member = True; - } - - fclose(f); - } - else - { - DEBUG(2,("Can't open browse configuration file %s\n",BROWSEFILE)); - } - default_smbbrowse_conf(default_name); -} - - diff --git a/source/namedbname.c b/source/namedbname.c deleted file mode 100644 index c91541cc815..00000000000 --- a/source/namedbname.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Module name: namedbname.c - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - created module namedbname containing name database functions -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - -extern pstring scope; -extern struct in_addr ipzero; -extern struct in_addr wins_ip; -extern BOOL updatedlists; - -extern struct subnet_record *subnetlist; - -#define WINS_LIST "wins.dat" - -uint16 nb_type = 0; /* samba's NetBIOS name type */ - - -/**************************************************************************** - samba's NetBIOS name type - - XXXX maybe functionality could be set: B, M, P or H name registration - and resolution could be set through nb_type. just a thought. - ****************************************************************************/ -void set_samba_nb_type(void) -{ - if (lp_wins_support() || (*lp_wins_server())) - { - nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ - } - else - { - nb_type = NB_BFLAG; /* samba is broadcast-only node type */ - } -} - - -/**************************************************************************** - true if two netbios names are equal -****************************************************************************/ -BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2) -{ - return n1->name_type == n2->name_type && - strequal(n1->name ,n2->name ) && - strequal(n1->scope,n2->scope); -} - - -/**************************************************************************** - true if the netbios name is ^1^2__MSBROWSE__^2^1 - - note: this name is registered if as a master browser or backup browser - you are responsible for a workgroup (when you announce a domain by - broadcasting on your local subnet, you announce it as coming from this - name: see announce_host()). - - **************************************************************************/ -BOOL ms_browser_name(char *name, int type) -{ - return strequal(name,MSBROWSE) && type == 0x01; -} - - -/**************************************************************************** - add a netbios name into the namelist - **************************************************************************/ -static void add_name(struct subnet_record *d, struct name_record *n) -{ - struct name_record *n2; - - if (!d) return; - - if (!d->namelist) - { - d->namelist = n; - n->prev = NULL; - n->next = NULL; - return; - } - - for (n2 = d->namelist; n2->next; n2 = n2->next) ; - - n2->next = n; - n->next = NULL; - n->prev = n2; - - if((d == wins_subnet) && lp_wins_support()) - updatedlists = True; -} - - -/**************************************************************************** - remove a name from the namelist. The pointer must be an element just - retrieved - **************************************************************************/ -void remove_name(struct subnet_record *d, struct name_record *n) -{ - struct name_record *nlist; - if (!d) return; - - nlist = d->namelist; - - while (nlist && nlist != n) nlist = nlist->next; - - if (nlist) - { - if (nlist->next) nlist->next->prev = nlist->prev; - if (nlist->prev) nlist->prev->next = nlist->next; - - if(nlist == d->namelist) - d->namelist = nlist->next; - - if(nlist->ip_flgs != NULL) - free(nlist->ip_flgs); - free(nlist); - } - - if((d == wins_subnet) && lp_wins_support()) - updatedlists = True; -} - - -/**************************************************************************** - find a name in a namelist. - **************************************************************************/ -struct name_record *find_name(struct name_record *n, - struct nmb_name *name, int search) -{ - struct name_record *ret; - - for (ret = n; ret; ret = ret->next) - { - if (name_equal(&ret->name,name)) - { - /* self search: self names only */ - if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) - { - continue; - } - DEBUG(9,("find_name: found name %s(%02x)\n", - name->name, name->name_type)); - return ret; - } - } - DEBUG(9,("find_name: name %s(%02x) NOT FOUND\n", name->name, - name->name_type)); - return NULL; -} - - -/**************************************************************************** - find a name in the domain database namelist - search can be any of: - FIND_SELF - look exclusively for names the samba server has added for itself - FIND_LOCAL - look for names in the local subnet record. - FIND_WINS - look for names in the WINS record - **************************************************************************/ -struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip) -{ - if (d == NULL) return NULL; /* bad error! */ - - if (search & FIND_LOCAL) { - if (*d != NULL) { - struct name_record *n = find_name((*d)->namelist, name, search); - DEBUG(4,("find_name on local: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - if (n) return n; - } - } - - if (!(search & FIND_WINS)) return NULL; - - /* find WINS subnet record. */ - *d = wins_subnet; - - if (*d == NULL) return NULL; - - DEBUG(4,("find_name on WINS: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - return find_name((*d)->namelist, name, search); -} - - -/**************************************************************************** - dump a copy of the name table - **************************************************************************/ -void dump_names(void) -{ - struct name_record *n; - fstring fname, fnamenew; - time_t t = time(NULL); - - FILE *f; - - if(lp_wins_support() == False || wins_subnet == 0) - return; - - strcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,WINS_LIST); - strcpy(fnamenew,fname); - strcat(fnamenew,"."); - - f = fopen(fnamenew,"w"); - - if (!f) - { - DEBUG(3,("Can't open %s - %s\n",fnamenew,strerror(errno))); - return; - } - - DEBUG(4,("Dump of WINS name table:\n")); - - for (n = wins_subnet->namelist; n; n = n->next) - { - int i; - - DEBUG(4,("%15s ", inet_ntoa(wins_subnet->bcast_ip))); - DEBUG(4,("%15s ", inet_ntoa(wins_subnet->mask_ip))); - DEBUG(4,("%-19s TTL=%ld ", - namestr(&n->name), - n->death_time?n->death_time-t:0)); - - for (i = 0; i < n->num_ips; i++) - { - DEBUG(4,("%15s NB=%2x source=%d", - inet_ntoa(n->ip_flgs[i].ip), - n->ip_flgs[i].nb_flags,n->source)); - - } - DEBUG(4,("\n")); - - if (f && ((n->source == REGISTER) || (n->source == SELF))) - { - /* XXXX i have little imagination as to how to output nb_flags as - anything other than as a hexadecimal number :-) */ - - fprintf(f, "%s#%02x %ld ", - n->name.name,n->name.name_type, /* XXXX ignore scope for now */ - n->death_time); - - for (i = 0; i < n->num_ips; i++) - { - fprintf(f, "%s %2x%c ", - inet_ntoa(n->ip_flgs[i].ip), - n->ip_flgs[i].nb_flags, (n->source == REGISTER ? 'R' : 'S')); - } - fprintf(f, "\n"); - } - - } - - fclose(f); - unlink(fname); - chmod(fnamenew,0644); - rename(fnamenew,fname); - - DEBUG(3,("Wrote wins database %s\n",fname)); -} - - -/**************************************************************************** - load a netbios name database file - - XXXX we cannot cope with loading Internet Group names, yet - ****************************************************************************/ -void load_netbios_names(void) -{ - struct subnet_record *d = wins_subnet; - fstring fname; - - FILE *f; - pstring line; - - if (!d) return; - - strcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,WINS_LIST); - - f = fopen(fname,"r"); - - if (!f) { - DEBUG(2,("Can't open wins database file %s\n",fname)); - return; - } - - while (!feof(f)) - { - pstring name_str, ip_str, ttd_str, nb_flags_str; - - pstring name; - int type = 0; - unsigned int nb_flags; - time_t ttd; - struct in_addr ipaddr; - - enum name_source source; - - char *ptr; - int count = 0; - - char *p; - - if (!fgets_slash(line,sizeof(pstring),f)) continue; - - if (*line == '#') continue; - - ptr = line; - - if (next_token(&ptr,name_str ,NULL)) ++count; - if (next_token(&ptr,ttd_str ,NULL)) ++count; - if (next_token(&ptr,ip_str ,NULL)) ++count; - if (next_token(&ptr,nb_flags_str,NULL)) ++count; - - if (count <= 0) continue; - - if (count != 4) { - DEBUG(0,("Ill formed wins line")); - DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); - continue; - } - - /* Deal with SELF or REGISTER name encoding. Default is REGISTER - for compatibility with old nmbds. */ - if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') - { - DEBUG(5,("Ignoring SELF name %s\n", line)); - continue; - } - - if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') - nb_flags_str[strlen(nb_flags_str)-1] = '\0'; - - /* netbios name. # divides the name from the type (hex): netbios#xx */ - strcpy(name,name_str); - - p = strchr(name,'#'); - - if (p) { - *p = 0; - sscanf(p+1,"%x",&type); - } - - /* decode the netbios flags (hex) and the time-to-die (seconds) */ - sscanf(nb_flags_str,"%x",&nb_flags); - sscanf(ttd_str,"%ld",&ttd); - - ipaddr = *interpret_addr2(ip_str); - - if (ip_equal(ipaddr,ipzero)) { - source = SELF; - } - else - { - source = REGISTER; - } - - DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n", - name,type, ttd, inet_ntoa(ipaddr), nb_flags)); - - /* add all entries that have 60 seconds or more to live */ - if (ttd - 60 > time(NULL) || ttd == 0) - { - time_t t = (ttd?ttd-time(NULL):0) / 3; - - /* add netbios entry read from the wins.dat file. IF it's ok */ - add_netbios_entry(d,name,type,nb_flags,t,source,ipaddr,True,True); - } - } - - fclose(f); -} - - -/**************************************************************************** - remove an entry from the name list - ****************************************************************************/ -void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip) -{ - struct nmb_name nn; - struct name_record *n; - - make_nmb_name(&nn, name, type, scope); - n = find_name_search(&d, &nn, FIND_LOCAL, ip); - - if (n && n->source == source) remove_name(d,n); -} - - -/**************************************************************************** - add an entry to the name list. - - this is a multi-purpose function. - - it adds samba's own names in to its records on each interface, keeping a - record of whether it is a master browser, domain master, or WINS server. - - it also keeps a record of WINS entries. - - ****************************************************************************/ -struct name_record *add_netbios_entry(struct subnet_record *d, - char *name, int type, int nb_flags, - int ttl, enum name_source source, struct in_addr ip, - BOOL new_only,BOOL wins) -{ - struct name_record *n; - struct name_record *n2=NULL; - struct subnet_record *found_subnet = 0; - int search = 0; - BOOL self = (source == SELF); - - /* add the name to the WINS list if the name comes from a directed query */ - search |= wins ? FIND_WINS : FIND_LOCAL; - - /* If it's a local search then we need to set the subnet - we are looking at. */ - if(search & FIND_LOCAL) - found_subnet = d; - - /* search for SELF names only */ - search |= self ? FIND_SELF : 0; - - if (!self) - { - if (!wins && (type != 0x1b)) - { - /* the only broadcast (non-WINS) names we are adding are ours - (SELF) and Domain Master type names */ - return NULL; - } - if(wins && (type == 0x1d)) - { - /* Do not allow any 0x1d names to be registered in a WINS, - database although we return success for them. - */ - return NULL; - } - } - - n = (struct name_record *)malloc(sizeof(*n)); - if (!n) return(NULL); - - bzero((char *)n,sizeof(*n)); - - n->num_ips = 1; /* XXXX ONLY USE THIS FUNCTION FOR ONE ENTRY */ - n->ip_flgs = (struct nmb_ip*)malloc(sizeof(*n->ip_flgs) * n->num_ips); - if (!n->ip_flgs) - { - free(n); - return NULL; - } - - make_nmb_name(&n->name,name,type,scope); - - if ((n2 = find_name_search(&found_subnet, &n->name, search, new_only?ipzero:ip))) - { - free(n->ip_flgs); - free(n); - if (new_only || (n2->source==SELF && source!=SELF)) return n2; - n = n2; - d = found_subnet; - } - - if (ttl) - n->death_time = time(NULL)+ttl*3; - n->refresh_time = time(NULL)+GET_TTL(ttl); - - /* XXXX only one entry expected with this function */ - n->ip_flgs[0].ip = ip; - n->ip_flgs[0].nb_flags = nb_flags; - - n->source = source; - - if (!n2) add_name(d,n); - - DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x to interface %s\n", - namestr(&n->name),inet_ntoa(ip),ttl,nb_flags, - ip_equal(d->bcast_ip, wins_ip) ? "WINS" : (char *)inet_ntoa(d->bcast_ip))); - - return(n); -} - - -/******************************************************************* - expires old names in the namelist - ******************************************************************/ -void expire_names(time_t t) -{ - struct name_record *n; - struct name_record *next; - struct subnet_record *d; - - /* expire old names */ - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - for (n = d->namelist; n; n = next) - { - next = n->next; - if (n->death_time && n->death_time < t) - { - if (n->source == SELF) - { - DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name))); - n->death_time += 300; - continue; - } - DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); - - if (n->prev) n->prev->next = n->next; - if (n->next) n->next->prev = n->prev; - - if (d->namelist == n) d->namelist = n->next; - - if(n->ip_flgs != NULL) - free(n->ip_flgs); - free(n); - } - } - } -} - - -/*************************************************************************** - assume a WINS name is a dns name, and do a gethostbyname() on it. - ****************************************************************************/ -struct name_record *dns_name_search(struct nmb_name *question, int Time) -{ - int name_type = question->name_type; - char *qname = question->name; - BOOL dns_type = (name_type == 0x20 || name_type == 0); - struct in_addr dns_ip; - - if (wins_subnet == NULL) - return NULL; - - DEBUG(3,("Search for %s - ", namestr(question))); - - /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ - if (!dns_type) - { - DEBUG(3,("types 0x20 0x0 only: name not found\n")); - return NULL; - } - - /* look it up with DNS */ - dns_ip.s_addr = interpret_addr(qname); - - if (!dns_ip.s_addr) - { - /* no luck with DNS. We could possibly recurse here XXXX */ - DEBUG(3,("not found. no recursion.\n")); - /* add the fail to WINS cache of names. give it 1 hour in the cache */ - add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, - True, True); - return NULL; - } - - DEBUG(3,("found with DNS: %s\n", inet_ntoa(dns_ip))); - - /* add it to our WINS cache of names. give it 2 hours in the cache */ - return add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip, - True,True); -} diff --git a/source/namedbname.doc b/source/namedbname.doc deleted file mode 100644 index 34a791dbb89..00000000000 --- a/source/namedbname.doc +++ /dev/null @@ -1,182 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namedbname.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -this module deals with the NetBIOS name database for samba. it deals -directly with adding, removing, finding, loading and saving of names. - -/************************************************************************* - search_for_name() - *************************************************************************/ - -this function is responsible for finding a name in the appropriate part -of samba's NetBIOS name database. if the name cannot be found, then it -should look the name up using DNS. later modifications will be to -forward the request on to another WINS server, should samba not be able -to find out about the requested name (this will be implemented through -issuing a new type of samba 'state'). - -the name is first searched for in the NetBIOS cache. if it cannot be -found, then it if the name looks like it's a server-type name (0x20 -0x0 or 0x1b) then DNS is used to look for the name. - -if DNS fails, then a record of this failure is kept. if it succeeds, then -a new NetBIOS entry is added. - -the successfully found name is returned. on failure, NULL is returned. - - -/************************************************************************* - expire_names() - *************************************************************************/ - -this function is responsible for removing old NetBIOS names from its -database. no further action is required. - -for over-zealous WINS systems, the use of query_refresh_names() is -recommended. this function initiates polling of hosts that have -registered with samba in its capacity as a WINS server. an alternative -means to achieve the same end as query_refresh_names() is to -reduce the time to live when the name is registered with samba, -except that in this instance the responsibility for refreshing the -name is with the owner of the name, not the server with which the name -is registered. - - -/************************************************************************* - add_netbios_entry() - *************************************************************************/ - -this function is responsible for adding or updating a NetBIOS name -in the database. into the local interface records, the only names -that will be added are those of domain master browsers and -samba's own names. into the WINS records, all names are added. - -the name to be added / updated will be looked up in the records. -if it is found, then we will not overwrite the entry if the flag -'newonly' is True, or if the name is being added as a non-SELF -(non-samba) name and the records indicate that samba owns the -name. - -otherwise, the name is added or updated with the new details. - - -/************************************************************************* - remove_netbios_entry() - *************************************************************************/ - -this function is responsible for removing a NetBIOS entry from -the database. the name is searched for in the records using -find_name_search(). if the ip is zero, then the ip is ignored. - -the name is removed if the expected source (e.g SELF, REGISTER) -matches that in the database. - - -/************************************************************************* - load_netbios_names() - *************************************************************************/ - -this function is responsible for loading any NetBIOS names that samba, -in its WINS capacity, has written out to disk. all the relevant details -are recorded in this file, including the time-to-live. should the -time left to live be small, the name is not added back in to samba's -WINS database. - - -/************************************************************************* - dump_names() - *************************************************************************/ - -this function is responsible for outputting NetBIOS names in two formats. -firstly, as debugging information, and secondly, all names that have been -registered with samba in its capacity as a WINS server are written to -disk. - -writing all WINS names allows two things. firstly, if samba's NetBIOS -daemon dies or is terminated, on restarting the daemon most if not all -of the registered WINS names will be preserved (which is a good reason -why query_netbios_names() should be used). - - -/************************************************************************* - find_name_search() - *************************************************************************/ - -this function is a wrapper around find_name(). find_name_search() can -be told whether to search for the name in a local subnet structure or -in the WINS database. on top of this, it can be told to search only -for samba's SELF names. - -if it finds the name in the WINS database, it will set the subnet_record -and also return the name it finds. - - -/************************************************************************* - find_name() - *************************************************************************/ - -this function is a low-level search function that searches a single -interface's NetBIOS records for a name. if the ip to be found is -zero then the ip address is ignored. this is to enable a name to -be found without knowing its ip address, and also to find the exact -name if a large number of group names are added with different ip -addresses. - - -/************************************************************************* - remove_name() - *************************************************************************/ - -this function is responsible for removing a specific NetBIOS entry -from a subnet list's records. only if the pointer to the entry is -in the list will the name be removed. - - -/************************************************************************* - add_name() - *************************************************************************/ - -this function is responsible for adding a NetBIOS entry into a -subnet list's records. - - -/************************************************************************* - ms_browser_name() - *************************************************************************/ - -this function returns True if the NetBIOS name passed to it is -^1^2__MSBROWSE__^2^1 - - -/************************************************************************* - name_equal() - *************************************************************************/ - -this function returns True if the two NetBIOS names passed to it -match in name, type and scope: the NetBIOS names are equal. - - diff --git a/source/namedbresp.c b/source/namedbresp.c deleted file mode 100644 index 98f8ca774bc..00000000000 --- a/source/namedbresp.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios library routines - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Module name: namedbresp.c - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern struct subnet_record *subnetlist; - -extern int DEBUGLEVEL; - -extern pstring scope; -extern pstring myname; -extern struct in_addr ipzero; - -int num_response_packets = 0; - -/*************************************************************************** - add an expected response record into the list - **************************************************************************/ -void add_response_record(struct subnet_record *d, - struct response_record *n) -{ - struct response_record *n2; - - if (!d) return; - - num_response_packets++; /* count of total number of packets still around */ - - DEBUG(4,("adding response record id:%d num_records:%d\n", - n->response_id, num_response_packets)); - - if (!d->responselist) - { - d->responselist = n; - n->prev = NULL; - n->next = NULL; - return; - } - - for (n2 = d->responselist; n2->next; n2 = n2->next) ; - - n2->next = n; - n->next = NULL; - n->prev = n2; -} - - -/*************************************************************************** - remove an expected response record from the list - **************************************************************************/ -void remove_response_record(struct subnet_record *d, - struct response_record *n) -{ - if (!d) return; - - if (n->prev) n->prev->next = n->next; - if (n->next) n->next->prev = n->prev; - - if (d->responselist == n) d->responselist = n->next; - - free(n); - - num_response_packets--; /* count of total number of packets still around */ -} - - -/**************************************************************************** - create a name query response record - **************************************************************************/ -struct response_record *make_response_queue_record(enum state_type state, - int id,uint16 fd, - int quest_type, char *name,int type, int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) -{ - struct response_record *n; - - if (!name || !name[0]) return NULL; - - if (!(n = (struct response_record *)malloc(sizeof(*n)))) - return(NULL); - - n->response_id = id; - n->state = state; - n->fd = fd; - n->quest_type = quest_type; - make_nmb_name(&n->name, name, type, scope); - n->nb_flags = nb_flags; - n->ttl = ttl; - n->server_type = server_type; - n->bcast = bcast; - n->recurse = recurse; - n->send_ip = send_ip; - n->reply_to_ip = reply_to_ip; - if(my_name) - StrnCpy(n->my_name, my_name, sizeof(n->my_name)-1); - else - *n->my_name = 0; - if(my_comment) - StrnCpy(n->my_comment, my_comment, sizeof(n->my_comment)-1); - else - *n->my_comment = 0; - n->repeat_interval = 1; /* XXXX should be in ms */ - n->repeat_count = 3; /* 3 retries */ - n->repeat_time = time(NULL) + n->repeat_interval; /* initial retry time */ - - n->num_msgs = 0; - - return n; -} - - -/**************************************************************************** - find a response in a subnet's name query response list. - **************************************************************************/ -struct response_record *find_response_record(struct subnet_record **d, - uint16 id) -{ - struct response_record *n; - - if (!d) return NULL; - - for ((*d) = FIRST_SUBNET; (*d); (*d) = NEXT_SUBNET_INCLUDING_WINS(*d)) - { - for (n = (*d)->responselist; n; n = n->next) - { - if (n->response_id == id) { - DEBUG(4, ("found response record on %s: %d\n", - inet_ntoa((*d)->bcast_ip), id)); - return n; - } - } - } - - *d = NULL; - - return NULL; -} - - diff --git a/source/namedbresp.doc b/source/namedbresp.doc deleted file mode 100644 index a54c0702758..00000000000 --- a/source/namedbresp.doc +++ /dev/null @@ -1,100 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.1 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namedbresp.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created - - 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au - tridge's comments on first revision -*/ - -module namedbresp deals with the maintenance of the list of expected -responses - creating, finding and removal. - -module nameresp deals with the initial transmission, re-transmission -and time-out of netbios response records. - - -/************************************************************************* - find_response_record() - *************************************************************************/ - -this function is responsible for matching the unique response transaction -id with an expected response record. as a side-effect of this search, -it will find the subnet (or the WINS pseudo-subnet) that samba expected -the response to come from. - - -/************************************************************************* - make_response_queue_record() - *************************************************************************/ - -this function is responsible for creating a response record, which will -be queued awaiting a response. - -the number of retries is set to 3, and the retry period set to 1 second. -if no response is received, then the packet is re-transmitted, which is -why so much information is stored in the response record. - -the number of expected responses queued is kept, so listen_for_packets() -knows it must time-out after 1 second if one or more responses are -expected. - - -/************************************************************************* - remove_response_record() - *************************************************************************/ - -this function is responsible for removing a response record from the -expected response queue. the number of expected responses is decreased. - - -/************************************************************************* - add_response_record() - *************************************************************************/ - -this function is responsible for adding the response record created by -make_response_queue_record() into the appropriate response record queue. - - ------------------ -NOTE FROM TRIDGE: - -namedbresp.c is interesting because it implements a novel way of -getting most of the advantages of a multi-threaded nmbd daemon without -the portability problems. - -The NBT specs (rfc1001/1002) talk about the 16 bit IDs in the packets -as being used to ensure that packets are unique, and to stop packets -from being confused. It suggests incrementing the ID by 1 each time. - -Instead Luke uses these IDs to identify individual threads of control -in nmbd. So when nmbd sends out a NBT packet as part of some complex -processing, it adds to a linked list the information required to -continue the processing when the reply comes in (or it times -out). When a reply arrives this list can be searched to find the -matching query and the next step in the processing can be carried out. - -This is really good stuff, and allows for much more complex behaviour -than was possible with the old nmbd. ----------------- diff --git a/source/namedbserver.c b/source/namedbserver.c deleted file mode 100644 index 9223cb6ce6a..00000000000 --- a/source/namedbserver.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - created module namedbserver containing server database functions - -*/ - -#include "includes.h" -#include "smb.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern int DEBUGLEVEL; - -extern pstring myname; -extern fstring myworkgroup; - -/* this is our domain/workgroup/server database */ -extern struct subnet_record *subnetlist; - -extern BOOL updatedlists; - - -/******************************************************************* - expire old servers in the serverlist - time of -1 indicates everybody dies except those with time of 0 - remove_all_servers indicates everybody dies. - ******************************************************************/ -void remove_old_servers(struct work_record *work, time_t t, - BOOL remove_all) -{ - struct server_record *s; - struct server_record *nexts; - - /* expire old entries in the serverlist */ - for (s = work->serverlist; s; s = nexts) - { - if (remove_all || (s->death_time && (t == -1 || s->death_time < t))) - { - DEBUG(3,("Removing dead server %s\n",s->serv.name)); - updatedlists = True; - nexts = s->next; - - if (s->prev) s->prev->next = s->next; - if (s->next) s->next->prev = s->prev; - - if (work->serverlist == s) - work->serverlist = s->next; - - free(s); - } - else - { - nexts = s->next; - } - } -} - - -/*************************************************************************** - add a server into the list - **************************************************************************/ -static void add_server(struct work_record *work,struct server_record *s) -{ - struct server_record *s2; - - if (!work->serverlist) { - work->serverlist = s; - s->prev = NULL; - s->next = NULL; - return; - } - - for (s2 = work->serverlist; s2->next; s2 = s2->next) ; - - s2->next = s; - s->next = NULL; - s->prev = s2; -} - - -/**************************************************************************** - find a server in a server list. - **************************************************************************/ -struct server_record *find_server(struct work_record *work, char *name) -{ - struct server_record *ret; - - if (!work) return NULL; - - for (ret = work->serverlist; ret; ret = ret->next) - { - if (strequal(ret->serv.name,name)) - { - return ret; - } - } - return NULL; -} - - -/**************************************************************************** - add a server entry - ****************************************************************************/ -struct server_record *add_server_entry(struct subnet_record *d, - struct work_record *work, - char *name,int servertype, - int ttl,char *comment, - BOOL replace) -{ - BOOL newentry=False; - struct server_record *s; - - if (name[0] == '*') - { - return (NULL); - } - - s = find_server(work, name); - - if (s && !replace) - { - DEBUG(4,("Not replacing %s\n",name)); - return(s); - } - - if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment)) - updatedlists=True; - - if (!s) - { - newentry = True; - s = (struct server_record *)malloc(sizeof(*s)); - - if (!s) return(NULL); - - bzero((char *)s,sizeof(*s)); - } - - - /* update the entry */ - StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1); - StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1); - strupper(s->serv.name); - s->serv.type = servertype; - s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1); - - /* for a domain entry, the comment field refers to the server name */ - - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment); - - if (newentry) - { - add_server(work, s); - - DEBUG(3,("Added ")); - } - else - { - DEBUG(3,("Updated ")); - } - - DEBUG(3,("server entry %s of type %x (%s) to %s %s\n", - name,servertype,comment, - work->work_group,inet_ntoa(d->bcast_ip))); - - return(s); -} - - -/******************************************************************* - expire old servers in the serverlist - ******************************************************************/ -void expire_servers(time_t t) -{ - struct subnet_record *d; - - for (d = FIRST_SUBNET; d ; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) - { - remove_old_servers(work, t, False); - } - } -} - diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c deleted file mode 100644 index 7e800930a53..00000000000 --- a/source/namedbsubnet.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - created module namedbsubnet containing subnet database functions - -*/ - -#include "includes.h" -#include "smb.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern int DEBUGLEVEL; - -extern struct in_addr wins_ip; -extern struct in_addr ipzero; - -extern pstring myname; -extern fstring myworkgroup; - -BOOL updatedlists = True; -int updatecount = 0; - -/* local interfaces structure */ -extern struct interface *local_interfaces; - -/* this is our domain/workgroup/server database */ -struct subnet_record *subnetlist = NULL; - -/* WINS subnet - keep this separate so enumeration code doesn't - run onto it by mistake. */ -struct subnet_record *wins_subnet = NULL; - -extern uint16 nb_type; /* samba's NetBIOS name type */ - -/**************************************************************************** - add a domain into the list - **************************************************************************/ -static void add_subnet(struct subnet_record *d) -{ - struct subnet_record *d2; - - if (!subnetlist) - { - subnetlist = d; - d->prev = NULL; - d->next = NULL; - return; - } - - for (d2 = subnetlist; d2->next; d2 = d2->next); - - d2->next = d; - d->next = NULL; - d->prev = d2; -} - - -/**************************************************************************** - find a subnet in the subnetlist - not including WINS. - **************************************************************************/ -struct subnet_record *find_subnet(struct in_addr bcast_ip) -{ - struct subnet_record *d; - - /* search through subnet list for broadcast/netmask that matches - the source ip address. */ - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - if (same_net(bcast_ip, d->bcast_ip, d->mask_ip)) - return d; - } - - return (NULL); -} - - -/**************************************************************************** - finds the appropriate subnet structure. directed packets (non-bcast) are - assumed to come from a point-to-point (P or M node), and so the subnet we - return in this instance is the WINS 'pseudo-subnet' with ip 255.255.255.255 - ****************************************************************************/ -struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast) -{ - if (bcast) - { - /* identify the subnet the broadcast request came from */ - return find_subnet(*iface_bcast(ip)); - } - /* Return the subnet with the pseudo-ip of 255.255.255.255 */ - return wins_subnet; -} - -/**************************************************************************** - find a subnet in the subnetlist - if the subnet is not found - then return the WINS subnet. - **************************************************************************/ -struct subnet_record *find_subnet_all(struct in_addr bcast_ip) -{ - struct subnet_record *d = find_subnet(bcast_ip); - if(!d) - return wins_subnet; - return d; -} - -/**************************************************************************** - create a domain entry - ****************************************************************************/ -static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip, BOOL add) -{ - struct subnet_record *d; - d = (struct subnet_record *)malloc(sizeof(*d)); - - if (!d) return(NULL); - - bzero((char *)d,sizeof(*d)); - - DEBUG(4, ("making subnet %s ", inet_ntoa(bcast_ip))); - DEBUG(4, ("%s\n", inet_ntoa(mask_ip))); - - d->bcast_ip = bcast_ip; - d->mask_ip = mask_ip; - d->workgrouplist = NULL; - - if(add) - add_subnet(d); - - return d; -} - -/**************************************************************************** - add a domain entry. creates a workgroup, if necessary, and adds the domain - to the named a workgroup. - ****************************************************************************/ -static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, - struct in_addr mask_ip, char *name, - BOOL create_subnets, BOOL add) -{ - struct subnet_record *d = NULL; - - if (zero_ip(bcast_ip)) - bcast_ip = *iface_bcast(bcast_ip); - - /* Note that we should also add into the WINS subnet as add_subnet_entry - should be called to add NetBIOS names and server entries on all - interfaces, including the WINS interface - */ - - if(create_subnets == True) - { - /* Create new subnets. */ - if((d = make_subnet(bcast_ip, mask_ip, add)) == NULL) - { - DEBUG(0,("add_subnet_entry: Unable to create subnet %s\n", - inet_ntoa(bcast_ip) )); - return NULL; - } - return d; - } - if(ip_equal(bcast_ip, wins_ip)) - return wins_subnet; - return find_subnet(bcast_ip); -} - -/**************************************************************************** - Add a workgroup into a subnet, and if it's our primary workgroup, - add the required names to it. -**************************************************************************/ - -void add_workgroup_to_subnet( struct subnet_record *d, char *group) -{ - struct work_record *w = NULL; - - DEBUG(5,("add_workgroup_to_subnet: Adding workgroup %s to subnet %s\n", - group, inet_ntoa(d->bcast_ip))); - - /* This next statement creates the workgroup struct if it doesn't - already exist. - */ - if((w = find_workgroupstruct(d, group, True)) == NULL) - { - DEBUG(0,("add_workgroup_to_subnet: Unable to add workgroup %s to subnet %s\n", - group, inet_ntoa(d->bcast_ip) )); - return; - } - - /* add WORKGROUP(00) entries into name database - or register with WINS server, if it's our workgroup. - */ - if (strequal(myworkgroup, group)) - { - add_my_name_entry(d,group,0x0 ,nb_type|NB_ACTIVE|NB_GROUP,False); - add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP,False); - /* add samba server name to workgroup list. */ - add_server_entry(d,w,myname,w->ServerType,0,lp_serverstring(),True); - DEBUG(3,("add_workgroup_to_subnet: Added server name entry %s to subnet %s\n", - myname, inet_ntoa(d->bcast_ip))); - } -} - -/**************************************************************************** - create subnet / workgroup / server entries - - - add or create the subnet lists - - add or create the workgroup entries in each subnet entry - - register appropriate NetBIOS names for the workgroup entries - -**************************************************************************/ -void add_my_subnets(char *group) -{ - static BOOL create_subnets = True; - struct subnet_record *d = NULL; - struct interface *i = NULL; - - if (*group == '*') return; - - /* Create subnets from all the local interfaces and thread them onto - the linked list. - */ - for (i = local_interfaces; i; i = i->next) - { - add_subnet_entry(i->bcast,i->nmask,group, create_subnets, True); - } - - /* If we are using WINS, then we must add the workgroup to the WINS - subnet. This is used as a place to keep collated server lists. - */ - - /* Create the WINS subnet if we are using WINS - but don't thread it - onto the linked subnet list. - */ - if (lp_wins_support() || lp_wins_server()) - { - struct in_addr wins_nmask = ipzero; - wins_subnet = add_subnet_entry(wins_ip, wins_nmask, group, create_subnets, False); - } - - /* Ensure we only create the subnets once. */ - create_subnets = False; - - /* Now we have created all the subnets - we can add the names - that make us a client member in the workgroup. - */ - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - add_workgroup_to_subnet(d, group); -} - -/******************************************************************* - write out browse.dat - ******************************************************************/ -void write_browse_list(time_t t) -{ - struct subnet_record *d; - pstring fname,fnamenew; - FILE *f; - - static time_t lasttime = 0; - - if (!lasttime) lasttime = t; - if (!updatedlists || t - lasttime < 5) return; - - lasttime = t; - updatedlists = False; - updatecount++; - - dump_names(); - dump_workgroups(); - - strcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,SERVER_LIST); - strcpy(fnamenew,fname); - strcat(fnamenew,"."); - - f = fopen(fnamenew,"w"); - - if (!f) - { - DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno))); - return; - } - - for (d = FIRST_SUBNET; d ; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct work_record *work; - for (work = d->workgrouplist; work ; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s ; s = s->next) - { - fstring tmp; - - /* don't list domains I don't have a master for */ - if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0]) - { - continue; - } - - /* output server details, plus what workgroup/domain - they're in. without the domain information, the - combined list of all servers in all workgroups gets - sent to anyone asking about any workgroup! */ - - sprintf(tmp, "\"%s\"", s->serv.name); - fprintf(f, "%-25s ", tmp); - fprintf(f, "%08x ", s->serv.type); - sprintf(tmp, "\"%s\" ", s->serv.comment); - fprintf(f, "%-30s", tmp); - fprintf(f, "\"%s\"\n", work->work_group); - } - } - } - - fclose(f); - unlink(fname); - chmod(fnamenew,0644); - rename(fnamenew,fname); - DEBUG(3,("Wrote browse list %s\n",fname)); -} - diff --git a/source/namedbwork.c b/source/namedbwork.c deleted file mode 100644 index a17de731bb1..00000000000 --- a/source/namedbwork.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - created module namedbwork containing workgroup database functions - -*/ - -#include "includes.h" -#include "smb.h" - -extern int ClientNMB; - -extern int DEBUGLEVEL; - -/* this is our domain/workgroup/server database */ -extern struct subnet_record *subnetlist; - -extern struct in_addr wins_ip; - -extern fstring myworkgroup; - -int workgroup_count = 0; /* unique index key: one for each workgroup */ - - - -/**************************************************************************** - add a workgroup into the domain list - **************************************************************************/ -static void add_workgroup(struct work_record *work, struct subnet_record *d) -{ - struct work_record *w2; - - if (!work || !d) return; - - if (!d->workgrouplist) - { - d->workgrouplist = work; - work->prev = NULL; - work->next = NULL; - return; - } - - for (w2 = d->workgrouplist; w2->next; w2 = w2->next); - - w2->next = work; - work->next = NULL; - work->prev = w2; -} - - -/**************************************************************************** - create a blank workgroup - **************************************************************************/ -static struct work_record *make_workgroup(char *name) -{ - struct work_record *work; - struct subnet_record *d; - int t = -1; - - if (!name || !name[0]) return NULL; - - work = (struct work_record *)malloc(sizeof(*work)); - if (!work) return(NULL); - - StrnCpy(work->work_group,name,sizeof(work->work_group)-1); - work->serverlist = NULL; - - work->ServerType = DFLT_SERVER_TYPE | (lp_local_master() ? - SV_TYPE_POTENTIAL_BROWSER : 0 ); - work->RunningElection = False; - work->ElectionCount = 0; - work->needelection = False; - work->needannounce = True; - work->mst_state = MST_POTENTIAL; - work->dom_state = DOMAIN_NONE; - work->log_state = LOGON_NONE; - - /* make sure all token representations of workgroups are unique */ - - for (d = FIRST_SUBNET; d && t == -1; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct work_record *w; - for (w = d->workgrouplist; w && t == -1; w = w->next) - { - if (strequal(w->work_group, work->work_group)) t = w->token; - } - } - - if (t == -1) - { - work->token = ++workgroup_count; - } - else - { - work->token = t; - } - - - /* WfWg uses 01040b01 */ - /* Win95 uses 01041501 */ - /* NTAS uses ???????? */ - work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8); - work->ElectionCriterion |= (lp_os_level() << 24); - if (lp_domain_master()) { - work->ElectionCriterion |= 0x80; - } - - return work; -} - - -/******************************************************************* - remove workgroups - ******************************************************************/ -struct work_record *remove_workgroup(struct subnet_record *d, - struct work_record *work, - BOOL remove_all_servers) -{ - struct work_record *ret_work = NULL; - - if (!d || !work) return NULL; - - DEBUG(3,("Removing old workgroup %s\n", work->work_group)); - - ret_work = work->next; - - remove_old_servers(work, -1, remove_all_servers); - - if (!work->serverlist) - { - if (work->prev) work->prev->next = work->next; - if (work->next) work->next->prev = work->prev; - - if (d->workgrouplist == work) d->workgrouplist = work->next; - - free(work); - } - - return ret_work; -} - - -/**************************************************************************** - find a workgroup in the workgrouplist - only create it if the domain allows it, or the parameter 'add' insists - that it get created/added anyway. this allows us to force entries in - lmhosts file to be added. - **************************************************************************/ -struct work_record *find_workgroupstruct(struct subnet_record *d, - fstring name, BOOL add) -{ - struct work_record *ret, *work; - - if (!d) return NULL; - - DEBUG(4, ("workgroup search for %s: ", name)); - - for (ret = d->workgrouplist; ret; ret = ret->next) { - if (!strcmp(ret->work_group,name)) { - DEBUG(4, ("found\n")); - return(ret); - } - } - - if (!add) { - DEBUG(4, ("not found\n")); - return NULL; - } - - DEBUG(4,("not found: creating\n")); - - if ((work = make_workgroup(name))) - { - if (!ip_equal(d->bcast_ip, wins_ip) && - lp_preferred_master() && lp_local_master() && - strequal(myworkgroup, name)) - { - DEBUG(3, ("preferred master startup for %s\n", work->work_group)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } - add_workgroup(work, d); - return(work); - } - return NULL; -} - - -/**************************************************************************** - dump a copy of the workgroup/domain database - **************************************************************************/ -void dump_workgroups(void) -{ - struct subnet_record *d; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - if (d->workgrouplist) - { - struct work_record *work; - - DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); - DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); - - for (work = d->workgrouplist; work; work = work->next) - { - DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); - if (work->serverlist) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - DEBUG(4,("\t\t%s %8x (%s)\n", - s->serv.name, s->serv.type, s->serv.comment)); - } - } - } - } - } -} diff --git a/source/nameelect.c b/source/nameelect.c deleted file mode 100644 index 2b4ebf091cc..00000000000 --- a/source/nameelect.c +++ /dev/null @@ -1,850 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Module name: nameelect.c - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - added system to become a master browser by stages. - - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern int DEBUGLEVEL; -extern pstring scope; - -extern pstring myname; -extern fstring myworkgroup; -extern struct in_addr ipzero; -extern struct in_addr wins_ip; - -/* here are my election parameters */ - -extern time_t StartupTime; - -extern struct subnet_record *subnetlist; - -extern uint16 nb_type; /* samba's NetBIOS name type */ - - -/******************************************************************* - occasionally check to see if the master browser is around - ******************************************************************/ -void check_master_browser(time_t t) -{ - static time_t lastrun=0; - struct subnet_record *d; - - if (!lastrun) lastrun = t; - if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return; - - lastrun = t; - - dump_workgroups(); - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) - { - if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work)) - { - if (lp_local_master()) - { - /* potential master browser - not a master browser. force - becoming a master browser, hence the log message. - */ - - DEBUG(2,("%s potential master for %s %s - force election\n", - timestring(), work->work_group, - inet_ntoa(d->bcast_ip))); - - browser_gone(work->work_group, d->bcast_ip); - } - else - { - /* if we are not the browse master of a workgroup, - and we can't find a browser on the subnet, do - something about it. - */ - - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, - work->work_group,0x1d,0,0,0,NULL,NULL, - True,False,d->bcast_ip,d->bcast_ip); - } - } - } - } -} - - -/******************************************************************* - what to do if a master browser DOESN't exist. - - option 1: force an election, and participate in it - option 2: force an election, and let everyone else participate. - - ******************************************************************/ -void browser_gone(char *work_name, struct in_addr ip) -{ - struct subnet_record *d = find_subnet(ip); - struct work_record *work = find_workgroupstruct(d, work_name, False); - - /* i don't know about this workgroup, therefore i don't care */ - if (!work || !d) return; - - /* don't do election stuff on the WINS subnet */ - if (ip_equal(d->bcast_ip,wins_ip)) - return; - - if (strequal(work->work_group, myworkgroup)) - { - - if (lp_local_master()) - { - /* we have discovered that there is no local master - browser, and we are configured to initiate - an election under exactly such circumstances. - */ - DEBUG(2,("Forcing election on %s %s\n", - work->work_group,inet_ntoa(d->bcast_ip))); - - /* we can attempt to become master browser */ - work->needelection = True; - } - else - { - /* we need to force an election, because we are configured - not to _become_ the local master, but we still _need_ one, - having detected that one doesn't exist. - */ - - /* local interfaces: force an election */ - send_election(d, work->work_group, 0, 0, myname); - - /* only removes workgroup completely on a local interface - persistent lmhosts entries on a local interface _will_ be removed). - */ - remove_workgroup(d, work,True); - add_workgroup_to_subnet(d, work->work_group); - } - } -} - - -/**************************************************************************** - send an election packet - **************************************************************************/ -void send_election(struct subnet_record *d, char *group,uint32 criterion, - int timeup,char *name) -{ - pstring outbuf; - char *p; - - if (!d) return; - - DEBUG(2,("Sending election to %s for workgroup %s\n", - inet_ntoa(d->bcast_ip),group)); - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - CVAL(p,0) = ANN_Election; /* election */ - p++; - - CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION; - SIVAL(p,1,criterion); - SIVAL(p,5,timeup*1000); /* ms - despite the spec */ - p += 13; - strcpy(p,name); - strupper(p); - p = skip_string(p,1); - - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip)); -} - - -/**************************************************************************** - un-register a SELF name that got rejected. - - if this name happens to be rejected when samba is in the process - of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d) - or WORKGROUP(1b)) then we must stop being a master browser. sad. - - **************************************************************************/ -void name_unregister_work(struct subnet_record *d, char *name, int name_type) -{ - struct work_record *work; - int remove_type_local = 0; - int remove_type_domain = 0; - int remove_type_logon = 0; - - remove_netbios_name(d,name,name_type,SELF,ipzero); - - if (!(work = find_workgroupstruct(d, name, False))) return; - - /* work out what to unbecome, from the name type being removed */ - - if (ms_browser_name(name, name_type)) - { - remove_type_local |= SV_TYPE_MASTER_BROWSER; - } - if (AM_MASTER(work) && strequal(name, myworkgroup) && name_type == 0x1d) - { - remove_type_local |= SV_TYPE_MASTER_BROWSER; - } - if (AM_DOMMST(work) && strequal(name, myworkgroup) && name_type == 0x1b) - { - remove_type_domain |= SV_TYPE_DOMAIN_MASTER; - } - if (AM_DOMMEM(work) && strequal(name, myworkgroup) && name_type == 0x1c) - { - remove_type_logon|= SV_TYPE_DOMAIN_MEMBER; - } - - if (remove_type_local ) unbecome_local_master (d, work, remove_type_local ); - if (remove_type_domain) unbecome_domain_master(d, work, remove_type_domain); - if (remove_type_logon ) unbecome_logon_server (d, work, remove_type_logon ); -} - - -/**************************************************************************** - registers a name. - - if the name being added is a SELF name, we must additionally check - whether to proceed to the next stage in samba becoming a master browser. - - **************************************************************************/ -void name_register_work(struct subnet_record *d, char *name, int name_type, - int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast) -{ - enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ? - SELF : REGISTER; - - if (source == SELF) - { - struct work_record *work = find_workgroupstruct(d, - myworkgroup, False); - - add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast); - - if (work) - { - int add_type_local = False; - int add_type_domain = False; - int add_type_logon = False; - - DEBUG(4,("checking next stage: name_register_work %s\n", name)); - - /* work out what to become, from the name type being added */ - - if (ms_browser_name(name, name_type)) - { - add_type_local = True; - } - if (strequal(name, myworkgroup) && name_type == 0x1d) - { - add_type_local = True; - } - if (strequal(name, myworkgroup) && name_type == 0x1b) - { - add_type_domain = True; - } - if (strequal(name, myworkgroup) && name_type == 0x1c) - { - add_type_logon = True; - } - - if (add_type_local ) become_local_master (d, work); - if (add_type_domain) become_domain_master(d, work); - if (add_type_logon ) become_logon_server (d, work); - } - } -} - - -/******************************************************************* - become the local master browser. - - this is done in stages. note that this could take a while, - particularly on a broadcast subnet, as we have to wait for - the implicit registration of each name to be accepted. - - as each name is successfully registered, become_local_master() is - called again, in order to initiate the next stage. see - dead_netbios_entry() - deals with implicit name registration - and response_name_reg() - deals with explicit registration - with a WINS server. - - stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1. - stage 2: was MST_BACK - go to MST_MSB and register WORKGROUP(0x1d) - stage 3: was MST_MSB - go to MST_BROWSER and stay there - - XXXX note: this code still does not cope with the distinction - between different types of nodes, particularly between M and P - nodes. that comes later. - - ******************************************************************/ -void become_local_master(struct subnet_record *d, struct work_record *work) -{ - /* domain type must be limited to domain enum + server type. it must - not have SV_TYPE_SERVER or anything else with SERVER in it, else - clients get confused and start thinking this entry is a server - not a workgroup - */ - uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; - - if (!work || !d) - return; - - if (!lp_local_master()) - { - DEBUG(0,("Samba not configured as a local master browser.\n")); - return; - } - - DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n", - work->work_group,inet_ntoa(d->bcast_ip),work->mst_state)); - - switch (work->mst_state) - { - case MST_POTENTIAL: /* while we were nothing but a server... */ - { - DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n")); - work->mst_state = MST_BACK; /* an election win was successful */ - - work->ElectionCriterion |= 0x5; - - /* update our server status */ - work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER; - add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY, - 0,lp_serverstring(),True); - - /* add special browser name */ - add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP,False); - - /* DON'T do anything else after calling add_my_name_entry() */ - break; - } - - case MST_BACK: /* while nothing had happened except we won an election... */ - { - DEBUG(3,("go to second stage: register as master browser\n")); - work->mst_state = MST_MSB; /* registering MSBROWSE was successful */ - - /* add server entry on successful registration of MSBROWSE */ - add_server_entry(d,work,work->work_group,domain_type|SV_TYPE_LOCAL_LIST_ONLY, - 0,myname,True); - - /* add master name */ - add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE,False); - - /* DON'T do anything else after calling add_my_name_entry() */ - break; - } - - case MST_MSB: /* while we were still only registered MSBROWSE state... */ - { - int i = 0; - struct server_record *sl; - - DEBUG(3,("2nd stage complete: registered as master browser for workgroup %s \ -on subnet %s\n", work->work_group, inet_ntoa(d->bcast_ip))); - work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */ - - /* update our server status */ - work->ServerType |= SV_TYPE_MASTER_BROWSER; - - DEBUG(3,("become_local_master: updating our server %s to type %x\n", - myname, work->ServerType)); - - add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY, - 0,lp_serverstring(),True); - - /* Count the number of servers we have on our list. If it's - less than 10 (just a heuristic) request the servers - to announce themselves. - */ - for( sl = work->serverlist; sl != NULL; sl = sl->next) - i++; - - if (i < 10) - { - /* ask all servers on our local net to announce to us */ - announce_request(work, d->bcast_ip); - } - - /* Reset the announce master timer so that we do an announce as soon as possible - now we are a master. */ - reset_announce_timer(); - - DEBUG(0,("Samba is now a local master browser for workgroup %s on subnet %s\n", - work->work_group, inet_ntoa(d->bcast_ip))); - - break; - } - - case MST_BROWSER: - { - /* don't have to do anything: just report success */ - DEBUG(3,("3rd stage: become master browser!\n")); - break; - } - } -} - - -/******************************************************************* - become the domain master browser. - - this is done in stages. note that this could take a while, - particularly on a broadcast subnet, as we have to wait for - the implicit registration of each name to be accepted. - - as each name is successfully registered, become_domain_master() is - called again, in order to initiate the next stage. see - dead_netbios_entry() - deals with implicit name registration - and response_name_reg() - deals with explicit registration - with a WINS server. - - stage 1: was DOMAIN_NONE - go to DOMAIN_MST - - XXXX note: this code still does not cope with the distinction - between different types of nodes, particularly between M and P - nodes. that comes later. - - ******************************************************************/ -void become_domain_master(struct subnet_record *d, struct work_record *work) -{ - /* domain type must be limited to domain enum + server type. it must - not have SV_TYPE_SERVER or anything else with SERVER in it, else - clients get confused and start thinking this entry is a server - not a workgroup - */ - - if (!work || !d) return; - - if (!lp_domain_master()) - { - DEBUG(0,("Samba not configured as a domain master browser.\n")); - return; - } - - DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n", - work->work_group,inet_ntoa(d->bcast_ip),work->dom_state)); - - switch (work->dom_state) - { - case DOMAIN_NONE: /* while we were nothing but a server... */ - { - DEBUG(3,("become_domain_master: go to first stage: register <1b> name\n")); - work->dom_state = DOMAIN_WAIT; - - /* Registering the DOMAIN<1b> name is very tricky. We need to - do this on all our subnets, but don't want to bradcast it - on locally connected subnets (WinNT doesn't do this). Also, - previous versions of Samba screw up royally when we do this. - We need to register it immediatly on our local subnet, but - also actually check with the WINS server if it exists. If the name - has already been claimed by someone else in the WINS server - then we need to back out all our local registrations and - fail. Thus we only directly enter the name on local subnets, - on the WINS subnet we actually check... - */ - /* XXXX the 0x1b is domain master browser name */ - if(d == wins_subnet) - add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE,False); - else - add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE,True); - - /* DON'T do anything else after calling add_my_name_entry() */ - break; - } - - case DOMAIN_WAIT: - { - work->dom_state = DOMAIN_MST; /* ... become domain master */ - DEBUG(3,("become_domain_master: first stage - register as domain member\n")); - - /* update our server status */ - work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER; - add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY, - 0, lp_serverstring(),True); - - DEBUG(0,("Samba is now a domain master browser for workgroup %s on subnet %s\n", - work->work_group, inet_ntoa(d->bcast_ip))); - - break; - } - - case DOMAIN_MST: - { - /* don't have to do anything: just report success */ - DEBUG(3,("domain second stage: there isn't one!\n")); - break; - } - } -} - - -/******************************************************************* - become a logon server. - ******************************************************************/ -void become_logon_server(struct subnet_record *d, struct work_record *work) -{ - if (!work || !d) return; - - if (!lp_domain_logons()) - { - DEBUG(0,("samba not configured as a logon master.\n")); - return; - } - - DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n", - work->work_group,inet_ntoa(d->bcast_ip),work->log_state)); - - switch (work->log_state) - { - case LOGON_NONE: /* while we were nothing but a server... */ - { - DEBUG(3,("go to first stage: register <1c> name\n")); - work->log_state = LOGON_WAIT; - - /* XXXX the 0x1c is apparently something to do with domain logons */ - add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP,False); - - /* DON'T do anything else after calling add_my_name_entry() */ - break; - } - - case LOGON_WAIT: - { - work->log_state = LOGON_SRV; /* ... become logon server */ - DEBUG(3,("logon second stage: register \n")); - - /* update our server status */ - work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER; - add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY - ,0, lp_serverstring(),True); - - /* DON'T do anything else after calling add_my_name_entry() */ - break; - } - - case LOGON_SRV: - { - DEBUG(3,("logon third stage: there isn't one!\n")); - break; - } - } -} - - -/******************************************************************* - unbecome the local master browser. initates removal of necessary netbios - names, and tells the world that we are no longer a master browser. - - XXXX this _should_ be used to demote to a backup master browser, without - going straight to non-master browser. another time. - - ******************************************************************/ -void unbecome_local_master(struct subnet_record *d, struct work_record *work, - int remove_type) -{ - int new_server_type = work->ServerType; - - /* can only remove master types with this function */ - remove_type &= SV_TYPE_MASTER_BROWSER; - - new_server_type &= ~remove_type; - - if (remove_type) - { - DEBUG(2,("Becoming local non-master for %s\n",work->work_group)); - - /* no longer a master browser of any sort */ - - work->ServerType |= SV_TYPE_POTENTIAL_BROWSER; - work->ElectionCriterion &= ~0x4; - work->mst_state = MST_POTENTIAL; - - /* announce ourselves as no longer active as a master browser. */ - announce_server(d, work, work->work_group, myname, 0, 0); - remove_name_entry(d,MSBROWSE ,0x01,False); - remove_name_entry(d,work->work_group,0x1d,False); - } -} - - -/******************************************************************* - unbecome the domain master browser. initates removal of necessary netbios - names, and tells the world that we are no longer a domain browser. - ******************************************************************/ -void unbecome_domain_master(struct subnet_record *d, struct work_record *work, - int remove_type) -{ - int new_server_type = work->ServerType; - - DEBUG(2,("Becoming domain non-master for %s\n",work->work_group)); - - /* can only remove master or domain types with this function */ - remove_type &= SV_TYPE_DOMAIN_MASTER; - - new_server_type &= ~remove_type; - - if (remove_type) - { - /* no longer a domain master browser of any sort */ - - work->dom_state = DOMAIN_NONE; - - /* announce ourselves as no longer active as a master browser on - all our local subnets. */ - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - work = find_workgroupstruct(d, myworkgroup, False); - - announce_server(d, work, work->work_group, myname, 0, 0); - /* Remove the name entry without any NetBIOS traffic as that's - how it was registered. */ - remove_name_entry(d,work->work_group,0x1b,True); - } - } -} - - -/******************************************************************* - unbecome the logon server. initates removal of necessary netbios - names, and tells the world that we are no longer a logon server. - ******************************************************************/ -void unbecome_logon_server(struct subnet_record *d, struct work_record *work, - int remove_type) -{ - int new_server_type = work->ServerType; - - DEBUG(2,("Becoming logon non-server for %s\n",work->work_group)); - - /* can only remove master or domain types with this function */ - remove_type &= SV_TYPE_DOMAIN_MEMBER; - - new_server_type &= ~remove_type; - - if (remove_type) - { - /* no longer a master browser of any sort */ - - work->log_state = LOGON_NONE; - - /* announce ourselves as no longer active as a master browser. */ - announce_server(d, work, work->work_group, myname, 0, 0); - remove_name_entry(d,work->work_group,0x1c,False); - } -} - - -/******************************************************************* - run the election - ******************************************************************/ -void run_elections(time_t t) -{ - static time_t lastime = 0; - - struct subnet_record *d; - - /* send election packets once a second */ - if (lastime && t-lastime <= 0) return; - - lastime = t; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) - { - if (work->RunningElection) - { - send_election(d,work->work_group, work->ElectionCriterion, - t-StartupTime,myname); - - if (work->ElectionCount++ >= 4) - { - /* I won! now what :-) */ - DEBUG(2,(">>> Won election on %s %s <<<\n", - work->work_group,inet_ntoa(d->bcast_ip))); - - work->RunningElection = False; - work->mst_state = MST_POTENTIAL; - - become_local_master(d, work); - } - } - } - } -} - - -/******************************************************************* - work out if I win an election - ******************************************************************/ -static BOOL win_election(struct work_record *work,int version,uint32 criterion, - int timeup,char *name) -{ - int mytimeup = time(NULL) - StartupTime; - uint32 mycriterion = work->ElectionCriterion; - - /* If local master is false then never win - in election broadcasts. */ - if(!lp_local_master()) - { - DEBUG(3,("win_election: Losing election as local master == False\n")); - return False; - } - - DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n", - version,ELECTION_VERSION, - criterion,mycriterion, - timeup,mytimeup, - name,myname)); - - if (version > ELECTION_VERSION) return(False); - if (version < ELECTION_VERSION) return(True); - - if (criterion > mycriterion) return(False); - if (criterion < mycriterion) return(True); - - if (timeup > mytimeup) return(False); - if (timeup < mytimeup) return(True); - - if (strcasecmp(myname,name) > 0) return(False); - - return(True); -} - - -/******************************************************************* - process a election packet - - An election dynamically decides who will be the master. - ******************************************************************/ -void process_election(struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - struct in_addr ip = dgram->header.source_ip; - struct subnet_record *d = find_subnet(ip); - int version = CVAL(buf,0); - uint32 criterion = IVAL(buf,1); - int timeup = IVAL(buf,5)/1000; - char *name = buf+13; - struct work_record *work; - - if (!d) return; - - if (ip_equal(d->bcast_ip,wins_ip)) - { - DEBUG(3,("Unexpected election request from %s %s on WINS net\n", - name, inet_ntoa(p->ip))); - return; - } - - name[15] = 0; - - DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n", - name,inet_ntoa(p->ip),version,criterion,timeup)); - - if (same_context(dgram)) return; - - for (work = d->workgrouplist; work; work = work->next) - { - if (!strequal(work->work_group, myworkgroup)) - continue; - - if (win_election(work, version,criterion,timeup,name)) - { - if (!work->RunningElection) - { - work->needelection = True; - work->ElectionCount=0; - work->mst_state = MST_POTENTIAL; - } - } - else - { - work->needelection = False; - - if (work->RunningElection || AM_MASTER(work)) - { - work->RunningElection = False; - DEBUG(3,(">>> Lost election on %s %s <<<\n", - work->work_group,inet_ntoa(d->bcast_ip))); - if (AM_MASTER(work)) - { - unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER); - } - } - } - } -} - - -/**************************************************************************** - checks whether a browser election is to be run on any workgroup - - this function really ought to return the time between election - packets (which depends on whether samba intends to be a domain - master or a master browser) in milliseconds. - - ***************************************************************************/ -BOOL check_elections(void) -{ - struct subnet_record *d; - BOOL run_any_election = False; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - run_any_election |= work->RunningElection; - - if (work->needelection && !work->RunningElection) - { - DEBUG(3,(">>> Starting election on %s %s <<<\n", - work->work_group,inet_ntoa(d->bcast_ip))); - work->ElectionCount = 0; - work->RunningElection = True; - work->needelection = False; - } - } - } - return run_any_election; -} - diff --git a/source/nameelect.doc b/source/nameelect.doc deleted file mode 100644 index df025e2069a..00000000000 --- a/source/nameelect.doc +++ /dev/null @@ -1,256 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.1 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: nameelect.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created - - 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au - tridge's comments on first revision -*/ - -the module nameelect.c deals with initiating, winning, losing -browsing elections, and checking if browsers are still around, -and the consequences of getting involved in all this. - -an election packet can be received at any time, which will initiate -an election. samba can also detect that there is no longer a -master browser and will initiate an election. - -there is one way to become a master browser, but there are two -ways to un-become a master browser. if you lose an election, you -must stop being a master browser. if you fail to register your -unique special browser names (either on your local subnet or with -the WINS server) then you must stop being a master browser. - -this is a double fail-safe mechanism to ensure that there is only -one master browser per workgroup per subnet (and one domain master -browser - per domain (workgroup) per wide area network). - -(a wide area network is created when one or more servers on a -broadcast-isolated subnet point to the same WINS server). - --------- -NOTE FROM TRIDGE: - -I'd say "domain master browser" not "WINS server" here. WINS doesn't -have much to do with browsing, it is the WAN varient of name -resolution. The name resolution and browsing functions of a netbios -network are almost entirely separate. Both grew out of systems that -could only be used on local networks. - -To adapt them to WANs, WINS was added for name resolution, and "domain -master browsers" were added for browse lists. It would be perfectly -possible to have a WINS server that doesn't even listen to UDP port -138. --------- - -/************************************************************************* - check_elections() - *************************************************************************/ - -this function returns True if samba is in the process of running an -election on any of its interfaces. a better version of this function -should return the time-out period in between election packets, in -milliseconds. - - -/************************************************************************* - process_election() - *************************************************************************/ - -this function is responsible for dealing with the receipt of an election -browse MAILSLOT packet. - -if samba is running an election, it checks the criteria in the packet -received using win_election() to see if it has lost the election or if -it should join in the election. - -if it loses the election, then it becomes a non-master. - - -/************************************************************************* - win_election() - *************************************************************************/ - -this function returns True if samba has won an election. the criteria -in order of precedence are: - -the election version; the election criteria; the time since samba was -started; and as a last resort, a name comparison is used. - - -/************************************************************************* - run_elections() - *************************************************************************/ - -this function is responsible for sending out election packets if -samba is running in an election. once the fourth packet is sent -out, it is assumed that we have won, and samba initiates becoming -a master browser. - -(it looks like samba sends out an extra packet just to be sure...) - - -/************************************************************************* - become_nonmaster() - *************************************************************************/ - -this function is responsible for down-grading samba's status from -either domain master to master browser or nothing, or master browser -to nothing, depending on its current status. - -samba can become a non-master in three ways: by losing an election - -see process_election(); by having one of its special browser names -de-registered - see name_unregister_work(); by receiving and -processing a browser reset packet - see process_reset_browser(). - -when samba stops being a domain master, it must release its unique -0x1b name. when samba stops being a master browser, it must release -its unique 0x1d name. - -becoming non-master is done on a per-subnet basis. - - -/************************************************************************* - become_master() - *************************************************************************/ - -this function is responsible for slowly turning samba into a -local master browser or a domain master browser. - - -this is done in stages. note that this could take a while, -particularly on a broadcast subnet, as we have to wait for -the implicit registration of each name to be accepted. - -as each name is successfully registered, become_master() is -called again via name_register_work(), in order to initiate -the next stage (see dead_netbios_entry() - deals with implicit -name registration and response_name_reg() - deals with explicit -registration with a WINS server). - -stage 1: was MST_NONE - go to MST_NONE and register ^1^2__MSBROWSE__^2^1. -stage 2: was MST_WON - go to MST_MSB and register WORKGROUP(0x1d) -stage 3: was MST_MSB - go to MST_BROWSER and register WORKGROUP(0x1b) -stage 4: was MST_BROWSER - go to MST_DOMAIN (do not pass GO, do not...) - -note that this code still does not cope with the distinction -between different types of nodes, particularly between M and P -nodes (see rfc1001.txt). that will be developed later. - - -/************************************************************************* - name_register_work() - *************************************************************************/ - -this function is called when a NetBIOS name is successfully -registered. it will add the registered name into samba's NetBIOS -records. - -it has the additional responsibility that when samba is becoming -a master browser, it must initiate the next stage in the progress -towards becoming a master browser. - -implicit name registration is done through dead_netbios_entry() -by time-out. explicit name registration is done through -response_name_reg() with a WINS server. - - -/************************************************************************* - name_unregister_work() - *************************************************************************/ - -this function is called when there is an objection to a NetBIOS -name being registered. this will always be done through a negative -response to a name registration, whether it be by a host that -already owns the unique name being registered on a subnet, or -by a WINS server. - -the name being objected to must be removed from samba's records. - -it has the additional responsibility of checking whether samba is -currently a master browser or not, and if so it should initiate -becoming a non-master. - - - -/************************************************************************* - send_election() - *************************************************************************/ - -this function is responsible for sending a browse mailslot -datagram election packet (of type ANN_Election). it constructs -the packet with all the relevant info needed to participate: -election version; election criteria; time since startup and -our name. - -this function can be used to ensure that initiate but lose an -election by specifying a criteria and time up of zero. this -is necessary if we are a master browser and we are about to -go down (politely!) - see nmbd.c:sig_term(). - - -/************************************************************************* - browser_gone() - *************************************************************************/ - -this function is responsible for dealing with the instance when -the master browser we thought was present on a subnet is no longer -responding. - -if it is samba's workgroup, and it's a local interface, samba -detects that it can participate in an election on that interface -and potentially become a master browser or domain master. - -if it's a local subnet and not one of samba's workgroups, then -samba will force an election (which it is not obliged to do). -remove_workgroup() will be expected to remove all references -to this workgroup and the servers in it from the database. - -if it's a remote subnet and not one of samba's workgroups then -no election is forced, and remove_workgroup() will be expected -to remove all server entries from this workgroup _except_ those -added from the lmhosts file. if there are entries added from -the lmhosts file, then the workgroup entry will remain, -otherwise it too will be removed. - - -/************************************************************************* - check_master_browser() - *************************************************************************/ - -this function is responsible for periodically checking whether -master browsers that samba expects to be alive are alive. this -is done every CHECK_TIME_MST_BROWSE minutes. - -for every workgroup record for which samba is not a master browser, -on both local and remote interfaces, samba will initiate a -broadcast query for a master browser on that subnet. - -(browser_gone() will be called to deal with the case where no -response is received to the NAME_QUERY_MST_CHK initiated here. -no action is required when a response _is_ received, however: -see nameservresp.c:response_process() and dead_netbios_entry() -for details) - - diff --git a/source/namelogon.c b/source/namelogon.c deleted file mode 100644 index 1c118c85418..00000000000 --- a/source/namelogon.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - -*/ - -#include "includes.h" - -extern int ClientDGRAM; - -#define TEST_CODE /* want to debug unknown browse packets */ - -extern int DEBUGLEVEL; - -extern pstring myname; - - -/**************************************************************************** - process a domain logon packet - - **************************************************************************/ -void process_logon_packet(struct packet_struct *p,char *buf,int len) -{ - struct dgram_packet *dgram = &p->packet.dgram; - char *logname,*q; - fstring reply_name; - BOOL add_slashes = False; - pstring outbuf; - int code,reply_code; - char unknown_byte = 0; - uint16 request_count = 0; - uint16 token = 0; - - if (!lp_domain_logons()) - { - DEBUG(3,("No domain logons\n")); - return; - } - - - code = SVAL(buf,0); - switch (code) - { - case 0: - { - char *machine = buf+2; - char *user = skip_string(machine,1); - char *tmp; - logname = skip_string(user,1); - tmp = skip_string(logname,1); - unknown_byte = CVAL(tmp,0); - request_count = SVAL(tmp,1); - token = SVAL(tmp,3); - - reply_code = 0x6; - strcpy(reply_name,myname); - strupper(reply_name); - add_slashes = True; - DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n", - machine,inet_ntoa(p->ip),user,token)); - break; - } - case 7: - { - char *machine = buf+2; - logname = skip_string(machine,1); - token = SVAL(skip_string(logname,1),0); - - strcpy(reply_name,lp_domain_controller()); - if (!*reply_name) - { - /* oo! no domain controller. must be us, then */ - strcpy(reply_name,myname); - reply_code = 0xC; - } - else - { - /* refer logon request to the domain controller */ - reply_code = 0x7; - } - - strupper(reply_name); - DEBUG(3,("GETDC request from %s(%s), reporting %s 0x%x token=%x\n", - machine,inet_ntoa(p->ip), reply_name, reply_code,token)); - break; - } - default: - { - DEBUG(3,("Unknown domain request %d\n",code)); - return; - } - } - - bzero(outbuf,sizeof(outbuf)); - q = outbuf; - SSVAL(q,0,reply_code); - q += 2; - - if (token == 0xffff || /* LM 2.0 or later */ - token == 0xfffe) /* WfWg networking */ - { - if (add_slashes) - { - strcpy(q,"\\\\"); - q += 2; - } - strcpy(q, reply_name); - strupper(q); - q = skip_string(q,1); - - if (token == 0xffff) /* LM 2.0 or later */ - { - SSVAL(q,0,token); - q += 2; - } - } - - SSVAL(q,0,0xFFFF); - q += 2; - - send_mailslot_reply(True, logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf), - myname,&dgram->source_name.name[0],0x20,0,p->ip, - *iface_ip(p->ip)); -} diff --git a/source/namelogon.doc b/source/namelogon.doc deleted file mode 100644 index c4a97d0cf16..00000000000 --- a/source/namelogon.doc +++ /dev/null @@ -1,36 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namelogon.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -this module deals with the first stage of domain logons. there is much -more work to be done on this: it's all totally undocumented. - - -/************************************************************************* - process_logon_packet() - *************************************************************************/ - -a function that processes logon packets (the most helpful comment yet :-). diff --git a/source/namepacket.c b/source/namepacket.c deleted file mode 100644 index 55b525d6c50..00000000000 --- a/source/namepacket.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern int DEBUGLEVEL; - -extern int num_response_packets; - -BOOL CanRecurse = True; -extern pstring scope; -extern struct in_addr wins_ip; - -static uint16 name_trn_id=0; - - -/*************************************************************************** - updates the unique transaction identifier - **************************************************************************/ -void debug_browse_data(char *outbuf, int len) -{ - int i,j; - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = outbuf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", outbuf[i+j])); - } - - DEBUG(4, ("\n")); - } - -} - - -/*************************************************************************** - updates the unique transaction identifier - **************************************************************************/ -static void update_name_trn_id(void) -{ - if (!name_trn_id) - { - name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100); - } - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; -} - - -/**************************************************************************** - initiate a netbios packet - ****************************************************************************/ -void initiate_netbios_packet(uint16 *id, - int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse, - struct in_addr to_ip) -{ - struct packet_struct p; - struct nmb_packet *nmb = &p.packet.nmb; - struct res_rec additional_rec; - char *packet_type = "unknown"; - int opcode = -1; - - if (!id) return; - - if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; } - if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; } - if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; } - if (quest_type == NMB_REG_REFRESH ) { packet_type = "nmb_reg_refresh"; opcode = 9; } - if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; } - - DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n", - packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip))); - - if (opcode == -1) return; - - bzero((char *)&p,sizeof(p)); - - if (*id == 0xffff) { - update_name_trn_id(); - *id = name_trn_id; /* allow resending with same id */ - } - - nmb->header.name_trn_id = *id; - nmb->header.opcode = opcode; - nmb->header.response = False; - - nmb->header.nm_flags.bcast = bcast; - nmb->header.nm_flags.recursion_available = False; - nmb->header.nm_flags.recursion_desired = recurse; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = False; - - nmb->header.rcode = 0; - nmb->header.qdcount = 1; - nmb->header.ancount = 0; - nmb->header.nscount = 0; - nmb->header.arcount = (quest_type==NMB_REG || - quest_type==NMB_REL || - quest_type==NMB_REG_REFRESH) ? 1 : 0; - - make_nmb_name(&nmb->question.question_name,name,name_type,scope); - - nmb->question.question_type = quest_type == NMB_STATUS ? 0x21 : 0x20; - nmb->question.question_class = 0x1; - - if (quest_type == NMB_REG || - quest_type == NMB_REG_REFRESH || - quest_type == NMB_REL) - { - nmb->additional = &additional_rec; - bzero((char *)nmb->additional,sizeof(*nmb->additional)); - - nmb->additional->rr_name = nmb->question.question_name; - nmb->additional->rr_type = 0x20; - nmb->additional->rr_class = 0x1; - - if (quest_type == NMB_REG || quest_type == NMB_REG_REFRESH) - nmb->additional->ttl = lp_max_ttl(); - else - nmb->additional->ttl = 0; - - nmb->additional->rdlength = 6; - nmb->additional->rdata[0] = nb_flags; - putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip)); - } - - p.ip = to_ip; - p.port = NMB_PORT; - p.fd = fd; - p.timestamp = time(NULL); - p.packet_type = NMB_PACKET; - - debug_nmb_packet(&p); - - if (!send_packet(&p)) { - DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port)); - *id = 0xffff; - } - - return; -} - - -/**************************************************************************** - reply to a netbios name packet - ****************************************************************************/ -void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, - struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, - char *data,int len) -{ - struct packet_struct p; - struct nmb_packet *nmb = &p.packet.nmb; - struct res_rec answers; - char *packet_type = "unknown"; - - p = *p1; - - switch (rcv_code) - { - case NMB_STATUS: - { - packet_type = "nmb_status"; - break; - } - case NMB_QUERY: - { - packet_type = "nmb_query"; - break; - } - case NMB_REG: - { - packet_type = "nmb_reg"; - break; - } - case NMB_REL: - { - packet_type = "nmb_rel"; - break; - } - case NMB_WAIT_ACK: - { - packet_type = "nmb_wack"; - break; - } - default: - { - DEBUG(1,("replying netbios packet: %s %s\n", - packet_type, namestr(rr_name), inet_ntoa(p.ip))); - - return; - } - } - - DEBUG(4,("replying netbios packet: %s %s\n", - packet_type, namestr(rr_name), inet_ntoa(p.ip))); - - nmb->header.name_trn_id = trn_id; - nmb->header.opcode = opcode; - nmb->header.response = True; - nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.recursion_available = (lp_wins_support() ? True : False ); - nmb->header.nm_flags.recursion_desired = (lp_wins_support() ? recurse : False ); - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = True; - - nmb->header.qdcount = 0; - nmb->header.ancount = 1; - nmb->header.nscount = 0; - nmb->header.arcount = 0; - nmb->header.rcode = rcode; - - bzero((char*)&nmb->question,sizeof(nmb->question)); - - nmb->answers = &answers; - bzero((char*)nmb->answers,sizeof(*nmb->answers)); - - nmb->answers->rr_name = *rr_name; - nmb->answers->rr_type = rr_type; - nmb->answers->rr_class = rr_class; - nmb->answers->ttl = ttl; - - if (data && len) - { - nmb->answers->rdlength = len; - memcpy(nmb->answers->rdata, data, len); - } - - p.packet_type = NMB_PACKET; - - debug_nmb_packet(&p); - - send_packet(&p); -} - - -/******************************************************************* - the global packet linked-list. incoming entries are added to the - end of this list. it is supposed to remain fairly short so we - won't bother with an end pointer. - ******************************************************************/ -static struct packet_struct *packet_queue = NULL; - -/******************************************************************* - queue a packet into the packet queue - ******************************************************************/ -void queue_packet(struct packet_struct *packet) -{ - struct packet_struct *p; - - if (!packet_queue) { - packet->prev = NULL; - packet->next = NULL; - packet_queue = packet; - return; - } - - /* find the bottom */ - for (p=packet_queue;p->next;p=p->next) ; - - p->next = packet; - packet->next = NULL; - packet->prev = p; -} - -/**************************************************************************** - determine if a packet is for us. Note that to have any chance of - being efficient we need to drop as many packets as possible at this - stage as subsequent processing is expensive. - - We also must make absolutely sure we don't tread on another machines - property by answering a packet that is not for us. - ****************************************************************************/ -static BOOL listening(struct packet_struct *p,struct nmb_name *n) -{ - struct subnet_record *d; - struct name_record *n1; - - /* We explicitly don't search WINS here - this will be done - in find_name_search if it was a packet from a non-local subnet. */ - d = find_subnet(p->ip); - - n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip); - - return (n1 != NULL); -} - - -/**************************************************************************** - process udp 138 datagrams - ****************************************************************************/ -static void process_dgram(struct packet_struct *p) -{ - char *buf; - char *buf2; - int len; - struct dgram_packet *dgram = &p->packet.dgram; - - /* if we aren't listening to the destination name then ignore the packet */ - if (!listening(p,&dgram->dest_name)) - { - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%x) from %s\n", - dgram->dest_name.name, dgram->dest_name.name_type, inet_ntoa(p->ip))); - return; - } - - if (dgram->header.msg_type != 0x10 && - dgram->header.msg_type != 0x11 && - dgram->header.msg_type != 0x12) - { - /* don't process error packets etc yet */ - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%d) from %s as it is \ - an error packet of type %x\n", - dgram->dest_name.name, dgram->dest_name.name_type, - inet_ntoa(p->ip), dgram->header.msg_type)); - return; - } - - buf = &dgram->data[0]; - buf -= 4; /* XXXX for the pseudo tcp length - - someday I need to get rid of this */ - - if (CVAL(buf,smb_com) != SMBtrans) return; - - len = SVAL(buf,smb_vwv11); - buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - - DEBUG(4,("process_dgram: datagram from %s to %s for %s of type %d len=%d\n", - namestr(&dgram->source_name),namestr(&dgram->dest_name), - smb_buf(buf),CVAL(buf2,0),len)); - - - if (len <= 0) return; - - /* datagram packet received for the browser mailslot */ - if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) { - process_browse_packet(p,buf2,len); - return; - } - - /* datagram packet received for the domain log on mailslot */ - if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) { - process_logon_packet(p,buf2,len); - return; - } -} - -/**************************************************************************** - process a nmb packet - ****************************************************************************/ -static void process_nmb(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - - debug_nmb_packet(p); - - switch (nmb->header.opcode) - { - case 8: /* what is this?? */ - case NMB_REG: - case NMB_REG_REFRESH: - { - if (nmb->header.response) - { - if (nmb->header.ancount ==0) break; - response_netbios_packet(p); /* response to registration dealt - with here */ - } - else - { - if (nmb->header.qdcount==0 || nmb->header.arcount==0) break; - reply_name_reg(p); - } - break; - } - - case 0: - { - if (nmb->header.response) - { - switch (nmb->question.question_type) - { - case 0x0: - { - response_netbios_packet(p); - break; - } - } - return; - } - else if (nmb->header.qdcount>0) - { - switch (nmb->question.question_type) - { - case NMB_QUERY: - { - reply_name_query(p); - break; - } - case NMB_STATUS: - { - reply_name_status(p); - break; - } - } - return; - } - break; - } - - case NMB_REL: - { - if (nmb->header.response) - { - if (nmb->header.ancount ==0) break; - response_netbios_packet(p); /* response to release dealt - with here */ - } - else - { - if (nmb->header.qdcount==0 || nmb->header.arcount==0) break; - reply_name_release(p); - } - break; - } - } -} - - -/******************************************************************* - run elements off the packet queue till its empty - ******************************************************************/ -void run_packet_queue() -{ - struct packet_struct *p; - - while ((p=packet_queue)) - { - switch (p->packet_type) - { - case NMB_PACKET: - process_nmb(p); - break; - - case DGRAM_PACKET: - process_dgram(p); - break; - } - - packet_queue = packet_queue->next; - if (packet_queue) packet_queue->prev = NULL; - free_packet(p); - } -} - -/**************************************************************************** - listens for NMB or DGRAM packets, and queues them - ***************************************************************************/ -void listen_for_packets(BOOL run_election) -{ - fd_set fds; - int selrtn; - struct timeval timeout; - - FD_ZERO(&fds); - FD_SET(ClientNMB,&fds); - FD_SET(ClientDGRAM,&fds); - - /* during elections and when expecting a netbios response packet we - need to send election packets at tighter intervals - - ideally it needs to be the interval (in ms) between time now and - the time we are expecting the next netbios packet */ - - timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP; - timeout.tv_usec = 0; - - /* We can only take term signals when we are in the select. */ - BlockSignals(False, SIGTERM); - selrtn = sys_select(&fds,&timeout); - BlockSignals(True, SIGTERM); - - if (FD_ISSET(ClientNMB,&fds)) - { - struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET); - if (packet) - { - if (ismyip(packet->ip) && packet->port == NMB_PORT) - { - DEBUG(7,("discarding own packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } - else - { - queue_packet(packet); - } - } - } - - if (FD_ISSET(ClientDGRAM,&fds)) - { - struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET); - if (packet) - { - if (ismyip(packet->ip) && packet->port == DGRAM_PORT) - { - DEBUG(7,("discarding own packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } - else - { - queue_packet(packet); - } - } - } -} - - - -/**************************************************************************** - construct and send a netbios DGRAM - - Note that this currently sends all answers to port 138. thats the - wrong things to do! I should send to the requestors port. XXX - **************************************************************************/ -BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,char *srcname, - char *dstname,int src_type,int dest_type, - struct in_addr dest_ip,struct in_addr src_ip) -{ - struct packet_struct p; - struct dgram_packet *dgram = &p.packet.dgram; - char *ptr,*p2; - char tmp[4]; - - /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */ - if (ip_equal(wins_ip, dest_ip)) return False; - - bzero((char *)&p,sizeof(p)); - - update_name_trn_id(); - - /* DIRECT GROUP or UNIQUE datagram */ - dgram->header.msg_type = unique ? 0x10 : 0x11; - dgram->header.flags.node_type = M_NODE; - dgram->header.flags.first = True; - dgram->header.flags.more = False; - dgram->header.dgm_id = name_trn_id; - dgram->header.source_ip = src_ip; - dgram->header.source_port = DGRAM_PORT; - dgram->header.dgm_length = 0; /* let build_dgram() handle this */ - dgram->header.packet_offset = 0; - - make_nmb_name(&dgram->source_name,srcname,src_type,scope); - make_nmb_name(&dgram->dest_name,dstname,dest_type,scope); - - ptr = &dgram->data[0]; - - /* now setup the smb part */ - ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */ - memcpy(tmp,ptr,4); - set_message(ptr,17,17 + len,True); - memcpy(ptr,tmp,4); - - CVAL(ptr,smb_com) = SMBtrans; - SSVAL(ptr,smb_vwv1,len); - SSVAL(ptr,smb_vwv11,len); - SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); - SSVAL(ptr,smb_vwv13,3); - SSVAL(ptr,smb_vwv14,1); - SSVAL(ptr,smb_vwv15,1); - SSVAL(ptr,smb_vwv16,2); - p2 = smb_buf(ptr); - strcpy(p2,mailslot); - p2 = skip_string(p2,1); - - memcpy(p2,buf,len); - p2 += len; - - dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */ - - p.ip = dest_ip; - p.port = DGRAM_PORT; - p.fd = ClientDGRAM; - p.timestamp = time(NULL); - p.packet_type = DGRAM_PACKET; - - DEBUG(4,("send mailslot %s from %s %s", mailslot, - inet_ntoa(src_ip),namestr(&dgram->source_name))); - DEBUG(4,("to %s %s\n", inet_ntoa(dest_ip),namestr(&dgram->dest_name))); - - return(send_packet(&p)); -} diff --git a/source/namepacket.doc b/source/namepacket.doc deleted file mode 100644 index 159a50738c5..00000000000 --- a/source/namepacket.doc +++ /dev/null @@ -1,133 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namepacket.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -this module deals with packets: sending, receiving, queueing -and some basic interpretation (e.g it excludes datagram -error packets at the moment). - -the packet queueing mechanism was originally introduced when -samba dealt with responses by sending a packet, receiving -packets and queueing all packets that didn't match up with -the response expected. this is fine in a single-thread -environment, but samba now deals with response packets by -queueing the responses. to some extent, therefore, this -queue_packet mechanism is redundant. - - -/************************************************************************* - send_mailslot_reply() - *************************************************************************/ - -this function is responsible for sending a MAILSLOT packet. - -it will _not_ send packets to the pseudo WINS subnet's address of -255.255.255.255: this would be disastrous. - -each packet sent out has a unique transaction identifier. this is done -so that responses can be matched later with the original purpose for -the packet being sent out in the first place. - - -/************************************************************************* - listen_for_packets() - *************************************************************************/ - -this function is responsible for reading NMB and DGRAM packets, and then -queueing them. it will normally time-out for NMBD_SELECT_LOOP seconds, but -if there is an election currently running or we are expecting a response -then this time is reduced to 1 second. - -note: the time-out period needs refining to the millisecond level. - - -/************************************************************************* - queue_packet() - *************************************************************************/ - -this function is responsible for queueing any NMB and DGRAM packets passed -to it. these packets will be removed from the queue in run_packet_queue(). - - -/************************************************************************* - run_packet_queue() - *************************************************************************/ - -this function is responsible for taking a packet off the queue, -identifying whether it is an NMB or a DGRAM packet, processing -it accordingly and deleting it. this process continues until -there are no more packets on the queue. - - -/************************************************************************* - process_nmb() - *************************************************************************/ - -this function receives a packet identified as a netbios packet. -it further identifies whether it is a response or a query packet. -by identifying the type of packet (name registration, query etc) -process_nmb() will call the appropriate function to deal with the -type of packet received. - - -/************************************************************************* - process_dgram() - *************************************************************************/ - -this function is responsible for identifying whether the datagram -packet received is a browser packet or a domain logon packet. it -also does some filtering of certain types of packets (e.g it -filters out error packets). - - -/************************************************************************* - reply_netbios_packet() - *************************************************************************/ - -this function is responsible for sending a reply to another NetBIOS -packet from another host. it can be used to send a reply to a name -registration, name release, name query or name status request. - -the reply can be either a positive or a negative one. - - -/************************************************************************* - initiate_netbios_packet() - *************************************************************************/ - -this function is responsible for construction a netbios packet and sending -it. if the packet has not had a unique transaction id allocated to it, -then initiate_netbios_packet() will give it one. - - -/************************************************************************* - update_name_trn_id() - *************************************************************************/ - -this function is responsible for allocating unique transaction identifiers -for each new packet sent on the network. - - diff --git a/source/namequery.doc b/source/namequery.doc deleted file mode 100644 index 4337cfb7e2a..00000000000 --- a/source/namequery.doc +++ /dev/null @@ -1,83 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namequery.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -this module contains non-threaded versions of name status and name -query functions. if a multi-threaded nmbd was to be written, these -functions would be the starting point. - -at the moment, the expected response queueing system is used to -replace these functions without needing to multi-thread nmbd. - -these functions are used in smbclient and nmblookup at present to -avoid having the vast quantities of complex and unused code needed -to support even a simple name query (or providing stubs for the -unused side of these functions). - -there is a down-side to these functions, which is all microsoft's -fault. microsoft machines always always reply to queries on the -priveleged ports, rather than following the usual tcp/ip mechanism -of replying on the client's port (the exception to this i am led -to believe is windows nt 3.50). - -as a result of this, in order to receive a response to a name -query from a microsoft machine, we must be able to listen on -the priveleged netbios name server ports. this is simply not -possible with some versions of unix, unless you have root access. - -it is also not possible if you run smbclient or nmblookup on an -interface that already has been claimed by the netbios name server -daemon nmbd. - -all in all, i wish that microsoft would fix this. - -a solution does exist: nmbd _does_ actually reply on the client's -port, so if smbclient and nmblookup were to use nmbd as a proxy -forwarder of queries (or to use samba's WINS capabilities) then -a query could be made without needing access to the priveleged -ports. in order to do this properly, samba must implement secured -netbios name server functionality (see rfc1001.txt 15.1.6). -(lkcl 01aug96: samba now supports secured name registration) - -/************************************************************************* - name_query() - *************************************************************************/ - - - -/************************************************************************* - name_status() - *************************************************************************/ - - - -/************************************************************************* - _interpret_node_status() - *************************************************************************/ - - -this is a older version of interpret_node_status(). - diff --git a/source/nameresp.c b/source/nameresp.c deleted file mode 100644 index 27796ec07c4..00000000000 --- a/source/nameresp.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios library routines - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Module name: nameresp.c - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern struct subnet_record *subnetlist; - -extern int DEBUGLEVEL; - -extern pstring scope; -extern struct in_addr ipzero; -extern struct in_addr wins_ip; - - -/*************************************************************************** - deals with an entry before it dies - **************************************************************************/ -static void dead_netbios_entry(struct subnet_record *d, - struct response_record *n) -{ - DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n", - inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); - - debug_state_type(n->state); - - switch (n->state) - { - case NAME_QUERY_CONFIRM: - { - if (!lp_wins_support()) return; /* only if we're a WINS server */ - - if (n->num_msgs == 0) - { - /* oops. name query had no response. check that the name is - unique and then remove it from our WINS database */ - - /* IMPORTANT: see query_refresh_names() */ - - if ((!NAME_GROUP(n->nb_flags))) - { - struct subnet_record *d1 = wins_subnet; - if (d1) - { - /* remove the name that had been registered with us, - and we're now getting no response when challenging. - see rfc1001.txt 15.5.2 - */ - remove_netbios_name(d1, n->name.name, n->name.name_type, - REGISTER, n->send_ip); - } - } - } - break; - } - - case NAME_QUERY_MST_CHK: - { - /* if no response received, the master browser must have gone - down on that subnet, without telling anyone. */ - - /* IMPORTANT: see response_netbios_packet() */ - - if (n->num_msgs == 0) - browser_gone(n->name.name, n->send_ip); - break; - } - - case NAME_RELEASE: - { - /* if no response received, it must be OK for us to release the - name. nobody objected (including a potentially dead or deaf - WINS server) */ - - /* IMPORTANT: see response_name_release() */ - - if (ismyip(n->send_ip)) - { - name_unregister_work(d,n->name.name,n->name.name_type); - } - if (!n->bcast && n->num_msgs == 0) - { - DEBUG(0,("WINS server did not respond to name release!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - case NAME_REGISTER_CHALLENGE: - { - /* name challenge: no reply. we can reply to the person that - wanted the unique name and tell them that they can have it - */ - - add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, - n->nb_flags, GET_TTL(0), - n->reply_to_ip, False, n->reply_to_ip); - - if (!n->bcast && n->num_msgs == 0) - { - DEBUG(1,("WINS server did not respond to name registration!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - case NAME_REGISTER: - { - /* if no response received, and we are using a broadcast registration - method, it must be OK for us to register the name: nobody objected - on that subnet. if we are using a WINS server, then the WINS - server must be dead or deaf. - */ - if (n->num_msgs == 0) - { - if (n->bcast) - { - /* broadcast method: implicit acceptance of the name registration - by not receiving any objections. */ - - /* IMPORTANT: see response_name_reg() */ - - name_register_work(d,n->name.name,n->name.name_type, - n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); - } - else - { - /* received no response. rfc1001.txt states that after retrying, - we should assume the WINS server is dead, and fall back to - broadcasting (see bits about M nodes: can't find any right - now) */ - - DEBUG(1,("WINS server did not respond to name registration!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } - } - break; - } - - case NAME_QUERY_DOMAIN: - { - /* if no response was received, there is no domain controller for - this DOMAIN registered within WINS. it's ok for us to register - the DOMAIN<1b> name. - */ - - if (n->num_msgs == 0) - { - struct work_record *work = find_workgroupstruct(d,n->name.name,False); - if (work && d) - { - become_domain_master(d,work); - } - } - else - { - DEBUG(0, ("ERROR: nmbd configured as domain master and one already exitsts !!!\n")); - exit(1); - } - break; - } - - default: - { - /* nothing to do but delete the dead expected-response structure */ - /* this is normal. */ - break; - } - } -} - - -/******************************************************************* - remove old name response entries - - XXXX retry code needs to be added, including a retry wait period and a count - see name_query() and name_status() for suggested implementation. - - ******************************************************************/ -void expire_netbios_response_entries(time_t t) -{ - struct subnet_record *d; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct response_record *n, *nextn; - - for (n = d->responselist; n; n = nextn) - { - nextn = n->next; - - if (n->repeat_time <= t) - { - if (n->repeat_count > 0) - { - /* resend the entry */ - initiate_netbios_packet(&n->response_id, n->fd, n->quest_type, - n->name.name, n->name.name_type, - n->nb_flags, n->bcast, n->recurse, n->send_ip); - - n->repeat_time += n->repeat_interval; /* XXXX ms needed */ - n->repeat_count--; - - } - else - { - DEBUG(4,("timeout response %d for %s %s\n", - n->response_id, namestr(&n->name), - inet_ntoa(n->send_ip))); - - dead_netbios_entry(d,n); /* process the non-response */ - remove_response_record(d,n); /* remove the non-response */ - - continue; - } - } - } - } -} - - -/**************************************************************************** - wrapper function to override a broadcast message and send it to the WINS - name server instead, if it exists. if wins is false, and there has been no - WINS server specified, the packet will NOT be sent. - ****************************************************************************/ -struct response_record *queue_netbios_pkt_wins( - int fd,int quest_type,enum state_type state, - char *name,int name_type,int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) -{ - /* XXXX note: please see rfc1001.txt section 10 for details on this - function: it is currently inappropriate to use this - it will do - for now - once there is a clarification of B, M and P nodes and - which one samba is supposed to be - */ - - if ((!lp_wins_support()) && (*lp_wins_server())) - { - /* samba is not a WINS server, and we are using a WINS server */ - struct in_addr real_wins_ip; - real_wins_ip = *interpret_addr2(lp_wins_server()); - - if (!zero_ip(real_wins_ip)) - { - bcast = False; - send_ip = real_wins_ip; - } - else - { - /* oops. smb.conf's wins server parameter MUST be a host_name - or an ip_address. */ - DEBUG(0,("invalid smb.conf parameter 'wins server'\n")); - } - } - - if (zero_ip(send_ip)) return NULL; - - return queue_netbios_packet(wins_subnet,fd, quest_type, state, - name, name_type, nb_flags, ttl, - server_type,my_name,my_comment, - bcast, recurse, send_ip, reply_to_ip); -} - - -/**************************************************************************** - initiate a netbios name query to find someone's or someones' IP - this is intended to be used (not exclusively) for broadcasting to - master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get - complete lists across a wide area network - ****************************************************************************/ -struct response_record *queue_netbios_packet(struct subnet_record *d, - int fd,int quest_type,enum state_type state,char *name, - int name_type,int nb_flags, time_t ttl, - int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, - struct in_addr send_ip, struct in_addr reply_to_ip) -{ - struct response_record *n; - uint16 id = 0xffff; - - /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */ - if (ip_equal(wins_ip, send_ip)) return NULL; - - initiate_netbios_packet(&id, fd, quest_type, name, name_type, - nb_flags, bcast, recurse, send_ip); - - if (id == 0xffff) { - DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip))); - return NULL; - } - - if ((n = make_response_queue_record(state,id,fd, - quest_type,name,name_type,nb_flags,ttl, - server_type,my_name, my_comment, - bcast,recurse,send_ip,reply_to_ip))) - { - add_response_record(d,n); - return n; - } - return NULL; -} diff --git a/source/nameresp.doc b/source/nameresp.doc deleted file mode 100644 index cfe63500c88..00000000000 --- a/source/nameresp.doc +++ /dev/null @@ -1,178 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: nameresp.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -the netbios expected response code is a key part of samba's NetBIOS -handling capabilities. it allows samba to carry on dealing with -other things while expecting a response from one or more hosts. - -this allows samba to simultaneously deal with registering its names -with another WINS server, register its names on its local subnets, -query any hosts that have registered with samba in its capacity as -a WINS server, and at a later date it will be also be able handle -END-NODE CHALLENGES (see rfc1001.txt 15.2.2.2 and 15.2.2.3 - secured -NBNS functionality). - -all at once! - -when a netbios packet is sent out by samba and it expects a response, -a record of all the relevant information is kept (most importantly, -the unique transaction id associated which will come back to us in -a response packet is recorded, and also recorded is the reason that -the original packet was sent out by samba in the first place!). - -if a response is received, then the unique transaction identifier -returned in the response packet is searched for in the expected -response records. the record indicates why the initial request was -made (and therefore the type of response can be verified) and -appropriate action can be taken. - -when no responses, after a number of retries, are not received, then -samba may take appropriate action. this is a crucial part of samba's -operation: for a key number of NetBIOS operations, no response is an -implicit positive response. - -module nameresp deals with the initial transmission, re-transmission -and time-out of netbios response records. - -module namedbresp deals with the maintenance of the list of expected -responses - creation, finding and removal. - - -/************************************************************************* - queue_netbios_packet() - *************************************************************************/ - -this function is responsible for sending out a netbios packet, and then -making a record of the information that was sent out. a response will -be expected later (or not, as the case may be). - -if a response is received, response_netbios_packet() will deal with it. -otherwise, it will be dealt with in expire_netbios_response_entries(). - - -/************************************************************************* - queue_netbios_pkt_wins() - *************************************************************************/ - -this function is a wrapper around queue_netbios_packet(). there is -some confusion about B, M and P nodes (see rfc1001.txt section 10) - -confusion introduced by luke :-) - which needs sorting out. - -for example, rfc1001.txt 15.2.3 - an M node must attempt to register a -name first as a B node, then attempt to register as an M node. negative -responses on either of these attempts is a failure to register the -name. - -this is NOT the case with a P node. - - -/************************************************************************* - expire_netbios_response_entries() - *************************************************************************/ - -this function is responsible for dealing with queued response records -that have not received a response packet matching their unique -transaction id. - -if the retry count for any record is non-zero, and its time-out period -has expired, the retry count is reduced, the time-out period is stepped -forward and the packet is re-transmitted (from the information stored -in the queued response record) with the same unique transaction id of -the initial attempt at soliciting a response. - -if the retry count is zero, then the packet is assumed to have expired. -dead_netbios_entry() is called to deal with the possibility of an error -or a problem (or in certain instances, no answer is an implicit -positive response!). - -the expected response record is then deleted, and the number of expected -responses reduced. when this count gets to zero, listen_for_packets() -will no longer time-out for 1 second on account of expecting response -packets. - - -/************************************************************************* - dead_netbios_entry() - *************************************************************************/ - -this function is responsible for dealing with the case when a NetBIOS -response to a packet sent out by samba was not received. for certain -transactions, this may be normal. for others, under certain conditions -it may constitute either an error or a problem with or failure of one -or more hosts. - -- NAME_QUERY_CONFIRM - -when a samba 'state' of type NAME_QUERY_CONFIRM is sent, a response -may or may not be forthcoming. if no response is received to a unique -name, then the record is removed from samba's WINS database. non-unique -names are simply expected to die off on a time-to-live basis (see -rfc1001.txt 15.1.3.4) - -query_refresh_names() issues this samba 'state' -response_name_query_sync() deals with responses to NAME_QUERY_CONFIRM. - -- NAME_QUERY_MST_CHK - -when a samba 'state' of type NAME_QUERY_MST_CHK is sent, and a response -is not received, this implies that a master browser will have failed. -remedial action may need to be taken, for example if samba is a member -of that workgroup and it is also a potential master browser it could -force an election. - -check_master_browser() issues this samba 'state'. -response_process() does nothing if a response is received. this is normal. - -- NAME_RELEASE - -when a samba 'state' of type NAME_RELEASE is sent, and a response is -not received, it is assumed to be acceptable to release the name. if the -original response was sent to another WINS server, then that WINS server -may be inaccessible or may have failed. if so, then at a later date -samba should take this into account (see rfc1001.txt 10.3). - -remove_name_entry() issues this samba 'state' -response_name_rel() deals with responses to NAME_RELEASE. - -- NAME_REGISTER - -when a samba 'state' of type NAME_REGISTER is sent, and a response is -not received, if the registration was done by broadcast, it is assumed -that there are no objections to the registration of this name, and samba -adds the name to the appropriate subnet record name database. if the -registration was point-to-point (i.e with another WINS server) then that -WINS server may be inaccessible or may have failed. if so, then at a later -date samba should take this into account (see rfc1001.txt 10.3). - -add_my_name_entry() issues this samba 'state' -response_name_reg() deals with responses to NAME_REGISTER. - -no action is taken for any other kinds of samba 'states' if a response -is not received. this is not to say that action may not be appropriate, -just that it's not been looked at yet :-) - - diff --git a/source/nameserv.c b/source/nameserv.c deleted file mode 100644 index f1b34482c85..00000000000 --- a/source/nameserv.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Module name: nameserv.c - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - module nameserv contains name server management functions -*/ - -#include "includes.h" - -extern int ClientNMB; - -extern int DEBUGLEVEL; - -extern pstring scope; -extern pstring myname; -extern fstring myworkgroup; -extern struct in_addr ipzero; -extern struct in_addr wins_ip; - -extern struct subnet_record *subnetlist; - -extern uint16 nb_type; /* samba's NetBIOS type */ - -/**************************************************************************** - remove an entry from the name list - - note: the name will _always_ be removed - XXXX at present, the name is removed _even_ if a WINS server says keep it. - - If direct is True then the name being removed must have been a direct name - add. This is done for special names such as DOMAIN<1b>. Just delete it - without any network release traffic. - - ****************************************************************************/ -void remove_name_entry(struct subnet_record *d, char *name,int type, BOOL direct) -{ - /* XXXX BUG: if samba is offering WINS support, it should still broadcast - a de-registration packet to the local subnet before removing the - name from its local-subnet name database. */ - - int search = FIND_SELF; - struct name_record n; - struct name_record *n2=NULL; - - make_nmb_name(&n.name,name,type,scope); - - if(d == wins_subnet) - search |= FIND_WINS; - else - search |= FIND_LOCAL; - - if ((n2 = find_name_search(&d, &n.name, search, ipzero))) - { - /* check name isn't already being de-registered */ - if (NAME_DEREG(n2->ip_flgs[0].nb_flags)) - return; - - /* mark the name as in the process of deletion. */ - n2->ip_flgs[0].nb_flags &= NB_DEREG; - } - - if (!n2) return; - - /* Only remove names with non-zero death times. */ - if(n2->death_time == 0) - { - DEBUG(5,("remove_name_entry: Name %s(%d) has zero ttl - not removing.\n", - name, type)); - return; - } - - /* remove the name immediately. even if the spec says we should - first try to release them, this is too dangerous with our current - name structures as otherwise we will end up replying to names we - don't really own */ - remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip); - - if (ip_equal(d->bcast_ip, wins_ip)) - { - if (!lp_wins_support() && !direct) - { - /* not a WINS server: we have to release them on the network */ - queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE, - name, type, 0, 0,0,NULL,NULL, - False, True, ipzero, ipzero); - } - } - else - { - if(!direct) - /* local interface: release them on the network */ - queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE, - name, type, 0, 0,0,NULL,NULL, - True, False, d->bcast_ip, d->bcast_ip); - } -} - - -/**************************************************************************** - add an entry to the name list - If the direct BOOL is set then no network traffic is done for the add - it - is just blasted into the subnet entry with a zero TTL - it will not - expire and has not been legitimately claimed. This is *only* done if - we are a WINS server or for a special name such as DOMAIN<1b>. - - big note: our name will _always_ be added (if there are no objections). - it's just a matter of when this will be done (e.g after a time-out). - - ****************************************************************************/ -void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags, BOOL direct) -{ - BOOL re_reg = False; - struct nmb_name n; - - if (!d) return; - - /* not that it particularly matters, but if the SELF name already exists, - it must be re-registered, rather than just registered */ - - make_nmb_name(&n, name, type, scope); - if (find_name(d->namelist, &n, SELF)) - re_reg = True; - - /* XXXX BUG: if samba is offering WINS support, it should still add the - name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28 - regarding the point about M-nodes. */ - - if (ip_equal(d->bcast_ip, wins_ip)) - { - if (lp_wins_support() || direct) - { - /* we are a WINS server. */ - if(lp_wins_support()) - DEBUG(4,("add_my_name_entry: samba as WINS server adding: ")); - else - DEBUG(4,("add_my_name_entry: direct name entry : adding: ")); - - /* this will call add_netbios_entry() */ - name_register_work(d, name, type, nb_flags,0, ipzero, False); - } - else - { - DEBUG(4,("add_my_name_entry registering name %s with WINS server.\n", - name)); - - /* a time-to-live allows us to refresh this name with the WINS server. */ - queue_netbios_pkt_wins(ClientNMB, - re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, - name, type, nb_flags, GET_TTL(0),0,NULL,NULL, - False, True, ipzero, ipzero); - } - } - else - { - if(direct) - { - /* Just enter the name to be the ip address of the subnet - via name_register_work to ensure all side effects are done. - */ - DEBUG(4,("add_my_name_entry: direct name entry : adding: ")); - /* this will call add_netbios_entry() */ - name_register_work(d, name, type, nb_flags,0, d->myip, False); - } - else - { - /* broadcast the packet, but it comes from ipzero */ - queue_netbios_packet(d,ClientNMB, - re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, - name, type, nb_flags, GET_TTL(0),0,NULL,NULL, - True, False, d->bcast_ip, ipzero); - } - } -} - - -/**************************************************************************** - add the domain logon server and domain master browser names - - this code was written so that several samba servers can co-operate in - sharing the task of (one server) being a domain master, and of being - domain logon servers. - - **************************************************************************/ -void add_domain_names(time_t t) -{ - static time_t lastrun = 0; - struct subnet_record *d; - struct work_record *work; - struct nmb_name n; - - if (lastrun != 0 && t < lastrun + CHECK_TIME_ADD_DOM_NAMES * 60) return; - lastrun = t; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - work = find_workgroupstruct(d, myworkgroup, False); - if (lp_domain_logons() && work && work->log_state == LOGON_NONE) - { - make_nmb_name(&n,myworkgroup,0x1c,scope); - if (!find_name(d->namelist, &n, FIND_SELF)) - { - /* logon servers are group names - we don't expect this to fail. */ - DEBUG(0,("%s attempting to become logon server for %s %s\n", - timestring(), myworkgroup, inet_ntoa(d->bcast_ip))); - become_logon_server(d, work); - } - } - } - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - work = find_workgroupstruct(d, myworkgroup, True); - - if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE) - { - make_nmb_name(&n,myworkgroup,0x1b,scope); - if (!find_name(d->namelist, &n, FIND_SELF)) - { - DEBUG(0,("%s add_domain_names: attempting to become domain master \ -browser on workgroup %s %s\n", - timestring(), myworkgroup, inet_ntoa(d->bcast_ip))); - - if(d == wins_subnet) - { - if (lp_wins_support()) - { - /* use the wins server's capabilities (indirectly). if - someone has already registered the domain<1b> name with - the WINS server, then the WINS server's job is to _check_ - that the owner still wants it, before giving it away. - */ - - DEBUG(1,("%s initiating becoming domain master for %s\n", - timestring(), myworkgroup)); - become_domain_master(d, work); - } - else - { - /* send out a query to establish whether there's a - domain controller on the WINS subnet. if not, - we can become a domain controller. - it's only polite that we check, before claiming the - NetBIOS name 0x1b. - */ - - DEBUG(0,("add_domain_names:querying WINS for domain master \ -on workgroup %s\n", myworkgroup)); - - queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,NAME_QUERY_DOMAIN, - myworkgroup, 0x1b, - 0, 0,0,NULL,NULL, - False, True, ipzero, ipzero); - } - } - else - { - DEBUG(0,("add_domain_names:querying subnet %s for domain master \ -on workgroup %s\n", inet_ntoa(d->bcast_ip), myworkgroup)); - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOMAIN, - myworkgroup, 0x1b, - 0, 0,0,NULL,NULL, - True, False, - d->bcast_ip, d->bcast_ip); - } - } - } - } -} - - -/**************************************************************************** - add the magic samba names, useful for finding samba servers - **************************************************************************/ -void add_my_names(void) -{ - struct subnet_record *d; - /* each subnet entry, including WINS pseudo-subnet, has SELF names */ - - /* XXXX if there was a transport layer added to samba (ipx/spx etc) then - there would be yet _another_ for-loop, this time on the transport type - */ - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - BOOL wins = (lp_wins_support() && (d == wins_subnet)); - - add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE,False); - add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE,False); - add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE,False); - - /* these names are added permanently (ttl of zero) and will NOT be - refreshed with the WINS server */ - add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); - add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); - add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); - add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins); - } -} - - -/**************************************************************************** - remove all the samba names... from a WINS server if necessary. - **************************************************************************/ -void remove_my_names() -{ - struct subnet_record *d; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct name_record *n, *next; - - for (n = d->namelist; n; n = next) - { - next = n->next; - if (n->source == SELF) - { - /* get all SELF names removed from the WINS server's database */ - /* XXXX note: problem occurs if this removes the wrong one! */ - - remove_name_entry(d,n->name.name, n->name.name_type,False); - } - } - } -} - - -/******************************************************************* - refresh my own names - ******************************************************************/ -void refresh_my_names(time_t t) -{ - struct subnet_record *d; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct name_record *n; - - for (n = d->namelist; n; n = n->next) - { - /* each SELF name has an individual time to be refreshed */ - if (n->source == SELF && n->refresh_time < t && - n->death_time != 0) - { - add_my_name_entry(d,n->name.name,n->name.name_type, - n->ip_flgs[0].nb_flags,False); - /* they get a new lease on life :-) */ - n->death_time += GET_TTL(0); - n->refresh_time += GET_TTL(0); - } - } - } -} - - -/******************************************************************* - queries names occasionally. an over-cautious, non-trusting WINS server! - - this function has been added because nmbd could be restarted. it - is generally a good idea to check all the names that have been - reloaded from file. - - XXXX which names to poll and which not can be refined at a later date. - ******************************************************************/ -void query_refresh_names(time_t t) -{ - struct name_record *n; - struct subnet_record *d = wins_subnet; - - static time_t lasttime = 0; - - int count = 0; - int name_refresh_time = NAME_POLL_REFRESH_TIME; - int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL; - if (max_count > 10) max_count = 10; - - name_refresh_time = NAME_POLL_INTERVAL * max_count / 2; - - /* if (!lp_poll_wins()) return; polling of registered names allowed */ - - if (!d) return; - - if (!lasttime) lasttime = t; - if (t - lasttime < NAME_POLL_INTERVAL) return; - - lasttime = time(NULL); - - for (n = d->namelist; n; n = n->next) - { - /* only do unique, registered names */ - - if (n->source != REGISTER) continue; - if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue; - - if (n->refresh_time < t) - { - DEBUG(3,("Polling name %s\n", namestr(&n->name))); - - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, - n->name.name, n->name.name_type, - 0,0,0,NULL,NULL, - False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); - count++; - } - - if (count >= max_count) - { - /* don't do too many of these at once, but do enough to - cover everyone in the list */ - return; - } - - /* this name will be checked on again, if it's not removed */ - n->refresh_time += name_refresh_time; - } -} - diff --git a/source/nameserv.doc b/source/nameserv.doc deleted file mode 100644 index af4934ade21..00000000000 --- a/source/nameserv.doc +++ /dev/null @@ -1,159 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: nameserv.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -this module deals with general maintenance of NetBIOS names. - -/************************************************************************* - query_refresh_names() - *************************************************************************/ - -this function is responsible for polling all names registered in the -WINS database. it is planned to enable this function should samba -detect an inconsistency on the network, which could occur if the -samba NetBIOS daemon dies and is restarted. - -polling is done very infrequently, but all names will be covered -within a period NAME_POLL_REFRESH_TIME. a group of at most ten names -will be queried at once, at intervals of NAME_POLL_INTERVAL seconds. -if the total number of names queried in this way will take too long, -then the time that an individual name will next be polled is -increased accordingly. - -name query polling is functionality over-and-above the normal -requirement (see rfc1001.txt 15.1.7 point 7). it is normally the -responsibility of the owner of a name to re-register the name at -regular intervals. - - -/************************************************************************* - refresh_my_names() - *************************************************************************/ - -this function is responsible for refreshing samba's names that have -been registered with other servers on a local subnet, or with another -WINS server if samba is using one. - -samba's names' refresh_time will be updated through the use of the function -add_my_name_entry(). - - -/************************************************************************* - remove_my_names() - *************************************************************************/ - -this function is responsible for removing all samba's SELF names. it -is used when samba receives a SIG_TERM. samba at present does not wait -for the WINS server to reply to the name releases sent out. - - -/************************************************************************* - add_my_names() - *************************************************************************/ - -this function is responsible for adding and registering if necessary all -samba's SELF names, on each of its local subnets and with another WINS -server if samba is using one. - -/************************************************************************* - add_my_name_entry() - *************************************************************************/ - -this function is responsible for registering or re-registering one of -samba's names, either on the local subnet or with another WINS server -if samba is using one. - -if the name is already in samba's database, then it is re-registered, -otherwise it is simply registered. - -if the name is being registered in a WINS capacity (the subnet to which -the name should be added is the WINS pseudo-subnet) then we add the entry -immediately if samba is a WINS server. it uses name_register_work() -because if the name is being added as part of becoming a master browser, -we want to carry on that process. if the name is registered with another -WINS server, we must wait for an answer from that WINS server. either -name_register_work() or name_unregister_work() will be called as a result. - -if the name is being registered on a local subnet, then it is -broadcast. an explicit rejection from another host will result -in name_unregister_work() being called. no response will, after -retrying, result in name_register_work() being called. - -what ever method is used, the name will either be registered -or rejected, and what ever process was taking place (becoming -a master browser for example) will carry on. - -expire_netbios_response_entries() is responsible for taking further -action if no response to the registration is received. - -note that there may be a large number of function calls on the -stack if become_master() is called and samba is configured as -a WINS server. the loop will be: - -become_master(), add_my_name_entry(), name_register_work() and -back to become_master() with the new value of the workgroup -'state'. - - -/************************************************************************* - remove_name_entry() - *************************************************************************/ - -this function is responsible for removing a NetBIOS name. if the name -being removed is registered on a local subnet, a name release should be -broadcast on the local subnet. - -if the name is being released in a WINS capacity (the subnet to -which the name should be added is the WINS pseudo-subnet) then we -remove the entry immediately if samba is a WINS server. it uses -name_unregister_work() because if the name is being added as part of -becoming a master browser, we want to terminate that process. if the -name is released from another WINS server, we must wait for an -answer from that WINS server. name_unregister_work() will -definitely be called as a result, because at present we ignore -negative responses for a name release from a WINS server. - -if the name is being releasedd on a local subnet, then it is -broadcast. name_unregister_work() will definitely be called -because we ignore negative name releases at present. - -what ever method is used, the name will be released. (NOT TRUE! -see response_name_release()) - -expire_netbios_response_entries() is responsible for taking further action -if no response to the name release is received. - - -/************************************************************************* - load_netbios_names() - *************************************************************************/ - -this function is responsible for loading any NetBIOS names that samba, -in its WINS capacity, has written out to disk. all the relevant details -are recorded in this file, including the time-to-live. should the -time left to live be small, the name is not added back in to samba's -WINS database. - diff --git a/source/nameservreply.c b/source/nameservreply.c deleted file mode 100644 index 9e46b803039..00000000000 --- a/source/nameservreply.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Module name: nameservreply.c - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 04 jul 96: lkcl@pires.co.uk - created module nameservreply containing NetBIOS reply functions - -*/ - -#include "includes.h" - -extern int ClientNMB; - -extern int DEBUGLEVEL; - -extern struct in_addr wins_ip; - -/**************************************************************************** -send a registration / release response: pos/neg -**************************************************************************/ -static void send_name_response(int fd, struct in_addr from_ip, - int name_trn_id, int opcode, BOOL success, BOOL recurse, - struct nmb_name *reply_name, int nb_flags, int ttl, - struct in_addr ip) -{ - char rdata[6]; - struct packet_struct p; - - int rcode = 0; - - if (success == False) - { - /* NEGATIVE RESPONSE */ - rcode = 6; - } - else if (opcode == NMB_REG && recurse == False) - { - /* END-NODE CHALLENGE REGISTRATION RESPONSE */ - rcode = 0; - } - - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&ip); - - p.ip = from_ip; - p.port = NMB_PORT; - p.fd = fd; - p.timestamp = time(NULL); - p.packet_type = NMB_PACKET; - - reply_netbios_packet(&p,name_trn_id, - rcode,opcode,opcode,recurse, - reply_name, 0x20, 0x1, - ttl, - rdata, 6); -} - -/**************************************************************************** - add a netbios entry. respond to the (possibly new) owner. - **************************************************************************/ -void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, - uint16 response_id, - struct nmb_name *name, - int nb_flags, int ttl, struct in_addr register_ip, - BOOL new_owner, struct in_addr reply_to_ip) -{ - /* register the old or the new owners' ip */ - add_netbios_entry(d,name->name,name->name_type, - nb_flags,ttl,REGISTER,register_ip,False,True); - - /* reply yes or no to the host that requested the name */ - send_name_response(fd,from_ip, response_id, NMB_REG, - new_owner, False, - name, nb_flags, ttl, reply_to_ip); -} - - -/**************************************************************************** -reply to a name release -****************************************************************************/ -void reply_name_release(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr ip; - int nb_flags = nmb->additional->rdata[0]; - BOOL bcast = nmb->header.nm_flags.bcast; - struct name_record *n; - struct subnet_record *d = NULL; - int search = 0; - BOOL success = False; - - putip((char *)&ip,&nmb->additional->rdata[2]); - - DEBUG(3,("Name release on name %s\n", - namestr(&nmb->question.question_name))); - - if (!(d = find_req_subnet(p->ip, bcast))) - { - DEBUG(3,("response packet: bcast %s not known\n", - inet_ntoa(p->ip))); - return; - } - - if (bcast) - search |= FIND_LOCAL; - else - search |= FIND_WINS; - - n = find_name_search(&d, &nmb->question.question_name, - search, ip); - - /* XXXX under what conditions should we reject the removal?? */ - /* For now - remove if the names match and the group bit matches. */ - if (n && (n->source != SELF) && (NAME_GROUP(n->ip_flgs[0].nb_flags) == NAME_GROUP(nb_flags))) - { - success = True; - - DEBUG(5, ("reply_name_release: Removing name %s on subnet %s\n", - namestr(&nmb->question.question_name), inet_ntoa(d->bcast_ip))); - remove_name(d,n); - n = NULL; - } - - if (bcast) return; - - /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ - send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL, - success, nmb->header.nm_flags.recursion_desired, - &nmb->question.question_name, nb_flags, 0, ip); -} - - -/**************************************************************************** -reply to a reg request -**************************************************************************/ -void reply_name_reg(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - - struct nmb_name *reply_name = question; - - char *qname = question->name; - int qname_type = question->name_type; - - BOOL bcast = nmb->header.nm_flags.bcast; - - int ttl = GET_TTL(nmb->additional->ttl); - int nb_flags = nmb->additional->rdata[0]; - BOOL group = NAME_GROUP(nb_flags); - - struct subnet_record *d = NULL; - struct name_record *n = NULL; - - BOOL success = True; - BOOL secured_redirect = False; - - struct in_addr ip, from_ip; - int search = 0; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - ip = from_ip; - - DEBUG(3,("Name registration for name %s at %s - ", - namestr(question),inet_ntoa(ip))); - - if (group) - { - /* apparently we should return 255.255.255.255 for group queries - (email from MS) */ - ip = *interpret_addr2("255.255.255.255"); - } - - if (!(d = find_req_subnet(p->ip, bcast))) - { - DEBUG(3,("reply_name_reg: subnet %s not known\n", - inet_ntoa(p->ip))); - return; - } - - if (bcast) - search |= FIND_LOCAL; - else - search |= FIND_WINS; - - /* see if the name already exists */ - n = find_name_search(&d, question, search, from_ip); - - if (n) - { - DEBUG(3,("found\n")); - if (!group) /* unique names */ - { - if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags)) - { - /* no-one can register one of samba's names, nor can they - register a name that's a group name as a unique name */ - - success = False; - } - else if(!ip_equal(ip, n->ip_flgs[0].ip)) - { - /* XXXX rfc1001.txt says: - * if we are doing secured WINS, we must send a Wait-Acknowledge - * packet (WACK) to the person who wants the name, then do a - * name query on the person who currently owns the unique name. - * if the current owner still says they own it, the person who wants - * the name can't have it. if they do not, or are not alive, they can. - */ - - secured_redirect = True; - - reply_name = &n->name; - } - else - { - n->ip_flgs[0].ip = ip; - n->death_time = ttl?p->timestamp+ttl*3:0; - DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip_flgs[0].ip))); - } - } - else - { - /* refresh the name */ - if (n->source != SELF) - { - n->death_time = ttl?p->timestamp + ttl*3:0; - } - } - - /* XXXX bug reported by terryt@ren.pc.athabascau.ca */ - /* names that people have checked for and not found get DNSFAILed. - we need to update the name record if someone then registers */ - - if (n->source == DNSFAIL) - n->source = REGISTER; - - } - else - { - DEBUG(3,("not found\n")); - /* add the name to our name/subnet, or WINS, database */ - n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip, - True,!bcast); - } - - /* if samba owns a unique name on a subnet, then it must respond and - disallow the attempted registration. if the registration is - successful by broadcast, only then is there no need to respond - (implicit registration: see rfc1001.txt 15.2.1). - */ - - if (bcast && success) return; - - if (secured_redirect) - { - char rdata[2]; - - /* XXXX i am confused. RSVAL or SSVAL? assume NMB byte ordering */ - RSSVAL(rdata,0,(nmb->header.opcode&0xf) + ((nb_flags&0xff) << 4)); - - /* XXXX mistake in rfc1002.txt? 4.2.16: NULL is 0xa see 4.2.1.3 - type = 0x0a; see rfc1002.txt 4.2.1.3 - class = 0x01; see rfc1002.txt 4.2.16 - */ - - /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */ - reply_netbios_packet(p,nmb->header.name_trn_id, - 0,NMB_WAIT_ACK,NMB_WAIT_ACK,False, - reply_name, 0x0a, 0x01, - 15*1000, /* 15 seconds long enough to wait? */ - rdata, 2); - - /* initiate some enquiries to the current owner. */ - queue_netbios_packet(d,ClientNMB,NMB_QUERY, - NAME_REGISTER_CHALLENGE, - reply_name->name,reply_name->name_type, - nb_flags,0,0,NULL,NULL, - False, False, n->ip_flgs[0].ip, p->ip); - } - else - { - /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.13-14 - or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7 - */ - - send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG, - success, nmb->header.nm_flags.recursion_desired, - reply_name, nb_flags, ttl, ip); - } -} - -/* this is used to sort names for a name status into a sensible order - we put our own names first, then in alphabetical order */ -static int status_compare(char *n1,char *n2) -{ - extern pstring myname; - int l1,l2,l3; - - /* its a bit tricky because the names are space padded */ - for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ; - for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ; - l3 = strlen(myname); - - if ((l1==l3) && strncmp(n1,myname,l3) == 0 && - (l2!=l3 || strncmp(n2,myname,l3) != 0)) - return -1; - - if ((l2==l3) && strncmp(n2,myname,l3) == 0 && - (l1!=l3 || strncmp(n1,myname,l3) != 0)) - return 1; - - return memcmp(n1,n2,18); -} - - -/**************************************************************************** - reply to a name status query - - combine the list of the local interface on which the query was made with - the names registered via wins. - ****************************************************************************/ -void reply_name_status(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char *qname = nmb->question.question_name.name; - int ques_type = nmb->question.question_name.name_type; - char rdata[MAX_DGRAM_SIZE]; - char *countptr, *buf, *bufend, *buf0; - int names_added,i; - struct name_record *n; - struct subnet_record *d = NULL; - int search = FIND_SELF | FIND_WINS | FIND_LOCAL; - - /* NOTE: we always treat a name status lookup as a bcast */ - if (!(d = find_req_subnet(p->ip, True))) - { - DEBUG(3,("Name status req: bcast %s not known\n", - inet_ntoa(p->ip))); - return; - } - - DEBUG(3,("Name status for name %s %s\n", - namestr(&nmb->question.question_name), - inet_ntoa(p->ip))); - - n = find_name_search(&d, &nmb->question.question_name, - search, p->ip); - - if (!n) return; - - /* XXXX hack, we should calculate exactly how many will fit */ - bufend = &rdata[MAX_DGRAM_SIZE] - 18; - countptr = buf = rdata; - buf += 1; - buf0 = buf; - - names_added = 0; - - n = d->namelist; - - while (buf < bufend) - { - if (n->source == SELF) - { - int name_type = n->name.name_type; - - /* check if we want to exclude other workgroup names - from the response. if we don't exclude them, windows clients - get confused and will respond with an error for NET VIEW */ - - if (!strequal(n->name.name,"*") && - !strequal(n->name.name,"__SAMBA__") && - (name_type < 0x1b || name_type >= 0x20 || - ques_type < 0x1b || ques_type >= 0x20 || - strequal(qname, n->name.name))) - { - /* start with first bit of putting info in buffer: the name */ - bzero(buf,18); - sprintf(buf,"%-15.15s",n->name.name); - strupper(buf); - - /* put name type and netbios flags in buffer */ - buf[15] = name_type; - buf[16] = n->ip_flgs[0].nb_flags; - - buf += 18; - - names_added++; - } - } - - /* remove duplicate names */ - qsort(buf0,names_added,18,QSORT_CAST status_compare); - - for (i=1;i<names_added;i++) { - if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) { - names_added--; - if (names_added == i) break; - memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i)); - i--; - } - } - - buf = buf0 + 18*names_added; - - n = n->next; - - if (!n) - { - /* end of this name list: add wins names too? */ - struct subnet_record *w_d; - - if (!(w_d = wins_subnet)) break; - - if (w_d != d) - { - d = w_d; - n = d->namelist; /* start on the wins name list */ - } - } - if (!n) break; - } - - SCVAL(countptr,0,names_added); - - /* XXXXXXX we should fill in more fields of the statistics structure */ - bzero(buf,64); - { - extern int num_good_sends,num_good_receives; - SIVAL(buf,20,num_good_sends); - SIVAL(buf,24,num_good_receives); - } - - buf += 46; - - /* Send a POSITIVE NAME STATUS RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id, - 0,NMB_STATUS,0,True, - &nmb->question.question_name, - 0x21, 0x01, - 0, rdata,PTR_DIFF(buf,rdata)); -} - - -/*************************************************************************** -reply to a name query. - -with broadcast name queries: - - - only reply if the query is for one of YOUR names. all other machines on - the network will be doing the same thing (that is, only replying to a - broadcast query if they own it) - NOTE: broadcast name queries should only be sent out by a machine - if they HAVEN'T been configured to use WINS. this is generally bad news - in a wide area tcp/ip network and should be rectified by the systems - administrator. USE WINS! :-) - - the exception to this is if the query is for a Primary Domain Controller - type name (0x1b), in which case, a reply is sent. - - - NEVER send a negative response to a broadcast query. no-one else will! - -with directed name queries: - - - if you are the WINS server, you are expected to respond with either - a negative response, a positive response, or a wait-for-acknowledgement - packet, and then later on a pos/neg response. - -****************************************************************************/ -void reply_name_query(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - int name_type = question->name_type; - BOOL bcast = nmb->header.nm_flags.bcast; - int ttl=0; - int rcode = 0; - int nb_flags = 0; - struct in_addr retip; - char rdata[6]; - struct subnet_record *d = NULL; - BOOL success = True; - struct name_record *n = NULL; - - /* directed queries are for WINS server: broadcasts are local SELF queries. - the exception is Domain Master names. */ - - int search = bcast ? FIND_LOCAL | FIND_WINS: FIND_WINS; - - if (search & FIND_LOCAL) - { - if (!(d = find_req_subnet(p->ip, bcast))) - { - DEBUG(3,("name query: bcast %s not known\n", - inet_ntoa(p->ip))); - success = False; - } - } - else - { - if (!(d = wins_subnet)) - { - DEBUG(3,("name query: wins search %s not known\n", - inet_ntoa(p->ip))); - success = False; - } - } - - DEBUG(3,("Name query from %s for name %s<0x%x>\n", - inet_ntoa(p->ip), question->name, question->name_type)); - - if (search == 0) - { - /* eh? no criterion for searching database. help! */ - success = False; - } - - if (!bcast && (name_type == 0x1d) && lp_wins_support()) - { - /* see WINS manager HELP - 'How WINS Handles Special Names' */ - /* a WINS query (unicasted) for a 0x1d name must always return False */ - success = False; - } - - if (success) - { - /* look up the name in the cache */ - n = find_name_search(&d, question, search, p->ip); - - /* it is a name that already failed DNS lookup or it's expired */ - if (n && (n->source == DNSFAIL || - (n->death_time && n->death_time < p->timestamp))) - { - success = False; - } - - /* do we want to do dns lookups? */ - /* XXXX this DELAYS nmbd while it does a search. not a good idea - but there's no pleasant alternative. phil@hands.com suggested - making the name a full DNS name, which would succeed / fail - much quicker. - */ - if (success && !n && (lp_wins_proxy() || !bcast)) - { - n = dns_name_search(question, p->timestamp); - } - } - - if (!n) success = False; - - if (success) - { - if (bcast && n->source != SELF && name_type != 0x1b) - { - /* don't respond to broadcast queries unless the query is for - a name we own or it is for a Primary Domain Controller name */ - - if (!lp_wins_proxy() || - same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip))) - { - /* never reply with a negative response to broadcast queries */ - return; - } - } - - /* name is directed query, or it's self, or it's a Domain Master type - name, or we're replying on behalf of a caller because they are on a - different subnet and cannot hear the broadcast. XXXX lp_wins_proxy - should be switched off in environments where broadcasts are forwarded - */ - - /* XXXX note: for proxy servers, we should forward the query on to - another WINS server if the name is not in our database, or we are - not a WINS server ourselves - */ - ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0); - retip = n->ip_flgs[0].ip; - nb_flags = n->ip_flgs[0].nb_flags; - } - - if (!success && bcast) return; /* never reply negative response to bcasts */ - - /* if the IP is 0 then substitute my IP */ - if (zero_ip(retip)) retip = *iface_ip(p->ip); - - /* SPECIAL CASE... If we are a WINS server and the request is explicitly - *to* the WINS server and the name type is WORKGROUP<0x1e> we should - respond with the local broadcast address 255.255.255.255. - */ - if(!bcast && (name_type == 0x1e) && lp_wins_support()) - retip = *interpret_addr2("255.255.255.255"); - - if (success) - { - rcode = 0; - DEBUG(3,("OK %s\n",inet_ntoa(retip))); - } - else - { - rcode = 3; - DEBUG(3,("UNKNOWN\n")); - } - - if (success) - { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&retip); - } - - reply_netbios_packet(p,nmb->header.name_trn_id, - rcode,NMB_QUERY,0,True, - &nmb->question.question_name, - 0x20, 0x01, - ttl, - rdata, success ? 6 : 0); -} diff --git a/source/nameservreply.doc b/source/nameservreply.doc deleted file mode 100644 index a5acf8a9c26..00000000000 --- a/source/nameservreply.doc +++ /dev/null @@ -1,213 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: nameservreply.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -/************************************************************************* - reply_name_query() - *************************************************************************/ - -this function is responsible for replying to a NetBIOS name query. - -there are two kinds of name queries: directed, and broadcast. directed -queries are usually sent to samba in its WINS capacity. such hosts are -termed 'point-to-point' hosts. broadcast queries are usually sent from -'broadcast' or 'mixed' hosts. - -broadcasting is used by either older NetBIOS hosts, new NetBIOS hosts that -have not had WINS capabilities added and new NetBIOS hosts that think the -WINS server has died. - -the samba NetBIOS name database is divided into sections, on a -per-subnet basis. there is also a WINS NetBIOS name database, and for -convenience this is added as a pseudo-subnet with the ip address of -255.255.255.255. - -the local subnet NetBIOS name databases only contain samba's names. -the reason for this is that if a broadcast query is received, a NetBIOS -hosts is only expected to respond if that query is for one of its own -names (the exception to this is if a host is configured as a 'proxy' -server, in which case, samba should redirect the query to another WINS -server). - -the WINS pseudo-subnet NetBIOS database contains all NetBIOS names -that are not 'special browser' type names (regarding this i am a -_bit_ confused :-). names of type 0x01, 0x1d and 0x1e i consider to -be 'special browser' names. at the moment. maybe. - -the type of search to be initiated is determined. if the NetBIOS name -type is a non-special-browser name, then the WINS database is included -in the search. - -if the name is not a special browser name, then we need to find the -right subnet that the query came from. this is done using -find_req_subnet(). this also has the benefit of stopping any queries -from subnets that samba does not know about. - -if the query is a broadcast query, then the database of the local subnet -is included in the search. - -the name is then searched for in the appropriate NetBIOS data structures. -if it is found, then we need to check whether it is appropriate for us -to reply to such a query. - -we will only reply if the query is a directed query, the name belongs to -samba on that subnet, or the name is a domain master browser type, -or we're doing replies on behalf of hosts on subnets not known to the -host issuing the query. in the latter instance, it would be appropriate -if samba is using a WINS server for it to forward the name query on to -this WINS server. - -reply_name_query() then takes note of all the information that is -needed to construct a reply to the caller. a negative reply (if the -name is unknown to samba) or a positive reply (the name is known to -samba) is then issued. - - -/************************************************************************* - reply_name_status() - *************************************************************************/ - -this function is responsible for constructing a reply to a NetBIOS -name status query. this response contains all samba's NetBIOS names -on the subnet that the query came in from. - -a reply will only be made if the NetBIOS name being queried exists. - -see rfc1001.txt and rfc1002.txt for details of the name status reply. - - -/************************************************************************* - reply_name_reg() - *************************************************************************/ - -this function is responsible for updating the NetBIOS name database -from registration packets sent out by hosts wishing to register a -name, and for informing them, if necessary, if this is acceptable -or not. - -name registration can be done by broadcast or by point-to-point, -i.e the registration is sent directly to samba in its capacity as -a WINS server. - -if the name registration is done by broadcast (see rfc1001.txt 15.2.1), -then samba's involvement in replying is limited to whether that name -is owned by samba or not, on the relevant subnet. - -if the name registration is done point-to-point (see rfc1001.txt 15.2.2) -then samba will first need to check its WINS name database records and -proceed accordingly. - -samba looks for the appropriate subnet record that the registration -should be added to / checked against, using find_req_subnet(). - -next, the name is searched for in the local database or the WINS -database as appropriate. - -if the name is not found, then it is added to the NetBIOS name database, -using add_netbios_entry(), which may choose not to add the name (not -that this affects the registration of the name on the network in any way). -it will only add names to the WINS database, and even then it will only -add non-special-browser type names. - -if the name is found, then samba must decide whether to accept the name -or not. a group name is always added. for unique names, further checks -need to be carried out. - -firstly, if the name in the database is one of samba's names, or if the -name in the database is a group name, then it cannot be added as a unique -name belonging to someone else. it is therefore rejected. - -secondly, if the ip address of the name being registered does not match -against the ip in the database, then the unique name may belong to -someone else. a check needs to be carried out with the owner in case -they still wish to keep this name. a detailed discussion of what action -to take is in rfc1001.txt 15.2.2.2 and 15.2.2.3. - -samba currently implements non-secured WINS, whereupon the responsibility -for checking the name is passed on to the host doing the registration. -rfc1001.txt refers to this as an END-NODE CHALLENGE REGISTRATION RESPONSE. -(samba itself cannot yet cope with receiving such responses if it -registers its names with another WINS server). - -having decided what kind of response to send (if any - acceptance of -name registrations by broadcast is implicit), samba will send either a -positive or negative NAME REGISTRATION RESPONSE, or an END-NODE CHALLENGE -REGISTRATION RESPONSE to the host that initially sent the registration. - -whew. - - -/************************************************************************* - reply_name_release() - *************************************************************************/ - -this function is responsible for removing a NetBIOS name from the -database when a server sends a release packet. - -samba looks for the appropriate subnet record that the release should -be removed from, using find_req_subnet(). next, the name is searched -for in the local database or the WINS database as appropriate. - -if the name is found, it is removed from the database and a -positive reply is sent confirming this. if the name is not -found, a negative reply is sent. - -a reply is _not_ sent if the release was done by broadcast: the -release is implicit, and we should be grateful that they bothered -to tell us. if the release was done by directed packet, then -we deal with it as a WINS server and must reply (pos / neg). - -at present, the criteria for removing a name have yet to be -developed / experimented with. at present, the only flags that -are checked are the NetBIOS flags. - - -/************************************************************************* - send_name_response() - *************************************************************************/ - -this function is a wrap around reply_netbios_packet(). it sends -a response to a name registration or release packet, minimising -the function parameters needed to do this. - -if the function is called with the parameter 'success' set to -True, then a positive response (to the registration or release) -is made (see rfc1002.txt 4.2.5 and 4.2.10). if this parameter -is False, then a negative response is issued (see rfc1002.txt -4.2.6 and 4.2.11) - -if the function is called with a registration code, and the -parameter 'recurse' is False, then an End-Node Challenge -Registration response is issued (see rfc1002.txt 4.2.7) - -note: this function could also easily be used for name conflict -demand (see rfc1002.txt 4.2.8). - -note: End-Node Challenge Registration response is only sent in -non-secured NetBIOS Name Server implementations. samba now -implements secured NetBIOS Name Server functionality (see -rfc1001.txt 15.1.6). - diff --git a/source/nameservresp.c b/source/nameservresp.c deleted file mode 100644 index 226a997c5f3..00000000000 --- a/source/nameservresp.c +++ /dev/null @@ -1,917 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - Module name: nameservresp.c - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - - 05 jul 96: lkcl@pires.co.uk - created module nameservresp containing NetBIOS response functions - -*/ - -#include "includes.h" - -extern int ClientNMB; - -extern int DEBUGLEVEL; - -extern pstring scope; -extern fstring myworkgroup; -extern struct in_addr ipzero; -extern struct in_addr wins_ip; -extern struct in_addr ipzero; - - -#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl()) - - -/**************************************************************************** - response for a reg release received. samba has asked a WINS server if it - could release a name. - **************************************************************************/ -static void response_name_release(struct nmb_name *ans_name, - struct subnet_record *d, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - char *name = ans_name->name; - int type = ans_name->name_type; - - DEBUG(4,("response name release received\n")); - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - /* IMPORTANT: see expire_netbios_response_entries() */ - - struct in_addr found_ip; - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - /* NOTE: we only release our own names at present */ - if (ismyip(found_ip)) - { - name_unregister_work(d,name,type); - } - else - { - DEBUG(2,("name release for different ip! %s %s\n", - inet_ntoa(found_ip), namestr(ans_name))); - } - } - else - { - DEBUG(2,("name release for %s rejected!\n", namestr(ans_name))); - - /* XXXX PANIC! what to do if it's one of samba's own names? */ - - /* XXXX do we honestly care if our name release was rejected? - only if samba is issuing the release on behalf of some out-of-sync - server. if it's one of samba's SELF names, we don't care. */ - } -} - - -/**************************************************************************** -response for a reg request received -**************************************************************************/ -static void response_name_reg(struct nmb_name *ans_name, - struct subnet_record *d, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - BOOL bcast = nmb->header.nm_flags.bcast; - char *name = ans_name->name; - int type = ans_name->name_type; - - DEBUG(4,("response name registration received!\n")); - -#if 1 - /* This code is neccesitated due to bugs in earlier versions of - Samba (up to 1.9.16p11). They respond to a broadcast - name registration of WORKGROUP<1b> when they should - not. Hence, until these versions are gone, we should - treat such errors as success for this particular - case only. jallison@whistle.com. - */ - if ( ((d != wins_subnet) && (nmb->header.rcode == 6) && strequal(myworkgroup, name) && - (type == 0x1b)) || - (nmb->header.rcode == 0 && nmb->answers->rdata)) -#else - if (nmb->header.rcode == 0 && nmb->answers->rdata) -#endif - { - /* IMPORTANT: see expire_netbios_response_entries() */ - - int nb_flags = nmb->answers->rdata[0]; - int ttl = nmb->answers->ttl; - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast); - } - else - { - DEBUG(2,("name registration for %s rejected by ip %s!\n", - namestr(ans_name), inet_ntoa(p->ip))); - - /* oh dear. we have problems. possibly unbecome a master browser. */ - name_unregister_work(d,name,type); - } -} - - -/**************************************************************************** - response from a name query announce host - NAME_QUERY_ANNOUNCE_HOST is dealt with here - ****************************************************************************/ -static void response_announce_host(struct nmb_name *ans_name, - struct nmb_packet *nmb, - struct response_record *n, struct subnet_record *d) -{ - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - /* we had sent out a name query to the current owner - of a name because someone else wanted it. now they - have responded saying that they still want the name, - so the other host can't have it. - */ - - /* first check all the details are correct */ - - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (nb_flags != n->nb_flags) - { - /* someone gave us the wrong nb_flags as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("expected nb_flags: %d\n", n->nb_flags)); - DEBUG(4,("unexpected nb_flags: %d\n", nb_flags)); - return; - } - - /* do an announce host */ - do_announce_host(ANN_HostAnnouncement, - n->my_name , 0x00, d->myip, - n->name.name, 0x1d, found_ip, - n->ttl, - n->my_name, n->server_type, n->my_comment); - } - else - { - /* XXXX negative name query response. no master exists. oops */ - } -} - - -/**************************************************************************** - response from a name query server check. states of type NAME_QUERY_DOM_SRV_CHK, - NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here. - ****************************************************************************/ -static void response_server_check(struct nmb_name *ans_name, - struct response_record *n, struct subnet_record *d) -{ - /* issue another state: this time to do a name status check */ - - enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ? - NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK; - - /* initiate a name status check on the server that replied - in addition, the workgroup being checked has been stored - in the response_record->my_name (see announce_master) we - also propagate this into the same field. */ - queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd, - ans_name->name, ans_name->name_type, - 0,0,0,n->my_name,NULL, - False,False,n->send_ip,n->reply_to_ip); -} - - -/**************************************************************************** - interpret a node status response. this is pretty hacked: we need two bits of - info. a) the name of the workgroup b) the name of the server. it will also - add all the names it finds into the namelist. -****************************************************************************/ -static BOOL interpret_node_status(struct subnet_record *d, - char *p, struct nmb_name *name,int t, - char *serv_name, struct in_addr ip, BOOL bcast) -{ - int numnames = CVAL(p,0); - BOOL found = False; - - DEBUG(4,("received %d names\n",numnames)); - - p += 1; - - if (serv_name) *serv_name = 0; - - while (numnames--) - { - char qname[17]; - int type; - fstring flags; - int nb_flags; - - BOOL group = False; - BOOL add = False; - - *flags = 0; - - StrnCpy(qname,p,15); - type = CVAL(p,15); - nb_flags = p[16]; - trim_string(qname,NULL," "); - - p += 18; - - if (NAME_GROUP (nb_flags)) { strcat(flags,"<GROUP> "); group=True;} - if (NAME_BFLAG (nb_flags)) { strcat(flags,"B "); } - if (NAME_PFLAG (nb_flags)) { strcat(flags,"P "); } - if (NAME_MFLAG (nb_flags)) { strcat(flags,"M "); } - if (NAME_HFLAG (nb_flags)) { strcat(flags,"H "); } - if (NAME_DEREG (nb_flags)) { strcat(flags,"<DEREGISTERING> "); } - if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); } - if (NAME_ACTIVE (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; } - if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;} - -/* I don't think we should be messing with our namelist here... JRA */ -#if 0 - /* might as well update our namelist while we're at it */ - if (add) - { - struct in_addr nameip; - enum name_source src; - - if (ismyip(ip)) { - nameip = ipzero; - src = SELF; - } else { - nameip = ip; - src = STATUS_QUERY; - } - add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); - } -#endif /* JRA */ - - /* we want the server name */ - if (serv_name && !*serv_name && !group && type == 0x20) - { - StrnCpy(serv_name,qname,15); - serv_name[15] = 0; - } - - /* looking for a name and type? */ - if (name && !found && (t == type)) - { - /* take a guess at some of the name types we're going to ask for. - evaluate whether they are group names or no... */ - if (((t == 0x1b || t == 0x1d || t == 0x20 ) && !group) || - ((t == 0x1c || t == 0x1e ) && group)) - { - found = True; - make_nmb_name(name,qname,type,scope); - } - } - - DEBUG(4,("\t%s(0x%x)\t%s\n",qname,type,flags)); - } - DEBUG(4,("num_good_sends=%d num_good_receives=%d\n", - IVAL(p,20),IVAL(p,24))); - return found; -} - - -/**************************************************************************** - response from a name status check. states of type NAME_STATUS_DOM_SRV_CHK - and NAME_STATUS_SRV_CHK dealt with here. - ****************************************************************************/ -static void response_name_status_check(struct in_addr ip, - struct nmb_packet *nmb, BOOL bcast, - struct response_record *n, struct subnet_record *d) -{ - /* NMB_STATUS arrives: contains workgroup name and server name required. - amongst other things. */ - - struct nmb_name name; - fstring serv_name; - - if (interpret_node_status(d,nmb->answers->rdata, - &name,0x20,serv_name,ip,bcast)) - { - if (*serv_name) - { - /* response_record->my_name contains the - workgroup name to sync with. See - response_server_check() */ - sync_server(n->state,serv_name, - n->my_name,name.name_type, d, n->send_ip); - } - } - else - { - DEBUG(1,("No 0x20 name type in interpret_node_status()\n")); - } -} - - -/**************************************************************************** - response from a name query for secured WINS registration. a state of - NAME_REGISTER_CHALLENGE is dealt with here. - ****************************************************************************/ -static void response_name_query_register(struct nmb_packet *nmb, - struct nmb_name *ans_name, - struct response_record *n, struct subnet_record *d) -{ - struct in_addr register_ip; - BOOL new_owner; - - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - /* we had sent out a name query to the current owner - of a name because someone else wanted it. now they - have responded saying that they still want the name, - so the other host can't have it. - */ - - /* first check all the details are correct */ - - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (nb_flags != n->nb_flags) - { - /* someone gave us the wrong nb_flags as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("expected nb_flags: %d\n", n->nb_flags)); - DEBUG(4,("unexpected nb_flags: %d\n", nb_flags)); - return; - } - - if (!ip_equal(n->send_ip, found_ip)) - { - /* someone gave us the wrong ip as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); - DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip))); - return; - } - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); - - /* fine: now tell the other host they can't have the name */ - register_ip = n->send_ip; - new_owner = False; - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE!\n")); - - /* the owner didn't want the name: the other host can have it */ - register_ip = n->reply_to_ip; - new_owner = True; - } - - /* register the old or the new owners' ip */ - add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags, - GET_TTL(0), register_ip, - new_owner, n->reply_to_ip); -} - - -/**************************************************************************** - response from a name query to sync browse lists or to update our netbios - entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM - ****************************************************************************/ -static void response_name_query_sync(struct nmb_packet *nmb, - struct nmb_name *ans_name, BOOL bcast, - struct response_record *n, struct subnet_record *d) -{ - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (!ip_equal(n->send_ip, found_ip)) - { - /* someone gave us the wrong ip as a reply. oops. */ - DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); - DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip))); - return; - } - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); - - if (n->state == NAME_QUERY_SYNC_LOCAL || - n->state == NAME_QUERY_SYNC_REMOTE) - { - struct work_record *work = NULL; - /* We cheat here as we know that the workgroup name has - been placed in the my_comment field of the - response_record struct by the code in - start_sync_browse_entry(). - */ - if ((work = find_workgroupstruct(d, n->my_comment, False))) - { - BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL; - - /* the server is there: sync quick before it (possibly) dies! */ - sync_browse_lists(d, work, ans_name->name, ans_name->name_type, - found_ip, local_list_only); - } - } - else - { - /* update our netbios name list (re-register it if necessary) */ - add_netbios_entry(d, ans_name->name, ans_name->name_type, - nb_flags,GET_TTL(0),REGISTER, - found_ip,False,!bcast); - } - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE!\n")); - - if (n->state == NAME_QUERY_CONFIRM) - { - /* XXXX remove_netbios_entry()? */ - /* lots of things we ought to do, here. if we get here, - then we're in a mess: our name database doesn't match - reality. sort it out - */ - remove_netbios_name(d,n->name.name, n->name.name_type, - REGISTER,n->send_ip); - } - } -} - -/**************************************************************************** - response from a name query for DOMAIN<1b> - NAME_QUERY_DOMAIN is dealt with here - we are trying to become a domain - master browser and WINS replied - check it's our address. - ****************************************************************************/ -static void response_name_query_domain(struct nmb_name *ans_name, - struct nmb_packet *nmb, - struct response_record *n, struct subnet_record *d) -{ - DEBUG(4, ("response_name_query_domain: Got %s response from %s for query \ -for %s\n", nmb->header.rcode == 0 ? "success" : "failure", - inet_ntoa(n->send_ip), namestr(ans_name))); - - /* Check the name is correct and ip address returned is our own. If it is then we - just remove the response record. - */ - if (name_equal(&n->name, ans_name) && (nmb->header.rcode == 0) && (nmb->answers->rdata)) - { - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - /* Samba 1.9.16p11 servers seem to return the broadcast address for this - query. */ - if (ismyip(found_ip) || ip_equal(wins_ip, found_ip) || ip_equal(ipzero, found_ip)) - { - DEBUG(4, ("response_name_query_domain: WINS server returned our ip \ -address. Pretending we never received response.\n")); - n->num_msgs = 0; - n->repeat_count = 0; - n->repeat_time = 0; - } - else - { - DEBUG(0,("response_name_query_domain: WINS server already has a \ -domain master browser registered %s at address %s\n", - namestr(ans_name), inet_ntoa(found_ip))); - } - } - else - { - /* Negative/incorrect response. No domain master - browser was registered - pretend we didn't get this response. - */ - n->num_msgs = 0; - n->repeat_count = 0; - n->repeat_time = 0; - } - -} - -/**************************************************************************** - report the response record type - ****************************************************************************/ -static void debug_rr_type(int rr_type) -{ - switch (rr_type) - { - case NMB_STATUS: DEBUG(3,("Name status ")); break; - case NMB_QUERY : DEBUG(3,("Name query ")); break; - case NMB_REG : DEBUG(3,("Name registration ")); break; - case NMB_REL : DEBUG(3,("Name release ")); break; - default : DEBUG(1,("wrong response packet type received")); break; - } -} - -/**************************************************************************** - report the response record nmbd state - ****************************************************************************/ -void debug_state_type(int state) -{ - /* report the state type to help debugging */ - switch (state) - { - case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("NAME_QUERY_DOM_SRV_CHK\n")); break; - case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break; - case NAME_QUERY_FIND_MST : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break; - case NAME_QUERY_MST_CHK : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break; - case NAME_QUERY_CONFIRM : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break; - case NAME_QUERY_SYNC_LOCAL : DEBUG(4,("NAME_QUERY_SYNC_LOCAL\n")); break; - case NAME_QUERY_SYNC_REMOTE : DEBUG(4,("NAME_QUERY_SYNC_REMOTE\n")); break; - case NAME_QUERY_ANNOUNCE_HOST: DEBUG(4,("NAME_QUERY_ANNCE_HOST\n"));break; - case NAME_QUERY_DOMAIN : DEBUG(4,("NAME_QUERY_DOMAIN\n")); break; - - case NAME_REGISTER : DEBUG(4,("NAME_REGISTER\n")); break; - case NAME_REGISTER_CHALLENGE : DEBUG(4,("NAME_REGISTER_CHALLENGE\n"));break; - - case NAME_RELEASE : DEBUG(4,("NAME_RELEASE\n")); break; - - case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STATUS_DOM_SRV_CHK\n")); break; - case NAME_STATUS_SRV_CHK : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break; - - default: break; - } -} - -/**************************************************************************** - report any problems with the fact that a response has been received. - - (responses for certain types of operations are only expected from one host) - ****************************************************************************/ -static BOOL response_problem_check(struct response_record *n, - struct nmb_packet *nmb, char *ans_name) -{ - switch (nmb->answers->rr_type) - { - case NMB_REL: - { - if (n->num_msgs > 1) - { - DEBUG(1,("more than one release name response received!\n")); - return True; - } - break; - } - - case NMB_REG: - { - if (n->num_msgs > 1) - { - DEBUG(1,("more than one register name response received!\n")); - return True; - } - break; - } - - case NMB_QUERY: - { - if (n->num_msgs > 1) - { - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - - if ((!NAME_GROUP(nb_flags))) - { - /* oh dear. more than one person responded to a - unique name. - there is either a network problem, a - configuration problem - or a server is mis-behaving */ - - /* XXXX mark the name as in conflict, and then let the - person who just responded know that they - must also mark it - as in conflict, and therefore must NOT use it. - see rfc1001.txt 15.1.3.5 */ - - /* this may cause problems for some - early versions of nmbd */ - - switch (n->state) - { - case NAME_QUERY_FIND_MST: - { - /* query for ^1^2__MSBROWSE__^2^1 expect - lots of responses */ - return False; - } - case NAME_QUERY_ANNOUNCE_HOST: - case NAME_QUERY_DOM_SRV_CHK: - case NAME_QUERY_SRV_CHK: - case NAME_QUERY_MST_CHK: - { - if (!strequal(ans_name,n->name.name)) - { - /* one subnet, one master browser - per workgroup */ - /* XXXX force an election? */ - - DEBUG(3,("more than one master browser replied!\n")); - return True; - } - break; - } - default: break; - } - DEBUG(3,("Unique Name conflict detected!\n")); - return True; - } - } - else - { - /* we have received a negative reply, - having already received - at least one response (pos/neg). - something's really wrong! */ - - DEBUG(3,("wierd name query problem detected!\n")); - return True; - } - } - } - } - return False; -} - -#if 0 -/**************************************************************************** - check that the response received is compatible with the response record - ****************************************************************************/ -static BOOL response_compatible(struct response_record *n, - struct nmb_packet *nmb) -{ - switch (n->state) - { - case NAME_RELEASE: - { - if (nmb->answers->rr_type != 0x20) - { - DEBUG(1,("Name release reply has wrong answer rr_type\n")); - return False; - } - break; - } - - case NAME_REGISTER: - { - if (nmb->answers->rr_type != 0x20) - { - DEBUG(1,("Name register reply has wrong answer rr_type\n")); - return False; - } - break; - } - - case NAME_REGISTER_CHALLENGE: /* this is a query: we then do a register */ - case NAME_QUERY_CONFIRM: - case NAME_QUERY_ANNOUNCE_HOST: - case NAME_QUERY_SYNC_LOCAL: - case NAME_QUERY_SYNC_REMOTE: - case NAME_QUERY_DOM_SRV_CHK: - case NAME_QUERY_SRV_CHK: - case NAME_QUERY_FIND_MST: - case NAME_QUERY_MST_CHK: - { - if (nmb->answers->rr_type != 0x20) - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - return False; - } - break; - } - - case NAME_STATUS_DOM_SRV_CHK: - case NAME_STATUS_SRV_CHK: - { - if (nmb->answers->rr_type != 0x21) - { - DEBUG(1,("Name status reply has wrong answer rr_type\n")); - return False; - } - break; - } - - default: - { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - return False; - } - } - return True; -} -#endif - - -/**************************************************************************** - process the response packet received - ****************************************************************************/ -static void response_process(struct subnet_record *d, struct packet_struct *p, - struct response_record *n, struct nmb_packet *nmb, - BOOL bcast, struct nmb_name *ans_name) -{ - switch (n->state) - { - case NAME_RELEASE: - { - response_name_release(ans_name, d, p); - break; - } - - case NAME_REGISTER: - { - response_name_reg(ans_name, d, p); - break; - } - - case NAME_REGISTER_CHALLENGE: - { - response_name_query_register(nmb, ans_name, n, d); - break; - } - - case NAME_QUERY_DOM_SRV_CHK: - case NAME_QUERY_SRV_CHK: - case NAME_QUERY_FIND_MST: - { - response_server_check(ans_name, n, d); - break; - } - - case NAME_STATUS_DOM_SRV_CHK: - case NAME_STATUS_SRV_CHK: - { - response_name_status_check(p->ip, nmb, bcast, n, d); - break; - } - - case NAME_QUERY_ANNOUNCE_HOST: - { - response_announce_host(ans_name, nmb, n, d); - break; - } - - case NAME_QUERY_CONFIRM: - case NAME_QUERY_SYNC_LOCAL: - case NAME_QUERY_SYNC_REMOTE: - { - response_name_query_sync(nmb, ans_name, bcast, n, d); - break; - } - case NAME_QUERY_MST_CHK: - { - /* no action required here. it's when NO responses are received - that we need to do something. see expire_name_query_entries() */ - - DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", - namestr(&n->name), inet_ntoa(n->send_ip))); - break; - } - - case NAME_QUERY_DOMAIN: - { - /* We were asking to be a domain master browser, and someone - replied. If it was the WINS server and the IP it is - returning is our own - then remove the record and pretend - we didn't get a response. Else we do nothing and let - dead_netbios_entry deal with it. - We can only become domain master browser - when no broadcast responses are received and WINS - either contains no entry for the DOMAIN<1b> name or - contains our IP address. - */ - response_name_query_domain(ans_name, nmb, n, d); - break; - } - default: - { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - break; - } - } -} - - -/**************************************************************************** - response from a netbios packet. - ****************************************************************************/ -void response_netbios_packet(struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *ans_name = NULL; - BOOL bcast = nmb->header.nm_flags.bcast; - struct response_record *n; - struct subnet_record *d = NULL; - - if (!(n = find_response_record(&d,nmb->header.name_trn_id))) { - DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n")); - return; - } - - if (!d) - { - DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip))); - return; - } - - /* args wrong way round: spotted by ccm@shentel.net */ - if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */ - { - DEBUG(2,("response from %s. ", inet_ntoa(p->ip))); - DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip))); - } - - if (nmb->answers == NULL) - { - /* hm. the packet received was a response, but with no answer. wierd! */ - DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", - inet_ntoa(p->ip), BOOLSTR(bcast))); - return; - } - - ans_name = &nmb->answers->rr_name; - DEBUG(3,("response for %s from %s (bcast=%s)\n", - namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); - - debug_rr_type(nmb->answers->rr_type); - - n->num_msgs++; /* count number of responses received */ - n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */ - - debug_state_type(n->state); - - /* problem checking: multiple responses etc */ - if (response_problem_check(n, nmb, ans_name->name)) - return; - - /* now deal with the current state */ - response_process(d, p, n, nmb, bcast, ans_name); -} diff --git a/source/nameservresp.doc b/source/nameservresp.doc deleted file mode 100644 index 635db45084f..00000000000 --- a/source/nameservresp.doc +++ /dev/null @@ -1,191 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.0 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: nameservresp.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created -*/ - -this module deals with the receipt of response packets. the -response packets are expected to be received, and there is a -record of this kept (see also: modules nameresp and namedbresp) - -point of interest to design purists: every function in this -module is static except response_netbios_packet(). - -/************************************************************************* - response_netbios_packet() - *************************************************************************/ - -this function receives netbios response packets. the samba server -(or a rogue tcp/ip system, or nmblookup) will have sent out a packet -requesting a response. a client (or a rogue tcp/ip system) responds -to that request. - -this function checks the validity of the packet it receives. -the expected response records are searched for the transaction id, -to see if it's a response expected by the samba server. if it isn't -it's reported as such, and ignored. - -if the response is found, then the subnet it was expected from will -also have been found. the subnet it actually came in on can be -checked against the subnet it was expected from and reported, -otherwise this function just carries on. - -the number of responses received is increased, and the number of -retries left to be sent is set to zero. - -after debug information is reported, and validation of the netbios -packet (e.g only one response from one machine is expected for some -functions) has occurred, the packet is processed. when the initial -request was sent out, the expected response record was flagged with, -for lack of a better word, a samba 'state' type. whenever a -response is received, the appropriate function is called to carry on -where the program control flow was interrupted while awaiting exactly -such a response. - -please note that _not_ receiving a response is dealt with in another -area of code - expire_netbios_response_entries(). - - -/************************************************************************* - response_name_query_sync() - *************************************************************************/ - -this function receives responses to samba 'states' NAME_QUERY_SYNC and -NAME_QUERY_CONFIRM. - -NAME_QUERY_SYNC: name query a server before synchronising browse lists. -NAME_QUERY_CONFIRM: name query a server to check that it's alive. - -a NAME_QUERY_SYNC will be carried out in order to check that a server -is alive before syncing browse lists. we don't want to delay the SMB -NetServerEnum api just because the server has gone down: we have too -much else to do. - -a NAME_QUERY_CONFIRM is just a name query to see whether the server is -alive. these queries are sent out by samba's WINS server side, to verify -its netbios name database of all machines that have registered with it. - -we don't normally expect a negative response from such a query, although -we may do so if the query was sent to another WINS server. the registered -entry should be removed if we receive a negative response. - - -/************************************************************************* - response_name_status_check() - *************************************************************************/ - -this function receives responses to samba 'states' NAME_STATUS_SRV_CHK -and NAME_STATUS_DOM_SRV_CHK - -NAME_STATUS_DOM_SRV_CHK: name status a domain master browser - confirm its domain and then initiate syncing - its browse list. - -NAME_STATUS_SRV_CHK: same as NAME_STATUS_DOM_SRV_CHK except the - name status is issued to a master browser. - -if we don't know what workgroup a server is responsible for, but we -know that there is a master browser at a certain ip, we can issue a -name status check. from the response received, there will be -a master browser netbios entry. this will allow us to synchronise -browse lists with that machine and then add the information to the -correct part of samba's workgroup - server database. - - -/************************************************************************* - response_server_check() - *************************************************************************/ - -this function receives responses to samba 'states' NAME_QUERY_DOM_SRV_CHK, -NAME_QUERY_SRV_CHK and NAME_QUERY_FIND_MST. - -NAME_QUERY_FIND_MST: issued as a broadcast when we wish to find out all - master browsers (i.e all servers that have registered - the NetBIOS name ^1^2__MSBROWSE__^2(0x1), and then - issue a NAME_STATUS_MASTER_CHECK on any servers that - respond, which will initiate a sync browse lists. - -NAME_QUERY_DOM_SRV_CHK: same as a NAME_QUERY_FIND_MST except this is sent - to a domain master browser. - -NAME_QUERY_SRV_CHK: same as a NAME_QUERY_DOM_SRV_CHK except this is sent to - a master browser. - -the purpose of each of these states is to do a broadcast name query, or -a name query directed at a WINS server, then to all hosts that respond, -we issue a name status check, which will confirm for us the workgroup -or domain name, and then initiate issuing a sync browse list call with -that server. - -a NAME_QUERY_SRV_CHK is sent when samba receives a list of backup -browsers. it checks to see if that server is alive (by doing a -name query on a server) and then syncs browse lists with it. - - -/************************************************************************* - response_name_reg() - *************************************************************************/ - -this function is responsible for dealing with samba's registration -attempts, by broadcast to a local subnet, or point-to-point with -another WINS server. - -please note that it cannot cope with END-NODE CHALLENGE REGISTRATION -RESPONSEs at present. - -when a response is received, samba determines if the response is a -positive or a negative one. if it is a positive response, the name -is added to samba's database. - -when a negative response is received, samba will remove the name -from its database. if, however, the name is a browser type (0x1b is -a domain master browser type name; or 0x1d, which is a local master -browser type name) then it must also stop being a domain master -browser or master browser respectively, depending on what kind -of name was rejected. - -(when no response is received, then expire_netbios_response_entries() -is expected to deal with this. the only case that is dealt with here -at present is when the registration was done by broadcast. if there -is no challenge to the broadcast registration, it is implicitly -assumed that claiming the name is acceptable). - - -/************************************************************************* - response_name_release() - *************************************************************************/ - -this function is responsible for removing samba's NetBIOS name when -samba contacts another WINS server with which it had registered the -name. - -only positive name releases are expected and dealt with. exactly what -to do if a negative name release (i.e someone says 'oi! you have to -keep that name!') is received is uncertain. - -(when no response is received, then expire_netbios_response_entries() -is expected to deal with this. if there is no challenge to the release -of the name, the name is then removed from that subnet's NetBIOS -name database). - diff --git a/source/namework.c b/source/namework.c deleted file mode 100644 index ff623e69dbf..00000000000 --- a/source/namework.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -#define TEST_CODE /* want to debug unknown browse packets */ - -extern int DEBUGLEVEL; -extern pstring scope; -extern BOOL CanRecurse; - -extern pstring myname; -extern fstring myworkgroup; - -extern int ClientNMB; -extern int ClientDGRAM; - -extern struct in_addr ipzero; - -extern int workgroup_count; /* total number of workgroups we know about */ - -/* this is our domain/workgroup/server database */ -extern struct subnet_record *subnetlist; - -extern int updatecount; - -/* backup request types: which servers are to be included */ -#define MASTER_TYPE (SV_TYPE_MASTER_BROWSER) -#define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL ) - -extern time_t StartupTime; - -extern BOOL updatedlists; - -/**************************************************************************** -tell a server to become a backup browser -state - 0x01 become backup instead of master - - 0x02 remove all entries in browse list and become non-master - - 0x04 stop master browser service altogether. NT ignores this -**************************************************************************/ -void reset_server(char *name, int state, struct in_addr ip) -{ - char outbuf[20]; - char *p; - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - - CVAL(p,0) = ANN_ResetBrowserState; - CVAL(p,2) = state; - p += 2; - - DEBUG(2,("sending reset to %s %s of state %d\n", - name,inet_ntoa(ip),state)); - - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - myname,name,0x20,0x1d,ip,*iface_ip(ip)); -} - - -/**************************************************************************** -tell a server to become a backup browser -**************************************************************************/ -void tell_become_backup(void) -{ - /* XXXX note: this function is currently unsuitable for use, as it - does not properly check that a server is in a fit state to become - a backup browser before asking it to be one. - */ - - struct subnet_record *d; - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - int num_servers = 0; - int num_backups = 0; - - for (s = work->serverlist; s; s = s->next) - { - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - num_servers++; - - if (strequal(myname, s->serv.name)) continue; - - if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { - num_backups++; - continue; - } - - if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; - - if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; - - DEBUG(3,("num servers: %d num backups: %d\n", - num_servers, num_backups)); - - /* make first server a backup server. thereafter make every - tenth server a backup server */ - if (num_backups != 0 && (num_servers+9) / num_backups > 10) - { - continue; - } - - DEBUG(2,("sending become backup to %s %s for %s\n", - s->serv.name, inet_ntoa(d->bcast_ip), - work->work_group)); - - /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ - do_announce_request(s->serv.name, work->work_group, - ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip); - } - } - } -} - - -/******************************************************************* - same context: scope. should check name_type as well, and makes sure - we don't process messages from ourselves - ******************************************************************/ -BOOL same_context(struct dgram_packet *dgram) -{ - if (!strequal(dgram->dest_name .scope,scope )) return(True); - if ( strequal(dgram->source_name.name ,myname)) return(True); - - return(False); -} - - -/******************************************************************* - process a domain announcement frame - - Announce frames come in 3 types. Servers send host announcements - (command=1) to let the master browswer know they are - available. Master browsers send local master announcements - (command=15) to let other masters and backups that they are the - master. They also send domain announcements (command=12) to register - the domain - - The comment field of domain announcements contains the master - browser name. The servertype is used by NetServerEnum to select - resources. We just have to pass it to smbd (via browser.dat) and let - the client choose using bit masks. - ******************************************************************/ -static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - struct subnet_record *d = find_subnet(p->ip); /* Explicitly exclude WINS - local nets only */ - int update_count = CVAL(buf,0); - - int ttl = IVAL(buf,1)/1000; - char *name = buf+5; - int osmajor=CVAL(buf,21); - int osminor=CVAL(buf,22); - uint32 servertype = IVAL(buf,23); - uint32 browse_type= CVAL(buf,27); - uint32 browse_sig = CVAL(buf,29); - char *comment = buf+31; - - struct work_record *work; - char *work_name; - char *serv_name = dgram->source_name.name; - BOOL add = False; - - comment[43] = 0; - - DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15])); - DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n", - namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, - servertype,browse_type,browse_sig,comment)); - - name[15] = 0; - - if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement) - { - DEBUG(2,("Announce to nametype(0) not supported yet\n")); - return; - } - - if (command == ANN_DomainAnnouncement && - ((!strequal(dgram->dest_name.name, MSBROWSE)) || - dgram->dest_name.name_type != 0x1)) - { - DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", - command, inet_ntoa(p->ip), namestr(&dgram->dest_name))); - return; - } - - if (!strequal(dgram->dest_name.scope,scope )) return; - - if (command == ANN_DomainAnnouncement) { - /* XXXX if we are a master browser for the workgroup work_name, - then there is a local subnet configuration problem. only - we should be sending out such domain announcements, because - as the master browser, that is our job. - - stop being a master browser, and force an election. this will - sort out the network problem. hopefully. - */ - - work_name = name; - add = True; - } else { - work_name = dgram->dest_name.name; - } - - /* we need some way of finding out about new workgroups - that appear to be sending packets to us. The name_type checks make - sure we don't add host names as workgroups */ - if (command == ANN_HostAnnouncement && - (dgram->dest_name.name_type == 0x1d || - dgram->dest_name.name_type == 0x1e)) - add = True; - - DEBUG(4,("search for workgroup: %s (add? %s)\n", - work_name, BOOLSTR(add))); - - if (!(work = find_workgroupstruct(d, work_name,add))) - return; - - DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name)); - - ttl = GET_TTL(ttl); - - /* add them to our browse list, and update the browse.dat file */ - add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True); - updatedlists = True; - -#if 0 - /* the tell become backup code is broken, no great harm is done by - disabling it */ - tell_become_backup(); -#endif - -#if 0 /* JRA TEST - I Think this code should not be here */ - /* get the local_only browse list from the local master and add it - to ours. */ - if (command == ANN_LocalMasterAnnouncement) - { - add_browser_entry(serv_name,dgram->dest_name.name_type, - work->work_group,30,p->ip,True); - } -#endif /* END JRA TEST */ -} - -/******************************************************************* - process a master announcement frame - Domain master browsers recieve these from local masters. The Domain - master should then issue a sync with the local master, asking for - that machines local server list. - ******************************************************************/ -static void process_master_announce(struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - char *name = buf; - struct work_record *work; - name[15] = 0; - - DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip))); - - if (same_context(dgram)) return; - - if (!wins_subnet) - { - DEBUG(3,("process_master_announce: No wins subnet !\n")); - return; - } - - if (!lp_domain_master()) - { - DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n")); - return; - } - - for (work = wins_subnet->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work) || AM_DOMMST(work)) - { - /* merge browse lists with them */ - add_browser_entry(name,0x1d, work->work_group,30,wins_subnet,p->ip,True); - } - } -} - -/******************************************************************* - process a receive backup list request - - we receive a list of servers, and we attempt to locate them all on - our local subnet, and sync browse lists with them on the workgroup - they are said to be in. - - XXXX NOTE: this function is in overdrive. it should not really do - half of what it actually does (it should pick _one_ name from the - list received and sync with it at regular intervals, rather than - sync with them all only once!) - - ******************************************************************/ -static void process_rcv_backup_list(struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int count = CVAL(buf,0); - uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */ - char *buf1; - - DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n", - namestr(&dgram->dest_name), inet_ntoa(p->ip), - count, info)); - - if (same_context(dgram)) return; - - if (count <= 0) return; - - /* go through the list of servers attempting to sync browse lists */ - for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count) - { - struct in_addr back_ip; - /* struct subnet_record *d; */ - - DEBUG(4,("Searching for backup browser %s at %s...\n", - buf1, inet_ntoa(p->ip))); - - /* XXXX assume name is a DNS name NOT a netbios name. a more complete - approach is to use reply_name_query functionality to find the name */ - - back_ip = *interpret_addr2(buf1); - - if (zero_ip(back_ip)) - { - DEBUG(4,("Failed to find backup browser server using DNS\n")); - continue; - } - - DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip))); - DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n")); - -#if 0 - /* XXXX function needs work */ - continue; - - if ((d = find_subnet(back_ip))) - { - struct subnet_record *d1; - for (d1 = subnetlist; d1; d1 = d1->next) - { - struct work_record *work; - for (work = d1->workgrouplist; work; work = work->next) - { - if (work->token == 0 /* token */) - { - queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, - work->work_group,0x1d, - 0,0,0,NULL,NULL, - False,False,back_ip,back_ip); - return; - } - } - } - } -#endif - } -} - - -/**************************************************************************** - send a backup list response. - **************************************************************************/ -static void send_backup_list(char *work_name, struct nmb_name *src_name, - int token, uint32 info, - int name_type, struct in_addr ip) -{ - char outbuf[1024]; - char *p, *countptr, *nameptr; - int count = 0; - char *theirname = src_name->name; - - DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", - work_name, inet_ntoa(ip), - myname,0x0,theirname,0x0)); - - if (name_type == 0x1d) - { - DEBUG(4,("master browsers: ")); - } - else if (name_type == 0x1b) - { - DEBUG(4,("domain controllers: ")); - } - else - { - DEBUG(0,("backup request for unknown type %0x\n", name_type)); - return; - } - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - - CVAL(p,0) = ANN_GetBackupListResp; /* backup list response */ - - p++; - countptr = p; - - SIVAL(p,1,info); /* the sender's unique info */ - - p += 5; - - nameptr = p; - -#if 0 - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - - if (!strequal(work->work_group, work_name)) continue; - - for (s = work->serverlist; s; s = s->next) - { - BOOL found = False; - char *n; - - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - for (n = nameptr; n < p; n = skip_string(n, 1)) - { - if (strequal(n, s->serv.name)) found = True; - } - - if (found) continue; /* exclude names already added */ - - /* workgroup request: include all backup browsers in the list */ - /* domain request: include all domain members in the list */ - - if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) || - (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) - { - DEBUG(4, ("%s ", s->serv.name)); - - count++; - strcpy(p,s->serv.name); - strupper(p); - p = skip_string(p,1); - } - } - } - } - -#endif - - count++; - strcpy(p,myname); - strupper(p); - p = skip_string(p,1); - - if (count == 0) - { - DEBUG(4, ("none\n")); - } - else - { - DEBUG(4, (" - count %d\n", count)); - } - - CVAL(countptr, 0) = count; - - { - int len = PTR_DIFF(p, outbuf); - debug_browse_data(outbuf, len); - } - send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM, - outbuf,PTR_DIFF(p,outbuf), - myname,theirname,0x0,0x0,ip,*iface_ip(ip)); -} - - -/******************************************************************* - process a send backup list request - - A client sends a backup list request to ask for a list of servers on - the net that maintain server lists for a domain. A server is then - chosen from this list to send NetServerEnum commands to to list - available servers. - - Currently samba only sends back one name in the backup list, its - own. For larger nets we'll have to add backups and send "become - backup" requests occasionally. - ******************************************************************/ -static void process_send_backup_list(struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - struct in_addr ip = dgram->header.source_ip; - struct subnet_record *d; - struct work_record *work; - - int token = CVAL(buf,0); /* sender's key index for the workgroup */ - uint32 info = IVAL(buf,1); /* XXXX don't know: some sort of info */ - int name_type = dgram->dest_name.name_type; - - if (same_context(dgram)) return; - - if (name_type != 0x1b && name_type != 0x1d) { - DEBUG(0,("backup request to wrong type %d from %s\n", - name_type,inet_ntoa(ip))); - return; - } - - for (d = subnetlist; d; d = d->next) - { - for (work = d->workgrouplist; work; work = work->next) - { - if (strequal(work->work_group, dgram->dest_name.name)) - { - DEBUG(2,("sending backup list to %s %s id=%x\n", - namestr(&dgram->dest_name),inet_ntoa(ip),info)); - - send_backup_list(work->work_group,&dgram->source_name, - token,info,name_type,ip); - return; - } - } - } -} - - -/******************************************************************* - process a reset browser state - - diagnostic packet: - 0x1 - stop being a master browser and become a backup browser. - 0x2 - discard browse lists, stop being a master browser, try again. - 0x4 - stop being a master browser forever. no way. ain't gonna. - - ******************************************************************/ -static void process_reset_browser(struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - int state = CVAL(buf,0); - - DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n", - namestr(&dgram->dest_name), state)); - - /* stop being a master but still deal with being a backup browser */ - if (state & 0x1) - { - struct subnet_record *d; - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER); - } - } - } - } - - /* XXXX documentation inconsistency: the above description does not - exactly tally with what is implemented for state & 0x2 - */ - - /* totally delete all servers and start afresh */ - if (state & 0x2) - { - struct subnet_record *d; - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct work_record *work; - for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True)); - } - add_my_subnets(myworkgroup); - } - - /* stop browsing altogether. i don't think this is a good idea! */ - if (state & 0x4) - { - DEBUG(1,("ignoring request to stop being a browser. sorry!\n")); - } -} - -/******************************************************************* - process a announcement request - - clients send these when they want everyone to send an announcement - immediately. This can cause quite a storm of packets! - ******************************************************************/ -static void process_announce_request(struct packet_struct *p,char *buf) -{ - struct dgram_packet *dgram = &p->packet.dgram; - struct work_record *work; - struct in_addr ip = dgram->header.source_ip; - struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */ - int token = CVAL(buf,0); - char *name = buf+1; - - name[15] = 0; - - DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n", - name,namestr(&dgram->dest_name), token)); - - if (strequal(dgram->source_name.name,myname)) return; - - /* XXXX BUG or FEATURE?: need to ensure that we are a member of - this workgroup before announcing, particularly as we only - respond on local interfaces anyway. - - if (strequal(dgram->dest_name, myworkgroup) return; ??? - */ - - if (!d) - { - DEBUG(3,("process_announce_request: No local interface to announce to %s\n", - name)); - return; - } - - for (work = d->workgrouplist; work; work = work->next) - { - /* XXXX BUG: the destination name type should also be checked, - not just the name. e.g if the name is WORKGROUP(0x1d) then - we should only respond if we own that name */ - - if (strequal(dgram->dest_name.name,work->work_group)) - { - work->needannounce = True; - } - } -} - - - -/**************************************************************************** -process a browse frame -****************************************************************************/ -void process_browse_packet(struct packet_struct *p,char *buf,int len) -{ - int command = CVAL(buf,0); - switch (command) - { - case ANN_HostAnnouncement: - case ANN_DomainAnnouncement: - case ANN_LocalMasterAnnouncement: - { - debug_browse_data(buf, len); - process_localnet_announce(p,command,buf+1); - break; - } - - case ANN_AnnouncementRequest: - { - process_announce_request(p,buf+1); - break; - } - - case ANN_Election: - { - process_election(p,buf+1); - break; - } - - case ANN_GetBackupListReq: - { - debug_browse_data(buf, len); - process_send_backup_list(p,buf+1); - break; - } - - case ANN_GetBackupListResp: - { - debug_browse_data(buf, len); - process_rcv_backup_list(p, buf+1); - break; - } - - case ANN_ResetBrowserState: - { - process_reset_browser(p, buf+1); - break; - } - - case ANN_MasterAnnouncement: - { - process_master_announce(p,buf+1); - break; - } - - default: - { - struct dgram_packet *dgram = &p->packet.dgram; - DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); - } - } -} - - diff --git a/source/namework.doc b/source/namework.doc deleted file mode 100644 index 958a86c8668..00000000000 --- a/source/namework.doc +++ /dev/null @@ -1,363 +0,0 @@ -/* - Unix SMB/Netbios documentation. - Version 0.1 - Copyright (C) Luke Leighton Andrew Tridgell 1996 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Document name: namework.doc - - Revision History: - - 0.0 - 02jul96 : lkcl@pires.co.uk - created - - 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au - tridge's comments on first revision -*/ - -the module namework.c deals with NetBIOS datagram packets, primarily. -it deals with nmbd's workgroup browser side and the domain log in -side. none of the functionality here has specification documents available. -empirical observation of packet traces has been the order of the day, -along with some guess-work. - -beware! - -the receipt of datagram packets for workgroup browsing are dealt with here. -some of the functions listed here will call others outside of this -module, or will activate functionality dealt with by other modules -(namedb, nameannounce, nameelect, namelogon, and namebrowse). - - -/************************************************************************* - process_browse_packet() - *************************************************************************/ - -this function is responsible for further identifying which type of -browser datagram packet has been received, and dealing with it -accordingly. if the packet is not dealt with, then an error is -logged along with the type of packet that has been received. - -if listening_type() was in use, then it would be used here. - -the types of packets received and dealt with are: - -- ANN_HostAnnouncement -- ANN_DomainAnnouncement -- ANN_LocalMasterAnnouncement - -these are all identical in format and can all be processed by -process_announce(). an announcement is received from a host -(either a master browser telling us about itself, a server -telling us about itself or a master browser telling us about -a domain / workgroup) - -- ANN_AnnouncementRequest - -these are sent by master browsers or by servers. it is a -request to announce ourselves as appropriate by sending -either a ANN_HostAnnouncement datagram or both an -ANN_DomainAnnouncement and an ANN_LocalMasterAnnouncement -if we are a master browser (but not both). - -- ANN_Election - -this is an election datagram. if samba has been configured -as a domain master then it will also send out election -datagrams. - -- ANN_GetBackupListReq - -this is a request from another server for us to send a -backup list of all servers that we know about. we respond -by sending a datagram ANN_GetBackupListResp. the protocol -here is a little dicey. - -- ANN_GetBackupListResp - -this is a response from another server that we have sent an -ANN_GetBackupListReq to. the protocol is a little dicey. - -- ANN_BecomeBackup - -this is a message sent by a master browser to a -potential master browser, indicating that it should become -a backup master browser for the workgroup it is a member -of. samba does not respond at present to such datagrams, -and it also sends out such datagrams for the wrong reasons -(this code has now been disabled until this is fixed). - -- ANN_ResetBrowserState - -this datagram is sent for trouble-shooting purposes. -it asks a browser to clear out its server lists, or to -stop becoming a master browser altogether. NT/AS and -samba do not implement this latter option. - -- ANN_MasterAnnouncement - -this datagram is sent by a master browser to a domain master -browser. it is a way to ensure that master browsers are kept in sync -with a domain master browser across a wide area network. on -receipt of an ANN_MasterAnnouncement we should sync browse lists with -the sender. - -(i never got the hang of this one when i was experimenting. -i forget exactly what it's for, and i never fully worked -out how to coax a server to send it. :-) - -NOTE FROM TRIDGE: The reason you didn't work out how to coax a server -into sending it is that you can't (or shouldn't try!). Basically these -"master announce" datagrams are the way that separate netbios subnets -are linked together to form a complete browse net. The way it works is -that the local master decides it is going to inform the domain master -of its presence, then sends this master announce to the domain -master. The domain master then syncs with the local master using a -"local only" sync. The whole transaction is initiated by the local -master, not the domain master, so the domain master should not do any -of this if it does not first receive a "master announcement". The -local domain masters need to be configured to know the IP address of -the domain master. - - -/************************************************************************* - listening_type() - *************************************************************************/ - - -a datagram packet is sent from one NetBIOS name of a specific type -to another NetBIOS name of a specific type. certain types of -datagrams are only expected from certain types of NetBIOS names. - -this function is intended to catch errors in the type of datagrams -received from different NetBIOS names. it is currently incomplete -due to lack of information on the types of names and the datagrams -they send. - - -/************************************************************************* - process_announce_request() - *************************************************************************/ - -this function is responsible for dealing with announcement requests. -if the type of name that the request is sent to matches our current -status, then we should respond. otherwise, the datagram should be -ignored. - -samba only responds on its local subnets. - -at present, just the name is checked to see if the packet is for us. -what should be done is that if we own the name (e.g WORGROUP(0x1d) -or WORKGROUP(0x1b) then we should respond, otherwise, ignore the -datagram. - -if the name is for us, and we are a member of that workgroup, then -samba should respond. - -note that samba does not respond immediately. this is to ensure that -if the master browser for the workgroup that samba is a member of -sends out a broadcast request announcement, that that master browser -is not swamped with replies. it is therefore up to samba to reply -at some random interval. hence, a flag is set indicating the need -to announce later. - - -/************************************************************************* - process_reset_browser() - *************************************************************************/ - -this function is responsible for dealing with reset state datagrams. -there are three kinds of diagnostic reset requests: - -- stop being a master browser -- discard browse lists, stop being a master browser, and run for re-election -- stop being a master browser forever. - -samba and windows nt do not implement the latter option. - -there appears to be a discrepancy between this description and the -code actually implemented. - - -/************************************************************************* - process_send_backup_list() - *************************************************************************/ - -this function is part of samba's domain master browser functionality. - -it is responsible for giving master browsers a list of other browsers -that maintain backup lists of servers for that master browser's workgroup. - -it is also responsible for giving master browsers a list of domain master -browsers for that local master browser's domain. - -a correct way to think of this function is that it is a 'request to -send out a backup list for the requested workgroup or domain'. - -i have some suspicions and intuitions about this function and how it -is to actually be used. there is no documentation on this, so it is a -matter of experimenting until it's right. - - -/************************************************************************* - send_backup_list() - *************************************************************************/ - -this function is responsible for compiling a list of either master -browsers and backup master browsers or domain master browsers and -backup domain master browsers. samba constructs this list from its -workgroup / server database. - -the list is then sent to the host that requested it by sending an -ANN_GetBackupListResp datagram to this host. - - -NOTE FROM TRIDGE: The "backup list" stuff is only relevant to -local subnets. It has nothing to do with PDCs or domain masters. Its -function is twofold: - -1) spread the browsing load over multiple servers so one server -doesn't get overloaded with browse requests -2) make sure the database doesn't get lost completely if the master -goes down - -To accomplish this a few things are supposed to be done: - -- the master browser maintains a list of "backup browsers". - -- backup browsers are are machines that are just like ordinary servers -but also maintain a browse list and respond to "NetServerEnum" -requests - -- when a server initially announces itself to the master it may set -its "maintain browse list" flag to auto. - -- when a master browser sees a server announcement with "auto" set it -may send a "become backup" to that server telling it to become a -backup. - -- the master has a simple algorithm to determine how many backups it wants -given the number of hosts on the net - -- when a client wishes to get a browse list it asks the master for a -backup list. The master sends it the current list of backup browsers, -including itself. The client caches this list. The client then sends -the NetServerEnum to a random member of this list easch time it wants -to browse. This spreads the load. - - - -/************************************************************************* - process_rcv_backup_list() - *************************************************************************/ - -this function is implemented with a slightly over-kill algorithm. -the correct functionality is to pick any three names at random from -the list that is received from this datagram, and then at intervals -contact _one_ of them for a list of browser, in order to update -samba's browse list. - -samba contacts every single one of the backup browsers listed, through -the use of a NAME_QUERY_SRV_CHK 'state'. - - -/************************************************************************* - process_master_announce() - *************************************************************************/ - -this function is responsible for synchronising browse lists with a -master browser that contacts samba in its capacity as a domain master -browser. - -the function add_browser_entry() is used to add the server that -contacts us to our list of browser to sync browse lists with at -some point in the near future. - - -/************************************************************************* - process_announce() - *************************************************************************/ - -this function is responsible for dealing with the three types of -announcement type datagrams that samba recognises. some appropriate -type-checking is done on the name that the datagram is sent to. - -samba does not at present deal with LanManager announcements. - -these announcements are for updating the browse entry records. -each browse entry has a time-to-live associated with it. each server -must refresh its entry with all other servers by broadcasting -Announcements. if it does not do so, then other servers will not -know about that machine, and the records on each server of that -other machine will die. - -if an ANN_DomainAnnouncement is received, then this will be from -a master browser. only one machine on any given broadcast area (e.g -a subnet) should be broadcasting such announcements. the information -it contains tells other servers that there is a master browser for -this workgroup. if another server thinks that it is also a master -browser for the same workgroup, then it should stop being a master -browser and force an election. - -if an ANN_LocalMasterAnnouncement is received, then a master browser -is telling us that it exists. i am uncertain that anything else -actually needs to be done with this, other than to shout 'hooray' and -'thank you for informing me of this fact'. - - -/************************************************************************* - listening_name() - *************************************************************************/ - -this function is an over-simplified way of identifying whether we -should be responding to a datagram that has been received. - - -/************************************************************************* - same_context() - *************************************************************************/ - -this function helps us to identify whether we should be responding to -a datagram that has been received. - - -/************************************************************************* - tell_become_backup() - *************************************************************************/ - -this function is part of samba's domain master browser capabilities. -it is responsible for finding appropriate servers to tell to become a -backup master browser for the domain that samba controls. - -other servers that contact samba asking for a list of backup browsers -will then be given that server's name, and that server can expect to -receive NetServerEnum requests for lists of servers and workgroups. - -this function must be updated before it is in a fit state to be used. -it must properly check whether a server is prepared to become a backup -browser before actually asking it to be one. - - -/************************************************************************* - reset_server() - *************************************************************************/ - -this function is responsible for issuing an ANN_ResetBrowserState to -the specified server, asking it to reset its browser information. - -see process_reset_browser() for details on this function. - - diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c deleted file mode 100644 index 75544535af2..00000000000 --- a/source/nmbd/nmbd.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 14 jan 96: lkcl@pires.co.uk - added multiple workgroup domain master support - -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - -extern pstring debugf; -pstring servicesf = CONFIGFILE; - -extern pstring scope; - -int ClientNMB = -1; -int ClientDGRAM = -1; - -extern pstring myhostname; -static pstring host_file; -extern pstring myname; -extern fstring myworkgroup; - -/* are we running as a daemon ? */ -static BOOL is_daemon = False; - -/* what server type are we currently */ - -time_t StartupTime =0; - -extern struct in_addr ipzero; - - /**************************************************************************** - catch a sigterm - ****************************************************************************/ -static int sig_term() -{ - BlockSignals(True,SIGTERM); - - DEBUG(0,("Got SIGTERM: going down...\n")); - - /* write out wins.dat file if samba is a WINS server */ - dump_names(); - - /* remove all samba names, with wins server if necessary. */ - remove_my_names(); - - /* announce all server entries as 0 time-to-live, 0 type */ - /* XXXX don't care if we never receive a response back... yet */ - announce_my_servers_removed(); - - /* XXXX other things: if we are a master browser, force an election? */ - - exit(0); - /* Keep compiler happy.. */ - return 0; -} - - -/**************************************************************************** -catch a sighup -****************************************************************************/ -static int sig_hup(void) -{ - BlockSignals(True,SIGHUP); - - DEBUG(0,("Got SIGHUP (reload not implemented)\n")); - dump_names(); - reload_services(True); - - set_samba_nb_type(); - - BlockSignals(False,SIGHUP); -#ifndef DONT_REINSTALL_SIG - signal(SIGHUP,SIGNAL_CAST sig_hup); -#endif - return(0); -} - -/**************************************************************************** -catch a sigpipe -****************************************************************************/ -static int sig_pipe(void) -{ - BlockSignals(True,SIGPIPE); - - DEBUG(0,("Got SIGPIPE\n")); - if (!is_daemon) - exit(1); - BlockSignals(False,SIGPIPE); - return(0); -} - -#if DUMP_CORE -/******************************************************************* -prepare to dump a core file - carefully! -********************************************************************/ -static BOOL dump_core(void) -{ - char *p; - pstring dname; - strcpy(dname,debugf); - if ((p=strrchr(dname,'/'))) *p=0; - strcat(dname,"/corefiles"); - mkdir(dname,0700); - sys_chown(dname,getuid(),getgid()); - chmod(dname,0700); - if (chdir(dname)) return(False); - umask(~(0700)); - -#ifndef NO_GETRLIMIT -#ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit(RLIMIT_CORE, &rlp); - rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur); - setrlimit(RLIMIT_CORE, &rlp); - getrlimit(RLIMIT_CORE, &rlp); - DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max)); - } -#endif -#endif - - - DEBUG(0,("Dumping core in %s\n",dname)); - return(True); -} -#endif - - -/**************************************************************************** -possibly continue after a fault -****************************************************************************/ -static void fault_continue(void) -{ -#if DUMP_CORE - dump_core(); -#endif -} - -/******************************************************************* - expire old names from the namelist and server list - ******************************************************************/ -static void expire_names_and_servers(time_t t) -{ - static time_t lastrun = 0; - - if (!lastrun) lastrun = t; - if (t < lastrun + 5) return; - lastrun = t; - - expire_names(t); - expire_servers(t); -} - -/***************************************************************************** - reload the services file - **************************************************************************/ -BOOL reload_services(BOOL test) -{ - BOOL ret; - extern fstring remote_machine; - - strcpy(remote_machine,"nmbd"); - - if (lp_loaded()) - { - pstring fname; - strcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) - { - strcpy(servicesf,fname); - test = False; - } - } - - if (test && !lp_file_list_changed()) - return(True); - - ret = lp_load(servicesf,True); - - /* perhaps the config filename is now set */ - if (!test) { - DEBUG(3,("services not loaded\n")); - reload_services(True); - } - - /* Do a sanity check for a misconfigured nmbd */ - if(lp_wins_support() && *lp_wins_server()) { - DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \ -cannot be set in the smb.conf file. nmbd aborting.\n")); - exit(10); - } - - return(ret); -} - - - -/**************************************************************************** -load a netbios hosts file -****************************************************************************/ -static void load_hosts_file(char *fname) -{ - FILE *f = fopen(fname,"r"); - pstring line; - if (!f) { - DEBUG(2,("Can't open lmhosts file %s\n",fname)); - return; - } - - while (!feof(f)) - { - pstring ip,name,flags,extra; - struct subnet_record *d; - char *ptr; - int count = 0; - struct in_addr ipaddr; - enum name_source source = LMHOSTS; - - if (!fgets_slash(line,sizeof(pstring),f)) continue; - - if (*line == '#') continue; - - strcpy(ip,""); - strcpy(name,""); - strcpy(flags,""); - - ptr = line; - - if (next_token(&ptr,ip ,NULL)) ++count; - if (next_token(&ptr,name ,NULL)) ++count; - if (next_token(&ptr,flags,NULL)) ++count; - if (next_token(&ptr,extra,NULL)) ++count; - - if (count <= 0) continue; - - if (count > 0 && count < 2) { - DEBUG(0,("Ill formed hosts line [%s]\n",line)); - continue; - } - - if (count >= 4) { - DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname)); - continue; - } - - DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags)); - - if (strchr(flags,'G') || strchr(flags,'S')) { - DEBUG(0,("group flag in %s ignored (obsolete)\n",fname)); - continue; - } - - if (strchr(flags,'M')) { - source = SELF; - strcpy(myname,name); - } - - ipaddr = *interpret_addr2(ip); - d = find_subnet_all(ipaddr); - if (d) { - add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True); - add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True); - } - } - - fclose(f); -} - - -/**************************************************************************** - The main select loop. - ***************************************************************************/ -static void process(void) -{ - BOOL run_election; - - while (True) - { - time_t t = time(NULL); - run_election = check_elections(); - listen_for_packets(run_election); - - run_packet_queue(); - run_elections(t); - - announce_host(t); - announce_master(t); - announce_remote(t); - - query_refresh_names(t); - - expire_names_and_servers(t); - expire_netbios_response_entries(t); - refresh_my_names(t); - - write_browse_list(t); - do_browser_lists(t); - check_master_browser(t); - add_domain_names(t); - } -} - - -/**************************************************************************** - open the socket communication -****************************************************************************/ -static BOOL open_sockets(BOOL isdaemon, int port) -{ - struct hostent *hp; - - /* get host info */ - if ((hp = Get_Hostbyname(myhostname)) == 0) { - DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname)); - return False; - } - - if (isdaemon) - ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address())); - else - ClientNMB = 0; - - ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address())); - - if (ClientNMB == -1) - return(False); - - signal(SIGPIPE, SIGNAL_CAST sig_pipe); - - set_socket_options(ClientNMB,"SO_BROADCAST"); - set_socket_options(ClientDGRAM,"SO_BROADCAST"); - - DEBUG(3,("Sockets opened.\n")); - return True; -} - - -/**************************************************************************** - initialise connect, service and file structs -****************************************************************************/ -static BOOL init_structs() -{ - extern fstring local_machine; - char *p; - - if (! *myname) { - strcpy(myname,myhostname); - p = strchr(myname,'.'); - if (p) *p = 0; - } - strupper(myname); - - strcpy(local_machine,myname); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - if (p) *p = 0; - strlower(local_machine); - - return True; -} - -/**************************************************************************** -usage on the program -****************************************************************************/ -static void usage(char *pname) -{ - DEBUG(0,("Incorrect program usage - is the command line correct?\n")); - - printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname); - printf("Version %s\n",VERSION); - printf("\t-D become a daemon\n"); - printf("\t-p port listen on the specified port\n"); - printf("\t-d debuglevel set the debuglevel\n"); - printf("\t-l log basename. Basename for log/debug files\n"); - printf("\t-n netbiosname. the netbios name to advertise for this host\n"); - printf("\t-H hosts file load a netbios hosts file\n"); - printf("\n"); -} - - -/**************************************************************************** - main program - **************************************************************************/ - int main(int argc,char *argv[]) -{ - int port = NMB_PORT; - int opt; - extern FILE *dbf; - extern char *optarg; - char pidFile[100] = { 0 }; - - *host_file = 0; - - StartupTime = time(NULL); - - TimeInit(); - - strcpy(debugf,NMBLOGFILE); - - setup_logging(argv[0],False); - - charset_initialise(-1); - -#ifdef LMHOSTSFILE - strcpy(host_file,LMHOSTSFILE); -#endif - - /* this is for people who can't start the program correctly */ - while (argc > 1 && (*argv[1] != '-')) { - argv++; - argc--; - } - - fault_setup(fault_continue); - - signal(SIGHUP ,SIGNAL_CAST sig_hup); - signal(SIGTERM,SIGNAL_CAST sig_term); - - while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF) - { - switch (opt) - { - case 'f': - strncpy(pidFile, optarg, sizeof(pidFile)); - break; - case 's': - strcpy(servicesf,optarg); - break; - case 'N': - case 'B': - case 'I': - case 'C': - case 'G': - DEBUG(0,("Obsolete option '%c' used\n",opt)); - break; - case 'H': - strcpy(host_file,optarg); - break; - case 'n': - strcpy(myname,optarg); - strupper(myname); - break; - case 'l': - sprintf(debugf,"%s.nmb",optarg); - break; - case 'i': - strcpy(scope,optarg); - strupper(scope); - break; - case 'D': - is_daemon = True; - break; - case 'd': - DEBUGLEVEL = atoi(optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 'h': - usage(argv[0]); - exit(0); - break; - default: - if (!is_a_socket(0)) { - usage(argv[0]); - } - break; - } - } - - DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION)); - DEBUG(1,("Copyright Andrew Tridgell 1994\n")); - - get_myname(myhostname,NULL); - - if (!reload_services(False)) - return(-1); - - charset_initialise(lp_client_code_page()); - - init_structs(); - - reload_services(True); - - strcpy(myworkgroup, lp_workgroup()); - - if (strequal(myworkgroup,"*")) { - DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); - exit(1); - } - - set_samba_nb_type(); - - if (!is_daemon && !is_a_socket(0)) { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - is_daemon = True; - } - - if (is_daemon) { - DEBUG(2,("%s becoming a daemon\n",timestring())); - become_daemon(); - } - - if (*pidFile) - { - int fd; - char buf[20]; - - if ((fd = open(pidFile, - O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0) - { - DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno))); - exit(1); - } - if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False) - { - DEBUG(0,("ERROR: nmbd is already running\n")); - exit(1); - } - sprintf(buf, "%u\n", (unsigned int) getpid()); - if (write(fd, buf, strlen(buf)) < 0) - { - DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno))); - exit(1); - } - /* Leave pid file open & locked for the duration... */ - } - - - DEBUG(3,("Opening sockets %d\n", port)); - - if (!open_sockets(is_daemon,port)) return 1; - - load_interfaces(); - add_my_subnets(myworkgroup); - - add_my_names(); - - DEBUG(3,("Checked names\n")); - - load_netbios_names(); - - DEBUG(3,("Loaded names\n")); - - if (*host_file) { - load_hosts_file(host_file); - DEBUG(3,("Loaded hosts file\n")); - } - - write_browse_list(time(NULL)); - - DEBUG(3,("Dumped names\n")); - - /* We can only take sigterm signals in the select. */ - BlockSignals(True,SIGTERM); - process(); - close_sockets(); - - if (dbf) - fclose(dbf); - return(0); -} diff --git a/source/nmbsync.c b/source/nmbsync.c deleted file mode 100644 index 97e7e02b2b9..00000000000 --- a/source/nmbsync.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines to synchronise browse lists - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - -extern int ClientNMB; -extern int ClientDGRAM; - -extern int DEBUGLEVEL; - -extern pstring myname; - -extern int name_type; -extern int max_protocol; -extern struct in_addr dest_ip; -extern int pid; -extern int gid; -extern int uid; -extern int mid; -extern BOOL got_pass; -extern BOOL have_ip; -extern pstring workgroup; -extern pstring service; -extern pstring desthost; -extern BOOL connect_as_ipc; - -/**************************************************************************** -fudge for getpass function -****************************************************************************/ -char *getsmbpass(char *pass) -{ - return "dummy"; /* return anything: it should be ignored anyway */ -} - -/**************************************************************************** -adds information retrieved from a NetServerEnum call -****************************************************************************/ -static BOOL add_info(struct subnet_record *d, struct work_record *work, int servertype) -{ - char *rparam = NULL; - char *rdata = NULL; - int rdrcnt,rprcnt; - char *p; - pstring param; - int uLevel = 1; - int count = -1; - - /* now send a SMBtrans command with api ServerEnum? */ - p = param; - SSVAL(p,0,0x68); /* api number */ - p += 2; - strcpy(p,"WrLehDz"); - p = skip_string(p,1); - - strcpy(p,"B16BBDz"); - - p = skip_string(p,1); - SSVAL(p,0,uLevel); - SSVAL(p,2,0x2000); /* buf length */ - p += 4; - SIVAL(p,0,servertype); - p += 4; - - strcpy(p, work->work_group); - p = skip_string(p,1); - - if (cli_call_api(PTR_DIFF(p,param),0, 8,10000, - &rprcnt,&rdrcnt, param,NULL, - &rparam,&rdata)) - { - int res = SVAL(rparam,0); - int converter=SVAL(rparam,2); - int i; - - if (res == 0) - { - count=SVAL(rparam,4); - p = rdata; - - for (i = 0;i < count;i++, p += 26) - { - char *sname = p; - uint32 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; - int comment_offset = IVAL(p,22) & 0xFFFF; - char *cmnt = comment_offset?(rdata+comment_offset-converter):""; - - struct work_record *w = work; - - DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); - - if (stype & SV_TYPE_DOMAIN_ENUM) - { - /* creates workgroup on remote subnet */ - if ((w = find_workgroupstruct(d,sname,True))) - { - announce_request(w, d->bcast_ip); - } - } - - if (w) - add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); - } - } - } - - if (rparam) free(rparam); - if (rdata) free(rdata); - - return(True); -} - - -/******************************************************************* - synchronise browse lists with another browse server. - - log in on the remote server's SMB port to their IPC$ service, - do a NetServerEnum and update our server and workgroup databases. - ******************************************************************/ -void sync_browse_lists(struct subnet_record *d, struct work_record *work, - char *name, int nm_type, struct in_addr ip, BOOL local) -{ - uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; - - if (!d || !work ) return; - - if(d != wins_subnet) { - DEBUG(0, - ("sync_browse_lists: ERROR sync requested on non-WINS subnet.\n")); - return; - } - - pid = getpid(); - uid = getuid(); - gid = getgid(); - mid = pid + 100; - name_type = nm_type; - - got_pass = True; - - DEBUG(0,("sync_browse_lists: Sync browse lists with %s for %s %s\n", - name, work->work_group, inet_ntoa(ip))); - - strcpy(workgroup,work->work_group); - strcpy(desthost,name); - dest_ip = ip; - - if (zero_ip(dest_ip)) return; - have_ip = True; - - connect_as_ipc = True; - - /* connect as server and get domains, then servers */ - - sprintf(service,"\\\\%s\\IPC$", name); - strupper(service); - - if (cli_open_sockets(SMB_PORT)) - { - if (cli_send_login(NULL,NULL,True,True)) - { - add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM); - add_info(d, work, local_type|(SV_TYPE_ALL& - ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY))); - } - - close_sockets(); - } -} diff --git a/source/param/params.c b/source/param/params.c deleted file mode 100644 index 0fdde0348ff..00000000000 --- a/source/param/params.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Parameter loading utlities - Copyright (C) Karl Auer 1993,1994,1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/************************************************************************** -PARAMS.C - -Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer - -This module provides for streamlines retrieval of information from a -Windows-like parameter files. There is a function which will search for -all sections in the file and call a specified function with each. There is -a similar function which will call a specified function for all parameters -in a section. The idea is that you pass the addresses of suitable functions -to a single function in this module which will then enumerate all sections, -and within each section all parameters, to your program. - -Parameter files contain text lines (newline delimited) which consist of -either a section name in square brackets or a parameter name, delimited -from the parameter value by an equals sign. Blank lines or lines where the -first non-whitespace character is a colon are ignored. All whitespace in -section names and parameter names is compressed to single spaces. Leading -and trailing whitespace on parameter names and parameter values is stripped. - -Only the first equals sign in a parameter line is significant - parameter -values may contain equals signs, square brackets and semicolons. Internal -whitespace is retained in parameter values. Parameter names may not start -with a square bracket, an equals sign or a semicolon, for obvious reasons. - -A sample parameter file might look like this: - -[things] -this=1 -that=2 -[other things] -the other = 3 - -**************************************************************************/ - -#include "includes.h" - -#include "smb.h" - -/* local variable pointing to passed filename */ -static char *pszParmFile = NULL; -extern int DEBUGLEVEL; - - -/************************************************************************** -Strip all leading whitespace from a string. -**************************************************************************/ -static void trimleft(char *psz) -{ - char *pszDest; - - pszDest = psz; - if (psz != NULL) - { - while (*psz != '\0' && isspace(*psz)) - psz++; - while (*psz != '\0') - *pszDest++ = *psz++; - *pszDest = '\0'; - } -} - -/************************************************************************** -Strip all trailing whitespace from a string. -**************************************************************************/ -static void trimright(char *psz) -{ - char *pszTemp; - - if (psz != NULL && psz[0] != '\0') - { - pszTemp = psz + strlen(psz) - 1; - while (isspace(*pszTemp)) - *pszTemp-- = '\0'; - } -} - -/*********************************************************************** -Collapse each whitespace area in a string to a single space. -***********************************************************************/ -static void collapse_spaces(char *psz) -{ - while (*psz) - if (isspace(*psz)) - { - *psz++ = ' '; - trimleft(psz); - } - else - psz++; -} - -/************************************************************************** -Return the value of the first non-white character in the specified string. -The terminating NUL counts as non-white for the purposes of this function. -Note - no check for a NULL string! What would we return? -**************************************************************************/ -static int firstnonwhite(char *psz) -{ - while (isspace(*psz) && (*psz != '\0')) - psz++; - return (*psz); -} - - -/************************************************************************** -Identifies all parameters in the current section, calls the parameter -function for each. Ignores comment lines, stops and backs up in file when -a section is encountered. Returns True on success, False on error. -**************************************************************************/ -static BOOL enumerate_parameters(FILE *fileIn, BOOL (*pfunc)(char *,char *)) -{ - pstring szBuf; - char *pszTemp; - BOOL bRetval; - long lFileOffset; - int cTemp; - BOOL bParmFound; - - bRetval = False; - bParmFound = False; - while (True) - { - /* first remember where we are */ - if ((lFileOffset = ftell(fileIn)) >= 0L) - { - /* then get and check a line */ - if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL) - { - /* stop - return OK unless file error */ - bRetval = !ferror(fileIn); - if (!bRetval) - DEBUG(0,( "Read error on configuration file (enumerating parameters)!\n")); - break; - } - else - /* if first non-white is a '[', stop (new section) */ - if ((cTemp = firstnonwhite(szBuf)) == '[') - { - /* restore position to start of new section */ - if (fseek(fileIn, lFileOffset, SEEK_SET) < 0L) - { - DEBUG(0,( "Seek error on configuration file!\n")); - break; - } - - /* return success */ - bRetval = True; - break; - } - else - /* if it's a semicolon or line is blank, ignore the line */ - if (!cTemp || strchr(";#",cTemp)) - { - continue; - } - else - /* if no equals sign and line contains non-whitespace */ - /* then line is badly formed */ - if ((pszTemp = strchr(szBuf, '=')) == NULL) - { - DEBUG(0,( "Ignoring badly formed line: %s", szBuf)); - } - else - { - /* Note that we have found a parameter */ - bParmFound = True; - /* cut line at the equals sign */ - *pszTemp++ = '\0'; - /* trim leading and trailing space from both halves */ - trimright(szBuf); - trimleft(szBuf); - trimright(pszTemp); - trimleft(pszTemp); - /* process the parameter iff passed pointer not NULL */ - if (pfunc != NULL) - if (!pfunc(szBuf, pszTemp)) - break; - } - } - } - return (bRetval); -} - - -/*********************************************************************** -Close up s by n chars, at offset start. -***********************************************************************/ -static void closestr(char *s, int start, int n) -{ - char *src; - char *dest; - int len; - - if (n > 0) - if ((src = dest = s) != NULL) - { - len = strlen(s); - if (start >= 0 && start < len - n) - { - src += start + n; - dest += start; - - while (*src) - *dest++ = *src++; - *dest = '\0'; - } - } -} - -/************************************************************************** -Identifies all sections in the parameter file, calls passed section_func() -for each, passing the section name, then calls enumerate_parameters(). -Returns True on success, False on failure. Note that the section and -parameter names will have all internal whitespace areas collapsed to a -single space for processing. -**************************************************************************/ -static BOOL enumerate_sections(FILE *fileIn, - BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *)) -{ - pstring szBuf; - BOOL bRetval; - BOOL bSectionFound; - - /* this makes sure we get include lines right */ - enumerate_parameters(fileIn, pfunc); - - bRetval = False; - bSectionFound = False; - while (True) - { - if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL) - { - /* stop - return OK unless file error */ - bRetval = !ferror(fileIn); - if (!bRetval) - DEBUG(0,( "Read error on configuration file (enumerating sections)!\n")); - break; - } - else - { - trimleft(szBuf); - trimright(szBuf); - if (szBuf[0] == '[') - { - closestr(szBuf, 0, 1); - if (strlen(szBuf) > 1) - if (szBuf[strlen(szBuf) - 1] == ']') - { - /* found a section - note the fact */ - bSectionFound = True; - /* remove trailing metabracket */ - szBuf[strlen(szBuf) - 1] = '\0'; - /* remove leading and trailing whitespace from name */ - trimleft(szBuf); - trimright(szBuf); - /* reduce all internal whitespace to one space */ - collapse_spaces(szBuf); - /* process it - stop if the processing fails */ - if (sfunc != NULL) - if (!sfunc(szBuf)) - break; - if (!enumerate_parameters(fileIn, pfunc)) - break; - } - } - } - } - - return (bRetval); -} - -/************************************************************************** -Process the passed parameter file. - -Returns True if successful, else False. -**************************************************************************/ -BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *)) -{ - FILE *fileIn; - BOOL bRetval; - - bRetval = False; - - /* record the filename for use in error messages one day... */ - pszParmFile = pszFileName; - - if (pszParmFile == NULL || strlen(pszParmFile) < 1) - DEBUG(0,( "No configuration filename specified!\n")); - else - if ((fileIn = fopen(pszParmFile, "r")) == NULL) - DEBUG(0,( "Unable to open configuration file \"%s\"!\n", pszParmFile)); - else - { - DEBUG(3,("Processing configuration file \"%s\"\n", pszParmFile)); - bRetval = enumerate_sections(fileIn, sfunc, pfunc); - fclose(fileIn); - } - - if (!bRetval) - DEBUG(0,("pm_process retuned false\n")); - return (bRetval); -} - - diff --git a/source/passdb/smbpass.c b/source/passdb/smbpass.c deleted file mode 100644 index 275ad5e353b..00000000000 --- a/source/passdb/smbpass.c +++ /dev/null @@ -1,299 +0,0 @@ -#ifdef SMB_PASSWD -/* - * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup - * Copyright (C) Andrew Tridgell 1992-1995 Modified by Jeremy Allison 1995. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 675 - * Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - -extern int DEBUGLEVEL; - -int gotalarm; - -void -gotalarm_sig() -{ - gotalarm = 1; -} - -int -do_pw_lock(int fd, int waitsecs, int type) -{ - struct flock lock; - int ret; - - gotalarm = 0; - signal(SIGALRM, SIGNAL_CAST gotalarm_sig); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 1; - lock.l_pid = 0; - - alarm(5); - ret = fcntl(fd, F_SETLKW, &lock); - alarm(0); - signal(SIGALRM, SIGNAL_CAST SIG_DFL); - - if (gotalarm) { - DEBUG(0, ("do_pw_lock: failed to %s SMB passwd file.\n", - type == F_UNLCK ? "unlock" : "lock")); - return -1; - } - return ret; -} - -int pw_file_lock(char *name, int type, int secs) -{ - int fd = open(name, O_RDWR | O_CREAT, 0600); - if (fd < 0) - return (-1); - if (do_pw_lock(fd, secs, type)) { - close(fd); - return -1; - } - return fd; -} - -int pw_file_unlock(int fd) -{ - do_pw_lock(fd, 5, F_UNLCK); - return close(fd); -} - -/* - * Routine to get the next 32 hex characters and turn them - * into a 16 byte array. - */ - -static int gethexpwd(char *p, char *pwd) -{ - int i; - unsigned char lonybble, hinybble; - char *hexchars = "0123456789ABCDEF"; - char *p1, *p2; - - for (i = 0; i < 32; i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); - - p1 = strchr(hexchars, hinybble); - p2 = strchr(hexchars, lonybble); - if (!p1 || !p2) - return (False); - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); - - pwd[i / 2] = (hinybble << 4) | lonybble; - } - return (True); -} - -/* - * Routine to search the smbpasswd file for an entry matching the username. - */ -struct smb_passwd *get_smbpwnam(char *name) -{ - /* Static buffers we will return. */ - static struct smb_passwd pw_buf; - static pstring user_name; - static unsigned char smbpwd[16]; - static unsigned char smbntpwd[16]; - char linebuf[256]; - char readbuf[16 * 1024]; - unsigned char c; - unsigned char *p; - long uidval; - long linebuf_len; - FILE *fp; - int lockfd; - char *pfile = lp_smb_passwd_file(); - - if (!*pfile) { - DEBUG(0, ("No SMB password file set\n")); - return (NULL); - } - DEBUG(10, ("get_smbpwnam: opening file %s\n", pfile)); - - fp = fopen(pfile, "r"); - - if (fp == NULL) { - DEBUG(0, ("get_smbpwnam: unable to open file %s\n", pfile)); - return NULL; - } - /* Set a 16k buffer to do more efficient reads */ - setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - - if ((lockfd = pw_file_lock(pfile, F_RDLCK, 5)) < 0) { - DEBUG(0, ("get_smbpwnam: unable to lock file %s\n", pfile)); - fclose(fp); - return NULL; - } - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* We have a read lock on the file. */ - /* - * Scan the file, a line at a time and check if the name matches. - */ - while (!feof(fp)) { - linebuf[0] = '\0'; - - fgets(linebuf, 256, fp); - if (ferror(fp)) { - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - linebuf_len = strlen(linebuf); - if (linebuf[linebuf_len - 1] != '\n') { - c = '\0'; - while (!ferror(fp) && !feof(fp)) { - c = fgetc(fp); - if (c == '\n') - break; - } - } else - linebuf[linebuf_len - 1] = '\0'; - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("get_smbpwnam: got line |%s|\n", linebuf)); -#endif - if ((linebuf[0] == 0) && feof(fp)) { - DEBUG(4, ("get_smbpwnam: end of file reached\n")); - break; - } - /* - * The line we have should be of the form :- - * - * username:uid:[32hex bytes]:....other flags presently - * ignored.... - * - * or, - * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... - * - * if Windows NT compatible passwords are also present. - */ - - if (linebuf[0] == '#' || linebuf[0] == '\0') { - DEBUG(6, ("get_smbpwnam: skipping comment or blank line\n")); - continue; - } - p = (unsigned char *) strchr(linebuf, ':'); - if (p == NULL) { - DEBUG(0, ("get_smbpwnam: malformed password entry (no :)\n")); - continue; - } - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); - user_name[PTR_DIFF(p, linebuf)] = '\0'; - if (!strequal(user_name, name)) - continue; - - /* User name matches - get uid and password */ - p++; /* Go past ':' */ - if (!isdigit(*p)) { - DEBUG(0, ("get_smbpwnam: malformed password entry (uid not number)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - uidval = atoi((char *) p); - while (*p && isdigit(*p)) - p++; - if (*p != ':') { - DEBUG(0, ("get_smbpwnam: malformed password entry (no : after uid)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - /* - * Now get the password value - this should be 32 hex digits - * which are the ascii representations of a 16 byte string. - * Get two at a time and put them into the password. - */ - p++; - if (*p == '*' || *p == 'X') { - /* Password deliberately invalid - end here. */ - DEBUG(10, ("get_smbpwnam: entry invalidated for user %s\n", user_name)); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) { - DEBUG(0, ("get_smbpwnam: malformed password entry (passwd too short)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return (False); - } - if (p[32] != ':') { - DEBUG(0, ("get_smbpwnam: malformed password entry (no terminating :)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - if (!strncasecmp((char *) p, "NO PASSWORD", 11)) { - pw_buf.smb_passwd = NULL; - } else { - if(!gethexpwd((char *)p,(char *)smbpwd)) { - DEBUG(0, ("Malformed Lanman password entry (non hex chars)\n")); - fclose(fp); - pw_file_unlock(lockfd); - return NULL; - } - pw_buf.smb_passwd = smbpwd; - } - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; - pw_buf.smb_nt_passwd = NULL; - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { - if (*p != '*' && *p != 'X') { - if(gethexpwd((char *)p,(char *)smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; - } - } - - fclose(fp); - pw_file_unlock(lockfd); - DEBUG(5, ("get_smbpwname: returning passwd entry for user %s, uid %d\n", - user_name, uidval)); - return &pw_buf; - } - - fclose(fp); - pw_file_unlock(lockfd); - return NULL; -} -#else - void smbpass_dummy(void) -{ -} /* To avoid compiler complaints */ -#endif diff --git a/source/printing/pcap.c b/source/printing/pcap.c deleted file mode 100644 index 13b850b3f5b..00000000000 --- a/source/printing/pcap.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - printcap parsing - Copyright (C) Karl Auer 1993,1994 - - Re-working by Martin Kiff, 1994 - - Re-written again by Andrew Tridgell - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * Parse printcap file. - * - * This module does exactly one thing - it looks into the printcap file - * and tells callers if a specified string appears as a printer name. - * - * The way this module looks at the printcap file is very simplistic. - * Only the local printcap file is inspected (no searching of NIS - * databases etc). - * - * There are assumed to be one or more printer names per record, held - * as a set of sub-fields separated by vertical bar symbols ('|') in the - * first field of the record. The field separator is assumed to be a colon - * ':' and the record separator a newline. - * - * Lines ending with a backspace '\' are assumed to flag that the following - * line is a continuation line so that a set of lines can be read as one - * printcap entry. - * - * A line stating with a hash '#' is assumed to be a comment and is ignored - * Comments are discarded before the record is strung together from the - * set of continuation lines. - * - * Opening a pipe for "lpc status" and reading that would probably - * be pretty effective. Code to do this already exists in the freely - * distributable PCNFS server code. - */ - -#include "includes.h" - -#include "smb.h" - -extern int DEBUGLEVEL; - -#ifdef AIX -/* ****************************************** - Extend for AIX system and qconfig file - from 'boulard@univ-rennes1.fr - ****************************************** */ -static int strlocate(char *xpLine,char *xpS) -{ - int iS,iL,i,iRet; - char *p; - iS = strlen(xpS); - iL = strlen(xpLine); - - iRet = 0; - p = xpLine; - while (iL >= iS) - { - if (strncmp(p,xpS,iS) == 0) {iRet =1;break;}; - p++; - iL--; - } - /*DEBUG(3,(" strlocate %s in line '%s',ret=%d\n",xpS,xpLine,iRet));*/ - - return(iRet); -} - - -/* ******************************************************************* */ -/* * Scan qconfig and search all virtual printer (device printer) * */ -/* ******************************************************************* */ -static void ScanQconfig_fn(char *psz,void (*fn)()) -{ - int iLg,iEtat; - FILE *pfile; - char *line,*p; - pstring name,comment; - line = NULL; - *name = 0; - *comment = 0; - - if ((pfile = fopen(psz, "r")) == NULL) - { - DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); - return; - } - - iEtat = 0; - /* scan qconfig file for searching <printername>: */ - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) - { - if (*line == '*' || *line == 0) - continue; - switch (iEtat) - { - case 0: /* locate an entry */ - if (*line == '\t' || *line == ' ') continue; - if ((p=strchr(line,':'))) - { - *p = '\0'; - p = strtok(line,":"); - if (strcmp(p,"bsh")!=0) - { - strcpy(name,p); - iEtat = 1; - continue; - } - } - break; - case 1: /* scanning device stanza */ - if (*line == '*' || *line == 0) continue; - if (*line != '\t' && *line != ' ') - { - /* name is found without stanza device */ - /* probably a good printer ??? */ - fn(name,comment); - iEtat = 0; - continue; - } - - if (strlocate(line,"backend")) - { - /* it's a device, not a virtual printer*/ - iEtat = 0; - } - else if (strlocate(line,"device")) - { - /* it's a good virtual printer */ - fn(name,comment); - iEtat = 0; - continue; - } - break; - } - } - fclose(pfile); -} - -/* Scan qconfig file and locate de printername */ - -static BOOL ScanQconfig(char *psz,char *pszPrintername) -{ - int iLg,iEtat; - FILE *pfile; - char *pName; - char *line; - - pName = NULL; - line = NULL; - if ((pszPrintername!= NULL) && ((iLg = strlen(pszPrintername)) > 0)) - pName = malloc(iLg+10); - if (pName == NULL) - { - DEBUG(0,(" Unable to allocate memory for printer %s\n",pszPrintername)); - return(False); - } - if ((pfile = fopen(psz, "r")) == NULL) - { - DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); - free(pName); - return(False); - } - sprintf(pName,"%s:",pszPrintername); - iLg = strlen(pName); - /*DEBUG(3,( " Looking for entry %s\n",pName));*/ - iEtat = 0; - /* scan qconfig file for searching <printername>: */ - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) - { - if (*line == '*' || *line == 0) - continue; - switch (iEtat) - { - case 0: /* scanning entry */ - if (strncmp(line,pName,iLg) == 0) - { - iEtat = 1; - continue; - } - break; - case 1: /* scanning device stanza */ - if (*line == '*' || *line == 0) continue; - if (*line != '\t' && *line != ' ') - { - /* name is found without stanza device */ - /* probably a good printer ??? */ - free (line); - free(pName); - fclose(pfile); - return(True); - } - - if (strlocate(line,"backend")) - { - /* it's a device, not a virtual printer*/ - iEtat = 0; - } - else if (strlocate(line,"device")) - { - /* it's a good virtual printer */ - free (line); - free(pName); - fclose(pfile); - return(True); - } - break; - } - } - free (pName); - fclose(pfile); - return(False); -} - -#endif -/*************************************************************************** -Scan printcap file pszPrintcapname for a printer called pszPrintername. -Return True if found, else False. Returns False on error, too, after logging -the error at level 0. For generality, the printcap name may be passed - if -passed as NULL, the configuration will be queried for the name. -***************************************************************************/ -BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname) -{ - char *line=NULL; - char *psz; - char *p,*q; - FILE *pfile; - - if (pszPrintername == NULL || pszPrintername[0] == '\0') - { - DEBUG(0,( "Attempt to locate null printername! Internal error?\n")); - return(False); - } - - /* only go looking if no printcap name supplied */ - if ((psz = pszPrintcapname) == NULL || psz[0] == '\0') - if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) - { - DEBUG(0,( "No printcap file name configured!\n")); - return(False); - } -#ifdef AIX - if (strlocate(psz,"/qconfig") != NULL) - return(ScanQconfig(psz,pszPrintername)); -#endif - if ((pfile = fopen(psz, "r")) == NULL) - { - DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); - return(False); - } - - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) - { - if (*line == '#' || *line == 0) - continue; - - /* now we have a real printer line - cut it off at the first : */ - p = strchr(line,':'); - if (p) *p = 0; - - /* now just check if the name is in the list */ - /* NOTE: I avoid strtok as the fn calling this one may be using it */ - for (p=line; p; p=q) - { - if ((q = strchr(p,'|'))) *q++ = 0; - - if (strequal(p,pszPrintername)) - { - /* normalise the case */ - strcpy(pszPrintername,p); - free(line); - fclose(pfile); - return(True); - } - p = q; - } - } - - - fclose(pfile); - return(False); -} - - -/*************************************************************************** -run a function on each printer name in the printcap file. The function is -passed the primary name and the comment (if possible) -***************************************************************************/ -void pcap_printer_fn(void (*fn)()) -{ - pstring name,comment; - char *line; - char *psz; - char *p,*q; - FILE *pfile; - - /* only go looking if no printcap name supplied */ - if (((psz = lp_printcapname()) == NULL) || (psz[0] == '\0')) - { - DEBUG(0,( "No printcap file name configured!\n")); - return; - } - -#ifdef AIX - if (strlocate(psz,"/qconfig") != NULL) - { - ScanQconfig_fn(psz,fn); - return; - } -#endif - if ((pfile = fopen(psz, "r")) == NULL) - { - DEBUG(0,( "Unable to open printcap file %s for read!\n", psz)); - return; - } - - for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) - { - if (*line == '#' || *line == 0) - continue; - - /* now we have a real printer line - cut it off at the first : */ - p = strchr(line,':'); - if (p) *p = 0; - - /* now find the most likely printer name and comment - this is pure guesswork, but it's better than nothing */ - *name = 0; - *comment = 0; - for (p=line; p; p=q) - { - BOOL has_punctuation; - if ((q = strchr(p,'|'))) *q++ = 0; - - has_punctuation = (strchr(p,' ') || strchr(p,'(') || strchr(p,')')); - - if (strlen(p)>strlen(comment) && has_punctuation) - { - StrnCpy(comment,p,sizeof(comment)-1); - continue; - } - - if (strlen(p) <= 8 && strlen(p)>strlen(name) && !has_punctuation) - { - if (!*comment) strcpy(comment,name); - strcpy(name,p); - continue; - } - - if (!strchr(comment,' ') && - strlen(p) > strlen(comment)) - { - StrnCpy(comment,p,sizeof(comment)-1); - continue; - } - } - - comment[60] = 0; - name[8] = 0; - - if (*name) - fn(name,comment); - } - fclose(pfile); -} diff --git a/source/printing/printing.c b/source/printing/printing.c deleted file mode 100644 index c4dd9803ebe..00000000000 --- a/source/printing/printing.c +++ /dev/null @@ -1,1082 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - printing routines - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -extern int DEBUGLEVEL; -extern connection_struct Connections[]; -extern files_struct Files[]; - -static BOOL * lpq_cache_reset=NULL; - -static int check_lpq_cache(int snum) { - static int lpq_caches=0; - - if (lpq_caches <= snum) { - BOOL * p; - p = (BOOL *) Realloc(lpq_cache_reset,(snum+1)*sizeof(BOOL)); - if (p) { - lpq_cache_reset=p; - lpq_caches = snum+1; - } - } - return lpq_caches; -} - -void lpq_reset(int snum) -{ - if (check_lpq_cache(snum) > snum) lpq_cache_reset[snum]=True; -} - - -/**************************************************************************** -Build the print command in the supplied buffer. This means getting the -print command for the service and inserting the printer name and the -print file name. Return NULL on error, else the passed buffer pointer. -****************************************************************************/ -static char *build_print_command(int cnum, char *command, char *syscmd, char *filename1) -{ - int snum = SNUM(cnum); - char *tstr; - pstring filename; - - /* get the print command for the service. */ - tstr = command; - if (!syscmd || !tstr) { - DEBUG(0,("No print command for service `%s'\n", SERVICE(snum))); - return (NULL); - } - - /* copy the command into the buffer for extensive meddling. */ - StrnCpy(syscmd, tstr, sizeof(pstring) - 1); - - /* look for "%s" in the string. If there is no %s, we cannot print. */ - if (!strstr(syscmd, "%s") && !strstr(syscmd, "%f")) { - DEBUG(2,("WARNING! No placeholder for the filename in the print command for service %s!\n", SERVICE(snum))); - } - - if (strstr(syscmd,"%s")) { - int iOffset = PTR_DIFF(strstr(syscmd, "%s"),syscmd); - - /* construct the full path for the filename, shouldn't be necessary unless - the subshell causes a "cd" to be executed. - Only use the full path if there isn't a / preceding the %s */ - if (iOffset==0 || syscmd[iOffset-1] != '/') { - StrnCpy(filename,Connections[cnum].connectpath,sizeof(filename)-1); - trim_string(filename,"","/"); - strcat(filename,"/"); - strcat(filename,filename1); - } - else - strcpy(filename,filename1); - - string_sub(syscmd, "%s", filename); - } - - string_sub(syscmd, "%f", filename1); - - /* Does the service have a printername? If not, make a fake and empty */ - /* printer name. That way a %p is treated sanely if no printer */ - /* name was specified to replace it. This eventuality is logged. */ - tstr = PRINTERNAME(snum); - if (tstr == NULL || tstr[0] == '\0') { - DEBUG(3,( "No printer name - using %s.\n", SERVICE(snum))); - tstr = SERVICE(snum); - } - - string_sub(syscmd, "%p", tstr); - - standard_sub(cnum,syscmd); - - return (syscmd); -} - - -/**************************************************************************** -print a file - called on closing the file -****************************************************************************/ -void print_file(int fnum) -{ - pstring syscmd; - int cnum = Files[fnum].cnum; - int snum=SNUM(cnum); - char *tempstr; - - *syscmd = 0; - - if (file_size(Files[fnum].name) <= 0) { - DEBUG(3,("Discarding null print job %s\n",Files[fnum].name)); - sys_unlink(Files[fnum].name); - return; - } - - tempstr = build_print_command(cnum, PRINTCOMMAND(snum), syscmd, Files[fnum].name); - if (tempstr != NULL) - { - int ret = smbrun(syscmd,NULL,False); - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - } - else - DEBUG(0,("Null print command?\n")); - - lpq_reset(snum); -} - -static char *Months[13] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Err"}; - - -/******************************************************************* -process time fields -********************************************************************/ -static time_t EntryTime(string tok[], int ptr, int count, int minimum) -{ - time_t jobtime,jobtime1; - - jobtime = time(NULL); /* default case: take current time */ - if (count >= minimum) { - struct tm *t; - int i, day, hour, min, sec; - char *c; - - for (i=0; i<13; i++) if (!strncmp(tok[ptr], Months[i],3)) break; /* Find month */ - if (i<12) { - t = localtime(&jobtime); - day = atoi(tok[ptr+1]); - c=(char *)(tok[ptr+2]); - *(c+2)=0; - hour = atoi(c); - *(c+5)=0; - min = atoi(c+3); - if(*(c+6) != 0)sec = atoi(c+6); - else sec=0; - - if ((t->tm_mon < i)|| - ((t->tm_mon == i)&& - ((t->tm_mday < day)|| - ((t->tm_mday == day)&& - (t->tm_hour*60+t->tm_min < hour*60+min))))) - t->tm_year--; /* last year's print job */ - - t->tm_mon = i; - t->tm_mday = day; - t->tm_hour = hour; - t->tm_min = min; - t->tm_sec = sec; - jobtime1 = mktime(t); - if (jobtime1 != (time_t)-1) - jobtime = jobtime1; - } - } - return jobtime; -} - - -/**************************************************************************** -parse a lpq line - -here is an example of lpq output under bsd - -Warning: no daemon present -Rank Owner Job Files Total Size -1st tridge 148 README 8096 bytes - -here is an example of lpq output under osf/1 - -Warning: no daemon present -Rank Pri Owner Job Files Total Size -1st 0 tridge 148 README 8096 bytes -****************************************************************************/ -static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first) -{ -#ifdef OSF1 -#define RANKTOK 0 -#define PRIOTOK 1 -#define USERTOK 2 -#define JOBTOK 3 -#define FILETOK 4 -#define TOTALTOK 5 -#define NTOK 6 -#else /* OSF1 */ -#define RANKTOK 0 -#define USERTOK 1 -#define JOBTOK 2 -#define FILETOK 3 -#define TOTALTOK 4 -#define NTOK 5 -#endif /* OSF1 */ - - string tok[NTOK]; - int count=0; - -#ifdef OSF1 - int length; - length = strlen(line); - if (line[length-3] == ':') - return(False); -#endif /* OSF1 */ - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN"); - string_sub(line,"(","\""); - string_sub(line,")","\""); - - for (count=0; count<NTOK && next_token(&line,tok[count],NULL); count++) ; - - /* we must get NTOK tokens */ - if (count < NTOK) - return(False); - - /* the Job and Total columns must be integer */ - if (!isdigit(*tok[JOBTOK]) || !isdigit(*tok[TOTALTOK])) return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr(tok[FILETOK],' ')) - strcpy(tok[FILETOK],"STDIN"); - - /* only take the last part of the filename */ - { - string tmp; - char *p = strrchr(tok[FILETOK],'/'); - if (p) - { - strcpy(tmp,p+1); - strcpy(tok[FILETOK],tmp); - } - } - - - buf->job = atoi(tok[JOBTOK]); - buf->size = atoi(tok[TOTALTOK]); - buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->time = time(NULL); - StrnCpy(buf->user,tok[USERTOK],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[FILETOK],sizeof(buf->file)-1); -#ifdef PRIOTOK - buf->priority = atoi(tok[PRIOTOK]); -#else - buf->priority = 1; -#endif - return(True); -} - -/* -<magnus@hum.auc.dk> -LPRng_time modifies the current date by inserting the hour and minute from -the lpq output. The lpq time looks like "23:15:07" -*/ -static time_t LPRng_time(string tok[],int pos) -{ - time_t jobtime; - struct tm *t; - char tmp_time[9]; - - jobtime = time(NULL); /* default case: take current time */ - t = localtime(&jobtime); - t->tm_hour = atoi(tok[pos]); - StrnCpy(tmp_time,tok[pos],sizeof(tmp_time)); - t->tm_min = atoi(tmp_time+3); - t->tm_sec = atoi(tmp_time+6); - jobtime = mktime(t); - - return jobtime; -} - - -/**************************************************************************** - parse a lpq line - <magnus@hum.auc.dk> - Most of the code is directly reused from parse_lpq_bsd() - -here are two examples of lpq output under lprng (LPRng-2.3.0) - -Printer: humprn@hum-fak - Queue: 1 printable job - Server: pid 4840 active, Unspooler: pid 4841 active - Status: job 'cfA659hum-fak', closing device at Fri Jun 21 10:10:21 1996 - Rank Owner Class Job Files Size Time -active magnus@hum-fak A 659 /var/spool/smb/Notesblok-ikke-na4024 10:03:31 - -Printer: humprn@hum-fak (printing disabled) - Queue: 1 printable job - Warning: no server present - Status: finished operations at Fri Jun 21 10:10:32 1996 - Rank Owner Class Job Files Size Time -1 magnus@hum-fak A 387 /var/spool/smb/netbudget.xls 21230 10:50:53 - -****************************************************************************/ -static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first) -{ -#define LPRNG_RANKTOK 0 -#define LPRNG_USERTOK 1 -#define LPRNG_PRIOTOK 2 -#define LPRNG_JOBTOK 3 -#define LPRNG_FILETOK 4 -#define LPRNG_TOTALTOK 5 -#define LPRNG_TIMETOK 6 -#define LPRNG_NTOK 7 - -/**************************************************************************** -From lpd_status.c in LPRng source. -0 1 2 3 4 5 6 7 -12345678901234567890123456789012345678901234567890123456789012345678901234 -" Rank Owner Class Job Files Size Time" - plp_snprintf( msg, sizeof(msg), "%-6s %-19s %c %03d %-32s", - number, line, priority, cfp->number, error ); - plp_snprintf( msg + len, sizeof(msg)-len, "%4d", - cfp->jobsize ); - plp_snprintf( msg+len, sizeof(msg)-len, " %s", - Time_str( 1, cfp->statb.st_ctime ) ); -****************************************************************************/ - /* The following define's are to be able to adjust the values if the -LPRng source changes. This is from version 2.3.0. Magnus */ -#define SPACE_W 1 -#define RANK_W 6 -#define OWNER_W 19 -#define CLASS_W 1 -#define JOB_W 3 -#define FILE_W 32 -/* The JOBSIZE_W is too small for big jobs, so time is pushed to the right */ -#define JOBSIZE_W 4 - -#define RANK_POS 0 -#define OWNER_POS RANK_POS+RANK_W+SPACE_W -#define CLASS_POS OWNER_POS+OWNER_W+SPACE_W -#define JOB_POS CLASS_POS+CLASS_W+SPACE_W -#define FILE_POS JOB_POS+JOB_W+SPACE_W -#define JOBSIZE_POS FILE_POS+FILE_W - - - string tok[LPRNG_NTOK]; - int count=0; - -/* -Need to insert one space in front of the size, to be able to use -next_token() unchanged. I would have liked to be able to insert a -space instead, to prevent losing that one char, but perl has spoiled -me :-\ So I did it the easiest way. - -HINT: Use as short a path as possible for the samba spool directory. -A long spool-path will just waste significant chars of the file name. -*/ - - line[JOBSIZE_POS-1]=' '; - - /* handle the case of "(stdin)" as a filename */ - string_sub(line,"stdin","STDIN"); - string_sub(line,"(","\""); - string_sub(line,")","\""); - - for (count=0; count<LPRNG_NTOK && next_token(&line,tok[count],NULL); count++) ; - - /* we must get LPRNG_NTOK tokens */ - if (count < LPRNG_NTOK) - return(False); - - /* the Job and Total columns must be integer */ - if (!isdigit(*tok[LPRNG_JOBTOK]) || !isdigit(*tok[LPRNG_TOTALTOK])) return(False); - - /* if the fname contains a space then use STDIN */ - /* I do not understand how this would be possible. Magnus. */ - if (strchr(tok[LPRNG_FILETOK],' ')) - strcpy(tok[LPRNG_FILETOK],"STDIN"); - - /* only take the last part of the filename */ - { - string tmp; - char *p = strrchr(tok[LPRNG_FILETOK],'/'); - if (p) - { - strcpy(tmp,p+1); - strcpy(tok[LPRNG_FILETOK],tmp); - } - } - - - buf->job = atoi(tok[LPRNG_JOBTOK]); - buf->size = atoi(tok[LPRNG_TOTALTOK]); - buf->status = strequal(tok[LPRNG_RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED; - /* buf->time = time(NULL); */ - buf->time = LPRng_time(tok,LPRNG_TIMETOK); -DEBUG(3,("Time reported for job %d is %s", buf->job, ctime(&buf->time))); - StrnCpy(buf->user,tok[LPRNG_USERTOK],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[LPRNG_FILETOK],sizeof(buf->file)-1); -#ifdef LPRNG_PRIOTOK - /* Here I try to map the CLASS char to a number, but the number - is never shown in Print Manager under NT anyway... Magnus. */ - buf->priority = atoi(tok[LPRNG_PRIOTOK]-('A'-1)); -#else - buf->priority = 1; -#endif - return(True); -} - - - -/******************************************************************* -parse lpq on an aix system - -Queue Dev Status Job Files User PP % Blks Cp Rnk -------- ----- --------- --- ------------------ ---------- ---- -- ----- --- --- -lazer lazer READY -lazer lazer RUNNING 537 6297doc.A kvintus@IE 0 10 2445 1 1 - QUEUED 538 C.ps root@IEDVB 124 1 2 - QUEUED 539 E.ps root@IEDVB 28 1 3 - QUEUED 540 L.ps root@IEDVB 172 1 4 - QUEUED 541 P.ps root@IEDVB 22 1 5 -********************************************************************/ -static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) -{ - string tok[11]; - int count=0; - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN"); - string_sub(line,"(","\""); - string_sub(line,")","\""); - - for (count=0; count<10 && next_token(&line,tok[count],NULL); count++) ; - - /* we must get 6 tokens */ - if (count < 10) - { - if ((count == 7) && (strcmp(tok[0],"QUEUED") == 0)) - { - /* the 2nd and 5th columns must be integer */ - if (!isdigit(*tok[1]) || !isdigit(*tok[4])) return(False); - buf->size = atoi(tok[4]) * 1024; - /* if the fname contains a space then use STDIN */ - if (strchr(tok[2],' ')) - strcpy(tok[2],"STDIN"); - - /* only take the last part of the filename */ - { - string tmp; - char *p = strrchr(tok[2],'/'); - if (p) - { - strcpy(tmp,p+1); - strcpy(tok[2],tmp); - } - } - - - buf->job = atoi(tok[1]); - buf->status = LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->user,tok[3],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[2],sizeof(buf->file)-1); - } - else - { - DEBUG(6,("parse_lpq_aix count=%d\n", count)); - return(False); - } - } - else - { - /* the 4th and 9th columns must be integer */ - if (!isdigit(*tok[3]) || !isdigit(*tok[8])) return(False); - buf->size = atoi(tok[8]) * 1024; - /* if the fname contains a space then use STDIN */ - if (strchr(tok[4],' ')) - strcpy(tok[4],"STDIN"); - - /* only take the last part of the filename */ - { - string tmp; - char *p = strrchr(tok[4],'/'); - if (p) - { - strcpy(tmp,p+1); - strcpy(tok[4],tmp); - } - } - - - buf->job = atoi(tok[3]); - buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->user,tok[5],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[4],sizeof(buf->file)-1); - } - - - return(True); -} - - -/**************************************************************************** -parse a lpq line -here is an example of lpq output under hpux; note there's no space after -o ! -$> lpstat -oljplus -ljplus-2153 user priority 0 Jan 19 08:14 on ljplus - util.c 125697 bytes - server.c 110712 bytes -ljplus-2154 user priority 0 Jan 19 08:14 from client - (standard input) 7551 bytes -****************************************************************************/ -static BOOL parse_lpq_hpux(char * line, print_queue_struct *buf, BOOL first) -{ - /* must read two lines to process, therefore keep some values static */ - static BOOL header_line_ok=False, base_prio_reset=False; - static string jobuser; - static int jobid; - static int jobprio; - static time_t jobtime; - static int jobstat=LPQ_QUEUED; - /* to store minimum priority to print, lpstat command should be invoked - with -p option first, to work */ - static int base_prio; - - int count; - char TAB = '\011'; - string tok[12]; - - /* If a line begins with a horizontal TAB, it is a subline type */ - - if (line[0] == TAB) { /* subline */ - /* check if it contains the base priority */ - if (!strncmp(line,"\tfence priority : ",18)) { - base_prio=atoi(&line[18]); - DEBUG(4, ("fence priority set at %d\n", base_prio)); - } - if (!header_line_ok) return (False); /* incorrect header line */ - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"standard input","STDIN"); - string_sub(line,"(","\""); - string_sub(line,")","\""); - - for (count=0; count<2 && next_token(&line,tok[count],NULL); count++) ; - /* we must get 2 tokens */ - if (count < 2) return(False); - - /* the 2nd column must be integer */ - if (!isdigit(*tok[1])) return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr(tok[0],' ')) - strcpy(tok[0],"STDIN"); - - buf->size = atoi(tok[1]); - StrnCpy(buf->file,tok[0],sizeof(buf->file)-1); - - /* fill things from header line */ - buf->time = jobtime; - buf->job = jobid; - buf->status = jobstat; - buf->priority = jobprio; - StrnCpy(buf->user,jobuser,sizeof(buf->user)-1); - - return(True); - } - else { /* header line */ - header_line_ok=False; /* reset it */ - if (first) { - if (!base_prio_reset) { - base_prio=0; /* reset it */ - base_prio_reset=True; - } - } - else if (base_prio) base_prio_reset=False; - - /* handle the dash in the job id */ - string_sub(line,"-"," "); - - for (count=0; count<12 && next_token(&line,tok[count],NULL); count++) ; - - /* we must get 8 tokens */ - if (count < 8) return(False); - - /* first token must be printer name (cannot check ?) */ - /* the 2nd, 5th & 7th column must be integer */ - if (!isdigit(*tok[1]) || !isdigit(*tok[4]) || !isdigit(*tok[6])) return(False); - jobid = atoi(tok[1]); - StrnCpy(jobuser,tok[2],sizeof(buf->user)-1); - jobprio = atoi(tok[4]); - - /* process time */ - jobtime=EntryTime(tok, 5, count, 8); - if (jobprio < base_prio) { - jobstat = LPQ_PAUSED; - DEBUG (4, ("job %d is paused: prio %d < %d; jobstat=%d\n", jobid, jobprio, base_prio, jobstat)); - } - else { - jobstat = LPQ_QUEUED; - if ((count >8) && (((strequal(tok[8],"on")) || - ((strequal(tok[8],"from")) && - ((count > 10)&&(strequal(tok[10],"on"))))))) - jobstat = LPQ_PRINTING; - } - - header_line_ok=True; /* information is correct */ - return(False); /* need subline info to include into queuelist */ - } -} - - -/**************************************************************************** -parse a lpq line - -here is an example of "lpstat -o dcslw" output under sysv - -dcslw-896 tridge 4712 Dec 20 10:30:30 on dcslw -dcslw-897 tridge 4712 Dec 20 10:30:30 being held - -****************************************************************************/ -static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first) -{ - string tok[9]; - int count=0; - char *p; - - /* handle the dash in the job id */ - string_sub(line,"-"," "); - - for (count=0; count<9 && next_token(&line,tok[count],NULL); count++) ; - - /* we must get 7 tokens */ - if (count < 7) - return(False); - - /* the 2nd and 4th, 6th columns must be integer */ - if (!isdigit(*tok[1]) || !isdigit(*tok[3])) return(False); - if (!isdigit(*tok[5])) return(False); - - /* if the user contains a ! then trim the first part of it */ - if ((p=strchr(tok[2],'!'))) - { - string tmp; - strcpy(tmp,p+1); - strcpy(tok[2],tmp); - } - - - buf->job = atoi(tok[1]); - buf->size = atoi(tok[3]); - if (count > 7 && strequal(tok[7],"on")) - buf->status = LPQ_PRINTING; - else if (count > 8 && strequal(tok[7],"being") && strequal(tok[8],"held")) - buf->status = LPQ_PAUSED; - else - buf->status = LPQ_QUEUED; - buf->priority = 0; - buf->time = EntryTime(tok, 4, count, 7); - StrnCpy(buf->user,tok[2],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[2],sizeof(buf->file)-1); - return(True); -} - -/**************************************************************************** -parse a lpq line - -here is an example of lpq output under qnx -Spooler: /qnx/spooler, on node 1 -Printer: txt (ready) -0000: root [job #1 ] active 1146 bytes /etc/profile -0001: root [job #2 ] ready 2378 bytes /etc/install -0002: root [job #3 ] ready 1146 bytes -- standard input -- -****************************************************************************/ -static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first) -{ - string tok[7]; - int count=0; - - DEBUG(0,("antes [%s]\n", line)); - - /* handle the case of "-- standard input --" as a filename */ - string_sub(line,"standard input","STDIN"); - DEBUG(0,("despues [%s]\n", line)); - string_sub(line,"-- ","\""); - string_sub(line," --","\""); - DEBUG(0,("despues 1 [%s]\n", line)); - - string_sub(line,"[job #",""); - string_sub(line,"]",""); - DEBUG(0,("despues 2 [%s]\n", line)); - - - - for (count=0; count<7 && next_token(&line,tok[count],NULL); count++) ; - - /* we must get 7 tokens */ - if (count < 7) - return(False); - - /* the 3rd and 5th columns must be integer */ - if (!isdigit(*tok[2]) || !isdigit(*tok[4])) return(False); - - /* only take the last part of the filename */ - { - string tmp; - char *p = strrchr(tok[6],'/'); - if (p) - { - strcpy(tmp,p+1); - strcpy(tok[6],tmp); - } - } - - - buf->job = atoi(tok[2]); - buf->size = atoi(tok[4]); - buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->user,tok[1],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[6],sizeof(buf->file)-1); - return(True); -} - - -/**************************************************************************** - parse a lpq line for the plp printing system - Bertrand Wallrich <Bertrand.Wallrich@loria.fr> - -redone by tridge. Here is a sample queue: - -Local Printer 'lp2' (fjall): - Printing (started at Jun 15 13:33:58, attempt 1). - Rank Owner Pr Opt Job Host Files Size Date - active tridge X - 6 fjall /etc/hosts 739 Jun 15 13:33 - 3rd tridge X - 7 fjall /etc/hosts 739 Jun 15 13:33 - -****************************************************************************/ -static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first) -{ - string tok[11]; - int count=0; - - /* handle the case of "(standard input)" as a filename */ - string_sub(line,"stdin","STDIN"); - string_sub(line,"(","\""); - string_sub(line,")","\""); - - for (count=0; count<11 && next_token(&line,tok[count],NULL); count++) ; - - /* we must get 11 tokens */ - if (count < 11) - return(False); - - /* the first must be "active" or begin with an integer */ - if (strcmp(tok[0],"active") && !isdigit(tok[0][0])) - return(False); - - /* the 5th and 8th must be integer */ - if (!isdigit(*tok[4]) || !isdigit(*tok[7])) - return(False); - - /* if the fname contains a space then use STDIN */ - if (strchr(tok[6],' ')) - strcpy(tok[6],"STDIN"); - - /* only take the last part of the filename */ - { - string tmp; - char *p = strrchr(tok[6],'/'); - if (p) - { - strcpy(tmp,p+1); - strcpy(tok[6],tmp); - } - } - - - buf->job = atoi(tok[4]); - - buf->size = atoi(tok[7]); - if (strchr(tok[7],'K')) - buf->size *= 1024; - if (strchr(tok[7],'M')) - buf->size *= 1024*1024; - - buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED; - buf->priority = 0; - buf->time = time(NULL); - StrnCpy(buf->user,tok[1],sizeof(buf->user)-1); - StrnCpy(buf->file,tok[6],sizeof(buf->file)-1); - return(True); -} - - - -char *stat0_strings[] = { "enabled", "online", "idle", "no entries", "free", "ready", NULL }; -char *stat1_strings[] = { "offline", "disabled", "down", "off", "waiting", "no daemon", NULL }; -char *stat2_strings[] = { "jam", "paper", "error", "responding", "not accepting", "not running", "turned off", NULL }; - -/**************************************************************************** -parse a lpq line. Choose printing style -****************************************************************************/ -static BOOL parse_lpq_entry(int snum,char *line, - print_queue_struct *buf, - print_status_struct *status,BOOL first) -{ - BOOL ret; - - switch (lp_printing()) - { - case PRINT_SYSV: - ret = parse_lpq_sysv(line,buf,first); - break; - case PRINT_AIX: - ret = parse_lpq_aix(line,buf,first); - break; - case PRINT_HPUX: - ret = parse_lpq_hpux(line,buf,first); - break; - case PRINT_QNX: - ret = parse_lpq_qnx(line,buf,first); - break; - case PRINT_LPRNG: - ret = parse_lpq_lprng(line,buf,first); - break; - case PRINT_PLP: - ret = parse_lpq_plp(line,buf,first); - break; - default: - ret = parse_lpq_bsd(line,buf,first); - break; - } - -#ifdef LPQ_GUEST_TO_USER - if (ret) { - extern pstring sesssetup_user; - /* change guest entries to the current logged in user to make - them appear deletable to windows */ - if (sesssetup_user[0] && strequal(buf->user,lp_guestaccount(snum))) - strcpy(buf->user,sesssetup_user); - } -#endif - - /* We don't want the newline in the status message. */ - { - char *p = strchr(line,'\n'); - if (p) *p = 0; - } - - if (status && !ret) - { - /* a few simple checks to see if the line might be a - printer status line: - handle them so that most severe condition is shown */ - int i; - strlower(line); - - switch (status->status) { - case LPSTAT_OK: - for (i=0; stat0_strings[i]; i++) - if (strstr(line,stat0_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_OK; - } - case LPSTAT_STOPPED: - for (i=0; stat1_strings[i]; i++) - if (strstr(line,stat1_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_STOPPED; - } - case LPSTAT_ERROR: - for (i=0; stat2_strings[i]; i++) - if (strstr(line,stat2_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_ERROR; - } - break; - } - } - - return(ret); -} - -/**************************************************************************** -get a printer queue -****************************************************************************/ -int get_printqueue(int snum,int cnum,print_queue_struct **queue, - print_status_struct *status) -{ - char *lpq_command = lp_lpqcommand(snum); - char *printername = PRINTERNAME(snum); - int ret=0,count=0; - pstring syscmd; - fstring outfile; - pstring line; - FILE *f; - struct stat sbuf; - BOOL dorun=True; - int cachetime = lp_lpqcachetime(); - - *line = 0; - check_lpq_cache(snum); - - if (!printername || !*printername) - { - DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n", - lp_servicename(snum),snum)); - printername = lp_servicename(snum); - } - - if (!lpq_command || !(*lpq_command)) - { - DEBUG(5,("No lpq command\n")); - return(0); - } - - strcpy(syscmd,lpq_command); - string_sub(syscmd,"%p",printername); - - standard_sub(cnum,syscmd); - - sprintf(outfile,"%s/lpq.%08x",tmpdir(),str_checksum(syscmd)); - - if (!lpq_cache_reset[snum] && cachetime && !stat(outfile,&sbuf)) - { - if (time(NULL) - sbuf.st_mtime < cachetime) { - DEBUG(3,("Using cached lpq output\n")); - dorun = False; - } - } - - if (dorun) { - ret = smbrun(syscmd,outfile,True); - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - } - - lpq_cache_reset[snum] = False; - - f = fopen(outfile,"r"); - if (!f) { - return(0); - } - - if (status) { - strcpy(status->message,""); - status->status = LPSTAT_OK; - } - - while (fgets(line,sizeof(pstring),f)) - { - DEBUG(6,("QUEUE2: %s\n",line)); - - *queue = Realloc(*queue,sizeof(print_queue_struct)*(count+1)); - if (! *queue) - { - count = 0; - break; - } - - bzero((char *)&(*queue)[count],sizeof(**queue)); - - /* parse it */ - if (!parse_lpq_entry(snum,line,&(*queue)[count],status,count==0)) - continue; - - count++; - } - - fclose(f); - - if (!cachetime) { - unlink(outfile); - } else { - /* we only expect this to succeed on trapdoor systems, on normal systems - the file is owned by root */ - chmod(outfile,0666); - } - return(count); -} - - -/**************************************************************************** -delete a printer queue entry -****************************************************************************/ -void del_printqueue(int cnum,int snum,int jobid) -{ - char *lprm_command = lp_lprmcommand(snum); - char *printername = PRINTERNAME(snum); - pstring syscmd; - char jobstr[20]; - int ret; - - if (!printername || !*printername) - { - DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n", - lp_servicename(snum),snum)); - printername = lp_servicename(snum); - } - - if (!lprm_command || !(*lprm_command)) - { - DEBUG(5,("No lprm command\n")); - return; - } - - sprintf(jobstr,"%d",jobid); - - strcpy(syscmd,lprm_command); - string_sub(syscmd,"%p",printername); - string_sub(syscmd,"%j",jobstr); - standard_sub(cnum,syscmd); - - ret = smbrun(syscmd,NULL,False); - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - lpq_reset(snum); /* queue has changed */ -} - -/**************************************************************************** -change status of a printer queue entry -****************************************************************************/ -void status_printjob(int cnum,int snum,int jobid,int status) -{ - char *lpstatus_command = - (status==LPQ_PAUSED?lp_lppausecommand(snum):lp_lpresumecommand(snum)); - char *printername = PRINTERNAME(snum); - pstring syscmd; - char jobstr[20]; - int ret; - - if (!printername || !*printername) - { - DEBUG(6,("replacing printer name with service (snum=(%s,%d))\n", - lp_servicename(snum),snum)); - printername = lp_servicename(snum); - } - - if (!lpstatus_command || !(*lpstatus_command)) - { - DEBUG(5,("No lpstatus command to %s job\n", - (status==LPQ_PAUSED?"pause":"resume"))); - return; - } - - sprintf(jobstr,"%d",jobid); - - strcpy(syscmd,lpstatus_command); - string_sub(syscmd,"%p",printername); - string_sub(syscmd,"%j",jobstr); - standard_sub(cnum,syscmd); - - ret = smbrun(syscmd,NULL,False); - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - lpq_reset(snum); /* queue has changed */ -} - - diff --git a/source/script/addtosmbpass b/source/script/addtosmbpass deleted file mode 100644 index 42af518397c..00000000000 --- a/source/script/addtosmbpass +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/awk -f -# edit the line above to point to your real location of awk interpreter - -# awk program for adding new entries in smbpasswd files -# arguments are account names to add; feed it an existent Samba password -# file on stdin, results will be written on stdout -# -# Michal Jaegermann, michal@ellpspace.math.ualberta.ca, 1995-11-09 - -BEGIN { - me = "addtosmbpass"; - count = ARGC; - FS = ":"; - - if (count == 1) { - print "Usage:", me, - "name1 [name2 ....] < smbpasswd.in > smbpasswd.out"; - ARGV[1] = "/dev/null"; - ARGC = 2; - exit; - } - - for(i = 1; i < count; i++) { - names[ARGV[i]] = " "; - delete ARGV[i]; - } -# sane awk should work simply with 'ARGC = 1', but not every awk -# implementation is sane - big sigh!! - ARGV[1] = "-"; - ARGC = 2; -# -# If you have ypmatch but is not RPC registered (some Linux systems -# for example) comment out the next line. -# "which ypmatch" | getline ypmatch; - if (1 != match(ypmatch, /^\//)) { - ypmatch = ""; - } - pwdf = "/etc/passwd"; -} -#check for names already present in input -{ - print $0; - for(name in names) { - if($1 ~ name) { - delete names[name]; - } - } -} -END { - fmt = "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:"; - fmt = fmt "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n"; - for(name in names) { - while ((getline < pwdf) > 0) { - if ($1 == name) { - printf(fmt, $1, $3, $5, $6, $7); - close(pwdf); - notfound = ""; - break; - } - notfound = "n"; - } - $0 = ""; - if (notfound && ypmatch) { -# try to find in NIS databases - command = ypmatch " " name " passwd"; - command | getline; - if (NF > 0) { - printf(fmt, $1, $3, $5, $6, $7); - } - close(command); - } - } -} - diff --git a/source/script/installbin.sh b/source/script/installbin.sh deleted file mode 100755 index b976a3e5ea8..00000000000 --- a/source/script/installbin.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -INSTALLPERMS=$1 -BASEDIR=$2 -BINDIR=$3 -LIBDIR=$4 -VARDIR=$5 -shift -shift -shift -shift -shift - -for d in $BASEDIR $BINDIR $LIBDIR $VARDIR; do -if [ ! -d $d ]; then -mkdir $d -if [ ! -d $d ]; then - echo Failed to make directory $d - exit 1 -fi -fi -done - - -for p in $*; do - echo Installing $p as $BINDIR/$p - if [ -f $BINDIR/$p ]; then - mv $BINDIR/$p $BINDIR/$p.old - fi - cp $p $BINDIR/$p - chmod $INSTALLPERMS $BINDIR/$p -done - - -cat << EOF -====================================================================== -The binaries are installed. You may restore the old binaries (if there -were any) using the command "make revert". You may uninstall the binaries -using the command "make uninstallbin" or "make uninstall" to uninstall -binaries, man pages and shell scripts. -====================================================================== -EOF - -exit 0 - diff --git a/source/script/installman.sh b/source/script/installman.sh deleted file mode 100755 index 3c8fc718654..00000000000 --- a/source/script/installman.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -#5 July 96 Dan.Shearer@unisa.edu.au removed hardcoded values - -MANDIR=$1 -SRCDIR=$2 - -echo Installing man pages in $MANDIR - -for d in $MANDIR $MANDIR/man1 $MANDIR/man5 $MANDIR/man7 $MANDIR/man8; do -if [ ! -d $d ]; then -mkdir $d -if [ ! -d $d ]; then - echo Failed to make directory $d, does $USER have privileges? - exit 1 -fi -fi -done - -for sect in 1 5 7 8 ; do - for m in $MANDIR/man$sect ; do - for s in $SRCDIR../docs/*$sect; do - FNAME=$m/`basename $s` - cp $s $m || echo Cannot create $FNAME... does $USER have privileges? - chmod 0644 $FNAME - done - done -done - -cat << EOF -====================================================================== -The man pages have been installed. You may uninstall them using the command -the command "make uninstallman" or make "uninstall" to uninstall binaries, -man pages and shell scripts. -====================================================================== -EOF - -exit 0 - diff --git a/source/script/installscripts.sh b/source/script/installscripts.sh deleted file mode 100755 index 1a230c8cfa2..00000000000 --- a/source/script/installscripts.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -# this script courtesy of James_K._Foote.PARC@xerox.com -# 5 July 96 Dan.Shearer@UniSA.Edu.Au Don't hardcode script names, get from Make - -INSTALLPERMS=$1 -BINDIR=$2 - -shift -shift - -echo Installing scripts in $BINDIR - -for d in $BINDIR; do - if [ ! -d $d ]; then - mkdir $d - if [ ! -d $d ]; then - echo Failed to make directory $d - echo Have you run installbin first? - exit 1 - fi - fi -done - -for p in $*; do - echo Installing $BINDIR/$p - cp $p $BINDIR/$p - if [ ! -f $BINDIR/$p ]; then - echo Cannot copy $p... does $USER have privileges? - fi - echo Setting permissions on $BINDIR/$p - chmod $INSTALLPERMS $BINDIR/$p -done - -cat << EOF -====================================================================== -The scripts have been installed. You may uninstall them using -the command "make uninstallscripts" or "make install" to install binaries, -man pages and shell scripts. You may recover the previous version (if any -by "make revert". -====================================================================== -EOF - -exit 0 diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk deleted file mode 100644 index 08b13d46108..00000000000 --- a/source/script/mkproto.awk +++ /dev/null @@ -1,82 +0,0 @@ -BEGIN { - inheader=0; - current_file=""; - print "/* This file is automatically generated with \"make proto\". DO NOT EDIT */" - print "" -} - -{ - if (FILENAME!=current_file) { - print "" - print "/*The following definitions come from ",FILENAME," */" - print "" - current_file=FILENAME - } - if (inheader) { - if (match($0,"[)][ \t]*$")) { - inheader = 0; - printf "%s;\n",$0; - } else { - printf "%s\n",$0; - } - next; - } -} - -# we handle the loadparm.c fns separately - -/^FN_LOCAL_BOOL/ { - split($0,a,"[,()]") - printf "BOOL %s(int );\n", a[2] -} - -/^FN_LOCAL_STRING/ { - split($0,a,"[,()]") - printf "char *%s(int );\n", a[2] -} - -/^FN_LOCAL_INT/ { - split($0,a,"[,()]") - printf "int %s(int );\n", a[2] -} - -/^FN_LOCAL_CHAR/ { - split($0,a,"[,()]") - printf "char %s(int );\n", a[2] -} - -/^FN_GLOBAL_BOOL/ { - split($0,a,"[,()]") - printf "BOOL %s(void);\n", a[2] -} - -/^FN_GLOBAL_STRING/ { - split($0,a,"[,()]") - printf "char *%s(void);\n", a[2] -} - -/^FN_GLOBAL_INT/ { - split($0,a,"[,()]") - printf "int %s(void);\n", a[2] -} - -/^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ { - next; -} - -!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^shm_offset_t/ { - next; -} - - -/[(].*[)][ \t]*$/ { - printf "%s;\n",$0; - next; -} - -/[(]/ { - inheader=1; - printf "%s\n",$0; - next; -} - diff --git a/source/script/mksmbpasswd.sh b/source/script/mksmbpasswd.sh deleted file mode 100755 index 6e592acd652..00000000000 --- a/source/script/mksmbpasswd.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -awk 'BEGIN {FS=":" - printf("#\n# SMB password file.\n#\n") - } -{ printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", $1, $3, $5, $6, $7) } -' diff --git a/source/script/revert.sh b/source/script/revert.sh deleted file mode 100755 index 68b47bf39d0..00000000000 --- a/source/script/revert.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -BINDIR=$1 -shift - -for p in $*; do - if [ -f $BINDIR/$p.old ]; then - echo Restoring $BINDIR/$p.old as $BINDIR/$p - mv $BINDIR/$p $BINDIR/$p.new - mv $BINDIR/$p.old $BINDIR/$p - rm -f $BINDIR/$p.new - fi -done - -exit 0 - diff --git a/source/script/smbtar b/source/script/smbtar deleted file mode 100644 index a947476dc6b..00000000000 --- a/source/script/smbtar +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/sh -# -# smbtar script - front end to smbclient -# -# Authors: Martin.Kraemer <Martin.Kraemer@mch.sni.de> -# and Ricky Poulten (ricky@logcam.co.uk) -# -# (May need to change shell to ksh for HPUX or OSF for better getopts) - -case $0 in - # when called by absolute path, assume smbclient is in the same directory - /*) - SMBCLIENT="`dirname $0`/smbclient";; - *) # you may need to edit this to show where your smbclient is - SMBCLIENT="smbclient";; -esac - -# These are the default values. You could fill them in if you know what -# you're doing, but beware: better not store a plain text password! -server="" -service="backup" # Default: a service called "backup" -password="" -username=$LOGNAME # Default: same user name as in *nix -verbose="2>/dev/null" # Default: no echo to stdout -log="-d 2" -newer="" -blocksize="" -tarcmd="c" -tarargs="" -cdcmd="\\" -tapefile=${TAPE-tar.out} - -Usage(){ - ex=$1 - shift -echo >&2 "Usage: `basename $0` [<options>] [<include/exclude files>] -Function: backup/restore a Windows PC directories to a local tape file -Options: (Description) (Default) - -r Restore from tape file to PC Save from PC to tapefile - -i Incremental mode Full backup mode - -v Verbose mode: echo command Don't echo anything - -s <server> Specify PC Server $server - -p <password> Specify PC Password $password - -x <share> Specify PC Share $service - -X Exclude mode Include - -N <newer> File for date comparison `set -- $newer; echo $2` - -b <blocksize> Specify tape's blocksize `set -- $blocksize; echo $2` - -d <dir> Specify a directory in share $cdcmd - -l <log> Specify a Samba Log Level `set -- $log; echo $2` - -u <user> Specify User Name $username - -t <tape> Specify Tape device $tapefile -" - echo >&2 "$@" - exit $ex -} - -while getopts rivl:b:d:N:s:p:x:u:Xt: c; do - case $c in - r) # [r]estore to Windows (instead of the default "Save from Windows") - tarcmd="x" - ;; - i) # [i]ncremental - tarargs=${tarargs}g - ;; - l) # specify [l]og file - log="-d $OPTARG" - case "$OPTARG" in - [0-9]*) ;; - *) echo >&2 "$0: Error, log level not numeric: -l $OPTARG" - exit 1 - esac - ;; - d) # specify [d]irectory to change to in server's share - cdcmd="$OPTARG" - ;; - N) # compare with a file, test if [n]ewer - if [ -f $OPTARG ]; then - newer=$OPTARG - tarargs=${tarargs}N - else - echo >&2 $0: Warning, $OPTARG not found - fi - ;; - X) # Add exclude flag - tarargs=${tarargs}X - ;; - s) # specify [s]erver's share to connect to - this MUST be given. - server="$OPTARG" - ;; - b) # specify [b]locksize - blocksize="blocksize $OPTARG" - case "$OPTARG" in - [0-9]*) ;; - *) echo >&2 "$0: Error, block size not numeric: -b $OPTARG" - exit 1 - esac - tarargs=${tarargs}b - ;; - p) # specify [p]assword to use - password="$OPTARG" - ;; - x) # specify windows [s]hare to use - service="$OPTARG" - ;; - t) # specify [t]apefile on local host - tapefile="$OPTARG" - ;; - u) # specify [u]sername for connection - username="$OPTARG" - ;; - v) # be [v]erbose and display what's going on - verbose="" - ;; - '?') # any other switch - Usage 2 "Invalid switch specified - abort." - ;; - esac -done - -shift `expr $OPTIND - 1` - -if [ "$server" = "" ] || [ "$service" = "" ]; then - Usage 1 "No server or no service specified - abort." -fi - -# if the -v switch is set, the echo the current parameters -if [ -z "$verbose" ]; then - echo "server is $server" -# echo "share is $service" - echo "share is $service\\$cdcmd" - echo "tar args is $tarargs" -# echo "password is $password" # passwords should never be sent to screen - echo "tape is $tapefile" - echo "blocksize is $blocksize" -fi - -eval $SMBCLIENT "'\\\\$server\\$service'" "'$password'" -U "'$username'" \ --E -N $log -D "'$cdcmd'" \ --T${tarcmd}${tarargs} $blocksize $newer $tapefile $* $verbose - diff --git a/source/script/uninstallbin.sh b/source/script/uninstallbin.sh deleted file mode 100755 index fab36804a29..00000000000 --- a/source/script/uninstallbin.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -#4 July 96 Dan.Shearer@UniSA.edu.au - -INSTALLPERMS=$1 -BASEDIR=$2 -BINDIR=$3 -LIBDIR=$4 -VARDIR=$5 -shift -shift -shift -shift -shift - -if [ ! -d $BINDIR ]; then - echo Directory $BINDIR does not exist! - echo Do a "make installbin" or "make install" first. - exit 1 -fi - -for p in $*; do - if [ ! -f $BINDIR/$p ]; then - echo $BINDIR/$p does not exist! - else - echo Removing $BINDIR/$p - rm -f $BINDIR/$p - if [ -f $BINDIR/$p ]; then - echo Cannot remove $BINDIR/$p... does $USER have privileges? - fi - fi -done - - -cat << EOF -====================================================================== -The binaries have been uninstalled. You may restore the binaries using -the command "make installbin" or "make install" to install binaries, -man pages and shell scripts. You can restore a previous version of the -binaries (if there were any) using "make revert". -====================================================================== -EOF - -exit 0 diff --git a/source/script/uninstallman.sh b/source/script/uninstallman.sh deleted file mode 100755 index b4d4bfc1f92..00000000000 --- a/source/script/uninstallman.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -#4 July 96 Dan.Shearer@UniSA.edu.au - -MANDIR=$1 -SRCDIR=$2 - -echo Uninstalling man pages from $MANDIR - -for sect in 1 5 7 8 ; do - for m in $MANDIR/man$sect ; do - for s in $SRCDIR../docs/*$sect; do - FNAME=$m/`basename $s` - if test -f $FNAME; then - echo Deleting $FNAME - rm -f $FNAME - test -f $FNAME && echo Cannot remove $FNAME... does $USER have privileges? - else - echo $FNAME does not exist! Check defines in the Makefile - fi - done - done -done - -cat << EOF -====================================================================== -The man pages have been uninstalled. You may install them again using -the command "make installman" or make "install" to install binaries, -man pages and shell scripts. -====================================================================== -EOF -exit 0 diff --git a/source/script/uninstallscripts.sh b/source/script/uninstallscripts.sh deleted file mode 100755 index ae907546f2e..00000000000 --- a/source/script/uninstallscripts.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# 5 July 96 Dan.Shearer@UniSA.Edu.Au - almost identical to uninstallbin.sh - -INSTALLPERMS=$1 -BINDIR=$2 - -shift -shift - -if [ ! -d $BINDIR ]; then - echo Directory $BINDIR does not exist! - echo Do a "make installscripts" or "make install" first. - exit 1 -fi - -for p in $*; do - if [ ! -f $BINDIR/$p ]; then - echo $BINDIR/$p does not exist! - else - echo Removing $BINDIR/$p - rm -f $BINDIR/$p - if [ -f $BINDIR/$p ]; then - echo Cannot remove $BINDIR/$p... does $USER have privileges? - fi - fi -done - -cat << EOF -====================================================================== -The scripts have been uninstalled. You may reinstall them using -the command "make installscripts" or "make install" to install binaries, -man pages and shell scripts. You may recover a previous version (if any -with "make revert". -====================================================================== -EOF - -exit 0 diff --git a/source/script/updatesmbpasswd.sh b/source/script/updatesmbpasswd.sh deleted file mode 100755 index 1d7e0d7332f..00000000000 --- a/source/script/updatesmbpasswd.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -nawk 'BEGIN {FS=":"} -{ - if( $0 ~ "^#" ) { - print $0 - } else if( (length($4) == 32) && (($4 ~ "^[0-9A-F]*$") || ($4 ~ "^[X]*$") || ( $4 ~ "^[*]*$"))) { - print $0 - } else { - printf( "%s:%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:", $1, $2, $3); - for(i = 4; i <= NF; i++) - printf("%s:", $i) - printf("\n") - } -}' diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c deleted file mode 100644 index 883ad5214a8..00000000000 --- a/source/smbd/chgpasswd.c +++ /dev/null @@ -1,379 +0,0 @@ -/* fork a child process to exec passwd and write to its -* tty to change a users password. This is running as the -* user who is attempting to change the password. -*/ - -/* - * This code was copied/borrowed and stolen from various sources. - * The primary source was the poppasswd.c from the authors of POPMail. This software - * was included as a client to change passwords using the 'passwd' program - * on the remote machine. - * - * This routine is called by set_user_password() in password.c only if ALLOW_PASSWORD_CHANGE - * is defined in the compiler directives located in the Makefile. - * - * This code has been hacked by Bob Nance (nance@niehs.nih.gov) and Evan Patterson - * (patters2@niehs.nih.gov) at the National Institute of Environmental Health Sciences - * and rights to modify, distribute or incorporate this change to the CAP suite or - * using it for any other reason are granted, so long as this disclaimer is left intact. - */ - -/* - This code was hacked considerably for inclusion in Samba, primarily - by Andrew.Tridgell@anu.edu.au. The biggest change was the addition - of the "password chat" option, which allows the easy runtime - specification of the expected sequence of events to change a - password. - */ - -#include "includes.h" - -extern int DEBUGLEVEL; - -#ifdef ALLOW_CHANGE_PASSWORD - -#define MINPASSWDLENGTH 5 -#define BUFSIZE 512 - -static int findpty(char **slave) -{ - int master; -#ifdef SVR4 - extern char *ptsname(); -#else - static char line[12]; - void *dirp; - char *dpname; -#endif - -#ifdef SVR4 - if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { - grantpt(master); - unlockpt(master); - *slave = ptsname(master); - return (master); - } -#else - strcpy( line, "/dev/ptyXX" ); - - dirp = OpenDir("/dev"); - if (!dirp) return(-1); - while ((dpname = ReadDirName(dirp)) != NULL) { - if (strncmp(dpname, "pty", 3) == 0 && strlen(dpname) == 5) { - DEBUG(3,("pty: try to open %s, line was %s\n", dpname, line ) ); - line[8] = dpname[3]; - line[9] = dpname[4]; - if ((master = open(line, O_RDWR)) >= 0) { - DEBUG(3,("pty: opened %s\n", line ) ); - line[5] = 't'; - *slave = line; - CloseDir(dirp); - return (master); - } - } - } - CloseDir(dirp); -#endif - return (-1); -} - -static int dochild(int master,char *slavedev, char *name, char *passwordprogram) -{ - int slave; - struct termios stermios; - struct passwd *pass = Get_Pwnam(name,True); - int gid = pass->pw_gid; - int uid = pass->pw_uid; - -#ifdef USE_SETRES - setresuid(0,0,0); -#else - setuid(0); -#endif - - /* Start new session - gets rid of controlling terminal. */ - if (setsid() < 0) { - DEBUG(3,("Weirdness, couldn't let go of controlling terminal\n")); - return(False); - } - - /* Open slave pty and acquire as new controlling terminal. */ - if ((slave = open(slavedev, O_RDWR)) < 0) { - DEBUG(3,("More weirdness, could not open %s\n", - slavedev)); - return(False); - } -#ifdef SVR4 - ioctl(slave, I_PUSH, "ptem"); - ioctl(slave, I_PUSH, "ldterm"); -#else - if (ioctl(slave,TIOCSCTTY,0) <0) { - DEBUG(3,("Error in ioctl call for slave pty\n")); - /* return(False); */ - } -#endif - - /* Close master. */ - close(master); - - /* Make slave stdin/out/err of child. */ - - if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) { - DEBUG(3,("Could not re-direct stdin\n")); - return(False); - } - if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { - DEBUG(3,("Could not re-direct stdout\n")); - return(False); - } - if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) { - DEBUG(3,("Could not re-direct stderr\n")); - return(False); - } - if (slave > 2) close(slave); - - /* Set proper terminal attributes - no echo, canonical input processing, - no map NL to CR/NL on output. */ - - if (tcgetattr(0, &stermios) < 0) { - DEBUG(3,("could not read default terminal attributes on pty\n")); - return(False); - } - stermios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); - stermios.c_lflag |= ICANON; - stermios.c_oflag &= ~(ONLCR); - if (tcsetattr(0, TCSANOW, &stermios) < 0) { - DEBUG(3,("could not set attributes of pty\n")); - return(False); - } - - /* make us completely into the right uid */ -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); -#else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); -#endif - - /* execl() password-change application */ - if (execl("/bin/sh","sh","-c",passwordprogram,NULL) < 0) { - DEBUG(3,("Bad status returned from %s\n",passwordprogram)); - return(False); - } - return(True); -} - -static int expect(int master,char *expected,char *buf) -{ - int n, m; - - n = 0; - buf[0] = 0; - while (1) { - if (n >= BUFSIZE-1) { - return False; - } - - /* allow 4 seconds for some output to appear */ - m = read_with_timeout(master, buf+n, 1, BUFSIZE-1-n, 4000); - if (m < 0) - return False; - - n += m; - buf[n] = 0; - - { - pstring s1,s2; - strcpy(s1,buf); - strcpy(s2,expected); - if (do_match(s1, s2, False)) - return(True); - } - } -} - -static void pwd_sub(char *buf) -{ - string_sub(buf,"\\n","\n"); - string_sub(buf,"\\r","\r"); - string_sub(buf,"\\s"," "); - string_sub(buf,"\\t","\t"); -} - -static void writestring(int fd,char *s) -{ - int l; - - l = strlen (s); - write (fd, s, l); -} - - -static int talktochild(int master, char *chatsequence) -{ - char buf[BUFSIZE]; - int count=0; - char *ptr=chatsequence; - fstring chatbuf; - - *buf = 0; - sleep(1); - - while (next_token(&ptr,chatbuf,NULL)) { - BOOL ok=True; - count++; - pwd_sub(chatbuf); - if (!strequal(chatbuf,".")) - ok = expect(master,chatbuf,buf); - -#if DEBUG_PASSWORD - DEBUG(100,("chatbuf=[%s] responsebuf=[%s]\n",chatbuf,buf)); -#endif - - if (!ok) { - DEBUG(3,("response %d incorrect\n",count)); - return(False); - } - - if (!next_token(&ptr,chatbuf,NULL)) break; - pwd_sub(chatbuf); - if (!strequal(chatbuf,".")) - writestring(master,chatbuf); - -#if DEBUG_PASSWORD - DEBUG(100,("sendbuf=[%s]\n",chatbuf)); -#endif - } - - if (count<1) return(False); - - return (True); -} - - -BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence) -{ - char *slavedev; - int master; - pid_t pid, wpid; - int wstat; - BOOL chstat; - - /* allocate a pseudo-terminal device */ - if ((master = findpty (&slavedev)) < 0) { - DEBUG(3,("Cannot Allocate pty for password change: %s",name)); - return(False); - } - - if ((pid = fork()) < 0) { - DEBUG(3,("Cannot fork() child for password change: %s",name)); - return(False); - } - - /* we now have a pty */ - if (pid > 0){ /* This is the parent process */ - if ((chstat = talktochild(master, chatsequence)) == False) { - DEBUG(3,("Child failed to change password: %s\n",name)); - kill(pid, SIGKILL); /* be sure to end this process */ - return(False); - } - if ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { - DEBUG(3,("The process is no longer waiting!\n\n")); - return(False); - } - if (pid != wpid) { - DEBUG(3,("We were waiting for the wrong process ID\n")); - return(False); - } - if (WIFEXITED(wstat) == 0) { - DEBUG(3,("The process exited while we were waiting\n")); - return(False); - } - if (WEXITSTATUS(wstat) != 0) { - DEBUG(3,("The status of the process exiting was %d\n", wstat)); - return(False); - } - - } else { - /* CHILD */ - - /* make sure it doesn't freeze */ - alarm(20); - - DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,getuid(),getgid())); - chstat = dochild(master, slavedev, name, passwordprogram); - } - DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name)); - return (chstat); -} - - -BOOL chgpasswd(char *name,char *oldpass,char *newpass) -{ - pstring passwordprogram; - pstring chatsequence; - - strlower(name); - DEBUG(3,("Password change for user: %s\n",name)); - -#if DEBUG_PASSWORD - DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); -#endif - - /* Take the passed information and test it for minimum criteria */ - /* Minimum password length */ - if (strlen(newpass) < MINPASSWDLENGTH) /* too short, must be at least MINPASSWDLENGTH */ - { - DEBUG(2,("Password Change: %s, New password is shorter than MINPASSWDLENGTH\n",name)); - return (False); /* inform the user */ - } - - /* Password is same as old password */ - if (strcmp(oldpass,newpass) == 0) /* don't allow same password */ - { - DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */ - return (False); /* inform the user */ - } - -#if (defined(PASSWD_PROGRAM) && defined(PASSWD_CHAT)) - strcpy(passwordprogram,PASSWD_PROGRAM); - strcpy(chatsequence,PASSWD_CHAT); -#else - strcpy(passwordprogram,lp_passwd_program()); - strcpy(chatsequence,lp_passwd_chat()); -#endif - - if (!*chatsequence) { - DEBUG(2,("Null chat sequence - no password changing\n")); - return(False); - } - - if (!*passwordprogram) { - DEBUG(2,("Null password program - no password changing\n")); - return(False); - } - - string_sub(passwordprogram,"%u",name); - string_sub(passwordprogram,"%o",oldpass); - string_sub(passwordprogram,"%n",newpass); - - string_sub(chatsequence,"%u",name); - string_sub(chatsequence,"%o",oldpass); - string_sub(chatsequence,"%n",newpass); - return(chat_with_program(passwordprogram,name,chatsequence)); -} - -#else -BOOL chgpasswd(char *name,char *oldpass,char *newpass) -{ - DEBUG(0,("Password changing not compiled in (user=%s)\n",name)); - return(False); -} -#endif diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c deleted file mode 100644 index 7922e416236..00000000000 --- a/source/smbd/ipc.c +++ /dev/null @@ -1,3098 +0,0 @@ - -/* - Unix SMB/Netbios implementation. - Version 1.9. - Inter-process communication and named pipe handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - This file handles the named pipe and mailslot calls - in the SMBtrans protocol - */ - -#include "includes.h" - -#ifdef CHECK_TYPES -#undef CHECK_TYPES -#endif -#define CHECK_TYPES 0 - -extern int DEBUGLEVEL; -extern int max_send; -extern files_struct Files[]; -extern connection_struct Connections[]; - -extern fstring local_machine; -extern fstring myworkgroup; - -#define NERR_Success 0 -#define NERR_badpass 86 -#define NERR_notsupported 50 - -#define NERR_BASE (2100) -#define NERR_BufTooSmall (NERR_BASE+23) -#define NERR_JobNotFound (NERR_BASE+51) -#define NERR_DestNotFound (NERR_BASE+52) -#define ERROR_INVALID_LEVEL 124 -#define ERROR_MORE_DATA 234 - -#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024)) - -#define ACCESS_READ 0x01 -#define ACCESS_WRITE 0x02 -#define ACCESS_CREATE 0x04 - -#define SHPWLEN 8 /* share password length */ -#define NNLEN 12 /* 8.3 net name length */ -#define SNLEN 15 /* service name length */ -#define QNLEN 12 /* queue name maximum length */ - -extern int Client; - -static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); -static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - - -static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n) -{ - pstring buf; - int l; - - if (!src || !dst || !n || !(*dst)) return(0); - - StrnCpy(buf,src,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - StrnCpy(*dst,buf,*n); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; -} - -static int CopyAndAdvance(char** dst, char* src, int* n) -{ - int l; - if (!src || !dst || !n || !(*dst)) return(0); - StrnCpy(*dst,src,*n); - l = strlen(*dst) + 1; - (*dst) += l; - (*n) -= l; - return l; -} - -static int StrlenExpanded(int cnum, int snum, char* s) -{ - pstring buf; - if (!s) return(0); - StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - return strlen(buf) + 1; -} - -static char* Expand(int cnum, int snum, char* s) -{ - static pstring buf; - if (!s) return(NULL); - StrnCpy(buf,s,sizeof(buf)/2); - string_sub(buf,"%S",lp_servicename(snum)); - standard_sub(cnum,buf); - return &buf[0]; -} - -/******************************************************************* - check a API string for validity when we only need to check the prefix - ******************************************************************/ -static BOOL prefix_ok(char *str,char *prefix) -{ - return(strncmp(str,prefix,strlen(prefix)) == 0); -} - - -/**************************************************************************** - send a trans reply - ****************************************************************************/ -static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup) -{ - int i; - int this_ldata,this_lparam; - int tot_data=0,tot_param=0; - int align; - - this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */ - this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam)); - - align = (this_lparam%4); - - set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True); - if (this_lparam) - memcpy(smb_buf(outbuf),param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata); - - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,lsetup); - for (i=0;i<lsetup;i++) - SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data = this_ldata; - tot_param = this_lparam; - - while (tot_data < ldata || tot_param < lparam) - { - this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */ - this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam)); - - align = (this_lparam%4); - - set_message(outbuf,10,this_ldata+this_lparam+align,False); - if (this_lparam) - memcpy(smb_buf(outbuf),param+tot_param,this_lparam); - if (this_ldata) - memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata); - - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data); - SSVAL(outbuf,smb_vwv9,0); - - show_msg(outbuf); - send_smb(Client,outbuf); - - tot_data += this_ldata; - tot_param += this_lparam; - } -} - -struct pack_desc { - char* format; /* formatstring for structure */ - char* subformat; /* subformat for structure */ - char* base; /* baseaddress of buffer */ - int buflen; /* remaining size for fixed part; on init: length of base */ - int subcount; /* count of substructures */ - char* structbuf; /* pointer into buffer for remaining fixed part */ - int stringlen; /* remaining size for variable part */ - char* stringbuf; /* pointer into buffer for remaining variable part */ - int neededlen; /* total needed size */ - int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ - char* curpos; /* current position; pointer into format or subformat */ - int errcode; -}; - -static int get_counter(char** p) -{ - int i, n; - if (!p || !(*p)) return(1); - if (!isdigit(**p)) return 1; - for (n = 0;;) { - i = **p; - if (isdigit(i)) - n = 10 * n + (i - '0'); - else - return n; - (*p)++; - } -} - -static int getlen(char* p) -{ - int n = 0; - if (!p) return(0); - while (*p) { - switch( *p++ ) { - case 'W': /* word (2 byte) */ - n += 2; - break; - case 'N': /* count of substructures (word) at end */ - n += 2; - break; - case 'D': /* double word (4 byte) */ - case 'z': /* offset to zero terminated string (4 byte) */ - case 'l': /* offset to user data (4 byte) */ - n += 4; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - n += 4; - get_counter(&p); - break; - case 'B': /* byte (with optional counter) */ - n += get_counter(&p); - break; - } - } - return n; -} - -static BOOL init_package(struct pack_desc* p, int count, int subcount) -{ - int n = p->buflen; - int i; - - if (!p->format || !p->base) return(False); - - i = count * getlen(p->format); - if (p->subformat) i += subcount * getlen(p->subformat); - p->structbuf = p->base; - p->neededlen = 0; - p->usedlen = 0; - p->subcount = 0; - p->curpos = p->format; - if (i > n) { - i = n = 0; - p->errcode = NERR_BufTooSmall; - } - - p->errcode = NERR_Success; - p->buflen = i; - n -= i; - p->stringbuf = p->base + i; - p->stringlen = n; - return(p->errcode == NERR_Success); -} - -#ifdef __STDC__ -static int package(struct pack_desc* p, ...) -{ -#else -static int package(va_alist) -va_dcl -{ - struct pack_desc* p; -#endif - va_list args; - int needed=0, stringneeded; - char* str=NULL; - int is_string=0, stringused; - int32 temp; - -#ifdef __STDC__ - va_start(args,p); -#else - va_start(args); - p = va_arg(args,struct pack_desc *); -#endif - - if (!*p->curpos) { - if (!p->subcount) - p->curpos = p->format; - else { - p->curpos = p->subformat; - p->subcount--; - } - } -#if CHECK_TYPES - str = va_arg(args,char*); - if (strncmp(str,p->curpos,strlen(str)) != 0) { - DEBUG(2,("type error in package: %s instead of %*s\n",str, - strlen(str),p->curpos)); - va_end(args); -#if AJT - ajt_panic(); -#endif - return 0; - } -#endif - stringneeded = -1; - - if (!p->curpos) return(0); - - switch( *p->curpos++ ) { - case 'W': /* word (2 byte) */ - needed = 2; - temp = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,temp); - break; - case 'N': /* count of substructures (word) at end */ - needed = 2; - p->subcount = va_arg(args,int); - if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount); - break; - case 'D': /* double word (4 byte) */ - needed = 4; - temp = va_arg(args,int); - if (p->buflen >= needed) SIVAL(p->structbuf,0,temp); - break; - case 'B': /* byte (with optional counter) */ - needed = get_counter(&p->curpos); - { - char *s = va_arg(args,char*); - if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed); - } - break; - case 'z': /* offset to zero terminated string (4 byte) */ - str = va_arg(args,char*); - stringneeded = (str ? strlen(str)+1 : 0); - is_string = 1; - break; - case 'l': /* offset to user data (4 byte) */ - str = va_arg(args,char*); - stringneeded = va_arg(args,int); - is_string = 0; - break; - case 'b': /* offset to data (with counter) (4 byte) */ - str = va_arg(args,char*); - stringneeded = get_counter(&p->curpos); - is_string = 0; - break; - } - va_end(args); - if (stringneeded >= 0) { - needed = 4; - if (p->buflen >= needed) { - stringused = stringneeded; - if (stringused > p->stringlen) { - stringused = (is_string ? p->stringlen : 0); - if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA; - } - if (!stringused) - SIVAL(p->structbuf,0,0); - else { - SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); - memcpy(p->stringbuf,str?str:"",stringused); - if (is_string) p->stringbuf[stringused-1] = '\0'; - p->stringbuf += stringused; - p->stringlen -= stringused; - p->usedlen += stringused; - } - } - p->neededlen += stringneeded; - } - p->neededlen += needed; - if (p->buflen >= needed) { - p->structbuf += needed; - p->buflen -= needed; - p->usedlen += needed; - } - else { - if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall; - } - return 1; -} - -#if CHECK_TYPES -#define PACK(desc,t,v) package(desc,t,v,0,0,0,0) -#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0) -#else -#define PACK(desc,t,v) package(desc,v) -#define PACKl(desc,t,v,l) package(desc,v,l) -#endif - -static void PACKI(struct pack_desc* desc,char *t,int v) -{ - PACK(desc,t,v); -} - -static void PACKS(struct pack_desc* desc,char *t,char *v) -{ - PACK(desc,t,v); -} - - -/**************************************************************************** - get a print queue - ****************************************************************************/ - -static void PackDriverData(struct pack_desc* desc) -{ - char drivdata[4+4+32]; - SIVAL(drivdata,0,sizeof drivdata); /* cb */ - SIVAL(drivdata,4,1000); /* lVersion */ - memset(drivdata+8,0,32); /* szDeviceName */ - strcpy(drivdata+8,"NULL"); - PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ -} - -static int check_printq_info(struct pack_desc* desc, - int uLevel, char *id1, const char* id2) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: - desc->format = "B13"; - break; - case 1: - desc->format = "B13BWWWzzzzzWW"; - break; - case 2: - desc->format = "B13BWWWzzzzzWN"; - desc->subformat = "WB21BB16B10zWWzDDz"; - break; - case 3: - desc->format = "zWWWWzzzzWWzzl"; - break; - case 4: - desc->format = "zWWWWzzzzWNzzl"; - desc->subformat = "WWzWWDDzz"; - break; - case 5: - desc->format = "z"; - break; - default: return False; - } - if (strcmp(desc->format,id1) != 0) return False; - if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False; - return True; -} - -static void fill_printjob_info(int cnum, int snum, int uLevel, - struct pack_desc* desc, - print_queue_struct* queue, int n) -{ - time_t t = queue->time; - - /* the client expects localtime */ - t -= TimeDiff(t); - - PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */ - if (uLevel == 1) { - PACKS(desc,"B21",queue->user); /* szUserName */ - PACKS(desc,"B",""); /* pad */ - PACKS(desc,"B16",""); /* szNotifyName */ - PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",queue->status); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z",queue->file); /* pszComment */ - } - if (uLevel == 2 || uLevel == 3) { - PACKI(desc,"W",queue->priority); /* uPriority */ - PACKS(desc,"z",queue->user); /* pszUserName */ - PACKI(desc,"W",n+1); /* uPosition */ - PACKI(desc,"W",queue->status); /* fsStatus */ - PACKI(desc,"D",t); /* ulSubmitted */ - PACKI(desc,"D",queue->size); /* ulSize */ - PACKS(desc,"z","Samba"); /* pszComment */ - PACKS(desc,"z",queue->file); /* pszDocument */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszNotifyName */ - PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ - PACKS(desc,"z",""); /* pszParms */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ - PACKS(desc,"z","lpd"); /* pszQProcName */ - PACKS(desc,"z",""); /* pszQProcParms */ - PACKS(desc,"z","NULL"); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - PACKS(desc,"z",""); /* pszPrinterName */ - } - } -} - -static void fill_printq_info(int cnum, int snum, int uLevel, - struct pack_desc* desc, - int count, print_queue_struct* queue, - print_status_struct* status) -{ - if (uLevel < 3) { - PACKS(desc,"B13",SERVICE(snum)); - } else { - PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum))); - } - if (uLevel == 1 || uLevel == 2) { - PACKS(desc,"B",""); /* alignment */ - PACKI(desc,"W",5); /* priority */ - PACKI(desc,"W",0); /* start time */ - PACKI(desc,"W",0); /* until time */ - PACKS(desc,"z",""); /* pSepFile */ - PACKS(desc,"z","lpd"); /* pPrProc */ - PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ - PACKS(desc,"z",""); /* pParms */ - if (snum < 0) { - PACKS(desc,"z","UNKNOWN PRINTER"); - PACKI(desc,"W",LPSTAT_ERROR); - } - else if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); - PACKI(desc,"W",LPSTAT_OK); /* status */ - } else { - PACKS(desc,"z",status->message); - PACKI(desc,"W",status->status); /* status */ - } - PACKI(desc,(uLevel == 1 ? "W" : "N"),count); - } - if (uLevel == 3 || uLevel == 4) { - PACKI(desc,"W",5); /* uPriority */ - PACKI(desc,"W",0); /* uStarttime */ - PACKI(desc,"W",0); /* uUntiltime */ - PACKI(desc,"W",5); /* pad1 */ - PACKS(desc,"z",""); /* pszSepFile */ - PACKS(desc,"z","WinPrint"); /* pszPrProc */ - PACKS(desc,"z",""); /* pszParms */ - if (!status || !status->message[0]) { - PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */ - PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ - } else { - PACKS(desc,"z",status->message); /* pszComment */ - PACKI(desc,"W",status->status); /* fsStatus */ - } - PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ - PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ - PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */ - PackDriverData(desc); /* pDriverData */ - } - if (uLevel == 2 || uLevel == 4) { - int i; - for (i=0;i<count;i++) - fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i); - } - - DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count)); -} - -static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char *QueueName = p; - int uLevel,cbBuf; - int count=0; - int snum; - char* str3; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - bzero(&status,sizeof(status)); - bzero(&desc,sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - str3 = p + 4; - - /* remove any trailing username */ - if ((p = strchr(QueueName,'%'))) *p = 0; - - DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName)); - - /* check it's a supported varient */ - if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_printq_info(&desc,uLevel,str2,str3)) return False; - - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = get_printqueue(snum,cnum,&queue,&status); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,count)) { - desc.subcount = count; - fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status); - } - - *rdata_len = desc.usedlen; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); - - if (queue) free(queue); - - return(True); -} - - -/**************************************************************************** - view list of all print jobs on all queues - ****************************************************************************/ -static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data, - int mdrcnt, int mprcnt, - char **rdata, char** rparam, - int *rdata_len, int *rparam_len) -{ - char *param_format = param+2; - char *output_format1 = skip_string(param_format,1); - char *p = skip_string(output_format1,1); - int uLevel = SVAL(p,0); - char *output_format2 = p + 4; - int services = lp_numservices(); - int i, n; - struct pack_desc desc; - print_queue_struct **queue = NULL; - print_status_struct *status = NULL; - int* subcntarr = NULL; - int queuecnt, subcnt=0, succnt=0; - - bzero(&desc,sizeof(desc)); - - DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); - - if (!prefix_ok(param_format,"WrLeh")) return False; - if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) - return False; - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - if (uLevel > 0) { - queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*)); - memset(queue,0,queuecnt*sizeof(print_queue_struct*)); - status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct)); - memset(status,0,queuecnt*sizeof(print_status_struct)); - subcntarr = (int*)malloc(queuecnt*sizeof(int)); - subcnt = 0; - n = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]); - subcnt += subcntarr[n]; - n++; - } - } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,queuecnt,subcnt)) { - n = 0; - succnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - - if (subcntarr) free(subcntarr); - - *rdata_len = desc.usedlen; - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - for (i = 0; i < queuecnt; i++) { - if (queue && queue[i]) free(queue[i]); - } - - if (queue) free(queue); - if (status) free(status); - - return True; -} - -/**************************************************************************** - get info level for a server list query - ****************************************************************************/ -static BOOL check_server_info(int uLevel, char* id) -{ - switch( uLevel ) { - case 0: - if (strcmp(id,"B16") != 0) return False; - break; - case 1: - if (strcmp(id,"B16BBDz") != 0) return False; - break; - default: - return False; - } - return True; -} - -struct srv_info_struct -{ - fstring name; - uint32 type; - fstring comment; - fstring domain; - BOOL server_added; -}; - - -/******************************************************************* - get server info lists from the files saved by nmbd. Return the - number of entries - ******************************************************************/ -static int get_server_info(uint32 servertype, - struct srv_info_struct **servers, - char *domain) -{ - FILE *f; - pstring fname; - int count=0; - int alloced=0; - pstring line; - BOOL local_list_only; - - strcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,SERVER_LIST); - - f = fopen(fname,"r"); - - if (!f) { - DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno))); - return(0); - } - - /* request for everything is code for request all servers */ - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); - - local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); - - DEBUG(4,("Servertype search: %8x\n",servertype)); - - while (!feof(f)) - { - fstring stype; - struct srv_info_struct *s; - char *ptr = line; - BOOL ok = True; - *ptr = 0; - - fgets(line,sizeof(line)-1,f); - if (!*line) continue; - - if (count == alloced) { - alloced += 10; - (*servers) = (struct srv_info_struct *) - Realloc(*servers,sizeof(**servers)*alloced); - if (!(*servers)) return(0); - bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count)); - } - s = &(*servers)[count]; - - if (!next_token(&ptr,s->name , NULL)) continue; - if (!next_token(&ptr,stype , NULL)) continue; - if (!next_token(&ptr,s->comment, NULL)) continue; - if (!next_token(&ptr,s->domain , NULL)) { - /* this allows us to cope with an old nmbd */ - strcpy(s->domain,myworkgroup); - } - - if (sscanf(stype,"%X",&s->type) != 1) { - DEBUG(4,("r:host file ")); - ok = False; - } - - /* Filter the servers/domains we return based on what was asked for. */ - - /* Check to see if we are being asked for a local list only. */ - if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { - DEBUG(4,("r: local list only")); - ok = False; - } - - /* doesn't match up: don't want it */ - if (!(servertype & s->type)) { - DEBUG(4,("r:serv type ")); - ok = False; - } - - if ((servertype & SV_TYPE_DOMAIN_ENUM) != - (s->type & SV_TYPE_DOMAIN_ENUM)) - { - DEBUG(4,("s: dom mismatch ")); - ok = False; - } - - if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - { - ok = False; - } - - /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ - s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; - - if (ok) - { - DEBUG(4,("**SV** %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - - s->server_added = True; - count++; - } - else - { - DEBUG(4,("%20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - } - } - - fclose(f); - return(count); -} - - -/******************************************************************* - fill in a server info structure - ******************************************************************/ -static int fill_srv_info(struct srv_info_struct *service, - int uLevel, char **buf, int *buflen, - char **stringbuf, int *stringspace, char *baseaddr) -{ - int struct_len; - char* p; - char* p2; - int l2; - int len; - - switch (uLevel) { - case 0: struct_len = 16; break; - case 1: struct_len = 26; break; - default: return -1; - } - - if (!buf) - { - len = 0; - switch (uLevel) - { - case 1: - len = strlen(service->comment)+1; - break; - } - - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } - - len = struct_len; - p = *buf; - if (*buflen < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = *buflen - struct_len; - } - if (!baseaddr) baseaddr = p; - - switch (uLevel) - { - case 0: - StrnCpy(p,service->name,15); - break; - - case 1: - StrnCpy(p,service->name,15); - SIVAL(p,18,service->type); - SIVAL(p,22,PTR_DIFF(p2,baseaddr)); - len += CopyAndAdvance(&p2,service->comment,&l2); - break; - } - - if (stringbuf) - { - *buf = p + struct_len; - *buflen -= struct_len; - *stringbuf = p2; - *stringspace = l2; - } - else - { - *buf = p2; - *buflen -= len; - } - return len; -} - - -static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) -{ - return(strcmp(s1->name,s2->name)); -} - -/**************************************************************************** - view list of servers available (or possibly domains). The info is - extracted from lists saved by nmbd on the local host - ****************************************************************************/ -static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, - int mdrcnt, int mprcnt, char **rdata, - char **rparam, int *rdata_len, int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - uint32 servertype = IVAL(p,4); - char *p2; - int data_len, fixed_len, string_len; - int f_len, s_len; - struct srv_info_struct *servers=NULL; - int counted=0,total=0; - int i,missed; - fstring domain; - BOOL domain_request; - BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY; - - if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM; - - domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); - - p += 8; - - if (!prefix_ok(str1,"WrLehD")) return False; - if (!check_server_info(uLevel,str2)) return False; - - DEBUG(4, ("server request level: %s %8x ", str2, servertype)); - DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); - DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); - - if (strcmp(str1, "WrLehDz") == 0) { - StrnCpy(domain, p, sizeof(fstring)-1); - } else { - StrnCpy(domain, myworkgroup, sizeof(fstring)-1); - } - - if (lp_browse_list()) - total = get_server_info(servertype,&servers,domain); - - data_len = fixed_len = string_len = 0; - missed = 0; - - qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); - - { - char *lastname=NULL; - - for (i=0;i<total;i++) - { - struct srv_info_struct *s = &servers[i]; - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0); - DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - - if (data_len <= buf_len) { - counted++; - fixed_len += f_len; - string_len += s_len; - } else { - missed++; - } - } - } - - *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); - bzero(*rdata,*rdata_len); - - p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - - { - char *lastname=NULL; - int count2 = counted; - for (i = 0; i < total && count2;i++) - { - struct srv_info_struct *s = &servers[i]; - if (lastname && strequal(lastname,s->name)) continue; - lastname = s->name; - fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata); - DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", - s->name, s->type, s->comment, s->domain)); - count2--; - } - } - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,counted+missed); - - if (servers) free(servers); - - DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", - domain,uLevel,counted,counted+missed)); - - return(True); -} - - -/**************************************************************************** - get info about a share - ****************************************************************************/ -static BOOL check_share_info(int uLevel, char* id) -{ - switch( uLevel ) { - case 0: - if (strcmp(id,"B13") != 0) return False; - break; - case 1: - if (strcmp(id,"B13BWz") != 0) return False; - break; - case 2: - if (strcmp(id,"B13BWzWWWzB9B") != 0) return False; - break; - case 91: - if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False; - break; - default: return False; - } - return True; -} - -static int fill_share_info(int cnum, int snum, int uLevel, - char** buf, int* buflen, - char** stringbuf, int* stringspace, char* baseaddr) -{ - int struct_len; - char* p; - char* p2; - int l2; - int len; - - switch( uLevel ) { - case 0: struct_len = 13; break; - case 1: struct_len = 20; break; - case 2: struct_len = 40; break; - case 91: struct_len = 68; break; - default: return -1; - } - - - if (!buf) - { - len = 0; - if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum)); - if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1; - if (buflen) *buflen = struct_len; - if (stringspace) *stringspace = len; - return struct_len + len; - } - - len = struct_len; - p = *buf; - if ((*buflen) < struct_len) return -1; - if (stringbuf) - { - p2 = *stringbuf; - l2 = *stringspace; - } - else - { - p2 = p + struct_len; - l2 = (*buflen) - struct_len; - } - if (!baseaddr) baseaddr = p; - - StrnCpy(p,lp_servicename(snum),13); - - if (uLevel > 0) - { - int type; - CVAL(p,13) = 0; - type = STYPE_DISKTREE; - if (lp_print_ok(snum)) type = STYPE_PRINTQ; - if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC; - SSVAL(p,14,type); /* device type */ - SIVAL(p,16,PTR_DIFF(p2,baseaddr)); - len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2); - } - - if (uLevel > 1) - { - SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ - SSVALS(p,22,-1); /* max uses */ - SSVAL(p,24,1); /* current uses */ - SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ - len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); - memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ - } - - if (uLevel > 2) - { - memset(p+40,0,SHPWLEN+2); - SSVAL(p,50,0); - SIVAL(p,52,0); - SSVAL(p,56,0); - SSVAL(p,58,0); - SIVAL(p,60,0); - SSVAL(p,64,0); - SSVAL(p,66,0); - } - - if (stringbuf) - { - (*buf) = p + struct_len; - (*buflen) -= struct_len; - (*stringbuf) = p2; - (*stringspace) = l2; - } - else - { - (*buf) = p2; - (*buflen) -= len; - } - return len; -} - -static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *netname = skip_string(str2,1); - char *p = skip_string(netname,1); - int uLevel = SVAL(p,0); - int snum = find_service(netname); - - if (snum < 0) return False; - - /* check it's a supported varient */ - if (!prefix_ok(str1,"zWrLh")) return False; - if (!check_share_info(uLevel,str2)) return False; - - *rdata = REALLOC(*rdata,mdrcnt); - p = *rdata; - *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0); - if (*rdata_len < 0) return False; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - -/**************************************************************************** - view list of shares available - ****************************************************************************/ -static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - int buf_len = SVAL(p,2); - char *p2; - int count=lp_numservices(); - int total=0,counted=0; - int i; - int data_len, fixed_len, string_len; - int f_len, s_len; - - if (!prefix_ok(str1,"WrLeh")) return False; - if (!check_share_info(uLevel,str2)) return False; - - data_len = fixed_len = string_len = 0; - for (i=0;i<count;i++) - if (lp_browseable(i) && lp_snum_ok(i)) - { - total++; - data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0); - if (data_len <= buf_len) - { - counted++; - fixed_len += f_len; - string_len += s_len; - } - } - *rdata_len = fixed_len + string_len; - *rdata = REALLOC(*rdata,*rdata_len); - memset(*rdata,0,*rdata_len); - - p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */ - p = *rdata; - f_len = fixed_len; - s_len = string_len; - for (i = 0; i < count;i++) - if (lp_browseable(i) && lp_snum_ok(i)) - if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0) - break; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,counted); - SSVAL(*rparam,6,total); - - DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n", - counted,total,uLevel, - buf_len,*rdata_len,mdrcnt)); - return(True); -} - - - -/**************************************************************************** - get the time of day info - ****************************************************************************/ -static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *p; - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 21; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - - { - struct tm *t; - time_t unixdate = time(NULL); - - put_dos_date3(p,0,unixdate); /* this is the time that is looked at - by NT in a "net time" operation, - it seems to ignore the one below */ - - /* the client expects to get localtime, not GMT, in this bit - (I think, this needs testing) */ - t = LocalTime(&unixdate); - - SIVAL(p,4,0); /* msecs ? */ - CVAL(p,8) = t->tm_hour; - CVAL(p,9) = t->tm_min; - CVAL(p,10) = t->tm_sec; - CVAL(p,11) = 0; /* hundredths of seconds */ - SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */ - SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ - CVAL(p,16) = t->tm_mday; - CVAL(p,17) = t->tm_mon + 1; - SSVAL(p,18,1900+t->tm_year); - CVAL(p,20) = t->tm_wday; - } - - - return(True); -} - -/**************************************************************************** - set the user password - ****************************************************************************/ -static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; - - strcpy(user,p); - - p = skip_string(p,1); - - StrnCpy(pass1,p,16); - StrnCpy(pass2,p+16,16); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ - - DEBUG(3,("Set password for <%s>\n",user)); - - if (password_ok(user,pass1,strlen(pass1),NULL) && - chgpasswd(user,pass1,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - - bzero(pass1,sizeof(fstring)); - bzero(pass2,sizeof(fstring)); - - return(True); -} - -/**************************************************************************** - delete a print job - Form: <W> <> - ****************************************************************************/ -static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - int function = SVAL(param,0); - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded - by the print queue api */ - int snum = (SVAL(p,0)>>8); - int i, count; - - - /* check it's a supported varient */ - if (!(strcsequal(str1,"W") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_Success); - - if (snum >= 0 && VALID_SNUM(snum)) - { - print_queue_struct *queue=NULL; - lpq_reset(snum); - count = get_printqueue(snum,cnum,&queue,NULL); - - for (i=0;i<count;i++) - if ((queue[i].job%0xFF) == jobid) - { - switch (function) { - case 81: /* delete */ - DEBUG(3,("Deleting queue entry %d\n",queue[i].job)); - del_printqueue(cnum,snum,queue[i].job); - break; - case 82: /* pause */ - case 83: /* resume */ - DEBUG(3,("%s queue entry %d\n", - (function==82?"pausing":"resuming"),queue[i].job)); - status_printjob(cnum,snum,queue[i].job, - (function==82?LPQ_PAUSED:LPQ_QUEUED)); - break; - } - break; - } - - if (i==count) - SSVAL(*rparam,0,NERR_JobNotFound); - - if (queue) free(queue); - } - - SSVAL(*rparam,2,0); /* converter word */ - - return(True); -} - -static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *QueueName = skip_string(str2,1); - int snum; - - /* check it's a supported varient */ - if (!(strcsequal(str1,"z") && strcsequal(str2,""))) - return(False); - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - snum = lp_servicenumber(QueueName); - if (snum < 0 && pcap_printername_ok(QueueName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(QueueName,pnum); - snum = lp_servicenumber(QueueName); - } - } - - if (snum >= 0 && VALID_SNUM(snum)) { - print_queue_struct *queue=NULL; - int i, count; - lpq_reset(snum); - - count = get_printqueue(snum,cnum,&queue,NULL); - for (i = 0; i < count; i++) - del_printqueue(cnum,snum,queue[i].job); - - if (queue) free(queue); - } - - DEBUG(3,("Print queue purge, queue=%s\n",QueueName)); - - return(True); -} - - -/**************************************************************************** - set the property of a print job (undocumented?) - ? function = 0xb -> set name of print job - ? function = 0x6 -> move print job up/down - Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> - or <WWsTP> <WB21BB16B10zWWzDDz> -****************************************************************************/ -static int check_printjob_info(struct pack_desc* desc, - int uLevel, char* id) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "W"; break; - case 1: desc->format = "WB21BB16B10zWWzDDz"; break; - case 2: desc->format = "WWzWWDDzz"; break; - case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; -} - -static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - struct pack_desc desc; - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded - by the print queue api */ - int snum = (SVAL(p,0)>>8); - int uLevel = SVAL(p,2); - int function = SVAL(p,4); /* what is this ?? */ - int i; - char *s = data; - - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - /* check it's a supported varient */ - if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2))) - return(False); - - switch (function) { - case 0x6: /* change job place in the queue, data gives the new place */ - if (snum >= 0 && VALID_SNUM(snum)) - { - print_queue_struct *queue=NULL; - int count; - - lpq_reset(snum); - count = get_printqueue(snum,cnum,&queue,NULL); - for (i=0;i<count;i++) /* find job */ - if ((queue[i].job%0xFF) == jobid) break; - - if (i==count) { - desc.errcode=NERR_JobNotFound; - if (queue) free(queue); - } - else { - desc.errcode=NERR_Success; - i++; -#if 0 - { - int place= SVAL(data,0); - /* we currently have no way of doing this. Can any unix do it? */ - if (i < place) /* move down */; - else if (i > place ) /* move up */; - } -#endif - desc.errcode=NERR_notsupported; /* not yet supported */ - if (queue) free(queue); - } - } - else desc.errcode=NERR_JobNotFound; - break; - case 0xb: /* change print job name, data gives the name */ - /* jobid, snum should be zero */ - if (isalpha(*s)) - { - pstring name; - int l = 0; - while (l<64 && *s) - { - if (issafe(*s)) name[l++] = *s; - s++; - } - name[l] = 0; - - DEBUG(3,("Setting print name to %s\n",name)); - - for (i=0;i<MAX_OPEN_FILES;i++) - if (Files[i].open && Files[i].print_file) - { - pstring wd; - GetWd(wd); - unbecome_user(); - - if (!become_user(Files[i].cnum,vuid) || - !become_service(Files[i].cnum,True)) - break; - - if (sys_rename(Files[i].name,name) == 0) - string_set(&Files[i].name,name); - break; - } - } - desc.errcode=NERR_Success; - - break; - default: /* not implemented */ - return False; - } - - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); /* converter word */ - - return(True); -} - - -/**************************************************************************** - get info about the server - ****************************************************************************/ -static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel = SVAL(p,0); - char *p2; - int struct_len; - - DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); - - /* check it's a supported varient */ - if (!prefix_ok(str1,"WrLh")) return False; - switch( uLevel ) { - case 0: - if (strcmp(str2,"B16") != 0) return False; - struct_len = 16; - break; - case 1: - if (strcmp(str2,"B16BBDz") != 0) return False; - struct_len = 26; - break; - case 2: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz") - != 0) return False; - struct_len = 134; - break; - case 3: - if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") - != 0) return False; - struct_len = 144; - break; - case 20: - if (strcmp(str2,"DN") != 0) return False; - struct_len = 6; - break; - case 50: - if (strcmp(str2,"B16BBDzWWzzz") != 0) return False; - struct_len = 42; - break; - default: return False; - } - - *rdata_len = mdrcnt; - *rdata = REALLOC(*rdata,*rdata_len); - - p = *rdata; - p2 = p + struct_len; - if (uLevel != 20) { - StrnCpy(p,local_machine,16); - strupper(p); - } - p += 16; - if (uLevel > 0) - { - struct srv_info_struct *servers=NULL; - int i,count; - pstring comment; - uint32 servertype=DFLT_SERVER_TYPE; - - strcpy(comment,lp_serverstring()); - - if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) { - for (i=0;i<count;i++) - if (strequal(servers[i].name,local_machine)) - { - servertype = servers[i].type; - strcpy(comment,servers[i].comment); - } - } - if (servers) free(servers); - - SCVAL(p,0,MAJOR_VERSION); - SCVAL(p,1,MINOR_VERSION); - SIVAL(p,2,servertype); - - if (mdrcnt == struct_len) { - SIVAL(p,6,0); - } else { - SIVAL(p,6,PTR_DIFF(p2,*rdata)); - standard_sub(cnum,comment); - StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); - p2 = skip_string(p2,1); - } - } - if (uLevel > 1) - { - return False; /* not yet implemented */ - } - - *rdata_len = PTR_DIFF(p2,*rdata); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - - -/**************************************************************************** - get info about the server - ****************************************************************************/ -static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char *p2; - extern pstring sesssetup_user; - int level = SVAL(p,0); - - DEBUG(4,("NetWkstaGetInfo level %d\n",level)); - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) - return(False); - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - p2 = p + 22; - - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ - strcpy(p2,local_machine); - strupper(p2); - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,sesssetup_user); - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ - strcpy(p2,myworkgroup); - strupper(p2); - p2 = skip_string(p2,1); - p += 4; - - SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */ - SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */ - p += 2; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); - strcpy(p2,myworkgroup); /* don't know. login domain?? */ - p2 = skip_string(p2,1); - p += 4; - - SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ - strcpy(p2,""); - p2 = skip_string(p2,1); - p += 4; - - *rdata_len = PTR_DIFF(p2,*rdata); - - SSVAL(*rparam,4,*rdata_len); - - return(True); -} - -/**************************************************************************** - get info about a user - - struct user_info_11 { - char usri11_name[21]; 0-20 - char usri11_pad; 21 - char *usri11_comment; 22-25 - char *usri11_usr_comment; 26-29 - unsigned short usri11_priv; 30-31 - unsigned long usri11_auth_flags; 32-35 - long usri11_password_age; 36-39 - char *usri11_homedir; 40-43 - char *usri11_parms; 44-47 - long usri11_last_logon; 48-51 - long usri11_last_logoff; 52-55 - unsigned short usri11_bad_pw_count; 56-57 - unsigned short usri11_num_logons; 58-59 - char *usri11_logon_server; 60-63 - unsigned short usri11_country_code; 64-65 - char *usri11_workstations; 66-69 - unsigned long usri11_max_storage; 70-73 - unsigned short usri11_units_per_week; 74-75 - unsigned char *usri11_logon_hours; 76-79 - unsigned short usri11_code_page; 80-81 - }; - -where: - - usri11_name specifies the user name for which information is retireved - - usri11_pad aligns the next data structure element to a word boundary - - usri11_comment is a null terminated ASCII comment - - usri11_user_comment is a null terminated ASCII comment about the user - - usri11_priv specifies the level of the privilege assigned to the user. - The possible values are: - -Name Value Description -USER_PRIV_GUEST 0 Guest privilege -USER_PRIV_USER 1 User privilege -USER_PRV_ADMIN 2 Administrator privilege - - usri11_auth_flags specifies the account operator privileges. The - possible values are: - -Name Value Description -AF_OP_PRINT 0 Print operator - - -Leach, Naik [Page 28]
- - -INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 - - -AF_OP_COMM 1 Communications operator -AF_OP_SERVER 2 Server operator -AF_OP_ACCOUNTS 3 Accounts operator - - - usri11_password_age specifies how many seconds have elapsed since the - password was last changed. - - usri11_home_dir points to a null terminated ASCII string that contains - the path name of the user's home directory. - - usri11_parms points to a null terminated ASCII string that is set - aside for use by applications. - - usri11_last_logon specifies the time when the user last logged on. - This value is stored as the number of seconds elapsed since - 00:00:00, January 1, 1970. - - usri11_last_logoff specifies the time when the user last logged off. - This value is stored as the number of seconds elapsed since - 00:00:00, January 1, 1970. A value of 0 means the last logoff - time is unknown. - - usri11_bad_pw_count specifies the number of incorrect passwords - entered since the last successful logon. - - usri11_log1_num_logons specifies the number of times this user has - logged on. A value of -1 means the number of logons is unknown. - - usri11_logon_server points to a null terminated ASCII string that - contains the name of the server to which logon requests are sent. - A null string indicates logon requests should be sent to the - domain controller. - - usri11_country_code specifies the country code for the user's language - of choice. - - usri11_workstations points to a null terminated ASCII string that - contains the names of workstations the user may log on from. - There may be up to 8 workstations, with the names separated by - commas. A null strings indicates there are no restrictions. - - usri11_max_storage specifies the maximum amount of disk space the user - can occupy. A value of 0xffffffff indicates there are no - restrictions. - - usri11_units_per_week specifies the equal number of time units into - which a week is divided. This value must be equal to 168. - - usri11_logon_hours points to a 21 byte (168 bits) string that - specifies the time during which the user can log on. Each bit - represents one unique hour in a week. The first bit (bit 0, word - 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is - - - -Leach, Naik [Page 29]
- - -INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 - - - Sunday, 1:00 to 1:59 and so on. A null pointer indicates there - are no restrictions. - - usri11_code_page specifies the code page for the user's language of - choice - -All of the pointers in this data structure need to be treated -specially. The pointer is a 32 bit pointer. The higher 16 bits need -to be ignored. The converter word returned in the parameters section -needs to be subtracted from the lower 16 bits to calculate an offset -into the return buffer where this ASCII string resides. - -There is no auxiliary data in the response. - - ****************************************************************************/ - -#define usri11_name 0 -#define usri11_pad 21 -#define usri11_comment 22 -#define usri11_usr_comment 26 -#define usri11_full_name 30 -#define usri11_priv 34 -#define usri11_auth_flags 36 -#define usri11_password_age 40 -#define usri11_homedir 44 -#define usri11_parms 48 -#define usri11_last_logon 52 -#define usri11_last_logoff 56 -#define usri11_bad_pw_count 60 -#define usri11_num_logons 62 -#define usri11_logon_server 64 -#define usri11_country_code 68 -#define usri11_workstations 70 -#define usri11_max_storage 74 -#define usri11_units_per_week 78 -#define usri11_logon_hours 80 -#define usri11_code_page 84 -#define usri11_end 86 - -#define USER_PRIV_GUEST 0 -#define USER_PRIV_USER 1 -#define USER_PRIV_ADMIN 2 - -#define AF_OP_PRINT 0 -#define AF_OP_COMM 1 -#define AF_OP_SERVER 2 -#define AF_OP_ACCOUNTS 3 - - -static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); - char *p2; - - /* get NIS home of a previously validated user - simeon */ - user_struct *vuser = get_valid_user_struct(vuid); - DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name)); -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share)); -#endif - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported variant */ - if (strcmp(str1,"zWrLh") != 0) return False; - switch( uLevel ) - { - case 0: p2 = "B21"; break; - case 1: p2 = "B21BB16DWzzWz"; break; - case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; - case 10: p2 = "B21Bzzz"; break; - case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break; - default: return False; - } - - if (strcmp(p2,str2) != 0) return False; - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - p2 = p + usri11_end; - - memset(p,0,21); - strcpy(p+usri11_name,UserName); /* 21 bytes - user name */ - - if (uLevel > 0) - { - SCVAL(p,usri11_pad,0); /* padding - 1 byte */ - *p2 = 0; - } - if (uLevel >= 10) - { - SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ - strcpy(p2,"Comment"); - p2 = skip_string(p2,1); - - SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ - strcpy(p2,"UserComment"); - p2 = skip_string(p2,1); - - /* EEK! the cifsrap.txt doesn't have this in!!!! */ - SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ - strcpy(p2,vuser->real_name); /* simeon */ - p2 = skip_string(p2,1); - } - - if (uLevel == 11) /* modelled after NTAS 3.51 reply */ - { - SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ - SIVALS(p,usri11_password_age,0xffffffff); /* password age */ - SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); -#else - strcpy(p2,"\\\\%L\\%U"); -#endif - } - standard_sub_basic(p2); - p2 = skip_string(p2,1); - SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,usri11_last_logon,0); /* last logon */ - SIVAL(p,usri11_last_logoff,0); /* last logoff */ - SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */ - SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */ - SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ - strcpy(p2,"\\\\*"); - p2 = skip_string(p2,1); - SSVAL(p,usri11_country_code,0); /* country code */ - - SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ - strcpy(p2,""); - p2 = skip_string(p2,1); - - SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */ - SSVAL(p,usri11_units_per_week,168); /* units per week */ - SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */ - - /* a simple way to get logon hours at all times. */ - memset(p2,0xff,21); - SCVAL(p2,21,0); /* fix zero termination */ - p2 = skip_string(p2,1); - - SSVAL(p,usri11_code_page,0); /* code page */ - } - if (uLevel == 1 || uLevel == 2) - { - memset(p+22,' ',16); /* password */ - SIVALS(p,38,-1); /* password age */ - SSVAL(p,42, - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ - if (*lp_logon_path()) - { - strcpy(p2,lp_logon_path()); - } - else - { -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - strcpy(p2, vuser->home_share); -#else - strcpy(p2,"\\\\%L\\%U"); -#endif - } - standard_sub_basic(p2); - p2 = skip_string(p2,1); - SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ - *p2++ = 0; - SSVAL(p,52,0); /* flags */ - SIVAL(p,54,0); /* script_path */ - if (uLevel == 2) - { - SIVAL(p,60,0); /* auth_flags */ - SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ - strcpy(p2,vuser->real_name); /* simeon */ - p2 = skip_string(p2,1); - SIVAL(p,68,0); /* urs_comment */ - SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ - strcpy(p2,""); - p2 = skip_string(p2,1); - SIVAL(p,76,0); /* workstations */ - SIVAL(p,80,0); /* last_logon */ - SIVAL(p,84,0); /* last_logoff */ - SIVALS(p,88,-1); /* acct_expires */ - SIVALS(p,92,-1); /* max_storage */ - SSVAL(p,96,168); /* units_per_week */ - SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ - memset(p2,-1,21); - p2 += 21; - SSVALS(p,102,-1); /* bad_pw_count */ - SSVALS(p,104,-1); /* num_logons */ - SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ - strcpy(p2,"\\\\%L"); - standard_sub_basic(p2); - p2 = skip_string(p2,1); - SSVAL(p,110,49); /* country_code */ - SSVAL(p,112,860); /* code page */ - } - } - - *rdata_len = PTR_DIFF(p2,*rdata); - - SSVAL(*rparam,4,*rdata_len); /* is this right?? */ - - return(True); -} - -/******************************************************************* - get groups that a user is a member of - ******************************************************************/ -static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *UserName = skip_string(str2,1); - char *p = skip_string(UserName,1); - int uLevel = SVAL(p,0); - char *p2; - int count=0; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLeh") != 0) return False; - switch( uLevel ) { - case 0: p2 = "B21"; break; - default: return False; - } - if (strcmp(p2,str2) != 0) return False; - - *rdata_len = mdrcnt + 1024; - *rdata = REALLOC(*rdata,*rdata_len); - - SSVAL(*rparam,0,NERR_Success); - SSVAL(*rparam,2,0); /* converter word */ - - p = *rdata; - - /* XXXX we need a real SAM database some day */ - strcpy(p,"Users"); p += 21; count++; - strcpy(p,"Domain Users"); p += 21; count++; - strcpy(p,"Guests"); p += 21; count++; - strcpy(p,"Domain Guests"); p += 21; count++; - - *rdata_len = PTR_DIFF(p,*rdata); - - SSVAL(*rparam,4,count); /* is this right?? */ - SSVAL(*rparam,6,count); /* is this right?? */ - - return(True); -} - - -static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel; - struct pack_desc desc; - char* name; - - uLevel = SVAL(p,0); - name = p + 2; - - bzero(&desc,sizeof(desc)); - - DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - if (strcmp(str1,"OOWb54WrLh") != 0) return False; - if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False; - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.subformat = NULL; - desc.format = str2; - - if (init_package(&desc,1,0)) - { - PACKI(&desc,"W",0); /* code */ - PACKS(&desc,"B21",name); /* eff. name */ - PACKS(&desc,"B",""); /* pad */ - PACKI(&desc,"W", - Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); - PACKI(&desc,"D",0); /* auth flags XXX */ - PACKI(&desc,"W",0); /* num logons */ - PACKI(&desc,"W",0); /* bad pw count */ - PACKI(&desc,"D",0); /* last logon */ - PACKI(&desc,"D",-1); /* last logoff */ - PACKI(&desc,"D",-1); /* logoff time */ - PACKI(&desc,"D",-1); /* kickoff time */ - PACKI(&desc,"D",0); /* password age */ - PACKI(&desc,"D",0); /* password can change */ - PACKI(&desc,"D",-1); /* password must change */ - { - fstring mypath; - strcpy(mypath,"\\\\"); - strcat(mypath,local_machine); - strupper(mypath); - PACKS(&desc,"z",mypath); /* computer */ - } - PACKS(&desc,"z",myworkgroup);/* domain */ - PACKS(&desc,"z",lp_logon_script()); /* script path */ - PACKI(&desc,"D",0x00000000); /* reserved */ - } - - *rdata_len = desc.usedlen; - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); - return(True); -} - - -/**************************************************************************** - api_WAccessGetUserPerms - ****************************************************************************/ -static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *user = skip_string(str2,1); - char *resource = skip_string(user,1); - - DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); - - /* check it's a supported varient */ - if (strcmp(str1,"zzh") != 0) return False; - if (strcmp(str2,"") != 0) return False; - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,0); /* errorcode */ - SSVAL(*rparam,2,0); /* converter word */ - SSVAL(*rparam,4,0x7f); /* permission flags */ - - return(True); -} - -/**************************************************************************** - api_WPrintJobEnumerate - ****************************************************************************/ -static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uJobId = SVAL(p,0); - int uLevel,cbBuf; - int count; - int i; - int snum; - int job; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - uLevel = SVAL(p,2); - cbBuf = SVAL(p,4); - - bzero(&desc,sizeof(desc)); - bzero(&status,sizeof(status)); - - DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId)); - - /* check it's a supported varient */ - if (strcmp(str1,"WWrLh") != 0) return False; - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/ - job = uJobId & 0xFF; - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = get_printqueue(snum,cnum,&queue,&status); - for (i = 0; i < count; i++) { - if ((queue[i].job % 0xFF) == job) break; - } - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,1,0)) { - if (i < count) { - fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); - *rdata_len = desc.usedlen; - } - else { - desc.errcode = NERR_JobNotFound; - *rdata_len = 0; - } - } - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - if (queue) free(queue); - - DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* name = p; - int uLevel,cbBuf; - int count; - int i, succnt=0; - int snum; - struct pack_desc desc; - print_queue_struct *queue=NULL; - print_status_struct status; - - bzero(&desc,sizeof(desc)); - bzero(&status,sizeof(status)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLeh") != 0) return False; - if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */ - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - snum = lp_servicenumber(name); - if (snum < 0 && pcap_printername_ok(name,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(name,pnum); - snum = lp_servicenumber(name); - } - } - - if (snum < 0 || !VALID_SNUM(snum)) return(False); - - count = get_printqueue(snum,cnum,&queue,&status); - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - - if (init_package(&desc,count,0)) { - succnt = 0; - for (i = 0; i < count; i++) { - fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i); - if (desc.errcode == NERR_Success) succnt = i+1; - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,count); - - if (queue) free(queue); - - DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} - -static int check_printdest_info(struct pack_desc* desc, - int uLevel, char* id) -{ - desc->subformat = NULL; - switch( uLevel ) { - case 0: desc->format = "B9"; break; - case 1: desc->format = "B9B21WWzW"; break; - case 2: desc->format = "z"; break; - case 3: desc->format = "zzzWWzzzWW"; break; - default: return False; - } - if (strcmp(desc->format,id) != 0) return False; - return True; -} - -static void fill_printdest_info(int cnum, int snum, int uLevel, - struct pack_desc* desc) -{ - char buf[100]; - strcpy(buf,SERVICE(snum)); - strupper(buf); - if (uLevel <= 1) { - PACKS(desc,"B9",buf); /* szName */ - if (uLevel == 1) { - PACKS(desc,"B21",""); /* szUserName */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKI(desc,"W",0); /* time */ - } - } - if (uLevel == 2 || uLevel == 3) { - PACKS(desc,"z",buf); /* pszPrinterName */ - if (uLevel == 3) { - PACKS(desc,"z",""); /* pszUserName */ - PACKS(desc,"z",""); /* pszLogAddr */ - PACKI(desc,"W",0); /* uJobId */ - PACKI(desc,"W",0); /* fsStatus */ - PACKS(desc,"z",""); /* pszStatus */ - PACKS(desc,"z",""); /* pszComment */ - PACKS(desc,"z","NULL"); /* pszDrivers */ - PACKI(desc,"W",0); /* time */ - PACKI(desc,"W",0); /* pad1 */ - } - } -} - -static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - char* PrinterName = p; - int uLevel,cbBuf; - struct pack_desc desc; - int snum; - - bzero(&desc,sizeof(desc)); - - p = skip_string(p,1); - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); - - /* check it's a supported varient */ - if (strcmp(str1,"zWrLh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - snum = lp_servicenumber(PrinterName); - if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) { - int pnum = lp_servicenumber(PRINTERS_NAME); - if (pnum >= 0) { - lp_add_printer(PrinterName,pnum); - snum = lp_servicenumber(PrinterName); - } - } - - if (snum < 0) { - *rdata_len = 0; - desc.errcode = NERR_DestNotFound; - desc.neededlen = 0; - } - else { - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - fill_printdest_info(cnum,snum,uLevel,&desc); - } - *rdata_len = desc.usedlen; - } - - *rparam_len = 6; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,desc.neededlen); - - DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel,cbBuf; - int queuecnt; - int i, n, succnt=0; - struct pack_desc desc; - int services = lp_numservices(); - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (!check_printdest_info(&desc,uLevel,str2)) return False; - - queuecnt = 0; - for (i = 0; i < services; i++) - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) - queuecnt++; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,queuecnt,0)) { - succnt = 0; - n = 0; - for (i = 0; i < services; i++) { - if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { - fill_printdest_info(cnum,i,uLevel,&desc); - n++; - if (desc.errcode == NERR_Success) succnt = n; - } - } - } - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,queuecnt); - - DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel,cbBuf; - int succnt; - struct pack_desc desc; - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B41") != 0) return False; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B41","NULL"); - } - - succnt = (desc.errcode == NERR_Success ? 1 : 0); - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); - - DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel,cbBuf; - int succnt; - struct pack_desc desc; - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B13") != 0) return False; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lpd"); - } - - succnt = (desc.errcode == NERR_Success ? 1 : 0); - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); - - DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); - return(True); -} - -static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - char *str1 = param+2; - char *str2 = skip_string(str1,1); - char *p = skip_string(str2,1); - int uLevel,cbBuf; - int succnt; - struct pack_desc desc; - - bzero(&desc,sizeof(desc)); - - uLevel = SVAL(p,0); - cbBuf = SVAL(p,2); - - DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); - - /* check it's a supported varient */ - if (strcmp(str1,"WrLeh") != 0) return False; - if (uLevel != 0 || strcmp(str2,"B9") != 0) return False; - - if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt); - bzero(&desc,sizeof(desc)); - desc.base = *rdata; - desc.buflen = mdrcnt; - desc.format = str2; - if (init_package(&desc,1,0)) { - PACKS(&desc,"B13","lp0"); - } - - succnt = (desc.errcode == NERR_Success ? 1 : 0); - - *rdata_len = desc.usedlen; - - *rparam_len = 8; - *rparam = REALLOC(*rparam,*rparam_len); - SSVALS(*rparam,0,desc.errcode); - SSVAL(*rparam,2,0); - SSVAL(*rparam,4,succnt); - SSVAL(*rparam,6,1); - - DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); - return(True); -} - - -struct -{ - char * name; - char * pipename; - int subcommand; - BOOL (*fn) (); -} api_fd_commands [] = - { - { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS }, - { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, - { NULL, NULL, -1, (BOOL (*)())api_Unsupported } - }; - -/**************************************************************************** - handle remote api calls delivered to a named pipe already opened. - ****************************************************************************/ -static int api_fd_reply(int cnum,uint16 vuid,char *outbuf, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt) -{ - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; - BOOL reply=False; - int i; - int fd; - int subcommand; - - /* First find out the name of this file. */ - if (suwcnt != 2) - { - DEBUG(0,("Unexpected named pipe transaction.\n")); - return(-1); - } - - /* Get the file handle and hence the file name. */ - fd = setup[1]; - subcommand = setup[0]; - - DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name)); - DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - tdscnt,tpscnt,mdrcnt,mprcnt)); - - for (i=0;api_fd_commands[i].name;i++) - if (strequal(api_fd_commands[i].pipename, Files[fd].name) && - api_fd_commands[i].subcommand == subcommand && - api_fd_commands[i].fn) - { - DEBUG(3,("Doing %s\n",api_fd_commands[i].name)); - break; - } - - rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); - rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - - reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - if (rdata_len > mdrcnt || - rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - - /* if we get False back then it's actually unsupported */ - if (!reply) - api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - - if (rdata) - free(rdata); - if (rparam) - free(rparam); - - return(-1); -} - - - -/**************************************************************************** - the buffer was too small - ****************************************************************************/ -static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - *rparam_len = MIN(*rparam_len,mprcnt); - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_BufTooSmall); - - DEBUG(3,("Supplied buffer too small in API command\n")); - - return(True); -} - - -/**************************************************************************** - the request is not supported - ****************************************************************************/ -static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); - - *rdata_len = 0; - - SSVAL(*rparam,0,NERR_notsupported); - SSVAL(*rparam,2,0); /* converter word */ - - DEBUG(3,("Unsupported API command\n")); - - return(True); -} - - - - -struct -{ - char *name; - int id; - BOOL (*fn)(); - int flags; -} api_commands[] = { - {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0}, - {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0}, - {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0}, - {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0}, - {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0}, - {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0}, - {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0}, - {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0}, - {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0}, - {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0}, - {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0}, - {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0}, - {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0}, - {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0}, - {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0}, - {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0}, - {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0}, - {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0}, - {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0}, - {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0}, - {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0}, - {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0}, - {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0}, - {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0}, - {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0}, - {NULL, -1, (BOOL (*)())api_Unsupported,0}}; - - -/**************************************************************************** - handle remote api calls - ****************************************************************************/ -static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params, - int tdscnt,int tpscnt,int mdrcnt,int mprcnt) -{ - int api_command = SVAL(params,0); - char *rdata = NULL; - char *rparam = NULL; - int rdata_len = 0; - int rparam_len = 0; - BOOL reply=False; - int i; - - DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", - api_command,params+2,skip_string(params+2,1), - tdscnt,tpscnt,mdrcnt,mprcnt)); - - for (i=0;api_commands[i].name;i++) - if (api_commands[i].id == api_command && api_commands[i].fn) - { - DEBUG(3,("Doing %s\n",api_commands[i].name)); - break; - } - - rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024); - rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024); - - reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - - if (rdata_len > mdrcnt || - rparam_len > mprcnt) - { - reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - } - - - /* if we get False back then it's actually unsupported */ - if (!reply) - api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt, - &rdata,&rparam,&rdata_len,&rparam_len); - - - - /* now send the reply */ - send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0); - - if (rdata) - free(rdata); - if (rparam) - free(rparam); - - return(-1); -} - -/**************************************************************************** - handle named pipe commands - ****************************************************************************/ -static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name, - uint16 *setup,char *data,char *params, - int suwcnt,int tdscnt,int tpscnt, - int msrcnt,int mdrcnt,int mprcnt) -{ - - if (strequal(name,"LANMAN")) - return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt)); - -if (strlen(name) < 1) - return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt)); - - - DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n", - name,(int)setup[0],(int)setup[1])); - - return(0); -} - - -/**************************************************************************** - reply to a SMBtrans - ****************************************************************************/ -int reply_trans(char *inbuf,char *outbuf) -{ - fstring name; - - char *data=NULL,*params=NULL; - uint16 *setup=NULL; - - int outsize = 0; - int cnum = SVAL(inbuf,smb_tid); - uint16 vuid = SVAL(inbuf,smb_uid); - - int tpscnt = SVAL(inbuf,smb_vwv0); - int tdscnt = SVAL(inbuf,smb_vwv1); - int mprcnt = SVAL(inbuf,smb_vwv2); - int mdrcnt = SVAL(inbuf,smb_vwv3); - int msrcnt = CVAL(inbuf,smb_vwv4); - BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0); - BOOL one_way = BITSETW(inbuf+smb_vwv5,1); - int pscnt = SVAL(inbuf,smb_vwv9); - int psoff = SVAL(inbuf,smb_vwv10); - int dscnt = SVAL(inbuf,smb_vwv11); - int dsoff = SVAL(inbuf,smb_vwv12); - int suwcnt = CVAL(inbuf,smb_vwv13); - - StrnCpy(name,smb_buf(inbuf),sizeof(name)-1); - - if (tdscnt) - { - data = (char *)malloc(tdscnt); - memcpy(data,smb_base(inbuf)+dsoff,dscnt); - } - if (tpscnt) - { - params = (char *)malloc(tpscnt); - memcpy(params,smb_base(inbuf)+psoff,pscnt); - } - - if (suwcnt) - { - int i; - setup = (uint16 *)malloc(suwcnt*sizeof(setup[0])); - for (i=0;i<suwcnt;i++) - setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD); - } - - - if (pscnt < tpscnt || dscnt < tdscnt) - { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - show_msg(outbuf); - send_smb(Client,outbuf); - } - - /* receive the rest of the trans packet */ - while (pscnt < tpscnt || dscnt < tdscnt) - { - int pcnt,poff,dcnt,doff,pdisp,ddisp; - - if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || - CVAL(inbuf, smb_com) != SMBtrans) - { - DEBUG(2,("Invalid secondary trans2 packet\n")); - if (params) free(params); - if (data) free(data); - if (setup) free(setup); - return(ERROR(ERRSRV,ERRerror)); - } - - show_msg(inbuf); - - tpscnt = SVAL(inbuf,smb_vwv0); - tdscnt = SVAL(inbuf,smb_vwv1); - - pcnt = SVAL(inbuf,smb_vwv2); - poff = SVAL(inbuf,smb_vwv3); - pdisp = SVAL(inbuf,smb_vwv4); - - dcnt = SVAL(inbuf,smb_vwv5); - doff = SVAL(inbuf,smb_vwv6); - ddisp = SVAL(inbuf,smb_vwv7); - - pscnt += pcnt; - dscnt += dcnt; - - if (pcnt) - memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt); - if (dcnt) - memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); - } - - - DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt)); - - - if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0) - outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params, - suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt); - - - if (data) free(data); - if (params) free(params); - if (setup) free(setup); - - if (close_on_completion) - close_cnum(cnum,vuid); - - if (one_way) - return(-1); - - if (outsize == 0) - return(ERROR(ERRSRV,ERRnosupport)); - - return(outsize); -} diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c deleted file mode 100644 index 96e787b07fb..00000000000 --- a/source/smbd/mangle.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Name mangling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; -extern int case_default; -extern BOOL case_mangle; - -/**************************************************************************** -provide a checksum on a string -****************************************************************************/ -int str_checksum(char *s) -{ - int res = 0; - int c; - int i=0; - while (*s) - { - c = *s; - res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); - s++; i++; - } - return(res); -} - -/**************************************************************************** -return True if a name is a special msdos reserved name -****************************************************************************/ -static BOOL is_reserved_msdos(char *fname) -{ - char upperFname[13]; - char *p; - - StrnCpy (upperFname, fname, 12); - - /* lpt1.txt and con.txt etc are also illegal */ - p=strchr(upperFname,'.'); - if (p) - *p='\0'; - strupper (upperFname); - if ((strcmp(upperFname,"CLOCK$") == 0) || - (strcmp(upperFname,"CON") == 0) || - (strcmp(upperFname,"AUX") == 0) || - (strcmp(upperFname,"COM1") == 0) || - (strcmp(upperFname,"COM2") == 0) || - (strcmp(upperFname,"COM3") == 0) || - (strcmp(upperFname,"COM4") == 0) || - (strcmp(upperFname,"LPT1") == 0) || - (strcmp(upperFname,"LPT2") == 0) || - (strcmp(upperFname,"LPT3") == 0) || - (strcmp(upperFname,"NUL") == 0) || - (strcmp(upperFname,"PRN") == 0)) - return (True) ; - - return (False); -} - - - -/**************************************************************************** -return True if a name is in 8.3 dos format -****************************************************************************/ -BOOL is_8_3(char *fname, BOOL check_case) -{ - int len; - char *dot_pos; - char *slash_pos = strrchr(fname,'/'); - int l; - - if (slash_pos) fname = slash_pos+1; - len = strlen(fname); - - DEBUG(5,("checking %s for 8.3\n",fname)); - - if (check_case && case_mangle) - switch (case_default) - { - case CASE_LOWER: - if (strhasupper(fname)) return(False); - break; - case CASE_UPPER: - if (strhaslower(fname)) return(False); - break; - } - - /* can't be longer than 12 chars */ - if (len == 0 || len > 12) - return(False); - - /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ - if (is_reserved_msdos(fname)) - return(False); - - /* can't contain invalid dos chars */ - /* Windows use the ANSI charset. - But filenames are translated in the PC charset. - This Translation may be more or less relaxed depending - the Windows application. */ - - /* %%% A nice improvment to name mangling would be to translate - filename to ANSI charset on the smb server host */ - - dot_pos = strchr(fname,'.'); - - { - char *p = fname; -#ifdef KANJI - dot_pos = 0; - while (*p) - { - if (is_shift_jis (*p)) { - p += 2; - } else if (is_kana (*p)) { - p ++; - } else { - if (*p == '.' && !dot_pos) - dot_pos = (char *) p; - if (!isdoschar(*p)) - return(False); - p++; - } - } -#else - while (*p) - { - if (!isdoschar(*p)) - return(False); - p++; - } -#endif /* KANJI */ - } - - /* no dot and less than 9 means OK */ - if (!dot_pos) - return(len <= 8); - - l = PTR_DIFF(dot_pos,fname); - - /* base must be at least 1 char except special cases . and .. */ - if (l == 0) - return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); - - /* base can't be greater than 8 */ - if (l > 8) - return(False); - - if (lp_strip_dot() && - len - l == 1 && - !strchr(dot_pos+1,'.')) - { - *dot_pos = 0; - return(True); - } - - /* extension must be between 1 and 3 */ - if ( (len - l < 2 ) || (len - l > 4) ) - return(False); - - /* extension can't have a dot */ - if (strchr(dot_pos+1,'.')) - return(False); - - /* must be in 8.3 format */ - return(True); -} - - - -/* -keep a stack of name mangling results - just -so file moves and copies have a chance of working -*/ -fstring *mangled_stack = NULL; -int mangled_stack_size = 0; -int mangled_stack_len = 0; - -/**************************************************************************** -create the mangled stack -****************************************************************************/ -void create_mangled_stack(int size) -{ - if (mangled_stack) - { - free(mangled_stack); - mangled_stack_size = 0; - mangled_stack_len = 0; - } - if (size > 0) - mangled_stack = (fstring *)malloc(sizeof(fstring)*size); - if (mangled_stack) mangled_stack_size = size; -} - -/**************************************************************************** -push a mangled name onto the stack -****************************************************************************/ -static void push_mangled_name(char *s) -{ - int i; - char *p; - - if (!mangled_stack) - return; - - for (i=0;i<mangled_stack_len;i++) - if (strcmp(s,mangled_stack[i]) == 0) - { - array_promote(mangled_stack[0],sizeof(fstring),i); - return; - } - - memmove(mangled_stack[1],mangled_stack[0], - sizeof(fstring)*MIN(mangled_stack_len,mangled_stack_size-1)); - strcpy(mangled_stack[0],s); - p = strrchr(mangled_stack[0],'.'); - if (p && (!strhasupper(p+1)) && (strlen(p+1) < 4)) - *p = 0; - mangled_stack_len = MIN(mangled_stack_size,mangled_stack_len+1); -} - -/**************************************************************************** -check for a name on the mangled name stack -****************************************************************************/ -BOOL check_mangled_stack(char *s) -{ - int i; - pstring tmpname; - char extension[5]; - char *p = strrchr(s,'.'); - BOOL check_extension = False; - - extension[0] = 0; - - if (!mangled_stack) return(False); - - if (p) - { - check_extension = True; - StrnCpy(extension,p,4); - strlower(extension); /* XXXXXXX */ - } - - for (i=0;i<mangled_stack_len;i++) - { - strcpy(tmpname,mangled_stack[i]); - mangle_name_83(tmpname); - if (strequal(tmpname,s)) - { - strcpy(s,mangled_stack[i]); - break; - } - if (check_extension && !strchr(mangled_stack[i],'.')) - { - strcpy(tmpname,mangled_stack[i]); - strcat(tmpname,extension); - mangle_name_83(tmpname); - if (strequal(tmpname,s)) - { - strcpy(s,mangled_stack[i]); - strcat(s,extension); - break; - } - } - } - - if (i < mangled_stack_len) - { - DEBUG(3,("Found %s on mangled stack as %s\n",s,mangled_stack[i])); - array_promote(mangled_stack[0],sizeof(fstring),i); - return(True); - } - - return(False); -} - -static char *map_filename(char *s, /* This is null terminated */ - char *pattern, /* This isn't. */ - int len) /* This is the length of pattern. */ -{ - static pstring matching_bit; /* The bit of the string which matches */ - /* a * in pattern if indeed there is a * */ - char *sp; /* Pointer into s. */ - char *pp; /* Pointer into p. */ - char *match_start; /* Where the matching bit starts. */ - pstring pat; - - StrnCpy(pat, pattern, len); /* Get pattern into a proper string! */ - strcpy(matching_bit,""); /* Match but no star gets this. */ - pp = pat; /* Initialise the pointers. */ - sp = s; - if ((len == 1) && (*pattern == '*')) { - return NULL; /* Impossible, too ambiguous for */ - /* words! */ - } - - while ((*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp) /* The two match. */ - && (*pp != '*')) { /* No wildcard. */ - sp++; /* Keep looking. */ - pp++; - } - if (!*sp && !*pp) /* End of pattern. */ - return matching_bit; /* Simple match. Return empty string. */ - if (*pp == '*') { - pp++; /* Always interrested in the chacter */ - /* after the '*' */ - if (!*pp) { /* It is at the end of the pattern. */ - StrnCpy(matching_bit, s, sp-s); - return matching_bit; - } else { - /* The next character in pattern must match a character further */ - /* along s than sp so look for that character. */ - match_start = sp; - while ((*sp) /* Not the end of s. */ - && (*sp != *pp)) /* Not the same */ - sp++; /* Keep looking. */ - if (!*sp) { /* Got to the end without a match. */ - return NULL; - } else { /* Still hope for a match. */ - /* Now sp should point to a matching character. */ - StrnCpy(matching_bit, match_start, sp-match_start); - /* Back to needing a stright match again. */ - while ((*sp) /* Not the end of the string. */ - && (*pp) /* Not the end of the pattern. */ - && (*sp == *pp)) { /* The two match. */ - sp++; /* Keep looking. */ - pp++; - } - if (!*sp && !*pp) /* Both at end so it matched */ - return matching_bit; - else - return NULL; - } - } - } - return NULL; /* No match. */ -} - - -/* this is the magic char used for mangling */ -char magic_char = '~'; - - -/**************************************************************************** -determine whther is name could be a mangled name -****************************************************************************/ -BOOL is_mangled(char *s) -{ - char *m = strchr(s,magic_char); - if (!m) return(False); - - /* we use two base 36 chars efore the extension */ - if (m[1] == '.' || m[1] == 0 || - m[2] == '.' || m[2] == 0 || - (m[3] != '.' && m[3] != 0)) - return(is_mangled(m+1)); - - /* it could be */ - return(True); -} - - - -/**************************************************************************** -return a base 36 character. v must be from 0 to 35. -****************************************************************************/ -static char base36(unsigned int v) -{ - static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - return basechars[v % 36]; -} - - -static void do_fwd_mangled_map(char *s, char *MangledMap) -{ - /* MangledMap is a series of name pairs in () separated by spaces. - * If s matches the first of the pair then the name given is the - * second of the pair. A * means any number of any character and if - * present in the second of the pair as well as the first the - * matching part of the first string takes the place of the * in the - * second. - * - * I wanted this so that we could have RCS files which can be used - * by UNIX and DOS programs. My mapping string is (RCS rcs) which - * converts the UNIX RCS file subdirectory to lowercase thus - * preventing mangling. - */ - char *start=MangledMap; /* Use this to search for mappings. */ - char *end; /* Used to find the end of strings. */ - char *match_string; - pstring new_string; /* Make up the result here. */ - char *np; /* Points into new_string. */ - - DEBUG(5,("Mangled Mapping '%s' map '%s'\n", s, MangledMap)); - while (*start) { - while ((*start) && (*start != '(')) - start++; - start++; /* Skip the ( */ - if (!*start) - continue; /* Always check for the end. */ - end = start; /* Search for the ' ' or a ')' */ - DEBUG(5,("Start of first in pair '%s'\n", start)); - while ((*end) && !((*end == ' ') || (*end == ')'))) - end++; - if (!*end) { - start = end; - continue; /* Always check for the end. */ - } - DEBUG(5,("End of first in pair '%s'\n", end)); - if ((match_string = map_filename(s, start, end-start))) { - DEBUG(5,("Found a match\n")); - /* Found a match. */ - start = end+1; /* Point to start of what it is to become. */ - DEBUG(5,("Start of second in pair '%s'\n", start)); - end = start; - np = new_string; - while ((*end) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*')) /* Not a wildcard. */ - *np++ = *end++; - if (!*end) { - start = end; - continue; /* Always check for the end. */ - } - if (*end == '*') { - strcpy(np, match_string); - np += strlen(match_string); - end++; /* Skip the '*' */ - while ((*end) /* Not the end of string. */ - && (*end != ')') /* Not the end of the pattern. */ - && (*end != '*')) /* Not a wildcard. */ - *np++ = *end++; - } - if (!*end) { - start = end; - continue; /* Always check for the end. */ - } - *np++ = '\0'; /* NULL terminate it. */ - DEBUG(5,("End of second in pair '%s'\n", end)); - strcpy(s, new_string); /* Substitute with the new name. */ - DEBUG(5,("s is now '%s'\n", s)); - } - start = end; /* Skip a bit which cannot be wanted */ - /* anymore. */ - start++; - } -} - -/**************************************************************************** -do the actual mangling to 8.3 format -****************************************************************************/ -void mangle_name_83(char *s) -{ - int csum = str_checksum(s); - char *p; - char extension[4]; - char base[9]; - int baselen = 0; - int extlen = 0; - - extension[0]=0; - base[0]=0; - - p = strrchr(s,'.'); - if (p && (strlen(p+1)<4) ) - { - BOOL all_normal = (strisnormal(p+1)); /* XXXXXXXXX */ - if (all_normal && p[1] != 0) - { - *p = 0; - csum = str_checksum(s); - *p = '.'; - } - } - - - strupper(s); - - DEBUG(5,("Mangling name %s to ",s)); - - if (p) - { - if (p == s) - strcpy(extension,"___"); - else - { - *p++ = 0; - while (*p && extlen < 3) - { -#ifdef KANJI - if (is_shift_jis (*p)) - { - if (extlen < 2) - { - extension[extlen++] = p[0]; - extension[extlen++] = p[1]; - } - else - { - extension[extlen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; - } - else if (is_kana (*p)) - { - extension[extlen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') - extension[extlen++] = p[0]; - p++; - } -#else - if (isdoschar(*p) && *p != '.') - extension[extlen++] = *p; - p++; -#endif /* KANJI */ - } - extension[extlen] = 0; - } - } - - p = s; - - while (*p && baselen < 5) - { -#ifdef KANJI - if (is_shift_jis (*p)) - { - if (baselen < 4) - { - base[baselen++] = p[0]; - base[baselen++] = p[1]; - } - else - { - base[baselen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; - } - else if (is_kana (*p)) - { - base[baselen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') - base[baselen++] = p[0]; - p++; - } -#else - if (isdoschar(*p) && *p != '.') - base[baselen++] = *p; - p++; -#endif /* KANJI */ - } - base[baselen] = 0; - - csum = csum % (36*36); - - sprintf(s,"%s%c%c%c",base,magic_char,base36(csum/36),base36(csum%36)); - - if (*extension) - { - strcat(s,"."); - strcat(s,extension); - } - DEBUG(5,("%s\n",s)); -} - - - -/******************************************************************* - work out if a name is illegal, even for long names - ******************************************************************/ -static BOOL illegal_name(char *name) -{ - static unsigned char illegal[256]; - static BOOL initialised=False; - unsigned char *s; - - if (!initialised) { - char *ill = "*\\/?<>|\":{}"; - initialised = True; - - bzero((char *)illegal,256); - for (s = (unsigned char *)ill; *s; s++) - illegal[*s] = True; - } - -#ifdef KANJI - for (s = (unsigned char *)name; *s;) { - if (is_shift_jis (*s)) { - s += 2; - } else if (illegal[*s]) { - return(True); - } else { - s++; - } - } -#else - for (s = (unsigned char *)name;*s;s++) - if (illegal[*s]) return(True); -#endif - - - return(False); -} - - -/**************************************************************************** -convert a filename to DOS format. return True if successful. -****************************************************************************/ -BOOL name_map_mangle(char *OutName,BOOL need83,int snum) -{ -#ifdef MANGLE_LONG_FILENAMES - if (!need83 && illegal_name(OutName)) need83 = True; -#endif - - /* apply any name mappings */ - { - char *map = lp_mangled_map(snum); - if (map && *map) - do_fwd_mangled_map(OutName,map); - } - - /* check if it's already in 8.3 format */ - if (need83 && !is_8_3(OutName, True)) { - if (!lp_manglednames(snum)) return(False); - - /* mangle it into 8.3 */ - push_mangled_name(OutName); - mangle_name_83(OutName); - } - - return(True); -} - diff --git a/source/smbd/message.c b/source/smbd/message.c deleted file mode 100644 index 93a2d9d850a..00000000000 --- a/source/smbd/message.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB messaging - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - This file handles the messaging system calls for winpopup style - messages -*/ - - -#include "includes.h" - -/* look in server.c for some explanation of these variables */ -extern int DEBUGLEVEL; - - -static char msgbuf[1600]; -static int msgpos=0; -static fstring msgfrom=""; -static fstring msgto=""; - -/**************************************************************************** -deliver the message -****************************************************************************/ -static void msg_deliver(void) -{ - pstring s; - fstring name; - int i; - int fd; - - if (! (*lp_msg_command())) - { - DEBUG(1,("no messaging command specified\n")); - msgpos = 0; - return; - } - - /* put it in a temporary file */ - sprintf(s,"%s/msg.XXXXXX",tmpdir()); - strcpy(name,(char *)mktemp(s)); - - fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL,0600); - if (fd == -1) { - DEBUG(1,("can't open message file %s\n",name)); - return; - } - - for (i=0;i<msgpos;) { - if (msgbuf[i]=='\r' && i<(msgpos-1) && msgbuf[i+1]=='\n') { - i++; continue; - } - write(fd,&msgbuf[i++],1); - } - close(fd); - - - /* run the command */ - if (*lp_msg_command()) - { - strcpy(s,lp_msg_command()); - string_sub(s,"%s",name); - string_sub(s,"%f",msgfrom); - string_sub(s,"%t",msgto); - standard_sub(-1,s); - smbrun(s,NULL,False); - } - - msgpos = 0; -} - - - -/**************************************************************************** - reply to a sends -****************************************************************************/ -int reply_sends(char *inbuf,char *outbuf) -{ - int len; - char *orig,*dest,*msg; - int outsize = 0; - - msgpos = 0; - - - if (! (*lp_msg_command())) - return(ERROR(ERRSRV,ERRmsgoff)); - - outsize = set_message(outbuf,0,0,True); - - orig = smb_buf(inbuf)+1; - dest = skip_string(orig,1)+1; - msg = skip_string(dest,1)+1; - - strcpy(msgfrom,orig); - strcpy(msgto,dest); - - len = SVAL(msg,0); - len = MIN(len,1600-msgpos); - - memcpy(&msgbuf[msgpos],msg+2,len); - msgpos += len; - - DEBUG(3,("%s SMBsends (from %s to %s)\n",timestring(),orig,dest)); - - msg_deliver(); - - return(outsize); -} - - -/**************************************************************************** - reply to a sendstrt -****************************************************************************/ -int reply_sendstrt(char *inbuf,char *outbuf) -{ - char *orig,*dest; - int outsize = 0; - - if (! (*lp_msg_command())) - return(ERROR(ERRSRV,ERRmsgoff)); - - outsize = set_message(outbuf,1,0,True); - - msgpos = 0; - - orig = smb_buf(inbuf)+1; - dest = skip_string(orig,1)+1; - - strcpy(msgfrom,orig); - strcpy(msgto,dest); - - DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),orig,dest)); - - return(outsize); -} - - -/**************************************************************************** - reply to a sendtxt -****************************************************************************/ -int reply_sendtxt(char *inbuf,char *outbuf) -{ - int len; - int outsize = 0; - char *msg; - - if (! (*lp_msg_command())) - return(ERROR(ERRSRV,ERRmsgoff)); - - outsize = set_message(outbuf,0,0,True); - - msg = smb_buf(inbuf) + 1; - - len = SVAL(msg,0); - len = MIN(len,1600-msgpos); - - memcpy(&msgbuf[msgpos],msg+2,len); - msgpos += len; - - DEBUG(3,("%s SMBsendtxt\n",timestring())); - - return(outsize); -} - - -/**************************************************************************** - reply to a sendend -****************************************************************************/ -int reply_sendend(char *inbuf,char *outbuf) -{ - int outsize = 0; - - if (! (*lp_msg_command())) - return(ERROR(ERRSRV,ERRmsgoff)); - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s SMBsendend\n",timestring())); - - msg_deliver(); - - return(outsize); -} - diff --git a/source/smbd/password.c b/source/smbd/password.c deleted file mode 100644 index 803418c97e3..00000000000 --- a/source/smbd/password.c +++ /dev/null @@ -1,1572 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Password and authentication handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#if (defined(NETGROUP) && defined (AUTOMOUNT)) -#include "rpcsvc/ypclnt.h" -#endif - -extern int DEBUGLEVEL; -extern int Protocol; - -/* users from session setup */ -static pstring session_users=""; - -/* these are kept here to keep the string_combinations function simple */ -static char this_user[100]=""; -static char this_salt[100]=""; -static char this_crypted[100]=""; - -#ifdef SMB_PASSWD -/* Data to do lanman1/2 password challenge. */ -static unsigned char saved_challenge[8]; -static BOOL challenge_sent=False; - -/******************************************************************* -Get the next challenge value - no repeats. -********************************************************************/ -void generate_next_challenge(char *challenge) -{ - static int counter = 0; - struct timeval tval; - int v1,v2; - GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - E1(challenge,"SAMBA",(char *)saved_challenge); - memcpy(challenge,saved_challenge,8); - challenge_sent = True; -} - -/******************************************************************* -set the last challenge sent, usually from a password server -********************************************************************/ -BOOL set_challenge(char *challenge) -{ - memcpy(saved_challenge,challenge,8); - challenge_sent = True; - return(True); -} - -/******************************************************************* -get the last challenge sent -********************************************************************/ -BOOL last_challenge(char *challenge) -{ - if (!challenge_sent) return(False); - memcpy(challenge,saved_challenge,8); - return(True); -} -#endif - -/* this holds info on user ids that are already validated for this VC */ -static user_struct *validated_users = NULL; -static int num_validated_users = 0; - -/**************************************************************************** -check if a uid has been validated, and return an pointer to the user_struct -if it has. NULL if not. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. -****************************************************************************/ -user_struct *get_valid_user_struct(uint16 vuid) -{ - if(vuid == UID_FIELD_INVALID) - return NULL; - vuid -= VUID_OFFSET; - if((vuid >= (uint16)num_validated_users) || - (validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1)) - return NULL; - return &validated_users[vuid]; -} - -/**************************************************************************** -invalidate a uid -****************************************************************************/ -void invalidate_vuid(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - if(vuser == 0) - return; - - vuser->uid = -1; - vuser->gid = -1; - vuser->user_ngroups = 0; - if(vuser->user_groups && - (vuser->user_groups != (gid_t *)vuser->user_igroups)) - free(vuser->user_groups); - vuser->user_groups = NULL; - if(vuser->user_igroups) - free(vuser->user_igroups); - vuser->user_igroups = NULL; -} - - -/**************************************************************************** -return a validated username -****************************************************************************/ -char *validated_username(uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - if(vuser == 0) - return 0; - return(vuser->name); -} - -/**************************************************************************** -register a uid/name pair as being valid and that a valid password -has been given. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. -****************************************************************************/ -uint16 register_vuid(int uid,int gid, char *name,BOOL guest) -{ - user_struct *vuser; - -#if (defined(NETGROUP) && defined (AUTOMOUNT)) - int nis_error; /* returned by yp all functions */ - char *nis_result; /* yp_match inits this */ - int nis_result_len; /* and set this */ - char *nis_domain; /* yp_get_default_domain inits this */ - char *nis_map = (char *)lp_nis_home_map_name(); - int home_server_len; -#endif - struct passwd *pwfile; /* for getting real name from passwd file */ - int real_name_len; - - int i; - for(i = 0; i < num_validated_users; i++) { - vuser = &validated_users[i]; - if( vuser->uid == uid ) - return (uint16)(i + VUID_OFFSET); /* User already validated */ - } - - validated_users = (user_struct *)Realloc(validated_users, - sizeof(user_struct)* - (num_validated_users+1)); - - if (!validated_users) - { - DEBUG(0,("Failed to realloc users struct!\n")); - num_validated_users = 0; - return UID_FIELD_INVALID; - } - - vuser = &validated_users[num_validated_users]; - num_validated_users++; - - vuser->uid = uid; - vuser->gid = gid; - vuser->guest = guest; - strcpy(vuser->name,name); - - vuser->user_ngroups = 0; - vuser->user_groups = NULL; - vuser->user_igroups = NULL; - - /* Find all the groups this uid is in and store them. - Used by become_user() */ - setup_groups(name,uid,gid, - &vuser->user_ngroups, - &vuser->user_igroups, - &vuser->user_groups); - - DEBUG(3,("uid %d registered to name %s\n",uid,name)); - -#if (defined(NETGROUP) && defined (AUTOMOUNT)) - vuser->home_share = NULL; - DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n")); - vuser->home_share = Realloc(vuser->home_share, 32); - strcpy(vuser->home_share,"\\\\%L\\HOMES"); - - if (nis_error = yp_get_default_domain(&nis_domain)) - DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); - DEBUG(3, ("NIS Domain: %s\n", nis_domain)); - - if (nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name), - &nis_result, &nis_result_len)) - DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error))); - if (!nis_error && lp_nis_home_map()) { - home_server_len = strcspn(nis_result,":"); - DEBUG(3, ("NIS lookup succeeded\n\tHome server length: %d\n",home_server_len)); - vuser->home_share = (char *)Realloc(vuser->home_share, home_server_len+12); - DEBUG(3, ("\tAllocated %d bytes for HOMESHR\n",home_server_len+12 )); - strcpy(vuser->home_share,"\\\\"); - strncat(vuser->home_share, nis_result, home_server_len); - strcat(vuser->home_share,"\\homes"); - DEBUG(2,("\tUser = %s\n\tUID = %d\n\tNIS result = %s\n\tHOMESHR = %s\n", - vuser->name, vuser->uid, nis_result, vuser->home_share)); - } -#endif - - vuser->real_name = NULL; - DEBUG(3, ("Clearing default real name\n")); - vuser->real_name = Realloc(vuser->real_name, 15); - strcpy(vuser->real_name, "<Full Name>\0"); - if (lp_unix_realname()) { - pwfile=getpwnam(vuser->name); - DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos)); - real_name_len = strcspn(pwfile->pw_gecos, ","); - DEBUG(3, ("Real name length: %d\n", real_name_len)); - vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1); - strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len); - vuser->real_name[real_name_len]='\0'; - } - - return (uint16)((num_validated_users - 1) + VUID_OFFSET); -} - - -/**************************************************************************** -add a name to the session users list -****************************************************************************/ -void add_session_user(char *user) -{ - fstring suser; - StrnCpy(suser,user,sizeof(suser)-1); - - if (!Get_Pwnam(suser,True)) return; - - if (suser && *suser && !in_list(suser,session_users,False)) - { - if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) - DEBUG(1,("Too many session users??\n")); - else - { - strcat(session_users," "); - strcat(session_users,suser); - } - } -} - - -#ifdef NO_GETSPNAM -/* a fake shadow password routine which just fills a fake spwd struct - * with the sp_pwdp field. (sreiz@aie.nl) - */ -static struct spwd *getspnam(char *username) /* fake shadow password routine */ -{ - FILE *f; - char line[1024]; - static char pw[20]; - static struct spwd static_spwd; - - static_spwd.sp_pwdp=0; - if (!(f=fopen("/etc/master.passwd", "r"))) - return 0; - while (fgets(line, 1024, f)) { - if (!strncmp(line, username, strlen(username)) && - line[strlen(username)]==':') { /* found entry */ - char *p, *q; - - p=line+strlen(username)+1; - if ((q=strchr(p, ':'))) { - *q=0; - if (q-p+1>20) - break; - strcpy(pw, p); - static_spwd.sp_pwdp=pw; - } - break; - } - } - fclose(f); - if (static_spwd.sp_pwdp) - return &static_spwd; - return 0; -} -#endif - - -#ifdef OSF1_ENH_SEC -/**************************************************************************** -an enhanced crypt for OSF1 -****************************************************************************/ -static char *osf1_bigcrypt(char *password,char *salt1) -{ - static char result[AUTH_MAX_PASSWD_LENGTH] = ""; - char *p1; - char *p2=password; - char salt[3]; - int i; - int parts = strlen(password) / AUTH_CLEARTEXT_SEG_CHARS; - if (strlen(password)%AUTH_CLEARTEXT_SEG_CHARS) - parts++; - - StrnCpy(salt,salt1,2); - StrnCpy(result,salt1,2); - - for (i=0; i<parts;i++) - { - p1 = crypt(p2,salt); - strcat(result,p1+2); - StrnCpy(salt,&result[2+i*AUTH_CIPHERTEXT_SEG_CHARS],2); - p2 += AUTH_CLEARTEXT_SEG_CHARS; - } - - return(result); -} -#endif - - -/**************************************************************************** -update the enhanced security database. Only relevant for OSF1 at the moment. -****************************************************************************/ -static void update_protected_database( char *user, BOOL result) -{ -#ifdef OSF1_ENH_SEC - struct pr_passwd *mypasswd; - time_t starttime; - - mypasswd = getprpwnam (user); - starttime = time (NULL); - - if (result) - { - mypasswd->ufld.fd_slogin = starttime; - mypasswd->ufld.fd_nlogins = 0; - - putprpwnam(user,mypasswd); - - DEBUG(3,("Update protected database for Account %s after succesful connection\n",user)); - } - else - { - mypasswd->ufld.fd_ulogin = starttime; - mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1; - if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries ) - { - mypasswd->uflg.fg_lock = 0; - DEBUG(3,("Account is disabled -- see Account Administrator.\n")); - } - putprpwnam ( user , mypasswd ); - DEBUG(3,("Update protected database for Account %s after refusing connection\n",user)); - } -#else - DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result))); -#endif -} - - -#ifdef USE_PAM -/******************************************************************* -check on PAM authentication -********************************************************************/ - -/* We first need some helper functions */ -#include <security/pam_appl.h> -/* Static variables used to communicate between the conversation function - * and the server_login function - */ -static char *PAM_username; -static char *PAM_password; - -/* PAM conversation function - * Here we assume (for now, at least) that echo on means login name, and - * echo off means password. - */ -static int PAM_conv (int num_msg, - const struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) { - int count = 0, replies = 0; - struct pam_response *reply = NULL; - int size = sizeof(struct pam_response); - - #define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \ - if (!reply) return PAM_CONV_ERR; \ - size += sizeof(struct pam_response) - #define COPY_STRING(s) (s) ? strdup(s) : NULL - - for (count = 0; count < num_msg; count++) { - switch (msg[count]->msg_style) { - case PAM_PROMPT_ECHO_ON: - GET_MEM; - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_username); - /* PAM frees resp */ - break; - case PAM_PROMPT_ECHO_OFF: - GET_MEM; - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies++].resp = COPY_STRING(PAM_password); - /* PAM frees resp */ - break; - case PAM_TEXT_INFO: - /* ignore it... */ - break; - case PAM_ERROR_MSG: - default: - /* Must be an error of some sort... */ - free (reply); - return PAM_CONV_ERR; - } - } - if (reply) *resp = reply; - return PAM_SUCCESS; -} -static struct pam_conv PAM_conversation = { - &PAM_conv, - NULL -}; - - -static BOOL pam_auth(char *this_user,char *password) -{ - pam_handle_t *pamh; - int pam_error; - - /* Now use PAM to do authentication. For now, we won't worry about - * session logging, only authentication. Bail out if there are any - * errors. Since this is a limited protocol, and an even more limited - * function within a server speaking this protocol, we can't be as - * verbose as would otherwise make sense. - * Query: should we be using PAM_SILENT to shut PAM up? - */ - #define PAM_BAIL if (pam_error != PAM_SUCCESS) { \ - pam_end(pamh, 0); return False; \ - } - PAM_password = password; - PAM_username = this_user; - pam_error = pam_start("samba", this_user, &PAM_conversation, &pamh); - PAM_BAIL; - pam_error = pam_authenticate(pamh, 0); - PAM_BAIL; - /* It is not clear to me that account management is the right thing - * to do, but it is not clear that it isn't, either. This can be - * removed if no account management should be done. Alternately, - * put a pam_allow.so entry in /etc/pam.conf for account handling. */ - pam_error = pam_acct_mgmt(pamh, 0); - PAM_BAIL; - pam_end(pamh, PAM_SUCCESS); - /* If this point is reached, the user has been authenticated. */ - return(True); -} -#endif - - -#ifdef AFS_AUTH -/******************************************************************* -check on AFS authentication -********************************************************************/ -static BOOL afs_auth(char *this_user,char *password) -{ - long password_expires = 0; - char *reason; - - /* For versions of AFS prior to 3.3, this routine has few arguments, */ - /* but since I can't find the old documentation... :-) */ - setpag(); - if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG, - this_user, - (char *) 0, /* instance */ - (char *) 0, /* cell */ - password, - 0, /* lifetime, default */ - &password_expires, /*days 'til it expires */ - 0, /* spare 2 */ - &reason) == 0) - return(True); - return(False); -} -#endif - - -#ifdef DFS_AUTH - -sec_login_handle_t my_dce_sec_context; -int dcelogin_atmost_once = 0; - -/******************************************************************* -check on a DCE/DFS authentication -********************************************************************/ -static BOOL dfs_auth(char *this_user,char *password) -{ - error_status_t err; - int err2; - int prterr; - boolean32 password_reset; - sec_passwd_rec_t my_dce_password; - sec_login_auth_src_t auth_src = sec_login_auth_src_network; - unsigned char dce_errstr[dce_c_error_string_len]; - - /* - * We only go for a DCE login context if the given password - * matches that stored in the local password file.. - * Assumes local passwd file is kept in sync w/ DCE RGY! - */ - - if (!strcmp((char *)crypt(password,this_salt),this_crypted) || - dcelogin_atmost_once) - return(False); - - if (sec_login_setup_identity( - (unsigned char *)this_user, - sec_login_no_flags, - &my_dce_sec_context, - &err) == 0) - { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE Setup Identity for %s failed: %s\n", - this_user,dce_errstr)); - return(False); - } - - my_dce_password.version_number = sec_passwd_c_version_none; - my_dce_password.pepper = NULL; - my_dce_password.key.key_type = sec_passwd_plain; - my_dce_password.key.tagged_union.plain = (idl_char *)password; - - if (sec_login_valid_and_cert_ident(my_dce_sec_context, - &my_dce_password, - &password_reset, - &auth_src, - &err) == 0 ) - { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE Identity Validation failed for principal %s: %s\n", - this_user,dce_errstr)); - - return(False); - } - - sec_login_set_context(my_dce_sec_context, &err); - if (err != error_status_ok ) - { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE login failed for principal %s, cant set context: %s\n", - this_user,dce_errstr)); - sec_login_purge_context(my_dce_sec_context, &err); - return(False); - } - else - { - DEBUG(0,("DCE login succeeded for principal %s on pid %d\n", - this_user, getpid())); - } - - dcelogin_atmost_once = 1; - return (True); -} - -void dfs_unlogin(void) -{ - error_status_t err; - int err2; - unsigned char dce_errstr[dce_c_error_string_len]; - - sec_login_purge_context(my_dce_sec_context, &err); - if (err != error_status_ok ) - { - dce_error_inq_text(err, dce_errstr, &err2); - DEBUG(0,("DCE purge login context failed for server instance %d: %s\n", - getpid(), dce_errstr)); - } -} - -#endif - - -#ifdef LINUX_BIGCRYPT -/**************************************************************************** -an enhanced crypt for Linux to handle password longer than 8 characters -****************************************************************************/ -static int linux_bigcrypt(char *password,char *salt1, char *crypted) -{ -#define LINUX_PASSWORD_SEG_CHARS 8 - char salt[3]; - int i; - - StrnCpy(salt,salt1,2); - crypted +=2; - - for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { - char * p = crypt(password,salt) + 2; - if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) - return(0); - password += LINUX_PASSWORD_SEG_CHARS; - crypted += strlen(p); - } - - return(1); -} -#endif - - -/**************************************************************************** -apply a function to upper/lower case combinations -of a string and return true if one of them returns true. -try all combinations with N uppercase letters. -offset is the first char to try and change (start with 0) -it assumes the string starts lowercased -****************************************************************************/ -static BOOL string_combinations2(char *s,int offset,BOOL (*fn)(),int N) -{ - int len = strlen(s); - int i; - -#ifdef PASSWORD_LENGTH - len = MIN(len,PASSWORD_LENGTH); -#endif - - if (N <= 0 || offset >= len) - return(fn(s)); - - for (i=offset;i<(len-(N-1));i++) - { - char c = s[i]; - if (!islower(c)) continue; - s[i] = toupper(c); - if (string_combinations2(s,i+1,fn,N-1)) - return(True); - s[i] = c; - } - return(False); -} - -/**************************************************************************** -apply a function to upper/lower case combinations -of a string and return true if one of them returns true. -try all combinations with up to N uppercase letters. -offset is the first char to try and change (start with 0) -it assumes the string starts lowercased -****************************************************************************/ -static BOOL string_combinations(char *s,BOOL (*fn)(),int N) -{ - int n; - for (n=1;n<=N;n++) - if (string_combinations2(s,0,fn,n)) return(True); - return(False); -} - - - -/**************************************************************************** -core of password checking routine -****************************************************************************/ -BOOL password_check(char *password) -{ - -#ifdef USE_PAM -/* This falls through if the password check fails - - if NO_CRYPT is defined this causes an error msg - saying Warning - no crypt available - - if NO_CRYPT is NOT defined this is a potential security hole - as it may authenticate via the crypt call when PAM - settings say it should fail. - if (pam_auth(this_user,password)) return(True); -Hence we make a direct return to avoid a second chance!!! -*/ - return (pam_auth(this_user,password)); -#endif - -#ifdef AFS_AUTH - if (afs_auth(this_user,password)) return(True); -#endif - -#ifdef DFS_AUTH - if (dfs_auth(this_user,password)) return(True); -#endif - -#ifdef PWDAUTH - if (pwdauth(this_user,password) == 0) - return(True); -#endif - -#ifdef OSF1_ENH_SEC - return(strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); -#endif - -#ifdef ULTRIX_AUTH - return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0); -#endif - -#ifdef LINUX_BIGCRYPT - return(linux_bigcrypt(password,this_salt,this_crypted)); -#endif - -#ifdef NO_CRYPT - DEBUG(1,("Warning - no crypt available\n")); - return(False); -#else - return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0); -#endif -} - -#ifdef SMB_PASSWD -/**************************************************************************** -core of smb password checking routine. -****************************************************************************/ -BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8) -{ - /* Finish the encryption of part_passwd. */ - unsigned char p21[21]; - unsigned char p24[24]; - - if(part_passwd == NULL) - DEBUG(10,("No password set - allowing access\n")); - /* No password set - always true ! */ - if(part_passwd == NULL) - return 1; - - memset(p21,'\0',21); - memcpy(p21,part_passwd,16); - E_P24(p21, c8, p24); -#if DEBUG_PASSWORD - { - int i; - DEBUG(100,("Part password (P16) was |")); - for(i = 0; i < 16; i++) - DEBUG(100,("%X ", (unsigned char)part_passwd[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Password from client was |")); - for(i = 0; i < 24; i++) - DEBUG(100,("%X ", (unsigned char)password[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Given challenge was |")); - for(i = 0; i < 8; i++) - DEBUG(100,("%X ", (unsigned char)c8[i])); - DEBUG(100,("|\n")); - DEBUG(100,("Value from encryption was |")); - for(i = 0; i < 24; i++) - DEBUG(100,("%X ", (unsigned char)p24[i])); - DEBUG(100,("|\n")); - } -#endif - return (memcmp(p24, password, 24) == 0); -} -#endif - -/**************************************************************************** -check if a username/password is OK -****************************************************************************/ -BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) -{ - pstring pass2; - int level = lp_passwordlevel(); - struct passwd *pass; -#ifdef SMB_PASSWD - char challenge[8]; - struct smb_passwd *smb_pass; - BOOL challenge_done = False; -#endif - - if (password) password[pwlen] = 0; - -#ifdef SMB_PASSWD - if (pwlen == 24) - challenge_done = last_challenge(challenge); -#endif - -#if DEBUG_PASSWORD -#ifdef SMB_PASSWD - if (challenge_done) - { - int i; - DEBUG(100,("checking user=[%s] pass=[",user)); - for( i = 0; i < 24; i++) - DEBUG(100,("%0x ", (unsigned char)password[i])); - DEBUG(100,("]\n")); - } - else -#endif - DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); -#endif - - if (!password) - return(False); - - if (((!*password) || (!pwlen)) && !lp_null_passwords()) - return(False); - - if (pwd && !user) - { - pass = (struct passwd *) pwd; - user = pass->pw_name; - } - else - pass = Get_Pwnam(user,True); - -#ifdef SMB_PASSWD - - DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); - - if((pwlen == 24) && challenge_done) - { - DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); - - if (!pass) - { - DEBUG(3,("Couldn't find user %s\n",user)); - return(False); - } - - smb_pass = get_smbpwnam(user); - if(!smb_pass) - { - DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); - return(False); - } - - /* Ensure the uid's match */ - if(smb_pass->smb_userid != pass->pw_uid) - { - DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); - return(False); - } - - if(Protocol >= PROTOCOL_NT1) - { - /* We have the NT MD4 hash challenge available - see if we can - use it (ie. does it exist in the smbpasswd file). - */ - if(smb_pass->smb_nt_passwd != NULL) - { - DEBUG(4,("Checking NT MD4 password\n")); - if(smb_password_check(password, - smb_pass->smb_nt_passwd, - (char *)challenge)) - { - update_protected_database(user,True); - return(True); - } - DEBUG(4,("NT MD4 password check failed\n")); - } - } - - /* Try against the lanman password */ - - if (smb_password_check(password, - smb_pass->smb_passwd, - (char *)challenge)) { - update_protected_database(user,True); - return(True); - } - - DEBUG(3,("Error smb_password_check failed\n")); - } -#endif - - DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); - - if (!pass) - { - DEBUG(3,("Couldn't find user %s\n",user)); - return(False); - } - -#ifdef SHADOW_PWD - { - struct spwd *spass; - - /* many shadow systems require you to be root to get the password, - in most cases this should already be the case when this - function is called, except perhaps for IPC password changing - requests */ - - spass = getspnam(pass->pw_name); - if (spass && spass->sp_pwdp) - pass->pw_passwd = spass->sp_pwdp; - } -#endif - -#ifdef SecureWare - { - struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); - if (pr_pw && pr_pw->ufld.fd_encrypt) - pass->pw_passwd = pr_pw->ufld.fd_encrypt; - } -#endif - -#ifdef HPUX_10_TRUSTED - { - struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); - if (pr_pw && pr_pw->ufld.fd_encrypt) - pass->pw_passwd = pr_pw->ufld.fd_encrypt; - } -#endif - -#ifdef OSF1_ENH_SEC - { - struct pr_passwd *mypasswd; - DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user)); - mypasswd = getprpwnam (user); - if ( mypasswd ) - { - strcpy(pass->pw_name,mypasswd->ufld.fd_name); - strcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); - } - else - { - DEBUG(5,("No entry for user %s in protected database !\n",user)); - return(False); - } - } -#endif - -#ifdef ULTRIX_AUTH - { - AUTHORIZATION *ap = getauthuid( pass->pw_uid ); - if (ap) - { - strcpy( pass->pw_passwd, ap->a_password ); - endauthent(); - } - } -#endif - - /* extract relevant info */ - strcpy(this_user,pass->pw_name); - strcpy(this_salt,pass->pw_passwd); - strcpy(this_crypted,pass->pw_passwd); - - if (!*this_crypted) { - if (!lp_null_passwords()) { - DEBUG(2,("Disallowing access to %s due to null password\n",this_user)); - return(False); - } -#ifndef PWDAUTH - if (!*password) { - DEBUG(3,("Allowing access to %s with null password\n",this_user)); - return(True); - } -#endif - } - - /* try it as it came to us */ - if (password_check(password)) - { - update_protected_database(user,True); - return(True); - } - - /* if the password was given to us with mixed case then we don't - need to proceed as we know it hasn't been case modified by the - client */ - if (strhasupper(password) && strhaslower(password)) - return(False); - - /* make a copy of it */ - StrnCpy(pass2,password,sizeof(pstring)-1); - - /* try all lowercase */ - strlower(password); - if (password_check(password)) - { - update_protected_database(user,True); - return(True); - } - - /* give up? */ - if(level < 1) - { - update_protected_database(user,False); - - /* restore it */ - strcpy(password,pass2); - - return(False); - } - - /* last chance - all combinations of up to level chars upper! */ - strlower(password); - - if (string_combinations(password,password_check,level)) - { - update_protected_database(user,True); - return(True); - } - - update_protected_database(user,False); - - /* restore it */ - strcpy(password,pass2); - - return(False); -} - - - -/**************************************************************************** -check if a username is valid -****************************************************************************/ -BOOL user_ok(char *user,int snum) -{ - pstring valid, invalid; - BOOL ret; - - StrnCpy(valid, lp_valid_users(snum), sizeof(pstring)); - StrnCpy(invalid, lp_invalid_users(snum), sizeof(pstring)); - - string_sub(valid,"%S",lp_servicename(snum)); - string_sub(invalid,"%S",lp_servicename(snum)); - - ret = !user_in_list(user,invalid); - - if (ret && valid && *valid) - ret = user_in_list(user,valid); - - if (ret && lp_onlyuser(snum)) { - char *user_list = lp_username(snum); - string_sub(user_list,"%S",lp_servicename(snum)); - ret = user_in_list(user,user_list); - } - - return(ret); -} - - - - -/**************************************************************************** -validate a group username entry. Return the username or NULL -****************************************************************************/ -static char *validate_group(char *group,char *password,int pwlen,int snum) -{ -#ifdef NETGROUP - { - char *host, *user, *domain; - setnetgrent(group); - while (getnetgrent(&host, &user, &domain)) { - if (user) { - if (user_ok(user, snum) && - password_ok(user,password,pwlen,NULL)) { - endnetgrent(); - return(user); - } - } - } - endnetgrent(); - } -#endif - -#if HAVE_GETGRNAM - { - struct group *gptr = (struct group *)getgrnam(group); - char **member; - if (gptr) - { - member = gptr->gr_mem; - while (member && *member) - { - static fstring name; - strcpy(name,*member); - if (user_ok(name,snum) && - password_ok(name,password,pwlen,NULL)) - return(&name[0]); - member++; - } -#ifdef GROUP_CHECK_PWENT - { - struct passwd *pwd; - static fstring tm; - - setpwent (); - while (pwd = getpwent ()) { - if (*(pwd->pw_passwd) && pwd->pw_gid == gptr->gr_gid) { - /* This Entry have PASSWORD and same GID then check pwd */ - if (password_ok(NULL, password, pwlen, pwd)) { - strcpy(tm, pwd->pw_name); - endpwent (); - return tm; - } - } - } - endpwent (); - } -#endif /* GROUP_CHECK_PWENT */ - } - } -#endif - return(NULL); -} - - - -/**************************************************************************** -check for authority to login to a service with a given username/password -****************************************************************************/ -BOOL authorise_login(int snum,char *user,char *password, int pwlen, - BOOL *guest,BOOL *force,uint16 vuid) -{ - BOOL ok = False; - - *guest = False; - -#if DEBUG_PASSWORD - DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password)); -#endif - - /* there are several possabilities: - 1) login as the given user with given password - 2) login as a previously registered username with the given password - 3) login as a session list username with the given password - 4) login as a previously validated user/password pair - 5) login as the "user =" user with given password - 6) login as the "user =" user with no password (guest connection) - 7) login as guest user with no password - - if the service is guest_only then steps 1 to 5 are skipped - */ - - if (GUEST_ONLY(snum)) *force = True; - - if (!(GUEST_ONLY(snum) && GUEST_OK(snum))) - { - - user_struct *vuser = get_valid_user_struct(vuid); - - /* check the given username and password */ - if (!ok && (*user) && user_ok(user,snum)) { - ok = password_ok(user,password, pwlen, NULL); - if (ok) DEBUG(3,("ACCEPTED: given username password ok\n")); - } - - /* check for a previously registered guest username */ - if (!ok && (vuser != 0) && vuser->guest) { - if (user_ok(vuser->name,snum) && - password_ok(vuser->name, password, pwlen, NULL)) { - strcpy(user, vuser->name); - vuser->guest = False; - DEBUG(3,("ACCEPTED: given password with registered user %s\n", user)); - ok = True; - } - } - - - /* now check the list of session users */ - if (!ok) - { - char *auser; - char *user_list = strdup(session_users); - if (!user_list) return(False); - - for (auser=strtok(user_list,LIST_SEP); - !ok && auser; - auser = strtok(NULL,LIST_SEP)) - { - fstring user2; - strcpy(user2,auser); - if (!user_ok(user2,snum)) continue; - - if (password_ok(user2,password, pwlen, NULL)) { - ok = True; - strcpy(user,user2); - DEBUG(3,("ACCEPTED: session list username and given password ok\n")); - } - } - free(user_list); - } - - /* check for a previously validated username/password pair */ - if (!ok && !lp_revalidate(snum) && - (vuser != 0) && !vuser->guest && - user_ok(vuser->name,snum)) { - strcpy(user,vuser->name); - *guest = False; - DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n")); - ok = True; - } - - /* check for a rhosts entry */ - if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) { - ok = True; - DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n")); - } - - /* check the user= fields and the given password */ - if (!ok && lp_username(snum)) { - char *auser; - pstring user_list; - StrnCpy(user_list,lp_username(snum),sizeof(pstring)); - - string_sub(user_list,"%S",lp_servicename(snum)); - - for (auser=strtok(user_list,LIST_SEP); - auser && !ok; - auser = strtok(NULL,LIST_SEP)) - { - if (*auser == '@') - { - auser = validate_group(auser+1,password,pwlen,snum); - if (auser) - { - ok = True; - strcpy(user,auser); - DEBUG(3,("ACCEPTED: group username and given password ok\n")); - } - } - else - { - fstring user2; - strcpy(user2,auser); - if (user_ok(user2,snum) && - password_ok(user2,password,pwlen,NULL)) - { - ok = True; - strcpy(user,user2); - DEBUG(3,("ACCEPTED: user list username and given password ok\n")); - } - } - } - } - } /* not guest only */ - - /* check for a normal guest connection */ - if (!ok && GUEST_OK(snum)) - { - fstring guestname; - StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1); - if (Get_Pwnam(guestname,True)) - { - strcpy(user,guestname); - ok = True; - DEBUG(3,("ACCEPTED: guest account and guest ok\n")); - } - else - DEBUG(0,("Invalid guest account %s??\n",guestname)); - *guest = True; - *force = True; - } - - if (ok && !user_ok(user,snum)) - { - DEBUG(0,("rejected invalid user %s\n",user)); - ok = False; - } - - return(ok); -} - - -/**************************************************************************** -read the a hosts.equiv or .rhosts file and check if it -allows this user from this machine -****************************************************************************/ -static BOOL check_user_equiv(char *user, char *remote, char *equiv_file) -{ - pstring buf; - int plus_allowed = 1; - char *file_host; - char *file_user; - FILE *fp = fopen(equiv_file, "r"); - DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file)); - if (! fp) return False; - while(fgets(buf, sizeof(buf), fp)) - { - trim_string(buf," "," "); - - if (buf[0] != '#' && buf[0] != '\n') - { - BOOL is_group = False; - int plus = 1; - char *bp = buf; - if (strcmp(buf, "NO_PLUS\n") == 0) - { - DEBUG(6, ("check_user_equiv NO_PLUS\n")); - plus_allowed = 0; - } - else { - if (buf[0] == '+') - { - bp++; - if (*bp == '\n' && plus_allowed) - { - /* a bare plus means everbody allowed */ - DEBUG(6, ("check_user_equiv everybody allowed\n")); - fclose(fp); - return True; - } - } - else if (buf[0] == '-') - { - bp++; - plus = 0; - } - if (*bp == '@') - { - is_group = True; - bp++; - } - file_host = strtok(bp, " \t\n"); - file_user = strtok(NULL, " \t\n"); - DEBUG(7, ("check_user_equiv %s %s\n", file_host, file_user)); - if (file_host && *file_host) - { - BOOL host_ok = False; - -#ifdef NETGROUP - if (is_group) - { - static char *mydomain = NULL; - if (!mydomain) - yp_get_default_domain(&mydomain); - if (mydomain && innetgr(file_host,remote,user,mydomain)) - host_ok = True; - } -#else - if (is_group) - { - DEBUG(1,("Netgroups not configured - add -DNETGROUP and recompile\n")); - continue; - } -#endif - - /* is it this host */ - /* the fact that remote has come from a call of gethostbyaddr - * means that it may have the fully qualified domain name - * so we could look up the file version to get it into - * a canonical form, but I would rather just type it - * in full in the equiv file - */ - if (!host_ok && !is_group && strequal(remote, file_host)) - host_ok = True; - - if (!host_ok) - continue; - - /* is it this user */ - if (file_user == 0 || strequal(user, file_user)) - { - fclose(fp); - DEBUG(5, ("check_user_equiv matched %s%s %s\n", - (plus ? "+" : "-"), file_host, - (file_user ? file_user : ""))); - return (plus ? True : False); - } - } - } - } - } - fclose(fp); - return False; -} - - -/**************************************************************************** -check for a possible hosts equiv or rhosts entry for the user -****************************************************************************/ -BOOL check_hosts_equiv(char *user) -{ - char *fname = NULL; - pstring rhostsfile; - struct passwd *pass = Get_Pwnam(user,True); - - if (!pass) - return(False); - - fname = lp_hosts_equiv(); - - /* note: don't allow hosts.equiv on root */ - if (fname && *fname && (pass->pw_uid != 0)) - { - if (check_user_equiv(user,client_name(),fname)) - return(True); - } - - if (lp_use_rhosts()) - { - char *home = get_home_dir(user); - if (home) - { - sprintf(rhostsfile, "%s/.rhosts", home); - if (check_user_equiv(user,client_name(),rhostsfile)) - return(True); - } - } - - return(False); -} - - -int password_client = -1; -static fstring pserver; - -/**************************************************************************** -attempted support for server level security -****************************************************************************/ -BOOL server_cryptkey(char *buf) -{ - pstring inbuf,outbuf; - fstring pass_protocol; - extern fstring remote_machine; - char *p; - int len; - fstring desthost; - struct in_addr dest_ip; - int port = SMB_PORT; - BOOL ret; - - if (password_client >= 0) - close(password_client); - password_client = -1; - - if (Protocol < PROTOCOL_NT1) { - strcpy(pass_protocol,"LM1.2X002"); - } else { - strcpy(pass_protocol,"NT LM 0.12"); - } - - bzero(inbuf,sizeof(inbuf)); - bzero(outbuf,sizeof(outbuf)); - - for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { - strcpy(desthost,p); - standard_sub_basic(desthost); - strupper(desthost); - - dest_ip = *interpret_addr2(desthost); - if (zero_ip(dest_ip)) { - DEBUG(1,("Can't resolve address for %s\n",p)); - continue; - } - - if (ismyip(dest_ip)) { - DEBUG(1,("Password server loop - disabling password server %s\n",p)); - continue; - } - - password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT); - if (password_client >= 0) { - DEBUG(3,("connected to password server %s\n",p)); - StrnCpy(pserver,p,sizeof(pserver)-1); - break; - } - } - - if (password_client < 0) { - DEBUG(1,("password server not available\n")); - return(False); - } - - - /* send a session request (RFC 8002) */ - - /* put in the destination name */ - len = 4; - p = outbuf+len; - name_mangle(desthost,p,' '); - len += name_len(p); - - /* and my name */ - p = outbuf+len; - name_mangle(remote_machine,p,' '); - len += name_len(p); - - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(password_client,outbuf); - - - if (!receive_smb(password_client,inbuf,5000) || - CVAL(inbuf,0) != 0x82) { - DEBUG(1,("%s rejected the session\n",pserver)); - close(password_client); password_client = -1; - return(False); - } - - DEBUG(3,("got session\n")); - - bzero(outbuf,smb_size); - - /* setup the protocol string */ - set_message(outbuf,0,strlen(pass_protocol)+2,True); - p = smb_buf(outbuf); - *p++ = 2; - strcpy(p,pass_protocol); - - CVAL(outbuf,smb_com) = SMBnegprot; - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); - - send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); - - if (!ret || CVAL(inbuf,smb_rcls) || SVAL(inbuf,smb_vwv0)) { - DEBUG(1,("%s rejected the protocol\n",pserver)); - close(password_client); password_client= -1; - return(False); - } - - if (!(CVAL(inbuf,smb_vwv1) & 1)) { - DEBUG(1,("%s isn't in user level security mode\n",pserver)); - close(password_client); password_client= -1; - return(False); - } - - memcpy(buf,inbuf,smb_len(inbuf)+4); - - DEBUG(3,("password server OK\n")); - - return(True); -} - -/**************************************************************************** -attempted support for server level security -****************************************************************************/ -BOOL server_validate(char *buf) -{ - pstring inbuf,outbuf; - BOOL ret; - - if (password_client < 0) { - DEBUG(1,("%s not connected\n",pserver)); - return(False); - } - - bzero(inbuf,sizeof(inbuf)); - memcpy(outbuf,buf,sizeof(outbuf)); - - /* send a session setup command */ - CVAL(outbuf,smb_flg) = 0x8; - SSVAL(outbuf,smb_flg2,0x1); - CVAL(outbuf,smb_vwv0) = 0xFF; - - set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False); - - SCVAL(inbuf,smb_rcls,1); - - send_smb(password_client,outbuf); - ret = receive_smb(password_client,inbuf,5000); - - if (!ret || CVAL(inbuf,smb_rcls) != 0) { - DEBUG(1,("password server %s rejected the password\n",pserver)); - return(False); - } - - /* if logged in as guest then reject */ - if ((SVAL(inbuf,smb_vwv2) & 1) != 0) { - DEBUG(1,("password server %s gave us guest only\n",pserver)); - return(False); - } - - DEBUG(3,("password server %s accepted the password\n",pserver)); - -#if !KEEP_PASSWORD_SERVER_OPEN - close(password_client); password_client= -1; -#endif - - return(True); -} - - diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c deleted file mode 100644 index a294ee4f491..00000000000 --- a/source/smbd/pipes.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Pipe SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - This file handles reply_ calls on named pipes that the server - makes to handle specific protocols -*/ - - -#include "includes.h" -#include "trans2.h" - -#define PIPE "\\PIPE\\" -#define PIPELEN strlen(PIPE) - -#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024)) - -/* look in server.c for some explanation of these variables */ -extern int Protocol; -extern int DEBUGLEVEL; -extern int chain_fnum; -extern char magic_char; -extern connection_struct Connections[]; -extern files_struct Files[]; -extern BOOL case_sensitive; -extern pstring sesssetup_user; -extern int Client; -extern fstring myworkgroup; - -/* this macro should always be used to extract an fnum (smb_fid) from -a packet to ensure chaining works correctly */ -#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) - -char * known_pipes [] = -{ - "lsarpc", - NULL -}; - -/**************************************************************************** - reply to an open and X on a named pipe - - In fact what we do is to open a regular file with the same name in - /tmp. This can then be closed as normal. Reading and writing won't - make much sense, but will do *something*. The real reason for this - support is to be able to do transactions on them (well, on lsarpc - for domain login purposes...). - - This code is basically stolen from reply_open_and_X with some - wrinkles to handle pipes. -****************************************************************************/ -int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - pstring fname; - int cnum = SVAL(inbuf,smb_tid); - int fnum = -1; - int smb_mode = SVAL(inbuf,smb_vwv3); - int smb_attr = SVAL(inbuf,smb_vwv5); -#if 0 - int open_flags = SVAL(inbuf,smb_vwv2); - int smb_sattr = SVAL(inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); -#endif - int smb_ofun = SVAL(inbuf,smb_vwv8); - int unixmode; - int size=0,fmode=0,mtime=0,rmode=0; - struct stat sbuf; - int smb_action = 0; - int i; - - /* XXXX we need to handle passed times, sattr and flags */ - strcpy(fname,smb_buf(inbuf)); - - /* If the name doesn't start \PIPE\ then this is directed */ - /* at a mailslot or something we really, really don't understand, */ - /* not just something we really don't understand. */ - if ( strncmp(fname,PIPE,PIPELEN) != 0 ) - return(ERROR(ERRSRV,ERRaccess)); - - DEBUG(4,("Opening pipe %s.\n", fname)); - - /* Strip \PIPE\ off the name. */ - strcpy(fname,smb_buf(inbuf) + PIPELEN); - - /* See if it is one we want to handle. */ - for( i = 0; known_pipes[i] ; i++ ) - if( strcmp(fname,known_pipes[i]) == 0 ) - break; - - if ( known_pipes[i] == NULL ) - return(ERROR(ERRSRV,ERRaccess)); - - /* Known pipes arrive with DIR attribs. Remove it so a regular file */ - /* can be opened and add it in after the open. */ - DEBUG(3,("Known pipe %s opening.\n",fname)); - smb_attr &= ~aDIR; - Connections[cnum].read_only = 0; - smb_ofun |= 0x10; /* Add Create it not exists flag */ - - unix_convert(fname,cnum,0); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - unixmode = unix_mode(cnum,smb_attr); - - open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - &rmode,&smb_action); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - /* Prepare the reply */ - set_message(outbuf,15,0,True); - - /* Put things back the way they were. */ - Connections[cnum].read_only = 1; - - /* Mark the opened file as an existing named pipe in message mode. */ - SSVAL(outbuf,smb_vwv9,2); - SSVAL(outbuf,smb_vwv10,0xc700); - if (rmode == 2) - { - DEBUG(4,("Resetting open result to open from create.\n")); - rmode = 1; - } - - SSVAL(outbuf,smb_vwv2,fnum); - SSVAL(outbuf,smb_vwv3,fmode); - put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,size); - SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,smb_action); - - chain_fnum = fnum; - - DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n", - fname, fnum, Files[fnum].name)); - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - api_LsarpcSNPHS - - SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here, - so just blithely return True. This is really only for NT domain stuff, - we we're only handling that - don't assume Samba now does complete - named pipe handling. -****************************************************************************/ -BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 id; - - id = param[0] + (param[1] << 8); - DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id)); - return(True); -} - - -/**************************************************************************** - api_LsarpcTNP - - TransactNamedPipe on \PIPE\lsarpc. -****************************************************************************/ -static void LsarpcTNP1(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1, dword2; - char pname[] = "\\PIPE\\lsass"; - - /* All kinds of mysterious numbers here */ - *rdata_len = 68; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - dword2 = IVAL(data,0x10); - - SIVAL(*rdata,0,0xc0005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x44); - SIVAL(*rdata,0xC,dword1); - - SIVAL(*rdata,0x10,dword2); - SIVAL(*rdata,0x14,0x15); - SSVAL(*rdata,0x18,sizeof(pname)); - strcpy(*rdata + 0x1a,pname); - SIVAL(*rdata,0x28,1); - memcpy(*rdata + 0x30, data + 0x34, 0x14); -} - -static void LsarpcTNP2(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - - /* All kinds of mysterious numbers here */ - *rdata_len = 48; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x30); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x18); - SIVAL(*rdata,0x1c,0x44332211); - SIVAL(*rdata,0x20,0x88776655); - SIVAL(*rdata,0x24,0xCCBBAA99); - SIVAL(*rdata,0x28,0x11FFEEDD); -} - -static void LsarpcTNP3(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - uint16 word1; - char * workgroup = myworkgroup; - int wglen = strlen(workgroup); - int i; - - /* All kinds of mysterious numbers here */ - *rdata_len = 90 + 2 * wglen; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - word1 = SVAL(data,0x2C); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x60); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x48); - SSVAL(*rdata,0x18,0x5988); /* This changes */ - SSVAL(*rdata,0x1A,0x15); - SSVAL(*rdata,0x1C,word1); - SSVAL(*rdata,0x20,6); - SSVAL(*rdata,0x22,8); - SSVAL(*rdata,0x24,0x8E8); /* So does this */ - SSVAL(*rdata,0x26,0x15); - SSVAL(*rdata,0x28,0x4D48); /* And this */ - SSVAL(*rdata,0x2A,0x15); - SIVAL(*rdata,0x2C,4); - SIVAL(*rdata,0x34,wglen); - for ( i = 0 ; i < wglen ; i++ ) - (*rdata)[0x38 + i * 2] = workgroup[i]; - - /* Now fill in the rest */ - i = 0x38 + wglen * 2; - SSVAL(*rdata,i,0x648); - SIVAL(*rdata,i+2,4); - SIVAL(*rdata,i+6,0x401); - SSVAL(*rdata,i+0xC,0x500); - SIVAL(*rdata,i+0xE,0x15); - SIVAL(*rdata,i+0x12,0x2372FE1); - SIVAL(*rdata,i+0x16,0x7E831BEF); - SIVAL(*rdata,i+0x1A,0x4B454B2); -} - -static void LsarpcTNP4(char *data,char **rdata, int *rdata_len) -{ - uint32 dword1; - - /* All kinds of mysterious numbers here */ - *rdata_len = 48; - *rdata = REALLOC(*rdata,*rdata_len); - - dword1 = IVAL(data,0xC); - - SIVAL(*rdata,0,0x03020005); - SIVAL(*rdata,4,0x10); - SIVAL(*rdata,8,0x30); - SIVAL(*rdata,0xC,dword1); - SIVAL(*rdata,0x10,0x18); -} - - -BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint32 id,id2; - - id = IVAL(data,0); - - DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id)); - switch (id) - { - case 0xb0005: - LsarpcTNP1(data,rdata,rdata_len); - break; - - case 0x03000005: - id2 = IVAL(data,8); - DEBUG(4,("\t- Suboperation %lx\n",id2)); - switch (id2 & 0xF) - { - case 8: - LsarpcTNP2(data,rdata,rdata_len); - break; - - case 0xC: - LsarpcTNP4(data,rdata,rdata_len); - break; - - case 0xE: - LsarpcTNP3(data,rdata,rdata_len); - break; - } - break; - } - return(True); -} diff --git a/source/smbd/predict.c b/source/smbd/predict.c deleted file mode 100644 index 691d8fbb4e0..00000000000 --- a/source/smbd/predict.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - file read prediction routines - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - - -/* variables used by the read prediction module */ -static int rp_fd = -1; -static int rp_offset = 0; -static int rp_length = 0; -static int rp_alloced = 0; -static int rp_predict_fd = -1; -static int rp_predict_offset = 0; -static int rp_predict_length = 0; -static int rp_timeout = 5; -static time_t rp_time = 0; -static char *rp_buffer = NULL; -static BOOL predict_skip=False; -time_t smb_last_time=(time_t)0; - -/**************************************************************************** -handle read prediction on a file -****************************************************************************/ -int read_predict(int fd,int offset,char *buf,char **ptr,int num) -{ - int ret = 0; - int possible = rp_length - (offset - rp_offset); - - possible = MIN(possible,num); - - /* give data if possible */ - if (fd == rp_fd && - offset >= rp_offset && - possible>0 && - smb_last_time-rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } - - if (ret == num) { - predict_skip = True; - } else { - predict_skip = False; - - /* prepare the next prediction */ - rp_predict_fd = fd; - rp_predict_offset = offset + num; - rp_predict_length = num; - } - - if (ret < 0) ret = 0; - - return(ret); -} - -/**************************************************************************** -pre-read some data -****************************************************************************/ -void do_read_prediction() -{ - static int readsize = 0; - - if (predict_skip) return; - - if (rp_predict_fd == -1) - return; - - rp_fd = rp_predict_fd; - rp_offset = rp_predict_offset; - rp_length = 0; - - rp_predict_fd = -1; - - if (readsize == 0) { - readsize = lp_readsize(); - readsize = MAX(readsize,1024); - } - - rp_predict_length = MIN(rp_predict_length,2*readsize); - rp_predict_length = MAX(rp_predict_length,1024); - rp_offset = (rp_offset/1024)*1024; - rp_predict_length = (rp_predict_length/1024)*1024; - - if (rp_predict_length > rp_alloced) - { - rp_buffer = Realloc(rp_buffer,rp_predict_length); - rp_alloced = rp_predict_length; - if (!rp_buffer) - { - DEBUG(0,("can't allocate read-prediction buffer\n")); - rp_predict_fd = -1; - rp_fd = -1; - rp_alloced = 0; - return; - } - } - - if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) { - rp_fd = -1; - rp_predict_fd = -1; - return; - } - - rp_length = read(rp_fd,rp_buffer,rp_predict_length); - rp_time = time(NULL); - if (rp_length < 0) - rp_length = 0; -} - -/**************************************************************************** -invalidate read-prediction on a fd -****************************************************************************/ -void invalidate_read_prediction(int fd) -{ - if (rp_fd == fd) - rp_fd = -1; - if (rp_predict_fd == fd) - rp_predict_fd = -1; -} - diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c deleted file mode 100644 index a1d29bcd12e..00000000000 --- a/source/smbd/quotas.c +++ /dev/null @@ -1,445 +0,0 @@ -#ifdef QUOTAS -/* - Unix SMB/Netbios implementation. - Version 1.9. - support for quotas - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -/* - * This is one of the most system dependent parts of Samba, and its - * done a litle differently. Each system has its own way of doing - * things :-( - */ - -#include "includes.h" - -extern int DEBUGLEVEL; - -#ifdef LINUX - -#include <sys/types.h> -#include <asm/types.h> -#include <sys/quota.h> - -#include <mntent.h> -#include <linux/unistd.h> - -_syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr); - -/**************************************************************************** -try to get the disk space from disk quotas (LINUX version) -****************************************************************************/ - -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t euser_id; - int r; - char dev_disk[256]; - struct dqblk D; - struct stat S; - FILE *fp; - struct mntent *mnt; - int devno; - int found; - - /* find the block device file */ - - if ( stat(path, &S) == -1 ) { - return(False) ; - } - - devno = S.st_dev ; - - fp = setmntent(MOUNTED,"r"); - found = False ; - - while ((mnt = getmntent(fp))) { - if ( stat(mnt->mnt_dir,&S) == -1 ) - continue ; - if (S.st_dev == devno) { - found = True ; - break ; - } - } - endmntent(fp) ; - - if (!found) { - return(False); - } - - euser_id=geteuid(); - seteuid(0); - r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D); - seteuid(euser_id); - - /* Use softlimit to determine disk space, except when it has been exceeded */ - *bsize = 1024; - if (r) - { - if (errno == EDQUOT) - { - *dfree =0; - *dsize =D.dqb_curblocks; - return (True); - } - else return(False); - } - /* Use softlimit to determine disk space, except when it has been exceeded */ - if ( - (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) || - (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) || - (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) || - (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit) - ) - { - *dfree = 0; - *dsize = D.dqb_curblocks; - } - else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0) - { - return(False); - } - else { - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - } - return (True); -} - -#elif defined(CRAY) - -#include <sys/quota.h> -#include <mntent.h> - -/**************************************************************************** -try to get the disk space from disk quotas (CRAY VERSION) -****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - struct mntent *mnt; - FILE *fd; - struct stat sbuf; - dev_t devno ; - static dev_t devno_cached = 0 ; - static char name[MNTMAXSTR] ; - struct q_request request ; - struct qf_header header ; - static int quota_default = 0 ; - int found ; - - if ( stat(path,&sbuf) == -1 ) - return(False) ; - - devno = sbuf.st_dev ; - - if ( devno != devno_cached ) { - - devno_cached = devno ; - - if ((fd = setmntent(KMTAB)) == NULL) - return(False) ; - - found = False ; - - while ((mnt = getmntent(fd)) != NULL) { - - if ( stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - - if (sbuf.st_dev == devno) { - - found = True ; - break ; - - } - - } - - strcpy(name,mnt->mnt_dir) ; - endmntent(fd) ; - - if ( ! found ) - return(False) ; - } - - request.qf_magic = QF_MAGIC ; - request.qf_entry.id = geteuid() ; - - if (quotactl(name, Q_GETQUOTA, &request) == -1) - return(False) ; - - if ( ! request.user ) - return(False) ; - - if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) { - - if ( ! quota_default ) { - - if ( quotactl(name, Q_GETHEADER, &header) == -1 ) - return(False) ; - else - quota_default = header.user_h.def_fq ; - } - - *dfree = quota_default ; - - }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) { - - *dfree = 0 ; - - }else{ - - *dfree = request.qf_entry.user_q.f_quota ; - - } - - *dsize = request.qf_entry.user_q.f_use ; - - if ( *dfree ) - *dfree -= *dsize ; - - if ( *dfree < 0 ) - *dfree = 0 ; - - *bsize = 4096 ; /* Cray blocksize */ - - return(True) ; - -} - - -#elif defined(SUNOS5) || defined(SUNOS4) - -#include <fcntl.h> -#if defined(SUNOS5) -#include <sys/fs/ufs_quota.h> -#include <sys/mnttab.h> -#else /* defined(SUNOS4) */ -#include <ufs/quota.h> -#include <mntent.h> -#endif - -/**************************************************************************** -try to get the disk space from disk quotas (solaris 2 version) -****************************************************************************/ -/* Quota code by Peter Urbanec (amiga@cse.unsw.edu.au) */ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t user_id, euser_id; - int ret; - struct dqblk D; -#if defined(SUNOS5) - struct quotctl command; - int file; - struct mnttab mnt; - static char name[MNT_LINE_MAX] ; -#else - struct mntent *mnt; - static char name[MNTMAXSTR] ; -#endif - FILE *fd; - struct stat sbuf; - dev_t devno ; - static dev_t devno_cached = 0 ; - int found ; - - if ( stat(path,&sbuf) == -1 ) - return(False) ; - - devno = sbuf.st_dev ; - DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%o\n", path,devno)); - if ( devno != devno_cached ) { - devno_cached = devno ; -#if defined(SUNOS5) - if ((fd = fopen(MNTTAB, "r")) == NULL) - return(False) ; - - found = False ; - while (getmntent(fd, &mnt) == 0) { - if ( stat(mnt.mnt_mountp,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", - mnt.mnt_mountp,sbuf.st_dev)); - if (sbuf.st_dev == devno) { - found = True ; - break ; - } - } - - strcpy(name,mnt.mnt_mountp) ; - strcat(name,"/quotas") ; - fclose(fd) ; -#else - if ((fd = setmntent(MOUNTED, "r")) == NULL) - return(False) ; - - found = False ; - while ((mnt = getmntent(fd)) != NULL) { - if ( stat(mnt->mnt_dir,&sbuf) == -1 ) - continue ; - DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", - mnt->mnt_dir,sbuf.st_dev)); - if (sbuf.st_dev == devno) { - found = True ; - break ; - } - } - - strcpy(name,mnt->mnt_fsname) ; - endmntent(fd) ; -#endif - - if ( ! found ) - return(False) ; - } - - euser_id = geteuid(); - user_id = getuid(); - - setuid(0); /* Solaris seems to want to give info only to super-user */ - seteuid(0); - -#if defined(SUNOS5) - DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name)); - if((file=open(name, O_RDONLY))<0) { - setuid(user_id); /* Restore the original UID status */ - seteuid(euser_id); - return(False); - } - command.op = Q_GETQUOTA; - command.uid = euser_id; - command.addr = (caddr_t) &D; - ret = ioctl(file, Q_QUOTACTL, &command); - close(file); -#else - DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name)); - ret = quotactl(Q_GETQUOTA, name, euser_id, &D); -#endif - - setuid(user_id); /* Restore the original UID status */ - seteuid(euser_id); - - if (ret < 0) { - DEBUG(2,("disk_quotas ioctl (Solaris) failed\n")); - return(False); - } - - - /* Use softlimit to determine disk space. A user exceeding the quota is told - * that there's no space left. Writes might actually work for a bit if the - * hardlimit is set higher than softlimit. Effectively the disk becomes - * made of rubber latex and begins to expand to accommodate the user :-) - */ - - if (D.dqb_bsoftlimit==0) - return(False); - *bsize = 512; - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - if(*dfree < 0) - { - *dfree = 0; - *dsize = D.dqb_curblocks; - } - -DEBUG(5,("disk_quotas for path \"%s\" returning bsize %d, dfree %d, dsize %d\n", - path,*bsize,*dfree,*dsize)); - - return(True); -} - -#else - -#ifdef __FreeBSD__ -#include <ufs/ufs/quota.h> -#else -#include <sys/quota.h> -#include <devnm.h> -#endif - -/**************************************************************************** -try to get the disk space from disk quotas - default version -****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t user_id, euser_id; - int r; - char dev_disk[256]; - struct dqblk D; - struct stat S; -#ifndef __FreeBSD__ - /* find the block device file */ - if ((stat(path, &S)<0) || - (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False); -#endif - - euser_id = geteuid(); - -#ifdef USE_SETRES - /* for HPUX, real uid must be same as euid to execute quotactl for euid */ - user_id = getuid(); - setresuid(euser_id,-1,-1); - r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); - if (setresuid(user_id,-1,-1)) - DEBUG(5,("Unable to reset uid to %d\n", user_id)); -#else -#if defined(__FreeBSD__) - r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); -#else - r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); -#endif -#endif - - /* Use softlimit to determine disk space, except when it has been exceeded */ - *bsize = 1024; - if (r) - { - if (errno == EDQUOT) - { - *dfree =0; - *dsize =D.dqb_curblocks; - return (True); - } - else return(False); - } - if (D.dqb_bsoftlimit==0) - return(False); - /* Use softlimit to determine disk space, except when it has been exceeded */ - if ((D.dqb_curblocks>D.dqb_bsoftlimit) -#if !defined(__FreeBSD__) -||(D.dqb_curfiles>D.dqb_fsoftlimit) -#endif - ) { - *dfree = 0; - *dsize = D.dqb_curblocks; - } - else { - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - } - return (True); -} - -#endif - -#else -/* this keeps fussy compilers happy */ - void quotas_dummy(void) {} -#endif /* QUOTAS */ - diff --git a/source/smbd/reply.c b/source/smbd/reply.c deleted file mode 100644 index 8af4536c195..00000000000 --- a/source/smbd/reply.c +++ /dev/null @@ -1,3341 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Main SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -/* - This file handles most of the reply_ calls that the server - makes to handle specific protocols -*/ - - -#include "includes.h" -#include "trans2.h" - -/* look in server.c for some explanation of these variables */ -extern int Protocol; -extern int DEBUGLEVEL; -extern int max_send; -extern int max_recv; -extern int chain_fnum; -extern char magic_char; -extern connection_struct Connections[]; -extern files_struct Files[]; -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL short_case_preserve; -extern pstring sesssetup_user; -extern fstring myworkgroup; -extern int Client; - -/* this macro should always be used to extract an fnum (smb_fid) from -a packet to ensure chaining works correctly */ -#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where)) - - -/**************************************************************************** - reply to an special message -****************************************************************************/ -int reply_special(char *inbuf,char *outbuf) -{ - int outsize = 4; - int msg_type = CVAL(inbuf,0); - int msg_flags = CVAL(inbuf,1); - pstring name1,name2; - extern fstring remote_machine; - extern fstring local_machine; - char *p; - - *name1 = *name2 = 0; - - smb_setlen(outbuf,0); - - switch (msg_type) - { - case 0x81: /* session request */ - CVAL(outbuf,0) = 0x82; - CVAL(outbuf,3) = 0; - if (name_len(inbuf+4) > 50) - { - DEBUG(0,("Invalid name length in session request\n")); - return(0); - } - name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); - DEBUG(2,("netbios connect: name1=%s name2=%s\n",name1,name2)); - - strcpy(remote_machine,name2); - trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); - strlower(remote_machine); - if (p) *p = 0; - - strcpy(local_machine,name1); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - strlower(local_machine); - if (p) *p = 0; - - add_session_user(remote_machine); - - reload_services(True); - reopen_logs(); - - break; - case 0x85: /* session keepalive */ - default: - return(0); - } - - DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",timestring(),msg_type,msg_flags)); - - return(outsize); -} - - -/******************************************************************* -work out what error to give to a failed connection -********************************************************************/ -static int connection_error(char *inbuf,char *outbuf,int connection_num) -{ - switch (connection_num) - { - case -8: - return(ERROR(ERRSRV,ERRnoresource)); - case -7: - return(ERROR(ERRSRV,ERRbaduid)); - case -6: - return(ERROR(ERRSRV,ERRinvdevice)); - case -5: - return(ERROR(ERRSRV,ERRinvnetname)); - case -4: - return(ERROR(ERRSRV,ERRaccess)); - case -3: - return(ERROR(ERRDOS,ERRnoipc)); - case -2: - return(ERROR(ERRSRV,ERRinvnetname)); - } - return(ERROR(ERRSRV,ERRbadpw)); -} - - - -/**************************************************************************** - parse a share descriptor string -****************************************************************************/ -static void parse_connect(char *p,char *service,char *user, - char *password,int *pwlen,char *dev) -{ - char *p2; - - DEBUG(4,("parsing connect string %s\n",p)); - - p2 = strrchr(p,'\\'); - if (p2 == NULL) - strcpy(service,p); - else - strcpy(service,p2+1); - - p += strlen(p) + 2; - - strcpy(password,p); - *pwlen = strlen(password); - - p += strlen(p) + 2; - - strcpy(dev,p); - - *user = 0; - p = strchr(service,'%'); - if (p != NULL) - { - *p = 0; - strcpy(user,p+1); - } -} - - - - -/**************************************************************************** - reply to a tcon -****************************************************************************/ -int reply_tcon(char *inbuf,char *outbuf) -{ - pstring service; - pstring user; - pstring password; - pstring dev; - int connection_num; - int outsize = 0; - uint16 vuid = SVAL(inbuf,smb_uid); - int pwlen=0; - - *service = *user = *password = *dev = 0; - - parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev); - - connection_num = make_connection(service,user,password,pwlen,dev,vuid); - - if (connection_num < 0) - return(connection_error(inbuf,outbuf,connection_num)); - - outsize = set_message(outbuf,2,0,True); - SSVAL(outbuf,smb_vwv0,max_recv); - SSVAL(outbuf,smb_vwv1,connection_num); - SSVAL(outbuf,smb_tid,connection_num); - - DEBUG(3,("%s tcon service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); - - return(outsize); -} - - -/**************************************************************************** - reply to a tcon and X -****************************************************************************/ -int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - pstring service; - pstring user; - pstring password; - pstring devicename; - int connection_num; - uint16 vuid = SVAL(inbuf,smb_uid); - int passlen = SVAL(inbuf,smb_vwv3); - BOOL doencrypt = SMBENCRYPT(); - - *service = *user = *password = *devicename = 0; - - /* we might have to close an old one */ - if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) - close_cnum(SVAL(inbuf,smb_tid),vuid); - - { - char *path; - char *p; - memcpy(password,smb_buf(inbuf),passlen); - password[passlen]=0; - path = smb_buf(inbuf) + passlen; - - if (!doencrypt || passlen != 24) { - if (strequal(password," ")) - *password = 0; - passlen = strlen(password); - } - - DEBUG(4,("parsing net-path %s, passlen=%d\n",path,passlen)); - strcpy(service,path+2); - p = strchr(service,'\\'); - if (!p) - return(ERROR(ERRSRV,ERRinvnetname)); - *p = 0; - strcpy(service,p+1); - p = strchr(service,'%'); - if (p) - { - *p++ = 0; - strcpy(user,p); - } - StrnCpy(devicename,path + strlen(path) + 1,6); - DEBUG(4,("Got device type %s\n",devicename)); - } - - connection_num = make_connection(service,user,password,passlen,devicename,vuid); - - if (connection_num < 0) - return(connection_error(inbuf,outbuf,connection_num)); - - set_message(outbuf,2,strlen(devicename)+1,True); - - DEBUG(3,("%s tconX service=%s user=%s cnum=%d\n",timestring(),service,user,connection_num)); - - /* set the incoming and outgoing tid to the just created one */ - SSVAL(inbuf,smb_tid,connection_num); - SSVAL(outbuf,smb_tid,connection_num); - - strcpy(smb_buf(outbuf),devicename); - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to an unknown type -****************************************************************************/ -int reply_unknown(char *inbuf,char *outbuf) -{ - int cnum; - int type; - cnum = SVAL(inbuf,smb_tid); - type = CVAL(inbuf,smb_com); - - DEBUG(0,("%s unknown command type (%s): cnum=%d type=%d (0x%X)\n", - timestring(), - smb_fn_name(type), - cnum,type,type)); - - return(ERROR(ERRSRV,ERRunknownsmb)); -} - - -/**************************************************************************** - reply to an ioctl -****************************************************************************/ -int reply_ioctl(char *inbuf,char *outbuf) -{ - DEBUG(3,("ignoring ioctl\n")); -#if 0 - /* we just say it succeeds and hope its all OK. - some day it would be nice to interpret them individually */ - return set_message(outbuf,1,0,True); -#else - return(ERROR(ERRSRV,ERRnosupport)); -#endif -} - - -/**************************************************************************** -reply to a session setup command -****************************************************************************/ -int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - uint16 sess_vuid; - int gid; - int uid; - int smb_bufsize; - int smb_mpxmax; - int smb_vc_num; - uint32 smb_sesskey; - int smb_apasslen = 0; - pstring smb_apasswd; - int smb_ntpasslen = 0; - pstring smb_ntpasswd; - BOOL valid_nt_password = False; - pstring user; - BOOL guest=False; - BOOL computer_id=False; - static BOOL done_sesssetup = False; - BOOL doencrypt = SMBENCRYPT(); - - *smb_apasswd = 0; - - smb_bufsize = SVAL(inbuf,smb_vwv2); - smb_mpxmax = SVAL(inbuf,smb_vwv3); - smb_vc_num = SVAL(inbuf,smb_vwv4); - smb_sesskey = IVAL(inbuf,smb_vwv5); - - if (Protocol < PROTOCOL_NT1) { - smb_apasslen = SVAL(inbuf,smb_vwv7); - memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - StrnCpy(user,smb_buf(inbuf)+smb_apasslen,sizeof(user)-1); - - if (lp_security() != SEC_SERVER && !doencrypt) - smb_apasslen = strlen(smb_apasswd); - } else { - uint16 passlen1 = SVAL(inbuf,smb_vwv7); - uint16 passlen2 = SVAL(inbuf,smb_vwv8); - char *p = smb_buf(inbuf); - - if (passlen1 != 24 && passlen2 != 24) - doencrypt = False; - - if(doencrypt) { - /* Save the lanman2 password and the NT md4 password. */ - smb_apasslen = passlen1; - memcpy(smb_apasswd,p,smb_apasslen); - smb_ntpasslen = passlen2; - memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen); - } else { - /* both Win95 and WinNT stuff up the password lengths for - non-encrypting systems. Uggh. - - if passlen1==24 its a win95 system, and its setting the - password length incorrectly. Luckily it still works with the - default code because Win95 will null terminate the password - anyway - - if passlen1>0 and passlen2>0 then maybe its a NT box and its - setting passlen2 to some random value which really stuffs - things up. we need to fix that one. */ - if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && - passlen2 != 1) { - passlen2 = 0; - } - /* we use the first password that they gave */ - smb_apasslen = passlen1; - StrnCpy(smb_apasswd,p,smb_apasslen); - - /* trim the password */ - smb_apasslen = strlen(smb_apasswd); - - /* wfwg sometimes uses a space instead of a null */ - if (strequal(smb_apasswd," ")) { - smb_apasslen = 0; - *smb_apasswd = 0; - } - } - - p += passlen1 + passlen2; - strcpy(user,p); p = skip_string(p,1); - DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n", - p,skip_string(p,1),skip_string(p,2))); - } - - - DEBUG(3,("sesssetupX:name=[%s]\n",user)); - - /* If name ends in $ then I think it's asking about whether a */ - /* computer with that name (minus the $) has access. For now */ - /* say yes to everything ending in $. */ - if (user[strlen(user) - 1] == '$') { - computer_id = True; - user[strlen(user) - 1] = '\0'; - } - - - if (!*user) - strcpy(user,lp_guestaccount(-1)); - - strlower(user); - - strcpy(sesssetup_user,user); - - reload_services(True); - - add_session_user(user); - - - if (!(lp_security() == SEC_SERVER && server_validate(inbuf)) && - !check_hosts_equiv(user)) - { - - if (strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) - guest = True; - - /* now check if it's a valid username/password */ - /* If an NT password was supplied try and validate with that - first. This is superior as the passwords are mixed case 128 length unicode */ - if(smb_ntpasslen && !guest) - { - if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL)) - DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n")); - else - valid_nt_password = True; - } - if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL)) - { - if (!computer_id && lp_security() >= SEC_USER) { -#if (GUEST_SESSSETUP == 0) - return(ERROR(ERRSRV,ERRbadpw)); -#endif -#if (GUEST_SESSSETUP == 1) - if (Get_Pwnam(user,True)) - return(ERROR(ERRSRV,ERRbadpw)); -#endif - } - if (*smb_apasswd || !Get_Pwnam(user,True)) - strcpy(user,lp_guestaccount(-1)); - DEBUG(3,("Registered username %s for guest access\n",user)); - guest = True; - } - } - - if (!Get_Pwnam(user,True)) { - DEBUG(3,("No such user %s - using guest account\n",user)); - strcpy(user,lp_guestaccount(-1)); - guest = True; - } - - if (!strequal(user,lp_guestaccount(-1)) && - lp_servicenumber(user) < 0) - { - int homes = lp_servicenumber(HOMES_NAME); - char *home = get_home_dir(user); - if (homes >= 0 && home) - lp_add_home(user,homes,home); - } - - - /* it's ok - setup a reply */ - if (Protocol < PROTOCOL_NT1) { - set_message(outbuf,3,0,True); - } else { - char *p; - set_message(outbuf,3,3,True); - p = smb_buf(outbuf); - strcpy(p,"Unix"); p = skip_string(p,1); - strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1); - strcpy(p,myworkgroup); p = skip_string(p,1); - set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); - /* perhaps grab OS version here?? */ - } - - /* Set the correct uid in the outgoing and incoming packets - We will use this on future requests to determine which - user we should become. - */ - { - struct passwd *pw = Get_Pwnam(user,False); - if (!pw) { - DEBUG(1,("Username %s is invalid on this system\n",user)); - return(ERROR(ERRSRV,ERRbadpw)); - } - gid = pw->pw_gid; - uid = pw->pw_uid; - } - - if (guest && !computer_id) - SSVAL(outbuf,smb_vwv2,1); - - /* register the name and uid as being validated, so further connections - to a uid can get through without a password, on the same VC */ - sess_vuid = register_vuid(uid,gid,user,guest); - - SSVAL(outbuf,smb_uid,sess_vuid); - SSVAL(inbuf,smb_uid,sess_vuid); - - if (!done_sesssetup) - max_send = MIN(max_send,smb_bufsize); - - DEBUG(1,(" Client requested max send size of %d\n", max_send)); - - done_sesssetup = True; - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to a chkpth -****************************************************************************/ -int reply_chkpth(char *inbuf,char *outbuf) -{ - int outsize = 0; - int cnum,mode; - pstring name; - BOOL ok = False; - - cnum = SVAL(inbuf,smb_tid); - - strcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,cnum,0); - - mode = SVAL(inbuf,smb_vwv0); - - if (check_name(name,cnum)) - ok = directory_exist(name,NULL); - - if (!ok) - return(ERROR(ERRDOS,ERRbadpath)); - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s chkpth %s cnum=%d mode=%d\n",timestring(),name,cnum,mode)); - - return(outsize); -} - - -/**************************************************************************** - reply to a getatr -****************************************************************************/ -int reply_getatr(char *inbuf,char *outbuf) -{ - pstring fname; - int cnum; - int outsize = 0; - struct stat sbuf; - BOOL ok = False; - int mode=0; - uint32 size=0; - time_t mtime=0; - - cnum = SVAL(inbuf,smb_tid); - - strcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0); - - /* dos smetimes asks for a stat of "" - it returns a "hidden directory" - under WfWg - weird! */ - if (! (*fname)) - { - mode = aHIDDEN | aDIR; - if (!CAN_WRITE(cnum)) mode |= aRONLY; - size = 0; - mtime = 0; - ok = True; - } - else - if (check_name(fname,cnum)) - { - if (sys_stat(fname,&sbuf) == 0) - { - mode = dos_mode(cnum,fname,&sbuf); - size = sbuf.st_size; - mtime = sbuf.st_mtime; - if (mode & aDIR) - size = 0; - ok = True; - } - else - DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno))); - } - - if (!ok) - return(UNIXERROR(ERRDOS,ERRbadfile)); - - outsize = set_message(outbuf,10,0,True); - - SSVAL(outbuf,smb_vwv0,mode); - put_dos_date3(outbuf,smb_vwv1,mtime); - SIVAL(outbuf,smb_vwv3,size); - - if (Protocol >= PROTOCOL_NT1) { - char *p = strrchr(fname,'/'); - uint16 flg2 = SVAL(outbuf,smb_flg2); - if (!p) p = fname; - if (!is_8_3(fname, True)) - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ - } - - DEBUG(3,("%s getatr name=%s mode=%d size=%d\n",timestring(),fname,mode,size)); - - return(outsize); -} - - -/**************************************************************************** - reply to a setatr -****************************************************************************/ -int reply_setatr(char *inbuf,char *outbuf) -{ - pstring fname; - int cnum; - int outsize = 0; - BOOL ok=False; - int mode; - time_t mtime; - - cnum = SVAL(inbuf,smb_tid); - - strcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0); - - mode = SVAL(inbuf,smb_vwv0); - mtime = make_unix_date3(inbuf+smb_vwv1); - - if (directory_exist(fname,NULL)) - mode |= aDIR; - if (check_name(fname,cnum)) - ok = (dos_chmod(cnum,fname,mode,NULL) == 0); - if (ok) - ok = set_filetime(fname,mtime); - - if (!ok) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s setatr name=%s mode=%d\n",timestring(),fname,mode)); - - return(outsize); -} - - -/**************************************************************************** - reply to a dskattr -****************************************************************************/ -int reply_dskattr(char *inbuf,char *outbuf) -{ - int cnum; - int outsize = 0; - int dfree,dsize,bsize; - - cnum = SVAL(inbuf,smb_tid); - - sys_disk_free(".",&bsize,&dfree,&dsize); - - outsize = set_message(outbuf,5,0,True); - - SSVAL(outbuf,smb_vwv0,dsize); - SSVAL(outbuf,smb_vwv1,bsize/512); - SSVAL(outbuf,smb_vwv2,512); - SSVAL(outbuf,smb_vwv3,dfree); - - DEBUG(3,("%s dskattr cnum=%d dfree=%d\n",timestring(),cnum,dfree)); - - return(outsize); -} - - -/**************************************************************************** - reply to a search - Can be called from SMBsearch, SMBffirst or SMBfunique. -****************************************************************************/ -int reply_search(char *inbuf,char *outbuf) -{ - pstring mask; - pstring directory; - pstring fname; - int size,mode; - time_t date; - int dirtype; - int cnum; - int outsize = 0; - int numentries = 0; - BOOL finished = False; - int maxentries; - int i; - char *p; - BOOL ok = False; - int status_len; - char *path; - char status[21]; - int dptr_num= -1; - BOOL check_descend = False; - BOOL expect_close = False; - BOOL can_open = True; - - *mask = *directory = *fname = 0; - - /* If we were called as SMBffirst then we must expect close. */ - if(CVAL(inbuf,smb_com) == SMBffirst) - expect_close = True; - - cnum = SVAL(inbuf,smb_tid); - - outsize = set_message(outbuf,1,3,True); - maxentries = SVAL(inbuf,smb_vwv0); - dirtype = SVAL(inbuf,smb_vwv1); - path = smb_buf(inbuf) + 1; - status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); - - - /* dirtype &= ~aDIR; */ - - DEBUG(5,("path=%s status_len=%d\n",path,status_len)); - - - if (status_len == 0) - { - pstring dir2; - - strcpy(directory,smb_buf(inbuf)+1); - strcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,cnum,0); - unix_format(dir2); - - if (!check_name(directory,cnum)) - can_open = False; - - p = strrchr(dir2,'/'); - if (p == NULL) - {strcpy(mask,dir2);*dir2 = 0;} - else - {*p = 0;strcpy(mask,p+1);} - - p = strrchr(directory,'/'); - if (!p) - *directory = 0; - else - *p = 0; - - if (strlen(directory) == 0) - strcpy(directory,"./"); - bzero(status,21); - CVAL(status,0) = dirtype; - } - else - { - memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); - memcpy(mask,status+1,11); - mask[11] = 0; - dirtype = CVAL(status,0) & 0x1F; - Connections[cnum].dirptr = dptr_fetch(status+12,&dptr_num); - if (!Connections[cnum].dirptr) - goto SearchEmpty; - string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); - if (!case_sensitive) - strnorm(mask); - } - - /* turn strings of spaces into a . */ - { - trim_string(mask,NULL," "); - if ((p = strrchr(mask,' '))) - { - fstring ext; - strcpy(ext,p+1); - *p = 0; - trim_string(mask,NULL," "); - strcat(mask,"."); - strcat(mask,ext); - } - } - - { - for (p=mask; *p; p++) - { - if (*p != '?' && *p != '*' && !isdoschar(*p)) - { - DEBUG(5,("Invalid char [%c] in search mask?\n",*p)); - *p = '?'; - } - } - } - - if (!strchr(mask,'.') && strlen(mask)>8) - { - fstring tmp; - strcpy(tmp,&mask[8]); - mask[8] = '.'; - mask[9] = 0; - strcat(mask,tmp); - } - - DEBUG(5,("mask=%s directory=%s\n",mask,directory)); - - if (can_open) - { - p = smb_buf(outbuf) + 3; - - ok = True; - - if (status_len == 0) - { - dptr_num = dptr_create(cnum,directory,expect_close,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) - return(ERROR(ERRDOS,ERRnofids)); - } - - DEBUG(4,("dptr_num is %d\n",dptr_num)); - - if (ok) - { - if ((dirtype&0x1F) == aVOLID) - { - memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0); - dptr_fill(p+12,dptr_num); - if (dptr_zero(p+12) && (status_len==0)) - numentries = 1; - else - numentries = 0; - p += DIR_STRUCT_SIZE; - } - else - { - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); - if (in_list(Connections[cnum].dirpath, - lp_dontdescend(SNUM(cnum)),True)) - check_descend = True; - - for (i=numentries;(i<maxentries) && !finished;i++) - { - finished = - !get_dir_entry(cnum,mask,dirtype,fname,&size,&mode,&date,check_descend); - if (!finished) - { - memcpy(p,status,21); - make_dir_struct(p,mask,fname,size,mode,date); - dptr_fill(p+12,dptr_num); - numentries++; - } - p += DIR_STRUCT_SIZE; - } - } - } - } - - - SearchEmpty: - - if (numentries == 0 || !ok) - { - CVAL(outbuf,smb_rcls) = ERRDOS; - SSVAL(outbuf,smb_err,ERRnofiles); - } - - /* If we were called as SMBffirst with smb_search_id == NULL - and no entries were found then return error and close dirptr - (X/Open spec) */ - - if(ok && expect_close && numentries == 0 && status_len == 0) - { - CVAL(outbuf,smb_rcls) = ERRDOS; - SSVAL(outbuf,smb_err,ERRnofiles); - /* Also close the dptr - we know it's gone */ - dptr_close(dptr_num); - } - - /* If we were called as SMBfunique, then we can close the dirptr now ! */ - if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) - dptr_close(dptr_num); - - SSVAL(outbuf,smb_vwv0,numentries); - SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE); - CVAL(smb_buf(outbuf),0) = 5; - SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); - - if (Protocol >= PROTOCOL_NT1) { - uint16 flg2 = SVAL(outbuf,smb_flg2); - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ - } - - outsize += DIR_STRUCT_SIZE*numentries; - smb_setlen(outbuf,outsize - 4); - - if ((! *directory) && dptr_path(dptr_num)) - sprintf(directory,"(%s)",dptr_path(dptr_num)); - - DEBUG(4,("%s %s mask=%s path=%s cnum=%d dtype=%d nument=%d of %d\n", - timestring(), - smb_fn_name(CVAL(inbuf,smb_com)), - mask,directory,cnum,dirtype,numentries,maxentries)); - - return(outsize); -} - - -/**************************************************************************** - reply to a fclose (stop directory search) -****************************************************************************/ -int reply_fclose(char *inbuf,char *outbuf) -{ - int cnum; - int outsize = 0; - int status_len; - char *path; - char status[21]; - int dptr_num= -1; - - cnum = SVAL(inbuf,smb_tid); - - outsize = set_message(outbuf,1,0,True); - path = smb_buf(inbuf) + 1; - status_len = SVAL(smb_buf(inbuf),3 + strlen(path)); - - - if (status_len == 0) - return(ERROR(ERRSRV,ERRsrverror)); - - memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21); - - if(dptr_fetch(status+12,&dptr_num)) { - /* Close the dptr - we know it's gone */ - dptr_close(dptr_num); - } - - SSVAL(outbuf,smb_vwv0,0); - - DEBUG(3,("%s search close cnum=%d\n",timestring(),cnum)); - - return(outsize); -} - - -/**************************************************************************** - reply to an open -****************************************************************************/ -int reply_open(char *inbuf,char *outbuf) -{ - pstring fname; - int cnum; - int fnum = -1; - int outsize = 0; - int fmode=0; - int share_mode; - int size = 0; - time_t mtime=0; - int unixmode; - int rmode=0; - struct stat sbuf; - - cnum = SVAL(inbuf,smb_tid); - - share_mode = SVAL(inbuf,smb_vwv0); - - strcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - unixmode = unix_mode(cnum,aARCH); - - open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - - if (fmode & aDIR) { - DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - outsize = set_message(outbuf,7,0,True); - SSVAL(outbuf,smb_vwv0,fnum); - SSVAL(outbuf,smb_vwv1,fmode); - put_dos_date3(outbuf,smb_vwv2,mtime); - SIVAL(outbuf,smb_vwv4,size); - SSVAL(outbuf,smb_vwv6,rmode); - - if (lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); - } - - return(outsize); -} - - -/**************************************************************************** - reply to an open and X -****************************************************************************/ -int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - pstring fname; - int cnum = SVAL(inbuf,smb_tid); - int fnum = -1; - int openmode = 0; - int smb_mode = SVAL(inbuf,smb_vwv3); - int smb_attr = SVAL(inbuf,smb_vwv5); - BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1); -#if 0 - int open_flags = SVAL(inbuf,smb_vwv2); - int smb_sattr = SVAL(inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(inbuf+smb_vwv6); -#endif - int smb_ofun = SVAL(inbuf,smb_vwv8); - int unixmode; - int size=0,fmode=0,mtime=0,rmode=0; - struct stat sbuf; - int smb_action = 0; - - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(cnum)) - return reply_open_pipe_and_X(inbuf,outbuf,length,bufsize); - - /* XXXX we need to handle passed times, sattr and flags */ - - strcpy(fname,smb_buf(inbuf)); - unix_convert(fname,cnum,0); - - /* now add create and trunc bits */ - if (smb_ofun & 0x10) - openmode |= O_CREAT; - if ((smb_ofun & 0x3) == 2) - openmode |= O_TRUNC; - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - unixmode = unix_mode(cnum,smb_attr | aARCH); - - open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - &rmode,&smb_action); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - if (fmode & aDIR) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= (1<<15); - } - - set_message(outbuf,15,0,True); - SSVAL(outbuf,smb_vwv2,fnum); - SSVAL(outbuf,smb_vwv3,fmode); - put_dos_date3(outbuf,smb_vwv4,mtime); - SIVAL(outbuf,smb_vwv6,size); - SSVAL(outbuf,smb_vwv8,rmode); - SSVAL(outbuf,smb_vwv11,smb_action); - - chain_fnum = fnum; - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to a SMBulogoffX -****************************************************************************/ -int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) -{ - uint16 vuid = SVAL(inbuf,smb_uid); - user_struct *vuser = get_valid_user_struct(vuid); - - if(vuser == 0) { - DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid)); - } - - /* in user level security we are supposed to close any files - open by this user */ - if ((vuser != 0) && (lp_security() != SEC_SHARE)) { - int i; - for (i=0;i<MAX_OPEN_FILES;i++) - if (Files[i].uid == vuser->uid && Files[i].open) { - close_file(i); - } - } - - invalidate_vuid(vuid); - - set_message(outbuf,2,0,True); - - DEBUG(3,("%s ulogoffX vuid=%d\n",timestring(),vuid)); - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to a mknew or a create -****************************************************************************/ -int reply_mknew(char *inbuf,char *outbuf) -{ - pstring fname; - int cnum,com; - int fnum = -1; - int outsize = 0; - int createmode; - mode_t unixmode; - int ofun = 0; - - com = SVAL(inbuf,smb_com); - cnum = SVAL(inbuf,smb_tid); - - createmode = SVAL(inbuf,smb_vwv0); - strcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0); - - if (createmode & aVOLID) - { - DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname)); - } - - unixmode = unix_mode(cnum,createmode); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if(com == SMBmknew) - { - /* We should fail if file exists. */ - ofun = 0x10; - } - else - { - /* SMBcreate - Create if file doesn't exist, truncate if it does. */ - ofun = 0x12; - } - - /* Open file in dos compatibility share mode. */ - open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fnum); - - if (lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); - } - - DEBUG(2,("new file %s\n",fname)); - DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); - - return(outsize); -} - - -/**************************************************************************** - reply to a create temporary file -****************************************************************************/ -int reply_ctemp(char *inbuf,char *outbuf) -{ - pstring fname; - pstring fname2; - int cnum; - int fnum = -1; - int outsize = 0; - int createmode; - mode_t unixmode; - - cnum = SVAL(inbuf,smb_tid); - createmode = SVAL(inbuf,smb_vwv0); - sprintf(fname,"%s/TMXXXXXX",smb_buf(inbuf)+1); - unix_convert(fname,cnum,0); - - unixmode = unix_mode(cnum,createmode); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - strcpy(fname2,(char *)mktemp(fname)); - - /* Open file in dos compatibility share mode. */ - /* We should fail if file exists. */ - open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize = set_message(outbuf,1,2 + strlen(fname2),True); - SSVAL(outbuf,smb_vwv0,fnum); - CVAL(smb_buf(outbuf),0) = 4; - strcpy(smb_buf(outbuf) + 1,fname2); - - if (lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); - } - - DEBUG(2,("created temp file %s\n",fname2)); - DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); - - return(outsize); -} - - -/******************************************************************* -check if a user is allowed to delete a file -********************************************************************/ -static BOOL can_delete(char *fname,int cnum,int dirtype) -{ - struct stat sbuf; - int fmode; - - if (!CAN_WRITE(cnum)) return(False); - - if (sys_lstat(fname,&sbuf) != 0) return(False); - fmode = dos_mode(cnum,fname,&sbuf); - if (fmode & aDIR) return(False); - if (!lp_delete_readonly(SNUM(cnum))) { - if (fmode & aRONLY) return(False); - } - if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) - return(False); - if (!check_file_sharing(cnum,fname)) return(False); - return(True); -} - -/**************************************************************************** - reply to a unlink -****************************************************************************/ -int reply_unlink(char *inbuf,char *outbuf) -{ - int outsize = 0; - pstring name; - int cnum; - int dirtype; - pstring directory; - pstring mask; - char *p; - int count=0; - int error = ERRnoaccess; - BOOL has_wild; - BOOL exists=False; - - *directory = *mask = 0; - - cnum = SVAL(inbuf,smb_tid); - dirtype = SVAL(inbuf,smb_vwv0); - - strcpy(name,smb_buf(inbuf) + 1); - - DEBUG(3,("reply_unlink : %s\n",name)); - - unix_convert(name,cnum,0); - - p = strrchr(name,'/'); - if (!p) { - strcpy(directory,"./"); - strcpy(mask,name); - } else { - *p = 0; - strcpy(directory,name); - strcpy(mask,p+1); - } - - if (is_mangled(mask)) - check_mangled_stack(mask); - - has_wild = strchr(mask,'*') || strchr(mask,'?'); - - if (!has_wild) { - strcat(directory,"/"); - strcat(directory,mask); - if (can_delete(directory,cnum,dirtype) && !sys_unlink(directory)) count++; - if (!count) exists = file_exist(directory,NULL); - } else { - void *dirptr = NULL; - char *dname; - - if (check_name(directory,cnum)) - dirptr = OpenDir(directory); - - /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then - the pattern matches against the long name, otherwise the short name - We don't implement this yet XXXX - */ - - if (dirptr) - { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - strcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - strcpy(fname,dname); - - if(!mask_match(fname, mask, case_sensitive, False)) continue; - - error = ERRnoaccess; - sprintf(fname,"%s/%s",directory,dname); - if (!can_delete(fname,cnum,dirtype)) continue; - if (!sys_unlink(fname)) count++; - DEBUG(3,("reply_unlink : doing unlink on %s\n",fname)); - } - CloseDir(dirptr); - } - } - - if (count == 0) { - if (exists) - return(ERROR(ERRDOS,error)); - else - return(UNIXERROR(ERRDOS,error)); - } - - outsize = set_message(outbuf,0,0,True); - - return(outsize); -} - - -/**************************************************************************** - reply to a readbraw (core+ protocol) -****************************************************************************/ -int reply_readbraw(char *inbuf, char *outbuf) -{ - int cnum,maxcount,mincount,fnum; - int nread = 0; - int startpos; - char *header = outbuf; - int ret=0; - int fd; - char *fname; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - startpos = IVAL(inbuf,smb_vwv1); - maxcount = SVAL(inbuf,smb_vwv3); - mincount = SVAL(inbuf,smb_vwv4); - - /* ensure we don't overrun the packet size */ - maxcount = MIN(65535,maxcount); - maxcount = MAX(mincount,maxcount); - - if (!FNUM_OK(fnum,cnum) || !Files[fnum].can_read) - { - DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",fnum)); - _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); - return(-1); - } - else - { - fd = Files[fnum].fd_ptr->fd; - fname = Files[fnum].name; - } - - - if (!is_locked(fnum,cnum,maxcount,startpos)) - { - int size = Files[fnum].size; - int sizeneeded = startpos + maxcount; - - if (size < sizeneeded) { - struct stat st; - if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) - size = st.st_size; - if (!Files[fnum].can_write) - Files[fnum].size = size; - } - - nread = MIN(maxcount,size - startpos); - } - - if (nread < mincount) - nread = 0; - - DEBUG(3,("%s readbraw fnum=%d cnum=%d start=%d max=%d min=%d nread=%d\n", - timestring(), - fnum,cnum,startpos, - maxcount,mincount,nread)); - -#if UNSAFE_READRAW - { - int predict=0; - _smb_setlen(header,nread); - - if (!Files[fnum].can_write) - predict = read_predict(fd,startpos,header+4,NULL,nread); - - if ((nread-predict) > 0) - seek_file(fnum,startpos + predict); - - ret = transfer_file(fd,Client,nread-predict,header,4+predict, - startpos+predict); - } - - if (ret != nread+4) - DEBUG(0,("ERROR: file read failure on %s at %d for %d bytes (%d)\n", - fname,startpos,nread,ret)); - -#else - ret = read_file(fnum,header+4,startpos,nread); - if (ret < mincount) ret = 0; - - _smb_setlen(header,ret); - transfer_file(0,Client,0,header,4+ret,0); -#endif - - DEBUG(5,("readbraw finished\n")); - return -1; -} - - -/**************************************************************************** - reply to a lockread (core+ protocol) -****************************************************************************/ -int reply_lockread(char *inbuf,char *outbuf) -{ - int cnum,fnum; - int nread = -1; - char *data; - int outsize = 0; - uint32 startpos, numtoread; - int eclass; - uint32 ecode; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_READ(fnum); - CHECK_ERROR(fnum); - - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - - outsize = set_message(outbuf,5,3,True); - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; - - if(!do_lock( fnum, cnum, numtoread, startpos, &eclass, &ecode)) - return (ERROR(eclass,ecode)); - - nread = read_file(fnum,data,startpos,numtoread); - - if (nread < 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - SSVAL(smb_buf(outbuf),1,nread); - - DEBUG(3,("%s lockread fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread)); - - return(outsize); -} - - -/**************************************************************************** - reply to a read -****************************************************************************/ -int reply_read(char *inbuf,char *outbuf) -{ - int cnum,numtoread,fnum; - int nread = 0; - char *data; - int startpos; - int outsize = 0; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_READ(fnum); - CHECK_ERROR(fnum); - - numtoread = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - - outsize = set_message(outbuf,5,3,True); - numtoread = MIN(BUFFER_SIZE-outsize,numtoread); - data = smb_buf(outbuf) + 3; - - if (is_locked(fnum,cnum,numtoread,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - if (numtoread > 0) - nread = read_file(fnum,data,startpos,numtoread); - - if (nread < 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize += nread; - SSVAL(outbuf,smb_vwv0,nread); - SSVAL(outbuf,smb_vwv5,nread+3); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,nread); - - DEBUG(3,("%s read fnum=%d cnum=%d num=%d nread=%d\n",timestring(),fnum,cnum,numtoread,nread)); - - return(outsize); -} - - -/**************************************************************************** - reply to a read and X -****************************************************************************/ -int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - int fnum = GETFNUM(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); - int smb_maxcnt = SVAL(inbuf,smb_vwv5); - int smb_mincnt = SVAL(inbuf,smb_vwv6); - int cnum; - int nread = -1; - char *data; - BOOL ok = False; - - cnum = SVAL(inbuf,smb_tid); - - CHECK_FNUM(fnum,cnum); - CHECK_READ(fnum); - CHECK_ERROR(fnum); - - set_message(outbuf,12,0,True); - data = smb_buf(outbuf); - - if (is_locked(fnum,cnum,smb_maxcnt,smb_offs)) - return(ERROR(ERRDOS,ERRlock)); - nread = read_file(fnum,data,smb_offs,smb_maxcnt); - ok = True; - - if (nread < 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - SSVAL(outbuf,smb_vwv5,nread); - SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); - SSVAL(smb_buf(outbuf),-2,nread); - - DEBUG(3,("%s readX fnum=%d cnum=%d min=%d max=%d nread=%d\n", - timestring(),fnum,cnum, - smb_mincnt,smb_maxcnt,nread)); - - chain_fnum = fnum; - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to a writebraw (core+ or LANMAN1.0 protocol) -****************************************************************************/ -int reply_writebraw(char *inbuf,char *outbuf) -{ - int nwritten=0; - int total_written=0; - int numtowrite=0; - int cnum,fnum; - int outsize = 0; - long startpos; - char *data=NULL; - BOOL write_through; - int tcount; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - tcount = IVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); - - /* We have to deal with slightly different formats depending - on whether we are using the core+ or lanman1.0 protocol */ - if(Protocol <= PROTOCOL_COREPLUS) { - numtowrite = SVAL(smb_buf(inbuf),-2); - data = smb_buf(inbuf); - } else { - numtowrite = SVAL(inbuf,smb_vwv10); - data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11); - } - - /* force the error type */ - CVAL(inbuf,smb_com) = SMBwritec; - CVAL(outbuf,smb_com) = SMBwritec; - - if (is_locked(fnum,cnum,tcount,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - if (seek_file(fnum,startpos) != startpos) - DEBUG(0,("couldn't seek to %d in writebraw\n",startpos)); - - if (numtowrite>0) - nwritten = write_file(fnum,data,numtowrite); - - DEBUG(3,("%s writebraw1 fnum=%d cnum=%d start=%d num=%d wrote=%d sync=%d\n", - timestring(),fnum,cnum,startpos,numtowrite,nwritten,write_through)); - - if (nwritten < numtowrite) - return(UNIXERROR(ERRHRD,ERRdiskfull)); - - total_written = nwritten; - - /* Return a message to the redirector to tell it - to send more bytes */ - CVAL(outbuf,smb_com) = SMBwritebraw; - SSVALS(outbuf,smb_vwv0,-1); - outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); - send_smb(Client,outbuf); - - /* Now read the raw data into the buffer and write it */ - if (read_smb_length(Client,inbuf,SMB_SECONDARY_WAIT) == -1) { - exit_server("secondary writebraw failed"); - } - - /* Even though this is not an smb message, smb_len - returns the generic length of an smb message */ - numtowrite = smb_len(inbuf); - - if (tcount > nwritten+numtowrite) { - DEBUG(3,("Client overestimated the write %d %d %d\n", - tcount,nwritten,numtowrite)); - } - - nwritten = transfer_file(Client,Files[fnum].fd_ptr->fd,numtowrite,NULL,0, - startpos+nwritten); - total_written += nwritten; - - /* Set up outbuf to return the correct return */ - outsize = set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBwritec; - SSVAL(outbuf,smb_vwv0,total_written); - - if (nwritten < numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; - SSVAL(outbuf,smb_err,ERRdiskfull); - } - - if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); - - DEBUG(3,("%s writebraw2 fnum=%d cnum=%d start=%d num=%d wrote=%d\n", - timestring(),fnum,cnum,startpos,numtowrite,total_written)); - - /* we won't return a status if write through is not selected - this - follows what WfWg does */ - if (!write_through && total_written==tcount) - return(-1); - - return(outsize); -} - - -/**************************************************************************** - reply to a writeunlock (core+) -****************************************************************************/ -int reply_writeunlock(char *inbuf,char *outbuf) -{ - int cnum,fnum; - int nwritten = -1; - int outsize = 0; - char *data; - uint32 numtowrite,startpos; - int eclass; - uint32 ecode; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - data = smb_buf(inbuf) + 3; - - if (is_locked(fnum,cnum,numtowrite,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - seek_file(fnum,startpos); - - /* The special X/Open SMB protocol handling of - zero length writes is *NOT* done for - this call */ - if(numtowrite == 0) - nwritten = 0; - else - nwritten = write_file(fnum,data,numtowrite); - - if (lp_syncalways(SNUM(cnum))) - sync_file(fnum); - - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if(!do_unlock(fnum, cnum, numtowrite, startpos, &eclass, &ecode)) - return(ERROR(eclass,ecode)); - - outsize = set_message(outbuf,1,0,True); - - SSVAL(outbuf,smb_vwv0,nwritten); - - DEBUG(3,("%s writeunlock fnum=%d cnum=%d num=%d wrote=%d\n", - timestring(),fnum,cnum,numtowrite,nwritten)); - - return(outsize); -} - - -/**************************************************************************** - reply to a write -****************************************************************************/ -int reply_write(char *inbuf,char *outbuf,int dum1,int dum2) -{ - int cnum,numtowrite,fnum; - int nwritten = -1; - int outsize = 0; - int startpos; - char *data; - - dum1 = dum2 = 0; - - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - data = smb_buf(inbuf) + 3; - - if (is_locked(fnum,cnum,numtowrite,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - seek_file(fnum,startpos); - - /* X/Open SMB protocol says that if smb_vwv1 is - zero then the file size should be extended or - truncated to the size given in smb_vwv[2-3] */ - if(numtowrite == 0) - nwritten = set_filelen(Files[fnum].fd_ptr->fd, startpos); - else - nwritten = write_file(fnum,data,numtowrite); - - if (lp_syncalways(SNUM(cnum))) - sync_file(fnum); - - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize = set_message(outbuf,1,0,True); - - SSVAL(outbuf,smb_vwv0,nwritten); - - if (nwritten < numtowrite) { - CVAL(outbuf,smb_rcls) = ERRHRD; - SSVAL(outbuf,smb_err,ERRdiskfull); - } - - DEBUG(3,("%s write fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,numtowrite,nwritten)); - - return(outsize); -} - - -/**************************************************************************** - reply to a write and X -****************************************************************************/ -int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) -{ - int fnum = GETFNUM(inbuf,smb_vwv2); - uint32 smb_offs = IVAL(inbuf,smb_vwv3); - int smb_dsize = SVAL(inbuf,smb_vwv10); - int smb_doff = SVAL(inbuf,smb_vwv11); - BOOL write_through = BITSETW(inbuf+smb_vwv7,0); - int cnum; - int nwritten = -1; - char *data; - - cnum = SVAL(inbuf,smb_tid); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - data = smb_base(inbuf) + smb_doff; - - if (is_locked(fnum,cnum,smb_dsize,smb_offs)) - return(ERROR(ERRDOS,ERRlock)); - - seek_file(fnum,smb_offs); - - /* X/Open SMB protocol says that, unlike SMBwrite - if the length is zero then NO truncation is - done, just a write of zero. To truncate a file, - use SMBwrite. */ - if(smb_dsize == 0) - nwritten = 0; - else - nwritten = write_file(fnum,data,smb_dsize); - - if(((nwritten == 0) && (smb_dsize != 0))||(nwritten < 0)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - set_message(outbuf,6,0,True); - - SSVAL(outbuf,smb_vwv2,nwritten); - - if (nwritten < smb_dsize) { - CVAL(outbuf,smb_rcls) = ERRHRD; - SSVAL(outbuf,smb_err,ERRdiskfull); - } - - DEBUG(3,("%s writeX fnum=%d cnum=%d num=%d wrote=%d\n",timestring(),fnum,cnum,smb_dsize,nwritten)); - - chain_fnum = fnum; - - if (lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to a lseek -****************************************************************************/ -int reply_lseek(char *inbuf,char *outbuf) -{ - int cnum,fnum; - uint32 startpos; - int32 res= -1; - int mode,umode; - int outsize = 0; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - mode = SVAL(inbuf,smb_vwv1) & 3; - startpos = IVAL(inbuf,smb_vwv2); - - switch (mode & 3) - { - case 0: umode = SEEK_SET; break; - case 1: umode = SEEK_CUR; break; - case 2: umode = SEEK_END; break; - default: - umode = SEEK_SET; break; - } - - res = lseek(Files[fnum].fd_ptr->fd,startpos,umode); - Files[fnum].pos = res; - - outsize = set_message(outbuf,2,0,True); - SIVALS(outbuf,smb_vwv0,res); - - DEBUG(3,("%s lseek fnum=%d cnum=%d ofs=%d mode=%d\n",timestring(),fnum,cnum,startpos,mode)); - - return(outsize); -} - - -/**************************************************************************** - reply to a flush -****************************************************************************/ -int reply_flush(char *inbuf,char *outbuf) -{ - int cnum, fnum; - int outsize = set_message(outbuf,0,0,True); - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - if (fnum != 0xFFFF) { - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - } - - if (fnum == 0xFFFF) - { - int i; - for (i=0;i<MAX_OPEN_FILES;i++) - if (OPEN_FNUM(i)) - sync_file(i); - } - else - sync_file(fnum); - - DEBUG(3,("%s flush fnum=%d\n",timestring(),fnum)); - return(outsize); -} - - -/**************************************************************************** - reply to a exit -****************************************************************************/ -int reply_exit(char *inbuf,char *outbuf) -{ - int outsize = set_message(outbuf,0,0,True); - DEBUG(3,("%s exit\n",timestring())); - - return(outsize); -} - - -/**************************************************************************** - reply to a close -****************************************************************************/ -int reply_close(char *inbuf,char *outbuf) -{ - int fnum,cnum; - int outsize = 0; - time_t mtime; - int32 eclass = 0, err = 0; - - outsize = set_message(outbuf,0,0,True); - - cnum = SVAL(inbuf,smb_tid); - - fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); - - if(HAS_CACHED_ERROR(fnum)) { - eclass = Files[fnum].wbmpx_ptr->wr_errclass; - err = Files[fnum].wbmpx_ptr->wr_error; - } - - mtime = make_unix_date3(inbuf+smb_vwv1); - - /* try and set the date */ - set_filetime(Files[fnum].name,mtime); - - close_file(fnum); - - /* We have a cached error */ - if(eclass || err) - return(ERROR(eclass,err)); - - DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n", - timestring(),Files[fnum].fd_ptr->fd,fnum,cnum, - Connections[cnum].num_files_open)); - - return(outsize); -} - - -/**************************************************************************** - reply to a writeclose (Core+ protocol) -****************************************************************************/ -int reply_writeclose(char *inbuf,char *outbuf) -{ - int cnum,numtowrite,fnum; - int nwritten = -1; - int outsize = 0; - int startpos; - char *data; - time_t mtime; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - numtowrite = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - mtime = make_unix_date3(inbuf+smb_vwv4); - data = smb_buf(inbuf) + 1; - - if (is_locked(fnum,cnum,numtowrite,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - seek_file(fnum,startpos); - - nwritten = write_file(fnum,data,numtowrite); - - set_filetime(Files[fnum].name,mtime); - - close_file(fnum); - - DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", - timestring(),fnum,cnum,numtowrite,nwritten, - Connections[cnum].num_files_open)); - - if (nwritten <= 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize = set_message(outbuf,1,0,True); - - SSVAL(outbuf,smb_vwv0,nwritten); - return(outsize); -} - - -/**************************************************************************** - reply to a lock -****************************************************************************/ -int reply_lock(char *inbuf,char *outbuf) -{ - int fnum,cnum; - int outsize = set_message(outbuf,0,0,True); - uint32 count,offset; - int eclass; - uint32 ecode; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); - - DEBUG(3,("%s lock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); - - if(!do_lock( fnum, cnum, count, offset, &eclass, &ecode)) - return (ERROR(eclass,ecode)); - - return(outsize); -} - - -/**************************************************************************** - reply to a unlock -****************************************************************************/ -int reply_unlock(char *inbuf,char *outbuf) -{ - int fnum,cnum; - int outsize = set_message(outbuf,0,0,True); - uint32 count,offset; - int eclass; - uint32 ecode; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - count = IVAL(inbuf,smb_vwv1); - offset = IVAL(inbuf,smb_vwv3); - - if(!do_unlock(fnum, cnum, count, offset, &eclass, &ecode)) - return (ERROR(eclass,ecode)); - - DEBUG(3,("%s unlock fd=%d fnum=%d cnum=%d ofs=%d cnt=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,offset,count)); - - return(outsize); -} - - -/**************************************************************************** - reply to a tdis -****************************************************************************/ -int reply_tdis(char *inbuf,char *outbuf) -{ - int cnum; - int outsize = set_message(outbuf,0,0,True); - uint16 vuid; - - cnum = SVAL(inbuf,smb_tid); - vuid = SVAL(inbuf,smb_uid); - - if (!OPEN_CNUM(cnum)) { - DEBUG(4,("Invalid cnum in tdis (%d)\n",cnum)); - return(ERROR(ERRSRV,ERRinvnid)); - } - - Connections[cnum].used = False; - - close_cnum(cnum,vuid); - - DEBUG(3,("%s tdis cnum=%d\n",timestring(),cnum)); - - return outsize; -} - - - -/**************************************************************************** - reply to a echo -****************************************************************************/ -int reply_echo(char *inbuf,char *outbuf) -{ - int cnum; - int smb_reverb = SVAL(inbuf,smb_vwv0); - int seq_num; - int data_len = smb_buflen(inbuf); - int outsize = set_message(outbuf,1,data_len,True); - - cnum = SVAL(inbuf,smb_tid); - - /* According to the latest CIFS spec we shouldn't - care what the TID is. - */ - -#if 0 - if (cnum != 0xFFFF && !OPEN_CNUM(cnum)) - { - DEBUG(4,("Invalid cnum in echo (%d)\n",cnum)); - return(ERROR(ERRSRV,ERRinvnid)); - } -#endif - - /* copy any incoming data back out */ - if (data_len > 0) - memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len); - - if (smb_reverb > 100) - { - DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb)); - smb_reverb = 100; - } - - for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) - { - SSVAL(outbuf,smb_vwv0,seq_num); - - smb_setlen(outbuf,outsize - 4); - - send_smb(Client,outbuf); - } - - DEBUG(3,("%s echo %d times cnum=%d\n",timestring(),smb_reverb,cnum)); - - return -1; -} - - -/**************************************************************************** - reply to a printopen -****************************************************************************/ -int reply_printopen(char *inbuf,char *outbuf) -{ - pstring fname; - pstring fname2; - int cnum; - int fnum = -1; - int outsize = 0; - - *fname = *fname2 = 0; - - cnum = SVAL(inbuf,smb_tid); - - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); - - { - pstring s; - char *p; - StrnCpy(s,smb_buf(inbuf)+1,sizeof(pstring)-1); - p = s; - while (*p) - { - if (!(isalnum(*p) || strchr("._-",*p))) - *p = 'X'; - p++; - } - - if (strlen(s) > 10) s[10] = 0; - - sprintf(fname,"%s.XXXXXX",s); - } - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - strcpy(fname2,(char *)mktemp(fname)); - - if (!check_name(fname2,cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); - - /* Open for exclusive use, write only. */ - open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - /* force it to be a print file */ - Files[fnum].print_file = True; - - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fnum); - - DEBUG(3,("%s openprint %s fd=%d fnum=%d cnum=%d\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum)); - - return(outsize); -} - - -/**************************************************************************** - reply to a printclose -****************************************************************************/ -int reply_printclose(char *inbuf,char *outbuf) -{ - int fnum,cnum; - int outsize = set_message(outbuf,0,0,True); - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); - - close_file(fnum); - - DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); - - return(outsize); -} - - -/**************************************************************************** - reply to a printqueue -****************************************************************************/ -int reply_printqueue(char *inbuf,char *outbuf) -{ - int cnum; - int outsize = set_message(outbuf,2,3,True); - int max_count = SVAL(inbuf,smb_vwv0); - int start_index = SVAL(inbuf,smb_vwv1); - uint16 vuid; - - cnum = SVAL(inbuf,smb_tid); - vuid = SVAL(inbuf,smb_uid); - -/* allow checking the queue for anyone */ -#if 0 - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); -#endif - - SSVAL(outbuf,smb_vwv0,0); - SSVAL(outbuf,smb_vwv1,0); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,0); - - DEBUG(3,("%s printqueue cnum=%d start_index=%d max_count=%d\n", - timestring(),cnum,start_index,max_count)); - - if (!OPEN_CNUM(cnum) || !Connections[cnum].printer) - { - int i; - cnum = -1; - - for (i=0;i<MAX_CONNECTIONS;i++) - if (CAN_PRINT(i) && Connections[i].printer) - cnum = i; - - if (cnum == -1) - for (i=0;i<MAX_CONNECTIONS;i++) - if (OPEN_CNUM(i)) - cnum = i; - - if (!OPEN_CNUM(cnum)) - return(ERROR(ERRSRV,ERRinvnid)); - - DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum)); - } - - if (!become_user(cnum,vuid)) - return(ERROR(ERRSRV,ERRinvnid)); - - { - print_queue_struct *queue = NULL; - char *p = smb_buf(outbuf) + 3; - int count = get_printqueue(SNUM(cnum),cnum,&queue,NULL); - int num_to_get = ABS(max_count); - int first = (max_count>0?start_index:start_index+max_count+1); - int i; - - if (first >= count) - num_to_get = 0; - else - num_to_get = MIN(num_to_get,count-first); - - - for (i=first;i<first+num_to_get;i++) - { - put_dos_date2(p,0,queue[i].time); - CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3); - SSVAL(p,5,queue[i].job); - SIVAL(p,7,queue[i].size); - CVAL(p,11) = 0; - StrnCpy(p+12,queue[i].user,16); - p += 28; - } - - if (count > 0) - { - outsize = set_message(outbuf,2,28*count+3,False); - SSVAL(outbuf,smb_vwv0,count); - SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); - CVAL(smb_buf(outbuf),0) = 1; - SSVAL(smb_buf(outbuf),1,28*count); - } - - if (queue) free(queue); - - DEBUG(3,("%d entries returned in queue\n",count)); - } - - return(outsize); -} - - -/**************************************************************************** - reply to a printwrite -****************************************************************************/ -int reply_printwrite(char *inbuf,char *outbuf) -{ - int cnum,numtowrite,fnum; - int outsize = set_message(outbuf,0,0,True); - char *data; - - cnum = SVAL(inbuf,smb_tid); - - if (!CAN_PRINT(cnum)) - return(ERROR(ERRDOS,ERRnoaccess)); - - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - numtowrite = SVAL(smb_buf(inbuf),1); - data = smb_buf(inbuf) + 3; - - if (write_file(fnum,data,numtowrite) != numtowrite) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - DEBUG(3,("%s printwrite fnum=%d cnum=%d num=%d\n",timestring(),fnum,cnum,numtowrite)); - - return(outsize); -} - - -/**************************************************************************** - reply to a mkdir -****************************************************************************/ -int reply_mkdir(char *inbuf,char *outbuf) -{ - pstring directory; - int cnum; - int outsize,ret= -1; - - strcpy(directory,smb_buf(inbuf) + 1); - cnum = SVAL(inbuf,smb_tid); - unix_convert(directory,cnum,0); - - if (check_name(directory,cnum)) - ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); - - if (ret < 0) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s mkdir %s cnum=%d ret=%d\n",timestring(),directory,cnum,ret)); - - return(outsize); -} - - -/**************************************************************************** - reply to a rmdir -****************************************************************************/ -int reply_rmdir(char *inbuf,char *outbuf) -{ - pstring directory; - int cnum; - int outsize = 0; - BOOL ok = False; - - cnum = SVAL(inbuf,smb_tid); - strcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,cnum,0); - - if (check_name(directory,cnum)) - { - dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = (sys_rmdir(directory) == 0); - if (!ok) - DEBUG(3,("couldn't remove directory %s : %s\n", - directory,strerror(errno))); - } - - if (!ok) - return(UNIXERROR(ERRDOS,ERRbadpath)); - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s rmdir %s\n",timestring(),directory)); - - return(outsize); -} - - -/******************************************************************* -resolve wildcards in a filename rename -********************************************************************/ -static BOOL resolve_wildcards(char *name1,char *name2) -{ - fstring root1,root2; - fstring ext1,ext2; - char *p,*p2; - - name1 = strrchr(name1,'/'); - name2 = strrchr(name2,'/'); - - if (!name1 || !name2) return(False); - - strcpy(root1,name1); - strcpy(root2,name2); - p = strrchr(root1,'.'); - if (p) { - *p = 0; - strcpy(ext1,p+1); - } else { - strcpy(ext1,""); - } - p = strrchr(root2,'.'); - if (p) { - *p = 0; - strcpy(ext2,p+1); - } else { - strcpy(ext2,""); - } - - p = root1; - p2 = root2; - while (*p2) { - if (*p2 == '?') { - *p2 = *p; - p2++; - } else { - p2++; - } - if (*p) p++; - } - - p = ext1; - p2 = ext2; - while (*p2) { - if (*p2 == '?') { - *p2 = *p; - p2++; - } else { - p2++; - } - if (*p) p++; - } - - strcpy(name2,root2); - if (ext2[0]) { - strcat(name2,"."); - strcat(name2,ext2); - } - - return(True); -} - -/******************************************************************* -check if a user is allowed to rename a file -********************************************************************/ -static BOOL can_rename(char *fname,int cnum) -{ - struct stat sbuf; - - if (!CAN_WRITE(cnum)) return(False); - - if (sys_lstat(fname,&sbuf) != 0) return(False); - if (!check_file_sharing(cnum,fname)) return(False); - - return(True); -} - -/**************************************************************************** - reply to a mv -****************************************************************************/ -int reply_mv(char *inbuf,char *outbuf) -{ - int outsize = 0; - pstring name; - int cnum; - pstring directory; - pstring mask,newname; - pstring newname_last_component; - char *p; - int count=0; - int error = ERRnoaccess; - BOOL has_wild; - BOOL exists=False; - - *directory = *mask = 0; - - cnum = SVAL(inbuf,smb_tid); - - strcpy(name,smb_buf(inbuf) + 1); - strcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); - - DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - - unix_convert(name,cnum,0); - unix_convert(newname,cnum,newname_last_component); - - /* - * Split the old name into directory and last component - * strings. Note that unix_convert may have stripped off a - * leading ./ from both name and newname if the rename is - * at the root of the share. We need to make sure either both - * name and newname contain a / character or neither of them do - * as this is checked in resolve_wildcards(). - */ - - p = strrchr(name,'/'); - if (!p) { - strcpy(directory,"."); - strcpy(mask,name); - } else { - *p = 0; - strcpy(directory,name); - strcpy(mask,p+1); - *p = '/'; /* Replace needed for exceptional test below. */ - } - - if (is_mangled(mask)) - check_mangled_stack(mask); - - has_wild = strchr(mask,'*') || strchr(mask,'?'); - - if (!has_wild) { - BOOL is_short_name = is_8_3(name, True); - - /* Add a terminating '/' to the directory name. */ - strcat(directory,"/"); - strcat(directory,mask); - - /* Ensure newname contains a '/' also */ - if(strrchr(newname,'/') == 0) { - pstring tmpstr; - - strcpy(tmpstr, "./"); - strcat(tmpstr, newname); - strcpy(newname, tmpstr); - } - - DEBUG(3,("reply_mv : case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", - case_sensitive, case_preserve, short_case_preserve, directory, - newname, newname_last_component, is_short_name)); - - /* - * Check for special case with case preserving and not - * case sensitive, if directory and newname are identical, - * and the old last component differs from the original - * last component only by case, then we should allow - * the rename (user is trying to change the case of the - * filename). - */ - if((case_sensitive == False) && ( ((case_preserve == True) && (is_short_name == False)) || - ((short_case_preserve == True) && (is_short_name == True))) && - strcsequal(directory, newname)) { - pstring newname_modified_last_component; - - /* - * Get the last component of the modified name. - * Note that we guarantee that newname contains a '/' - * character above. - */ - p = strrchr(newname,'/'); - strcpy(newname_modified_last_component,p+1); - - if(strcsequal(newname_modified_last_component, - newname_last_component) == False) { - /* - * Replace the modified last component with - * the original. - */ - strcpy(p+1, newname_last_component); - } - } - - if (resolve_wildcards(directory,newname) && - can_rename(directory,cnum) && - !file_exist(newname,NULL) && - !sys_rename(directory,newname)) count++; - - DEBUG(3,("reply_mv : %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed", - directory,newname)); - - if (!count) exists = file_exist(directory,NULL); - if (!count && exists && file_exist(newname,NULL)) { - exists = True; - error = 183; - } - } else { - void *dirptr = NULL; - char *dname; - pstring destname; - - if (check_name(directory,cnum)) - dirptr = OpenDir(directory); - - if (dirptr) - { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - strcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - strcpy(fname,dname); - - if(!mask_match(fname, mask, case_sensitive, False)) continue; - - error = ERRnoaccess; - sprintf(fname,"%s/%s",directory,dname); - if (!can_rename(fname,cnum)) continue; - strcpy(destname,newname); - - if (!resolve_wildcards(fname,destname)) continue; - - if (file_exist(destname,NULL)) { - error = 183; - continue; - } - if (!sys_rename(fname,destname)) count++; - DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname)); - } - CloseDir(dirptr); - } - } - - if (count == 0) { - if (exists) - return(ERROR(ERRDOS,error)); - else - return(UNIXERROR(ERRDOS,error)); - } - - outsize = set_message(outbuf,0,0,True); - - return(outsize); -} - -/******************************************************************* - copy a file as part of a reply_copy - ******************************************************************/ -static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, - int count,BOOL target_is_directory) -{ - int Access,action; - struct stat st; - int ret=0; - int fnum1,fnum2; - pstring dest; - - strcpy(dest,dest1); - if (target_is_directory) { - char *p = strrchr(src,'/'); - if (p) - p++; - else - p = src; - strcat(dest,"/"); - strcat(dest,p); - } - - if (!file_exist(src,&st)) return(False); - - fnum1 = find_free_file(); - if (fnum1<0) return(False); - open_file_shared(fnum1,cnum,src,(DENY_NONE<<4), - 1,0,&Access,&action); - - if (!Files[fnum1].open) return(False); - - if (!target_is_directory && count) - ofun = 1; - - fnum2 = find_free_file(); - if (fnum2<0) { - close_file(fnum1); - return(False); - } - open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, - ofun,st.st_mode,&Access,&action); - - if (!Files[fnum2].open) { - close_file(fnum1); - return(False); - } - - if ((ofun&3) == 1) { - lseek(Files[fnum2].fd_ptr->fd,0,SEEK_END); - } - - if (st.st_size) - ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); - - close_file(fnum1); - close_file(fnum2); - - return(ret == st.st_size); -} - - - -/**************************************************************************** - reply to a file copy. - ****************************************************************************/ -int reply_copy(char *inbuf,char *outbuf) -{ - int outsize = 0; - pstring name; - int cnum; - pstring directory; - pstring mask,newname; - char *p; - int count=0; - int error = ERRnoaccess; - BOOL has_wild; - BOOL exists=False; - int tid2 = SVAL(inbuf,smb_vwv0); - int ofun = SVAL(inbuf,smb_vwv1); - int flags = SVAL(inbuf,smb_vwv2); - BOOL target_is_directory=False; - - *directory = *mask = 0; - - cnum = SVAL(inbuf,smb_tid); - - strcpy(name,smb_buf(inbuf)); - strcpy(newname,smb_buf(inbuf) + 1 + strlen(name)); - - DEBUG(3,("reply_copy : %s -> %s\n",name,newname)); - - if (tid2 != cnum) { - /* can't currently handle inter share copies XXXX */ - DEBUG(3,("Rejecting inter-share copy\n")); - return(ERROR(ERRSRV,ERRinvdevice)); - } - - unix_convert(name,cnum,0); - unix_convert(newname,cnum,0); - - target_is_directory = directory_exist(newname,NULL); - - if ((flags&1) && target_is_directory) { - return(ERROR(ERRDOS,ERRbadfile)); - } - - if ((flags&2) && !target_is_directory) { - return(ERROR(ERRDOS,ERRbadpath)); - } - - if ((flags&(1<<5)) && directory_exist(name,NULL)) { - /* wants a tree copy! XXXX */ - DEBUG(3,("Rejecting tree copy\n")); - return(ERROR(ERRSRV,ERRerror)); - } - - p = strrchr(name,'/'); - if (!p) { - strcpy(directory,"./"); - strcpy(mask,name); - } else { - *p = 0; - strcpy(directory,name); - strcpy(mask,p+1); - } - - if (is_mangled(mask)) - check_mangled_stack(mask); - - has_wild = strchr(mask,'*') || strchr(mask,'?'); - - if (!has_wild) { - strcat(directory,"/"); - strcat(directory,mask); - if (resolve_wildcards(directory,newname) && - copy_file(directory,newname,cnum,ofun, - count,target_is_directory)) count++; - if (!count) exists = file_exist(directory,NULL); - } else { - void *dirptr = NULL; - char *dname; - pstring destname; - - if (check_name(directory,cnum)) - dirptr = OpenDir(directory); - - if (dirptr) - { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - strcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - strcpy(fname,dname); - - if(!mask_match(fname, mask, case_sensitive, False)) continue; - - error = ERRnoaccess; - sprintf(fname,"%s/%s",directory,dname); - strcpy(destname,newname); - if (resolve_wildcards(fname,destname) && - copy_file(directory,newname,cnum,ofun, - count,target_is_directory)) count++; - DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname)); - } - CloseDir(dirptr); - } - } - - if (count == 0) { - if (exists) - return(ERROR(ERRDOS,error)); - else - return(UNIXERROR(ERRDOS,error)); - } - - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,count); - - return(outsize); -} - - - -/**************************************************************************** - reply to a setdir -****************************************************************************/ -int reply_setdir(char *inbuf,char *outbuf) -{ - int cnum,snum; - int outsize = 0; - BOOL ok = False; - pstring newdir; - - cnum = SVAL(inbuf,smb_tid); - - snum = Connections[cnum].service; - if (!CAN_SETDIR(snum)) - return(ERROR(ERRDOS,ERRnoaccess)); - - strcpy(newdir,smb_buf(inbuf) + 1); - strlower(newdir); - - if (strlen(newdir) == 0) - ok = True; - else - { - ok = directory_exist(newdir,NULL); - if (ok) - string_set(&Connections[cnum].connectpath,newdir); - } - - if (!ok) - return(ERROR(ERRDOS,ERRbadpath)); - - outsize = set_message(outbuf,0,0,True); - CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh); - - DEBUG(3,("%s setdir %s cnum=%d\n",timestring(),newdir,cnum)); - - return(outsize); -} - - -/**************************************************************************** - reply to a lockingX request -****************************************************************************/ -int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) -{ - int fnum = GETFNUM(inbuf,smb_vwv2); - uint16 locktype = SVAL(inbuf,smb_vwv3); - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); - uint32 count, offset; - - int cnum; - int i; - char *data; - uint32 ecode=0, dummy2; - int eclass=0, dummy1; - - cnum = SVAL(inbuf,smb_tid); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - data = smb_buf(inbuf); - /* Data now points at the beginning of the list - of smb_unlkrng structs */ - for(i = 0; i < (int)num_ulocks; i++) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_unlock(fnum,cnum,count,offset,&eclass, &ecode)) - return ERROR(eclass,ecode); - } - - /* Now do any requested locks */ - data += 10*num_ulocks; - /* Data now points at the beginning of the list - of smb_lkrng structs */ - for(i = 0; i < (int)num_locks; i++) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - if(!do_lock(fnum,cnum,count,offset, &eclass, &ecode)) - break; - } - - /* If any of the above locks failed, then we must unlock - all of the previous locks (X/Open spec). */ - if(i != num_locks && num_locks != 0) { - for(; i >= 0; i--) { - count = IVAL(data,SMB_LKLEN_OFFSET(i)); - offset = IVAL(data,SMB_LKOFF_OFFSET(i)); - do_unlock(fnum,cnum,count,offset,&dummy1,&dummy2); - } - return ERROR(eclass,ecode); - } - - set_message(outbuf,2,0,True); - - DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", - timestring(),fnum,cnum,locktype,num_locks,num_ulocks)); - - chain_fnum = fnum; - - return chain_reply(inbuf,outbuf,length,bufsize); -} - - -/**************************************************************************** - reply to a SMBreadbmpx (read block multiplex) request -****************************************************************************/ -int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize) -{ - int cnum,fnum; - int nread = -1; - int total_read; - char *data; - int32 startpos; - int outsize, mincount, maxcount; - int max_per_packet; - int tcount; - int pad; - - /* this function doesn't seem to work - disable by default */ - if (!lp_readbmpx()) - return(ERROR(ERRSRV,ERRuseSTD)); - - outsize = set_message(outbuf,8,0,True); - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_READ(fnum); - CHECK_ERROR(fnum); - - startpos = IVAL(inbuf,smb_vwv1); - maxcount = SVAL(inbuf,smb_vwv3); - mincount = SVAL(inbuf,smb_vwv4); - - data = smb_buf(outbuf); - pad = ((int)data)%4; - if (pad) pad = 4 - pad; - data += pad; - - max_per_packet = bufsize-(outsize+pad); - tcount = maxcount; - total_read = 0; - - if (is_locked(fnum,cnum,maxcount,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - do - { - int N = MIN(max_per_packet,tcount-total_read); - - nread = read_file(fnum,data,startpos,N); - - if (nread <= 0) nread = 0; - - if (nread < N) - tcount = total_read + nread; - - set_message(outbuf,8,nread,False); - SIVAL(outbuf,smb_vwv0,startpos); - SSVAL(outbuf,smb_vwv2,tcount); - SSVAL(outbuf,smb_vwv6,nread); - SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf)); - - send_smb(Client,outbuf); - - total_read += nread; - startpos += nread; - } - while (total_read < tcount); - - return(-1); -} - - -/**************************************************************************** - reply to a SMBwritebmpx (write block multiplex primary) request -****************************************************************************/ -int reply_writebmpx(char *inbuf,char *outbuf) -{ - int cnum,numtowrite,fnum; - int nwritten = -1; - int outsize = 0; - int32 startpos; - int tcount, write_through, smb_doff; - char *data; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - CHECK_ERROR(fnum); - - tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv3); - write_through = BITSETW(inbuf+smb_vwv7,0); - numtowrite = SVAL(inbuf,smb_vwv10); - smb_doff = SVAL(inbuf,smb_vwv11); - - data = smb_base(inbuf) + smb_doff; - - /* If this fails we need to send an SMBwriteC response, - not an SMBwritebmpx - set this up now so we don't forget */ - CVAL(outbuf,smb_com) = SMBwritec; - - if (is_locked(fnum,cnum,tcount,startpos)) - return(ERROR(ERRDOS,ERRlock)); - - seek_file(fnum,startpos); - nwritten = write_file(fnum,data,numtowrite); - - if(lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); - - if(nwritten < numtowrite) - return(UNIXERROR(ERRHRD,ERRdiskfull)); - - /* If the maximum to be written to this file - is greater than what we just wrote then set - up a secondary struct to be attached to this - fd, we will use this to cache error messages etc. */ - if(tcount > nwritten) - { - write_bmpx_struct *wbms; - if(Files[fnum].wbmpx_ptr != NULL) - wbms = Files[fnum].wbmpx_ptr; /* Use an existing struct */ - else - wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct)); - if(!wbms) - { - DEBUG(0,("Out of memory in reply_readmpx\n")); - return(ERROR(ERRSRV,ERRnoresource)); - } - wbms->wr_mode = write_through; - wbms->wr_discard = False; /* No errors yet */ - wbms->wr_total_written = nwritten; - wbms->wr_errclass = 0; - wbms->wr_error = 0; - Files[fnum].wbmpx_ptr = wbms; - } - - /* We are returning successfully, set the message type back to - SMBwritebmpx */ - CVAL(outbuf,smb_com) = SMBwriteBmpx; - - outsize = set_message(outbuf,1,0,True); - - SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */ - - DEBUG(3,("%s writebmpx fnum=%d cnum=%d num=%d wrote=%d\n", - timestring(),fnum,cnum,numtowrite,nwritten)); - - if (write_through && tcount==nwritten) { - /* we need to send both a primary and a secondary response */ - smb_setlen(outbuf,outsize - 4); - send_smb(Client,outbuf); - - /* now the secondary */ - outsize = set_message(outbuf,1,0,True); - CVAL(outbuf,smb_com) = SMBwritec; - SSVAL(outbuf,smb_vwv0,nwritten); - } - - return(outsize); -} - - -/**************************************************************************** - reply to a SMBwritebs (write block multiplex secondary) request -****************************************************************************/ -int reply_writebs(char *inbuf,char *outbuf) -{ - int cnum,numtowrite,fnum; - int nwritten = -1; - int outsize = 0; - int32 startpos; - int tcount, write_through, smb_doff; - char *data; - write_bmpx_struct *wbms; - BOOL send_response = False; - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - CHECK_FNUM(fnum,cnum); - CHECK_WRITE(fnum); - - tcount = SVAL(inbuf,smb_vwv1); - startpos = IVAL(inbuf,smb_vwv2); - numtowrite = SVAL(inbuf,smb_vwv6); - smb_doff = SVAL(inbuf,smb_vwv7); - - data = smb_base(inbuf) + smb_doff; - - /* We need to send an SMBwriteC response, not an SMBwritebs */ - CVAL(outbuf,smb_com) = SMBwritec; - - /* This fd should have an auxiliary struct attached, - check that it does */ - wbms = Files[fnum].wbmpx_ptr; - if(!wbms) return(-1); - - /* If write through is set we can return errors, else we must - cache them */ - write_through = wbms->wr_mode; - - /* Check for an earlier error */ - if(wbms->wr_discard) - return -1; /* Just discard the packet */ - - seek_file(fnum,startpos); - nwritten = write_file(fnum,data,numtowrite); - - if(lp_syncalways(SNUM(cnum)) || write_through) - sync_file(fnum); - - if (nwritten < numtowrite) - { - if(write_through) { - /* We are returning an error - we can delete the aux struct */ - if (wbms) free((char *)wbms); - Files[fnum].wbmpx_ptr = NULL; - return(ERROR(ERRHRD,ERRdiskfull)); - } - return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); - } - - /* Increment the total written, if this matches tcount - we can discard the auxiliary struct (hurrah !) and return a writeC */ - wbms->wr_total_written += nwritten; - if(wbms->wr_total_written >= tcount) - { - if (write_through) { - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,wbms->wr_total_written); - send_response = True; - } - - free((char *)wbms); - Files[fnum].wbmpx_ptr = NULL; - } - - if(send_response) - return(outsize); - - return(-1); -} - - -/**************************************************************************** - reply to a SMBsetattrE -****************************************************************************/ -int reply_setattrE(char *inbuf,char *outbuf) -{ - int cnum,fnum; - struct utimbuf unix_times; - int outsize = 0; - - outsize = set_message(outbuf,0,0,True); - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - /* Convert the DOS times into unix times. Ignore create - time as UNIX can't set this. - */ - unix_times.actime = make_unix_date2(inbuf+smb_vwv3); - unix_times.modtime = make_unix_date2(inbuf+smb_vwv5); - - /* Set the date on this file */ - if(sys_utime(Files[fnum].name, &unix_times)) - return(ERROR(ERRDOS,ERRnoaccess)); - - DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); - - return(outsize); -} - - -/**************************************************************************** - reply to a SMBgetattrE -****************************************************************************/ -int reply_getattrE(char *inbuf,char *outbuf) -{ - int cnum,fnum; - struct stat sbuf; - int outsize = 0; - int mode; - - outsize = set_message(outbuf,11,0,True); - - cnum = SVAL(inbuf,smb_tid); - fnum = GETFNUM(inbuf,smb_vwv0); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - /* Do an fstat on this file */ - if(fstat(Files[fnum].fd_ptr->fd, &sbuf)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - mode = dos_mode(cnum,Files[fnum].name,&sbuf); - - /* Convert the times into dos times. Set create - date to be last modify date as UNIX doesn't save - this */ - put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime); - put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime); - put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime); - if (mode & aDIR) - { - SIVAL(outbuf,smb_vwv6,0); - SIVAL(outbuf,smb_vwv8,0); - } - else - { - SIVAL(outbuf,smb_vwv6,sbuf.st_size); - SIVAL(outbuf,smb_vwv8,ROUNDUP(sbuf.st_size,1024)); - } - SSVAL(outbuf,smb_vwv10, mode); - - DEBUG(3,("%s reply_getattrE fnum=%d cnum=%d\n",timestring(),fnum,cnum)); - - return(outsize); -} - - - - - diff --git a/source/smbd/smbrun.c b/source/smbd/smbrun.c deleted file mode 100644 index 42ce7f60ad0..00000000000 --- a/source/smbd/smbrun.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - external program running routine - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - -/******************************************************************* -close the low 3 fd's and open dev/null in their place -********************************************************************/ -static void close_fds(void) -{ - int fd; - int i; - close(0); close(1); close(2); - /* try and use up these file descriptors, so silly - library routines writing to stdout etc won't cause havoc */ - for (i=0;i<3;i++) { - fd = open("/dev/null",O_RDWR,0); - if (fd < 0) fd = open("/dev/null",O_WRONLY,0); - if (fd != i) return; - } -} - - -/* -This is a wrapper around the system() call to allow commands to run correctly -as non root from a program which is switching between root and non-root - -It takes 3 arguments as uid,gid,command and runs command after -becoming a non-root user */ - int main(int argc,char *argv[]) -{ - int uid,gid; - - close_fds(); - - if (argc != 4) exit(2); - - uid = atoi(argv[1]); - gid = atoi(argv[2]); - - /* first become root - we may need to do this in order to lose - our privilages! */ -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); -#endif - -#ifdef USE_SETFS - setfsuid(uid); - setfsgid(gid); -#endif - -#ifdef USE_SETRES - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); -#else - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); -#endif - - - /* paranoia :-) */ - if (getuid() != uid) - return(3); - - if (geteuid() != getuid()) - return(4); - - /* this is to make sure that the system() call doesn't run forever */ - alarm(30); - - return(system(argv[3])); -} diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c deleted file mode 100644 index 1f727c4ecdf..00000000000 --- a/source/smbd/trans2.c +++ /dev/null @@ -1,1651 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-1997 - - Extensively modified by Andrew Tridgell, 1995 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "trans2.h" - -extern int DEBUGLEVEL; -extern int Protocol; -extern connection_struct Connections[]; -extern files_struct Files[]; -extern BOOL case_sensitive; -extern int Client; - -/**************************************************************************** - Send the required number of replies back. - We assume all fields other than the data fields are - set correctly for the type of call. - HACK ! Always assumes smb_setup field is zero. -****************************************************************************/ -static int send_trans2_replies(char *outbuf, int bufsize, char *params, - int paramsize, char *pdata, int datasize) -{ - /* As we are using a protocol > LANMAN1 then the max_send - variable must have been set in the sessetupX call. - This takes precedence over the max_xmit field in the - global struct. These different max_xmit variables should - be merged as this is now too confusing */ - - extern int max_send; - int data_to_send = datasize; - int params_to_send = paramsize; - int useable_space; - char *pp = params; - char *pd = pdata; - int params_sent_thistime, data_sent_thistime, total_sent_thistime; - int alignment_offset = 1; - - /* Initially set the wcnt area to be 10 - this is true for all - trans2 replies */ - set_message(outbuf,10,0,True); - - /* If there genuinely are no parameters or data to send just send - the empty packet */ - if(params_to_send == 0 && data_to_send == 0) - { - send_smb(Client,outbuf); - return 0; - } - - /* Space is bufsize minus Netbios over TCP header minus SMB header */ - /* The alignment_offset is to align the param and data bytes on an even byte - boundary. NT 4.0 Beta needs this to work correctly. */ - useable_space = bufsize - ((smb_buf(outbuf)+alignment_offset) - outbuf); - /* useable_space can never be more than max_send minus the - alignment offset. */ - useable_space = MIN(useable_space, max_send - alignment_offset); - - while( params_to_send || data_to_send) - { - /* Calculate whether we will totally or partially fill this packet */ - total_sent_thistime = params_to_send + data_to_send + alignment_offset; - /* We can never send more than useable_space */ - total_sent_thistime = MIN(total_sent_thistime, useable_space); - - set_message(outbuf, 10, total_sent_thistime, True); - - /* Set total params and data to be sent */ - SSVAL(outbuf,smb_tprcnt,paramsize); - SSVAL(outbuf,smb_tdrcnt,datasize); - - /* Calculate how many parameters and data we can fit into - this packet. Parameters get precedence */ - - params_sent_thistime = MIN(params_to_send,useable_space); - data_sent_thistime = useable_space - params_sent_thistime; - data_sent_thistime = MIN(data_sent_thistime,data_to_send); - - SSVAL(outbuf,smb_prcnt, params_sent_thistime); - if(params_sent_thistime == 0) - { - SSVAL(outbuf,smb_proff,0); - SSVAL(outbuf,smb_prdisp,0); - } else { - /* smb_proff is the offset from the start of the SMB header to the - parameter bytes, however the first 4 bytes of outbuf are - the Netbios over TCP header. Thus use smb_base() to subtract - them from the calculation */ - SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf))); - /* Absolute displacement of param bytes sent in this packet */ - SSVAL(outbuf,smb_prdisp,pp - params); - } - - SSVAL(outbuf,smb_drcnt, data_sent_thistime); - if(data_sent_thistime == 0) - { - SSVAL(outbuf,smb_droff,0); - SSVAL(outbuf,smb_drdisp, 0); - } else { - /* The offset of the data bytes is the offset of the - parameter bytes plus the number of parameters being sent this time */ - SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - - smb_base(outbuf)) + params_sent_thistime); - SSVAL(outbuf,smb_drdisp, pd - pdata); - } - - /* Copy the param bytes into the packet */ - if(params_sent_thistime) - memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime); - /* Copy in the data bytes */ - if(data_sent_thistime) - memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime,pd,data_sent_thistime); - - DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n", - params_sent_thistime, data_sent_thistime, useable_space)); - DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n", - params_to_send, data_to_send, paramsize, datasize)); - - /* Send the packet */ - send_smb(Client,outbuf); - - pp += params_sent_thistime; - pd += data_sent_thistime; - - params_to_send -= params_sent_thistime; - data_to_send -= data_sent_thistime; - - /* Sanity check */ - if(params_to_send < 0 || data_to_send < 0) - { - DEBUG(2,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!", - params_to_send, data_to_send)); - return -1; - } - } - - return 0; -} - - -/**************************************************************************** - reply to a TRANSACT2_OPEN -****************************************************************************/ -static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, - char **pparams, char **ppdata) -{ - char *params = *pparams; - int16 open_mode = SVAL(params, 2); - int16 open_attr = SVAL(params,6); - BOOL oplock_request = BITSETW(params,1); -#if 0 - BOOL return_additional_info = BITSETW(params,0); - int16 open_sattr = SVAL(params, 4); - time_t open_time = make_unix_date3(params+8); -#endif - int16 open_ofun = SVAL(params,12); - int32 open_size = IVAL(params,14); - char *pname = ¶ms[28]; - int16 namelen = strlen(pname)+1; - - pstring fname; - int fnum = -1; - int unixmode; - int size=0,fmode=0,mtime=0,rmode; - int32 inode = 0; - struct stat sbuf; - int smb_action = 0; - - StrnCpy(fname,pname,namelen); - - DEBUG(3,("trans2open %s cnum=%d mode=%d attr=%d ofun=%d size=%d\n", - fname,cnum,open_mode, open_attr, open_ofun, open_size)); - - /* XXXX we need to handle passed times, sattr and flags */ - - unix_convert(fname,cnum,0); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - unixmode = unix_mode(cnum,open_attr | aARCH); - - - open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, - &rmode,&smb_action); - - if (!Files[fnum].open) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - size = sbuf.st_size; - fmode = dos_mode(cnum,fname,&sbuf); - mtime = sbuf.st_mtime; - inode = sbuf.st_ino; - if (fmode & aDIR) { - close_file(fnum); - return(ERROR(ERRDOS,ERRnoaccess)); - } - - /* Realloc the size of parameters and data we will return */ - params = *pparams = Realloc(*pparams, 28); - if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); - - bzero(params,28); - SSVAL(params,0,fnum); - SSVAL(params,2,fmode); - put_dos_date2(params,4, mtime); - SIVAL(params,8, size); - SSVAL(params,12,rmode); - - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= (1<<15); - } - - SSVAL(params,18,smb_action); - SIVAL(params,20,inode); - - /* Send the required number of replies */ - send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0); - - return -1; -} - -/**************************************************************************** - get a level dependent lanman2 dir entry. -****************************************************************************/ -static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_level, - int requires_resume_key, - BOOL dont_descend,char **ppdata, - char *base_data, int space_remaining, - BOOL *out_of_space, - int *last_name_off) -{ - char *dname; - BOOL found = False; - struct stat sbuf; - pstring mask; - pstring pathreal; - pstring fname; - BOOL matched; - char *p, *pdata = *ppdata; - int reskey=0, prev_dirpos=0; - int mode=0; - uint32 size=0,len; - uint32 mdate=0, adate=0, cdate=0; - char *nameptr; - BOOL isrootdir = (strequal(Connections[cnum].dirpath,"./") || - strequal(Connections[cnum].dirpath,".") || - strequal(Connections[cnum].dirpath,"/")); - BOOL was_8_3; - int nt_extmode; /* Used for NT connections instead of mode */ - BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/'); - - *fname = 0; - *out_of_space = False; - - if (!Connections[cnum].dirptr) - return(False); - - p = strrchr(path_mask,'/'); - if(p != NULL) - { - if(p[1] == '\0') - strcpy(mask,"*.*"); - else - strcpy(mask, p+1); - } - else - strcpy(mask, path_mask); - - while (!found) - { - /* Needed if we run out of space */ - prev_dirpos = TellDir(Connections[cnum].dirptr); - dname = ReadDirName(Connections[cnum].dirptr); - - reskey = TellDir(Connections[cnum].dirptr); - - DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", - Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); - - if (!dname) - return(False); - - matched = False; - - strcpy(fname,dname); - - if(mask_match(fname, mask, case_sensitive, True)) - { - BOOL isdots = (strequal(fname,"..") || strequal(fname,".")); - if (dont_descend && !isdots) - continue; - - if (isrootdir && isdots) - continue; - - strcpy(pathreal,Connections[cnum].dirpath); - if(needslash) - strcat(pathreal,"/"); - strcat(pathreal,fname); - if (sys_stat(pathreal,&sbuf) != 0) - { - DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno))); - continue; - } - - mode = dos_mode(cnum,pathreal,&sbuf); - - if (!dir_check_ftype(cnum,mode,&sbuf,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype)); - continue; - } - - size = sbuf.st_size; - mdate = sbuf.st_mtime; - adate = sbuf.st_atime; - cdate = sbuf.st_ctime; - if(mode & aDIR) - size = 0; - - DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname)); - - found = True; - } - } - - - - p = pdata; - nameptr = p; - - name_map_mangle(fname,False,SNUM(cnum)); - - nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL; - - switch (info_level) - { - case 1: - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - put_dos_date2(p,l1_fdateCreation,cdate); - put_dos_date2(p,l1_fdateLastAccess,adate); - put_dos_date2(p,l1_fdateLastWrite,mdate); - SIVAL(p,l1_cbFile,size); - SIVAL(p,l1_cbFileAlloc,ROUNDUP(size,1024)); - SSVAL(p,l1_attrFile,mode); - SCVAL(p,l1_cchName,strlen(fname)); - strcpy(p + l1_achName, fname); - nameptr = p + l1_achName; - p += l1_achName + strlen(fname) + 1; - break; - - case 2: - /* info_level 2 */ - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - put_dos_date2(p,l2_fdateCreation,cdate); - put_dos_date2(p,l2_fdateLastAccess,adate); - put_dos_date2(p,l2_fdateLastWrite,mdate); - SIVAL(p,l2_cbFile,size); - SIVAL(p,l2_cbFileAlloc,ROUNDUP(size,1024)); - SSVAL(p,l2_attrFile,mode); - SIVAL(p,l2_cbList,0); /* No extended attributes */ - SCVAL(p,l2_cchName,strlen(fname)); - strcpy(p + l2_achName, fname); - nameptr = p + l2_achName; - p += l2_achName + strlen(fname) + 1; - break; - - case 3: - SIVAL(p,0,reskey); - put_dos_date2(p,4,cdate); - put_dos_date2(p,8,adate); - put_dos_date2(p,12,mdate); - SIVAL(p,16,size); - SIVAL(p,20,ROUNDUP(size,1024)); - SSVAL(p,24,mode); - SIVAL(p,26,4); - CVAL(p,30) = strlen(fname); - strcpy(p+31, fname); - nameptr = p+31; - p += 31 + strlen(fname) + 1; - break; - - case 4: - if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; - } - SIVAL(p,0,33+strlen(fname)+1); - put_dos_date2(p,4,cdate); - put_dos_date2(p,8,adate); - put_dos_date2(p,12,mdate); - SIVAL(p,16,size); - SIVAL(p,20,ROUNDUP(size,1024)); - SSVAL(p,24,mode); - CVAL(p,32) = strlen(fname); - strcpy(p + 33, fname); - nameptr = p+33; - p += 33 + strlen(fname) + 1; - break; - - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - was_8_3 = is_8_3(fname, True); - len = 94+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; - SIVAL(p,0,0); p += 4; - if (!was_8_3) { - strcpy(p+2,fname); - if (!name_map_mangle(p+2,True,SNUM(cnum))) - (p+2)[12] = 0; - } else - *(p+2) = 0; - strupper(p+2); - SSVAL(p,0,strlen(p+2)); - p += 2 + 24; - /* nameptr = p; */ - strcpy(p,fname); p += strlen(p); - p = pdata + len; - break; - - case SMB_FIND_FILE_DIRECTORY_INFO: - len = 64+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; - strcpy(p,fname); - p = pdata + len; - break; - - - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - len = 68+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; - SIVAL(p,0,reskey); p += 4; - put_long_date(p,cdate); p += 8; - put_long_date(p,adate); p += 8; - put_long_date(p,mdate); p += 8; - put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; - SIVAL(p,0,0); p += 4; - strcpy(p,fname); - p = pdata + len; - break; - - case SMB_FIND_FILE_NAMES_INFO: - len = 12+strlen(fname); - len = (len + 3) & ~3; - SIVAL(p,0,len); p += 4; - SIVAL(p,0,reskey); p += 4; - SIVAL(p,0,strlen(fname)); p += 4; - strcpy(p,fname); - p = pdata + len; - break; - - default: - return(False); - } - - - if (PTR_DIFF(p,pdata) > space_remaining) { - /* Move the dirptr back to prev_dirpos */ - SeekDir(Connections[cnum].dirptr, prev_dirpos); - *out_of_space = True; - DEBUG(9,("get_lanman2_dir_entry: out of space\n")); - return False; /* Not finished - just out of space */ - } - - /* Setup the last_filename pointer, as an offset from base_data */ - *last_name_off = PTR_DIFF(nameptr,base_data); - /* Advance the data pointer to the next slot */ - *ppdata = p; - return(found); -} - -/**************************************************************************** - reply to a TRANS2_FINDFIRST -****************************************************************************/ -static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum, - char **pparams, char **ppdata) -{ - /* We must be careful here that we don't return more than the - allowed number of data bytes. If this means returning fewer than - maxentries then so be it. We assume that the redirector has - enough room for the fixed number of parameter bytes it has - requested. */ - uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt); - char *params = *pparams; - char *pdata = *ppdata; - int dirtype = SVAL(params,0); - int maxentries = SVAL(params,2); - BOOL close_after_first = BITSETW(params+4,0); - BOOL close_if_end = BITSETW(params+4,1); - BOOL requires_resume_key = BITSETW(params+4,2); - int info_level = SVAL(params,6); - pstring directory; - pstring mask; - char *p, *wcard; - int last_name_off=0; - int dptr_num = -1; - int numentries = 0; - int i; - BOOL finished = False; - BOOL dont_descend = False; - BOOL out_of_space = False; - int space_remaining; - - *directory = *mask = 0; - - DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", - dirtype, maxentries, close_after_first, close_if_end, requires_resume_key, - info_level, max_data_bytes)); - - switch (info_level) - { - case 1: - case 2: - case 3: - case 4: - case SMB_FIND_FILE_DIRECTORY_INFO: - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - case SMB_FIND_FILE_NAMES_INFO: - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - break; - default: - return(ERROR(ERRDOS,ERRunknownlevel)); - } - - strcpy(directory, params + 12); /* Complete directory path with - wildcard mask appended */ - - DEBUG(5,("path=%s\n",directory)); - - unix_convert(directory,cnum,0); - if(!check_name(directory,cnum)) { - return(ERROR(ERRDOS,ERRbadpath)); - } - - p = strrchr(directory,'/'); - if(p == NULL) { - strcpy(mask,directory); - strcpy(directory,"./"); - } else { - strcpy(mask,p+1); - *p = 0; - } - - DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); - - pdata = *ppdata = Realloc(*ppdata, max_data_bytes + 1024); - if(!*ppdata) - return(ERROR(ERRDOS,ERRnomem)); - bzero(pdata,max_data_bytes); - - /* Realloc the params space */ - params = *pparams = Realloc(*pparams, 10); - if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); - - dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) - return(ERROR(ERRDOS,ERRbadpath)); - - /* convert the formatted masks */ - { - p = mask; - while (*p) { - if (*p == '<') *p = '*'; - if (*p == '>') *p = '?'; - if (*p == '"') *p = '.'; - p++; - } - } - - /* a special case for 16 bit apps */ - if (strequal(mask,"????????.???")) strcpy(mask,"*"); - - /* handle broken clients that send us old 8.3 format */ - string_sub(mask,"????????","*"); - string_sub(mask,".???",".*"); - - /* Save the wildcard match and attribs we are using on this directory - - needed as lanman2 assumes these are being saved between calls */ - - if(!(wcard = strdup(mask))) { - dptr_close(dptr_num); - return(ERROR(ERRDOS,ERRnomem)); - } - - dptr_set_wcard(dptr_num, wcard); - dptr_set_attr(dptr_num, dirtype); - - DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype)); - - /* We don't need to check for VOL here as this is returned by - a different TRANS2 call. */ - - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", - Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); - if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive)) - dont_descend = True; - - p = pdata; - space_remaining = max_data_bytes; - out_of_space = False; - - for (i=0;(i<maxentries) && !finished && !out_of_space;i++) - { - - /* this is a heuristic to avoid seeking the dirptr except when - absolutely necessary. It allows for a filename of about 40 chars */ - if (space_remaining < DIRLEN_GUESS && numentries > 0) - { - out_of_space = True; - finished = False; - } - else - { - finished = - !get_lanman2_dir_entry(cnum,mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, - &last_name_off); - } - - if (finished && out_of_space) - finished = False; - - if (!finished && !out_of_space) - numentries++; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); - } - - /* Check if we can close the dirptr */ - if(close_after_first || (finished && close_if_end)) - { - dptr_close(dptr_num); - DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); - dptr_num = -1; - } - - /* At this point pdata points to numentries directory entries. */ - - /* Set up the return parameter block */ - SSVAL(params,0,dptr_num); - SSVAL(params,2,numentries); - SSVAL(params,4,finished); - SSVAL(params,6,0); /* Never an EA error */ - SSVAL(params,8,last_name_off); - - send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata)); - - if ((! *directory) && dptr_path(dptr_num)) - sprintf(directory,"(%s)",dptr_path(dptr_num)); - - DEBUG(4,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", - timestring(), - smb_fn_name(CVAL(inbuf,smb_com)), - mask,directory,cnum,dirtype,numentries)); - - return(-1); -} - - -/**************************************************************************** - reply to a TRANS2_FINDNEXT -****************************************************************************/ -static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) -{ - /* We must be careful here that we don't return more than the - allowed number of data bytes. If this means returning fewer than - maxentries then so be it. We assume that the redirector has - enough room for the fixed number of parameter bytes it has - requested. */ - int max_data_bytes = SVAL(inbuf, smb_mdrcnt); - char *params = *pparams; - char *pdata = *ppdata; - int16 dptr_num = SVAL(params,0); - int maxentries = SVAL(params,2); - uint16 info_level = SVAL(params,4); - uint32 resume_key = IVAL(params,6); - BOOL close_after_request = BITSETW(params+10,0); - BOOL close_if_end = BITSETW(params+10,1); - BOOL requires_resume_key = BITSETW(params+10,2); - BOOL continue_bit = BITSETW(params+10,3); - pstring mask; - pstring directory; - char *p; - uint16 dirtype; - int numentries = 0; - int i, last_name_off=0; - BOOL finished = False; - BOOL dont_descend = False; - BOOL out_of_space = False; - int space_remaining; - - *mask = *directory = 0; - - DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, close_after_request=%d, close_if_end = %d requires_resume_key = %d resume_key = %d continue=%d level = %d\n", - dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, - requires_resume_key, resume_key, continue_bit, info_level)); - - switch (info_level) - { - case 1: - case 2: - case 3: - case 4: - case SMB_FIND_FILE_DIRECTORY_INFO: - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - case SMB_FIND_FILE_NAMES_INFO: - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - break; - default: - return(ERROR(ERRDOS,ERRunknownlevel)); - } - - pdata = *ppdata = Realloc( *ppdata, max_data_bytes + 1024); - if(!*ppdata) - return(ERROR(ERRDOS,ERRnomem)); - bzero(pdata,max_data_bytes); - - /* Realloc the params space */ - params = *pparams = Realloc(*pparams, 6*SIZEOFWORD); - if(!params) - return(ERROR(ERRDOS,ERRnomem)); - - /* Check that the dptr is valid */ - if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num))) - return(ERROR(ERRDOS,ERRnofiles)); - - string_set(&Connections[cnum].dirpath,dptr_path(dptr_num)); - - /* Get the wildcard mask from the dptr */ - if((p = dptr_wcard(dptr_num))== NULL) { - DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); - return (ERROR(ERRDOS,ERRnofiles)); - } - strcpy(mask, p); - strcpy(directory,Connections[cnum].dirpath); - - /* Get the attr mask from the dptr */ - dirtype = dptr_attr(dptr_num); - - DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%X,%d)\n", - dptr_num, mask, dirtype, - Connections[cnum].dirptr, - TellDir(Connections[cnum].dirptr))); - - /* We don't need to check for VOL here as this is returned by - a different TRANS2 call. */ - - DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)))); - if (in_list(Connections[cnum].dirpath,lp_dontdescend(SNUM(cnum)),case_sensitive)) - dont_descend = True; - - p = pdata; - space_remaining = max_data_bytes; - out_of_space = False; - - /* If we have a resume key - seek to the correct position. */ - if(requires_resume_key && !continue_bit) - SeekDir(Connections[cnum].dirptr, resume_key); - - for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) - { - /* this is a heuristic to avoid seeking the dirptr except when - absolutely necessary. It allows for a filename of about 40 chars */ - if (space_remaining < DIRLEN_GUESS && numentries > 0) - { - out_of_space = True; - finished = False; - } - else - { - finished = - !get_lanman2_dir_entry(cnum,mask,dirtype,info_level, - requires_resume_key,dont_descend, - &p,pdata,space_remaining, &out_of_space, - &last_name_off); - } - - if (finished && out_of_space) - finished = False; - - if (!finished && !out_of_space) - numentries++; - space_remaining = max_data_bytes - PTR_DIFF(p,pdata); - } - - /* Check if we can close the dirptr */ - if(close_after_request || (finished && close_if_end)) - { - dptr_close(dptr_num); /* This frees up the saved mask */ - DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); - dptr_num = -1; - } - - - /* Set up the return parameter block */ - SSVAL(params,0,numentries); - SSVAL(params,2,finished); - SSVAL(params,4,0); /* Never an EA error */ - SSVAL(params,6,last_name_off); - - send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata)); - - if ((! *directory) && dptr_path(dptr_num)) - sprintf(directory,"(%s)",dptr_path(dptr_num)); - - DEBUG(3,("%s %s mask=%s directory=%s cnum=%d dirtype=%d numentries=%d\n", - timestring(), - smb_fn_name(CVAL(inbuf,smb_com)), - mask,directory,cnum,dirtype,numentries)); - - return(-1); -} - -/**************************************************************************** - reply to a TRANS2_QFSINFO (query filesystem info) -****************************************************************************/ -static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) -{ - char *pdata = *ppdata; - char *params = *pparams; - uint16 info_level = SVAL(params,0); - int data_len; - struct stat st; - char *vname = volume_label(SNUM(cnum)); - - DEBUG(3,("call_trans2qfsinfo: cnum = %d, level = %d\n", cnum, info_level)); - - if(sys_stat(".",&st)!=0) { - DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); - return (ERROR(ERRSRV,ERRinvdevice)); - } - - pdata = *ppdata = Realloc(*ppdata, 1024); bzero(pdata,1024); - - switch (info_level) - { - case 1: - { - int dfree,dsize,bsize; - data_len = 18; - sys_disk_free(".",&bsize,&dfree,&dsize); - SIVAL(pdata,l1_idFileSystem,st.st_dev); - SIVAL(pdata,l1_cSectorUnit,bsize/512); - SIVAL(pdata,l1_cUnit,dsize); - SIVAL(pdata,l1_cUnitAvail,dfree); - SSVAL(pdata,l1_cbSector,512); - DEBUG(5,("call_trans2qfsinfo : bsize=%d, id=%x, cSectorUnit=%d, cUnit=%d, cUnitAvail=%d, cbSector=%d\n", - bsize, st.st_dev, bsize/512, dsize, dfree, 512)); - break; - } - case 2: - { - /* Return volume name */ - int volname_len = MIN(strlen(vname),11); - data_len = l2_vol_szVolLabel + volname_len + 1; - put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime); - SCVAL(pdata,l2_vol_cch,volname_len); - StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len); - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len, - pdata+l2_vol_szVolLabel)); - break; - } - case SMB_QUERY_FS_ATTRIBUTE_INFO: - data_len = 12 + 2*strlen(FSTYPE_STRING); - SIVAL(pdata,0,0x4006); /* FS ATTRIBUTES == long filenames supported? */ - SIVAL(pdata,4,128); /* Max filename component length */ - SIVAL(pdata,8,2*strlen(FSTYPE_STRING)); - PutUniCode(pdata+12,FSTYPE_STRING); - break; - case SMB_QUERY_FS_LABEL_INFO: - data_len = 4 + strlen(vname); - SIVAL(pdata,0,strlen(vname)); - strcpy(pdata+4,vname); - break; - case SMB_QUERY_FS_VOLUME_INFO: - data_len = 18 + 2*strlen(vname); - SIVAL(pdata,12,2*strlen(vname)); - PutUniCode(pdata+18,vname); - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname), - vname)); - break; - case SMB_QUERY_FS_SIZE_INFO: - { - int dfree,dsize,bsize; - data_len = 24; - sys_disk_free(".",&bsize,&dfree,&dsize); - SIVAL(pdata,0,dsize); - SIVAL(pdata,8,dfree); - SIVAL(pdata,16,bsize/512); - SIVAL(pdata,20,512); - } - break; - case SMB_QUERY_FS_DEVICE_INFO: - data_len = 8; - SIVAL(pdata,0,0); /* dev type */ - SIVAL(pdata,4,0); /* characteristics */ - break; - default: - return(ERROR(ERRDOS,ERRunknownlevel)); - } - - - send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len); - - DEBUG(4,("%s %s info_level =%d\n",timestring(),smb_fn_name(CVAL(inbuf,smb_com)), info_level)); - - return -1; -} - -/**************************************************************************** - reply to a TRANS2_SETFSINFO (set filesystem info) -****************************************************************************/ -static int call_trans2setfsinfo(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) -{ - /* Just say yes we did it - there is nothing that - can be set here so it doesn't matter. */ - int outsize; - DEBUG(3,("call_trans2setfsinfo\n")); - - if (!CAN_WRITE(cnum)) - return(ERROR(ERRSRV,ERRaccess)); - - outsize = set_message(outbuf,10,0,True); - - return outsize; -} - -/**************************************************************************** - reply to a TRANS2_QFILEINFO (query file info by fileid) -****************************************************************************/ -static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length, - int bufsize,int cnum, - char **pparams,char **ppdata, - int total_data) -{ - char *params = *pparams; - char *pdata = *ppdata; - uint16 tran_call = SVAL(inbuf, smb_setup0); - uint16 info_level; - int mode=0; - int size=0; - unsigned int data_size; - struct stat sbuf; - pstring fname1; - char *fname; - char *p; - int l,pos; - - - if (tran_call == TRANSACT2_QFILEINFO) { - int16 fnum = SVALS(params,0); - info_level = SVAL(params,2); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - fname = Files[fnum].name; - if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - DEBUG(3,("fstat of fnum %d failed (%s)\n",fnum, strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadfid)); - } - pos = lseek(Files[fnum].fd_ptr->fd,0,SEEK_CUR); - } else { - /* qpathinfo */ - info_level = SVAL(params,0); - fname = &fname1[0]; - strcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0); - if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - pos = 0; - } - - - DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", - fname,info_level,tran_call,total_data)); - - p = strrchr(fname,'/'); - if (!p) - p = fname; - else - p++; - l = strlen(p); - mode = dos_mode(cnum,fname,&sbuf); - size = sbuf.st_size; - if (mode & aDIR) size = 0; - - params = *pparams = Realloc(*pparams,2); bzero(params,2); - data_size = 1024; - pdata = *ppdata = Realloc(*ppdata, data_size); - - if (total_data > 0 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); -#if 0 - SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED); - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - return(-1); -#else - return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); -#endif - } - - bzero(pdata,data_size); - - switch (info_level) - { - case 1: - case 2: - data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); - SIVAL(pdata,l1_cbFile,size); - SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024)); - SSVAL(pdata,l1_attrFile,mode); - SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ - break; - - case 3: - data_size = 24; - put_dos_date2(pdata,0,sbuf.st_ctime); - put_dos_date2(pdata,4,sbuf.st_atime); - put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,size); - SIVAL(pdata,16,ROUNDUP(size,1024)); - SIVAL(pdata,20,mode); - break; - - case 4: - data_size = 4; - SIVAL(pdata,0,data_size); - break; - - case 6: - return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */ - - case SMB_QUERY_FILE_BASIC_INFO: - data_size = 36; - put_long_date(pdata,sbuf.st_ctime); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); - put_long_date(pdata+24,sbuf.st_mtime); - SIVAL(pdata,32,mode); - break; - - case SMB_QUERY_FILE_STANDARD_INFO: - data_size = 22; - SIVAL(pdata,0,size); - SIVAL(pdata,8,size); - SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = 0; - CVAL(pdata,21) = (mode&aDIR)?1:0; - break; - - case SMB_QUERY_FILE_EA_INFO: - data_size = 4; - break; - - case SMB_QUERY_FILE_NAME_INFO: - case SMB_QUERY_FILE_ALT_NAME_INFO: - data_size = 4 + l; - SIVAL(pdata,0,l); - strcpy(pdata+4,fname); - break; - case SMB_QUERY_FILE_ALLOCATION_INFO: - case SMB_QUERY_FILE_END_OF_FILEINFO: - data_size = 8; - SIVAL(pdata,0,size); - break; - - case SMB_QUERY_FILE_ALL_INFO: - put_long_date(pdata,sbuf.st_ctime); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); - put_long_date(pdata+24,sbuf.st_mtime); - SIVAL(pdata,32,mode); - pdata += 40; - SIVAL(pdata,0,size); - SIVAL(pdata,8,size); - SIVAL(pdata,16,sbuf.st_nlink); - CVAL(pdata,20) = 0; - CVAL(pdata,21) = (mode&aDIR)?1:0; - pdata += 24; - pdata += 8; /* index number */ - pdata += 4; /* EA info */ - if (mode & aRONLY) - SIVAL(pdata,0,0xA9); - else - SIVAL(pdata,0,0xd01BF); - pdata += 4; - SIVAL(pdata,0,pos); /* current offset */ - pdata += 8; - SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ - pdata += 4; - pdata += 4; /* alignment */ - SIVAL(pdata,0,l); - strcpy(pdata+4,fname); - pdata += 4 + l; - data_size = PTR_DIFF(pdata,(*ppdata)); - break; - - case SMB_QUERY_FILE_STREAM_INFO: - data_size = 24 + l; - SIVAL(pdata,0,pos); - SIVAL(pdata,4,size); - SIVAL(pdata,12,size); - SIVAL(pdata,20,l); - strcpy(pdata+24,fname); - break; - default: - return(ERROR(ERRDOS,ERRunknownlevel)); - } - - send_trans2_replies( outbuf, bufsize, params, 2, *ppdata, data_size); - - return(-1); -} - -/**************************************************************************** - reply to a TRANS2_SETFILEINFO (set file info by fileid) -****************************************************************************/ -static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, - int bufsize, int cnum, char **pparams, - char **ppdata, int total_data) -{ - char *params = *pparams; - char *pdata = *ppdata; - uint16 tran_call = SVAL(inbuf, smb_setup0); - uint16 info_level; - int mode=0; - int size=0; - struct utimbuf tvs; - struct stat st; - pstring fname1; - char *fname; - int fd = -1; - - if (!CAN_WRITE(cnum)) - return(ERROR(ERRSRV,ERRaccess)); - - if (tran_call == TRANSACT2_SETFILEINFO) { - int16 fnum = SVALS(params,0); - info_level = SVAL(params,2); - - CHECK_FNUM(fnum,cnum); - CHECK_ERROR(fnum); - - fname = Files[fnum].name; - fd = Files[fnum].fd_ptr->fd; - - if(fstat(fd,&st)!=0) { - DEBUG(3,("fstat of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRbadpath)); - } - } else { - /* set path info */ - info_level = SVAL(params,0); - fname = fname1; - strcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0); - if(!check_name(fname, cnum)) - return(ERROR(ERRDOS,ERRbadpath)); - - if(sys_stat(fname,&st)!=0) { - DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRbadpath)); - } - } - - DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", - tran_call,fname,info_level,total_data)); - - /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,2); SSVAL(params,0,0); - if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); - - size = st.st_size; - tvs.modtime = st.st_mtime; - tvs.actime = st.st_atime; - mode = dos_mode(cnum,fname,&st); - - if (total_data > 0 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED); - - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - - return(-1); - } - - switch (info_level) - { - case 1: - tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - mode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; - - case 2: - tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - mode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; - - case 3: - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - mode = IVAL(pdata,24); - break; - - case 4: - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - mode = IVAL(pdata,24); - break; - - case SMB_SET_FILE_BASIC_INFO: - pdata += 8; /* create time */ - tvs.actime = interpret_long_date(pdata); pdata += 8; - tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8)); - pdata += 16; - mode = IVAL(pdata,0); - break; - - case SMB_SET_FILE_END_OF_FILE_INFO: - if (IVAL(pdata,4) != 0) /* more than 32 bits? */ - return(ERROR(ERRDOS,ERRunknownlevel)); - size = IVAL(pdata,0); - break; - - case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ - case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */ - default: - return(ERROR(ERRDOS,ERRunknownlevel)); - } - - - if (!tvs.actime) tvs.actime = st.st_atime; - if (!tvs.modtime) tvs.modtime = st.st_mtime; - if (!size) size = st.st_size; - - /* Try and set the times, size and mode of this file - if they are different - from the current values */ - if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) { - if(sys_utime(fname, &tvs)!=0) - return(ERROR(ERRDOS,ERRnoaccess)); - } - if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) { - DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno))); - return(ERROR(ERRDOS,ERRnoaccess)); - } - if(size != st.st_size) { - if (fd == -1) { - fd = sys_open(fname,O_RDWR,0); - if (fd == -1) - return(ERROR(ERRDOS,ERRbadpath)); - set_filelen(fd, size); - close(fd); - } else { - set_filelen(fd, size); - } - } - - SSVAL(params,0,0); - - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - - return(-1); -} - -/**************************************************************************** - reply to a TRANS2_MKDIR (make directory with extended attributes). -****************************************************************************/ -static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) -{ - char *params = *pparams; - pstring directory; - int ret = -1; - - if (!CAN_WRITE(cnum)) - return(ERROR(ERRSRV,ERRaccess)); - - strcpy(directory, ¶ms[4]); - - DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - - unix_convert(directory,cnum,0); - if (check_name(directory,cnum)) - ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); - - if(ret < 0) - { - DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,2); - if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); - - SSVAL(params,0,0); - - send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); - - return(-1); -} - -/**************************************************************************** - reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes) - We don't actually do this - we just send a null response. -****************************************************************************/ -static int call_trans2findnotifyfirst(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) -{ - static uint16 fnf_handle = 257; - char *params = *pparams; - uint16 info_level = SVAL(params,4); - - DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level)); - - switch (info_level) - { - case 1: - case 2: - break; - default: - return(ERROR(ERRDOS,ERRunknownlevel)); - } - - /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,6); - if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); - - SSVAL(params,0,fnf_handle); - SSVAL(params,2,0); /* No changes */ - SSVAL(params,4,0); /* No EA errors */ - - fnf_handle++; - - if(fnf_handle == 0) - fnf_handle = 257; - - send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0); - - return(-1); -} - -/**************************************************************************** - reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for - changes). Currently this does nothing. -****************************************************************************/ -static int call_trans2findnotifynext(char *inbuf, char *outbuf, int length, int bufsize, - int cnum, char **pparams, char **ppdata) -{ - char *params = *pparams; - - DEBUG(3,("call_trans2findnotifynext\n")); - - /* Realloc the parameter and data sizes */ - params = *pparams = Realloc(*pparams,4); - if(params == NULL) - return(ERROR(ERRDOS,ERRnomem)); - - SSVAL(params,0,0); /* No changes */ - SSVAL(params,2,0); /* No EA errors */ - - send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0); - - return(-1); -} - -/**************************************************************************** - reply to a SMBfindclose (stop trans2 directory search) -****************************************************************************/ -int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize) -{ - int cnum; - int outsize = 0; - int16 dptr_num=SVALS(inbuf,smb_vwv0); - - cnum = SVAL(inbuf,smb_tid); - - DEBUG(3,("reply_findclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num)); - - dptr_close(dptr_num); - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s SMBfindclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num)); - - return(outsize); -} - -/**************************************************************************** - reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search) -****************************************************************************/ -int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize) -{ - int cnum; - int outsize = 0; - int dptr_num= -1; - - cnum = SVAL(inbuf,smb_tid); - dptr_num = SVAL(inbuf,smb_vwv0); - - DEBUG(3,("reply_findnclose, cnum = %d, dptr_num = %d\n", cnum, dptr_num)); - - /* We never give out valid handles for a - findnotifyfirst - so any dptr_num is ok here. - Just ignore it. */ - - outsize = set_message(outbuf,0,0,True); - - DEBUG(3,("%s SMB_findnclose cnum=%d, dptr_num = %d\n",timestring(),cnum,dptr_num)); - - return(outsize); -} - - -/**************************************************************************** - reply to a SMBtranss2 - just ignore it! -****************************************************************************/ -int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize) -{ - DEBUG(4,("Ignoring transs2 of length %d\n",length)); - return(-1); -} - -/**************************************************************************** - reply to a SMBtrans2 -****************************************************************************/ -int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize) -{ - int outsize = 0; - int cnum = SVAL(inbuf,smb_tid); - unsigned int total_params = SVAL(inbuf, smb_tpscnt); - unsigned int total_data =SVAL(inbuf, smb_tdscnt); -#if 0 - unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt); - unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt); - unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt); - BOOL close_tid = BITSETW(inbuf+smb_flags,0); - BOOL no_final_response = BITSETW(inbuf+smb_flags,1); - int32 timeout = IVALS(inbuf,smb_timeout); -#endif - unsigned int suwcnt = SVAL(inbuf, smb_suwcnt); - unsigned int tran_call = SVAL(inbuf, smb_setup0); - char *params = NULL, *data = NULL; - int num_params, num_params_sofar, num_data, num_data_sofar; - - outsize = set_message(outbuf,0,0,True); - - /* All trans2 messages we handle have smb_sucnt == 1 - ensure this - is so as a sanity check */ - if(suwcnt != 1 ) - { - DEBUG(2,("Invalid smb_sucnt in trans2 call\n")); - return(ERROR(ERRSRV,ERRerror)); - } - - /* Allocate the space for the maximum needed parameters and data */ - if (total_params > 0) - params = (char *)malloc(total_params); - if (total_data > 0) - data = (char *)malloc(total_data); - - if ((total_params && !params) || (total_data && !data)) - { - DEBUG(2,("Out of memory in reply_trans2\n")); - return(ERROR(ERRDOS,ERRnomem)); - } - - /* Copy the param and data bytes sent with this request into - the params buffer */ - num_params = num_params_sofar = SVAL(inbuf,smb_pscnt); - num_data = num_data_sofar = SVAL(inbuf, smb_dscnt); - - memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params); - memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data); - - if(num_data_sofar < total_data || num_params_sofar < total_params) - { - /* We need to send an interim response then receive the rest - of the parameter/data bytes */ - outsize = set_message(outbuf,0,0,True); - send_smb(Client,outbuf); - - while( num_data_sofar < total_data || num_params_sofar < total_params) - { - if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) || - CVAL(inbuf, smb_com) != SMBtranss2) - { - outsize = set_message(outbuf,0,0,True); - DEBUG(2,("Invalid secondary trans2 packet\n")); - free(params); - free(data); - return(ERROR(ERRSRV,ERRerror)); - } - - /* Revise total_params and total_data in case they have changed downwards */ - total_params = SVAL(inbuf, smb_tpscnt); - total_data = SVAL(inbuf, smb_tdscnt); - num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt)); - num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt)); - memcpy( ¶ms[ SVAL(inbuf, smb_spsdisp)], - smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params); - memcpy( &data[SVAL(inbuf, smb_sdsdisp)], - smb_base(inbuf)+ SVAL(inbuf, smb_sdsoff), num_data); - } - } - - if (Protocol >= PROTOCOL_NT1) { - uint16 flg2 = SVAL(outbuf,smb_flg2); - SSVAL(outbuf,smb_flg2,flg2 | 0x40); /* IS_LONG_NAME */ - } - - /* Now we must call the relevant TRANS2 function */ - switch(tran_call) - { - case TRANSACT2_OPEN: - outsize = call_trans2open(inbuf, outbuf, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_FINDFIRST: - outsize = call_trans2findfirst(inbuf, outbuf, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_FINDNEXT: - outsize = call_trans2findnext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_QFSINFO: - outsize = call_trans2qfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_SETFSINFO: - outsize = call_trans2setfsinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_QPATHINFO: - case TRANSACT2_QFILEINFO: - outsize = call_trans2qfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data); - break; - case TRANSACT2_SETPATHINFO: - case TRANSACT2_SETFILEINFO: - outsize = call_trans2setfilepathinfo(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data, total_data); - break; - case TRANSACT2_FINDNOTIFYFIRST: - outsize = call_trans2findnotifyfirst(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_FINDNOTIFYNEXT: - outsize = call_trans2findnotifynext(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - case TRANSACT2_MKDIR: - outsize = call_trans2mkdir(inbuf, outbuf, length, bufsize, cnum, ¶ms, &data); - break; - default: - /* Error in request */ - DEBUG(2,("%s Unknown request %d in trans2 call\n",timestring(), tran_call)); - if(params) - free(params); - if(data) - free(data); - return (ERROR(ERRSRV,ERRerror)); - } - - /* As we do not know how many data packets will need to be - returned here the various call_trans2xxxx calls - must send their own. Thus a call_trans2xxx routine only - returns a value other than -1 when it wants to send - an error packet. - */ - - if(params) - free(params); - if(data) - free(data); - return outsize; /* If a correct response was needed the call_trans2xxx - calls have already sent it. If outsize != -1 then it is - returning an error packet. */ -} diff --git a/source/smbd/uid.c b/source/smbd/uid.c deleted file mode 100644 index 0cf1c217a9b..00000000000 --- a/source/smbd/uid.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - uid/user handling - Copyright (C) Andrew Tridgell 1992-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -extern int DEBUGLEVEL; - -extern connection_struct Connections[]; - -static int initial_uid; -static int initial_gid; - -/* what user is current? */ -struct current_user current_user; - -extern pstring OriginalDir; - -/**************************************************************************** -initialise the uid routines -****************************************************************************/ -void init_uid(void) -{ - initial_uid = current_user.uid = geteuid(); - initial_gid = current_user.gid = getegid(); - - if (initial_gid != 0 && initial_uid == 0) - { -#ifdef HPUX - setresgid(0,0,0); -#else - setgid(0); - setegid(0); -#endif - } - - initial_uid = geteuid(); - initial_gid = getegid(); - - current_user.cnum = -1; - - ChDir(OriginalDir); -} - - -/**************************************************************************** - become the specified uid -****************************************************************************/ -static BOOL become_uid(int uid) -{ - if (initial_uid != 0) - return(True); - - if (uid == -1 || uid == 65535) { - DEBUG(1,("WARNING: using uid %d is a security risk\n",uid)); - } - -#ifdef AIX - { - /* AIX 3 stuff - inspired by a code fragment in wu-ftpd */ - priv_t priv; - - priv.pv_priv[0] = 0; - priv.pv_priv[1] = 0; - if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH, - &priv, sizeof(priv_t)) < 0 || - setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)uid) < 0 || - seteuid((uid_t)uid) < 0) - DEBUG(1,("Can't set uid (AIX3)")); - } -#endif - -#ifdef USE_SETRES - if (setresuid(-1,uid,-1) != 0) -#elif defined(USE_SETFS) - if (setfsuid(uid) != 0) -#else - if ((seteuid(uid) != 0) && - (setuid(uid) != 0)) -#endif - { - DEBUG(0,("Couldn't set uid %d currently set to (%d,%d)\n", - uid,getuid(), geteuid())); - if (uid > 32000) - DEBUG(0,("Looks like your OS doesn't like high uid values - try using a different account\n")); - return(False); - } - - if (((uid == -1) || (uid == 65535)) && geteuid() != uid) { - DEBUG(0,("Invalid uid -1. perhaps you have a account with uid 65535?\n")); - return(False); - } - - current_user.uid = uid; - - return(True); -} - - -/**************************************************************************** - become the specified gid -****************************************************************************/ -static BOOL become_gid(int gid) -{ - if (initial_uid != 0) - return(True); - - if (gid == -1 || gid == 65535) { - DEBUG(1,("WARNING: using gid %d is a security risk\n",gid)); - } - -#ifdef USE_SETRES - if (setresgid(-1,gid,-1) != 0) -#elif defined(USE_SETFS) - if (setfsgid(gid) != 0) -#else - if (setgid(gid) != 0) -#endif - { - DEBUG(0,("Couldn't set gid %d currently set to (%d,%d)\n", - gid,getgid(),getegid())); - if (gid > 32000) - DEBUG(0,("Looks like your OS doesn't like high gid values - try using a different account\n")); - return(False); - } - - current_user.gid = gid; - - return(True); -} - - -/**************************************************************************** - become the specified uid and gid -****************************************************************************/ -static BOOL become_id(int uid,int gid) -{ - return(become_gid(gid) && become_uid(uid)); -} - -/**************************************************************************** -become the guest user -****************************************************************************/ -BOOL become_guest(void) -{ - BOOL ret; - static struct passwd *pass=NULL; - - if (initial_uid != 0) - return(True); - - if (!pass) - pass = Get_Pwnam(lp_guestaccount(-1),True); - if (!pass) return(False); - - ret = become_id(pass->pw_uid,pass->pw_gid); - - if (!ret) - DEBUG(1,("Failed to become guest. Invalid guest account?\n")); - - current_user.cnum = -2; - - return(ret); -} - -/******************************************************************* -check if a username is OK -********************************************************************/ -static BOOL check_user_ok(int cnum,user_struct *vuser,int snum) -{ - int i; - for (i=0;i<Connections[cnum].uid_cache.entries;i++) - if (Connections[cnum].uid_cache.list[i] == vuser->uid) return(True); - - if (!user_ok(vuser->name,snum)) return(False); - - i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE; - Connections[cnum].uid_cache.list[i] = vuser->uid; - - if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE) - Connections[cnum].uid_cache.entries++; - - return(True); -} - - -/**************************************************************************** - become the user of a connection number -****************************************************************************/ -BOOL become_user(int cnum, uint16 vuid) -{ - user_struct *vuser = get_valid_user_struct(vuid); - int snum,gid; - int uid; - - if (current_user.cnum == cnum && vuser != 0 && current_user.id == vuser->uid) { - DEBUG(4,("Skipping become_user - already user\n")); - return(True); - } - - unbecome_user(); - - if (!OPEN_CNUM(cnum)) { - DEBUG(2,("Connection %d not open\n",cnum)); - return(False); - } - - snum = Connections[cnum].service; - - if (Connections[cnum].force_user || - lp_security() == SEC_SHARE || - !(vuser) || (vuser->guest) || - !check_user_ok(cnum,vuser,snum)) { - uid = Connections[cnum].uid; - gid = Connections[cnum].gid; - current_user.groups = Connections[cnum].groups; - current_user.igroups = Connections[cnum].igroups; - current_user.ngroups = Connections[cnum].ngroups; - } else { - if (!vuser) { - DEBUG(2,("Invalid vuid used %d\n",vuid)); - return(False); - } - uid = vuser->uid; - if(!*lp_force_group(snum)) - gid = vuser->gid; - else - gid = Connections[cnum].gid; - current_user.groups = vuser->user_groups; - current_user.igroups = vuser->user_igroups; - current_user.ngroups = vuser->user_ngroups; - } - - if (initial_uid == 0) - { - if (!become_gid(gid)) return(False); - -#ifndef NO_SETGROUPS - if (!IS_IPC(cnum)) { - /* groups stuff added by ih/wreu */ - if (current_user.ngroups > 0) - if (setgroups(current_user.ngroups,current_user.groups)<0) - DEBUG(0,("setgroups call failed!\n")); - } -#endif - - if (!Connections[cnum].admin_user && !become_uid(uid)) - return(False); - } - - current_user.cnum = cnum; - current_user.id = uid; - - DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", - getuid(),geteuid(),getgid(),getegid())); - - return(True); -} - -/**************************************************************************** - unbecome the user of a connection number -****************************************************************************/ -BOOL unbecome_user(void ) -{ - if (current_user.cnum == -1) - return(False); - - ChDir(OriginalDir); - - if (initial_uid == 0) - { -#ifdef USE_SETRES - setresuid(-1,getuid(),-1); - setresgid(-1,getgid(),-1); -#elif defined(USE_SETFS) - setfsuid(initial_uid); - setfsgid(initial_gid); -#else - if (seteuid(initial_uid) != 0) - setuid(initial_uid); - setgid(initial_gid); -#endif - } -#ifdef NO_EID - if (initial_uid == 0) - DEBUG(2,("Running with no EID\n")); - initial_uid = getuid(); - initial_gid = getgid(); -#else - if (geteuid() != initial_uid) - { - DEBUG(0,("Warning: You appear to have a trapdoor uid system\n")); - initial_uid = geteuid(); - } - if (getegid() != initial_gid) - { - DEBUG(0,("Warning: You appear to have a trapdoor gid system\n")); - initial_gid = getegid(); - } -#endif - - current_user.uid = initial_uid; - current_user.gid = initial_gid; - - if (ChDir(OriginalDir) != 0) - DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", - timestring(),OriginalDir)); - - DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", - getuid(),geteuid(),getgid(),getegid())); - - current_user.cnum = -1; - - return(True); -} - - -/**************************************************************************** -This is a utility function of smbrun(). It must be called only from -the child as it may leave the caller in a privilaged state. -****************************************************************************/ -static BOOL setup_stdout_file(char *outfile,BOOL shared) -{ - int fd; - struct stat st; - mode_t mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH; - int flags = O_RDWR|O_CREAT|O_TRUNC|O_EXCL; - - close(1); - - if (shared) { - /* become root - unprivilaged users can't delete these files */ -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); -#endif - } - - if(stat(outfile, &st) == 0) { - /* Check we're not deleting a device file. */ - if(st.st_mode & S_IFREG) - unlink(outfile); - else - flags = O_RDWR; - } - /* now create the file */ - fd = open(outfile,flags,mode); - - if (fd == -1) return False; - - if (fd != 1) { - if (dup2(fd,1) != 0) { - DEBUG(2,("Failed to create stdout file descriptor\n")); - close(fd); - return False; - } - close(fd); - } - return True; -} - - -/**************************************************************************** -run a command being careful about uid/gid handling and putting the output in -outfile (or discard it if outfile is NULL). - -if shared is True then ensure the file will be writeable by all users -but created such that its owned by root. This overcomes a security hole. - -if shared is not set then open the file with O_EXCL set -****************************************************************************/ -int smbrun(char *cmd,char *outfile,BOOL shared) -{ - int fd,pid; - int uid = current_user.uid; - int gid = current_user.gid; - -#if USE_SYSTEM - int ret; - pstring syscmd; - char *path = lp_smbrun(); - - /* in the old method we use system() to execute smbrun which then - executes the command (using system() again!). This involves lots - of shell launches and is very slow. It also suffers from a - potential security hole */ - if (!file_exist(path,NULL)) - { - DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",path)); - return(1); - } - - sprintf(syscmd,"%s %d %d \"(%s 2>&1) > %s\"", - path,uid,gid,cmd, - outfile?outfile:"/dev/null"); - - DEBUG(5,("smbrun - running %s ",syscmd)); - ret = system(syscmd); - DEBUG(5,("gave %d\n",ret)); - return(ret); -#else - /* in this newer method we will exec /bin/sh with the correct - arguments, after first setting stdout to point at the file */ - - if ((pid=fork())) { - int status=0; - /* the parent just waits for the child to exit */ - if (sys_waitpid(pid,&status,0) != pid) { - DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno))); - return -1; - } - return status; - } - - - /* we are in the child. we exec /bin/sh to do the work for us. we - don't directly exec the command we want because it may be a - pipeline or anything else the config file specifies */ - - /* point our stdout at the file we want output to go into */ - if (outfile && !setup_stdout_file(outfile,shared)) { - exit(80); - } - - /* now completely lose our privilages. This is a fairly paranoid - way of doing it, but it does work on all systems that I know of */ -#ifdef USE_SETRES - setresgid(0,0,0); - setresuid(0,0,0); - setresgid(gid,gid,gid); - setresuid(uid,uid,uid); -#else - setuid(0); - seteuid(0); - setgid(gid); - setegid(gid); - setuid(uid); - seteuid(uid); -#endif - - if (getuid() != uid || geteuid() != uid || - getgid() != gid || getegid() != gid) { - /* we failed to lose our privilages - do not execute the command */ - exit(81); /* we can't print stuff at this stage, instead use exit codes - for debugging */ - } - - /* close all other file descriptors, leaving only 0, 1 and 2. 0 and - 2 point to /dev/null from the startup code */ - for (fd=3;fd<256;fd++) close(fd); - - execl("/bin/sh","sh","-c",cmd,NULL); - - /* not reached */ - exit(82); -#endif - return 1; -} diff --git a/source/smbd/vt_mode.c b/source/smbd/vt_mode.c deleted file mode 100644 index 0a4d50c217f..00000000000 --- a/source/smbd/vt_mode.c +++ /dev/null @@ -1,490 +0,0 @@ -/* vt_mode.c */ -/* -support vtp-sessions - -written by Christian A. Lademann <cal@zls.com> -*/ - -/* -02.05.95:cal:ported to samba-1.9.13 -*/ - -#define __vt_mode_c__ - - -/* #include <stdio.h> */ -/* #include <fcntl.h> */ -/* #include <sys/types.h> */ -/* #include <unistd.h> */ -/* #include <signal.h> */ -/* #include <errno.h> */ -/* #include <ctype.h> */ -/* #include <utmp.h> */ -/* #include <sys/param.h> */ -/* #include <sys/ioctl.h> */ -/* #include <stdlib.h> */ -/* #include <string.h> */ - -#include "includes.h" -#include "vt_mode.h" -#include <utmp.h> - -#ifdef SCO - extern char *strdup(); -#endif - -extern int Client; - -#ifdef LINUX -# define HAS_VTY -#endif - -#ifdef SCO -# define HAS_PTY -# define HAS_VTY - -# include <sys/tty.h> -#endif - -extern int DEBUGLEVEL; -extern char *InBuffer, *OutBuffer; -extern int done_become_user; - -char master_name [64], slave_name [64]; -int master, slave, i, o, e; - -int ms_type = MS_NONE, - ms_poll = 0; - - -/* -VT_Check: test incoming packet for "vtp" or "iVT1\0" -*/ -int VT_Check(char *buffer) -{ - DEBUG(3,("Checking packet: <%10s...>\n", buffer+4)); - if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5)) - return(1); - else - return(0); -} - - -/* -VT_Start_utmp: prepare /etc/utmp for /bin/login -*/ -int VT_Start_utmp(void) -{ - struct utmp u, *v; - char *tt; - - - setutent(); - - strcpy(u.ut_line, VT_Line); - - if((v = getutline(&u)) == NULL) { - if(strncmp(VT_Line, "tty", 3) == 0) - tt = VT_Line + 3; - else if(strlen(VT_Line) > 4) - tt = VT_Line + strlen(VT_Line) - 4; - else - tt = VT_Line; - - strcpy(u.ut_id, tt); - u.ut_time = time((time_t*)0); - } - - strcpy(u.ut_user, "LOGIN"); - strcpy(u.ut_line, VT_Line); - u.ut_pid = getpid(); - u.ut_type = LOGIN_PROCESS; - pututline(&u); - - endutent(); - - return(0); -} - - -/* -VT_Stop_utmp: prepare /etc/utmp for other processes -*/ -int VT_Stop_utmp(void) -{ - struct utmp u, *v; - - - if(VT_Line != NULL) { - setutent(); - - strcpy(u.ut_line, VT_Line); - - if((v = getutline(&u)) != NULL) { - strcpy(v->ut_user, ""); - v->ut_type = DEAD_PROCESS; - v->ut_time = time((time_t*)0); - pututline(v); - } - - endutent(); - } - - return(0); -} - - -/* -VT_AtExit: Things to do when the program exits -*/ -void VT_AtExit(void) -{ - if(VT_ChildPID > 0) { - kill(VT_ChildPID, SIGHUP); - (void)wait(NULL); - } - - VT_Stop_utmp(); -} - - -/* -VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died -*/ -void VT_SigCLD(int sig) -{ - if(wait(NULL) == VT_ChildPID) - VT_ChildDied = True; - else - signal(SIGCLD, VT_SigCLD); -} - - -/* -VT_SigEXIT: signalhandler for signals that cause the process to exit -*/ -void VT_SigEXIT(int sig) -{ - VT_AtExit(); - - exit(1); -} - - -/* -VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK -*/ -int VT_Start(void) -{ - char OutBuf [64], *X, *Y; - - - ms_type = MS_NONE; - master = slave = -1; - -#ifdef HAS_VTY -#ifdef LINUX -# define MASTER_TMPL "/dev/pty " -# define SLAVE_TMPL "/dev/tty " -# define LETTER1 "pqrs" -# define POS1 8 -# define LETTER2 "0123456789abcdef" -# define POS2 9 -#endif - -#ifdef SCO -# define MASTER_TMPL "/dev/ptyp_ " -# define SLAVE_TMPL "/dev/ttyp_ " -# define LETTER1 "0123456" -# define POS1 10 -# define LETTER2 "0123456789abcdef" -# define POS2 11 -#endif - - if(ms_poll == MS_VTY || ms_poll == 0) { - strcpy(master_name, MASTER_TMPL); - strcpy(slave_name, SLAVE_TMPL); - - for(X = LETTER1; *X && master < 0; X++) - for(Y = LETTER2; *Y && master < 0; Y++) { - master_name [POS1] = *X; - master_name [POS2] = *Y; - if((master = open(master_name, O_RDWR)) >= 0) { - slave_name [POS1] = *X; - slave_name [POS2] = *Y; - if((slave = open(slave_name, O_RDWR)) < 0) - close(master); - } - } - - if(master >= 0 && slave >= 0) - ms_type = MS_VTY; - } - -# undef MASTER_TMPL -# undef SLAVE_TMPL -# undef LETTER1 -# undef LETTER2 -# undef POS1 -# undef POS2 -#endif - - -#ifdef HAS_PTY -#ifdef SCO -# define MASTER_TMPL "/dev/ptyp%d" -# define SLAVE_TMPL "/dev/ttyp%d" -# define MIN_I 0 -# define MAX_I 63 -#endif - - if(ms_poll == MS_PTY || ms_poll == 0) { - int i; - - for(i = MIN_I; i <= MAX_I && master < 0; i++) { - sprintf(master_name, MASTER_TMPL, i); - if((master = open(master_name, O_RDWR)) >= 0) { - sprintf(slave_name, SLAVE_TMPL, i); - if((slave = open(slave_name, O_RDWR)) < 0) - close(master); - } - } - - if(master >= 0 && slave >= 0) - ms_type = MS_PTY; - } - -# undef MASTER_TMPL -# undef SLAVE_TMPL -# undef MIN_I -# undef MAX_I -#endif - - - if(! ms_type) - return(-1); - - VT_Line = strdup(strrchr(slave_name, '/') + 1); - - switch((VT_ChildPID = fork())) { - case -1: - return(-1); - break; - - case 0: -#ifdef SCO - setsid(); -#endif - close(0); - close(1); - close(2); - - i = open(slave_name, O_RDWR); - o = open(slave_name, O_RDWR); - e = open(slave_name, O_RDWR); - -#ifdef LINUX - setsid(); - if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1) - exit(1); -#endif -#ifdef SCO - tcsetpgrp(0, getpid()); -#endif - - VT_Start_utmp(); - - system("stty sane"); - execlp("/bin/login", "login", "-c", (char*)0); - exit(1); - break; - - default: - VT_Mode = True; - VT_Status = VT_OPEN; - VT_ChildDied = False; - VT_Fd = master; - - signal(SIGCLD, VT_SigCLD); - - signal(SIGHUP, VT_SigEXIT); - signal(SIGTERM, VT_SigEXIT); - signal(SIGINT, VT_SigEXIT); - signal(SIGQUIT, VT_SigEXIT); - - memset(OutBuf, 0, sizeof(OutBuf)); - OutBuf [4] = 0x06; - _smb_setlen(OutBuf, 1); - - send_smb(Client,OutBuf); - - return(0); - break; - } -} - - -/* -VT_Output: transport data from socket to pty -*/ -int VT_Output(char *Buffer) -{ - int i, len, nb; - - - if(VT_Status != VT_OPEN) - return(-1); - - len = smb_len(Buffer); - - nb = write(VT_Fd, Buffer + 4, len); - - return((nb == len) ? 0 : -1); -} - - -/* -VT_Input: transport data from pty to socket -*/ -int VT_Input(char *Buffer,int Size) -{ - int len; - - - if(VT_Status != VT_OPEN) - return(-1); - - memset(Buffer, 0, Size); - len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size)); - - _smb_setlen(Buffer, len); - - return(len + 4); -} - - -/* -VT_Process: main loop while in vt-mode -*/ -void VT_Process(void) -{ - static int trans_num = 0; - extern int Client; - int nread; - - - VT_Start(); - - atexit(VT_AtExit); - - while (True) { - int32 len; - int msg_type; - int msg_flags; - int counter; - int last_keepalive=0; - struct fd_set si; - struct timeval to, *top; - int n, ret, t; - - - errno = 0; - t = SMBD_SELECT_LOOP*1000; - - - FD_ZERO(&si); - FD_SET(Client, &si); - - FD_SET(VT_Fd, &si); - - if(t >= 0) { - to.tv_sec = t / 1000; - to.tv_usec = t - (to.tv_sec * 1000); - - top = &to; - } else - top = NULL; - - if(VT_ChildDied) - goto leave_VT_Process; - - n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top); - - if(VT_ChildDied) - goto leave_VT_Process; - - if(n == 0) { - int i; - time_t t; - BOOL allidle = True; - extern int keepalive; - - counter += SMBD_SELECT_LOOP; - - t = time(NULL); - - if (keepalive && (counter-last_keepalive)>keepalive) { - if (!send_keepalive(Client)) - goto leave_VT_Process; - last_keepalive = counter; - } - } else if(n > 0) { - counter = 0; - - if(FD_ISSET(VT_Fd, &si)) { - /* got input from vt */ - nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit())); - - if(nread > 0) - send_smb(Client,OutBuffer); - } - - if(FD_ISSET(Client, &si)) { - /* got input from socket */ - - if(receive_smb(Client,InBuffer, 0)) { - msg_type = CVAL(InBuffer,0); - msg_flags = CVAL(InBuffer,1); - - len = smb_len(InBuffer); - - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - - nread = len + 4; - - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); - - if(msg_type == 0) - VT_Output(InBuffer); - else { - nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit())); - - if(nread > 0) { - if (nread != smb_len(OutBuffer) + 4) { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, - smb_len(OutBuffer))); - } else - send_smb(Client,OutBuffer); - } - } - } else - if(errno == EBADF) - goto leave_VT_Process; - } - } - - trans_num++; - } - - leave_VT_Process: -/* - if(VT_ChildPID > 0) - kill(VT_ChildPID, SIGHUP); - - VT_Stop_utmp(VT_Line); - return; -*/ - close_sockets(); - exit(0); -} diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c deleted file mode 100644 index 68093c10ede..00000000000 --- a/source/utils/nmblookup.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT client - used to lookup netbios names - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifdef SYSLOG -#undef SYSLOG -#endif - -#include "includes.h" - -extern int DEBUGLEVEL; - -extern pstring scope; - -extern pstring myhostname; -extern struct in_addr ipzero; - -int ServerFD= -1; - -/**************************************************************************** - open the socket communication - **************************************************************************/ -static BOOL open_sockets(void) -{ - struct hostent *hp; - - /* get host info */ - if ((hp = Get_Hostbyname(myhostname)) == 0) - { - DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname)); - return False; - } - - ServerFD = open_socket_in(SOCK_DGRAM, 0,3,interpret_addr(lp_socket_address())); - - if (ServerFD == -1) - return(False); - - set_socket_options(ServerFD,"SO_BROADCAST"); - - DEBUG(3, ("Socket opened.\n")); - return True; -} - - -/**************************************************************************** - initialise connect, service and file structs -****************************************************************************/ -static BOOL init_structs(void ) -{ - if (!get_myname(myhostname,NULL)) - return(False); - - return True; -} - -/**************************************************************************** -usage on the program -****************************************************************************/ -static void usage(void) -{ - printf("Usage: nmblookup [-M] [-B bcast address] [-d debuglevel] name\n"); - printf("Version %s\n",VERSION); - printf("\t-d debuglevel set the debuglevel\n"); - printf("\t-B broadcast address the address to use for broadcasts\n"); - printf("\t-M searches for a master browser\n"); - printf("\t-S lookup node status as well\n"); - printf("\n"); -} - - -/**************************************************************************** - main program -****************************************************************************/ -int main(int argc,char *argv[]) -{ - int opt; - unsigned int lookup_type = 0x0; - pstring lookup; - extern int optind; - extern char *optarg; - BOOL find_master=False; - BOOL find_status=False; - int i; - static pstring servicesf = CONFIGFILE; - struct in_addr bcast_addr; - BOOL got_bcast = False; - - DEBUGLEVEL = 1; - *lookup = 0; - - TimeInit(); - - setup_logging(argv[0],True); - - charset_initialise(0); - - while ((opt = getopt(argc, argv, "p:d:B:i:s:SMh")) != EOF) - switch (opt) - { - case 'B': - iface_set_default(NULL,optarg,NULL); - bcast_addr = *interpret_addr2(optarg); - got_bcast = True; - break; - case 'i': - strcpy(scope,optarg); - strupper(scope); - break; - case 'M': - find_master = True; - break; - case 'S': - find_status = True; - break; - case 'd': - DEBUGLEVEL = atoi(optarg); - break; - case 's': - strcpy(servicesf, optarg); - break; - case 'h': - usage(); - exit(0); - break; - default: - usage(); - exit(1); - } - - if (argc < 2) { - usage(); - exit(1); - } - - if (!lp_load(servicesf,True)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); - } - - load_interfaces(); - init_structs(); - if (!open_sockets()) return(1); - - if (!got_bcast) - bcast_addr = *iface_bcast(ipzero); - - DEBUG(1,("Sending queries to %s\n",inet_ntoa(bcast_addr))); - - - for (i=optind;i<argc;i++) - { - BOOL bcast = True; - int retries = 2; - char *p; - struct in_addr ip; - - strcpy(lookup,argv[i]); - - if (find_master) { - if (*lookup == '-') { - strcpy(lookup,"\01\02__MSBROWSE__\02"); - lookup_type = 1; - } else { - lookup_type = 0x1d; - } - } - - p = strchr(lookup,'#'); - - if (p) { - *p = 0; - sscanf(p+1,"%x",&lookup_type); - bcast = False; - retries = 1; - } - - if (name_query(ServerFD,lookup,lookup_type,bcast,True, - bcast_addr,&ip,NULL)) - { - printf("%s %s\n",inet_ntoa(ip),lookup); - } - if (find_status) - { - printf("Looking up status of %s\n",inet_ntoa(ip)); - name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL); - printf("\n"); - } - } - - return(0); -} diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c deleted file mode 100644 index 495f8e585cb..00000000000 --- a/source/utils/smbpasswd.c +++ /dev/null @@ -1,457 +0,0 @@ -#ifdef SMB_PASSWD - -/* - * Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright - * (C) Jeremy Allison 1995-1997. - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 675 - * Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" -#include "des.h" - -/* Static buffers we will return. */ -static struct smb_passwd pw_buf; -static pstring user_name; -static unsigned char smbpwd[16]; -static unsigned char smbntpwd[16]; - -static int gethexpwd(char *p, char *pwd) -{ - int i; - unsigned char lonybble, hinybble; - char *hexchars = "0123456789ABCDEF"; - char *p1, *p2; - for (i = 0; i < 32; i += 2) { - hinybble = toupper(p[i]); - lonybble = toupper(p[i + 1]); - - p1 = strchr(hexchars, hinybble); - p2 = strchr(hexchars, lonybble); - if (!p1 || !p2) - return (False); - - hinybble = PTR_DIFF(p1, hexchars); - lonybble = PTR_DIFF(p2, hexchars); - - pwd[i / 2] = (hinybble << 4) | lonybble; - } - return (True); -} - -struct smb_passwd * -_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd, - BOOL *got_valid_nt_entry, long *pwd_seekpos) -{ - char linebuf[256]; - unsigned char c; - unsigned char *p; - long uidval; - long linebuf_len; - - /* - * Scan the file, a line at a time and check if the name matches. - */ - while (!feof(fp)) { - linebuf[0] = '\0'; - *pwd_seekpos = ftell(fp); - - fgets(linebuf, 256, fp); - if (ferror(fp)) - return NULL; - - /* - * Check if the string is terminated with a newline - if not - * then we must keep reading and discard until we get one. - */ - linebuf_len = strlen(linebuf); - if (linebuf[linebuf_len - 1] != '\n') { - c = '\0'; - while (!ferror(fp) && !feof(fp)) { - c = fgetc(fp); - if (c == '\n') - break; - } - } else - linebuf[linebuf_len - 1] = '\0'; - - if ((linebuf[0] == 0) && feof(fp)) - break; - /* - * The line we have should be of the form :- - * - * username:uid:[32hex bytes]:....other flags presently - * ignored.... - * - * or, - * - * username:uid:[32hex bytes]:[32hex bytes]:....ignored.... - * - * if Windows NT compatible passwords are also present. - */ - - if (linebuf[0] == '#' || linebuf[0] == '\0') - continue; - p = (unsigned char *) strchr(linebuf, ':'); - if (p == NULL) - continue; - /* - * As 256 is shorter than a pstring we don't need to check - * length here - if this ever changes.... - */ - strncpy(user_name, linebuf, PTR_DIFF(p, linebuf)); - user_name[PTR_DIFF(p, linebuf)] = '\0'; - if (!strequal(user_name, name)) - continue; - - /* User name matches - get uid and password */ - p++; /* Go past ':' */ - if (!isdigit(*p)) - return (False); - - uidval = atoi((char *) p); - while (*p && isdigit(*p)) - p++; - - if (*p != ':') - return (False); - - /* - * Now get the password value - this should be 32 hex digits - * which are the ascii representations of a 16 byte string. - * Get two at a time and put them into the password. - */ - p++; - *pwd_seekpos += PTR_DIFF(p, linebuf); /* Save exact position - * of passwd in file - - * this is used by - * smbpasswd.c */ - if (*p == '*' || *p == 'X') { - /* Password deliberately invalid - end here. */ - *valid_old_pwd = False; - *got_valid_nt_entry = False; - pw_buf.smb_nt_passwd = NULL; /* No NT password (yet)*/ - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { - /* NT Entry was valid - even if 'X' or '*', can be overwritten */ - *got_valid_nt_entry = True; - if (*p != '*' && *p != 'X') { - if (gethexpwd((char *)p,(char *)smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; - } - } - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; - pw_buf.smb_passwd = NULL; /* No password */ - return (&pw_buf); - } - if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) - return (False); - - if (p[32] != ':') - return (False); - - if (!strncasecmp((char *)p, "NO PASSWORD", 11)) { - pw_buf.smb_passwd = NULL; /* No password */ - } else { - if(!gethexpwd((char *)p,(char *)smbpwd)) - return False; - pw_buf.smb_passwd = smbpwd; - } - - pw_buf.smb_name = user_name; - pw_buf.smb_userid = uidval; - pw_buf.smb_nt_passwd = NULL; - *got_valid_nt_entry = False; - *valid_old_pwd = True; - - /* Now check if the NT compatible password is - available. */ - p += 33; /* Move to the first character of the line after - the lanman password. */ - if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) { - /* NT Entry was valid - even if 'X' or '*', can be overwritten */ - *got_valid_nt_entry = True; - if (*p != '*' && *p != 'X') { - if (gethexpwd((char *)p,(char *)smbntpwd)) - pw_buf.smb_nt_passwd = smbntpwd; - } - } - return &pw_buf; - } - return NULL; -} - -/* - * Print command usage on stderr and die. - */ -static void usage(char *name) -{ - fprintf(stderr, "Usage is : %s [username]\n", name); - exit(1); -} - - int main(int argc, char **argv) -{ - int real_uid; - struct passwd *pwd; - fstring old_passwd; - uchar old_p16[16]; - uchar old_nt_p16[16]; - fstring new_passwd; - uchar new_p16[16]; - uchar new_nt_p16[16]; - char *p; - struct smb_passwd *smb_pwent; - FILE *fp; - BOOL valid_old_pwd = False; - BOOL got_valid_nt_entry = False; - long seekpos; - int pwfd; - char ascii_p16[66]; - char c; - int ret, i, err, writelen; - int lockfd = -1; - char *pfile = SMB_PASSWD_FILE; - char readbuf[16 * 1024]; - - TimeInit(); - - setup_logging(argv[0],True); - - charset_initialise(0); - -#ifndef DEBUG_PASSWORD - /* Check the effective uid */ - if (geteuid() != 0) { - fprintf(stderr, "%s: Must be setuid root.\n", argv[0]); - exit(1); - } -#endif - - /* Get the real uid */ - real_uid = getuid(); - - /* Deal with usage problems */ - if (real_uid == 0) { - /* As root we can change anothers password. */ - if (argc != 1 && argc != 2) - usage(argv[0]); - } else if (argc != 1) - usage(argv[0]); - - - if (real_uid == 0 && argc == 2) { - /* If we are root we can change anothers password. */ - strncpy(user_name, argv[1], sizeof(user_name) - 1); - user_name[sizeof(user_name) - 1] = '\0'; - pwd = getpwnam(user_name); - } else { - pwd = getpwuid(real_uid); - } - - if (pwd == 0) { - fprintf(stderr, "%s: Unable to get UNIX password entry for user.\n", argv[0]); - exit(1); - } - /* If we are root we don't ask for the old password. */ - old_passwd[0] = '\0'; - if (real_uid != 0) { - p = getpass("Old SMB password:"); - strncpy(old_passwd, p, sizeof(fstring)); - old_passwd[sizeof(fstring)-1] = '\0'; - } - new_passwd[0] = '\0'; - p = getpass("New SMB password:"); - strncpy(new_passwd, p, sizeof(fstring)); - new_passwd[sizeof(fstring)-1] = '\0'; - p = getpass("Retype new SMB password:"); - if (strcmp(p, new_passwd)) { - fprintf(stderr, "%s: Mismatch - password unchanged.\n", argv[0]); - exit(1); - } - - if (new_passwd[0] == '\0') { - printf("Password not set\n"); - exit(0); - } - - /* Calculate the MD4 hash (NT compatible) of the old and new passwords */ - memset(old_nt_p16, '\0', 16); - E_md4hash((uchar *)old_passwd, old_nt_p16); - - memset(new_nt_p16, '\0', 16); - E_md4hash((uchar *) new_passwd, new_nt_p16); - - /* Mangle the passwords into Lanman format */ - old_passwd[14] = '\0'; - strupper(old_passwd); - new_passwd[14] = '\0'; - strupper(new_passwd); - - /* - * Calculate the SMB (lanman) hash functions of both old and new passwords. - */ - - memset(old_p16, '\0', 16); - E_P16((uchar *) old_passwd, old_p16); - - memset(new_p16, '\0', 16); - E_P16((uchar *) new_passwd, new_p16); - - /* - * Open the smbpaswd file XXXX - we need to parse smb.conf to get the - * filename - */ - if ((fp = fopen(pfile, "r+")) == NULL) { - err = errno; - fprintf(stderr, "%s: Failed to open password file %s.\n", - argv[0], pfile); - errno = err; - perror(argv[0]); - exit(err); - } - /* Set read buffer to 16k for effiecient reads */ - setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf)); - - /* make sure it is only rw by the owner */ - chmod(pfile, 0600); - - /* Lock the smbpasswd file for write. */ - if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) { - err = errno; - fprintf(stderr, "%s: Failed to lock password file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - exit(err); - } - /* Get the smb passwd entry for this user */ - smb_pwent = _my_get_smbpwnam(fp, pwd->pw_name, &valid_old_pwd, - &got_valid_nt_entry, &seekpos); - if (smb_pwent == NULL) { - fprintf(stderr, "%s: Failed to find entry for user %s in file %s.\n", - argv[0], pwd->pw_name, pfile); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - /* If we are root we don't need to check the old password. */ - if (real_uid != 0) { - if ((valid_old_pwd == False) || (smb_pwent->smb_passwd == NULL)) { - fprintf(stderr, "%s: User %s is disabled, plase contact your administrator to enable it.\n", argv[0], pwd->pw_name); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - /* Check the old Lanman password */ - if (memcmp(old_p16, smb_pwent->smb_passwd, 16)) { - fprintf(stderr, "%s: Couldn't change password.\n", argv[0]); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - /* Check the NT password if it exists */ - if (smb_pwent->smb_nt_passwd != NULL) { - if (memcmp(old_nt_p16, smb_pwent->smb_nt_passwd, 16)) { - fprintf(stderr, "%s: Couldn't change password.\n", argv[0]); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - } - } - /* - * If we get here either we were root or the old password checked out - * ok. - */ - /* Create the 32 byte representation of the new p16 */ - for (i = 0; i < 16; i++) { - sprintf(&ascii_p16[i * 2], "%02X", (uchar) new_p16[i]); - } - if(got_valid_nt_entry) { - /* Add on the NT md4 hash */ - ascii_p16[32] = ':'; - for (i = 0; i < 16; i++) { - sprintf(&ascii_p16[(i * 2)+33], "%02X", (uchar) new_nt_p16[i]); - } - } - /* - * Do an atomic write into the file at the position defined by - * seekpos. - */ - pwfd = fileno(fp); - ret = lseek(pwfd, seekpos - 1, SEEK_SET); - if (ret != seekpos - 1) { - err = errno; - fprintf(stderr, "%s: seek fail on file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - pw_file_unlock(lockfd); - exit(1); - } - /* Sanity check - ensure the character is a ':' */ - if (read(pwfd, &c, 1) != 1) { - err = errno; - fprintf(stderr, "%s: read fail on file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - pw_file_unlock(lockfd); - exit(1); - } - if (c != ':') { - fprintf(stderr, "%s: sanity check on passwd file %s failed.\n", - argv[0], pfile); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - writelen = (got_valid_nt_entry) ? 65 : 32; - if (write(pwfd, ascii_p16, writelen) != writelen) { - err = errno; - fprintf(stderr, "%s: write fail in file %s.\n", - argv[0], pfile); - fclose(fp); - errno = err; - perror(argv[0]); - pw_file_unlock(lockfd); - exit(err); - } - fclose(fp); - pw_file_unlock(lockfd); - printf("Password changed\n"); - return 0; -} - -#else - -#include "includes.h" - -int -main(int argc, char **argv) -{ - printf("smb password encryption not selected in Makefile\n"); - return 0; -} -#endif diff --git a/source/utils/status.c b/source/utils/status.c deleted file mode 100644 index 77fbc7fae11..00000000000 --- a/source/utils/status.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - status reporting - Copyright (C) Andrew Tridgell 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Revision History: - - 12 aug 96: Erik.Devriendt@te6.siemens.be - added support for shared memory implementation of share mode locking -*/ - -/* - * This program reports current SMB connections - */ - -#ifdef SYSLOG -#undef SYSLOG -#endif - -#include "includes.h" - -struct connect_record crec; - -struct session_record{ - int pid; - int uid; - char machine[31]; - time_t start; - struct session_record *next; -} *srecs; - -extern int DEBUGLEVEL; -extern FILE *dbf; -extern pstring myhostname; - -static pstring Ucrit_username = ""; /* added by OH */ -int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */ -int Ucrit_MaxPid=0; /* added by OH */ -unsigned int Ucrit_IsActive = 0; /* added by OH */ - -#ifndef FAST_SHARE_MODES -static char *read_share_file(int fd, char *fname, char *progname) -{ - struct stat sb; - char *buf; - int size; - - if(fstat(fd, &sb) != 0) - { - printf("%s: ERROR: read_share_file: Failed to do stat on share file %s (%s)\n", - progname, fname, strerror(errno)); - return 0; - } - - if(sb.st_size == 0) - { - return 0; - } - - /* Allocate space for the file */ - if((buf = (char *)malloc(sb.st_size)) == NULL) - { - printf("%s: read_share_file: malloc for file size %d fail !\n", - progname, (int)sb.st_size); - return 0; - } - - if(lseek(fd, 0, SEEK_SET) != 0) - { - printf("%s: ERROR: read_share_file: Failed to reset position to 0 \ -for share file %s (%s)\n", progname, fname, strerror(errno)); - if(buf) - free(buf); - return 0; - } - - if (read(fd,buf,sb.st_size) != sb.st_size) - { - printf("%s: ERROR: read_share_file: Failed to read share file %s (%s)\n", - progname, fname, strerror(errno)); - if(buf) - free(buf); - return 0; - } - - if (IVAL(buf,0) != LOCKING_VERSION) { - printf("%s: ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - progname, IVAL(buf,0), LOCKING_VERSION); - if(buf) - free(buf); - return 0; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= 10; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, 8); - - /* The remaining size must be a multiple of 16 - error if not. */ - if((size % 16) != 0) - { - printf("%s: ERROR: read_share_file: share file %s is an incorrect length.\n", - progname, fname); - if(buf) - free(buf); - return 0; - } - - return buf; -} -#endif /* FAST_SHARE_MODES */ - - int main(int argc, char *argv[]) -{ - FILE *f; - pstring fname; - int uid, c; - static pstring servicesf = CONFIGFILE; - extern char *optarg; - int verbose = 0, brief =0; - BOOL firstopen=True; - BOOL processes_only=False; - int last_pid=0; -#ifdef FAST_SHARE_MODES - pstring shmem_file_name; - share_mode_record *file_scanner_p; - smb_shm_offset_t *mode_array; - int bytes_free, bytes_used, bytes_overhead, bytes_total; -#else /* FAST_SHARE_MODES */ - void *dir; - char *s; -#endif /* FAST_SHARE_MODES */ - int i; - struct session_record *ptr; - - - TimeInit(); - setup_logging(argv[0],True); - - charset_initialise(0); - - DEBUGLEVEL = 0; - dbf = fopen("/dev/null","w"); - - if (getuid() != geteuid()) { - printf("smbstatus should not be run setuid\n"); - return(1); - } - - while ((c = getopt(argc, argv, "pds:u:b")) != EOF) { - switch (c) { - case 'b': - brief = 1; - break; - case 'd': - verbose = 1; - break; - case 'p': - processes_only = 1; - break; - case 's': - strcpy(servicesf, optarg); - break; - case 'u': /* added by OH */ - Ucrit_addUsername(optarg); /* added by OH */ - break; - default: - fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */ - return (-1); - } - } - - if (!lp_load(servicesf,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); - return (-1); - } - - get_myname(myhostname, NULL); - - if (verbose) { - printf("using configfile = %s\n", servicesf); - printf("lockdir = %s\n", *lp_lockdir() ? lp_lockdir() : "NULL"); - } - - strcpy(fname,lp_lockdir()); - standard_sub_basic(fname); - trim_string(fname,"","/"); - strcat(fname,"/STATUS..LCK"); - - f = fopen(fname,"r"); - if (!f) { - printf("Couldn't open status file %s\n",fname); - if (!lp_status(-1)) - printf("You need to have status=yes in your smb config file\n"); - return(0); - } - else if (verbose) { - printf("Opened status file %s\n", fname); - } - - uid = getuid(); - - if (!processes_only) { - printf("\nSamba version %s\n",VERSION); - - if (brief) - { - printf("PID Username Machine Time logged in\n"); - printf("-------------------------------------------------------------------\n"); - } - else - { - printf("Service uid gid pid machine\n"); - printf("----------------------------------------------\n"); - } - } - - while (!feof(f)) - { - if (fread(&crec,sizeof(crec),1,f) != 1) - break; - if ( crec.magic == 0x280267 && process_exists(crec.pid) - && Ucrit_checkUsername(uidtoname(crec.uid)) /* added by OH */ - ) - { - if (brief) - { - ptr=srecs; - while (ptr!=NULL) - { - if ((ptr->pid==crec.pid)&&(strncmp(ptr->machine,crec.machine,30)==0)) - { - if (ptr->start > crec.start) - ptr->start=crec.start; - break; - } - ptr=ptr->next; - } - if (ptr==NULL) - { - ptr=(struct session_record *) malloc(sizeof(struct session_record)); - ptr->uid=crec.uid; - ptr->pid=crec.pid; - ptr->start=crec.start; - strncpy(ptr->machine,crec.machine,30); - ptr->machine[30]='\0'; - ptr->next=srecs; - srecs=ptr; - } - } - else - { - Ucrit_addPid(crec.pid); /* added by OH */ - if (processes_only) { - if (last_pid != crec.pid) - printf("%d\n",crec.pid); - last_pid = crec.pid; /* XXXX we can still get repeats, have to - add a sort at some time */ - } - else - printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s", - crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid, - crec.machine,crec.addr, - asctime(LocalTime(&crec.start))); - } - } - } - fclose(f); - - if (processes_only) exit(0); - - if (brief) - { - ptr=srecs; - while (ptr!=NULL) - { - printf("%-8d%-10.10s%-30.30s%s",ptr->pid,uidtoname(ptr->uid),ptr->machine,asctime(LocalTime(&(ptr->start)))); - ptr=ptr->next; - } - printf("\n"); - exit(0); - } - - printf("\n"); - -#ifdef FAST_SHARE_MODES - /******************************************************************* - initialize the shared memory for share_mode management - ******************************************************************/ - - strcpy(shmem_file_name,lp_lockdir()); - trim_string(shmem_file_name,"","/"); - if (!*shmem_file_name) exit(-1); - strcat(shmem_file_name, "/SHARE_MEM_FILE"); - if(!smb_shm_open(shmem_file_name, lp_shmem_size())) exit(-1); - - mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off()); - if(mode_array == NULL) - { - printf("%s: base of shared memory hash array == 0! Exiting.\n", argv[0]); - smb_shm_close(); - exit(-1); - } - - for( i = 0; i < lp_shmem_hash_size(); i++) - { - smb_shm_lock_hash_entry(i); - if(mode_array[i] == NULL_OFFSET) - { - smb_shm_unlock_hash_entry(i); - continue; - } - file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]); - while((file_scanner_p != 0) && (file_scanner_p->num_share_mode_entries != 0)) - { - share_mode_entry *entry_scanner_p = - (share_mode_entry *)smb_shm_offset2addr( - file_scanner_p->share_mode_entries); - - while(entry_scanner_p != 0) - { - struct timeval t; - int pid = entry_scanner_p->pid; - int mode = entry_scanner_p->share_mode; - - t.tv_sec = entry_scanner_p->time.tv_sec; - t.tv_usec = entry_scanner_p->time.tv_usec; - strcpy(fname, file_scanner_p->file_name); -#else /* FAST_SHARE_MODES */ - - /* For slow share modes go through all the files in - the share mode directory and read the entries in - each. - */ - - dir = opendir(lp_lockdir()); - if (!dir) - { - printf("%s: Unable to open lock directory %s.\n", argv[0], lp_lockdir()); - return(0); - } - while ((s=readdirname(dir))) { - char *buf; - char *base; - int fd; - pstring lname; - uint32 dev,inode; - - if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue; - - strcpy(lname,lp_lockdir()); - trim_string(lname,NULL,"/"); - strcat(lname,"/"); - strcat(lname,s); - - fd = open(lname,O_RDWR,0); - if (fd < 0) - { - printf("%s: Unable to open share file %s.\n", argv[0], lname); - continue; - } - - /* Lock the share mode file while we read it. */ - if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) - { - printf("%s: Unable to lock open share file %s.\n", argv[0], lname); - close(fd); - continue; - } - - if(( buf = read_share_file( fd, lname, argv[0] )) == NULL) - { - close(fd); - continue; - } - strcpy( fname, &buf[10]); - close(fd); - - base = buf + 10 + SVAL(buf,8); - for( i = 0; i < IVAL(buf, 4); i++) - { - char *p = base + (i*16); - struct timeval t; - int pid = IVAL(p,12); - int mode = IVAL(p,8); - - t.tv_sec = IVAL(p,0); - t.tv_usec = IVAL(p,4); -#endif /* FAST_SHARE_MODES */ - - fname[sizeof(fname)-1] = 0; - - if (firstopen) { - firstopen=False; - printf("Locked files:\n"); - printf("Pid DenyMode R/W Name\n"); - printf("------------------------------\n"); - } - - - printf("%-5d ",pid); - switch ((mode>>4)&0xF) - { - case DENY_NONE: printf("DENY_NONE "); break; - case DENY_ALL: printf("DENY_ALL "); break; - case DENY_DOS: printf("DENY_DOS "); break; - case DENY_READ: printf("DENY_READ "); break; - case DENY_WRITE:printf("DENY_WRITE "); break; - } - switch (mode&0xF) - { - case 0: printf("RDONLY "); break; - case 1: printf("WRONLY "); break; - case 2: printf("RDWR "); break; - } - printf(" %s %s",fname,asctime(LocalTime((time_t *)&t.tv_sec))); - -#ifdef FAST_SHARE_MODES - - entry_scanner_p = (share_mode_entry *)smb_shm_offset2addr( - entry_scanner_p->next_share_mode_entry); - } /* end while entry_scanner_p */ - file_scanner_p = (share_mode_record *)smb_shm_offset2addr( - file_scanner_p->next_offset); - } /* end while file_scanner_p */ - smb_shm_unlock_hash_entry(i); - } /* end for */ - - smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead); - bytes_total = bytes_free + bytes_used + bytes_overhead; - - /******************************************************************* - deinitialize the shared memory for share_mode management - ******************************************************************/ - smb_shm_close(); - -#else /* FAST_SHARE_MODES */ - } /* end for i */ - - if(buf) - free(buf); - base = 0; - } /* end while */ - closedir(dir); - -#endif /* FAST_SHARE_MODES */ - if (firstopen) - printf("No locked files\n"); -#ifdef FAST_SHARE_MODES - printf("\nShare mode memory usage (bytes):\n"); - printf(" %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n", - bytes_free, (bytes_free * 100)/bytes_total, - bytes_used, (bytes_used * 100)/bytes_total, - bytes_overhead, (bytes_overhead * 100)/bytes_total, - bytes_total); - -#endif /* FAST_SHARE_MODES */ - - return (0); -} - -/* added by OH */ -void Ucrit_addUsername(pstring username) -{ - strcpy(Ucrit_username, username); - if(strlen(Ucrit_username) > 0) - Ucrit_IsActive = 1; -} - -unsigned int Ucrit_checkUsername(pstring username) -{ - if ( !Ucrit_IsActive) return 1; - if (strcmp(Ucrit_username,username) ==0) return 1; - return 0; -} - -void Ucrit_addPid(int pid) -{ - int i; - if ( !Ucrit_IsActive) return; - for (i=0;i<Ucrit_MaxPid;i++) - if( pid == Ucrit_pid[i] ) return; - Ucrit_pid[Ucrit_MaxPid++] = pid; -} - -unsigned int Ucrit_checkPid(int pid) -{ - int i; - if ( !Ucrit_IsActive) return 1; - for (i=0;i<Ucrit_MaxPid;i++) - if( pid == Ucrit_pid[i] ) return 1; - return 0; -} - diff --git a/source/utils/testparm.c b/source/utils/testparm.c deleted file mode 100644 index e9a848eb0b4..00000000000 --- a/source/utils/testparm.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Test validity of smb.conf - Copyright (C) Karl Auer 1993, 1994-1997 - - Extensively modified by Andrew Tridgell, 1995 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * Testbed for loadparm.c/params.c - * - * This module simply loads a specified configuration file and - * if successful, dumps it's contents to stdout. Note that the - * operation is performed with DEBUGLEVEL at 3. - * - * Useful for a quick 'syntax check' of a configuration file. - * - */ - -#include "includes.h" -#include "smb.h" - -/* these live in util.c */ -extern FILE *dbf; -extern int DEBUGLEVEL; - - int main(int argc, char *argv[]) -{ - pstring configfile; - int s; - - TimeInit(); - - setup_logging(argv[0],True); - - charset_initialise(0); - - if (argc < 2) - strcpy(configfile,CONFIGFILE); - else - strcpy(configfile,argv[1]); - - dbf = stdout; - DEBUGLEVEL = 2; - - printf("Load smb config files from %s\n",configfile); - - if (!lp_load(configfile,False)) - { - printf("Error loading services.\n"); - return(1); - } - - - printf("Loaded services file OK.\n"); - - for (s=0;s<1000;s++) - if (VALID_SNUM(s)) - if (strlen(lp_servicename(s)) > 8) { - printf("WARNING: You have some share names that are longer than 8 chars\n"); - printf("These may give errors while browsing or may not be accessible\nto some older clients\n"); - break; - } - - if (argc < 4) - { - printf("Press enter to see a dump of your service definitions\n"); - fflush(stdout); - getc(stdin); - lp_dump(); - } - - if (argc == 4) - { - char *cname = argv[2]; - char *caddr = argv[3]; - - /* this is totally ugly, a real `quick' hack */ - for (s=0;s<1000;s++) - if (VALID_SNUM(s)) - { - if (allow_access(lp_hostsdeny(s),lp_hostsallow(s),cname,caddr)) - { - printf("Allow connection from %s (%s) to %s\n", - cname,caddr,lp_servicename(s)); - } - else - { - printf("Deny connection from %s (%s) to %s\n", - cname,caddr,lp_servicename(s)); - } - } - } - return(0); -} - - diff --git a/source/utils/testprns.c b/source/utils/testprns.c deleted file mode 100644 index c96ad476d29..00000000000 --- a/source/utils/testprns.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - test printer setup - Copyright (C) Karl Auer 1993, 1994-1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - * Testbed for pcap.c - * - * This module simply checks a given printer name against the compiled-in - * printcap file. - * - * The operation is performed with DEBUGLEVEL at 3. - * - * Useful for a quick check of a printcap file. - * - */ - -#include "includes.h" -#include "smb.h" - -/* these live in util.c */ -extern FILE *dbf; -extern int DEBUGLEVEL; - -int main(int argc, char *argv[]) -{ - char *pszTemp; - - TimeInit(); - - setup_logging(argv[0],True); - - charset_initialise(0); - - if (argc < 2 || argc > 3) - printf("Usage: testprns printername [printcapfile]\n"); - else - { - dbf = fopen("test.log", "w"); - if (dbf == NULL) { - printf("Unable to open logfile.\n"); - } else { - DEBUGLEVEL = 3; - pszTemp = (argc < 3) ? PRINTCAP_NAME : argv[2]; - printf("Looking for printer %s in printcap file %s\n", - argv[1], pszTemp); - if (!pcap_printername_ok(argv[1], pszTemp)) - printf("Printer name %s is not valid.\n", argv[1]); - else - printf("Printer name %s is valid.\n", argv[1]); - fclose(dbf); - } - } - return (0); -} - |