diff options
author | cvs2svn Import User <samba-bugs@samba.org> | 1997-10-10 14:46:44 +0000 |
---|---|---|
committer | cvs2svn Import User <samba-bugs@samba.org> | 1997-10-10 14:46:44 +0000 |
commit | 4480ee713f3ebaaf6852c2e3a5967b30e587f7db (patch) | |
tree | 70a8a34fa622fd9adef3dd7f65da299bf6c3e48a /source | |
parent | 3590a783338defa4ff1385b2d5bb095c5051ac82 (diff) | |
download | samba-4480ee713f3ebaaf6852c2e3a5967b30e587f7db.tar.gz samba-4480ee713f3ebaaf6852c2e3a5967b30e587f7db.tar.xz samba-4480ee713f3ebaaf6852c2e3a5967b30e587f7db.zip |
This commit was manufactured by cvs2svn to create tag 'samba'.samba-misc-tags/samba
Diffstat (limited to 'source')
124 files changed, 0 insertions, 69767 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/arcfour.c b/source/arcfour.c deleted file mode 100644 index a28d702a861..00000000000 --- a/source/arcfour.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - - a implementation of arcfour designed for use in the - SMB password change protocol based on the description - in 'Applied Cryptography', 2nd Edition. - - Copyright (C) Jeremy Allison 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 "arcfour.h" - -void set_arc4_key(unsigned char *data, int key_length, arc4_key *arckey) -{ - unsigned int i; - unsigned char j; - unsigned char tc; - unsigned char *s_box = &arckey->s_box[0]; - - arckey->index_i = 0; - arckey->index_j = 0; - for(i = 0; i < 256; i++) - s_box[i] = (unsigned char)i; - - j = 0; - for( i = 0; i < 256; i++) - { - j += (s_box[i] + data[i%key_length]); - tc = s_box[i]; - s_box[i] = s_box[j]; - s_box[j] = tc; - } -} - -void arc4(arc4_key *arckey, unsigned char *data_in, unsigned char *data_out, - int length) -{ - unsigned char tc; - int ind; - unsigned char i, j; - unsigned char t; - unsigned char *s_box = &arckey->s_box[0]; - - for( ind = 0; ind < length; ind++) - { - i = ++arckey->index_i; - j = arckey->index_j += s_box[i]; - tc = s_box[i]; - s_box[i] = s_box[j]; - s_box[j] = tc; - t = s_box[i] + s_box[j]; - *data_out++ = *data_in++ ^ s_box[t]; - } -} - -#if 0 -/* Test vector */ -unsigned char key_data[] = { 0x61, 0x8a, 0x63, 0xd2, 0xfb }; -unsigned char plaintext[] = { 0xdc, 0xee, 0x4c, 0xf9, 0x2c }; -unsigned char ciphertext[] = { 0xf1, 0x38, 0x29, 0xc9, 0xde }; - -int main(int argc, char *argv[]) -{ - unsigned char out[5]; - arc4_key key; - - set_arc4_key(key_data, 5, &key); - arc4(&key, plaintext, out, 5); - - if(memcmp(out, ciphertext, 5) ==0) - printf("Test ok !\n"); - else - printf("Test fail !\n"); - return 0; -} -#endif diff --git a/source/arcfour.h b/source/arcfour.h deleted file mode 100644 index 34a4e8f91be..00000000000 --- a/source/arcfour.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _ARC4_H_ -#define _ARC4_H_ - -/* - Unix SMB/Netbios implementation. - Version 1.9. - - a implementation of arcfour designed for use in the - SMB password change protocol based on the description - in 'Applied Cryptography', 2nd Edition. - - Copyright (C) Jeremy Allison 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. -*/ - -typedef struct { - unsigned char s_box[256]; - unsigned char index_i; - unsigned char index_j; -} arc4_key; - -extern void set_arc4_key(unsigned char *data, int key_length, arc4_key *arckey); -extern void arc4(arc4_key *arckey, unsigned char *data_in, - unsigned char *data_out, int length); - -#endif /* _ARC4_H_ */ diff --git a/source/cgi.c b/source/cgi.c deleted file mode 100644 index 56c293985d6..00000000000 --- a/source/cgi.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - some simple CGI helper routines - Copyright (C) Andrew Tridgell 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 MAX_VARIABLES 512 - -struct var { - char *name; - char *value; -}; - -static struct var variables[MAX_VARIABLES]; -static int num_variables; - - -static int grab_line(int *cl, char *line, int maxsize) -{ - int i = 0; - - while ((*cl)) { - int c = fgetc(stdin); - (*cl)--; - - if (c == EOF) { - (*cl) = 0; - break; - } - - if (c == '+') { - c = ' '; - } - - if (c == '\r') continue; - - if (strchr("\n&", c)) break; - - if (c == '%' && (*cl) >= 2) { - int c1, c2; - c1 = fgetc(stdin); - c2 = fgetc(stdin); - (*cl) -= 2; - if (c1 == EOF || c2 == EOF) break; - if (c1 >= '0' && c1 <= '9') - c1 = c1 - '0'; - else if (c1 >= 'A' && c1 <= 'F') - c1 = 10 + c1 - 'A'; - else if (c1 >= 'a' && c1 <= 'f') - c1 = 10 + c1 - 'a'; - else break; - - if (c2 >= '0' && c2 <= '9') - c2 = c2 - '0'; - else if (c2 >= 'A' && c2 <= 'F') - c2 = 10 + c2 - 'A'; - else if (c2 >= 'a' && c2 <= 'f') - c2 = 10 + c2 - 'a'; - else break; - - c = (c1<<4) | c2; - } - - line[i++] = c; - - if (i == maxsize) break; - } - - /* now unescape the line */ - - - line[i] = 0; - return 1; -} - - -/*************************************************************************** - load all the variables passed to the CGI program - ***************************************************************************/ -void cgi_load_variables(void) -{ - static pstring line; - char *p; - int len; - - if (!(p=getenv("CONTENT_LENGTH"))) return; - - len = atoi(p); - - if (len <= 0) return; - - - - while (len && grab_line(&len, line, sizeof(line)-1)) { - p = strchr(line,'='); - if (!p) continue; - - *p = 0; - - variables[num_variables].name = strdup(line); - variables[num_variables].value = strdup(p+1); - - if (!variables[num_variables].name || - !variables[num_variables].value) - continue; - -#if 0 - printf("%s=%s<br>\n", - variables[num_variables].name, - variables[num_variables].value); -#endif - - num_variables++; - if (num_variables == MAX_VARIABLES) break; - } - - fclose(stdin); -} - - -/*************************************************************************** - find a variable passed via CGI - ***************************************************************************/ -char *cgi_variable(char *name) -{ - int i; - - for (i=0;i<num_variables;i++) - if (strcmp(variables[i].name, name) == 0) - return variables[i].value; - return NULL; -} - - -/*************************************************************************** - return the value of a CGI boolean variable. - ***************************************************************************/ -int cgi_boolean(char *name, int def) -{ - char *p = cgi_variable(name); - - if (!p) return def; - - return strcmp(p, "1") == 0; -} 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 6d85bd8807f..00000000000 --- a/source/client/client.c +++ /dev/null @@ -1,4910 +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; -extern pstring myhostname; -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); -static BOOL do_this_one(file_info *finfo); - -/* 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; - -/* totals globals */ -int dir_total = 0; - -extern int Client; - -#define USENMB - -extern int coding_system; -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; -} -#define CNV_LANG(s) dos2unix_format(s,False) -#define CNV_INPUT(s) unix2dos_format(s,True) - -/**************************************************************************** -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++; - } - - if(i < 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); - -#if 0 - { - /* this little bit of code can be used to extract NT error codes. - Just feed a bunch of "cd foo" commands to smbclient then watch - in netmon (tridge) */ - static int code=0; - SIVAL(outbuf, smb_rcls, code | 0xC0000000); - SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14)); - code++; - } -#endif - - 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) -{ - if (do_this_one(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)))); - dir_total += finfo->size; - } -} - - -/**************************************************************************** - 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=%lu, rdrcnt=%d>", datap, converter, (unsigned long)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; - - dir_total = 0; - 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(); - - DEBUG(3, ("Total bytes listed: %d\n", dir_total)); -} - - - -/**************************************************************************** - 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); - - if (doencrypt && *pass) { - DEBUG(3,("Using encrypted passwords\n")); - passlen = 24; - SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword); - } - - /* 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); - - if (doencrypt && *pass) { - passlen=24; - SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword); - } - - /* 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 -/* If strcasecmp is already defined, remove it. */ -#ifdef strcasecmp -#undef strcasecmp -#endif /* strcasecmp */ -#define strcasecmp StrCaseCmp -#endif /* NOSTRCASECMP */ - - 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,BUFFER_SIZE - SAFETY_MARGIN); /* 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,BUFFER_SIZE - SAFETY_MARGIN, - &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,BUFFER_SIZE - SAFETY_MARGIN, - &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 readret; - - set_blocking(fileno(stdin), False); - readret = read_data( fileno(stdin), &ch, 1); - set_blocking(fileno(stdin), True); - 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(0,("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)); - - 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")); - DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n")); - 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; - pstring term_code; - char *p; - -#ifdef KANJI - strcpy(term_code, KANJI); -#else /* KANJI */ - *term_code = 0; -#endif /* KANJI */ - - *query_host = 0; - *base_directory = 0; - - DEBUGLEVEL = 2; - - setup_logging(pname,True); - - TimeInit(); - charset_initialise(); - - pid = getpid(); - uid = getuid(); - gid = getgid(); - mid = pid + 100; - myumask = umask(0); - umask(myumask); - - if (getenv("USER")) - { - strcpy(username,getenv("USER")); - - /* modification to support userid%passwd syntax in the USER var - 25.Aug.97, jdblair@uab.edu */ - - if ((p=strchr(username,'%'))) - { - *p = 0; - strcpy(password,p+1); - got_pass = True; - memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); - } - strupper(username); - } - - /* modification to support PASSWD environmental var - 25.Aug.97, jdblair@uab.edu */ - - if (getenv("PASSWD")) - strcpy(password,getenv("PASSWD")); - - 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++; - } - } - - 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 *lp; - strcpy(username,optarg); - if ((lp=strchr(username,'%'))) - { - *lp = 0; - strcpy(password,lp+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': - strcpy(term_code, optarg); - 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(!get_myname(myhostname,NULL)) - { - DEBUG(0,("Failed to get my hostname.\n")); - } - - if (!lp_load(servicesf,True)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); - } - - codepage_initialise(lp_client_code_page()); - - if(lp_client_code_page() == KANJI_CODEPAGE) - { - if (!setup_term_code (term_code)) - { - DEBUG(0, ("%s: unknown terminal code name\n", optarg)); - usage (pname); - exit (1); - } - } - - 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,"An 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 01b4a093214..00000000000 --- a/source/client/clientutil.c +++ /dev/null @@ -1,1040 +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 + *data_len > total_data || - this_param + *param_len > total_param) { - DEBUG(1,("Data overflow in cli_receive_trans_response\n")); - return False; - } - - 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) */ - - fstrcpy(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); - } - - pstrcpy(dev,"A:"); - if (connect_as_printer) - pstrcpy(dev,"LPT1:"); - if (connect_as_ipc) - pstrcpy(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(pass == NULL) - { - DEBUG(0, ("cli_send_login : no password available - logon failed.\n")); - return False; - } - - if (Protocol >= PROTOCOL_LANMAN1 && use_setup) - { - fstring pword; - int passlen = strlen(pass)+1; - fstrcpy(pword,pass); - - if (doencrypt && *pass) { - DEBUG(5,("Using encrypted passwords\n")); - passlen = 24; - SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword); - } - - /* if in share level security then don't send a password now */ - if (!(sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} - - /* send a session setup command */ - bzero(outbuf,smb_size); - - if (passlen > MAX_PASS_LEN) { - DEBUG(1,("password too long %d\n", passlen)); - return False; - } - - 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; - fstrcpy(pword,pass); - - if (doencrypt && *pass) { - passlen=24; - SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword); - } - - /* if in user level security then don't send a password now */ - if ((sec_mode & 1)) { - fstrcpy(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 - { - pstrcpy(service2,service); - host = strtok(service2,"\\/"); - pstrcpy(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 c085cd9e5a1..00000000000 --- a/source/client/clitar.c +++ /dev/null @@ -1,1771 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Tar Extensions - Copyright (C) Ricky Poulten 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 "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, ttarf; -/* 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) { - /* write a GNU tar style long header */ - char *b; - b = (char *)malloc(l+TBLOCK+100); - if (!b) { - DEBUG(0,("out of memory\n")); - exit(1); - } - writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0"); - memset(b, 0, l+TBLOCK+100); - fixtarname(b, aname, l+1); - i = strlen(b)+1; - dotarbuf(f, b, TBLOCK*((i+(TBLOCK-1)/TBLOCK))); - free(b); - } - - /* 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)); - memset(hb.dbuf.linkname, 0, NAMSIZ); - if (strcmp("/./@LongLink", aname) == 0) { - /* we're doing a GNU tar long filename */ - hb.dbuf.linkflag='L'; - } else { - hb.dbuf.linkflag='0'; - } - - 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 and total dumped */ - tp=0; ntarf=0; ttarf=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++='.'; - if(lp_client_code_page() == KANJI_CODEPAGE) - { - 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++; - } - } -} - -/**************************************************************************** -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, allowing s1 to match s2 -if s1 is an "initial" string (up to directory marker). Thus, if s2 is -a file in any subdirectory of s1, declare a match. -***************************************************************************/ -static int strslashcmp(char *s1, char *s2) -{ - char *s1_0=s1; - - while(*s1 && *s2 && - (*s1 == *s2 - || tolower(*s1) == tolower(*s2) - || (*s1 == '\\' && *s2=='/') - || (*s1 == '/' && *s2=='\\'))) { - s1++; s2++; - } - - /* if s1 has a trailing slash, it compared equal, so s1 is an "initial" - string of s2. - */ - if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0; - - /* ignore trailing slash on s1 */ - if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0; - - /* check for s1 is an "initial" string of s2 */ - if (*s2 == '/' || *s2 == '\\') return 0; - - 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 to tar file - %s\n", strerror(errno))); - 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 tar file - %s\n", strerror(errno))); - } - - /* round tar file to nearest block */ - if (finfo.size % TBLOCK) - dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK)); - - ttarf+=finfo.size + 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'; - - 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++; - - if(lp_client_code_page() == KANJI_CODEPAGE) - { - 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++; - } - } -} - -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)); - DEBUG(0, ("Total bytes written: %d\n", ttarf)); - 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 - %s\n", - argv[Optind], strerror(errno))); - return(0); - } - } - - return 1; -} diff --git a/source/codepages/codepage_def.437 b/source/codepages/codepage_def.437 deleted file mode 100644 index d357c074e44..00000000000 --- a/source/codepages/codepage_def.437 +++ /dev/null @@ -1,70 +0,0 @@ -# -# 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. -# - -# Codepage definition file for IBM Code Page 437 - MS-DOS Latin US -# defines lower->upper mapping. -# Written by Jeremy Allison <jallison@whistle.com> - -# The columns are : -# lower upper map upper to lower map lower to upper -# - 0x87 0x80 True True - 0x81 0x9A True True - 0x82 0x90 True True - 0x83 0x41 True False - 0x84 0x8E True True - 0x85 0x41 True False - 0x86 0x8F True True - 0x88 0x45 True False - 0x89 0x45 True False - 0x8A 0x45 True False - 0x8B 0x49 True False - 0x8C 0x49 True False - 0x8D 0x49 True False - 0x91 0x92 True True - 0x93 0x4F True False - 0x94 0x99 True True - 0x95 0x4F True False - 0x96 0x55 True False - 0x97 0x55 True False - 0x9B 0 False False - 0x9C 0 False False - 0x9D 0 False False - 0xA0 0x41 True False - 0xA1 0x49 True False - 0xA2 0x4F True False - 0xA3 0x55 True False - 0xA4 0xA5 True True - 0xA8 0 False False - 0xAD 0 False False - 0xAE 0 False False - 0xAF 0 False False - 0xE0 0 False False - 0xE1 0 False False - 0xE2 0 False False - 0xE3 0 False False - 0xE4 0 False False - 0xE5 0 False False - 0xE6 0 False False - 0xE7 0 False False - 0xE8 0 False False - 0xE9 0 False False - 0xEA 0 False False - 0xEB 0 False False - 0xEC 0 False False - 0xED 0 False False - 0xEE 0 False False - 0xEF 0 False False diff --git a/source/codepages/codepage_def.850 b/source/codepages/codepage_def.850 deleted file mode 100644 index e2466a707af..00000000000 --- a/source/codepages/codepage_def.850 +++ /dev/null @@ -1,54 +0,0 @@ -# -# 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. -# - -# Codepage definition file for IBM Code Page 850 - MS-DOS Latin 1 -# defines lower->upper mapping. -# Written by Jeremy Allison (jallison@whistle.com) - -# The columns are : -# lower upper map upper to lower map lower to upper -# - 0x85 0xB7 True True - 0xA0 0xB5 True True - 0x83 0xB6 True True - 0xC6 0xC7 True True - 0x84 0x8E True True - 0x86 0x8F True True - 0x91 0x92 True True - 0x87 0x80 True True - 0x8A 0xD4 True True - 0x82 0x90 True True - 0x88 0xD2 True True - 0x89 0xD3 True True - 0x8D 0xDE True True - 0xA1 0xD6 True True - 0x8C 0xD7 True True - 0x8B 0xD8 True True - 0xD0 0xD1 True True - 0xA4 0xA5 True True - 0x95 0xE3 True True - 0xA2 0xE0 True True - 0x93 0xE2 True True - 0xE4 0xE5 True True - 0x94 0x99 True True - 0x9B 0x9D True True - 0x97 0xEB True True - 0xA3 0xE9 True True - 0x96 0xEA True True - 0x81 0x9A True True - 0xEC 0xED True True - 0xE7 0xE8 True True - 0x9C 0 False False diff --git a/source/codepages/codepage_def.852 b/source/codepages/codepage_def.852 deleted file mode 100644 index ed1423428ca..00000000000 --- a/source/codepages/codepage_def.852 +++ /dev/null @@ -1,63 +0,0 @@ -# -# 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. -# - -# Codepage definition file for IBM Code Page 852 - MS-DOS Latin 2 -# defines lower->upper mapping. -# Written by Leos Bitto <bitto@altec.cz> - -# The columns are : -# lower upper map upper to lower map lower to upper -# - 0x81 0x9A True True - 0x82 0x90 True True - 0x83 0xB6 True True - 0x84 0x8E True True - 0x85 0xDE True True - 0x86 0x8F True True - 0x87 0x80 True True - 0x88 0x9D True True - 0x89 0xD3 True True - 0x8B 0x8A True True - 0x8C 0xD7 True True - 0x92 0x91 True True - 0x93 0xE2 True True - 0x94 0x99 True True - 0x96 0x95 True True - 0x98 0x97 True True - 0x9C 0x9B True True - 0x9F 0xAC True True - 0xA0 0xB5 True True - 0xA1 0xD6 True True - 0xA2 0xE0 True True - 0xA3 0xE9 True True - 0xA5 0xA4 True True - 0xA7 0xA6 True True - 0xA9 0xA8 True True - 0xAB 0x8D True True - 0xAD 0xB8 True True - 0xBE 0xBD True True - 0xC7 0xC6 True True - 0xD0 0xD1 True True - 0xD4 0xD2 True True - 0xD8 0xB7 True True - 0xE4 0xE3 True True - 0xE5 0xD5 True True - 0xE7 0xE6 True True - 0xEA 0xE8 True True - 0xEC 0xED True True - 0xEE 0xDD True True - 0xFB 0xEB True True - 0xFD 0xFC True True diff --git a/source/codepages/codepage_def.932 b/source/codepages/codepage_def.932 deleted file mode 100644 index 8d9ff631fba..00000000000 --- a/source/codepages/codepage_def.932 +++ /dev/null @@ -1,24 +0,0 @@ -# -# 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. -# - -# Codepage definition file for IBM Code Page 932 - MS-DOS Japanese SJIS -# defines lower->upper mapping. -# Written by Jeremy Allison <jallison@whistle.com> - -# The columns are : -# lower upper map upper to lower map lower to upper -# -# This file is intentionaly empty - no mappings are done.
\ No newline at end of file diff --git a/source/include/byteorder.h b/source/include/byteorder.h deleted file mode 100644 index 0664a338175..00000000000 --- a/source/include/byteorder.h +++ /dev/null @@ -1,200 +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 :-) - -*/ - -/* some switch macros that do both store and read to and from SMB buffers */ - -#define RW_PCVAL(read,inbuf,outbuf,len) \ - if (read) { PCVAL (inbuf,0,outbuf,len) } \ - else { PSCVAL(inbuf,0,outbuf,len) } - -#define RW_PSVAL(read,inbuf,outbuf,len) \ - if (read) { PSVAL (inbuf,0,outbuf,len) } \ - else { PSSVAL(inbuf,0,outbuf,len) } - -#define RW_CVAL(read, inbuf, outbuf, offset) \ - if (read) (outbuf) = CVAL (inbuf,offset); \ - else SCVAL(inbuf,offset,outbuf); - -#define RW_IVAL(read, inbuf, outbuf, offset) \ - if (read) (outbuf)= IVAL (inbuf,offset); \ - else SIVAL(inbuf,offset,outbuf); - -#define RW_SVAL(read, inbuf, outbuf, offset) \ - if (read) (outbuf)= SVAL (inbuf,offset); \ - else SSVAL(inbuf,offset,outbuf); - -#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 -*/ - -/* get single value from an SMB buffer */ -#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))) - -/* store single value in an SMB buffer */ -#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 - - -/* macros for reading / writing arrays */ - -#define SMBMACRO(macro,buf,pos,val,len,size) \ -{ int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); } - -#define SSMBMACRO(macro,buf,pos,val,len,size) \ -{ int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); } - -/* reads multiple data from an SMB buffer */ -#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1) -#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2) -#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4) -#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1) -#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2) -#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4) - -/* stores multiple data in an SMB buffer */ -#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1) -#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2) -#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4) -#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1) -#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2) -#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4) - - -/* 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 fb184897c07..00000000000 --- a/source/include/charset.h +++ /dev/null @@ -1,75 +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(void); - -#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 - -/* Dynamic codepage files defines. */ - -/* Version id for dynamically loadable codepage files. */ -#define CODEPAGE_FILE_VERSION_ID 0x1 -/* Version 1 codepage file header size. */ -#define CODEPAGE_HEADER_SIZE 8 -/* Offsets for codepage file header entries. */ -#define CODEPAGE_VERSION_OFFSET 0 -#define CODEPAGE_CLIENT_CODEPAGE_OFFSET 2 -#define CODEPAGE_LENGTH_OFFSET 4 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 a877f1ffb35..00000000000 --- a/source/include/includes.h +++ /dev/null @@ -1,1290 +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 -#ifdef GLIBC2 -#define _LINUX_C_LIB_VERSION_MAJOR 6 -#include <termios.h> -#include <rpcsvc/ypclnt.h> -#include <crypt.h> -#include <netinet/tcp.h> -#include <netinet/ip.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> -#include <sys/stropts.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 -#ifndef REPLACE_GETPASS -#define REPLACE_GETPASS -#endif /* 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 SGI4 -#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 - -#if defined(SGI5) || defined(SGI6) -#include <arpa/inet.h> -#include <netinet/tcp.h> -#include <netinet/in_systm.h> -#include <netinet/ip.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 -#ifndef REPLACE_GETPASS -#define REPLACE_GETPASS -#endif /* 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)) -#ifndef HPUX10 /* This is only needed for HPUX 9.x */ -#define SELECT_CAST (int *) -#endif /* HPUX10 */ -#define SYSV -#define USE_WAITPID -#define WAIT3_CAST2 (int *) -#define USE_GETCWD -#define USE_SETSID -#define USE_SETRES -#define DEFAULT_PRINTING PRINT_HPUX -/* Ken Weiss <krweiss@ucdavis.edu> tells us that SIGCLD_IGNORE is - not good for HPUX */ -/* #define SIGCLD_IGNORE */ -#endif /* HPUX */ - - -#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 /* EVEREST */ -#ifdef NETGROUP -#include <rpcsvc/ypclnt.h> -#endif /* NETGROUP */ -#ifdef SecureWare -#include <sys/security.h> -#include <sys/audit.h> -#include <prot.h> -#define crypt bigcrypt -#endif /* SecureWare */ -#define SIGNAL_CAST (void (*)(int)) -#define USE_WAITPID -#define USE_GETCWD -#define USE_SETSID -#ifdef SCO3_2_2 -#define setuid(u) setreuid(u,-1) -#define seteuid(u) setreuid(-1,u) -#else /* SCO3_2_2 */ -#ifndef EVEREST -#define ftruncate(f,l) syscall(0x0a28,f,l) -#define USE_IFREQ -#define NO_INITGROUPS -#endif /* EVEREST */ -#endif /* SCO3_2_2 */ -#define STATFS4 -#define NO_FSYNC -#define HAVE_PATHCONF -#define NO_GETRLIMIT -#endif /* SCO */ - - - -/* 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 - -/* For UnixWare 2.x's ia_uinfo routines. (tangent@cyberport.com) */ -#ifdef IA_UINFO -#include <iaf.h> -#include <ia.h> -#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 KRB5_AUTH -#include <krb5.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 - -#if !defined(S_ISLNK) && defined(S_IFLNK) -#define S_ISLNK(x) ((S_IFLNK & (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 - -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK 0x7f000001 -#endif /* INADDR_LOOPBACK */ - -/* this is a rough check to see if this machine has a lstat() call. - it is not guaranteed to work */ -#if !defined(S_ISLNK) -#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 cf303659208..00000000000 --- a/source/include/kanji.h +++ /dev/null @@ -1,133 +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> - and add upper/lower case conversion 1997.8.21 -*/ -#ifndef _KANJI_H_ -#define _KANJI_H_ - -/* 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)) - -/* case conversion */ -#define is_sj_upper2(c) \ - ((0x60 <= (unsigned char) (c)) && ((unsigned char) (c) <= 0x79)) -#define is_sj_lower2(c) \ - ((0x81 <= (unsigned char) (c)) && ((unsigned char) (c) <= 0x9A)) -#define sjis_alph 0x82 -#define is_sj_alph(c) (sjis_alph == (unsigned char) (c)) -#define is_sj_upper(c1, c2) (is_sj_alph (c1) && is_sj_upper2 (c2)) -#define is_sj_lower(c1, c2) (is_sj_alph (c1) && is_sj_lower2 (c2)) -#define sj_toupper2(c) \ - (is_sj_lower2 (c) ? ((int) ((unsigned char) (c) - 0x81 + 0x60)) : \ - ((int) (unsigned char) (c))) -#define sj_tolower2(c) \ - (is_sj_upper2 (c) ? ((int) ((unsigned char) (c) - 0x60 + 0x81)) : \ - ((int) (unsigned char) (c))) - -#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)(char *str, BOOL overwrite); -extern char *(*_unix_to_dos)(char *str, BOOL overwrite); - -#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); - -#define unix_to_dos(x,y) unix2dos_format(x,y) -#define dos_to_unix(x,y) dos2unix_format(x,y) - -#endif /* _KANJI_H_ */ diff --git a/source/include/local.h b/source/include/local.h deleted file mode 100644 index 97857727c74..00000000000 --- a/source/include/local.h +++ /dev/null @@ -1,167 +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 - -/* the maximum password length before we declare a likely attack */ -#define MAX_PASS_LEN 200 - -/* 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 (60) -#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 "/" */ - -/* Timout (in seconds) to wait for an oplock break - message to return. */ - -#define OPLOCK_BREAK_TIMEOUT 30 - -#endif diff --git a/source/include/nameserv.h b/source/include/nameserv.h deleted file mode 100644 index 83f3a3c5246..00000000000 --- a/source/include/nameserv.h +++ /dev/null @@ -1,427 +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_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 - -/* Types of machine we can announce as */ -#define ANNOUNCE_AS_NT 1 -#define ANNOUNCE_AS_WIN95 2 -#define ANNOUNCE_AS_WFW 3 - -/* 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/nterr.h b/source/include/nterr.h deleted file mode 100644 index 92f02612dbc..00000000000 --- a/source/include/nterr.h +++ /dev/null @@ -1,505 +0,0 @@ -/* these are the NT error codes less than 1000. They are here for when - we start supporting NT error codes in Samba. They were extracted - using a loop in smbclient then printing a netmon sniff to a file */ - -#define NT_STATUS_UNSUCCESSFUL (1) -#define NT_STATUS_NOT_IMPLEMENTED (2) -#define NT_STATUS_INVALID_INFO_CLASS (3) -#define NT_STATUS_INFO_LENGTH_MISMATCH (4) -#define NT_STATUS_ACCESS_VIOLATION (5) -#define NT_STATUS_IN_PAGE_ERROR (6) -#define NT_STATUS_PAGEFILE_QUOTA (7) -#define NT_STATUS_INVALID_HANDLE (8) -#define NT_STATUS_BAD_INITIAL_STACK (9) -#define NT_STATUS_BAD_INITIAL_PC (10) -#define NT_STATUS_INVALID_CID (11) -#define NT_STATUS_TIMER_NOT_CANCELED (12) -#define NT_STATUS_INVALID_PARAMETER (13) -#define NT_STATUS_NO_SUCH_DEVICE (14) -#define NT_STATUS_NO_SUCH_FILE (15) -#define NT_STATUS_INVALID_DEVICE_REQUEST (16) -#define NT_STATUS_END_OF_FILE (17) -#define NT_STATUS_WRONG_VOLUME (18) -#define NT_STATUS_NO_MEDIA_IN_DEVICE (19) -#define NT_STATUS_UNRECOGNIZED_MEDIA (20) -#define NT_STATUS_NONEXISTENT_SECTOR (21) -#define NT_STATUS_MORE_PROCESSING_REQUIRED (22) -#define NT_STATUS_NO_MEMORY (23) -#define NT_STATUS_CONFLICTING_ADDRESSES (24) -#define NT_STATUS_NOT_MAPPED_VIEW (25) -#define NT_STATUS_UNABLE_TO_FREE_VM (26) -#define NT_STATUS_UNABLE_TO_DELETE_SECTION (27) -#define NT_STATUS_INVALID_SYSTEM_SERVICE (28) -#define NT_STATUS_ILLEGAL_INSTRUCTION (29) -#define NT_STATUS_INVALID_LOCK_SEQUENCE (30) -#define NT_STATUS_INVALID_VIEW_SIZE (31) -#define NT_STATUS_INVALID_FILE_FOR_SECTION (32) -#define NT_STATUS_ALREADY_COMMITTED (33) -#define NT_STATUS_ACCESS_DENIED (34) -#define NT_STATUS_BUFFER_TOO_SMALL (35) -#define NT_STATUS_OBJECT_TYPE_MISMATCH (36) -#define NT_STATUS_NONCONTINUABLE_EXCEPTION (37) -#define NT_STATUS_INVALID_DISPOSITION (38) -#define NT_STATUS_UNWIND (39) -#define NT_STATUS_BAD_STACK (40) -#define NT_STATUS_INVALID_UNWIND_TARGET (41) -#define NT_STATUS_NOT_LOCKED (42) -#define NT_STATUS_PARITY_ERROR (43) -#define NT_STATUS_UNABLE_TO_DECOMMIT_VM (44) -#define NT_STATUS_NOT_COMMITTED (45) -#define NT_STATUS_INVALID_PORT_ATTRIBUTES (46) -#define NT_STATUS_PORT_MESSAGE_TOO_LONG (47) -#define NT_STATUS_INVALID_PARAMETER_MIX (48) -#define NT_STATUS_INVALID_QUOTA_LOWER (49) -#define NT_STATUS_DISK_CORRUPT_ERROR (50) -#define NT_STATUS_OBJECT_NAME_INVALID (51) -#define NT_STATUS_OBJECT_NAME_NOT_FOUND (52) -#define NT_STATUS_OBJECT_NAME_COLLISION (53) -#define NT_STATUS_HANDLE_NOT_WAITABLE (54) -#define NT_STATUS_PORT_DISCONNECTED (55) -#define NT_STATUS_DEVICE_ALREADY_ATTACHED (56) -#define NT_STATUS_OBJECT_PATH_INVALID (57) -#define NT_STATUS_OBJECT_PATH_NOT_FOUND (58) -#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD (59) -#define NT_STATUS_DATA_OVERRUN (60) -#define NT_STATUS_DATA_LATE_ERROR (61) -#define NT_STATUS_DATA_ERROR (62) -#define NT_STATUS_CRC_ERROR (63) -#define NT_STATUS_SECTION_TOO_BIG (64) -#define NT_STATUS_PORT_CONNECTION_REFUSED (65) -#define NT_STATUS_INVALID_PORT_HANDLE (66) -#define NT_STATUS_SHARING_VIOLATION (67) -#define NT_STATUS_QUOTA_EXCEEDED (68) -#define NT_STATUS_INVALID_PAGE_PROTECTION (69) -#define NT_STATUS_MUTANT_NOT_OWNED (70) -#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED (71) -#define NT_STATUS_PORT_ALREADY_SET (72) -#define NT_STATUS_SECTION_NOT_IMAGE (73) -#define NT_STATUS_SUSPEND_COUNT_EXCEEDED (74) -#define NT_STATUS_THREAD_IS_TERMINATING (75) -#define NT_STATUS_BAD_WORKING_SET_LIMIT (76) -#define NT_STATUS_INCOMPATIBLE_FILE_MAP (77) -#define NT_STATUS_SECTION_PROTECTION (78) -#define NT_STATUS_EAS_NOT_SUPPORTED (79) -#define NT_STATUS_EA_TOO_LARGE (80) -#define NT_STATUS_NONEXISTENT_EA_ENTRY (81) -#define NT_STATUS_NO_EAS_ON_FILE (82) -#define NT_STATUS_EA_CORRUPT_ERROR (83) -#define NT_STATUS_FILE_LOCK_CONFLICT (84) -#define NT_STATUS_LOCK_NOT_GRANTED (85) -#define NT_STATUS_DELETE_PENDING (86) -#define NT_STATUS_CTL_FILE_NOT_SUPPORTED (87) -#define NT_STATUS_UNKNOWN_REVISION (88) -#define NT_STATUS_REVISION_MISMATCH (89) -#define NT_STATUS_INVALID_OWNER (90) -#define NT_STATUS_INVALID_PRIMARY_GROUP (91) -#define NT_STATUS_NO_IMPERSONATION_TOKEN (92) -#define NT_STATUS_CANT_DISABLE_MANDATORY (93) -#define NT_STATUS_NO_LOGON_SERVERS (94) -#define NT_STATUS_NO_SUCH_LOGON_SESSION (95) -#define NT_STATUS_NO_SUCH_PRIVILEGE (96) -#define NT_STATUS_PRIVILEGE_NOT_HELD (97) -#define NT_STATUS_INVALID_ACCOUNT_NAME (98) -#define NT_STATUS_USER_EXISTS (99) -#define NT_STATUS_NO_SUCH_USER (100) -#define NT_STATUS_GROUP_EXISTS (101) -#define NT_STATUS_NO_SUCH_GROUP (102) -#define NT_STATUS_MEMBER_IN_GROUP (103) -#define NT_STATUS_MEMBER_NOT_IN_GROUP (104) -#define NT_STATUS_LAST_ADMIN (105) -#define NT_STATUS_WRONG_PASSWORD (106) -#define NT_STATUS_ILL_FORMED_PASSWORD (107) -#define NT_STATUS_PASSWORD_RESTRICTION (108) -#define NT_STATUS_LOGON_FAILURE (109) -#define NT_STATUS_ACCOUNT_RESTRICTION (110) -#define NT_STATUS_INVALID_LOGON_HOURS (111) -#define NT_STATUS_INVALID_WORKSTATION (112) -#define NT_STATUS_PASSWORD_EXPIRED (113) -#define NT_STATUS_ACCOUNT_DISABLED (114) -#define NT_STATUS_NONE_MAPPED (115) -#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED (116) -#define NT_STATUS_LUIDS_EXHAUSTED (117) -#define NT_STATUS_INVALID_SUB_AUTHORITY (118) -#define NT_STATUS_INVALID_ACL (119) -#define NT_STATUS_INVALID_SID (120) -#define NT_STATUS_INVALID_SECURITY_DESCR (121) -#define NT_STATUS_PROCEDURE_NOT_FOUND (122) -#define NT_STATUS_INVALID_IMAGE_FORMAT (123) -#define NT_STATUS_NO_TOKEN (124) -#define NT_STATUS_BAD_INHERITANCE_ACL (125) -#define NT_STATUS_RANGE_NOT_LOCKED (126) -#define NT_STATUS_DISK_FULL (127) -#define NT_STATUS_SERVER_DISABLED (128) -#define NT_STATUS_SERVER_NOT_DISABLED (129) -#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED (130) -#define NT_STATUS_GUIDS_EXHAUSTED (131) -#define NT_STATUS_INVALID_ID_AUTHORITY (132) -#define NT_STATUS_AGENTS_EXHAUSTED (133) -#define NT_STATUS_INVALID_VOLUME_LABEL (134) -#define NT_STATUS_SECTION_NOT_EXTENDED (135) -#define NT_STATUS_NOT_MAPPED_DATA (136) -#define NT_STATUS_RESOURCE_DATA_NOT_FOUND (137) -#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND (138) -#define NT_STATUS_RESOURCE_NAME_NOT_FOUND (139) -#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED (140) -#define NT_STATUS_FLOAT_DENORMAL_OPERAND (141) -#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO (142) -#define NT_STATUS_FLOAT_INEXACT_RESULT (143) -#define NT_STATUS_FLOAT_INVALID_OPERATION (144) -#define NT_STATUS_FLOAT_OVERFLOW (145) -#define NT_STATUS_FLOAT_STACK_CHECK (146) -#define NT_STATUS_FLOAT_UNDERFLOW (147) -#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO (148) -#define NT_STATUS_INTEGER_OVERFLOW (149) -#define NT_STATUS_PRIVILEGED_INSTRUCTION (150) -#define NT_STATUS_TOO_MANY_PAGING_FILES (151) -#define NT_STATUS_FILE_INVALID (152) -#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED (153) -#define NT_STATUS_INSUFFICIENT_RESOURCES (154) -#define NT_STATUS_DFS_EXIT_PATH_FOUND (155) -#define NT_STATUS_DEVICE_DATA_ERROR (156) -#define NT_STATUS_DEVICE_NOT_CONNECTED (157) -#define NT_STATUS_DEVICE_POWER_FAILURE (158) -#define NT_STATUS_FREE_VM_NOT_AT_BASE (159) -#define NT_STATUS_MEMORY_NOT_ALLOCATED (160) -#define NT_STATUS_WORKING_SET_QUOTA (161) -#define NT_STATUS_MEDIA_WRITE_PROTECTED (162) -#define NT_STATUS_DEVICE_NOT_READY (163) -#define NT_STATUS_INVALID_GROUP_ATTRIBUTES (164) -#define NT_STATUS_BAD_IMPERSONATION_LEVEL (165) -#define NT_STATUS_CANT_OPEN_ANONYMOUS (166) -#define NT_STATUS_BAD_VALIDATION_CLASS (167) -#define NT_STATUS_BAD_TOKEN_TYPE (168) -#define NT_STATUS_BAD_MASTER_BOOT_RECORD (169) -#define NT_STATUS_INSTRUCTION_MISALIGNMENT (170) -#define NT_STATUS_INSTANCE_NOT_AVAILABLE (171) -#define NT_STATUS_PIPE_NOT_AVAILABLE (172) -#define NT_STATUS_INVALID_PIPE_STATE (173) -#define NT_STATUS_PIPE_BUSY (174) -#define NT_STATUS_ILLEGAL_FUNCTION (175) -#define NT_STATUS_PIPE_DISCONNECTED (176) -#define NT_STATUS_PIPE_CLOSING (177) -#define NT_STATUS_PIPE_CONNECTED (178) -#define NT_STATUS_PIPE_LISTENING (179) -#define NT_STATUS_INVALID_READ_MODE (180) -#define NT_STATUS_IO_TIMEOUT (181) -#define NT_STATUS_FILE_FORCED_CLOSED (182) -#define NT_STATUS_PROFILING_NOT_STARTED (183) -#define NT_STATUS_PROFILING_NOT_STOPPED (184) -#define NT_STATUS_COULD_NOT_INTERPRET (185) -#define NT_STATUS_FILE_IS_A_DIRECTORY (186) -#define NT_STATUS_NOT_SUPPORTED (187) -#define NT_STATUS_REMOTE_NOT_LISTENING (188) -#define NT_STATUS_DUPLICATE_NAME (189) -#define NT_STATUS_BAD_NETWORK_PATH (190) -#define NT_STATUS_NETWORK_BUSY (191) -#define NT_STATUS_DEVICE_DOES_NOT_EXIST (192) -#define NT_STATUS_TOO_MANY_COMMANDS (193) -#define NT_STATUS_ADAPTER_HARDWARE_ERROR (194) -#define NT_STATUS_INVALID_NETWORK_RESPONSE (195) -#define NT_STATUS_UNEXPECTED_NETWORK_ERROR (196) -#define NT_STATUS_BAD_REMOTE_ADAPTER (197) -#define NT_STATUS_PRINT_QUEUE_FULL (198) -#define NT_STATUS_NO_SPOOL_SPACE (199) -#define NT_STATUS_PRINT_CANCELLED (200) -#define NT_STATUS_NETWORK_NAME_DELETED (201) -#define NT_STATUS_NETWORK_ACCESS_DENIED (202) -#define NT_STATUS_BAD_DEVICE_TYPE (203) -#define NT_STATUS_BAD_NETWORK_NAME (204) -#define NT_STATUS_TOO_MANY_NAMES (205) -#define NT_STATUS_TOO_MANY_SESSIONS (206) -#define NT_STATUS_SHARING_PAUSED (207) -#define NT_STATUS_REQUEST_NOT_ACCEPTED (208) -#define NT_STATUS_REDIRECTOR_PAUSED (209) -#define NT_STATUS_NET_WRITE_FAULT (210) -#define NT_STATUS_PROFILING_AT_LIMIT (211) -#define NT_STATUS_NOT_SAME_DEVICE (212) -#define NT_STATUS_FILE_RENAMED (213) -#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED (214) -#define NT_STATUS_NO_SECURITY_ON_OBJECT (215) -#define NT_STATUS_CANT_WAIT (216) -#define NT_STATUS_PIPE_EMPTY (217) -#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO (218) -#define NT_STATUS_CANT_TERMINATE_SELF (219) -#define NT_STATUS_INVALID_SERVER_STATE (220) -#define NT_STATUS_INVALID_DOMAIN_STATE (221) -#define NT_STATUS_INVALID_DOMAIN_ROLE (222) -#define NT_STATUS_NO_SUCH_DOMAIN (223) -#define NT_STATUS_DOMAIN_EXISTS (224) -#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED (225) -#define NT_STATUS_OPLOCK_NOT_GRANTED (226) -#define NT_STATUS_INVALID_OPLOCK_PROTOCOL (227) -#define NT_STATUS_INTERNAL_DB_CORRUPTION (228) -#define NT_STATUS_INTERNAL_ERROR (229) -#define NT_STATUS_GENERIC_NOT_MAPPED (230) -#define NT_STATUS_BAD_DESCRIPTOR_FORMAT (231) -#define NT_STATUS_INVALID_USER_BUFFER (232) -#define NT_STATUS_UNEXPECTED_IO_ERROR (233) -#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR (234) -#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR (235) -#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR (236) -#define NT_STATUS_NOT_LOGON_PROCESS (237) -#define NT_STATUS_LOGON_SESSION_EXISTS (238) -#define NT_STATUS_INVALID_PARAMETER_1 (239) -#define NT_STATUS_INVALID_PARAMETER_2 (240) -#define NT_STATUS_INVALID_PARAMETER_3 (241) -#define NT_STATUS_INVALID_PARAMETER_4 (242) -#define NT_STATUS_INVALID_PARAMETER_5 (243) -#define NT_STATUS_INVALID_PARAMETER_6 (244) -#define NT_STATUS_INVALID_PARAMETER_7 (245) -#define NT_STATUS_INVALID_PARAMETER_8 (246) -#define NT_STATUS_INVALID_PARAMETER_9 (247) -#define NT_STATUS_INVALID_PARAMETER_10 (248) -#define NT_STATUS_INVALID_PARAMETER_11 (249) -#define NT_STATUS_INVALID_PARAMETER_12 (250) -#define NT_STATUS_REDIRECTOR_NOT_STARTED (251) -#define NT_STATUS_REDIRECTOR_STARTED (252) -#define NT_STATUS_STACK_OVERFLOW (253) -#define NT_STATUS_NO_SUCH_PACKAGE (254) -#define NT_STATUS_BAD_FUNCTION_TABLE (255) -#define NT_STATUS_DIRECTORY_NOT_EMPTY (257) -#define NT_STATUS_FILE_CORRUPT_ERROR (258) -#define NT_STATUS_NOT_A_DIRECTORY (259) -#define NT_STATUS_BAD_LOGON_SESSION_STATE (260) -#define NT_STATUS_LOGON_SESSION_COLLISION (261) -#define NT_STATUS_NAME_TOO_LONG (262) -#define NT_STATUS_FILES_OPEN (263) -#define NT_STATUS_CONNECTION_IN_USE (264) -#define NT_STATUS_MESSAGE_NOT_FOUND (265) -#define NT_STATUS_PROCESS_IS_TERMINATING (266) -#define NT_STATUS_INVALID_LOGON_TYPE (267) -#define NT_STATUS_NO_GUID_TRANSLATION (268) -#define NT_STATUS_CANNOT_IMPERSONATE (269) -#define NT_STATUS_IMAGE_ALREADY_LOADED (270) -#define NT_STATUS_ABIOS_NOT_PRESENT (271) -#define NT_STATUS_ABIOS_LID_NOT_EXIST (272) -#define NT_STATUS_ABIOS_LID_ALREADY_OWNED (273) -#define NT_STATUS_ABIOS_NOT_LID_OWNER (274) -#define NT_STATUS_ABIOS_INVALID_COMMAND (275) -#define NT_STATUS_ABIOS_INVALID_LID (276) -#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (277) -#define NT_STATUS_ABIOS_INVALID_SELECTOR (278) -#define NT_STATUS_NO_LDT (279) -#define NT_STATUS_INVALID_LDT_SIZE (280) -#define NT_STATUS_INVALID_LDT_OFFSET (281) -#define NT_STATUS_INVALID_LDT_DESCRIPTOR (282) -#define NT_STATUS_INVALID_IMAGE_NE_FORMAT (283) -#define NT_STATUS_RXACT_INVALID_STATE (284) -#define NT_STATUS_RXACT_COMMIT_FAILURE (285) -#define NT_STATUS_MAPPED_FILE_SIZE_ZERO (286) -#define NT_STATUS_TOO_MANY_OPENED_FILES (287) -#define NT_STATUS_CANCELLED (288) -#define NT_STATUS_CANNOT_DELETE (289) -#define NT_STATUS_INVALID_COMPUTER_NAME (290) -#define NT_STATUS_FILE_DELETED (291) -#define NT_STATUS_SPECIAL_ACCOUNT (292) -#define NT_STATUS_SPECIAL_GROUP (293) -#define NT_STATUS_SPECIAL_USER (294) -#define NT_STATUS_MEMBERS_PRIMARY_GROUP (295) -#define NT_STATUS_FILE_CLOSED (296) -#define NT_STATUS_TOO_MANY_THREADS (297) -#define NT_STATUS_THREAD_NOT_IN_PROCESS (298) -#define NT_STATUS_TOKEN_ALREADY_IN_USE (299) -#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED (300) -#define NT_STATUS_COMMITMENT_LIMIT (301) -#define NT_STATUS_INVALID_IMAGE_LE_FORMAT (302) -#define NT_STATUS_INVALID_IMAGE_NOT_MZ (303) -#define NT_STATUS_INVALID_IMAGE_PROTECT (304) -#define NT_STATUS_INVALID_IMAGE_WIN_16 (305) -#define NT_STATUS_LOGON_SERVER_CONFLICT (306) -#define NT_STATUS_TIME_DIFFERENCE_AT_DC (307) -#define NT_STATUS_SYNCHRONIZATION_REQUIRED (308) -#define NT_STATUS_DLL_NOT_FOUND (309) -#define NT_STATUS_OPEN_FAILED (310) -#define NT_STATUS_IO_PRIVILEGE_FAILED (311) -#define NT_STATUS_ORDINAL_NOT_FOUND (312) -#define NT_STATUS_ENTRYPOINT_NOT_FOUND (313) -#define NT_STATUS_CONTROL_C_EXIT (314) -#define NT_STATUS_LOCAL_DISCONNECT (315) -#define NT_STATUS_REMOTE_DISCONNECT (316) -#define NT_STATUS_REMOTE_RESOURCES (317) -#define NT_STATUS_LINK_FAILED (318) -#define NT_STATUS_LINK_TIMEOUT (319) -#define NT_STATUS_INVALID_CONNECTION (320) -#define NT_STATUS_INVALID_ADDRESS (321) -#define NT_STATUS_DLL_INIT_FAILED (322) -#define NT_STATUS_MISSING_SYSTEMFILE (323) -#define NT_STATUS_UNHANDLED_EXCEPTION (324) -#define NT_STATUS_APP_INIT_FAILURE (325) -#define NT_STATUS_PAGEFILE_CREATE_FAILED (326) -#define NT_STATUS_NO_PAGEFILE (327) -#define NT_STATUS_INVALID_LEVEL (328) -#define NT_STATUS_WRONG_PASSWORD_CORE (329) -#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT (330) -#define NT_STATUS_PIPE_BROKEN (331) -#define NT_STATUS_REGISTRY_CORRUPT (332) -#define NT_STATUS_REGISTRY_IO_FAILED (333) -#define NT_STATUS_NO_EVENT_PAIR (334) -#define NT_STATUS_UNRECOGNIZED_VOLUME (335) -#define NT_STATUS_SERIAL_NO_DEVICE_INITED (336) -#define NT_STATUS_NO_SUCH_ALIAS (337) -#define NT_STATUS_MEMBER_NOT_IN_ALIAS (338) -#define NT_STATUS_MEMBER_IN_ALIAS (339) -#define NT_STATUS_ALIAS_EXISTS (340) -#define NT_STATUS_LOGON_NOT_GRANTED (341) -#define NT_STATUS_TOO_MANY_SECRETS (342) -#define NT_STATUS_SECRET_TOO_LONG (343) -#define NT_STATUS_INTERNAL_DB_ERROR (344) -#define NT_STATUS_FULLSCREEN_MODE (345) -#define NT_STATUS_TOO_MANY_CONTEXT_IDS (346) -#define NT_STATUS_LOGON_TYPE_NOT_GRANTED (347) -#define NT_STATUS_NOT_REGISTRY_FILE (348) -#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED (349) -#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR (350) -#define NT_STATUS_FT_MISSING_MEMBER (351) -#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY (352) -#define NT_STATUS_ILLEGAL_CHARACTER (353) -#define NT_STATUS_UNMAPPABLE_CHARACTER (354) -#define NT_STATUS_UNDEFINED_CHARACTER (355) -#define NT_STATUS_FLOPPY_VOLUME (356) -#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND (357) -#define NT_STATUS_FLOPPY_WRONG_CYLINDER (358) -#define NT_STATUS_FLOPPY_UNKNOWN_ERROR (359) -#define NT_STATUS_FLOPPY_BAD_REGISTERS (360) -#define NT_STATUS_DISK_RECALIBRATE_FAILED (361) -#define NT_STATUS_DISK_OPERATION_FAILED (362) -#define NT_STATUS_DISK_RESET_FAILED (363) -#define NT_STATUS_SHARED_IRQ_BUSY (364) -#define NT_STATUS_FT_ORPHANING (365) -#define NT_STATUS_PARTITION_FAILURE (370) -#define NT_STATUS_INVALID_BLOCK_LENGTH (371) -#define NT_STATUS_DEVICE_NOT_PARTITIONED (372) -#define NT_STATUS_UNABLE_TO_LOCK_MEDIA (373) -#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA (374) -#define NT_STATUS_EOM_OVERFLOW (375) -#define NT_STATUS_NO_MEDIA (376) -#define NT_STATUS_NO_SUCH_MEMBER (378) -#define NT_STATUS_INVALID_MEMBER (379) -#define NT_STATUS_KEY_DELETED (380) -#define NT_STATUS_NO_LOG_SPACE (381) -#define NT_STATUS_TOO_MANY_SIDS (382) -#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED (383) -#define NT_STATUS_KEY_HAS_CHILDREN (384) -#define NT_STATUS_CHILD_MUST_BE_VOLATILE (385) -#define NT_STATUS_DEVICE_CONFIGURATION_ERROR (386) -#define NT_STATUS_DRIVER_INTERNAL_ERROR (387) -#define NT_STATUS_INVALID_DEVICE_STATE (388) -#define NT_STATUS_IO_DEVICE_ERROR (389) -#define NT_STATUS_DEVICE_PROTOCOL_ERROR (390) -#define NT_STATUS_BACKUP_CONTROLLER (391) -#define NT_STATUS_LOG_FILE_FULL (392) -#define NT_STATUS_TOO_LATE (393) -#define NT_STATUS_NO_TRUST_LSA_SECRET (394) -#define NT_STATUS_NO_TRUST_SAM_ACCOUNT (395) -#define NT_STATUS_TRUSTED_DOMAIN_FAILURE (396) -#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE (397) -#define NT_STATUS_EVENTLOG_FILE_CORRUPT (398) -#define NT_STATUS_EVENTLOG_CANT_START (399) -#define NT_STATUS_TRUST_FAILURE (400) -#define NT_STATUS_MUTANT_LIMIT_EXCEEDED (401) -#define NT_STATUS_NETLOGON_NOT_STARTED (402) -#define NT_STATUS_ACCOUNT_EXPIRED (403) -#define NT_STATUS_POSSIBLE_DEADLOCK (404) -#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT (405) -#define NT_STATUS_REMOTE_SESSION_LIMIT (406) -#define NT_STATUS_EVENTLOG_FILE_CHANGED (407) -#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (408) -#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (409) -#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (410) -#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT (411) -#define NT_STATUS_FS_DRIVER_REQUIRED (412) -#define NT_STATUS_NO_USER_SESSION_KEY (514) -#define NT_STATUS_USER_SESSION_DELETED (515) -#define NT_STATUS_RESOURCE_LANG_NOT_FOUND (516) -#define NT_STATUS_INSUFF_SERVER_RESOURCES (517) -#define NT_STATUS_INVALID_BUFFER_SIZE (518) -#define NT_STATUS_INVALID_ADDRESS_COMPONENT (519) -#define NT_STATUS_INVALID_ADDRESS_WILDCARD (520) -#define NT_STATUS_TOO_MANY_ADDRESSES (521) -#define NT_STATUS_ADDRESS_ALREADY_EXISTS (522) -#define NT_STATUS_ADDRESS_CLOSED (523) -#define NT_STATUS_CONNECTION_DISCONNECTED (524) -#define NT_STATUS_CONNECTION_RESET (525) -#define NT_STATUS_TOO_MANY_NODES (526) -#define NT_STATUS_TRANSACTION_ABORTED (527) -#define NT_STATUS_TRANSACTION_TIMED_OUT (528) -#define NT_STATUS_TRANSACTION_NO_RELEASE (529) -#define NT_STATUS_TRANSACTION_NO_MATCH (530) -#define NT_STATUS_TRANSACTION_RESPONDED (531) -#define NT_STATUS_TRANSACTION_INVALID_ID (532) -#define NT_STATUS_TRANSACTION_INVALID_TYPE (533) -#define NT_STATUS_NOT_SERVER_SESSION (534) -#define NT_STATUS_NOT_CLIENT_SESSION (535) -#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE (536) -#define NT_STATUS_DEBUG_ATTACH_FAILED (537) -#define NT_STATUS_SYSTEM_PROCESS_TERMINATED (538) -#define NT_STATUS_DATA_NOT_ACCEPTED (539) -#define NT_STATUS_NO_BROWSER_SERVERS_FOUND (540) -#define NT_STATUS_VDM_HARD_ERROR (541) -#define NT_STATUS_DRIVER_CANCEL_TIMEOUT (542) -#define NT_STATUS_REPLY_MESSAGE_MISMATCH (543) -#define NT_STATUS_MAPPED_ALIGNMENT (544) -#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH (545) -#define NT_STATUS_LOST_WRITEBEHIND_DATA (546) -#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID (547) -#define NT_STATUS_PASSWORD_MUST_CHANGE (548) -#define NT_STATUS_NOT_FOUND (549) -#define NT_STATUS_NOT_TINY_STREAM (550) -#define NT_STATUS_RECOVERY_FAILURE (551) -#define NT_STATUS_STACK_OVERFLOW_READ (552) -#define NT_STATUS_FAIL_CHECK (553) -#define NT_STATUS_DUPLICATE_OBJECTID (554) -#define NT_STATUS_OBJECTID_EXISTS (555) -#define NT_STATUS_CONVERT_TO_LARGE (556) -#define NT_STATUS_RETRY (557) -#define NT_STATUS_FOUND_OUT_OF_SCOPE (558) -#define NT_STATUS_ALLOCATE_BUCKET (559) -#define NT_STATUS_PROPSET_NOT_FOUND (560) -#define NT_STATUS_MARSHALL_OVERFLOW (561) -#define NT_STATUS_INVALID_VARIANT (562) -#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND (563) -#define NT_STATUS_ACCOUNT_LOCKED_OUT (564) -#define NT_STATUS_HANDLE_NOT_CLOSABLE (565) -#define NT_STATUS_CONNECTION_REFUSED (566) -#define NT_STATUS_GRACEFUL_DISCONNECT (567) -#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED (568) -#define NT_STATUS_ADDRESS_NOT_ASSOCIATED (569) -#define NT_STATUS_CONNECTION_INVALID (570) -#define NT_STATUS_CONNECTION_ACTIVE (571) -#define NT_STATUS_NETWORK_UNREACHABLE (572) -#define NT_STATUS_HOST_UNREACHABLE (573) -#define NT_STATUS_PROTOCOL_UNREACHABLE (574) -#define NT_STATUS_PORT_UNREACHABLE (575) -#define NT_STATUS_REQUEST_ABORTED (576) -#define NT_STATUS_CONNECTION_ABORTED (577) -#define NT_STATUS_BAD_COMPRESSION_BUFFER (578) -#define NT_STATUS_USER_MAPPED_FILE (579) -#define NT_STATUS_AUDIT_FAILED (580) -#define NT_STATUS_TIMER_RESOLUTION_NOT_SET (581) -#define NT_STATUS_CONNECTION_COUNT_LIMIT (582) -#define NT_STATUS_LOGIN_TIME_RESTRICTION (583) -#define NT_STATUS_LOGIN_WKSTA_RESTRICTION (584) -#define NT_STATUS_IMAGE_MP_UP_MISMATCH (585) -#define NT_STATUS_INSUFFICIENT_LOGON_INFO (592) -#define NT_STATUS_BAD_DLL_ENTRYPOINT (593) -#define NT_STATUS_BAD_SERVICE_ENTRYPOINT (594) -#define NT_STATUS_LPC_REPLY_LOST (595) -#define NT_STATUS_IP_ADDRESS_CONFLICT1 (596) -#define NT_STATUS_IP_ADDRESS_CONFLICT2 (597) -#define NT_STATUS_REGISTRY_QUOTA_LIMIT (598) -#define NT_STATUS_PATH_NOT_COVERED (599) -#define NT_STATUS_NO_CALLBACK_ACTIVE (600) -#define NT_STATUS_LICENSE_QUOTA_EXCEEDED (601) -#define NT_STATUS_PWD_TOO_SHORT (602) -#define NT_STATUS_PWD_TOO_RECENT (603) -#define NT_STATUS_PWD_HISTORY_CONFLICT (604) -#define NT_STATUS_PLUGPLAY_NO_DEVICE (606) -#define NT_STATUS_UNSUPPORTED_COMPRESSION (607) -#define NT_STATUS_INVALID_HW_PROFILE (608) -#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH (609) -#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND (610) -#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (611) -#define NT_STATUS_RESOURCE_NOT_OWNED (612) -#define NT_STATUS_TOO_MANY_LINKS (613) -#define NT_STATUS_QUOTA_LIST_INCONSISTENT (614) -#define NT_STATUS_FILE_IS_OFFLINE (615) diff --git a/source/include/proto.h b/source/include/proto.h deleted file mode 100644 index 009d83db5c2..00000000000 --- a/source/include/proto.h +++ /dev/null @@ -1,1057 +0,0 @@ -/* This file is automatically generated with "make proto". DO NOT EDIT */ - - -/*The following definitions come from access.c */ - -BOOL check_access(int snum); -BOOL allow_access(char *deny_list,char *allow_list,char *cname,char *caddr); - -/*The following definitions come from charcnv.c */ - -char *unix2dos_format(char *str,BOOL overwrite); -char *dos2unix_format(char *str, BOOL overwrite); -int interpret_character_set(char *str, int def); - -/*The following definitions come from charset.c */ - -void charset_initialise(); -void codepage_initialise(int client_codepage); -void add_char_string(char *s); - -/*The following definitions come from chgpasswd.c */ - -BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence); -BOOL chgpasswd(char *name,char *oldpass,char *newpass); -BOOL chgpasswd(char *name,char *oldpass,char *newpass); - -/*The following definitions come from client.c */ - -void setup_pkt(char *outbuf); -void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); -void cmd_help(void); -BOOL reopen_connection(char *inbuf,char *outbuf); -char *smb_errstr(char *inbuf); - -/*The following definitions come from clientutil.c */ - -void cli_setup_pkt(char *outbuf); -BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, - int *param_len, char **data,char **param); -BOOL cli_send_session_request(char *inbuf, char *outbuf); -BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup); -void cli_send_logout(void); -BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, - int *rdrcnt, char *param,char *data, char **rparam,char **rdata); -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); -BOOL cli_open_sockets(int port); -BOOL cli_reopen_connection(char *inbuf,char *outbuf); -char *smb_errstr(char *inbuf); - -/*The following definitions come from clitar.c */ - -int padit(char *buf, int bufsize, int padsize); -void cmd_block(void); -void cmd_tarmode(void); -void cmd_setmode(void); -void cmd_tar(char *inbuf, char *outbuf); -int process_tar(char *inbuf, char *outbuf); -int clipfind(char **aret, int ret, char *tok); -int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind); - -/*The following definitions come from dir.c */ - -void init_dptrs(void); -char *dptr_path(int key); -char *dptr_wcard(int key); -BOOL dptr_set_wcard(int key, char *wcard); -BOOL dptr_set_attr(int key, uint16 attr); -uint16 dptr_attr(int key); -void dptr_close(int key); -void dptr_closecnum(int cnum); -void dptr_idlecnum(int cnum); -void dptr_closepath(char *path,int pid); -int dptr_create(int cnum,char *path, BOOL expect_close,int pid); -BOOL dptr_fill(char *buf1,unsigned int key); -BOOL dptr_zero(char *buf); -void *dptr_fetch(char *buf,int *num); -void *dptr_fetch_lanman2(char *params,int dptr_num); -BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype); -BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend); -void *OpenDir(int cnum, char *name, BOOL use_veto); -void CloseDir(void *p); -char *ReadDirName(void *p); -BOOL SeekDir(void *p,int pos); -int TellDir(void *p); -void DirCacheAdd(char *path,char *name,char *dname,int snum); -char *DirCacheCheck(char *path,char *name,int snum); -void DirCacheFlush(int snum); - -/*The following definitions come from fault.c */ - -void fault_setup(void (*fn)()); - -/*The following definitions come from getsmbpass.c */ - -char *getsmbpass(char *prompt) ; - -/*The following definitions come from interface.c */ - -void load_interfaces(void); -void iface_set_default(char *ip,char *bcast,char *nmask); -BOOL ismyip(struct in_addr ip); -BOOL ismybcast(struct in_addr bcast); -int iface_count(void); -struct in_addr *iface_n_ip(int n); -struct in_addr *iface_bcast(struct in_addr ip); -struct in_addr *iface_nmask(struct in_addr ip); -struct in_addr *iface_ip(struct in_addr ip); - -/*The following definitions come from ipc.c */ - -int reply_trans(char *inbuf,char *outbuf); - -/*The following definitions come from kanji.c */ - -char *sj_strtok(char *s1, char *s2); -char *sj_strstr(char *s1, char *s2); -char *sj_strchr (char *s, int c); -char *sj_strrchr(char *s, int c); -int interpret_coding_system(char *str, int def); - -/*The following definitions come from loadparm.c */ - -char *lp_string(char *s); -char *lp_logfile(void); -char *lp_smbrun(void); -char *lp_configfile(void); -char *lp_smb_passwd_file(void); -char *lp_serverstring(void); -char *lp_printcapname(void); -char *lp_lockdir(void); -char *lp_rootdir(void); -char *lp_defaultservice(void); -char *lp_msg_command(void); -char *lp_dfree_command(void); -char *lp_hosts_equiv(void); -char *lp_auto_services(void); -char *lp_passwd_program(void); -char *lp_passwd_chat(void); -char *lp_passwordserver(void); -char *lp_workgroup(void); -char *lp_domain_controller(void); -char *lp_username_map(void); -char *lp_character_set(void); -char *lp_logon_script(void); -char *lp_logon_path(void); -char *lp_remote_announce(void); -char *lp_wins_server(void); -char *lp_interfaces(void); -char *lp_socket_address(void); -char *lp_nis_home_map_name(void); -char *lp_announce_version(void); -char *lp_netbios_aliases(void); -char *lp_domainsid(void); -BOOL lp_dns_proxy(void); -BOOL lp_wins_support(void); -BOOL lp_wins_proxy(void); -BOOL lp_local_master(void); -BOOL lp_domain_master(void); -BOOL lp_domain_logons(void); -BOOL lp_preferred_master(void); -BOOL lp_load_printers(void); -BOOL lp_use_rhosts(void); -BOOL lp_getwdcache(void); -BOOL lp_readprediction(void); -BOOL lp_readbmpx(void); -BOOL lp_readraw(void); -BOOL lp_writeraw(void); -BOOL lp_null_passwords(void); -BOOL lp_strip_dot(void); -BOOL lp_encrypted_passwords(void); -BOOL lp_syslog_only(void); -BOOL lp_browse_list(void); -BOOL lp_unix_realname(void); -BOOL lp_nis_home_map(void); -BOOL lp_time_server(void); -int lp_os_level(void); -int lp_max_ttl(void); -int lp_max_log_size(void); -int lp_mangledstack(void); -int lp_maxxmit(void); -int lp_maxmux(void); -int lp_maxpacket(void); -int lp_keepalive(void); -int lp_passwordlevel(void); -int lp_usernamelevel(void); -int lp_readsize(void); -int lp_shmem_size(void); -int lp_shmem_hash_size(void); -int lp_deadtime(void); -int lp_maxprotocol(void); -int lp_security(void); -int lp_printing(void); -int lp_maxdisksize(void); -int lp_lpqcachetime(void); -int lp_syslog(void); -int lp_client_code_page(void); -int lp_announce_as(void); -char *lp_preexec(int ); -char *lp_postexec(int ); -char *lp_rootpreexec(int ); -char *lp_rootpostexec(int ); -char *lp_servicename(int ); -char *lp_pathname(int ); -char *lp_dontdescend(int ); -char *lp_username(int ); -char *lp_guestaccount(int ); -char *lp_invalid_users(int ); -char *lp_valid_users(int ); -char *lp_admin_users(int ); -char *lp_printcommand(int ); -char *lp_lpqcommand(int ); -char *lp_lprmcommand(int ); -char *lp_lppausecommand(int ); -char *lp_lpresumecommand(int ); -char *lp_printername(int ); -char *lp_printerdriver(int ); -char *lp_hostsallow(int ); -char *lp_hostsdeny(int ); -char *lp_magicscript(int ); -char *lp_magicoutput(int ); -char *lp_comment(int ); -char *lp_force_user(int ); -char *lp_force_group(int ); -char *lp_readlist(int ); -char *lp_writelist(int ); -char *lp_volume(int ); -char *lp_mangled_map(int ); -char *lp_veto_files(int ); -char *lp_hide_files(int ); -BOOL lp_alternate_permissions(int ); -BOOL lp_revalidate(int ); -BOOL lp_casesensitive(int ); -BOOL lp_preservecase(int ); -BOOL lp_shortpreservecase(int ); -BOOL lp_casemangle(int ); -BOOL lp_status(int ); -BOOL lp_hide_dot_files(int ); -BOOL lp_browseable(int ); -BOOL lp_readonly(int ); -BOOL lp_no_set_dir(int ); -BOOL lp_guest_ok(int ); -BOOL lp_guest_only(int ); -BOOL lp_print_ok(int ); -BOOL lp_postscript(int ); -BOOL lp_map_hidden(int ); -BOOL lp_map_archive(int ); -BOOL lp_locking(int ); -BOOL lp_strict_locking(int ); -BOOL lp_share_modes(int ); -BOOL lp_oplocks(int ); -BOOL lp_onlyuser(int ); -BOOL lp_manglednames(int ); -BOOL lp_widelinks(int ); -BOOL lp_symlinks(int ); -BOOL lp_syncalways(int ); -BOOL lp_map_system(int ); -BOOL lp_delete_readonly(int ); -BOOL lp_fake_oplocks(int ); -BOOL lp_recursive_veto_delete(int ); -int lp_create_mode(int ); -int lp_force_create_mode(int ); -int lp_dir_mode(int ); -int lp_force_dir_mode(int ); -int lp_max_connections(int ); -int lp_defaultcase(int ); -int lp_minprintspace(int ); -char lp_magicchar(int ); -BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir); -int lp_add_service(char *pszService, int iDefaultService); -BOOL lp_add_printer(char *pszPrintername, int iDefaultService); -BOOL lp_file_list_changed(void); -BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue); -int lp_next_parameter(int snum, int *i, char *label, - char *value, int allparameters); -BOOL lp_snum_ok(int iService); -BOOL lp_loaded(void); -void lp_killunused(BOOL (*snumused)(int )); -BOOL lp_load(char *pszFname,BOOL global_only); -int lp_numservices(void); -void lp_dump(FILE *f); -int lp_servicenumber(char *pszServiceName); -char *volume_label(int snum); -void lp_rename_service(int snum, char *new_name); -void lp_remove_service(int snum); -void lp_copy_service(int snum, char *new_name); -int lp_default_server_announce(void); -int lp_major_announce_version(void); -int lp_minor_announce_version(void); - -/*The following definitions come from locking.c */ - -BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset); -BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode); -BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode); -BOOL start_share_mode_mgmt(void); -BOOL stop_share_mode_mgmt(void); -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok); -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token); -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares); -void del_share_mode(share_lock_token token, int fnum); -BOOL set_share_mode(share_lock_token token, int fnum, uint16 port, uint16 op_type); -BOOL remove_share_oplock(int fnum, share_lock_token token); -BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok); -BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token); -int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode, - min_share_mode_entry **old_shares); -void del_share_mode(share_lock_token token, int fnum); -BOOL set_share_mode(share_lock_token token,int fnum, uint16 port, uint16 op_type); -BOOL remove_share_oplock(int fnum, share_lock_token token); - -/*The following definitions come from lsaparse.c */ - -char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align); -char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align); -char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align); -char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align); -char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align); -char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align); -char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align); -char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align); -char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align); -char* lsa_io_q_auth2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align); -char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align); -char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align); -char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align); -char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align); -char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align); -char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align); -char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align); -char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align); - -/*The following definitions come from mangle.c */ - -int str_checksum(char *s); -BOOL is_8_3(char *fname, BOOL check_case); -void create_mangled_stack(int size); -BOOL check_mangled_stack(char *s); -BOOL is_mangled(char *s); -void mangle_name_83(char *s); -BOOL name_map_mangle(char *OutName,BOOL need83,int snum); - -/*The following definitions come from md4.c */ - -void mdfour(unsigned char *out, unsigned char *in, int n); - -/*The following definitions come from message.c */ - -int reply_sends(char *inbuf,char *outbuf); -int reply_sendstrt(char *inbuf,char *outbuf); -int reply_sendtxt(char *inbuf,char *outbuf); -int reply_sendend(char *inbuf,char *outbuf); - -/*The following definitions come from nameannounce.c */ - -void announce_request(struct work_record *work, struct in_addr ip); -void do_announce_request(char *info, char *to_name, int announce_type, - int from, - int to, struct in_addr dest_ip); -void sync_server(enum state_type state, char *serv_name, char *work_name, - int name_type, - struct subnet_record *d, - struct in_addr ip); -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); -void announce_my_servers_removed(void); -void announce_server(struct subnet_record *d, struct work_record *work, - char *name, char *comment, time_t ttl, int server_type); -void announce_host(time_t t); -void reset_announce_timer(); -void announce_master(time_t t); -void announce_remote(time_t t); - -/*The following definitions come from namebrowse.c */ - -void expire_browse_cache(time_t t); -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); -void do_browser_lists(time_t t); - -/*The following definitions come from namedbname.c */ - -void set_samba_nb_type(void); -BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2); -BOOL ms_browser_name(char *name, int type); -void remove_name(struct subnet_record *d, struct name_record *n); -struct name_record *find_name(struct name_record *n, - struct nmb_name *name, int search); -struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip); -void dump_names(void); -void load_netbios_names(void); -void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip); -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); -void expire_names(time_t t); -struct name_record *dns_name_search(struct nmb_name *question, int Time); - -/*The following definitions come from namedbresp.c */ - -void add_response_record(struct subnet_record *d, - struct response_record *n); -void remove_response_record(struct subnet_record *d, - struct response_record *n); -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 *find_response_record(struct subnet_record **d, - uint16 id); - -/*The following definitions come from namedbserver.c */ - -void remove_old_servers(struct work_record *work, time_t t, - BOOL remove_all); -struct server_record *find_server(struct work_record *work, char *name); -struct server_record *add_server_entry(struct subnet_record *d, - struct work_record *work, - char *name,int servertype, - int ttl,char *comment, - BOOL replace); -void expire_servers(time_t t); - -/*The following definitions come from namedbsubnet.c */ - -struct subnet_record *find_subnet(struct in_addr bcast_ip); -struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast); -struct subnet_record *find_subnet_all(struct in_addr bcast_ip); -void add_workgroup_to_subnet( struct subnet_record *d, char *group); -void add_my_subnets(char *group); -void write_browse_list(time_t t); - -/*The following definitions come from namedbwork.c */ - -struct work_record *remove_workgroup(struct subnet_record *d, - struct work_record *work, - BOOL remove_all_servers); -struct work_record *find_workgroupstruct(struct subnet_record *d, - fstring name, BOOL add); -void dump_workgroups(void); - -/*The following definitions come from nameelect.c */ - -void check_master_browser(time_t t); -void browser_gone(char *work_name, struct in_addr ip); -void send_election(struct subnet_record *d, char *group,uint32 criterion, - int timeup,char *name); -void name_unregister_work(struct subnet_record *d, char *name, int name_type); -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); -void become_local_master(struct subnet_record *d, struct work_record *work); -void become_domain_master(struct subnet_record *d, struct work_record *work); -void become_logon_server(struct subnet_record *d, struct work_record *work); -void unbecome_local_master(struct subnet_record *d, struct work_record *work, - int remove_type); -void unbecome_domain_master(struct subnet_record *d, struct work_record *work, - int remove_type); -void unbecome_logon_server(struct subnet_record *d, struct work_record *work, - int remove_type); -void run_elections(time_t t); -void process_election(struct packet_struct *p,char *buf); -BOOL check_elections(void); - -/*The following definitions come from namelogon.c */ - -void process_logon_packet(struct packet_struct *p,char *buf,int len); - -/*The following definitions come from namepacket.c */ - -void debug_browse_data(char *outbuf, int len); -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); -void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, - BOOL recursion_available, - BOOL recursion_desired, - struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, - char *data,int len); -void queue_packet(struct packet_struct *packet); -void run_packet_queue(); -void listen_for_packets(BOOL run_election); -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); - -/*The following definitions come from namequery.c */ - -BOOL name_status(int fd,char *name,int name_type,BOOL recurse, - struct in_addr to_ip,char *master,char *rname, - void (*fn)()); -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)()); - -/*The following definitions come from nameresp.c */ - -void expire_netbios_response_entries(time_t t); -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, - struct in_addr send_ip, struct in_addr reply_to_ip); -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); - -/*The following definitions come from nameserv.c */ - -void remove_name_entry(struct subnet_record *d, char *name,int type); -void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags); -void add_domain_logon_names(void); -void add_domain_master_bcast(void); -void add_domain_master_wins(void); -void add_domain_names(time_t t); -void add_my_names(void); -void remove_my_names(); -void refresh_my_names(time_t t); -void query_refresh_names(time_t t); - -/*The following definitions come from nameservreply.c */ - -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); -void reply_name_release(struct packet_struct *p); -void reply_name_reg(struct packet_struct *p); -void reply_name_status(struct packet_struct *p); -void reply_name_query(struct packet_struct *p); - -/*The following definitions come from nameservresp.c */ - -void debug_state_type(int state); -void response_netbios_packet(struct packet_struct *p); - -/*The following definitions come from namework.c */ - -void reset_server(char *name, int state, struct in_addr ip); -void tell_become_backup(void); -BOOL same_context(struct dgram_packet *dgram); -void process_browse_packet(struct packet_struct *p,char *buf,int len); - -/*The following definitions come from nmbd.c */ - -BOOL reload_services(BOOL test); - -/*The following definitions come from nmblib.c */ - -char *lookup_opcode_name( int opcode ); -void debug_nmb_packet(struct packet_struct *p); -char *namestr(struct nmb_name *n); -void free_nmb_packet(struct nmb_packet *nmb); -void free_packet(struct packet_struct *packet); -struct packet_struct *read_packet(int fd,enum packet_type packet_type); -void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope); -BOOL send_packet(struct packet_struct *p); -struct packet_struct *receive_packet(int fd,enum packet_type type,int t); - -/*The following definitions come from nmblookup.c */ - -int main(int argc,char *argv[]); - -/*The following definitions come from nmbsync.c */ - -char *getsmbpass(char *pass); -void sync_browse_lists(struct subnet_record *d, struct work_record *work, - char *name, int nm_type, struct in_addr ip, BOOL local); - -/*The following definitions come from params.c */ - -BOOL pm_process( char *FileName, - BOOL (*sfunc)(char *), - BOOL (*pfunc)(char *, char *) ); - -/*The following definitions come from password.c */ - -void generate_next_challenge(char *challenge); -BOOL set_challenge(char *challenge); -BOOL last_challenge(char *challenge); -user_struct *get_valid_user_struct(uint16 vuid); -void invalidate_vuid(uint16 vuid); -char *validated_username(uint16 vuid); -uint16 register_vuid(int uid,int gid, char *name,BOOL guest); -void add_session_user(char *user); -void dfs_unlogin(void); -BOOL password_check(char *password); -BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8); -BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd); -BOOL user_ok(char *user,int snum); -BOOL authorise_login(int snum,char *user,char *password, int pwlen, - BOOL *guest,BOOL *force,uint16 vuid); -BOOL check_hosts_equiv(char *user); -BOOL server_cryptkey(char *buf); -BOOL server_validate(char *buf); - -/*The following definitions come from pcap.c */ - -BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname); -void pcap_printer_fn(void (*fn)()); - -/*The following definitions come from pipes.c */ - -int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize); -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); -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); -char *dom_sid_to_string(DOM_SID *sid); -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len); - -/*The following definitions come from predict.c */ - -int read_predict(int fd,int offset,char *buf,char **ptr,int num); -void do_read_prediction(); -void invalidate_read_prediction(int fd); - -/*The following definitions come from printing.c */ - -void lpq_reset(int snum); -void print_file(int fnum); -int get_printqueue(int snum,int cnum,print_queue_struct **queue, - print_status_struct *status); -void del_printqueue(int cnum,int snum,int jobid); -void status_printjob(int cnum,int snum,int jobid,int status); -int printjob_encode(int snum, int job); -void printjob_decode(int jobid, int *snum, int *job); - -/*The following definitions come from quotas.c */ - -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); - -/*The following definitions come from replace.c */ - -char *Strstr(char *s, char *p); -time_t Mktime(struct tm *t); -int InNetGr(char *group,char *host,char *user,char *dom); -void *malloc_wrapped(int size,char *file,int line); -void *realloc_wrapped(void *ptr,int size,char *file,int line); -void free_wrapped(void *ptr,char *file,int line); -void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line); - -/*The following definitions come from reply.c */ - -int reply_special(char *inbuf,char *outbuf); -int reply_tcon(char *inbuf,char *outbuf); -int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize); -int reply_unknown(char *inbuf,char *outbuf); -int reply_ioctl(char *inbuf,char *outbuf); -int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize); -int reply_chkpth(char *inbuf,char *outbuf); -int reply_getatr(char *inbuf,char *outbuf); -int reply_setatr(char *inbuf,char *outbuf); -int reply_dskattr(char *inbuf,char *outbuf); -int reply_search(char *inbuf,char *outbuf); -int reply_fclose(char *inbuf,char *outbuf); -int reply_open(char *inbuf,char *outbuf); -int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize); -int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize); -int reply_mknew(char *inbuf,char *outbuf); -int reply_ctemp(char *inbuf,char *outbuf); -int reply_unlink(char *inbuf,char *outbuf); -int reply_readbraw(char *inbuf, char *outbuf); -int reply_lockread(char *inbuf,char *outbuf); -int reply_read(char *inbuf,char *outbuf); -int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize); -int reply_writebraw(char *inbuf,char *outbuf); -int reply_writeunlock(char *inbuf,char *outbuf); -int reply_write(char *inbuf,char *outbuf,int dum1,int dum2); -int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize); -int reply_lseek(char *inbuf,char *outbuf); -int reply_flush(char *inbuf,char *outbuf); -int reply_exit(char *inbuf,char *outbuf); -int reply_close(char *inbuf,char *outbuf); -int reply_writeclose(char *inbuf,char *outbuf); -int reply_lock(char *inbuf,char *outbuf); -int reply_unlock(char *inbuf,char *outbuf); -int reply_tdis(char *inbuf,char *outbuf); -int reply_echo(char *inbuf,char *outbuf); -int reply_printopen(char *inbuf,char *outbuf); -int reply_printclose(char *inbuf,char *outbuf); -int reply_printqueue(char *inbuf,char *outbuf); -int reply_printwrite(char *inbuf,char *outbuf); -int reply_mkdir(char *inbuf,char *outbuf); -int reply_rmdir(char *inbuf,char *outbuf); -int reply_mv(char *inbuf,char *outbuf); -int reply_copy(char *inbuf,char *outbuf); -int reply_setdir(char *inbuf,char *outbuf); -int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize); -int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize); -int reply_writebmpx(char *inbuf,char *outbuf); -int reply_writebs(char *inbuf,char *outbuf); -int reply_setattrE(char *inbuf,char *outbuf); -int reply_getattrE(char *inbuf,char *outbuf); - -/*The following definitions come from server.c */ - -void *dflt_sig(void); -void killkids(void); -mode_t unix_mode(int cnum,int dosmode); -int dos_mode(int cnum,char *path,struct stat *sbuf); -int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st); -BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path); -int disk_free(char *path,int *bsize,int *dfree,int *dsize); -int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize); -BOOL check_name(char *name,int cnum); -void sync_file(int fnum); -void close_file(int fnum); -BOOL check_file_sharing(int cnum,char *fname); -int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, - BOOL fcbopen, int *flags); -void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, - int mode,int oplock_request, int *Access,int *action); -int seek_file(int fnum,uint32 pos); -int read_file(int fnum,char *data,uint32 pos,int n); -int write_file(int fnum,char *data,int n); -BOOL become_service(int cnum,BOOL do_chdir); -int find_service(char *service); -int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line); -int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line); -int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line); -BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval); -BOOL request_oplock_break(min_share_mode_entry *share_entry, - uint32 dev, uint32 inode); -BOOL snum_used(int snum); -BOOL reload_services(BOOL test); -int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups); -int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid); -int find_free_file(void ); -int reply_corep(char *outbuf); -int reply_coreplus(char *outbuf); -int reply_lanman1(char *outbuf); -int reply_lanman2(char *outbuf); -int reply_nt1(char *outbuf); -void close_cnum(int cnum, uint16 vuid); -BOOL yield_connection(int cnum,char *name,int max_connections); -BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear); -void exit_server(char *reason); -void standard_sub(int cnum,char *str); -char *smb_fn_name(int type); -int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); -int construct_reply(char *inbuf,char *outbuf,int size,int bufsize); - -/*The following definitions come from shmem.c */ - -BOOL smb_shm_create_hash_table( unsigned int size ); -BOOL smb_shm_open( char *file_name, int size); -BOOL smb_shm_close( void ); -smb_shm_offset_t smb_shm_alloc(int size); -BOOL smb_shm_free(smb_shm_offset_t offset); -smb_shm_offset_t smb_shm_get_userdef_off(void); -BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off); -void *smb_shm_offset2addr(smb_shm_offset_t offset); -smb_shm_offset_t smb_shm_addr2offset(void *addr); -BOOL smb_shm_lock_hash_entry( unsigned int entry); -BOOL smb_shm_unlock_hash_entry( unsigned int entry ); -BOOL smb_shm_get_usage(int *bytes_free, - int *bytes_used, - int *bytes_overhead); - -/*The following definitions come from smbdes.c */ - -void E_P16(unsigned char *p14,unsigned char *p16); -void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); - -/*The following definitions come from smbencrypt.c */ - -void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24); -void E_md4hash(uchar *passwd, uchar *p16); -void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24); - -/*The following definitions come from smbparse.c */ - -char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align); -char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align); -char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align); -char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align); -char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align); -char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align); -char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align); -char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align); -char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align); -char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align); -char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align); -char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align); -char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align); -char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align); -char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align); -char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align); -char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align); -char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align); -char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align); -char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align); -char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); -char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align); -char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align); -char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align); -char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align); -char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align); - -/*The following definitions come from smbpass.c */ - -int pw_file_lock(char *name, int type, int secs); -int pw_file_unlock(int fd); -struct smb_passwd *get_smbpwnam(char *name); - -/*The following definitions come from smbpasswd.c */ - - -/*The following definitions come from smbrun.c */ - - -/*The following definitions come from status.c */ - -void Ucrit_addUsername(pstring username); -unsigned int Ucrit_checkUsername(pstring username); -void Ucrit_addPid(int pid); -unsigned int Ucrit_checkPid(int pid); - -/*The following definitions come from system.c */ - -int sys_select(fd_set *fds,struct timeval *tval); -int sys_select(fd_set *fds,struct timeval *tval); -int sys_unlink(char *fname); -int sys_open(char *fname,int flags,int mode); -DIR *sys_opendir(char *dname); -int sys_stat(char *fname,struct stat *sbuf); -int sys_waitpid(pid_t pid,int *status,int options); -int sys_lstat(char *fname,struct stat *sbuf); -int sys_mkdir(char *dname,int mode); -int sys_rmdir(char *dname); -int sys_chdir(char *dname); -int sys_utime(char *fname,struct utimbuf *times); -int sys_rename(char *from, char *to); -int sys_chmod(char *fname,int mode); -char *sys_getwd(char *s); -int sys_chown(char *fname,int uid,int gid); -int sys_chroot(char *dname); -struct hostent *sys_gethostbyname(char *name); - -/*The following definitions come from testparm.c */ - - -/*The following definitions come from testprns.c */ - -int main(int argc, char *argv[]); - -/*The following definitions come from time.c */ - -void GetTimeOfDay(struct timeval *tval); -void TimeInit(void); -int TimeDiff(time_t t); -struct tm *LocalTime(time_t *t); -time_t interpret_long_date(char *p); -void put_long_date(char *p,time_t t); -void put_dos_date(char *buf,int offset,time_t unixdate); -void put_dos_date2(char *buf,int offset,time_t unixdate); -void put_dos_date3(char *buf,int offset,time_t unixdate); -time_t make_unix_date(void *date_ptr); -time_t make_unix_date2(void *date_ptr); -time_t make_unix_date3(void *date_ptr); -BOOL set_filetime(char *fname,time_t mtime); -char *timestring(void ); - -/*The following definitions come from trans2.c */ - -int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize); -int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize); -int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize); -int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize); - -/*The following definitions come from ufc.c */ - -char *ufc_crypt(char *key,char *salt); - -/*The following definitions come from uid.c */ - -void init_uid(void); -BOOL become_guest(void); -BOOL become_user(int cnum, uint16 vuid); -BOOL unbecome_user(void ); -int smbrun(char *cmd,char *outfile,BOOL shared); - -/*The following definitions come from username.c */ - -char *get_home_dir(char *user); -void map_username(char *user); -struct passwd *Get_Pwnam(char *user,BOOL allow_change); -BOOL user_in_list(char *user,char *list); - -/*The following definitions come from util.c */ - -void setup_logging(char *pname,BOOL interactive); -void reopen_logs(void); -char *tmpdir(void); -BOOL is_a_socket(int fd); -BOOL next_token(char **ptr,char *buff,char *sep); -char **toktocliplist(int *ctok, char *sep); -void *MemMove(void *dest,void *src,int size); -void array_promote(char *array,int elsize,int element); -void set_socket_options(int fd, char *options); -void close_sockets(void ); -BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups); -char *StrCpy(char *dest,char *src); -char *StrnCpy(char *dest,char *src,int n); -void putip(void *dest,void *src); -int name_mangle( char *In, char *Out, char name_type ); -BOOL file_exist(char *fname,struct stat *sbuf); -time_t file_modtime(char *fname); -BOOL directory_exist(char *dname,struct stat *st); -uint32 file_size(char *file_name); -char *attrib_string(int mode); -int StrCaseCmp(char *s, char *t); -int StrnCaseCmp(char *s, char *t, int n); -BOOL strequal(char *s1, char *s2); -BOOL strnequal(char *s1,char *s2,int n); -BOOL strcsequal(char *s1,char *s2); -void strlower(char *s); -void strupper(char *s); -void strnorm(char *s); -BOOL strisnormal(char *s); -void string_replace(char *s,char oldc,char newc); -void unix_format(char *fname); -void dos_format(char *fname); -void show_msg(char *buf); -int smb_len(char *buf); -void _smb_setlen(char *buf,int len); -void smb_setlen(char *buf,int len); -int set_message(char *buf,int num_words,int num_bytes,BOOL zero); -int smb_numwords(char *buf); -int smb_buflen(char *buf); -int smb_buf_ofs(char *buf); -char *smb_buf(char *buf); -int smb_offset(char *p,char *buf); -char *skip_string(char *buf,int n); -BOOL trim_string(char *s,char *front,char *back); -void dos_clean_name(char *s); -void unix_clean_name(char *s); -int ChDir(char *path); -char *GetWd(char *str); -BOOL reduce_name(char *s,char *dir,BOOL widelinks); -void expand_mask(char *Mask,BOOL doext); -BOOL strhasupper(char *s); -BOOL strhaslower(char *s); -int count_chars(char *s,char c); -void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date); -void close_low_fds(void); -int set_blocking(int fd, BOOL set); -int write_socket(int fd,char *buf,int len); -int read_udp_socket(int fd,char *buf,int len); -int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out); -int read_max_udp(int fd,char *buffer,int bufsize,int maxtime); -int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew); -BOOL send_keepalive(int client); -int read_data(int fd,char *buffer,int N); -int write_data(int fd,char *buffer,int N); -int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align); -int read_smb_length(int fd,char *inbuf,int timeout); -BOOL receive_smb(int fd,char *buffer, int timeout); -BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout); -BOOL push_local_message(char *buf, int msg_len); -BOOL receive_message_or_smb(int smbfd, int oplock_fd, - char *buffer, int buffer_len, - int timeout, BOOL *got_smb); -BOOL send_smb(int fd,char *buffer); -char *name_ptr(char *buf,int ofs); -int name_extract(char *buf,int ofs,char *name); -int name_len( char *s ); -BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type); -void msleep(int t); -BOOL in_list(char *s,char *list,BOOL casesensitive); -BOOL string_init(char **dest,char *src); -void string_free(char **s); -BOOL string_set(char **dest,char *src); -BOOL string_sub(char *s,char *pattern,char *insert); -BOOL do_match(char *str, char *regexp, int case_sig); -BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2); -void become_daemon(void); -BOOL yesno(char *p); -char *fgets_slash(char *s2,int maxlen,FILE *f); -int set_filelen(int fd, long len); -int byte_checksum(char *buf,int len); -char *dirname_dos(char *path,char *buf); -void *Realloc(void *p,int size); -void Abort(void ); -BOOL get_myname(char *my_name,struct in_addr *ip); -BOOL ip_equal(struct in_addr ip1,struct in_addr ip2); -int open_socket_in(int type, int port, int dlevel,uint32 socket_addr); -int open_socket_out(int type, struct in_addr *addr, int port ,int timeout); -int interpret_protocol(char *str,int def); -int interpret_security(char *str,int def); -uint32 interpret_addr(char *str); -struct in_addr *interpret_addr2(char *str); -BOOL zero_ip(struct in_addr ip); -void reset_globals_after_fork(); -char *client_name(void); -char *client_addr(void); -void standard_sub_basic(char *str); -BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask); -int PutUniCode(char *dst,char *src); -struct hostent *Get_Hostbyname(char *name); -BOOL process_exists(int pid); -char *uidtoname(int uid); -char *gidtoname(int gid); -void BlockSignals(BOOL block,int signum); -void ajt_panic(void); -char *readdirname(void *p); -BOOL is_in_path(char *name, name_compare_entry *namelist); -void set_namearray(name_compare_entry **ppname_array, char *namelist); -void free_namearray(name_compare_entry *name_array); -BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type); -int file_lock(char *name,int timeout); -void file_unlock(int fd); -BOOL is_myname(char *s); -void set_remote_arch(enum remote_arch_types type); -enum remote_arch_types get_remote_arch(); -char *skip_unicode_string(char *buf,int n); -char *unistr2(uint16 *buf); -char *unistr(char *buf); -int unistrncpy(char *dst, char *src, int len); -int unistrcpy(char *dst, char *src); -void fstrcpy(char *dest, char *src); -void pstrcpy(char *dest, char *src); -char *align4(char *q, char *base); -char *align2(char *q, char *base); -char *align_offset(char *q, char *base, int align_offset_len); diff --git a/source/include/smb.h b/source/include/smb.h deleted file mode 100644 index 54ce9e88e88..00000000000 --- a/source/include/smb.h +++ /dev/null @@ -1,1694 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1997 - Copyright (C) John H Terpstra 1996-1997 - Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Paul Ashton 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 _SMB_H -#define _SMB_H - -#ifndef MAX_CONNECTIONS -#define MAX_CONNECTIONS 127 -#endif - -#ifndef MAX_OPEN_FILES -#define MAX_OPEN_FILES 50 -#endif - -#ifndef GUEST_ACCOUNT -#define GUEST_ACCOUNT "nobody" -#endif - -#define BUFFER_SIZE (0xFFFF) -#define SAFETY_MARGIN 1024 - -/* Default size of shared memory used for share mode locking */ -#ifndef SHMEM_SIZE -#define SHMEM_SIZE 102400 -#endif - -/* Default number of hash buckets used in shared memory share mode */ -#ifndef SHMEM_HASH_SIZE -#define SHMEM_HASH_SIZE 113 -#endif - -#define NMB_PORT 137 -#define DGRAM_PORT 138 -#define SMB_PORT 139 - -#define False (0) -#define True (1) -#define BOOLSTR(b) ((b) ? "Yes" : "No") -#define BITSETB(ptr,bit) ((((char *)ptr)[0] & (1<<(bit)))!=0) -#define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0) -#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2))) - -typedef int BOOL; - -/* offset in shared memory */ -typedef int smb_shm_offset_t; -#define NULL_OFFSET (smb_shm_offset_t)(0) - - -/* - Samba needs type definitions for int16, int32, uint16 and uint32. - - Normally these are signed and unsigned 16 and 32 bit integers, but - they actually only need to be at least 16 and 32 bits - respectively. Thus if your word size is 8 bytes just defining them - as signed and unsigned int will work. -*/ - -/* afs/stds.h defines int16 and int32 */ -#ifndef AFS_AUTH -typedef short int16; -typedef int int32; -#endif - -#ifndef uint8 -typedef unsigned char uint8; -#endif - -#ifndef uint16 -typedef unsigned short uint16; -#endif - -#ifndef uint32 -typedef unsigned int uint32; -#endif - -#ifndef uchar -#define uchar unsigned char -#endif -#ifndef int16 -#define int16 short -#endif -#ifndef uint16 -#define uint16 unsigned short -#endif -#ifndef uint32 -#define uint32 unsigned int -#endif - -#define SIZEOFWORD 2 - -#ifndef DEF_CREATE_MASK -#define DEF_CREATE_MASK (0755) -#endif - -/* how long to wait for secondary SMB packets (milli-seconds) */ -#define SMB_SECONDARY_WAIT (60*1000) - -/* debugging code */ -#ifndef SYSLOG -#define DEBUG(level,body) ((DEBUGLEVEL>=(level))?(Debug1 body):0) -#else -extern int syslog_level; - -#define DEBUG(level,body) ((DEBUGLEVEL>=(level))? (syslog_level = (level), Debug1 body):0) -#endif - -/* this defines the error codes that receive_smb can put in smb_read_error */ -#define READ_TIMEOUT 1 -#define READ_EOF 2 -#define READ_ERROR 3 - - -#define DIR_STRUCT_SIZE 43 - -/* these define all the command types recognised by the server - there -are lots of gaps so probably there are some rare commands that are not -implemented */ - -#define pSETDIR '\377' - -/* these define the attribute byte as seen by DOS */ -#define aRONLY (1L<<0) -#define aHIDDEN (1L<<1) -#define aSYSTEM (1L<<2) -#define aVOLID (1L<<3) -#define aDIR (1L<<4) -#define aARCH (1L<<5) - -/* deny modes */ -#define DENY_DOS 0 -#define DENY_ALL 1 -#define DENY_WRITE 2 -#define DENY_READ 3 -#define DENY_NONE 4 -#define DENY_FCB 7 - -/* share types */ -#define STYPE_DISKTREE 0 /* Disk drive */ -#define STYPE_PRINTQ 1 /* Spooler queue */ -#define STYPE_DEVICE 2 /* Serial device */ -#define STYPE_IPC 3 /* Interprocess communication (IPC) */ - -/* SMB X/Open error codes for the ERRdos error class */ -#define ERRbadfunc 1 /* Invalid function (or system call) */ -#define ERRbadfile 2 /* File not found (pathname error) */ -#define ERRbadpath 3 /* Directory not found */ -#define ERRnofids 4 /* Too many open files */ -#define ERRnoaccess 5 /* Access denied */ -#define ERRbadfid 6 /* Invalid fid */ -#define ERRnomem 8 /* Out of memory */ -#define ERRbadmem 9 /* Invalid memory block address */ -#define ERRbadenv 10 /* Invalid environment */ -#define ERRbadaccess 12 /* Invalid open mode */ -#define ERRbaddata 13 /* Invalid data (only from ioctl call) */ -#define ERRres 14 /* reserved */ -#define ERRbaddrive 15 /* Invalid drive */ -#define ERRremcd 16 /* Attempt to delete current directory */ -#define ERRdiffdevice 17 /* rename/move across different filesystems */ -#define ERRnofiles 18 /* no more files found in file search */ -#define ERRbadshare 32 /* Share mode on file conflict with open mode */ -#define ERRlock 33 /* Lock request conflicts with existing lock */ -#define ERRfilexists 80 /* File in operation already exists */ -#define ERRcannotopen 110 /* Cannot open the file specified */ -#define ERRunknownlevel 124 -#define ERRbadpipe 230 /* Named pipe invalid */ -#define ERRpipebusy 231 /* All instances of pipe are busy */ -#define ERRpipeclosing 232 /* named pipe close in progress */ -#define ERRnotconnected 233 /* No process on other end of named pipe */ -#define ERRmoredata 234 /* More data to be returned */ -#define ERRbaddirectory 267 /* Invalid directory name in a path. */ -#define ERROR_EAS_DIDNT_FIT 275 /* Extended attributes didn't fit */ -#define ERROR_EAS_NOT_SUPPORTED 282 /* Extended attributes not supported */ -#define ERRunknownipc 2142 - - -/* here's a special one from observing NT */ -#define ERRnoipc 66 /* don't support ipc */ - -/* Error codes for the ERRSRV class */ - -#define ERRerror 1 /* Non specific error code */ -#define ERRbadpw 2 /* Bad password */ -#define ERRbadtype 3 /* reserved */ -#define ERRaccess 4 /* No permissions to do the requested operation */ -#define ERRinvnid 5 /* tid invalid */ -#define ERRinvnetname 6 /* Invalid servername */ -#define ERRinvdevice 7 /* Invalid device */ -#define ERRqfull 49 /* Print queue full */ -#define ERRqtoobig 50 /* Queued item too big */ -#define ERRinvpfid 52 /* Invalid print file in smb_fid */ -#define ERRsmbcmd 64 /* Unrecognised command */ -#define ERRsrverror 65 /* smb server internal error */ -#define ERRfilespecs 67 /* fid and pathname invalid combination */ -#define ERRbadlink 68 /* reserved */ -#define ERRbadpermits 69 /* Access specified for a file is not valid */ -#define ERRbadpid 70 /* reserved */ -#define ERRsetattrmode 71 /* attribute mode invalid */ -#define ERRpaused 81 /* Message server paused */ -#define ERRmsgoff 82 /* Not receiving messages */ -#define ERRnoroom 83 /* No room for message */ -#define ERRrmuns 87 /* too many remote usernames */ -#define ERRtimeout 88 /* operation timed out */ -#define ERRnoresource 89 /* No resources currently available for request. */ -#define ERRtoomanyuids 90 /* too many userids */ -#define ERRbaduid 91 /* bad userid */ -#define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX mode */ -#define ERRuseSTD 251 /* temporarily unable to use raw mode, use standard mode */ -#define ERRcontMPX 252 /* resume MPX mode */ -#define ERRbadPW /* reserved */ -#define ERRnosupport 0xFFFF -#define ERRunknownsmb 22 /* from NT 3.5 response */ - - -/* Error codes for the ERRHRD class */ - -#define ERRnowrite 19 /* read only media */ -#define ERRbadunit 20 /* Unknown device */ -#define ERRnotready 21 /* Drive not ready */ -#define ERRbadcmd 22 /* Unknown command */ -#define ERRdata 23 /* Data (CRC) error */ -#define ERRbadreq 24 /* Bad request structure length */ -#define ERRseek 25 -#define ERRbadmedia 26 -#define ERRbadsector 27 -#define ERRnopaper 28 -#define ERRwrite 29 /* write fault */ -#define ERRread 30 /* read fault */ -#define ERRgeneral 31 /* General hardware failure */ -#define ERRwrongdisk 34 -#define ERRFCBunavail 35 -#define ERRsharebufexc 36 /* share buffer exceeded */ -#define ERRdiskfull 39 - - -typedef char pstring[1024]; -typedef char fstring[128]; -typedef fstring string; - - -/* NETLOGON opcodes and data structures */ - -#define NET_QUERYFORPDC 7 /* Query for PDC */ -#define NET_QUERYFORPDC_R 12 /* Response to Query for PDC */ -#define NET_SAMLOGON 18 -#define NET_SAMLOGON_R 19 - -/* Allowable account control bits */ -#define ACB_DISABLED 1 /* 1 = User account disabled */ -#define ACB_HOMDIRREQ 2 /* 1 = Home directory required */ -#define ACB_PWNOTREQ 4 /* 1 = User password not required */ -#define ACB_TEMPDUP /* 1 = Temporary duplicate account */ -#define ACB_NORMAL /* 1 = Normal user account */ -#define ACB_MNS /* 1 = MNS logon user account */ -#define ACB_DOMTRUST /* 1 = Interdomain trust account */ -#define ACB_WSTRUST /* 1 = Workstation trust account */ -#define ACB_SVRTRUST /* 1 = Server trust account */ -#define ACB_PWNOEXP /* 1 = User password does not expire */ -#define ACB_AUTOLOCK /* 1 = Account auto locked */ - -#define LSA_OPENPOLICY 0x2c -#define LSA_QUERYINFOPOLICY 0x07 -#define LSA_ENUMTRUSTDOM 0x0d -#define LSA_REQCHAL 0x04 -#define LSA_SVRPWSET 0x06 -#define LSA_SAMLOGON 0x02 -#define LSA_AUTH2 0x0f -#define LSA_CLOSE 0x00 - -/* unknown .... */ -#define LSA_OPENSECRET 0xFF -#define LSA_LOOKUPSIDS 0xFE -#define LSA_LOOKUPNAMES 0xFD -#define LSA_SAMLOGOFF 0xFC - - -/* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */ -typedef struct time_info -{ - uint32 time; - -} UTIME; - -/* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ -typedef struct nttime_info -{ - uint32 low; - uint32 high; - -} NTTIME; - - -#define MAXSUBAUTHS 10 /* max sub authorities in a SID */ - -/* DOM_SID - security id */ -typedef struct sid_info -{ - uint8 sid_no; /* SID revision number */ - uint8 num_auths; /* number of sub-authorities */ - uint8 id_auth[6]; /* Identifier Authority */ - uint16 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */ - -} DOM_SID; - -/* UNIHDR - unicode string header */ -typedef struct unihdr_info -{ - uint16 uni_max_len; - uint16 uni_str_len; - uint32 undoc; /* usually has a value of 4 */ - -} UNIHDR; - -/* UNIHDR2 - unicode string header and undocumented buffer */ -typedef struct unihdr2_info -{ - UNIHDR unihdr; - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - -} UNIHDR2; - -/* clueless as to what maximum length should be */ -#define MAX_UNISTRLEN 1024 - -/* UNISTR - unicode string size and buffer */ -typedef struct unistr_info -{ - uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. ***MUST*** be null-terminated */ - -} UNISTR; - -/* UNISTR2 - unicode string size and buffer */ -typedef struct unistr2_info -{ - uint32 uni_max_len; - uint32 undoc; - uint32 uni_str_len; - uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */ - -} UNISTR2; - -/* DOM_SID2 - domain SID structure - SIDs stored in unicode */ -typedef struct domsid2_info -{ - uint32 type; /* value is 5 */ - uint32 undoc; /* value is 0 */ - - UNIHDR2 hdr; /* XXXX conflict between hdr and str for length */ - UNISTR str; /* XXXX conflict between hdr and str for length */ - -} DOM_SID2; - -/* DOM_RID2 - domain RID structure */ -typedef struct domrid2_info -{ - uint32 type; /* value is 5 */ - uint32 undoc; /* value is 5 */ - uint32 rid; - uint32 rid_idx; /* don't know what this is */ - -} DOM_RID2; - -/* DOM_LOG_INFO - login info */ -typedef struct log_info -{ - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - UNISTR2 uni_acct_name; /* account name */ - uint16 sec_chan; /* secure channel type */ - UNISTR2 uni_comp_name; /* client machine name */ - -} DOM_LOG_INFO; - -/* DOM_CHAL - challenge info */ -typedef struct chal_info -{ - uint8 data[8]; /* credentials */ - -} DOM_CHAL; - -/* DOM_CREDs - timestamped client or server credentials */ -typedef struct cred_info -{ - DOM_CHAL challenge; /* credentials */ - UTIME timestamp; /* credential time-stamp */ - -} DOM_CRED; - -/* DOM_CLNT_INFO - client info */ -typedef struct clnt_info -{ - DOM_LOG_INFO login; - DOM_CRED cred; - -} DOM_CLNT_INFO; - -/* DOM_LOGON_ID - logon id */ -typedef struct logon_info -{ - uint32 low; - uint32 high; - -} DOM_LOGON_ID; - -/* ARC4_OWF */ -typedef struct arc4_owf_info -{ - uint8 data[16]; - -} ARC4_OWF; - - -/* DOM_ID_INFO_1 */ -typedef struct id_info_1 -{ - UNIHDR hdr_domain_name; /* domain name unicode header */ - uint32 param; /* param control */ - DOM_LOGON_ID logon_id; /* logon ID */ - UNIHDR hdr_user_name; /* user name unicode header */ - UNIHDR hdr_workgroup_name; /* workgroup name unicode header */ - ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */ - ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */ - UNISTR2 uni_domain_name; /* domain name unicode string */ - UNISTR2 uni_user_name; /* user name unicode string */ - UNISTR2 uni_workgroup_name; /* workgroup name unicode string */ - -} DOM_ID_INFO_1; - -/* SAM_INFO - sam logon/off id structure */ -typedef struct sam_info -{ - DOM_CLNT_INFO client; - DOM_CRED rtn_cred; /* return credentials */ - uint16 logon_level; - uint32 auth_level; /* undocumented */ - - union - { - DOM_ID_INFO_1 id1; /* auth-level 1 */ - - } auth; - -} DOM_SAM_INFO; - -/* DOM_GID - group id + user attributes */ -typedef struct gid_info -{ - uint32 gid; /* group id */ - uint32 attr; - -} DOM_GID; - -/* RPC_HDR - ms rpc header */ -typedef struct rpc_hdr_info -{ - uint8 major; /* 5 - RPC major version */ - uint8 minor; /* 0 - RPC minor version */ - uint8 pkt_type; /* 2 - RPC response packet */ - uint8 frag; /* 3 - first frag + last frag */ - uint32 pack_type; /* 0x0000 0010 - packed data representation */ - uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */ - uint16 auth_len; /* 0 - authentication length */ - uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */ - uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */ - uint16 context_id; /* 0 - presentation context identifier */ - uint8 cancel_count; /* 0 - cancel count */ - uint8 reserved; /* 0 - reserved */ - -} RPC_HDR; - -/* DOM_QUERY - info class 3 and 5 LSA Query response */ -typedef struct dom_query_info -{ - uint16 uni_dom_max_len; /* domain name string length * 2 */ - uint16 padding; /* 2 padding bytes? */ - uint16 uni_dom_str_len; /* domain name string length * 2 */ - uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */ - uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */ - UNISTR2 uni_domain_name; /* domain name (unicode string) */ - DOM_SID dom_sid; /* domain SID */ - -} DOM_QUERY; - -/* level 5 is same as level 3. we hope. */ -typedef DOM_QUERY DOM_QUERY_3; -typedef DOM_QUERY DOM_QUERY_5; - -#define POL_HND_SIZE 20 - -/* LSA_POL_HND */ -typedef struct lsa_policy_info -{ - uint8 data[POL_HND_SIZE]; /* policy handle */ - -} LSA_POL_HND; - - -/* LSA_R_OPEN_POL - response to LSA Open Policy */ -typedef struct lsa_r_open_pol_info -{ - LSA_POL_HND pol; /* policy handle */ - - uint32 status; /* return code */ - -} LSA_R_OPEN_POL; - -/* LSA_Q_QUERY_INFO - LSA query info policy */ -typedef struct lsa_query_info -{ - LSA_POL_HND pol; /* policy handle */ - uint16 info_class; /* info class */ - -} LSA_Q_QUERY_INFO; - -/* LSA_R_QUERY_INFO - response to LSA query info policy */ -typedef struct lsa_r_query_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer */ - uint16 info_class; /* info class (same as info class in request) */ - - union - { - DOM_QUERY_3 id3; - DOM_QUERY_5 id5; - } dom; - - uint32 status; /* return code */ - -} LSA_R_QUERY_INFO; - -#define MAX_REF_DOMAINS 10 - -/* DOM_R_REF */ -typedef struct dom_ref_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer. */ - uint32 num_ref_doms_1; /* num referenced domains? */ - uint32 buffer_dom_name; /* undocumented domain name buffer pointer. */ - uint32 max_entries; /* 32 - max number of entries */ - uint32 num_ref_doms_2; /* 4 - num referenced domains? */ - - UNIHDR2 hdr_dom_name; /* domain name unicode string header */ - UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */ - - UNISTR uni_dom_name; /* domain name unicode string */ - DOM_SID ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */ - -} DOM_R_REF; - -#define MAX_LOOKUP_SIDS 10 - -/* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */ -typedef struct lsa_q_lookup_sids -{ - LSA_POL_HND pol_hnd; /* policy handle */ - uint32 num_entries; - uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ - uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ - uint32 buffer_lookup_sids[MAX_LOOKUP_SIDS]; /* undocumented domain SID pointers to be looked up. */ - DOM_SID dom_sids[MAX_LOOKUP_SIDS]; /* domain SIDs to be looked up. */ - uint8 undoc[16]; /* completely undocumented 16 bytes */ - -} LSA_Q_LOOKUP_SIDS; - -/* LSA_R_LOOKUP_SIDS - response to LSA Lookup SIDs */ -typedef struct lsa_r_lookup_sids -{ - DOM_R_REF dom_ref; /* domain reference info */ - - uint32 num_entries; - uint32 undoc_buffer; /* undocumented buffer pointer */ - uint32 num_entries2; - - DOM_SID2 dom_sid[MAX_LOOKUP_SIDS]; /* domain SIDs being looked up */ - - uint32 num_entries3; - - uint32 status; /* return code */ - -} LSA_R_LOOKUP_SIDS; - -/* DOM_NAME - XXXX not sure about this structure */ -typedef struct dom_name_info -{ - uint32 uni_str_len; - UNISTR str; - -} DOM_NAME; - - -#define UNKNOWN_LEN 1 - -/* LSA_Q_LOOKUP_RIDS - LSA Lookup RIDs */ -typedef struct lsa_q_lookup_rids -{ - - LSA_POL_HND pol_hnd; /* policy handle */ - uint32 num_entries; - uint32 num_entries2; - uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */ - uint32 buffer_dom_name; /* undocumented domain name buffer pointer */ - DOM_NAME lookup_name[MAX_LOOKUP_SIDS]; /* names to be looked up */ - uint8 undoc[UNKNOWN_LEN]; /* completely undocumented bytes of unknown length */ - -} LSA_Q_LOOKUP_RIDS; - -/* LSA_R_LOOKUP_RIDS - response to LSA Lookup Names */ -typedef struct lsa_r_lookup_rids -{ - DOM_R_REF dom_ref; /* domain reference info */ - - uint32 num_entries; - uint32 undoc_buffer; /* undocumented buffer pointer */ - - uint32 num_entries2; - DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */ - - uint32 num_entries3; - - uint32 status; /* return code */ - -} LSA_R_LOOKUP_RIDS; - - - -/* NEG_FLAGS */ -typedef struct lsa_neg_flags_info -{ - uint32 neg_flags; /* negotiated flags */ - -} NEG_FLAGS; - - -/* LSA_Q_REQ_CHAL */ -typedef struct lsa_q_req_chal_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server unicode string */ - UNISTR2 uni_logon_clnt; /* logon client unicode string */ - DOM_CHAL clnt_chal; /* client challenge */ - -} LSA_Q_REQ_CHAL; - - -/* LSA_R_REQ_CHAL */ -typedef struct lsa_r_req_chal_info -{ - DOM_CHAL srv_chal; /* server challenge */ - - uint32 status; /* return code */ - -} LSA_R_REQ_CHAL; - - - -/* LSA_Q_AUTH_2 */ -typedef struct lsa_q_auth2_info -{ - DOM_LOG_INFO clnt_id; /* client identification info */ - DOM_CHAL clnt_chal; /* client-calculated credentials */ - - NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */ - -} LSA_Q_AUTH_2; - - -/* LSA_R_AUTH_2 */ -typedef struct lsa_r_auth2_info -{ - DOM_CHAL srv_chal; /* server-calculated credentials */ - NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */ - - uint32 status; /* return code */ - -} LSA_R_AUTH_2; - - -/* LSA_Q_SRV_PWSET */ -typedef struct lsa_q_srv_pwset_info -{ - DOM_CLNT_INFO clnt_id; /* client identification/authentication info */ - char pwd[16]; /* new password - undocumented. */ - -} LSA_Q_SRV_PWSET; - -/* LSA_R_SRV_PWSET */ -typedef struct lsa_r_srv_pwset_info -{ - DOM_CRED srv_cred; /* server-calculated credentials */ - - uint32 status; /* return code */ - -} LSA_R_SRV_PWSET; - -#define LSA_MAX_GROUPS 32 -#define LSA_MAX_SIDS 32 - -/* LSA_USER_INFO */ -typedef struct lsa_q_user_info -{ - uint32 undoc_buffer; - - NTTIME logon_time; /* logon time */ - NTTIME logoff_time; /* logoff time */ - NTTIME kickoff_time; /* kickoff time */ - NTTIME pass_last_set_time; /* password last set time */ - NTTIME pass_can_change_time; /* password can change time */ - NTTIME pass_must_change_time; /* password must change time */ - - UNIHDR hdr_user_name; /* username unicode string header */ - UNIHDR hdr_full_name; /* user's full name unicode string header */ - UNIHDR hdr_logon_script; /* logon script unicode string header */ - UNIHDR hdr_profile_path; /* profile path unicode string header */ - UNIHDR hdr_home_dir; /* home directory unicode string header */ - UNIHDR hdr_dir_drive; /* home directory drive unicode string header */ - - uint16 logon_count; /* logon count */ - uint16 bad_pw_count; /* bad password count */ - - uint32 user_id; /* User ID */ - uint32 group_id; /* Group ID */ - uint32 num_groups; /* num groups */ - uint32 buffer_groups; /* undocumented buffer pointer to groups. */ - uint32 user_flgs; /* user flags */ - - char sess_key[16]; /* unused user session key */ - - UNIHDR hdr_logon_srv; /* logon server unicode string header */ - UNIHDR hdr_logon_dom; /* logon domain unicode string header */ - - uint32 buffer_dom_id; /* undocumented logon domain id pointer */ - char padding[40]; /* unused padding bytes? */ - - uint32 num_other_sids; /* 0 - num_sids */ - uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */ - - UNISTR2 uni_user_name; /* username unicode string */ - UNISTR2 uni_full_name; /* user's full name unicode string */ - UNISTR2 uni_logon_script; /* logon script unicode string */ - UNISTR2 uni_profile_path; /* profile path unicode string */ - UNISTR2 uni_home_dir; /* home directory unicode string */ - UNISTR2 uni_dir_drive; /* home directory drive unicode string */ - - uint32 num_groups2; /* num groups */ - DOM_GID gids[LSA_MAX_GROUPS]; /* group info */ - - UNISTR2 uni_logon_srv; /* logon server unicode string */ - UNISTR2 uni_logon_dom; /* logon domain unicode string */ - - DOM_SID dom_sid; /* domain SID */ - DOM_SID other_sids[LSA_MAX_SIDS]; /* undocumented - domain SIDs */ - -} LSA_USER_INFO; - - -/* LSA_Q_SAM_LOGON */ -typedef struct lsa_q_sam_logon_info -{ - DOM_SAM_INFO sam_id; - -} LSA_Q_SAM_LOGON; - -/* LSA_R_SAM_LOGON */ -typedef struct lsa_r_sam_logon_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - - uint32 buffer_user; - LSA_USER_INFO *user; - - uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ - - uint32 status; /* return code */ - -} LSA_R_SAM_LOGON; - - -/* LSA_Q_SAM_LOGOFF */ -typedef struct lsa_q_sam_logoff_info -{ - DOM_SAM_INFO sam_id; - -} LSA_Q_SAM_LOGOFF; - -/* LSA_R_SAM_LOGOFF */ -typedef struct lsa_r_sam_logoff_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - - uint32 status; /* return code */ - -} LSA_R_SAM_LOGOFF; - -/* - -Yet to be turned into structures: - -6) \\MAILSLOT\NET\NTLOGON -------------------------- - -6.1) Query for PDC ------------------- - -Request: - - uint16 0x0007 - Query for PDC - STR machine name - STR response mailslot - uint8[] padding to 2-byte align with start of mailslot. - UNISTR machine name - uint32 NTversion - uint16 LMNTtoken - uint16 LM20token - -Response: - - uint16 0x000A - Respose to Query for PDC - STR machine name (in uppercase) - uint8[] padding to 2-byte align with start of mailslot. - UNISTR machine name - UNISTR domain name - uint32 NTversion (same as received in request) - uint16 LMNTtoken (same as received in request) - uint16 LM20token (same as received in request) - - -6.2) SAM Logon --------------- - -Request: - - uint16 0x0012 - SAM Logon - uint16 request count - UNISTR machine name - UNISTR user name - STR response mailslot - uint32 alloweable account - uint32 domain SID size - char[sid_size] domain SID, of sid_size bytes. - uint8[] ???? padding to 4? 2? -byte align with start of mailslot. - uint32 NTversion - uint16 LMNTtoken - uint16 LM20token - -Response: - - uint16 0x0013 - Response to SAM Logon - UNISTR machine name - UNISTR user name - workstation trust account - UNISTR domain name - uint32 NTversion - uint16 LMNTtoken - uint16 LM20token - -*/ - - -struct smb_passwd { - int smb_userid; - char *smb_name; - unsigned char *smb_passwd; /* Null if no password */ - unsigned char *smb_nt_passwd; /* Null if no password */ - /* Other fields / flags may be added later */ -}; - - -struct current_user { - int cnum, id; - int uid, gid; - int ngroups; - gid_t *groups; - int *igroups; -}; - -typedef struct -{ - int size; - int mode; - int uid; - int gid; - /* these times are normally kept in GMT */ - time_t mtime; - time_t atime; - time_t ctime; - pstring name; -} file_info; - - -/* Structure used when SMBwritebmpx is active */ -typedef struct - { - int wr_total_written; /* So we know when to discard this */ - int32 wr_timeout; - int32 wr_errclass; - int32 wr_error; /* Cached errors */ - BOOL wr_mode; /* write through mode) */ - BOOL wr_discard; /* discard all further data */ - } write_bmpx_struct; - -/* - * Structure used to indirect fd's from the files_struct. - * Needed as POSIX locking is based on file and process, not - * file descriptor and process. - */ - -typedef struct -{ - uint16 ref_count; - uint32 dev; - uint32 inode; - int fd; - int fd_readonly; - int fd_writeonly; - int real_open_flags; -} file_fd_struct; - -typedef struct -{ - int cnum; - file_fd_struct *fd_ptr; - int pos; - uint32 size; - int mode; - int uid; - char *mmap_ptr; - uint32 mmap_size; - write_bmpx_struct *wbmpx_ptr; - struct timeval open_time; - BOOL open; - BOOL can_lock; - BOOL can_read; - BOOL can_write; - BOOL share_mode; - BOOL print_file; - BOOL modified; - BOOL granted_oplock; - char *name; -} files_struct; - - -struct uid_cache { - int entries; - int list[UID_CACHE_SIZE]; -}; - -typedef struct -{ - char *name; - BOOL is_wild; -} name_compare_entry; - -typedef struct -{ - int service; - BOOL force_user; - struct uid_cache uid_cache; - void *dirptr; - BOOL open; - BOOL printer; - BOOL ipc; - BOOL read_only; - BOOL admin_user; - char *dirpath; - char *connectpath; - char *origpath; - char *user; /* name of user who *opened* this connection */ - int uid; /* uid of user who *opened* this connection */ - int gid; /* gid of user who *opened* this connection */ - uint16 vuid; /* vuid of user who *opened* this connection, or UID_FIELD_INVALID */ - /* following groups stuff added by ih */ - /* This groups info is valid for the user that *opened* the connection */ - int ngroups; - gid_t *groups; - int *igroups; /* an integer version - some OSes are broken :-( */ - time_t lastused; - BOOL used; - int num_files_open; - name_compare_entry *hide_list; /* Per-share list of files to return as hidden. */ - name_compare_entry *veto_list; /* Per-share list of files to veto (never show). */ -} connection_struct; - - -typedef struct -{ - int uid; /* uid of a validated user */ - int gid; /* gid of a validated user */ - fstring name; /* name of a validated user */ - BOOL guest; - /* following groups stuff added by ih */ - /* This groups info is needed for when we become_user() for this uid */ - int user_ngroups; - gid_t *user_groups; - int *user_igroups; /* an integer version - some OSes are broken :-( */ -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - char *home_share; /* to store NIS home of a user - simeon */ -#endif - char *real_name; /* to store real name from password file - simeon */ -} user_struct; - - -enum {LPQ_QUEUED,LPQ_PAUSED,LPQ_SPOOLING,LPQ_PRINTING}; - -typedef struct -{ - int job; - int size; - int status; - int priority; - time_t time; - char user[30]; - char file[100]; -} print_queue_struct; - -enum {LPSTAT_OK, LPSTAT_STOPPED, LPSTAT_ERROR}; - -typedef struct -{ - fstring message; - int status; -} print_status_struct; - -/* used for server information: client, nameserv and ipc */ -struct server_info_struct -{ - fstring name; - uint32 type; - fstring comment; - fstring domain; /* used ONLY in ipc.c NOT namework.c */ - BOOL server_added; /* used ONLY in ipc.c NOT namework.c */ -}; - - -/* used for network interfaces */ -struct interface -{ - struct interface *next; - struct in_addr ip; - struct in_addr bcast; - struct in_addr nmask; -}; - -/* share mode record pointed to in shared memory hash bucket */ -typedef struct -{ - smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */ - int locking_version; - int32 st_dev; - int32 st_ino; - int num_share_mode_entries; - smb_shm_offset_t share_mode_entries; /* Chain of share mode entries for this file */ - char file_name[1]; -} share_mode_record; - -/* share mode entry pointed to by share_mode_record struct */ -typedef struct -{ - smb_shm_offset_t next_share_mode_entry; - int pid; - uint16 op_port; - uint16 op_type; - int share_mode; - struct timeval time; -} share_mode_entry; - -/* struct returned by get_share_modes */ -typedef struct -{ - int pid; - uint16 op_port; - uint16 op_type; - int share_mode; - struct timeval time; -} min_share_mode_entry; - -/* Token returned by lock_share_entry (actually ignored by FAST_SHARE_MODES code) */ -typedef int share_lock_token; - -/* Conversion to hash entry index from device and inode numbers. */ -#define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size()) - -/* this is used for smbstatus */ -struct connect_record -{ - int magic; - int pid; - int cnum; - int uid; - int gid; - char name[24]; - char addr[24]; - char machine[128]; - time_t start; -}; - -#ifndef LOCKING_VERSION -#define LOCKING_VERSION 4 -#endif /* LOCKING_VERSION */ - -#if !defined(FAST_SHARE_MODES) -/* - * Defines for slow share modes. - */ - -/* - * Locking file header lengths & offsets. - */ -#define SMF_VERSION_OFFSET 0 -#define SMF_NUM_ENTRIES_OFFSET 4 -#define SMF_FILENAME_LEN_OFFSET 8 -#define SMF_HEADER_LENGTH 10 - -#define SMF_ENTRY_LENGTH 20 - -/* - * Share mode record offsets. - */ - -#define SME_SEC_OFFSET 0 -#define SME_USEC_OFFSET 4 -#define SME_SHAREMODE_OFFSET 8 -#define SME_PID_OFFSET 12 -#define SME_PORT_OFFSET 16 -#define SME_OPLOCK_TYPE_OFFSET 18 - -#endif /* FAST_SHARE_MODES */ - -/* these are useful macros for checking validity of handles */ -#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_OPEN_FILES)) -#define OPEN_FNUM(fnum) (VALID_FNUM(fnum) && Files[fnum].open) -#define VALID_CNUM(cnum) (((cnum) >= 0) && ((cnum) < MAX_CONNECTIONS)) -#define OPEN_CNUM(cnum) (VALID_CNUM(cnum) && Connections[cnum].open) -#define IS_IPC(cnum) (VALID_CNUM(cnum) && Connections[cnum].ipc) -#define IS_PRINT(cnum) (VALID_CNUM(cnum) && Connections[cnum].printer) -#define FNUM_OK(fnum,c) (OPEN_FNUM(fnum) && (c)==Files[fnum].cnum) - -#define CHECK_FNUM(fnum,c) if (!FNUM_OK(fnum,c)) \ - return(ERROR(ERRDOS,ERRbadfid)) -#define CHECK_READ(fnum) if (!Files[fnum].can_read) \ - return(ERROR(ERRDOS,ERRbadaccess)) -#define CHECK_WRITE(fnum) if (!Files[fnum].can_write) \ - return(ERROR(ERRDOS,ERRbadaccess)) -#define CHECK_ERROR(fnum) if (HAS_CACHED_ERROR(fnum)) \ - return(CACHED_ERROR(fnum)) - -/* translates a connection number into a service number */ -#define SNUM(cnum) (Connections[cnum].service) - -/* access various service details */ -#define SERVICE(snum) (lp_servicename(snum)) -#define PRINTCAP (lp_printcapname()) -#define PRINTCOMMAND(snum) (lp_printcommand(snum)) -#define PRINTERNAME(snum) (lp_printername(snum)) -#define CAN_WRITE(cnum) (OPEN_CNUM(cnum) && !Connections[cnum].read_only) -#define VALID_SNUM(snum) (lp_snum_ok(snum)) -#define GUEST_OK(snum) (VALID_SNUM(snum) && lp_guest_ok(snum)) -#define GUEST_ONLY(snum) (VALID_SNUM(snum) && lp_guest_only(snum)) -#define CAN_SETDIR(snum) (!lp_no_set_dir(snum)) -#define CAN_PRINT(cnum) (OPEN_CNUM(cnum) && lp_print_ok(SNUM(cnum))) -#define POSTSCRIPT(cnum) (OPEN_CNUM(cnum) && lp_postscript(SNUM(cnum))) -#define MAP_HIDDEN(cnum) (OPEN_CNUM(cnum) && lp_map_hidden(SNUM(cnum))) -#define MAP_SYSTEM(cnum) (OPEN_CNUM(cnum) && lp_map_system(SNUM(cnum))) -#define MAP_ARCHIVE(cnum) (OPEN_CNUM(cnum) && lp_map_archive(SNUM(cnum))) -#define IS_HIDDEN_PATH(cnum,path) (is_in_path((path),Connections[(cnum)].hide_list)) -#define IS_VETO_PATH(cnum,path) (is_in_path((path),Connections[(cnum)].veto_list)) - -#define SMBENCRYPT() (lp_encrypted_passwords()) - -/* the basic packet size, assuming no words or bytes */ -#define smb_size 39 - -/* offsets into message for common items */ -#define smb_com 8 -#define smb_rcls 9 -#define smb_reh 10 -#define smb_err 11 -#define smb_flg 13 -#define smb_flg2 14 -#define smb_reb 13 -#define smb_tid 28 -#define smb_pid 30 -#define smb_uid 32 -#define smb_mid 34 -#define smb_wct 36 -#define smb_vwv 37 -#define smb_vwv0 37 -#define smb_vwv1 39 -#define smb_vwv2 41 -#define smb_vwv3 43 -#define smb_vwv4 45 -#define smb_vwv5 47 -#define smb_vwv6 49 -#define smb_vwv7 51 -#define smb_vwv8 53 -#define smb_vwv9 55 -#define smb_vwv10 57 -#define smb_vwv11 59 -#define smb_vwv12 61 -#define smb_vwv13 63 -#define smb_vwv14 65 -#define smb_vwv15 67 -#define smb_vwv16 69 -#define smb_vwv17 71 - - -/* the complete */ -#define SMBmkdir 0x00 /* create directory */ -#define SMBrmdir 0x01 /* delete directory */ -#define SMBopen 0x02 /* open file */ -#define SMBcreate 0x03 /* create file */ -#define SMBclose 0x04 /* close file */ -#define SMBflush 0x05 /* flush file */ -#define SMBunlink 0x06 /* delete file */ -#define SMBmv 0x07 /* rename file */ -#define SMBgetatr 0x08 /* get file attributes */ -#define SMBsetatr 0x09 /* set file attributes */ -#define SMBread 0x0A /* read from file */ -#define SMBwrite 0x0B /* write to file */ -#define SMBlock 0x0C /* lock byte range */ -#define SMBunlock 0x0D /* unlock byte range */ -#define SMBctemp 0x0E /* create temporary file */ -#define SMBmknew 0x0F /* make new file */ -#define SMBchkpth 0x10 /* check directory path */ -#define SMBexit 0x11 /* process exit */ -#define SMBlseek 0x12 /* seek */ -#define SMBtcon 0x70 /* tree connect */ -#define SMBtconX 0x75 /* tree connect and X*/ -#define SMBtdis 0x71 /* tree disconnect */ -#define SMBnegprot 0x72 /* negotiate protocol */ -#define SMBdskattr 0x80 /* get disk attributes */ -#define SMBsearch 0x81 /* search directory */ -#define SMBsplopen 0xC0 /* open print spool file */ -#define SMBsplwr 0xC1 /* write to print spool file */ -#define SMBsplclose 0xC2 /* close print spool file */ -#define SMBsplretq 0xC3 /* return print queue */ -#define SMBsends 0xD0 /* send single block message */ -#define SMBsendb 0xD1 /* send broadcast message */ -#define SMBfwdname 0xD2 /* forward user name */ -#define SMBcancelf 0xD3 /* cancel forward */ -#define SMBgetmac 0xD4 /* get machine name */ -#define SMBsendstrt 0xD5 /* send start of multi-block message */ -#define SMBsendend 0xD6 /* send end of multi-block message */ -#define SMBsendtxt 0xD7 /* send text of multi-block message */ - -/* Core+ protocol */ -#define SMBlockread 0x13 /* Lock a range and read */ -#define SMBwriteunlock 0x14 /* Unlock a range then write */ -#define SMBreadbraw 0x1a /* read a block of data with no smb header */ -#define SMBwritebraw 0x1d /* write a block of data with no smb header */ -#define SMBwritec 0x20 /* secondary write request */ -#define SMBwriteclose 0x2c /* write a file then close it */ - -/* dos extended protocol */ -#define SMBreadBraw 0x1A /* read block raw */ -#define SMBreadBmpx 0x1B /* read block multiplexed */ -#define SMBreadBs 0x1C /* read block (secondary response) */ -#define SMBwriteBraw 0x1D /* write block raw */ -#define SMBwriteBmpx 0x1E /* write block multiplexed */ -#define SMBwriteBs 0x1F /* write block (secondary request) */ -#define SMBwriteC 0x20 /* write complete response */ -#define SMBsetattrE 0x22 /* set file attributes expanded */ -#define SMBgetattrE 0x23 /* get file attributes expanded */ -#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */ -#define SMBtrans 0x25 /* transaction - name, bytes in/out */ -#define SMBtranss 0x26 /* transaction (secondary request/response) */ -#define SMBioctl 0x27 /* IOCTL */ -#define SMBioctls 0x28 /* IOCTL (secondary request/response) */ -#define SMBcopy 0x29 /* copy */ -#define SMBmove 0x2A /* move */ -#define SMBecho 0x2B /* echo */ -#define SMBopenX 0x2D /* open and X */ -#define SMBreadX 0x2E /* read and X */ -#define SMBwriteX 0x2F /* write and X */ -#define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */ -#define SMBffirst 0x82 /* find first */ -#define SMBfunique 0x83 /* find unique */ -#define SMBfclose 0x84 /* find close */ -#define SMBinvalid 0xFE /* invalid command */ - -/* Extended 2.0 protocol */ -#define SMBtrans2 0x32 /* TRANS2 protocol set */ -#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */ -#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */ -#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */ -#define SMBulogoffX 0x74 /* user logoff */ - -/* NT SMB extensions. */ -#define SMBnttrans 0xA0 /* NT transact */ -#define SMBnttranss 0xA1 /* NT transact secondary */ -#define SMBntcreateX 0xA2 /* NT create and X */ -#define SMBntcancel 0xA4 /* NT cancel */ - -/* These are the TRANS2 sub commands */ -#define TRANSACT2_OPEN 0 -#define TRANSACT2_FINDFIRST 1 -#define TRANSACT2_FINDNEXT 2 -#define TRANSACT2_QFSINFO 3 -#define TRANSACT2_SETFSINFO 4 -#define TRANSACT2_QPATHINFO 5 -#define TRANSACT2_SETPATHINFO 6 -#define TRANSACT2_QFILEINFO 7 -#define TRANSACT2_SETFILEINFO 8 -#define TRANSACT2_FSCTL 9 -#define TRANSACT2_IOCTL 0xA -#define TRANSACT2_FINDNOTIFYFIRST 0xB -#define TRANSACT2_FINDNOTIFYNEXT 0xC -#define TRANSACT2_MKDIR 0xD -#define TRANSACT2_SESSION_SETUP 0xE -#define TRANSACT2_GET_DFS_REFERRAL 0x10 -#define TRANSACT2_REPORT_DFS_INCONSISTANCY 0x11 - -/* These are the NT transact sub commands. */ -#define NT_TRANSACT_CREATE 1 -#define NT_TRANSACT_IOCTL 2 -#define NT_TRANSACT_SET_SECURITY_DESC 3 -#define NT_TRANSACT_NOTIFY_CHANGE 4 -#define NT_TRANSACT_RENAME 5 -#define NT_TRANSACT_QUERY_SECURITY_DESC 6 - -/* these are the trans2 sub fields for primary requests */ -#define smb_tpscnt smb_vwv0 -#define smb_tdscnt smb_vwv1 -#define smb_mprcnt smb_vwv2 -#define smb_mdrcnt smb_vwv3 -#define smb_msrcnt smb_vwv4 -#define smb_flags smb_vwv5 -#define smb_timeout smb_vwv6 -#define smb_pscnt smb_vwv9 -#define smb_psoff smb_vwv10 -#define smb_dscnt smb_vwv11 -#define smb_dsoff smb_vwv12 -#define smb_suwcnt smb_vwv13 -#define smb_setup smb_vwv14 -#define smb_setup0 smb_setup -#define smb_setup1 (smb_setup+2) -#define smb_setup2 (smb_setup+4) - -/* these are for the secondary requests */ -#define smb_spscnt smb_vwv2 -#define smb_spsoff smb_vwv3 -#define smb_spsdisp smb_vwv4 -#define smb_sdscnt smb_vwv5 -#define smb_sdsoff smb_vwv6 -#define smb_sdsdisp smb_vwv7 -#define smb_sfid smb_vwv8 - -/* and these for responses */ -#define smb_tprcnt smb_vwv0 -#define smb_tdrcnt smb_vwv1 -#define smb_prcnt smb_vwv3 -#define smb_proff smb_vwv4 -#define smb_prdisp smb_vwv5 -#define smb_drcnt smb_vwv6 -#define smb_droff smb_vwv7 -#define smb_drdisp smb_vwv8 - -/* where to find the base of the SMB packet proper */ -#define smb_base(buf) (((char *)(buf))+4) - - -#define SUCCESS 0 /* The request was successful. */ -#define ERRDOS 0x01 /* Error is from the core DOS operating system set. */ -#define ERRSRV 0x02 /* Error is generated by the server network file manager.*/ -#define ERRHRD 0x03 /* Error is an hardware error. */ -#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ - -#ifdef __STDC__ -int Debug1(char *, ...); -#else -int Debug1(); -#endif - -#ifdef DFS_AUTH -void dfs_unlogin(void); -extern int dcelogin_atmost_once; -#endif - -#if AJT -void ajt_panic(void); -#endif - -#ifdef NOSTRDUP -char *strdup(char *s); -#endif - -#ifdef REPLACE_STRLEN -int Strlen(char *); -#endif - -#ifdef REPLACE_STRSTR -char *Strstr(char *s, char *p); -#endif - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -#ifndef ABS -#define ABS(a) ((a)>0?(a):(-(a))) -#endif - -#ifndef SIGNAL_CAST -#define SIGNAL_CAST -#endif - -#ifndef SELECT_CAST -#define SELECT_CAST -#endif - - -/* Some POSIX definitions for those without */ - -#ifndef S_IFDIR -#define S_IFDIR 0x4000 -#endif -#ifndef S_ISDIR -#define S_ISDIR(mode) ((mode & 0xF000) == S_IFDIR) -#endif -#ifndef S_IRWXU -#define S_IRWXU 00700 /* read, write, execute: owner */ -#endif -#ifndef S_IRUSR -#define S_IRUSR 00400 /* read permission: owner */ -#endif -#ifndef S_IWUSR -#define S_IWUSR 00200 /* write permission: owner */ -#endif -#ifndef S_IXUSR -#define S_IXUSR 00100 /* execute permission: owner */ -#endif -#ifndef S_IRWXG -#define S_IRWXG 00070 /* read, write, execute: group */ -#endif -#ifndef S_IRGRP -#define S_IRGRP 00040 /* read permission: group */ -#endif -#ifndef S_IWGRP -#define S_IWGRP 00020 /* write permission: group */ -#endif -#ifndef S_IXGRP -#define S_IXGRP 00010 /* execute permission: group */ -#endif -#ifndef S_IRWXO -#define S_IRWXO 00007 /* read, write, execute: other */ -#endif -#ifndef S_IROTH -#define S_IROTH 00004 /* read permission: other */ -#endif -#ifndef S_IWOTH -#define S_IWOTH 00002 /* write permission: other */ -#endif -#ifndef S_IXOTH -#define S_IXOTH 00001 /* execute permission: other */ -#endif - - -/* these are used in NetServerEnum to choose what to receive */ -#define SV_TYPE_WORKSTATION 0x00000001 -#define SV_TYPE_SERVER 0x00000002 -#define SV_TYPE_SQLSERVER 0x00000004 -#define SV_TYPE_DOMAIN_CTRL 0x00000008 -#define SV_TYPE_DOMAIN_BAKCTRL 0x00000010 -#define SV_TYPE_TIME_SOURCE 0x00000020 -#define SV_TYPE_AFP 0x00000040 -#define SV_TYPE_NOVELL 0x00000080 -#define SV_TYPE_DOMAIN_MEMBER 0x00000100 -#define SV_TYPE_PRINTQ_SERVER 0x00000200 -#define SV_TYPE_DIALIN_SERVER 0x00000400 -#define SV_TYPE_SERVER_UNIX 0x00000800 -#define SV_TYPE_NT 0x00001000 -#define SV_TYPE_WFW 0x00002000 -#define SV_TYPE_SERVER_MFPN 0x00004000 -#define SV_TYPE_SERVER_NT 0x00008000 -#define SV_TYPE_POTENTIAL_BROWSER 0x00010000 -#define SV_TYPE_BACKUP_BROWSER 0x00020000 -#define SV_TYPE_MASTER_BROWSER 0x00040000 -#define SV_TYPE_DOMAIN_MASTER 0x00080000 -#define SV_TYPE_SERVER_OSF 0x00100000 -#define SV_TYPE_SERVER_VMS 0x00200000 -#define SV_TYPE_WIN95_PLUS 0x00400000 -#define SV_TYPE_ALTERNATE_XPORT 0x20000000 -#define SV_TYPE_LOCAL_LIST_ONLY 0x40000000 -#define SV_TYPE_DOMAIN_ENUM 0x80000000 -#define SV_TYPE_ALL 0xFFFFFFFF - -/* what server type are we currently - JHT Says we ARE 4.20 */ -/* this was set by JHT in liaison with Jeremy Allison early 1997 */ -/* setting to 4.20 at same time as announcing ourselves as NT Server */ -/* History: */ -/* Version 4.0 - never made public */ -/* Version 4.10 - New to 1.9.16p2, lost in space 1.9.16p3 to 1.9.16p9 */ -/* - Reappeared in 1.9.16p11 with fixed smbd services */ -/* Version 4.20 - To indicate that nmbd and browsing now works better */ - -#define DEFAULT_MAJOR_VERSION 0x04 -#define DEFAULT_MINOR_VERSION 0x02 - -/* Browser Election Values */ -#define BROWSER_ELECTION_VERSION 0x010f -#define BROWSER_CONSTANT 0xaa55 - - -/* Capabilities. see ftp.microsoft.com/developr/drg/cifs/cifs/cifs4.txt */ - -#define CAP_RAW_MODE 0x0001 -#define CAP_MPX_MODE 0x0002 -#define CAP_UNICODE 0x0004 -#define CAP_LARGE_FILES 0x0008 -#define CAP_NT_SMBS 0x0010 -#define CAP_RPC_REMOTE_APIS 0x0020 -#define CAP_STATUS32 0x0040 -#define CAP_LEVEL_II_OPLOCKS 0x0080 -#define CAP_LOCK_AND_READ 0x0100 -#define CAP_NT_FIND 0x0200 -#define CAP_DFS 0x1000 -#define CAP_LARGE_READX 0x4000 - -/* protocol types. It assumes that higher protocols include lower protocols - as subsets */ -enum protocol_types {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL_LANMAN2,PROTOCOL_NT1}; - -/* security levels */ -enum security_types {SEC_SHARE,SEC_USER,SEC_SERVER}; - -/* printing types */ -enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX, - PRINT_QNX,PRINT_PLP,PRINT_LPRNG}; - -/* Remote architectures we know about. */ -enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_SAMBA}; - -/* case handling */ -enum case_handling {CASE_LOWER,CASE_UPPER}; - - -/* Macros to get at offsets within smb_lkrng and smb_unlkrng - structures. We cannot define these as actual structures - due to possible differences in structure packing - on different machines/compilers. */ - -#define SMB_LPID_OFFSET(indx) (10 * (indx)) -#define SMB_LKOFF_OFFSET(indx) ( 2 + (10 * (indx))) -#define SMB_LKLEN_OFFSET(indx) ( 6 + (10 * (indx))) - -/* Macro to cache an error in a write_bmpx_struct */ -#define CACHE_ERROR(w,c,e) ((w)->wr_errclass = (c), (w)->wr_error = (e), \ - w->wr_discard = True, -1) -/* Macro to test if an error has been cached for this fnum */ -#define HAS_CACHED_ERROR(fnum) (Files[(fnum)].open && \ - Files[(fnum)].wbmpx_ptr && \ - Files[(fnum)].wbmpx_ptr->wr_discard) -/* Macro to turn the cached error into an error packet */ -#define CACHED_ERROR(fnum) cached_error_packet(inbuf,outbuf,fnum,__LINE__) - -/* these are the datagram types */ -#define DGRAM_DIRECT_UNIQUE 0x10 - -#define ERROR(class,x) error_packet(inbuf,outbuf,class,x,__LINE__) - -/* this is how errors are generated */ -#define UNIXERROR(defclass,deferror) unix_error_packet(inbuf,outbuf,defclass,deferror,__LINE__) - -#define ROUNDUP(x,g) (((x)+((g)-1))&~((g)-1)) - -/* - * Global value meaing that the smb_uid field should be - * ingored (in share level security and protocol level == CORE) - */ - -#define UID_FIELD_INVALID 0 -#define VUID_OFFSET 100 /* Amount to bias returned vuid numbers */ - -#endif - -/* Defines needed for multi-codepage support. */ -#define KANJI_CODEPAGE 932 - -#ifdef KANJI -/* - * Default client code page - Japanese - */ -#define DEFAULT_CLIENT_CODE_PAGE KANJI_CODEPAGE -#else /* KANJI */ -/* - * Default client code page - 850 - Western European - */ -#define DEFAULT_CLIENT_CODE_PAGE 850 -#endif /* KANJI */ - -/* - * Size of buffer to use when moving files across filesystems. - */ -#define COPYBUF_SIZE (8*1024) - -/* - * Integers used to override error codes. - */ -extern int unix_ERR_class; -extern int unix_ERR_code; - -/* - * Map the Core and Extended Oplock requesst bits down - * to common bits (EXCLUSIVE_OPLOCK & BATCH_OPLOCK). - */ - -/* - * Core protocol. - */ -#define CORE_OPLOCK_REQUEST(inbuf) (((CVAL(inbuf,smb_flg)|(1<<5))>>5) | \ - ((CVAL(inbuf,smb_flg)|(1<<6))>>5)) - -/* - * Extended protocol. - */ -#define EXTENDED_OPLOCK_REQUEST(inbuf) (((SVAL(inbuf,smb_vwv2)|(1<<1))>>1) | \ - ((SVAL(inbuf,smb_vwv2)|(1<<2))>>1)) - -/* Lock types. */ -#define LOCKING_ANDX_SHARED_LOCK 0x1 -#define LOCKING_ANDX_OPLOCK_RELEASE 0x2 -#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x4 -#define LOCKING_ANDX_CANCEL_LOCK 0x8 -#define LOCKING_ANDX_LARGE_FILES 0x10 - -/* Oplock levels */ -#define OPLOCKLEVEL_NONE 0 -#define OPLOCKLEVEL_II 1 - -/* - * Bits we test with. - */ -#define EXCLUSIVE_OPLOCK 1 -#define BATCH_OPLOCK 2 - -#define CORE_OPLOCK_GRANTED (1<<5) -#define EXTENDED_OPLOCK_GRANTED (1<<15) - -/* - * Loopback command offsets. - */ - -#define UDP_CMD_LEN_OFFSET 0 -#define UDP_CMD_PORT_OFFSET 4 -#define UDP_CMD_HEADER_LEN 6 - -#define UDP_MESSAGE_CMD_OFFSET 0 - -/* - * Oplock break command code to send over the udp socket. - * - * Form of this is : - * - * 0 2 6 10 14 18 22 - * +----+--------+--------+--------+-------+--------+ - * | cmd| pid | dev | inode | sec | usec | - * +----+--------+--------+--------+-------+--------+ - */ - -#define OPLOCK_BREAK_CMD 0x1 -#define OPLOCK_BREAK_PID_OFFSET 2 -#define OPLOCK_BREAK_DEV_OFFSET 6 -#define OPLOCK_BREAK_INODE_OFFSET 10 -#define OPLOCK_BREAK_SEC_OFFSET 14 -#define OPLOCK_BREAK_USEC_OFFSET 18 -#define OPLOCK_BREAK_MSG_LEN 22 - - -#define CMD_REPLY 0x8000 - -/* _SMB_H */ diff --git a/source/include/trans2.h b/source/include/trans2.h deleted file mode 100644 index 9a2de631095..00000000000 --- a/source/include/trans2.h +++ /dev/null @@ -1,251 +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_INFO_STANDARD 1 -#define SMB_INFO_QUERY_EA_SIZE 2 -#define SMB_INFO_QUERY_EAS_FROM_LIST 3 -#define SMB_INFO_QUERY_ALL_EAS 4 -#define SMB_INFO_IS_NAME_VALID 6 -#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 33c9d240baf..00000000000 --- a/source/include/version.h +++ /dev/null @@ -1 +0,0 @@ -#define VERSION "1.9.18alpha1" 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 c338517ed67..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,("%s Denied connection from %s (%s) to %s\n", - timestring(), 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 a7dff4224be..00000000000 --- a/source/lib/charcnv.c +++ /dev/null @@ -1,164 +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(lp_client_code_page() == KANJI_CODEPAGE) - return (*_unix_to_dos)(str, overwrite); - else { - 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(lp_client_code_page() == KANJI_CODEPAGE) - return (*_dos_to_unix)(str, overwrite); - else { - 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 4869e09fecf..00000000000 --- a/source/lib/charset.c +++ /dev/null @@ -1,383 +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. - */ - -#if !defined(KANJI) -/* 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} -}; -#else /* KANJI */ -/* lower->upper mapping for IBM Code Page 932 - MS-DOS Japanese SJIS */ -unsigned char cp_932[][4] = { - {0,0,0,0} -}; -#endif /* KANJI */ - -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 i; - -#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,False,0,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); - } -} - -/**************************************************************************** -load the client codepage. -****************************************************************************/ - -typedef unsigned char (*codepage_p)[4]; - -static codepage_p load_client_codepage( int client_codepage ) -{ - pstring codepage_file_name; - unsigned char buf[8]; - FILE *fp = NULL; - unsigned int size; - codepage_p cp_p = NULL; - struct stat st; - - DEBUG(5, ("load_client_codepage: loading codepage %d.\n", client_codepage)); - - if(strlen(CODEPAGEDIR) + 14 > sizeof(codepage_file_name)) - { - DEBUG(0,("load_client_codepage: filename too long to load\n")); - return NULL; - } - - strcpy(codepage_file_name, CODEPAGEDIR); - strcat(codepage_file_name, "/"); - strcat(codepage_file_name, "codepage."); - sprintf( &codepage_file_name[strlen(codepage_file_name)], "%03d", - client_codepage); - - if(!file_exist(codepage_file_name,&st)) - { - DEBUG(0,("load_client_codepage: filename %s does not exist.\n", - codepage_file_name)); - return NULL; - } - - /* Check if it is at least big enough to hold the required - data. Should be 2 byte version, 2 byte codepage, 4 byte length, - plus zero or more bytes of data. Note that the data cannot be more - than 512 bytes - giving a max size of 520. - */ - size = (unsigned int)st.st_size; - - if( size < CODEPAGE_HEADER_SIZE || size > (CODEPAGE_HEADER_SIZE + 256)) - { - DEBUG(0,("load_client_codepage: file %s is an incorrect size for a \ -code page file.\n", codepage_file_name)); - return NULL; - } - - /* Read the first 8 bytes of the codepage file - check - the version number and code page number. All the data - is held in little endian format. - */ - - if((fp = fopen( codepage_file_name, "r")) == NULL) - { - DEBUG(0,("load_client_codepage: cannot open file %s. Error was %s\n", - codepage_file_name, strerror(errno))); - return NULL; - } - - if(fread( buf, 1, CODEPAGE_HEADER_SIZE, fp)!=CODEPAGE_HEADER_SIZE) - { - DEBUG(0,("load_client_codepage: cannot read header from file %s. Error was %s\n", - codepage_file_name, strerror(errno))); - goto clean_and_exit; - } - - /* Check the version value */ - if(SVAL(buf,CODEPAGE_VERSION_OFFSET) != CODEPAGE_FILE_VERSION_ID) - { - DEBUG(0,("load_client_codepage: filename %s has incorrect version id. \ -Needed %hu, got %hu.\n", - codepage_file_name, (uint16)CODEPAGE_FILE_VERSION_ID, - SVAL(buf,CODEPAGE_VERSION_OFFSET))); - goto clean_and_exit; - } - - /* Check the codepage matches */ - if(SVAL(buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET) != (uint16)client_codepage) - { - DEBUG(0,("load_client_codepage: filename %s has incorrect codepage. \ -Needed %hu, got %hu.\n", - codepage_file_name, (uint16)client_codepage, - SVAL(buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET))); - goto clean_and_exit; - } - - /* Check the length is correct. */ - if(IVAL(buf,CODEPAGE_LENGTH_OFFSET) != - (unsigned int)(size - CODEPAGE_HEADER_SIZE)) - { - DEBUG(0,("load_client_codepage: filename %s has incorrect size headers. \ -Needed %u, got %u.\n", codepage_file_name, size - CODEPAGE_HEADER_SIZE, - IVAL(buf,CODEPAGE_LENGTH_OFFSET))); - goto clean_and_exit; - } - - size -= CODEPAGE_HEADER_SIZE; /* Remove header */ - - /* Make sure the size is a multiple of 4. */ - if((size % 4 ) != 0) - { - DEBUG(0,("load_client_codepage: filename %s has a codepage size not a \ -multiple of 4.\n", codepage_file_name)); - goto clean_and_exit; - } - - /* Allocate space for the code page file and read it all in. */ - if((cp_p = (codepage_p)malloc( size + 4 )) == NULL) - { - DEBUG(0,("load_client_codepage: malloc fail.\n")); - goto clean_and_exit; - } - - if(fread( (char *)cp_p, 1, size, fp)!=size) - { - DEBUG(0,("load_client_codepage: read fail on file %s. Error was %s.\n", - codepage_file_name, strerror(errno))); - goto clean_and_exit; - } - - /* Ensure array is correctly terminated. */ - memset(((char *)cp_p) + size, '\0', 4); - - fclose(fp); - return cp_p; - -clean_and_exit: - - /* pseudo destructor :-) */ - - if(fp != NULL) - fclose(fp); - if(cp_p) - free((char *)cp_p); - return NULL; -} - -/**************************************************************************** -initialise the client codepage. -****************************************************************************/ -void codepage_initialise(int client_codepage) -{ - int i; - codepage_p cp = NULL; - static BOOL done = False; - - if(done == True) - { - DEBUG(6, - ("codepage_initialise: called twice - ignoring second client code page = %d\n", - client_codepage)); - return; - } - - DEBUG(6,("codepage_initialise: client code page = %d\n", client_codepage)); - - /* - * Known client codepages - these can be added to. - */ - cp = load_client_codepage( client_codepage ); - - if(cp == NULL) - { -#ifdef KANJI - DEBUG(6,("codepage_initialise: loading dynamic codepage file %s/codepage.%d \ -for code page %d failed. Using default client codepage 932\n", - CODEPAGEDIR, client_codepage, client_codepage)); - cp = cp_932; -#else /* KANJI */ - DEBUG(6,("codepage_initialise: loading dynamic codepage file %s/codepage.%d \ -for code page %d failed. Using default client codepage 850\n", - CODEPAGEDIR, client_codepage, client_codepage)); - cp = cp_850; -#endif /* KANJI */ - } - - 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]); - } - - done = True; -} - -/******************************************************************* -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((unsigned char)*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((unsigned char)c1,True,(unsigned char)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 e8cb683d0b1..00000000000 --- a/source/lib/getsmbpass.c +++ /dev/null @@ -1,165 +0,0 @@ -/* Copyright (C) 1992-1997 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, 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, 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 147425d0fc1..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) || defined(_AIX41) - 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(2,("Added interface ip=%s ",inet_ntoa(iface->ip))); - DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); - DEBUG(2,("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 5d7de87248d..00000000000 --- a/source/lib/kanji.c +++ /dev/null @@ -1,868 +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> -*/ - -#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, 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(char *s1, char *s2) -{ - 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 (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(char *s, int c) -{ - 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 (int hi, 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 (int hi, 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(char *from, BOOL overwrite) -{ - 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(char *from, BOOL overwrite) -{ - 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(int hi, 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(int hi, 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(char *from, BOOL overwrite) -{ - char *out; - 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(char *from, BOOL overwrite) -{ - char *out; - 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(char *from, BOOL overwrite) -{ - char *out; - 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(char *from, BOOL overwrite) -{ - char *out; - 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(char *from, BOOL overwrite) -{ - char *out; - 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(char *from, BOOL overwrite) -{ - char *out; - 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(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(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(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(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)(char *str, BOOL overwrite) = sj_to_sj; -char *(*_unix_to_dos)(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); -} diff --git a/source/lib/md4.c b/source/lib/md4.c deleted file mode 100644 index 1c9c2e6ecd5..00000000000 --- a/source/lib/md4.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - a implementation of MD4 designed for use in the SMB authentication protocol - Copyright (C) Andrew Tridgell 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. -*/ - - -/* NOTE: This code makes no attempt to be fast! - - It assumes that a int is at least 32 bits long -*/ - -typedef unsigned int uint32; - -static uint32 A, B, C, D; - -static uint32 F(uint32 X, uint32 Y, uint32 Z) -{ - return (X&Y) | ((~X)&Z); -} - -static uint32 G(uint32 X, uint32 Y, uint32 Z) -{ - return (X&Y) | (X&Z) | (Y&Z); -} - -static uint32 H(uint32 X, uint32 Y, uint32 Z) -{ - return X^Y^Z; -} - -static uint32 lshift(uint32 x, int s) -{ - x &= 0xFFFFFFFF; - return ((x<<s)&0xFFFFFFFF) | (x>>(32-s)); -} - -#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) -#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) -#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) - -/* this applies md4 to 64 byte chunks */ -static void mdfour64(uint32 *M) -{ - int j; - uint32 AA, BB, CC, DD; - uint32 X[16]; - - for (j=0;j<16;j++) - X[j] = M[j]; - - AA = A; BB = B; CC = C; DD = D; - - ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); - ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19); - ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); - ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19); - ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); - ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19); - ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); - ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); - - ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); - ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13); - ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); - ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13); - ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); - ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13); - ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); - ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13); - - ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); - ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15); - ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); - ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15); - ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); - ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15); - ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); - ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15); - - A += AA; B += BB; C += CC; D += DD; - - A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; - C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; - - for (j=0;j<16;j++) - X[j] = 0; -} - -static void copy64(uint32 *M, unsigned char *in) -{ - int i; - - for (i=0;i<16;i++) - M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | - (in[i*4+1]<<8) | (in[i*4+0]<<0); -} - -static void copy4(unsigned char *out,uint32 x) -{ - out[0] = x&0xFF; - out[1] = (x>>8)&0xFF; - out[2] = (x>>16)&0xFF; - out[3] = (x>>24)&0xFF; -} - -/* produce a md4 message digest from data of length n bytes */ -void mdfour(unsigned char *out, unsigned char *in, int n) -{ - unsigned char buf[128]; - uint32 M[16]; - uint32 b = n * 8; - int i; - - A = 0x67452301; - B = 0xefcdab89; - C = 0x98badcfe; - D = 0x10325476; - - while (n > 64) { - copy64(M, in); - mdfour64(M); - in += 64; - n -= 64; - } - - for (i=0;i<128;i++) - buf[i] = 0; - memcpy(buf, in, n); - buf[n] = 0x80; - - if (n <= 55) { - copy4(buf+56, b); - copy64(M, buf); - mdfour64(M); - } else { - copy4(buf+120, b); - copy64(M, buf); - mdfour64(M); - copy64(M, buf+64); - mdfour64(M); - } - - for (i=0;i<128;i++) - buf[i] = 0; - copy64(M, buf); - - copy4(out, A); - copy4(out+4, B); - copy4(out+8, C); - copy4(out+12, D); - - A = B = C = D = 0; -} - - 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 fe8e8004d04..00000000000 --- a/source/lib/system.c +++ /dev/null @@ -1,413 +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(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; - - pstrcpy (zfrom, dos_to_unix (from, False)); - pstrcpy (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)); -} - -/******************************************************************* -for getwd -********************************************************************/ -char *sys_getwd(char *s) -{ - char *wd; -#ifdef USE_GETCWD - wd = (char *) getcwd (s, sizeof (pstring)); -#else - wd = (char *) getwd (s); -#endif - if (wd) - unix_to_dos (wd, True); - return wd; -} - -/******************************************************************* -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) -{ -#ifdef REDUCE_ROOT_DNS_LOOKUPS - 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)); -#else /* REDUCE_ROOT_DNS_LOOKUPS */ - return(gethostbyname(name)); -#endif /* REDUCE_ROOT_DNS_LOOKUPS */ -} - diff --git a/source/lib/time.c b/source/lib/time.c deleted file mode 100644 index 4f688d2214a..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 fstring TimeBuf; - time_t t = time(NULL); - struct tm *tm = LocalTime(&t); - -#ifdef NO_STRFTIME - fstrcpy(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 0fa5cfd3a0f..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-1997, 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 a9f64259916..00000000000 --- a/source/lib/username.c +++ /dev/null @@ -1,324 +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; - -/* internal functions - modified versions of the ones in password.c */ -static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (), int N); -static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (), int N); - -/**************************************************************************** -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)); - fstrcpy(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; - int last_char; - int usernamelevel = lp_usernamelevel(); - - 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); - - /* try with last letter capitalised */ - strlower(user); - last_char = strlen(user)-1; - user[last_char] = toupper(user[last_char]); - DEBUG(3, ("Trying username %s\n", user)); - ret = _Get_Pwnam(user); - if (ret) return(ret); - - /* try all combinations up to usernamelevel */ - strlower(user); - ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel); - if (ret) return(ret); - - if (allow_change) - fstrcpy(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); -} - -/* The functions below have been taken from password.c and slightly modified */ -/**************************************************************************** -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 struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(),int N) -{ - int len = strlen(s); - int i; - struct passwd *ret; - -#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); - ret = uname_string_combinations2(s,i+1,fn,N-1); - if(ret) return(ret); - s[i] = c; - } - return(NULL); -} - -/**************************************************************************** -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 struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(),int N) -{ - int n; - struct passwd *ret; - - for (n=1;n<=N;n++) - { - ret = uname_string_combinations2(s,0,fn,n); - if(ret) return(ret); - } - return(NULL); -} diff --git a/source/lib/util.c b/source/lib/util.c deleted file mode 100644 index 4e6bfb7054a..00000000000 --- a/source/lib/util.c +++ /dev/null @@ -1,4392 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Samba utility 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" - -pstring scope = ""; - -int DEBUGLEVEL = 1; - -BOOL passive = False; - -int Protocol = PROTOCOL_COREPLUS; - -/* a default finfo structure to ensure all fields are sensible */ -file_info def_finfo = {-1,0,0,0,0,0,0,""}; - -/* these are some file handles where debug info will be stored */ -FILE *dbf = NULL; - -/* the client file descriptor */ -int Client = -1; - -/* the last IP received from */ -struct in_addr lastip; - -/* the last port received from */ -int lastport=0; - -/* this is used by the chaining code */ -int chain_size = 0; - -int trans_num = 0; - -/* - case handling on filenames -*/ -int case_default = CASE_LOWER; - -pstring debugf = ""; -int syslog_level; - -/* the following control case operations - they are put here so the - client can link easily */ -BOOL case_sensitive; -BOOL case_preserve; -BOOL use_mangled_map = False; -BOOL short_case_preserve; -BOOL case_mangle; - -fstring remote_machine=""; -fstring local_machine=""; -fstring remote_arch="UNKNOWN"; -static enum remote_arch_types ra_type = RA_UNKNOWN; -fstring remote_proto="UNKNOWN"; -pstring myhostname=""; -pstring user_socket_options=""; -pstring sesssetup_user=""; -pstring myname = ""; -fstring myworkgroup = ""; -char **my_netbios_names; - -int smb_read_error = 0; - -static BOOL stdout_logging = False; - -static char *filename_dos(char *path,char *buf); - -/******************************************************************* - get ready for syslog stuff - ******************************************************************/ -void setup_logging(char *pname,BOOL interactive) -{ -#ifdef SYSLOG - if (!interactive) { - char *p = strrchr(pname,'/'); - if (p) pname = p+1; -#ifdef LOG_DAEMON - openlog(pname, LOG_PID, LOG_DAEMON); -#else /* LOG_DAEMON - for old systems that have no facility codes. */ - openlog(pname, LOG_PID); -#endif /* LOG_DAEMON */ - } -#endif - if (interactive) { - stdout_logging = True; - dbf = stdout; - } -} - - -BOOL append_log=False; - - -/**************************************************************************** -reopen the log files -****************************************************************************/ -void reopen_logs(void) -{ - extern FILE *dbf; - pstring fname; - - if (DEBUGLEVEL > 0) - { - strcpy(fname,debugf); - if (lp_loaded() && (*lp_logfile())) - strcpy(fname,lp_logfile()); - - if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL)) - { - int oldumask = umask(022); - strcpy(debugf,fname); - if (dbf) fclose(dbf); - if (append_log) - dbf = fopen(debugf,"a"); - else - dbf = fopen(debugf,"w"); - if (dbf) setbuf(dbf,NULL); - umask(oldumask); - } - } - else - { - if (dbf) - { - fclose(dbf); - dbf = NULL; - } - } -} - - -/******************************************************************* -check if the log has grown too big -********************************************************************/ -static void check_log_size(void) -{ - static int debug_count=0; - int maxlog; - struct stat st; - - if (debug_count++ < 100 || getuid() != 0) return; - - maxlog = lp_max_log_size() * 1024; - if (!dbf || maxlog <= 0) return; - - if (fstat(fileno(dbf),&st) == 0 && st.st_size > maxlog) { - fclose(dbf); dbf = NULL; - reopen_logs(); - if (dbf && file_size(debugf) > maxlog) { - pstring name; - fclose(dbf); dbf = NULL; - sprintf(name,"%s.old",debugf); - sys_rename(debugf,name); - reopen_logs(); - } - } - debug_count=0; -} - - -/******************************************************************* -write an debug message on the debugfile. This is called by the DEBUG -macro -********************************************************************/ -#ifdef __STDC__ - int Debug1(char *format_str, ...) -{ -#else - int Debug1(va_alist) -va_dcl -{ - char *format_str; -#endif - va_list ap; - int old_errno = errno; - - if (stdout_logging) { -#ifdef __STDC__ - va_start(ap, format_str); -#else - va_start(ap); - format_str = va_arg(ap,char *); -#endif - vfprintf(dbf,format_str,ap); - va_end(ap); - errno = old_errno; - return(0); - } - -#ifdef SYSLOG - if (!lp_syslog_only()) -#endif - { - if (!dbf) { - int oldumask = umask(022); - dbf = fopen(debugf,"w"); - umask(oldumask); - if (dbf) { - setbuf(dbf,NULL); - } else { - errno = old_errno; - return(0); - } - } - } - -#ifdef SYSLOG - if (syslog_level < lp_syslog()) - { - /* - * map debug levels to syslog() priorities - * note that not all DEBUG(0, ...) calls are - * necessarily errors - */ - static int priority_map[] = { - LOG_ERR, /* 0 */ - LOG_WARNING, /* 1 */ - LOG_NOTICE, /* 2 */ - LOG_INFO, /* 3 */ - }; - int priority; - pstring msgbuf; - - if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) || - syslog_level < 0) - priority = LOG_DEBUG; - else - priority = priority_map[syslog_level]; - -#ifdef __STDC__ - va_start(ap, format_str); -#else - va_start(ap); - format_str = va_arg(ap,char *); -#endif - vsprintf(msgbuf, format_str, ap); - va_end(ap); - - msgbuf[255] = '\0'; - syslog(priority, "%s", msgbuf); - } -#endif - -#ifdef SYSLOG - if (!lp_syslog_only()) -#endif - { -#ifdef __STDC__ - va_start(ap, format_str); -#else - va_start(ap); - format_str = va_arg(ap,char *); -#endif - vfprintf(dbf,format_str,ap); - va_end(ap); - fflush(dbf); - } - - check_log_size(); - - errno = old_errno; - - return(0); -} - -/**************************************************************************** - find a suitable temporary directory. The result should be copied immediately - as it may be overwritten by a subsequent call - ****************************************************************************/ -char *tmpdir(void) -{ - char *p; - if ((p = getenv("TMPDIR"))) { - return p; - } - return "/tmp"; -} - - - -/**************************************************************************** -determine if a file descriptor is in fact a socket -****************************************************************************/ -BOOL is_a_socket(int fd) -{ - int v,l; - l = sizeof(int); - return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0); -} - - -static char *last_ptr=NULL; - -/**************************************************************************** - Get the next token from a string, return False if none found - handles double-quotes. -Based on a routine by GJC@VILLAGE.COM. -Extensively modified by Andrew.Tridgell@anu.edu.au -****************************************************************************/ -BOOL next_token(char **ptr,char *buff,char *sep) -{ - char *s; - BOOL quoted; - - if (!ptr) ptr = &last_ptr; - if (!ptr) return(False); - - s = *ptr; - - /* default to simple separators */ - if (!sep) sep = " \t\n\r"; - - /* find the first non sep char */ - while(*s && strchr(sep,*s)) s++; - - /* nothing left? */ - if (! *s) return(False); - - /* copy over the token */ - for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++) - { - if (*s == '\"') - quoted = !quoted; - else - *buff++ = *s; - } - - *ptr = (*s) ? s+1 : s; - *buff = 0; - last_ptr = *ptr; - - return(True); -} - -/**************************************************************************** -Convert list of tokens to array; dependent on above routine. -Uses last_ptr from above - bit of a hack. -****************************************************************************/ -char **toktocliplist(int *ctok, char *sep) -{ - char *s=last_ptr; - int ictok=0; - char **ret, **iret; - - if (!sep) sep = " \t\n\r"; - - while(*s && strchr(sep,*s)) s++; - - /* nothing left? */ - if (!*s) return(NULL); - - do { - ictok++; - while(*s && (!strchr(sep,*s))) s++; - while(*s && strchr(sep,*s)) *s++=0; - } while(*s); - - *ctok=ictok; - s=last_ptr; - - if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL; - - while(ictok--) { - *iret++=s; - while(*s++); - while(!*s) s++; - } - - return ret; -} - -#ifndef HAVE_MEMMOVE -/******************************************************************* -safely copies memory, ensuring no overlap problems. -this is only used if the machine does not have it's own memmove(). -this is not the fastest algorithm in town, but it will do for our -needs. -********************************************************************/ -void *MemMove(void *dest,void *src,int size) -{ - unsigned long d,s; - int i; - if (dest==src || !size) return(dest); - - d = (unsigned long)dest; - s = (unsigned long)src; - - if ((d >= (s+size)) || (s >= (d+size))) { - /* no overlap */ - memcpy(dest,src,size); - return(dest); - } - - if (d < s) - { - /* we can forward copy */ - if (s-d >= sizeof(int) && - !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=0;i<size;i++) idest[i] = isrc[i]; - } else { - /* simplest */ - char *cdest = (char *)dest; - char *csrc = (char *)src; - for (i=0;i<size;i++) cdest[i] = csrc[i]; - } - } - else - { - /* must backward copy */ - if (d-s >= sizeof(int) && - !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=size-1;i>=0;i--) idest[i] = isrc[i]; - } else { - /* simplest */ - char *cdest = (char *)dest; - char *csrc = (char *)src; - for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; - } - } - return(dest); -} -#endif - - -/**************************************************************************** -prompte a dptr (to make it recently used) -****************************************************************************/ -void array_promote(char *array,int elsize,int element) -{ - char *p; - if (element == 0) - return; - - p = (char *)malloc(elsize); - - if (!p) - { - DEBUG(5,("Ahh! Can't malloc\n")); - return; - } - memcpy(p,array + element * elsize, elsize); - memmove(array + elsize,array,elsize*element); - memcpy(array,p,elsize); - free(p); -} - -enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON}; - -struct -{ - char *name; - int level; - int option; - int value; - int opttype; -} socket_options[] = { - {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL}, - {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL}, - {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL}, -#ifdef TCP_NODELAY - {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL}, -#endif -#ifdef IPTOS_LOWDELAY - {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON}, -#endif -#ifdef IPTOS_THROUGHPUT - {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON}, -#endif -#ifdef SO_SNDBUF - {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT}, -#endif -#ifdef SO_RCVBUF - {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT}, -#endif -#ifdef SO_SNDLOWAT - {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT}, -#endif -#ifdef SO_RCVLOWAT - {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT}, -#endif -#ifdef SO_SNDTIMEO - {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT}, -#endif -#ifdef SO_RCVTIMEO - {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT}, -#endif - {NULL,0,0,0,0}}; - - - -/**************************************************************************** -set user socket options -****************************************************************************/ -void set_socket_options(int fd, char *options) -{ - string tok; - - while (next_token(&options,tok," \t,")) - { - int ret=0,i; - int value = 1; - char *p; - BOOL got_value = False; - - if ((p = strchr(tok,'='))) - { - *p = 0; - value = atoi(p+1); - got_value = True; - } - - for (i=0;socket_options[i].name;i++) - if (strequal(socket_options[i].name,tok)) - break; - - if (!socket_options[i].name) - { - DEBUG(0,("Unknown socket option %s\n",tok)); - continue; - } - - switch (socket_options[i].opttype) - { - case OPT_BOOL: - case OPT_INT: - ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option,(char *)&value,sizeof(int)); - break; - - case OPT_ON: - if (got_value) - DEBUG(0,("syntax error - %s does not take a value\n",tok)); - - { - int on = socket_options[i].value; - ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option,(char *)&on,sizeof(int)); - } - break; - } - - if (ret != 0) - DEBUG(0,("Failed to set socket option %s\n",tok)); - } -} - - - -/**************************************************************************** - close the socket communication -****************************************************************************/ -void close_sockets(void ) -{ - close(Client); - Client = 0; -} - -/**************************************************************************** -determine whether we are in the specified group -****************************************************************************/ -BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups) -{ - int i; - - if (group == current_gid) return(True); - - for (i=0;i<ngroups;i++) - if (group == groups[i]) - return(True); - - return(False); -} - -/**************************************************************************** -this is a safer strcpy(), meant to prevent core dumps when nasty things happen -****************************************************************************/ -char *StrCpy(char *dest,char *src) -{ - char *d = dest; - -#if AJT - /* I don't want to get lazy with these ... */ - if (!dest || !src) { - DEBUG(0,("ERROR: NULL StrCpy() called!\n")); - ajt_panic(); - } -#endif - - if (!dest) return(NULL); - if (!src) { - *dest = 0; - return(dest); - } - while ((*d++ = *src++)) ; - return(dest); -} - -/**************************************************************************** -line strncpy but always null terminates. Make sure there is room! -****************************************************************************/ -char *StrnCpy(char *dest,char *src,int n) -{ - char *d = dest; - if (!dest) return(NULL); - if (!src) { - *dest = 0; - return(dest); - } - while (n-- && (*d++ = *src++)) ; - *d = 0; - return(dest); -} - - -/******************************************************************* -copy an IP address from one buffer to another -********************************************************************/ -void putip(void *dest,void *src) -{ - memcpy(dest,src,4); -} - - -/**************************************************************************** -interpret the weird netbios "name". Return the name type -****************************************************************************/ -static int name_interpret(char *in,char *out) -{ - int ret; - int len = (*in++) / 2; - - *out=0; - - if (len > 30 || len<1) return(0); - - while (len--) - { - if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') { - *out = 0; - return(0); - } - *out = ((in[0]-'A')<<4) + (in[1]-'A'); - in += 2; - out++; - } - *out = 0; - ret = out[-1]; - -#ifdef NETBIOS_SCOPE - /* Handle any scope names */ - while(*in) - { - *out++ = '.'; /* Scope names are separated by periods */ - len = *(unsigned char *)in++; - StrnCpy(out, in, len); - out += len; - *out=0; - in += len; - } -#endif - return(ret); -} - -/**************************************************************************** -mangle a name into netbios format - - Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum. -****************************************************************************/ -int name_mangle( char *In, char *Out, char name_type ) - { - int i; - int c; - int len; - char buf[20]; - char *p = Out; - - /* Safely copy the input string, In, into buf[]. */ - (void)memset( buf, 0, 20 ); - if( '*' == In[0] ) - buf[0] = '*'; - else - (void)sprintf( buf, "%-15.15s%c", In, name_type ); - - /* Place the length of the first field into the output buffer. */ - p[0] = 32; - p++; - - /* Now convert the name to the rfc1001/1002 format. */ - for( i = 0; i < 16; i++ ) - { - c = toupper( buf[i] ); - p[i*2] = ( (c >> 4) & 0x000F ) + 'A'; - p[(i*2)+1] = (c & 0x000F) + 'A'; - } - p += 32; - p[0] = '\0'; - - /* Add the scope string. */ - for( i = 0, len = 0; NULL != scope; i++, len++ ) - { - switch( scope[i] ) - { - case '\0': - p[0] = len; - if( len > 0 ) - p[len+1] = 0; - return( name_len(Out) ); - case '.': - p[0] = len; - p += (len + 1); - len = 0; - break; - default: - p[len+1] = scope[i]; - break; - } - } - - return( name_len(Out) ); - } /* name_mangle */ - -/******************************************************************* - check if a file exists -********************************************************************/ -BOOL file_exist(char *fname,struct stat *sbuf) -{ - struct stat st; - if (!sbuf) sbuf = &st; - - if (sys_stat(fname,sbuf) != 0) - return(False); - - return(S_ISREG(sbuf->st_mode)); -} - -/******************************************************************* -check a files mod time -********************************************************************/ -time_t file_modtime(char *fname) -{ - struct stat st; - - if (sys_stat(fname,&st) != 0) - return(0); - - return(st.st_mtime); -} - -/******************************************************************* - check if a directory exists -********************************************************************/ -BOOL directory_exist(char *dname,struct stat *st) -{ - struct stat st2; - BOOL ret; - - if (!st) st = &st2; - - if (sys_stat(dname,st) != 0) - return(False); - - ret = S_ISDIR(st->st_mode); - if(!ret) - errno = ENOTDIR; - return ret; -} - -/******************************************************************* -returns the size in bytes of the named file -********************************************************************/ -uint32 file_size(char *file_name) -{ - struct stat buf; - buf.st_size = 0; - sys_stat(file_name,&buf); - return(buf.st_size); -} - -/******************************************************************* -return a string representing an attribute for a file -********************************************************************/ -char *attrib_string(int mode) -{ - static char attrstr[10]; - - attrstr[0] = 0; - - if (mode & aVOLID) strcat(attrstr,"V"); - if (mode & aDIR) strcat(attrstr,"D"); - if (mode & aARCH) strcat(attrstr,"A"); - if (mode & aHIDDEN) strcat(attrstr,"H"); - if (mode & aSYSTEM) strcat(attrstr,"S"); - if (mode & aRONLY) strcat(attrstr,"R"); - - return(attrstr); -} - - -/******************************************************************* - case insensitive string compararison -********************************************************************/ -int StrCaseCmp(char *s, char *t) -{ - /* compare until we run out of string, either t or s, or find a difference */ - /* We *must* use toupper rather than tolower here due to the - asynchronous upper to lower mapping. - */ -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - int diff; - for (;;) - { - if (!*s || !*t) - return toupper (*s) - toupper (*t); - else if (is_sj_alph (*s) && is_sj_alph (*t)) - { - diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1)); - if (diff) - return diff; - s += 2; - t += 2; - } - else if (is_shift_jis (*s) && is_shift_jis (*t)) - { - diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t); - if (diff) - return diff; - diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1)); - if (diff) - return diff; - s += 2; - t += 2; - } - else if (is_shift_jis (*s)) - return 1; - else if (is_shift_jis (*t)) - return -1; - else - { - diff = toupper (*s) - toupper (*t); - if (diff) - return diff; - s++; - t++; - } - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - while (*s && *t && toupper(*s) == toupper(*t)) - { - s++; - t++; - } - - return(toupper(*s) - toupper(*t)); - } -} - -/******************************************************************* - case insensitive string compararison, length limited -********************************************************************/ -int StrnCaseCmp(char *s, char *t, int n) -{ - /* compare until we run out of string, either t or s, or chars */ - /* We *must* use toupper rather than tolower here due to the - asynchronous upper to lower mapping. - */ -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - int diff; - for (;n > 0;) - { - if (!*s || !*t) - return toupper (*s) - toupper (*t); - else if (is_sj_alph (*s) && is_sj_alph (*t)) - { - diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1)); - if (diff) - return diff; - s += 2; - t += 2; - n -= 2; - } - else if (is_shift_jis (*s) && is_shift_jis (*t)) - { - diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t); - if (diff) - return diff; - diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1)); - if (diff) - return diff; - s += 2; - t += 2; - n -= 2; - } - else if (is_shift_jis (*s)) - return 1; - else if (is_shift_jis (*t)) - return -1; - else - { - diff = toupper (*s) - toupper (*t); - if (diff) - return diff; - s++; - t++; - n--; - } - } - return 0; - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - while (n-- && *s && *t && toupper(*s) == toupper(*t)) - { - s++; - t++; - } - - /* not run out of chars - strings are different lengths */ - if (n) - return(toupper(*s) - toupper(*t)); - - /* identical up to where we run out of chars, - and strings are same length */ - return(0); - } -} - -/******************************************************************* - compare 2 strings -********************************************************************/ -BOOL strequal(char *s1, char *s2) -{ - if (s1 == s2) return(True); - if (!s1 || !s2) return(False); - - return(StrCaseCmp(s1,s2)==0); -} - -/******************************************************************* - compare 2 strings up to and including the nth char. - ******************************************************************/ -BOOL strnequal(char *s1,char *s2,int n) -{ - if (s1 == s2) return(True); - if (!s1 || !s2 || !n) return(False); - - return(StrnCaseCmp(s1,s2,n)==0); -} - -/******************************************************************* - compare 2 strings (case sensitive) -********************************************************************/ -BOOL strcsequal(char *s1,char *s2) -{ - if (s1 == s2) return(True); - if (!s1 || !s2) return(False); - - return(strcmp(s1,s2)==0); -} - - -/******************************************************************* - convert a string to lower case -********************************************************************/ -void strlower(char *s) -{ - while (*s) - { -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - if (is_shift_jis (*s)) - { - if (is_sj_upper (s[0], s[1])) - s[1] = sj_tolower2 (s[1]); - s += 2; - } - else if (is_kana (*s)) - { - s++; - } - else - { - if (isupper(*s)) - *s = tolower(*s); - s++; - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - if (isupper(*s)) - *s = tolower(*s); - s++; - } - } -} - -/******************************************************************* - convert a string to upper case -********************************************************************/ -void strupper(char *s) -{ - while (*s) - { -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - if (is_shift_jis (*s)) - { - if (is_sj_lower (s[0], s[1])) - s[1] = sj_toupper2 (s[1]); - s += 2; - } - else if (is_kana (*s)) - { - s++; - } - else - { - if (islower(*s)) - *s = toupper(*s); - s++; - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - if (islower(*s)) - *s = toupper(*s); - s++; - } - } -} - -/******************************************************************* - convert a string to "normal" form -********************************************************************/ -void strnorm(char *s) -{ - if (case_default == CASE_UPPER) - strupper(s); - else - strlower(s); -} - -/******************************************************************* -check if a string is in "normal" case -********************************************************************/ -BOOL strisnormal(char *s) -{ - if (case_default == CASE_UPPER) - return(!strhaslower(s)); - - return(!strhasupper(s)); -} - - -/**************************************************************************** - string replace -****************************************************************************/ -void string_replace(char *s,char oldc,char newc) -{ - while (*s) - { -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - if (is_shift_jis (*s)) - s += 2; - else if (is_kana (*s)) - s++; - else - { - if (oldc == *s) - *s = newc; - s++; - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - if (oldc == *s) - *s = newc; - s++; - } - } -} - -/**************************************************************************** - make a file into unix format -****************************************************************************/ -void unix_format(char *fname) -{ - pstring namecopy; - string_replace(fname,'\\','/'); - - if (*fname == '/') - { - pstrcpy(namecopy,fname); - strcpy(fname,"."); - strcat(fname,namecopy); - } -} - -/**************************************************************************** - make a file into dos format -****************************************************************************/ -void dos_format(char *fname) -{ - string_replace(fname,'/','\\'); -} - - -/******************************************************************* - show a smb message structure -********************************************************************/ -void show_msg(char *buf) -{ - int i; - int j; - int bcc=0; - if (DEBUGLEVEL < 5) - return; - - DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n", - smb_len(buf), - (int)CVAL(buf,smb_com), - (int)CVAL(buf,smb_rcls), - (int)CVAL(buf,smb_reh), - (int)SVAL(buf,smb_err), - (int)CVAL(buf,smb_flg), - (int)SVAL(buf,smb_flg2))); - DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n", - (int)SVAL(buf,smb_tid), - (int)SVAL(buf,smb_pid), - (int)SVAL(buf,smb_uid), - (int)SVAL(buf,smb_mid), - (int)CVAL(buf,smb_wct))); - for (i=0;i<(int)CVAL(buf,smb_wct);i++) - DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i, - SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i))); - bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct))); - DEBUG(5,("smb_bcc=%d\n",bcc)); - if (DEBUGLEVEL < 10) - return; - for (i = 0; i < MIN(bcc, 256); i += 16) - { - for (j = 0; j < 16 && i+j < MIN(bcc,256); j++) - { - - DEBUG(10,("%2X ",CVAL(smb_buf(buf),i+j))); - if (j == 7) DEBUG(10, (" ")); - - } - DEBUG(10,(" ")); - - for (j = 0; j < 16 && i+j < MIN(bcc,256); j++) - { - unsigned char c = CVAL(smb_buf(buf),i+j); - if (c < 32 || c > 128) c = '.'; - DEBUG(10,("%c",c)); - - if (j == 7) DEBUG(10, (" ")); - } - - DEBUG(10,("\n")); -} -} - -/******************************************************************* - return the length of an smb packet -********************************************************************/ -int smb_len(char *buf) -{ - return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) ); -} - -/******************************************************************* - set the length of an smb packet -********************************************************************/ -void _smb_setlen(char *buf,int len) -{ - buf[0] = 0; - buf[1] = (len&0x10000)>>16; - buf[2] = (len&0xFF00)>>8; - buf[3] = len&0xFF; -} - -/******************************************************************* - set the length and marker of an smb packet -********************************************************************/ -void smb_setlen(char *buf,int len) -{ - _smb_setlen(buf,len); - - CVAL(buf,4) = 0xFF; - CVAL(buf,5) = 'S'; - CVAL(buf,6) = 'M'; - CVAL(buf,7) = 'B'; -} - -/******************************************************************* - setup the word count and byte count for a smb message -********************************************************************/ -int set_message(char *buf,int num_words,int num_bytes,BOOL zero) -{ - if (zero) - bzero(buf + smb_size,num_words*2 + num_bytes); - CVAL(buf,smb_wct) = num_words; - SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); - smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4); - return (smb_size + num_words*2 + num_bytes); -} - -/******************************************************************* -return the number of smb words -********************************************************************/ -int smb_numwords(char *buf) -{ - return (CVAL(buf,smb_wct)); -} - -/******************************************************************* -return the size of the smb_buf region of a message -********************************************************************/ -int smb_buflen(char *buf) -{ - return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2)); -} - -/******************************************************************* - return a pointer to the smb_buf data area -********************************************************************/ -int smb_buf_ofs(char *buf) -{ - return (smb_size + CVAL(buf,smb_wct)*2); -} - -/******************************************************************* - return a pointer to the smb_buf data area -********************************************************************/ -char *smb_buf(char *buf) -{ - return (buf + smb_buf_ofs(buf)); -} - -/******************************************************************* -return the SMB offset into an SMB buffer -********************************************************************/ -int smb_offset(char *p,char *buf) -{ - return(PTR_DIFF(p,buf+4) + chain_size); -} - - -/******************************************************************* -skip past some strings in a buffer -********************************************************************/ -char *skip_string(char *buf,int n) -{ - while (n--) - buf += strlen(buf) + 1; - return(buf); -} - -/******************************************************************* -trim the specified elements off the front and back of a string -********************************************************************/ -BOOL trim_string(char *s,char *front,char *back) -{ - BOOL ret = False; - while (front && *front && strncmp(s,front,strlen(front)) == 0) - { - char *p = s; - ret = True; - while (1) - { - if (!(*p = p[strlen(front)])) - break; - p++; - } - } - while (back && *back && strlen(s) >= strlen(back) && - (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0)) - { - ret = True; - s[strlen(s)-strlen(back)] = 0; - } - return(ret); -} - - -/******************************************************************* -reduce a file name, removing .. elements. -********************************************************************/ -void dos_clean_name(char *s) -{ - char *p=NULL; - - DEBUG(3,("dos_clean_name [%s]\n",s)); - - /* remove any double slashes */ - string_sub(s, "\\\\", "\\"); - - while ((p = strstr(s,"\\..\\")) != NULL) - { - pstring s1; - - *p = 0; - pstrcpy(s1,p+3); - - if ((p=strrchr(s,'\\')) != NULL) - *p = 0; - else - *s = 0; - strcat(s,s1); - } - - trim_string(s,NULL,"\\.."); - - string_sub(s, "\\.\\", "\\"); -} - -/******************************************************************* -reduce a file name, removing .. elements. -********************************************************************/ -void unix_clean_name(char *s) -{ - char *p=NULL; - - DEBUG(3,("unix_clean_name [%s]\n",s)); - - /* remove any double slashes */ - string_sub(s, "//","/"); - - /* Remove leading ./ characters */ - if(strncmp(s, "./", 2) == 0) { - trim_string(s, "./", NULL); - if(*s == 0) - strcpy(s,"./"); - } - - while ((p = strstr(s,"/../")) != NULL) - { - pstring s1; - - *p = 0; - pstrcpy(s1,p+3); - - if ((p=strrchr(s,'/')) != NULL) - *p = 0; - else - *s = 0; - strcat(s,s1); - } - - trim_string(s,NULL,"/.."); -} - - -/******************************************************************* -a wrapper for the normal chdir() function -********************************************************************/ -int ChDir(char *path) -{ - int res; - static pstring LastDir=""; - - if (strcsequal(path,".")) return(0); - - if (*path == '/' && strcsequal(LastDir,path)) return(0); - DEBUG(3,("chdir to %s\n",path)); - res = sys_chdir(path); - if (!res) - pstrcpy(LastDir,path); - return(res); -} - -/* number of list structures for a caching GetWd function. */ -#define MAX_GETWDCACHE (50) - -struct -{ - ino_t inode; - dev_t dev; - char *text; - BOOL valid; -} ino_list[MAX_GETWDCACHE]; - -BOOL use_getwd_cache=True; - -/******************************************************************* - return the absolute current directory path -********************************************************************/ -char *GetWd(char *str) -{ - pstring s; - static BOOL getwd_cache_init = False; - struct stat st, st2; - int i; - - *s = 0; - - if (!use_getwd_cache) - return(sys_getwd(str)); - - /* init the cache */ - if (!getwd_cache_init) - { - getwd_cache_init = True; - for (i=0;i<MAX_GETWDCACHE;i++) - { - string_init(&ino_list[i].text,""); - ino_list[i].valid = False; - } - } - - /* Get the inode of the current directory, if this doesn't work we're - in trouble :-) */ - - if (stat(".",&st) == -1) - { - DEBUG(0,("Very strange, couldn't stat \".\"\n")); - return(sys_getwd(str)); - } - - - for (i=0; i<MAX_GETWDCACHE; i++) - if (ino_list[i].valid) - { - - /* If we have found an entry with a matching inode and dev number - then find the inode number for the directory in the cached string. - If this agrees with that returned by the stat for the current - directory then all is o.k. (but make sure it is a directory all - the same...) */ - - if (st.st_ino == ino_list[i].inode && - st.st_dev == ino_list[i].dev) - { - if (stat(ino_list[i].text,&st2) == 0) - { - if (st.st_ino == st2.st_ino && - st.st_dev == st2.st_dev && - (st2.st_mode & S_IFMT) == S_IFDIR) - { - strcpy (str, ino_list[i].text); - - /* promote it for future use */ - array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); - return (str); - } - else - { - /* If the inode is different then something's changed, - scrub the entry and start from scratch. */ - ino_list[i].valid = False; - } - } - } - } - - - /* We don't have the information to hand so rely on traditional methods. - The very slow getcwd, which spawns a process on some systems, or the - not quite so bad getwd. */ - - if (!sys_getwd(s)) - { - DEBUG(0,("Getwd failed, errno %s\n",strerror(errno))); - return (NULL); - } - - strcpy(str,s); - - DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev)); - - /* add it to the cache */ - i = MAX_GETWDCACHE - 1; - string_set(&ino_list[i].text,s); - ino_list[i].dev = st.st_dev; - ino_list[i].inode = st.st_ino; - ino_list[i].valid = True; - - /* put it at the top of the list */ - array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i); - - return (str); -} - - - -/******************************************************************* -reduce a file name, removing .. elements and checking that -it is below dir in the heirachy. This uses GetWd() and so must be run -on the system that has the referenced file system. - -widelinks are allowed if widelinks is true -********************************************************************/ -BOOL reduce_name(char *s,char *dir,BOOL widelinks) -{ -#ifndef REDUCE_PATHS - return True; -#else - pstring dir2; - pstring wd; - pstring basename; - pstring newname; - char *p=NULL; - BOOL relative = (*s != '/'); - - *dir2 = *wd = *basename = *newname = 0; - - if (widelinks) - { - unix_clean_name(s); - /* can't have a leading .. */ - if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/')) - { - DEBUG(3,("Illegal file name? (%s)\n",s)); - return(False); - } - - if (strlen(s) == 0) - strcpy(s,"./"); - - return(True); - } - - DEBUG(3,("reduce_name [%s] [%s]\n",s,dir)); - - /* remove any double slashes */ - string_sub(s,"//","/"); - - pstrcpy(basename,s); - p = strrchr(basename,'/'); - - if (!p) - return(True); - - if (!GetWd(wd)) - { - DEBUG(0,("couldn't getwd for %s %s\n",s,dir)); - return(False); - } - - if (ChDir(dir) != 0) - { - DEBUG(0,("couldn't chdir to %s\n",dir)); - return(False); - } - - if (!GetWd(dir2)) - { - DEBUG(0,("couldn't getwd for %s\n",dir)); - ChDir(wd); - return(False); - } - - - if (p && (p != basename)) - { - *p = 0; - if (strcmp(p+1,".")==0) - p[1]=0; - if (strcmp(p+1,"..")==0) - *p = '/'; - } - - if (ChDir(basename) != 0) - { - ChDir(wd); - DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename)); - return(False); - } - - if (!GetWd(newname)) - { - ChDir(wd); - DEBUG(2,("couldn't get wd for %s %s\n",s,dir2)); - return(False); - } - - if (p && (p != basename)) - { - strcat(newname,"/"); - strcat(newname,p+1); - } - - { - int l = strlen(dir2); - if (dir2[l-1] == '/') - l--; - - if (strncmp(newname,dir2,l) != 0) - { - ChDir(wd); - DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l)); - return(False); - } - - if (relative) - { - if (newname[l] == '/') - pstrcpy(s,newname + l + 1); - else - pstrcpy(s,newname+l); - } - else - pstrcpy(s,newname); - } - - ChDir(wd); - - if (strlen(s) == 0) - strcpy(s,"./"); - - DEBUG(3,("reduced to %s\n",s)); - return(True); -#endif -} - -/**************************************************************************** -expand some *s -****************************************************************************/ -static void expand_one(char *Mask,int len) -{ - char *p1; - while ((p1 = strchr(Mask,'*')) != NULL) - { - int lfill = (len+1) - strlen(Mask); - int l1= (p1 - Mask); - pstring tmp; - pstrcpy(tmp,Mask); - memset(tmp+l1,'?',lfill); - pstrcpy(tmp + l1 + lfill,Mask + l1 + 1); - pstrcpy(Mask,tmp); - } -} - -/**************************************************************************** -expand a wildcard expression, replacing *s with ?s -****************************************************************************/ -void expand_mask(char *Mask,BOOL doext) -{ - pstring mbeg,mext; - pstring dirpart; - pstring filepart; - BOOL hasdot = False; - char *p1; - BOOL absolute = (*Mask == '\\'); - - *mbeg = *mext = *dirpart = *filepart = 0; - - /* parse the directory and filename */ - if (strchr(Mask,'\\')) - dirname_dos(Mask,dirpart); - - filename_dos(Mask,filepart); - - pstrcpy(mbeg,filepart); - if ((p1 = strchr(mbeg,'.')) != NULL) - { - hasdot = True; - *p1 = 0; - p1++; - pstrcpy(mext,p1); - } - else - { - strcpy(mext,""); - if (strlen(mbeg) > 8) - { - pstrcpy(mext,mbeg + 8); - mbeg[8] = 0; - } - } - - if (*mbeg == 0) - strcpy(mbeg,"????????"); - if ((*mext == 0) && doext && !hasdot) - strcpy(mext,"???"); - - if (strequal(mbeg,"*") && *mext==0) - strcpy(mext,"*"); - - /* expand *'s */ - expand_one(mbeg,8); - if (*mext) - expand_one(mext,3); - - pstrcpy(Mask,dirpart); - if (*dirpart || absolute) strcat(Mask,"\\"); - strcat(Mask,mbeg); - strcat(Mask,"."); - strcat(Mask,mext); - - DEBUG(6,("Mask expanded to [%s]\n",Mask)); -} - - -/**************************************************************************** -does a string have any uppercase chars in it? -****************************************************************************/ -BOOL strhasupper(char *s) -{ - while (*s) - { -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - if (is_shift_jis (*s)) - s += 2; - else if (is_kana (*s)) - s++; - else - { - if (isupper(*s)) - return(True); - s++; - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - if (isupper(*s)) - return(True); - s++; - } - } - return(False); -} - -/**************************************************************************** -does a string have any lowercase chars in it? -****************************************************************************/ -BOOL strhaslower(char *s) -{ - while (*s) - { -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - if (is_shift_jis (*s)) - { - if (is_sj_upper (s[0], s[1])) - return(True); - if (is_sj_lower (s[0], s[1])) - return (True); - s += 2; - } - else if (is_kana (*s)) - { - s++; - } - else - { - if (islower(*s)) - return(True); - s++; - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - if (islower(*s)) - return(True); - s++; - } - } - return(False); -} - -/**************************************************************************** -find the number of chars in a string -****************************************************************************/ -int count_chars(char *s,char c) -{ - int count=0; - -#if !defined(KANJI_WIN95_COMPATIBILITY) - if(lp_client_code_page() == KANJI_CODEPAGE) - { - /* Win95 treats full width ascii characters as case sensitive. */ - while (*s) - { - if (is_shift_jis (*s)) - s += 2; - else - { - if (*s == c) - count++; - s++; - } - } - } - else -#endif /* KANJI_WIN95_COMPATIBILITY */ - { - while (*s) - { - if (*s == c) - count++; - s++; - } - } - return(count); -} - - -/**************************************************************************** - make a dir struct -****************************************************************************/ -void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date) -{ - char *p; - pstring mask2; - - pstrcpy(mask2,mask); - - if ((mode & aDIR) != 0) - size = 0; - - memset(buf+1,' ',11); - if ((p = strchr(mask2,'.')) != NULL) - { - *p = 0; - memcpy(buf+1,mask2,MIN(strlen(mask2),8)); - memcpy(buf+9,p+1,MIN(strlen(p+1),3)); - *p = '.'; - } - else - memcpy(buf+1,mask2,MIN(strlen(mask2),11)); - - bzero(buf+21,DIR_STRUCT_SIZE-21); - CVAL(buf,21) = mode; - put_dos_date(buf,22,date); - SSVAL(buf,26,size & 0xFFFF); - SSVAL(buf,28,size >> 16); - StrnCpy(buf+30,fname,12); - if (!case_sensitive) - strupper(buf+30); - DEBUG(8,("put name [%s] into dir struct\n",buf+30)); -} - - -/******************************************************************* -close the low 3 fd's and open dev/null in their place -********************************************************************/ -void close_low_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 < 0) { - DEBUG(0,("Can't open /dev/null\n")); - return; - } - if (fd != i) { - DEBUG(0,("Didn't get file descriptor %d\n",i)); - return; - } - } -} - -/**************************************************************************** -Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, -else -if SYSV use O_NDELAY -if BSD use FNDELAY -****************************************************************************/ -int set_blocking(int fd, BOOL set) -{ - int val; -#ifdef O_NONBLOCK -#define FLAG_TO_SET O_NONBLOCK -#else -#ifdef SYSV -#define FLAG_TO_SET O_NDELAY -#else /* BSD */ -#define FLAG_TO_SET FNDELAY -#endif -#endif - - if((val = fcntl(fd, F_GETFL, 0)) == -1) - return -1; - if(set) /* Turn blocking on - ie. clear nonblock flag */ - val &= ~FLAG_TO_SET; - else - val |= FLAG_TO_SET; - return fcntl( fd, F_SETFL, val); -#undef FLAG_TO_SET -} - - -/**************************************************************************** -write to a socket -****************************************************************************/ -int write_socket(int fd,char *buf,int len) -{ - int ret=0; - - if (passive) - return(len); - DEBUG(6,("write_socket(%d,%d)\n",fd,len)); - ret = write_data(fd,buf,len); - - DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret)); - return(ret); -} - -/**************************************************************************** -read from a socket -****************************************************************************/ -int read_udp_socket(int fd,char *buf,int len) -{ - int ret; - struct sockaddr sock; - int socklen; - - socklen = sizeof(sock); - bzero((char *)&sock,socklen); - bzero((char *)&lastip,sizeof(lastip)); - ret = recvfrom(fd,buf,len,0,&sock,&socklen); - if (ret <= 0) { - DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno))); - return(0); - } - - lastip = *(struct in_addr *) &sock.sa_data[2]; - lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port); - - return(ret); -} - -/**************************************************************************** -read data from a device with a timout in msec. -mincount = if timeout, minimum to read before returning -maxcount = number to be read. -****************************************************************************/ -int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out) -{ - fd_set fds; - int selrtn; - int readret; - int nread = 0; - struct timeval timeout; - - /* just checking .... */ - if (maxcnt <= 0) return(0); - - smb_read_error = 0; - - /* Blocking read */ - if (time_out <= 0) { - if (mincnt == 0) mincnt = maxcnt; - - while (nread < mincnt) { - readret = read(fd, buf + nread, maxcnt - nread); - if (readret == 0) { - smb_read_error = READ_EOF; - return -1; - } - - if (readret == -1) { - smb_read_error = READ_ERROR; - return -1; - } - nread += readret; - } - return(nread); - } - - /* Most difficult - timeout read */ - /* If this is ever called on a disk file and - mincnt is greater then the filesize then - system performance will suffer severely as - select always return true on disk files */ - - /* Set initial timeout */ - timeout.tv_sec = time_out / 1000; - timeout.tv_usec = 1000 * (time_out % 1000); - - for (nread=0; nread<mincnt; ) - { - FD_ZERO(&fds); - FD_SET(fd,&fds); - - selrtn = sys_select(&fds,&timeout); - - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return -1; - } - - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return -1; - } - - readret = read(fd, buf+nread, maxcnt-nread); - if (readret == 0) { - /* we got EOF on the file descriptor */ - smb_read_error = READ_EOF; - return -1; - } - - if (readret == -1) { - /* the descriptor is probably dead */ - smb_read_error = READ_ERROR; - return -1; - } - - nread += readret; - } - - /* Return the number we got */ - return(nread); -} - -/**************************************************************************** -read data from the client. Maxtime is in milliseconds -****************************************************************************/ -int read_max_udp(int fd,char *buffer,int bufsize,int maxtime) -{ - fd_set fds; - int selrtn; - int nread; - struct timeval timeout; - - FD_ZERO(&fds); - FD_SET(fd,&fds); - - timeout.tv_sec = maxtime / 1000; - timeout.tv_usec = (maxtime % 1000) * 1000; - - selrtn = sys_select(&fds,maxtime>0?&timeout:NULL); - - if (!FD_ISSET(fd,&fds)) - return 0; - - nread = read_udp_socket(fd, buffer, bufsize); - - /* return the number got */ - return(nread); -} - -/******************************************************************* -find the difference in milliseconds between two struct timeval -values -********************************************************************/ -int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew) -{ - return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + - ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000); -} - -/**************************************************************************** -send a keepalive packet (rfc1002) -****************************************************************************/ -BOOL send_keepalive(int client) -{ - unsigned char buf[4]; - - buf[0] = 0x85; - buf[1] = buf[2] = buf[3] = 0; - - return(write_data(client,(char *)buf,4) == 4); -} - - - -/**************************************************************************** - read data from the client, reading exactly N bytes. -****************************************************************************/ -int read_data(int fd,char *buffer,int N) -{ - int ret; - int total=0; - - smb_read_error = 0; - - while (total < N) - { - ret = read(fd,buffer + total,N - total); - if (ret == 0) { - smb_read_error = READ_EOF; - return 0; - } - if (ret == -1) { - smb_read_error = READ_ERROR; - return -1; - } - total += ret; - } - return total; -} - - -/**************************************************************************** - write data to a fd -****************************************************************************/ -int write_data(int fd,char *buffer,int N) -{ - int total=0; - int ret; - - while (total < N) - { - ret = write(fd,buffer + total,N - total); - - if (ret == -1) return -1; - if (ret == 0) return total; - - total += ret; - } - return total; -} - - -/**************************************************************************** -transfer some data between two fd's -****************************************************************************/ -int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align) -{ - static char *buf=NULL; - static int size=0; - char *buf1,*abuf; - int total = 0; - - DEBUG(4,("transfer_file %d (head=%d) called\n",n,headlen)); - - if (size == 0) { - size = lp_readsize(); - size = MAX(size,1024); - } - - while (!buf && size>0) { - buf = (char *)Realloc(buf,size+8); - if (!buf) size /= 2; - } - - if (!buf) { - DEBUG(0,("Can't allocate transfer buffer!\n")); - exit(1); - } - - abuf = buf + (align%8); - - if (header) - n += headlen; - - while (n > 0) - { - int s = MIN(n,size); - int ret,ret2=0; - - ret = 0; - - if (header && (headlen >= MIN(s,1024))) { - buf1 = header; - s = headlen; - ret = headlen; - headlen = 0; - header = NULL; - } else { - buf1 = abuf; - } - - if (header && headlen > 0) - { - ret = MIN(headlen,size); - memcpy(buf1,header,ret); - headlen -= ret; - header += ret; - if (headlen <= 0) header = NULL; - } - - if (s > ret) - ret += read(infd,buf1+ret,s-ret); - - if (ret > 0) - { - ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret); - if (ret2 > 0) total += ret2; - /* if we can't write then dump excess data */ - if (ret2 != ret) - transfer_file(infd,-1,n-(ret+headlen),NULL,0,0); - } - if (ret <= 0 || ret2 != ret) - return(total); - n -= ret; - } - return(total); -} - - -/**************************************************************************** -read 4 bytes of a smb packet and return the smb length of the packet -possibly store the result in the buffer -****************************************************************************/ -int read_smb_length(int fd,char *inbuf,int timeout) -{ - char *buffer; - char buf[4]; - int len=0, msg_type; - BOOL ok=False; - - if (inbuf) - buffer = inbuf; - else - buffer = buf; - - while (!ok) - { - if (timeout > 0) - ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4); - else - ok = (read_data(fd,buffer,4) == 4); - - if (!ok) - return(-1); - - len = smb_len(buffer); - msg_type = CVAL(buffer,0); - - if (msg_type == 0x85) - { - DEBUG(5,("Got keepalive packet\n")); - ok = False; - } - } - - DEBUG(10,("got smb length of %d\n",len)); - - return(len); -} - - - -/**************************************************************************** - read an smb from a fd. Note that the buffer *MUST* be of size - BUFFER_SIZE+SAFETY_MARGIN. -The timeout is in milli seconds -****************************************************************************/ -BOOL receive_smb(int fd,char *buffer, int timeout) -{ - int len,ret; - - smb_read_error = 0; - - bzero(buffer,smb_size + 100); - - len = read_smb_length(fd,buffer,timeout); - if (len == -1) - return(False); - - if (len > BUFFER_SIZE) { - DEBUG(0,("Invalid packet length! (%d bytes).\n",len)); - if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) - exit(1); - } - - ret = read_data(fd,buffer+4,len); - if (ret != len) { - smb_read_error = READ_ERROR; - return False; - } - - return(True); -} - -/**************************************************************************** - read a message from a udp fd. -The timeout is in milli seconds -****************************************************************************/ -BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout) -{ - struct sockaddr_in from; - int fromlen = sizeof(from); - int32 msg_len = 0; - - if(timeout != 0) - { - struct timeval to; - fd_set fds; - int selrtn; - - FD_ZERO(&fds); - FD_SET(fd,&fds); - - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - - selrtn = sys_select(&fds,&to); - - /* Check if error */ - if(selrtn == -1) - { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } - - /* Did we timeout ? */ - if (selrtn == 0) - { - smb_read_error = READ_TIMEOUT; - return False; - } - } - - /* - * Read a loopback udp message. - */ - msg_len = recvfrom(fd, &buffer[UDP_CMD_HEADER_LEN], - buffer_len - UDP_CMD_HEADER_LEN, 0, - (struct sockaddr *)&from, &fromlen); - - if(msg_len < 0) - { - DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); - return False; - } - - /* Validate message length. */ - if(msg_len > (buffer_len - UDP_CMD_HEADER_LEN)) - { - DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", - msg_len, - buffer_len - UDP_CMD_HEADER_LEN)); - return False; - } - - /* Validate message from address (must be localhost). */ - if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) - { - DEBUG(0,("receive_local_message: invalid 'from' address \ -(was %x should be 127.0.0.1\n", from.sin_addr.s_addr)); - return False; - } - - /* Setup the message header */ - SIVAL(buffer,UDP_CMD_LEN_OFFSET,msg_len); - SSVAL(buffer,UDP_CMD_PORT_OFFSET,ntohs(from.sin_port)); - - return True; -} - -/**************************************************************************** - structure to hold a linked list of local udp messages. - for processing. -****************************************************************************/ - -typedef struct _udp_message_list { - struct _udp_message_list *msg_next; - char *msg_buf; - int msg_len; -} udp_message_list; - -static udp_message_list *udp_msg_head = NULL; - -/**************************************************************************** - Function to push a linked list of local udp messages ready - for processing. -****************************************************************************/ -BOOL push_local_message(char *buf, int msg_len) -{ - udp_message_list *msg = (udp_message_list *)malloc(sizeof(udp_message_list)); - - if(msg == NULL) - { - DEBUG(0,("push_local_message: malloc fail (1)\n")); - return False; - } - - msg->msg_buf = (char *)malloc(msg_len); - if(msg->msg_buf == NULL) - { - DEBUG(0,("push_local_message: malloc fail (2)\n")); - free((char *)msg); - return False; - } - - memcpy(msg->msg_buf, buf, msg_len); - msg->msg_len = msg_len; - - msg->msg_next = udp_msg_head; - udp_msg_head = msg; - - return True; -} - -/**************************************************************************** - Do a select on an two fd's - with timeout. - - If a local udp message has been pushed onto the - queue (this can only happen during oplock break - processing) return this first. - - If the first smbfd is ready then read an smb from it. - if the second (loopback UDP) fd is ready then read a message - from it and setup the buffer header to identify the length - and from address. - Returns False on timeout or error. - Else returns True. - -The timeout is in milli seconds -****************************************************************************/ -BOOL receive_message_or_smb(int smbfd, int oplock_fd, - char *buffer, int buffer_len, - int timeout, BOOL *got_smb) -{ - fd_set fds; - int selrtn; - struct timeval to; - - *got_smb = False; - - /* - * Check to see if we already have a message on the udp queue. - * If so - copy and return it. - */ - - if(udp_msg_head) - { - udp_message_list *msg = udp_msg_head; - memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len)); - udp_msg_head = msg->msg_next; - - /* Free the message we just copied. */ - free((char *)msg->msg_buf); - free((char *)msg); - return True; - } - - FD_ZERO(&fds); - FD_SET(smbfd,&fds); - FD_SET(oplock_fd,&fds); - - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - - selrtn = sys_select(&fds,timeout>0?&to:NULL); - - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } - - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } - - if (FD_ISSET(smbfd,&fds)) - { - *got_smb = True; - return receive_smb(smbfd, buffer, 0); - } - else - { - return receive_local_message(oplock_fd, buffer, buffer_len, 0); - } -} - -/**************************************************************************** - send an smb to a fd -****************************************************************************/ -BOOL send_smb(int fd,char *buffer) -{ - int len; - int ret,nwritten=0; - len = smb_len(buffer) + 4; - - while (nwritten < len) - { - ret = write_socket(fd,buffer+nwritten,len - nwritten); - if (ret <= 0) - { - DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret)); - close_sockets(); - exit(1); - } - nwritten += ret; - } - - - return True; -} - - -/**************************************************************************** -find a pointer to a netbios name -****************************************************************************/ -char *name_ptr(char *buf,int ofs) -{ - unsigned char c = *(unsigned char *)(buf+ofs); - - if ((c & 0xC0) == 0xC0) - { - uint16 l; - char p[2]; - memcpy(p,buf+ofs,2); - p[0] &= ~0xC0; - l = RSVAL(p,0); - DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l)); - return(buf + l); - } - else - return(buf+ofs); -} - -/**************************************************************************** -extract a netbios name from a buf -****************************************************************************/ -int name_extract(char *buf,int ofs,char *name) -{ - char *p = name_ptr(buf,ofs); - int d = PTR_DIFF(p,buf+ofs); - strcpy(name,""); - if (d < -50 || d > 50) return(0); - return(name_interpret(p,name)); -} - -/**************************************************************************** -return the total storage length of a mangled name -****************************************************************************/ -int name_len( char *s ) - { - int len; - - /* If the two high bits of the byte are set, return 2. */ - if( 0xC0 == (*(unsigned char *)s & 0xC0) ) - return(2); - - /* Add up the length bytes. */ - for( len = 1; (*s); s += (*s) + 1 ) - { - len += *s + 1; - } - - return( len ); - } /* name_len */ - -/**************************************************************************** -send a single packet to a port on another machine -****************************************************************************/ -BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type) -{ - BOOL ret; - int out_fd; - struct sockaddr_in sock_out; - - if (passive) - return(True); - - /* create a socket to write to */ - out_fd = socket(AF_INET, type, 0); - if (out_fd == -1) - { - DEBUG(0,("socket failed")); - return False; - } - - /* 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; - - if (DEBUGLEVEL > 0) - DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n", - len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM")); - - /* send it */ - ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0); - - if (!ret) - DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n", - inet_ntoa(ip),port,strerror(errno))); - - close(out_fd); - return(ret); -} - -/******************************************************************* -sleep for a specified number of milliseconds -********************************************************************/ -void msleep(int t) -{ - int tdiff=0; - struct timeval tval,t1,t2; - fd_set fds; - - GetTimeOfDay(&t1); - GetTimeOfDay(&t2); - - while (tdiff < t) { - tval.tv_sec = (t-tdiff)/1000; - tval.tv_usec = 1000*((t-tdiff)%1000); - - FD_ZERO(&fds); - errno = 0; - sys_select(&fds,&tval); - - GetTimeOfDay(&t2); - tdiff = TvalDiff(&t1,&t2); - } -} - -/**************************************************************************** -check if a string is part of a list -****************************************************************************/ -BOOL in_list(char *s,char *list,BOOL casesensitive) -{ - pstring tok; - char *p=list; - - if (!list) return(False); - - while (next_token(&p,tok,LIST_SEP)) - { - if (casesensitive) { - if (strcmp(tok,s) == 0) - return(True); - } else { - if (StrCaseCmp(tok,s) == 0) - return(True); - } - } - return(False); -} - -/* this is used to prevent lots of mallocs of size 1 */ -static char *null_string = NULL; - -/**************************************************************************** -set a string value, allocing the space for the string -****************************************************************************/ -BOOL string_init(char **dest,char *src) -{ - int l; - if (!src) - src = ""; - - l = strlen(src); - - if (l == 0) - { - if (!null_string) - null_string = (char *)malloc(1); - - *null_string = 0; - *dest = null_string; - } - else - { - (*dest) = (char *)malloc(l+1); - if ((*dest) == NULL) { - DEBUG(0,("Out of memory in string_init\n")); - return False; - } - - strcpy(*dest,src); - } - return(True); -} - -/**************************************************************************** -free a string value -****************************************************************************/ -void string_free(char **s) -{ - if (!s || !(*s)) return; - if (*s == null_string) - *s = NULL; - if (*s) free(*s); - *s = NULL; -} - -/**************************************************************************** -set a string value, allocing the space for the string, and deallocating any -existing space -****************************************************************************/ -BOOL string_set(char **dest,char *src) -{ - string_free(dest); - - return(string_init(dest,src)); -} - -/**************************************************************************** -substitute a string for a pattern in another string. Make sure there is -enough room! - -This routine looks for pattern in s and replaces it with -insert. It may do multiple replacements. - -return True if a substitution was done. -****************************************************************************/ -BOOL string_sub(char *s,char *pattern,char *insert) -{ - BOOL ret = False; - char *p; - int ls,lp,li; - - if (!insert || !pattern || !s) return(False); - - ls = strlen(s); - lp = strlen(pattern); - li = strlen(insert); - - if (!*pattern) return(False); - - while (lp <= ls && (p = strstr(s,pattern))) - { - ret = True; - memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp)); - memcpy(p,insert,li); - s = p + li; - ls = strlen(s); - } - return(ret); -} - - - -/********************************************************* -* Recursive routine that is called by mask_match. -* Does the actual matching. -*********************************************************/ -BOOL do_match(char *str, char *regexp, int case_sig) -{ - char *p; - - for( p = regexp; *p && *str; ) { - switch(*p) { - case '?': - str++; p++; - break; - - case '*': - /* Look for a character matching - the one after the '*' */ - p++; - if(!*p) - return True; /* Automatic match */ - while(*str) { - while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str)))) - str++; - if(do_match(str,p,case_sig)) - return True; - if(!*str) - return False; - else - str++; - } - return False; - - default: - if(case_sig) { - if(*str != *p) - return False; - } else { - if(toupper(*str) != toupper(*p)) - return False; - } - str++, p++; - break; - } - } - if(!*p && !*str) - return True; - - if (!*p && str[0] == '.' && str[1] == 0) - return(True); - - if (!*str && *p == '?') - { - while (*p == '?') p++; - return(!*p); - } - - if(!*str && (*p == '*' && p[1] == '\0')) - return True; - return False; -} - - -/********************************************************* -* Routine to match a given string with a regexp - uses -* simplified regexp that takes * and ? only. Case can be -* significant or not. -*********************************************************/ -BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2) -{ - char *p; - pstring p1, p2; - fstring ebase,eext,sbase,sext; - - BOOL matched; - - /* Make local copies of str and regexp */ - StrnCpy(p1,regexp,sizeof(pstring)-1); - StrnCpy(p2,str,sizeof(pstring)-1); - - if (!strchr(p2,'.')) { - strcat(p2,"."); - } - -/* - if (!strchr(p1,'.')) { - strcat(p1,"."); - } -*/ - -#if 0 - if (strchr(p1,'.')) - { - string_sub(p1,"*.*","*"); - string_sub(p1,".*","*"); - } -#endif - - /* Remove any *? and ** as they are meaningless */ - for(p = p1; *p; p++) - while( *p == '*' && (p[1] == '?' ||p[1] == '*')) - (void)strcpy( &p[1], &p[2]); - - if (strequal(p1,"*")) return(True); - - DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig)); - - if (trans2) { - fstrcpy(ebase,p1); - fstrcpy(sbase,p2); - } else { - if ((p=strrchr(p1,'.'))) { - *p = 0; - fstrcpy(ebase,p1); - fstrcpy(eext,p+1); - } else { - fstrcpy(ebase,p1); - eext[0] = 0; - } - - if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) { - *p = 0; - fstrcpy(sbase,p2); - fstrcpy(sext,p+1); - } else { - fstrcpy(sbase,p2); - fstrcpy(sext,""); - } - } - - matched = do_match(sbase,ebase,case_sig) && - (trans2 || do_match(sext,eext,case_sig)); - - DEBUG(8,("mask_match returning %d\n", matched)); - - return matched; -} - - - -/**************************************************************************** -become a daemon, discarding the controlling terminal -****************************************************************************/ -void become_daemon(void) -{ -#ifndef NO_FORK_DEBUG - if (fork()) - exit(0); - - /* detach from the terminal */ -#ifdef USE_SETSID - setsid(); -#else /* USE_SETSID */ -#ifdef TIOCNOTTY - { - int i = open("/dev/tty", O_RDWR); - if (i >= 0) - { - ioctl(i, (int) TIOCNOTTY, (char *)0); - close(i); - } - } -#endif /* TIOCNOTTY */ -#endif /* USE_SETSID */ - /* Close fd's 0,1,2. Needed if started by rsh */ - close_low_fds(); -#endif /* NO_FORK_DEBUG */ -} - - -/**************************************************************************** -put up a yes/no prompt -****************************************************************************/ -BOOL yesno(char *p) -{ - pstring ans; - printf("%s",p); - - if (!fgets(ans,sizeof(ans)-1,stdin)) - return(False); - - if (*ans == 'y' || *ans == 'Y') - return(True); - - return(False); -} - -/**************************************************************************** -read a line from a file with possible \ continuation chars. -Blanks at the start or end of a line are stripped. -The string will be allocated if s2 is NULL -****************************************************************************/ -char *fgets_slash(char *s2,int maxlen,FILE *f) -{ - char *s=s2; - int len = 0; - int c; - BOOL start_of_line = True; - - if (feof(f)) - return(NULL); - - if (!s2) - { - maxlen = MIN(maxlen,8); - s = (char *)Realloc(s,maxlen); - } - - if (!s || maxlen < 2) return(NULL); - - *s = 0; - - while (len < maxlen-1) - { - c = getc(f); - switch (c) - { - case '\r': - break; - case '\n': - while (len > 0 && s[len-1] == ' ') - { - s[--len] = 0; - } - if (len > 0 && s[len-1] == '\\') - { - s[--len] = 0; - start_of_line = True; - break; - } - return(s); - case EOF: - if (len <= 0 && !s2) - free(s); - return(len>0?s:NULL); - case ' ': - if (start_of_line) - break; - default: - start_of_line = False; - s[len++] = c; - s[len] = 0; - } - if (!s2 && len > maxlen-3) - { - maxlen *= 2; - s = (char *)Realloc(s,maxlen); - if (!s) return(NULL); - } - } - return(s); -} - - - -/**************************************************************************** -set the length of a file from a filedescriptor. -Returns 0 on success, -1 on failure. -****************************************************************************/ -int set_filelen(int fd, long len) -{ -/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot - extend a file with ftruncate. Provide alternate implementation - for this */ - -#if FTRUNCATE_CAN_EXTEND - return ftruncate(fd, len); -#else - struct stat st; - char c = 0; - long currpos = lseek(fd, 0L, SEEK_CUR); - - if(currpos < 0) - return -1; - /* Do an fstat to see if the file is longer than - the requested size (call ftruncate), - or shorter, in which case seek to len - 1 and write 1 - byte of zero */ - if(fstat(fd, &st)<0) - return -1; - -#ifdef S_ISFIFO - if (S_ISFIFO(st.st_mode)) return 0; -#endif - - if(st.st_size == len) - return 0; - if(st.st_size > len) - return ftruncate(fd, len); - - if(lseek(fd, len-1, SEEK_SET) != len -1) - return -1; - if(write(fd, &c, 1)!=1) - return -1; - /* Seek to where we were */ - lseek(fd, currpos, SEEK_SET); - return 0; -#endif -} - - -/**************************************************************************** -return the byte checksum of some data -****************************************************************************/ -int byte_checksum(char *buf,int len) -{ - unsigned char *p = (unsigned char *)buf; - int ret = 0; - while (len--) - ret += *p++; - return(ret); -} - - - -#ifdef HPUX -/**************************************************************************** -this is a version of setbuffer() for those machines that only have setvbuf -****************************************************************************/ - void setbuffer(FILE *f,char *buf,int bufsize) -{ - setvbuf(f,buf,_IOFBF,bufsize); -} -#endif - - -/**************************************************************************** -parse out a directory name from a path name. Assumes dos style filenames. -****************************************************************************/ -char *dirname_dos(char *path,char *buf) -{ - char *p = strrchr(path,'\\'); - - if (!p) - strcpy(buf,path); - else - { - *p = 0; - strcpy(buf,path); - *p = '\\'; - } - - return(buf); -} - - -/**************************************************************************** -parse out a filename from a path name. Assumes dos style filenames. -****************************************************************************/ -static char *filename_dos(char *path,char *buf) -{ - char *p = strrchr(path,'\\'); - - if (!p) - strcpy(buf,path); - else - strcpy(buf,p+1); - - return(buf); -} - - - -/**************************************************************************** -expand a pointer to be a particular size -****************************************************************************/ -void *Realloc(void *p,int size) -{ - void *ret=NULL; - - if (size == 0) { - if (p) free(p); - DEBUG(5,("Realloc asked for 0 bytes\n")); - return NULL; - } - - if (!p) - ret = (void *)malloc(size); - else - ret = (void *)realloc(p,size); - - if (!ret) - DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size)); - - return(ret); -} - -#ifdef NOSTRDUP -/**************************************************************************** -duplicate a string -****************************************************************************/ - char *strdup(char *s) -{ - char *ret = NULL; - if (!s) return(NULL); - ret = (char *)malloc(strlen(s)+1); - if (!ret) return(NULL); - strcpy(ret,s); - return(ret); -} -#endif - - -/**************************************************************************** - Signal handler for SIGPIPE (write on a disconnected socket) -****************************************************************************/ -void Abort(void ) -{ - DEBUG(0,("Probably got SIGPIPE\nExiting\n")); - exit(2); -} - -/**************************************************************************** -get my own name and IP -****************************************************************************/ -BOOL get_myname(char *my_name,struct in_addr *ip) -{ - struct hostent *hp; - pstring hostname; - - *hostname = 0; - - /* get my host name */ - if (gethostname(hostname, MAXHOSTNAMELEN) == -1) - { - DEBUG(0,("gethostname failed\n")); - return False; - } - - /* get host info */ - if ((hp = Get_Hostbyname(hostname)) == 0) - { - DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname)); - return False; - } - - if (my_name) - { - /* split off any parts after an initial . */ - char *p = strchr(hostname,'.'); - if (p) *p = 0; - - fstrcpy(my_name,hostname); - } - - if (ip) - putip((char *)ip,(char *)hp->h_addr); - - return(True); -} - - -/**************************************************************************** -true if two IP addresses are equal -****************************************************************************/ -BOOL ip_equal(struct in_addr ip1,struct in_addr ip2) -{ - uint32 a1,a2; - a1 = ntohl(ip1.s_addr); - a2 = ntohl(ip2.s_addr); - return(a1 == a2); -} - - -/**************************************************************************** -open a socket of the specified type, port and address for incoming data -****************************************************************************/ -int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) -{ - struct hostent *hp; - struct sockaddr_in sock; - pstring host_name; - int res; - - /* get my host name */ - if (gethostname(host_name, MAXHOSTNAMELEN) == -1) - { DEBUG(0,("gethostname failed\n")); return -1; } - - /* get host info */ - if ((hp = Get_Hostbyname(host_name)) == 0) - { - DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name)); - return -1; - } - - bzero((char *)&sock,sizeof(sock)); - memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length); -#if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */ - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = htons( port ); - sock.sin_family = hp->h_addrtype; - sock.sin_addr.s_addr = socket_addr; - res = socket(hp->h_addrtype, type, 0); - if (res == -1) - { DEBUG(0,("socket failed\n")); return -1; } - - { - int one=1; - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); - } - - /* now we've got a socket - we need to bind it */ - if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) - { - if (port) { - if (port == SMB_PORT || port == NMB_PORT) - DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n", - port,socket_addr,strerror(errno))); - close(res); - - if (dlevel > 0 && port < 1000) - port = 7999; - - if (port >= 1000 && port < 9000) - return(open_socket_in(type,port+1,dlevel,socket_addr)); - } - - return(-1); - } - DEBUG(3,("bind succeeded on port %d\n",port)); - - return res; -} - - -/**************************************************************************** - create an outgoing socket - **************************************************************************/ -int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) -{ - struct sockaddr_in sock_out; - int res,ret; - int connect_loop = 250; /* 250 milliseconds */ - int loops = (timeout * 1000) / connect_loop; - - /* create a socket to write to */ - res = socket(PF_INET, type, 0); - if (res == -1) - { DEBUG(0,("socket error\n")); return -1; } - - if (type != SOCK_STREAM) return(res); - - bzero((char *)&sock_out,sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)addr); - - sock_out.sin_port = htons( port ); - sock_out.sin_family = PF_INET; - - /* set it non-blocking */ - set_blocking(res,False); - - DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); - - /* and connect it to the destination */ -connect_again: - ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); - - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && loops--) { - msleep(connect_loop); - goto connect_again; - } - - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); - close(res); - return -1; - } - -#ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; - } -#endif - - if (ret < 0) { - DEBUG(1,("error connecting to %s:%d (%s)\n", - inet_ntoa(*addr),port,strerror(errno))); - return -1; - } - - /* set it blocking again */ - set_blocking(res,True); - - return res; -} - - -/**************************************************************************** -interpret a protocol description string, with a default -****************************************************************************/ -int interpret_protocol(char *str,int def) -{ - if (strequal(str,"NT1")) - return(PROTOCOL_NT1); - if (strequal(str,"LANMAN2")) - return(PROTOCOL_LANMAN2); - if (strequal(str,"LANMAN1")) - return(PROTOCOL_LANMAN1); - if (strequal(str,"CORE")) - return(PROTOCOL_CORE); - if (strequal(str,"COREPLUS")) - return(PROTOCOL_COREPLUS); - if (strequal(str,"CORE+")) - return(PROTOCOL_COREPLUS); - - DEBUG(0,("Unrecognised protocol level %s\n",str)); - - return(def); -} - -/**************************************************************************** -interpret a security level -****************************************************************************/ -int interpret_security(char *str,int def) -{ - if (strequal(str,"SERVER")) - return(SEC_SERVER); - if (strequal(str,"USER")) - return(SEC_USER); - if (strequal(str,"SHARE")) - return(SEC_SHARE); - - DEBUG(0,("Unrecognised security level %s\n",str)); - - return(def); -} - - -/**************************************************************************** -interpret an internet address or name into an IP address in 4 byte form -****************************************************************************/ -uint32 interpret_addr(char *str) -{ - struct hostent *hp; - uint32 res; - int i; - BOOL pure_address = True; - - if (strcmp(str,"0.0.0.0") == 0) return(0); - if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF); - - for (i=0; pure_address && str[i]; i++) - if (!(isdigit(str[i]) || str[i] == '.')) - pure_address = False; - - /* if it's in the form of an IP address then get the lib to interpret it */ - if (pure_address) { - res = inet_addr(str); - } else { - /* otherwise assume it's a network name of some sort and use - Get_Hostbyname */ - if ((hp = Get_Hostbyname(str)) == 0) { - DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str)); - return 0; - } - if(hp->h_addr == NULL) { - DEBUG(3,("Get_Hostbyname: host address is invalid for host %s.\n",str)); - return 0; - } - putip((char *)&res,(char *)hp->h_addr); - } - - if (res == (uint32)-1) return(0); - - return(res); -} - -/******************************************************************* - a convenient addition to interpret_addr() - ******************************************************************/ -struct in_addr *interpret_addr2(char *str) -{ - static struct in_addr ret; - uint32 a = interpret_addr(str); - ret.s_addr = a; - return(&ret); -} - -/******************************************************************* - check if an IP is the 0.0.0.0 - ******************************************************************/ -BOOL zero_ip(struct in_addr ip) -{ - uint32 a; - putip((char *)&a,(char *)&ip); - return(a == 0); -} - - -/******************************************************************* - matchname - determine if host name matches IP address - ******************************************************************/ -static BOOL matchname(char *remotehost,struct in_addr addr) -{ - struct hostent *hp; - int i; - - if ((hp = Get_Hostbyname(remotehost)) == 0) { - DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost)); - return False; - } - - /* - * Make sure that gethostbyname() returns the "correct" host name. - * Unfortunately, gethostbyname("localhost") sometimes yields - * "localhost.domain". Since the latter host name comes from the - * local DNS, we just have to trust it (all bets are off if the local - * DNS is perverted). We always check the address list, though. - */ - - if (strcasecmp(remotehost, hp->h_name) - && strcasecmp(remotehost, "localhost")) { - DEBUG(0,("host name/name mismatch: %s != %s", - remotehost, hp->h_name)); - return False; - } - - /* Look up the host address in the address list we just got. */ - for (i = 0; hp->h_addr_list[i]; i++) { - if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0) - return True; - } - - /* - * The host name does not map to the original host address. Perhaps - * someone has compromised a name server. More likely someone botched - * it, but that could be dangerous, too. - */ - - DEBUG(0,("host name/address mismatch: %s != %s", - inet_ntoa(addr), hp->h_name)); - return False; -} - -/******************************************************************* - Reset the 'done' variables so after a client process is created - from a fork call these calls will be re-done. This should be - expanded if more variables need reseting. - ******************************************************************/ - -static BOOL global_client_name_done = False; -static BOOL global_client_addr_done = False; - -void reset_globals_after_fork() -{ - global_client_name_done = False; - global_client_addr_done = False; -} - -/******************************************************************* - return the DNS name of the client - ******************************************************************/ -char *client_name(void) -{ - extern int Client; - struct sockaddr sa; - struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); - int length = sizeof(sa); - static pstring name_buf; - struct hostent *hp; - - if (global_client_name_done) - return name_buf; - - strcpy(name_buf,"UNKNOWN"); - - if (getpeername(Client, &sa, &length) < 0) { - DEBUG(0,("getpeername failed\n")); - return name_buf; - } - - /* Look up the remote host name. */ - if ((hp = gethostbyaddr((char *) &sockin->sin_addr, - sizeof(sockin->sin_addr), - AF_INET)) == 0) { - DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr())); - StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1); - } else { - StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1); - if (!matchname(name_buf, sockin->sin_addr)) { - DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr())); - strcpy(name_buf,"UNKNOWN"); - } - } - global_client_name_done = True; - return name_buf; -} - -/******************************************************************* - return the IP addr of the client as a string - ******************************************************************/ -char *client_addr(void) -{ - extern int Client; - struct sockaddr sa; - struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa); - int length = sizeof(sa); - static fstring addr_buf; - - if (global_client_addr_done) - return addr_buf; - - strcpy(addr_buf,"0.0.0.0"); - - if (getpeername(Client, &sa, &length) < 0) { - DEBUG(0,("getpeername failed\n")); - return addr_buf; - } - - fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); - - global_client_addr_done = True; - return addr_buf; -} - -/******************************************************************* -sub strings with useful parameters -Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and -Paul Rippin <pr3245@nopc.eurostat.cec.be> -********************************************************************/ -void standard_sub_basic(char *str) - { - char *s, *p; - char pidstr[10]; - struct passwd *pass; - - for (s = str ; (p = strchr(s,'%')) != NULL ; s = p ) - { - switch (*(p+1)) - { - case 'G' : if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL) - string_sub(p,"%G",gidtoname(pass->pw_gid)); - else - p += 2; - break; - case 'I' : string_sub(p,"%I",client_addr()); break; - case 'L' : string_sub(p,"%L",local_machine); break; - case 'M' : string_sub(p,"%M",client_name()); break; - case 'R' : string_sub(p,"%R",remote_proto); break; - case 'T' : string_sub(p,"%T",timestring()); break; - case 'U' : string_sub(p,"%U",sesssetup_user); break; - case 'a' : string_sub(p,"%a",remote_arch); break; - case 'd' : sprintf(pidstr,"%d",(int)getpid()); - string_sub(p,"%d",pidstr); - break; - case 'h' : string_sub(p,"%h",myhostname); break; - case 'm' : string_sub(p,"%m",remote_machine); break; - case 'v' : string_sub(p,"%v",VERSION); break; - case '\0' : p++; break; /* don't run off end if last character is % */ - default : p+=2; break; - } - } - return; -} - -/******************************************************************* -are two IPs on the same subnet? -********************************************************************/ -BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask) -{ - uint32 net1,net2,nmask; - - nmask = ntohl(mask.s_addr); - net1 = ntohl(ip1.s_addr); - net2 = ntohl(ip2.s_addr); - - return((net1 & nmask) == (net2 & nmask)); -} - - -/******************************************************************* -write a string in unicoode format -********************************************************************/ -int PutUniCode(char *dst,char *src) -{ - int ret = 0; - while (*src) { - dst[ret++] = src[0]; - dst[ret++] = 0; - src++; - } - dst[ret++]=0; - dst[ret++]=0; - return(ret); -} - -/**************************************************************************** -a wrapper for gethostbyname() that tries with all lower and all upper case -if the initial name fails -****************************************************************************/ -struct hostent *Get_Hostbyname(char *name) -{ - char *name2 = strdup(name); - struct hostent *ret; - - if (!name2) - { - DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n")); - exit(0); - } - - if (!isalnum(*name2)) - { - free(name2); - return(NULL); - } - - ret = sys_gethostbyname(name2); - if (ret != NULL) - { - free(name2); - return(ret); - } - - /* try with all lowercase */ - strlower(name2); - ret = sys_gethostbyname(name2); - if (ret != NULL) - { - free(name2); - return(ret); - } - - /* try with all uppercase */ - strupper(name2); - ret = sys_gethostbyname(name2); - if (ret != NULL) - { - free(name2); - return(ret); - } - - /* nothing works :-( */ - free(name2); - return(NULL); -} - - -/**************************************************************************** -check if a process exists. Does this work on all unixes? -****************************************************************************/ -BOOL process_exists(int pid) -{ -#ifdef LINUX - fstring s; - sprintf(s,"/proc/%d",pid); - return(directory_exist(s,NULL)); -#else - { - static BOOL tested=False; - static BOOL ok=False; - fstring s; - if (!tested) { - tested = True; - sprintf(s,"/proc/%05d",(int)getpid()); - ok = file_exist(s,NULL); - } - if (ok) { - sprintf(s,"/proc/%05d",pid); - return(file_exist(s,NULL)); - } - } - - /* CGH 8/16/96 - added ESRCH test */ - return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH); -#endif -} - - -/******************************************************************* -turn a uid into a user name -********************************************************************/ -char *uidtoname(int uid) -{ - static char name[40]; - struct passwd *pass = getpwuid(uid); - if (pass) return(pass->pw_name); - sprintf(name,"%d",uid); - return(name); -} - -/******************************************************************* -turn a gid into a group name -********************************************************************/ -char *gidtoname(int gid) -{ - static char name[40]; - struct group *grp = getgrgid(gid); - if (grp) return(grp->gr_name); - sprintf(name,"%d",gid); - return(name); -} - -/******************************************************************* -block sigs -********************************************************************/ -void BlockSignals(BOOL block,int signum) -{ -#ifdef USE_SIGBLOCK - int block_mask = sigmask(signum); - static int oldmask = 0; - if (block) - oldmask = sigblock(block_mask); - else - sigsetmask(oldmask); -#elif defined(USE_SIGPROCMASK) - sigset_t set; - sigemptyset(&set); - sigaddset(&set,signum); - sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL); -#endif -} - -#if AJT -/******************************************************************* -my own panic function - not suitable for general use -********************************************************************/ -void ajt_panic(void) -{ - system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT"); -} -#endif - -#ifdef USE_DIRECT -#define DIRECT direct -#else -#define DIRECT dirent -#endif - -/******************************************************************* -a readdir wrapper which just returns the file name -also return the inode number if requested -********************************************************************/ -char *readdirname(void *p) -{ - struct DIRECT *ptr; - char *dname; - - if (!p) return(NULL); - - ptr = (struct DIRECT *)readdir(p); - if (!ptr) return(NULL); - - dname = ptr->d_name; - -#ifdef NEXT2 - if (telldir(p) < 0) return(NULL); -#endif - -#ifdef SUNOS5 - /* this handles a broken compiler setup, causing a mixture - of BSD and SYSV headers and libraries */ - { - static BOOL broken_readdir = False; - if (!broken_readdir && !(*(dname)) && strequal("..",dname-2)) - { - DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n")); - broken_readdir = True; - } - if (broken_readdir) - dname = dname - 2; - } -#endif - - { - static pstring buf; - pstrcpy(buf, dname); - unix_to_dos(buf, True); - dname = buf; - } - - return(dname); -} - -/******************************************************************* - Utility function used to decide if the last component - of a path matches a (possibly wildcarded) entry in a namelist. -********************************************************************/ - -BOOL is_in_path(char *name, name_compare_entry *namelist) -{ - pstring last_component; - char *p; - - DEBUG(8, ("is_in_path: %s\n", name)); - - /* if we have no list it's obviously not in the path */ - if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) - { - DEBUG(8,("is_in_path: no name list.\n")); - return False; - } - - /* Get the last component of the unix name. */ - p = strrchr(name, '/'); - strncpy(last_component, p ? p : name, sizeof(last_component)-1); - last_component[sizeof(last_component)-1] = '\0'; - - for(; namelist->name != NULL; namelist++) - { - if(namelist->is_wild) - { - /* look for a wildcard match. */ - if (mask_match(last_component, namelist->name, case_sensitive, False)) - { - DEBUG(8,("is_in_path: mask match succeeded\n")); - return True; - } - } - else - { - if((case_sensitive && (strcmp(last_component, namelist->name) == 0))|| - (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) - { - DEBUG(8,("is_in_path: match succeeded\n")); - return True; - } - } - } - DEBUG(8,("is_in_path: match not found\n")); - - return False; -} - -/******************************************************************* - Strip a '/' separated list into an array of - name_compare_enties structures suitable for - passing to is_in_path(). We do this for - speed so we can pre-parse all the names in the list - and don't do it for each call to is_in_path(). - namelist is modified here and is assumed to be - a copy owned by the caller. - We also check if the entry contains a wildcard to - remove a potentially expensive call to mask_match - if possible. -********************************************************************/ - -void set_namearray(name_compare_entry **ppname_array, char *namelist) -{ - char *name_end; - char *nameptr = namelist; - int num_entries = 0; - int i; - - (*ppname_array) = NULL; - - if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) - return; - - /* We need to make two passes over the string. The - first to count the number of elements, the second - to split it. - */ - while(*nameptr) - { - if ( *nameptr == '/' ) - { - /* cope with multiple (useless) /s) */ - nameptr++; - continue; - } - /* find the next / */ - name_end = strchr(nameptr, '/'); - - /* oops - the last check for a / didn't find one. */ - if (name_end == NULL) - break; - - /* next segment please */ - nameptr = name_end + 1; - num_entries++; - } - - if(num_entries == 0) - return; - - if(( (*ppname_array) = (name_compare_entry *)malloc( - (num_entries + 1) * sizeof(name_compare_entry))) == NULL) - { - DEBUG(0,("set_namearray: malloc fail\n")); - return; - } - - /* Now copy out the names */ - nameptr = namelist; - i = 0; - while(*nameptr) - { - if ( *nameptr == '/' ) - { - /* cope with multiple (useless) /s) */ - nameptr++; - continue; - } - /* find the next / */ - if ((name_end = strchr(nameptr, '/')) != NULL) - { - *name_end = 0; - } - - /* oops - the last check for a / didn't find one. */ - if(name_end == NULL) - break; - - (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) || - (strchr( nameptr, '*')!=NULL)); - if(((*ppname_array)[i].name = strdup(nameptr)) == NULL) - { - DEBUG(0,("set_namearray: malloc fail (1)\n")); - return; - } - - /* next segment please */ - nameptr = name_end + 1; - i++; - } - - (*ppname_array)[i].name = NULL; - - return; -} - -/**************************************************************************** -routine to free a namearray. -****************************************************************************/ - -void free_namearray(name_compare_entry *name_array) -{ - if(name_array == 0) - return; - - if(name_array->name != NULL) - free(name_array->name); - - free((char *)name_array); -} - -/**************************************************************************** -routine to do file locking -****************************************************************************/ -BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type) -{ -#if HAVE_FCNTL_LOCK - struct flock lock; - int ret; - -#if 1 - uint32 mask = 0xC0000000; - - /* make sure the count is reasonable, we might kill the lockd otherwise */ - count &= ~mask; - - /* the offset is often strange - remove 2 of its bits if either of - the top two bits are set. Shift the top ones by two bits. This - still allows OLE2 apps to operate, but should stop lockd from - dieing */ - if ((offset & mask) != 0) - offset = (offset & ~mask) | ((offset & mask) >> 2); -#else - uint32 mask = ((unsigned)1<<31); - - /* interpret negative counts as large numbers */ - if (count < 0) - count &= ~mask; - - /* no negative offsets */ - offset &= ~mask; - - /* count + offset must be in range */ - while ((offset < 0 || (offset + count < 0)) && mask) - { - offset &= ~mask; - mask = mask >> 1; - } -#endif - - - DEBUG(8,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type)); - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = (int)offset; - lock.l_len = (int)count; - lock.l_pid = 0; - - errno = 0; - - ret = fcntl(fd,op,&lock); - - if (errno != 0) - DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno))); - - /* a lock query */ - if (op == F_GETLK) - { - if ((ret != -1) && - (lock.l_type != F_UNLCK) && - (lock.l_pid != 0) && - (lock.l_pid != getpid())) - { - DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid)); - return(True); - } - - /* it must be not locked or locked by me */ - return(False); - } - - /* a lock set or unset */ - if (ret == -1) - { - DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n", - offset,count,op,type,strerror(errno))); - - /* perhaps it doesn't support this sort of locking?? */ - if (errno == EINVAL) - { - DEBUG(3,("locking not supported? returning True\n")); - return(True); - } - - return(False); - } - - /* everything went OK */ - DEBUG(8,("Lock call successful\n")); - - return(True); -#else - return(False); -#endif -} - -/******************************************************************* -lock a file - returning a open file descriptor or -1 on failure -The timeout is in seconds. 0 means no timeout -********************************************************************/ -int file_lock(char *name,int timeout) -{ - int fd = open(name,O_RDWR|O_CREAT,0666); - time_t t=0; - if (fd < 0) return(-1); - -#if HAVE_FCNTL_LOCK - if (timeout) t = time(NULL); - while (!timeout || (time(NULL)-t < timeout)) { - if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd); - msleep(LOCK_RETRY_TIMEOUT); - } - return(-1); -#else - return(fd); -#endif -} - -/******************************************************************* -unlock a file locked by file_lock -********************************************************************/ -void file_unlock(int fd) -{ - if (fd<0) return; -#if HAVE_FCNTL_LOCK - fcntl_lock(fd,F_SETLK,0,1,F_UNLCK); -#endif - close(fd); -} - -/******************************************************************* -is the name specified one of my netbios names -returns true is it is equal, false otherwise -********************************************************************/ -BOOL is_myname(char *s) -{ - int n; - BOOL ret = False; - - for (n=0; my_netbios_names[n]; n++) { - if (strequal(my_netbios_names[n], s)) - ret=True; - } - DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret)); - return(ret); -} - -/******************************************************************* -set the horrid remote_arch string based on an enum. -********************************************************************/ -void set_remote_arch(enum remote_arch_types type) -{ - ra_type = type; - switch( type ) - { - case RA_WFWG: - strcpy(remote_arch, "WfWg"); - return; - case RA_OS2: - strcpy(remote_arch, "OS2"); - return; - case RA_WIN95: - strcpy(remote_arch, "Win95"); - return; - case RA_WINNT: - strcpy(remote_arch, "WinNT"); - return; - case RA_SAMBA: - strcpy(remote_arch,"Samba"); - return; - default: - ra_type = RA_UNKNOWN; - strcpy(remote_arch, "UNKNOWN"); - break; - } -} - -/******************************************************************* - Get the remote_arch type. -********************************************************************/ -enum remote_arch_types get_remote_arch() -{ - return ra_type; -} - - -/******************************************************************* -skip past some unicode strings in a buffer -********************************************************************/ -char *skip_unicode_string(char *buf,int n) -{ - while (n--) - { - while (*buf) - buf += 2; - buf += 2; - } - return(buf); -} - -/******************************************************************* -Return a ascii version of a unicode string -Hack alert: uses fixed buffer(s) and only handles ascii strings -********************************************************************/ -#define MAXUNI 1024 -char *unistr2(uint16 *buf) -{ - static char lbufs[8][MAXUNI]; - static int nexti; - char *lbuf = lbufs[nexti]; - char *p; - nexti = (nexti+1)%8; - for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++) - { - *p = *buf; - } - *p = 0; - return lbuf; -} - -/******************************************************************* -Return a ascii version of a unicode string -Hack alert: uses fixed buffer(s) and only handles ascii strings -********************************************************************/ -#define MAXUNI 1024 -char *unistr(char *buf) -{ - static char lbufs[8][MAXUNI]; - static int nexti; - char *lbuf = lbufs[nexti]; - char *p; - - nexti = (nexti+1)%8; - - for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2) - { - *p = *buf; - } - *p = 0; - return lbuf; -} - -/******************************************************************* -strncpy for unicode strings -********************************************************************/ -int unistrncpy(char *dst, char *src, int len) -{ - int num_wchars = 0; - - while (*src && len > 0) - { - *dst++ = *src++; - *dst++ = *src++; - len--; - num_wchars++; - } - *dst++ = 0; - *dst++ = 0; - - return num_wchars; -} - - -/******************************************************************* -strcpy for unicode strings. returns length (in num of wide chars) -********************************************************************/ -int unistrcpy(char *dst, char *src) -{ - int num_wchars = 0; - - while (*src) - { - *dst++ = *src++; - *dst++ = *src++; - num_wchars++; - } - *dst++ = 0; - *dst++ = 0; - - return num_wchars; -} - - -/******************************************************************* -safe string copy into a fstring -********************************************************************/ -void fstrcpy(char *dest, char *src) -{ - int maxlength = sizeof(fstring) - 1; - if (!dest) { - DEBUG(0,("ERROR: NULL dest in fstrcpy\n")); - return; - } - - if (!src) { - *dest = 0; - return; - } - - while (maxlength-- && *src) - *dest++ = *src++; - *dest = 0; - if (*src) { - DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n", - strlen(src))); - } -} - -/******************************************************************* -safe string copy into a pstring -********************************************************************/ -void pstrcpy(char *dest, char *src) -{ - int maxlength = sizeof(pstring) - 1; - if (!dest) { - DEBUG(0,("ERROR: NULL dest in pstrcpy\n")); - return; - } - - if (!src) { - *dest = 0; - return; - } - - while (maxlength-- && *src) - *dest++ = *src++; - *dest = 0; - if (*src) { - DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n", - strlen(src))); - } -} - - -/******************************************************************* -align a pointer to a multiple of 4 bytes -********************************************************************/ -char *align4(char *q, char *base) -{ - if ((q - base) & 3) - { - q += 4 - ((q - base) & 3); - } - return q; -} - -/******************************************************************* -align a pointer to a multiple of 2 bytes -********************************************************************/ -char *align2(char *q, char *base) -{ - if ((q - base) & 1) - { - q++; - } - return q; -} - -/******************************************************************* -align a pointer to a multiple of align_offset bytes. looks like it -will work for offsets of 0, 2 and 4... -********************************************************************/ -char *align_offset(char *q, char *base, int align_offset_len) -{ - if (align_offset_len != 0 && ((q - base) & (align_offset_len-1))) - { - q += align_offset_len - ((q - base) & (align_offset_len)); - } - return q; -} - diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c deleted file mode 100644 index 4c81177fb20..00000000000 --- a/source/libsmb/credentials.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - code to manipulate domain credentials - Copyright (C) Andrew Tridgell 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" - - -/**************************************************************************** - setup the session key. -Input: 8 byte challenge block - 8 byte server challenge block - 16 byte md4 encrypted password -Output: - 8 byte session key -****************************************************************************/ -void cred_session_key(char *challenge, char *srv_challenge, char *pass, - char *session_key) -{ - uint32 sum[2]; - char sum2[8]; - char buf[8]; - - sum[0] = IVAL(challenge, 0) + IVAL(srv_challenge, 0); - sum[1] = IVAL(challenge, 4) + IVAL(srv_challenge, 4); - - SIVAL(sum2,0,sum[0]); - SIVAL(sum2,4,sum[1]); - - E1(pass,sum2,buf); - E1(pass+9,buf,session_key); -} - - -/**************************************************************************** -create a credential - -Input: - 8 byte sesssion key - 8 byte stored credential - 4 byte timestamp - -Output: - 8 byte credential -****************************************************************************/ -void cred_create(char *session_key, char *stored_cred, UTIME timestamp, - char *cred) -{ - char key2[7]; - char buf[8]; - char timecred[8]; - - memcpy(timecred, stored_cred, 8); - SIVAL(timecred, 0, IVAL(stored_cred, 0) + timestamp.time); - - E1(session_key, timecred, buf); - memset(key2, 0, 7); - key2[0] = session_key[7]; - E1(key2, buf, cred); -} - - -/**************************************************************************** - check a supplied credential - -Input: - 8 byte received credential - 8 byte sesssion key - 8 byte stored credential - 4 byte timestamp - -Output: - returns 1 if computed credential matches received credential - returns 0 otherwise -****************************************************************************/ -int cred_assert(char *cred, char *session_key, char *stored_cred, - NTTIME timestamp) -{ - char cred2[8]; - - cred_create(session_key, stored_cred, timestamp, cred2); - - return memcmp(cred, cred2, 8) == 0; -} - 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 48f988de2a2..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 { - 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. - ****************************************************************************/ - -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) -{ - fstrcpy(n->name,name); - strupper(n->name); - n->name_type = type; - fstrcpy(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/smbdes.c b/source/libsmb/smbdes.c deleted file mode 100644 index 1c38612b739..00000000000 --- a/source/libsmb/smbdes.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - - a partial implementation of DES designed for use in the - SMB authentication protocol - - Copyright (C) Andrew Tridgell 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. -*/ - - -/* NOTES: - - This code makes no attempt to be fast! In fact, it is a very - slow implementation - - This code is NOT a complete DES implementation. It implements only - the minimum necessary for SMB authentication, as used by all SMB - products (including every copy of Microsoft Windows95 ever sold) - - In particular, it can only do a unchained forward DES pass. This - means it is not possible to use this code for encryption/decryption - of data, instead it is only useful as a "hash" algorithm. - - There is no entry point into this code that allows normal DES operation. - - I believe this means that this code does not come under ITAR - regulations but this is NOT a legal opinion. If you are concerned - about the applicability of ITAR regulations to this code then you - should confirm it for yourself (and maybe let me know if you come - up with a different answer to the one above) -*/ - - - -static int perm1[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}; - -static int perm2[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}; - -static int perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7}; - -static int perm4[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 perm5[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}; - - -static int perm6[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}; - - -static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; - -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}}}; - -static void permute(char *out, char *in, int *p, int n) -{ - int i; - for (i=0;i<n;i++) - out[i] = in[p[i]-1]; -} - -static void lshift(char *d, int count, int n) -{ - char out[64]; - int i; - for (i=0;i<n;i++) - out[i] = d[(i+count)%n]; - for (i=0;i<n;i++) - d[i] = out[i]; -} - -static void concat(char *out, char *in1, char *in2, int l1, int l2) -{ - while (l1--) - *out++ = *in1++; - while (l2--) - *out++ = *in2++; -} - -static void xor(char *out, char *in1, char *in2, int n) -{ - int i; - for (i=0;i<n;i++) - out[i] = in1[i] ^ in2[i]; -} - -static void dohash(char *out, char *in, char *key) -{ - int i, j, k; - char pk1[56]; - char c[28]; - char d[28]; - char cd[56]; - char ki[16][48]; - char pd1[64]; - char l[32], r[32]; - char rl[64]; - - permute(pk1, key, perm1, 56); - - for (i=0;i<28;i++) - c[i] = pk1[i]; - for (i=0;i<28;i++) - d[i] = pk1[i+28]; - - for (i=0;i<16;i++) { - lshift(c, sc[i], 28); - lshift(d, sc[i], 28); - - concat(cd, c, d, 28, 28); - permute(ki[i], cd, perm2, 48); - } - - permute(pd1, in, perm3, 64); - - for (j=0;j<32;j++) { - l[j] = pd1[j]; - r[j] = pd1[j+32]; - } - - for (i=0;i<16;i++) { - char er[48]; - char erk[48]; - char b[8][6]; - char cb[32]; - char pcb[32]; - char r2[32]; - - permute(er, r, perm4, 48); - - xor(erk, er, ki[i], 48); - - for (j=0;j<8;j++) - for (k=0;k<6;k++) - b[j][k] = erk[j*6 + k]; - - for (j=0;j<8;j++) { - int m, n; - m = (b[j][0]<<1) | b[j][5]; - - n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4]; - - for (k=0;k<4;k++) - b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0; - } - - for (j=0;j<8;j++) - for (k=0;k<4;k++) - cb[j*4+k] = b[j][k]; - permute(pcb, cb, perm5, 32); - - xor(r2, l, pcb, 32); - - for (j=0;j<32;j++) - l[j] = r[j]; - - for (j=0;j<32;j++) - r[j] = r2[j]; - } - - concat(rl, r, l, 32, 32); - - permute(out, rl, perm6, 64); -} - -static void str_to_key(unsigned char *str,unsigned char *key) -{ - 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); - } -} - - -static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) -{ - int i; - char outb[64]; - char inb[64]; - char keyb[64]; - unsigned char key2[8]; - - str_to_key(key, key2); - - for (i=0;i<64;i++) { - inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0; - keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0; - outb[i] = 0; - } - - dohash(outb, inb, keyb); - - for (i=0;i<8;i++) { - out[i] = 0; - } - - for (i=0;i<64;i++) { - if (outb[i]) - out[i/8] |= (1<<(7-(i%8))); - } -} - -void E_P16(unsigned char *p14,unsigned char *p16) -{ - unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; - smbhash(p16, sp8, p14); - smbhash(p16+8, sp8, p14+7); -} - -void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) -{ - smbhash(p24, c8, p21); - smbhash(p24+8, c8, p21+7); - smbhash(p24+16, c8, p21+14); -} - - diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c deleted file mode 100644 index 27172fd4136..00000000000 --- a/source/libsmb/smbencrypt.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - 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" - -extern int DEBUGLEVEL; - -#include "byteorder.h" - -/* - 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 len; - int16 wpwd[129]; - - /* 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); - - mdfour(p16, (unsigned char *)wpwd, len); -} - -/* 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); -} - diff --git a/source/locking/locking.c b/source/locking/locking.c deleted file mode 100644 index 639bc7be0ba..00000000000 --- a/source/locking/locking.c +++ /dev/null @@ -1,1535 +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. - - September 1997. Jeremy Allison (jallison@whistle.com). Added oplock - support. - -*/ - -#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; - - pstrcpy(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\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 (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; - int share_mode = entry_scanner_p->share_mode; - - 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 %d (number of entries now = %d)\n", - pid, 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; - share_array[num_entries_copied].op_port = entry_scanner_p->op_port; - share_array[num_entries_copied].op_type = entry_scanner_p->op_type; - 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, uint16 port, uint16 op_type) -{ - 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; - new_entry_p->op_port = port; - new_entry_p->op_type = op_type; - 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); -} - -/******************************************************************* -Remove an oplock port and mode entry from a share mode. -********************************************************************/ -BOOL remove_share_oplock(int fnum, share_lock_token token) -{ - 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:remove_share_oplock (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()); - - if(mode_array[hash_entry] == NULL_OFFSET) - { - DEBUG(0,("PANIC ERROR:remove_share_oplock (FAST_SHARE_MODES): hash bucket %d empty\n", - hash_entry)); - return False; - } - - 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:remove_share_oplock (FAST_SHARE_MODES): no entry found for dev %d, \ -inode %d in hash bucket %d\n", dev, inode, hash_entry)); - return False; - } - - if(file_scanner_p->locking_version != LOCKING_VERSION) - { - DEBUG(0,("ERROR: remove_share_oplock (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 False; - } - - 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) && - (entry_scanner_p->share_mode == Files[fnum].share_mode) && - (memcmp(&entry_scanner_p->time, - &Files[fnum].open_time,sizeof(struct timeval)) == 0) ) - { - /* Delete the oplock info. */ - entry_scanner_p->op_port = 0; - entry_scanner_p->op_type = 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) - { - DEBUG(0,("ERROR: remove_share_oplock (FAST_SHARE_MODES): No oplock granted share \ -mode record found dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry)); - return False; - } - - 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; - BOOL gotlock = False; - unbecome_user(); - old_umask = umask(0); - - /* - * There was a race condition in the original slow share mode code. - * A smbd could open a share mode file, and before getting - * the lock, another smbd could delete the last entry for - * the share mode file and delete the file entry from the - * directory. Thus this smbd would be left with a locked - * share mode fd attached to a file that no longer had a - * directory entry. Thus another smbd would think that - * there were no outstanding opens on the file. To fix - * this we now check we can do a stat() call on the filename - * before allowing the lock to proceed, and back out completely - * and try the open again if we cannot. - * Jeremy Allison (jallison@whistle.com). - */ - - do - { - struct stat dummy_stat; - -#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,0666); -#endif /* SECURE_SHARE_MODES */ - - /* 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 on file %s failed with %s\n", - fname, strerror(errno))); - close(fd); - return False; - } - - /* - * If we cannot stat the filename, the file was deleted between - * the open and the lock call. Back out and try again. - */ - - if(stat(fname, &dummy_stat)!=0) - { - DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n", - fname, strerror(errno))); - close(fd); - } - else - gotlock = True; - } while(!gotlock); - - 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; - } - } - - *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(fd); - 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,SMF_VERSION_OFFSET) != LOCKING_VERSION) { - DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, - IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(cnum, fname); - return -1; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= SMF_HEADER_LENGTH; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 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 - 16 - oplock port (if oplocks in use) - 2 bytes. - */ - - 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,SMF_NUM_ENTRIES_OFFSET); - - 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 + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for( i = 0; i < num_entries; i++) - { - int pid; - char *p = base + (i*SMF_ENTRY_LENGTH); - - pid = IVAL(p,SME_PID_OFFSET); - - 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,SME_SHAREMODE_OFFSET), fname)); - continue; - } - share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET); - share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET); - share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET); - share_array[num_entries_copied].pid = pid; - share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET); - share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); - - 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, SMF_NUM_ENTRIES_OFFSET, num_entries_copied); - for( i = 0; i < num_entries_copied; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - SIVAL(p,SME_PID_OFFSET,share_array[i].pid); - SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode); - SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec); - SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type); - } - - newsize = (base - buf) + (SMF_ENTRY_LENGTH*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,SMF_NUM_ENTRIES_OFFSET); - - 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 + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != 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 + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH); - - 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,SMF_NUM_ENTRIES_OFFSET, 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) + (SMF_ENTRY_LENGTH*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, uint16 port, uint16 op_type) -{ - 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 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", - sb.st_size + SMF_ENTRY_LENGTH)); - 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,SMF_VERSION_OFFSET) != LOCKING_VERSION) - { - DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \ -locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET), - LOCKING_VERSION)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */ - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 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(SMF_HEADER_LENGTH + - strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL) - { - DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n")); - return False; - } - SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION); - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0); - SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1); - strcpy(buf + SMF_HEADER_LENGTH, fs_p->name); - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH); - SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec); - SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec); - SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode); - SIVAL(p,SME_PID_OFFSET,pid); - SSVAL(p,SME_PORT_OFFSET,port); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type); - - num_entries++; - - SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,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*SMF_ENTRY_LENGTH)) != - (header_size + (num_entries*SMF_ENTRY_LENGTH))) - { - 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 + (SMF_ENTRY_LENGTH*num_entries))!= 0) - { - DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \ -mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*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; -} - -/******************************************************************* -Remove an oplock port and mode entry from a share mode. -********************************************************************/ -BOOL remove_share_oplock(int fnum, share_lock_token token) -{ - pstring fname; - int fd = (int)token; - char *buf = 0; - char *base = 0; - int num_entries; - int fsize; - int i; - files_struct *fs_p = &Files[fnum]; - int pid; - BOOL found = 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: remove_share_oplock: Failed to read share file %s\n", - fname)); - return False; - } - - if(new_file == True) - { - DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \ -deleting it.\n", fname)); - delete_share_file(fs_p->cnum, fname); - return False; - } - - num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET); - - DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n", - fname, num_entries)); - - /* PARANOIA TEST */ - if(num_entries < 0) - { - DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \ -for share file %d\n", num_entries, fname)); - return False; - } - - if(num_entries == 0) - { - /* No entries - just delete the file. */ - DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n", - fname)); - if(buf) - free(buf); - delete_share_file(fs_p->cnum, fname); - return False; - } - - pid = getpid(); - - /* Go through the entries looking for the particular one - we have set - remove the oplock settings on it. - */ - - base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - - for(i = 0; i < num_entries; i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - - if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) || - (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) || - (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) || - (IVAL(p,SME_PID_OFFSET) != pid)) - continue; - - DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \ -from the share file %s\n", i, num_entries, fname)); - - SSVAL(p,SME_PORT_OFFSET,0); - SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0); - found = True; - break; - } - - if(!found) - { - DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname)); - if(buf) - free(buf); - return False; - } - - /* Re-write the file - and truncate it at the correct point. */ - if(lseek(fd, 0, SEEK_SET) != 0) - { - DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \ -position 0 for share mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries); - if(write(fd, buf, fsize) != fsize) - { - DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \ -mode file %s (%s)\n", fname, strerror(errno))); - if(buf) - free(buf); - return False; - } - - return True; - -} -#endif /* FAST_SHARE_MODES */ diff --git a/source/locking/shmem.c b/source/locking/shmem.c deleted file mode 100644 index bbb11f215a0..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 %s\n",strerror(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 %s\n",strerror(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 = -((int)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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 = -((int)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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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 %s\n",strerror(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/lsaparse.c b/source/lsaparse.c deleted file mode 100644 index 9ea6f566b23..00000000000 --- a/source/lsaparse.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Samba utility functions - Copyright (C) Luke Leighton 1996 - 1997 Paul Ashton 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; - - -/******************************************************************* -reads or writes an LSA_R_OPEN_POL structure. -********************************************************************/ -char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align) -{ - if (r_p == NULL) return NULL; - - q = smb_io_pol_hnd(io, &(r_p->pol), q, base, align); - - RW_IVAL(io, q, r_p->status, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes an LSA_Q_QUERY_INFO structure. -********************************************************************/ -char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align) -{ - if (q_q == NULL) return NULL; - - q = smb_io_pol_hnd(io, &(q_q->pol), q, base, align); - - RW_SVAL(io, q, q_q->info_class, 0); q += 2; - - return q; -} - -/******************************************************************* -reads or writes an LSA_Q_QUERY_INFO structure. -********************************************************************/ -char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align) -{ - if (r_q == NULL) return NULL; - - RW_IVAL(io, q, r_q->undoc_buffer, 0); q += 4; - - if (r_q->undoc_buffer != 0) - { - RW_SVAL(io, q, r_q->info_class, 0); q += 2; - - switch (r_q->info_class) - { - case 3: - { - q = smb_io_dom_query_3(io, &(r_q->dom.id3), q, base, align); - break; - } - case 5: - { - q = smb_io_dom_query_5(io, &(r_q->dom.id3), q, base, align); - break; - } - default: - { - /* PANIC! */ - break; - } - } - } - - RW_IVAL(io, q, r_q->status, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align) -{ - int i; - - if (q_s == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_pol_hnd(io, &(q_s->pol_hnd), q, base, align); /* policy handle */ - - RW_IVAL(io, q, q_s->num_entries, 0); q += 4; - RW_IVAL(io, q, q_s->buffer_dom_sid, 0); q += 4; /* undocumented domain SID buffer pointer */ - RW_IVAL(io, q, q_s->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer */ - - for (i = 0; i < q_s->num_entries; i++) - { - RW_IVAL(io, q, q_s->buffer_lookup_sids[i], 0); q += 4; /* undocumented domain SID pointers to be looked up. */ - } - - for (i = 0; i < q_s->num_entries; i++) - { - q = smb_io_dom_sid(io, &(q_s->dom_sids[i]), q, base, align); /* domain SIDs to be looked up. */ - } - - RW_PCVAL(io, q, q_s->undoc, 16); q += 16; /* completely undocumented 16 bytes */ - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align) -{ - int i; - - if (r_s == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_dom_r_ref(io, &(r_s->dom_ref), q, base, align); /* domain reference info */ - - RW_IVAL(io, q, r_s->num_entries, 0); q += 4; - RW_IVAL(io, q, r_s->undoc_buffer, 0); q += 4; - RW_IVAL(io, q, r_s->num_entries2, 0); q += 4; - - for (i = 0; i < r_s->num_entries2; i++) - { - q = smb_io_dom_sid2(io, &(r_s->dom_sid[i]), q, base, align); /* domain SIDs being looked up */ - } - - RW_IVAL(io, q, r_s->num_entries3, 0); q += 4; - - RW_IVAL(io, q, r_s->status, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align) -{ - int i; - - if (q_r == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_pol_hnd(io, &(q_r->pol_hnd), q, base, align); /* policy handle */ - - RW_IVAL(io, q, q_r->num_entries, 0); q += 4; - RW_IVAL(io, q, q_r->num_entries2, 0); q += 4; - RW_IVAL(io, q, q_r->buffer_dom_sid, 0); q += 4; /* undocumented domain SID buffer pointer */ - RW_IVAL(io, q, q_r->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer */ - - for (i = 0; i < q_r->num_entries; i++) - { - q = smb_io_dom_name(io, &(q_r->lookup_name[i]), q, base, 0); /* names to be looked up */ - } - - RW_PCVAL(io, q, q_r->undoc, UNKNOWN_LEN); q += UNKNOWN_LEN; /* completely undocumented bytes of unknown length */ - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align) -{ - int i; - - if (r_r == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_dom_r_ref(io, &(r_r->dom_ref), q, base, align); /* domain reference info */ - - RW_IVAL(io, q, r_r->num_entries, 0); q += 4; - RW_IVAL(io, q, r_r->undoc_buffer, 0); q += 4; - RW_IVAL(io, q, r_r->num_entries2, 0); q += 4; - - for (i = 0; i < r_r->num_entries2; i++) - { - q = smb_io_dom_rid2(io, &(r_r->dom_rid[i]), q, base, align); /* domain RIDs being looked up */ - } - - RW_IVAL(io, q, r_r->num_entries3, 0); q += 4; - - RW_IVAL(io, q, r_r->status, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align) -{ - if (q_c == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_unistr2(io, &(q_c->uni_logon_srv), q, base, align); /* logon server unicode string */ - q = smb_io_unistr2(io, &(q_c->uni_logon_clnt), q, base, align); /* logon client unicode string */ - q = smb_io_chal(io, &(q_c->clnt_chal), q, base, align); /* client challenge */ - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align) -{ - if (r_c == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_chal(io, &(r_c->srv_chal), q, base, align); /* server challenge */ - - RW_IVAL(io, q, r_c->status, 0); q += 4; - - return q; -} - - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_auth2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align) -{ - if (q_a == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_log_info (io, &(q_a->clnt_id), q, base, align); /* client identification info */ - q = smb_io_chal (io, &(q_a->clnt_chal), q, base, align); /* client-calculated credentials */ - q = smb_io_neg_flags(io, &(q_a->clnt_flgs), q, base, align); - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align) -{ - if (r_a == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_chal (io, &(r_a->srv_chal), q, base, align); /* server challenge */ - q = smb_io_neg_flags(io, &(r_a->srv_flgs), q, base, align); - - RW_IVAL(io, q, r_a->status, 0); q += 4; - - return q; -} - - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align) -{ - if (q_s == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_clnt_info(io, &(q_s->clnt_id), q, base, align); /* client identification/authentication info */ - RW_PCVAL(io, q, q_s->pwd, 16); q += 16; /* new password - undocumented */ - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align) -{ - if (r_s == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_cred(io, &(r_s->srv_cred), q, base, align); /* server challenge */ - - RW_IVAL(io, q, r_s->status, 0); q += 4; - - return q; -} - -/* LSA_USER_INFO */ - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align) -{ - int i; - - if (usr == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, usr->undoc_buffer, 0); q += 4; - - q = smb_io_time(io, &(usr->logon_time) , q, base, align); /* logon time */ - q = smb_io_time(io, &(usr->logoff_time) , q, base, align); /* logoff time */ - q = smb_io_time(io, &(usr->kickoff_time) , q, base, align); /* kickoff time */ - q = smb_io_time(io, &(usr->pass_last_set_time) , q, base, align); /* password last set time */ - q = smb_io_time(io, &(usr->pass_can_change_time) , q, base, align); /* password can change time */ - q = smb_io_time(io, &(usr->pass_must_change_time), q, base, align); /* password must change time */ - - q = smb_io_unihdr(io, &(usr->hdr_user_name) , q, base, align); /* username unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_full_name) , q, base, align); /* user's full name unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_logon_script), q, base, align); /* logon script unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_profile_path), q, base, align); /* profile path unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_home_dir) , q, base, align); /* home directory unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_dir_drive) , q, base, align); /* home directory drive unicode string header */ - - RW_SVAL(io, q, usr->logon_count , 0); q += 2; /* logon count */ - RW_SVAL(io, q, usr->bad_pw_count, 0); q += 2; /* bad password count */ - - RW_IVAL(io, q, usr->user_id , 0); q += 4; /* User ID */ - RW_IVAL(io, q, usr->group_id , 0); q += 4; /* Group ID */ - RW_IVAL(io, q, usr->num_groups , 0); q += 4; /* num groups */ - RW_IVAL(io, q, usr->buffer_groups, 0); q += 4; /* undocumented buffer pointer to groups. */ - RW_IVAL(io, q, usr->user_flgs , 0); q += 4; /* user flags */ - - RW_PCVAL(io, q, usr->sess_key, 16); q += 16; /* unused user session key */ - - q = smb_io_unihdr(io, &(usr->hdr_logon_srv), q, base, align); /* logon server unicode string header */ - q = smb_io_unihdr(io, &(usr->hdr_logon_dom), q, base, align); /* logon domain unicode string header */ - - RW_IVAL(io, q, usr->buffer_dom_id, 0); q += 4; /* undocumented logon domain id pointer */ - RW_PCVAL(io, q, usr->padding, 40); q += 40; /* unused padding bytes? */ - - RW_IVAL(io, q, usr->num_other_sids, 0); q += 4; /* 0 - num_sids */ - RW_IVAL(io, q, usr->buffer_other_sids, 0); q += 4; /* NULL - undocumented pointer to SIDs. */ - - q = smb_io_unistr2(io, &(usr->uni_user_name) , q, base, align); /* username unicode string */ - q = smb_io_unistr2(io, &(usr->uni_full_name) , q, base, align); /* user's full name unicode string */ - q = smb_io_unistr2(io, &(usr->uni_logon_script), q, base, align); /* logon script unicode string */ - q = smb_io_unistr2(io, &(usr->uni_profile_path), q, base, align); /* profile path unicode string */ - q = smb_io_unistr2(io, &(usr->uni_home_dir) , q, base, align); /* home directory unicode string */ - q = smb_io_unistr2(io, &(usr->uni_dir_drive) , q, base, align); /* home directory drive unicode string */ - - RW_IVAL(io, q, usr->num_groups2, 0); q += 4; /* num groups */ - for (i = 0; i < usr->num_groups2; i++) - { - q = smb_io_gid(io, &(usr->gids[i]), q, base, align); /* group info */ - } - - q = smb_io_unistr2(io, &( usr->uni_logon_srv), q, base, align); /* logon server unicode string */ - q = smb_io_unistr2(io, &( usr->uni_logon_dom), q, base, align); /* logon domain unicode string */ - - q = smb_io_dom_sid(io, &(usr->dom_sid), q, base, align); /* domain SID */ - - for (i = 0; i < usr->num_other_sids; i++) - { - q = smb_io_dom_sid(io, &(usr->other_sids[i]), q, base, align); /* other domain SIDs */ - } - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align) -{ - if (q_l == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align) -{ - if (r_l == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, r_l->buffer_creds, 0); q += 4; /* undocumented buffer pointer */ - q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ - - RW_IVAL(io, q, r_l->buffer_user, 0); q += 4; - if (r_l->buffer_user != 0) - { - q = lsa_io_user_info(io, r_l->user, q, base, align); - } - - RW_IVAL(io, q, r_l->auth_resp, 0); q += 4; /* 1 - Authoritative response; 0 - Non-Auth? */ - - RW_IVAL(io, q, r_l->status, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align) -{ - if (q_l == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_sam_info(io, &(q_l->sam_id), q, base, align); /* domain SID */ - - return q; -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align) -{ - if (r_l == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, r_l->buffer_creds, 0); q += 4; /* undocumented buffer pointer */ - q = smb_io_cred(io, &(r_l->srv_creds), q, base, align); /* server credentials. server time stamp appears to be ignored. */ - - RW_IVAL(io, q, r_l->status, 0); q += 4; - - return q; -} - -#if 0 -/******************************************************************* -reads or writes a structure. -********************************************************************/ - char* lsa_io_(BOOL io, *, char *q, char *base, int align) -{ - if (== NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, , 0); q += 4; - - return q; -} -#endif diff --git a/source/nameannounce.c b/source/nameannounce.c deleted file mode 100644 index d3344ebd478..00000000000 --- a/source/nameannounce.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - NBT netbios routines and daemon - version 2 - Copyright (C) Andrew Tridgell 1994-1997 - - SMB Version handling - Copyright (C) John H Terpstra 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. - - 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 char **my_netbios_names; - -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) = lp_major_announce_version(); /* major version */ - CVAL(p,22) = lp_minor_announce_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 */ - - pstrcpy(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 (!is_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) - { - DEBUG(0,("announce_server: error - announcement requested on WINS \ -interface for workgroup %s, name %s\n", work->work_group, name)); - return; - } - - /* Only do domain announcements if we are a master and it's - our name we're being asked to announce. */ - if (AM_MASTER(work) && strequal(myname,name)) - { - 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; - - /* 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 (is_myname(s->serv.name)) { - /* If we are any kind of browser or logon server, only - announce it for our primary name, not our aliases. */ - if(!strequal(myname, s->serv.name)) - stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER| - SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); - announce_server(d,work,s->serv.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)) - { - 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; - - { - /* 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, - ipzero, ipzero); - } - else if(lp_wins_support()) - { - /* We are the WINS server - query ourselves for the dmb name. */ - - struct nmb_name netb_name; - struct name_record *nr = 0; - - d = NULL; - - 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 = lp_default_server_announce(); - - 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; - int n; - - wgroup = strchr(s2,'/'); - if (wgroup) *wgroup++ = 0; - if (!wgroup || !*wgroup) - wgroup = workgroup; - - addr = *interpret_addr2(s2); - - /* Announce all our names including aliases */ - for (n=0; my_netbios_names[n]; n++) - { - char *name = my_netbios_names[n]; - do_announce_host(ANN_HostAnnouncement,name,0x20,*iface_ip(addr), - wgroup,0x1e,addr, - REMOTE_ANNOUNCE_INTERVAL, - name,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 19068780611..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-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: - - 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 51571d786a8..00000000000 --- a/source/namedbname.c +++ /dev/null @@ -1,601 +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; - - fstrcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,WINS_LIST); - fstrcpy(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; - - fstrcpy(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 */ - pstrcpy(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; - } - - bzero((char *)n->ip_flgs, sizeof(*n->ip_flgs) * n->num_ips); - - 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 86d7eddbd41..00000000000 --- a/source/namedbresp.c +++ /dev/null @@ -1,166 +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); - - bzero((char *)n, sizeof(*n)); - - 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 c6663d71fd4..00000000000 --- a/source/namedbsubnet.c +++ /dev/null @@ -1,367 +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; -extern char **my_netbios_names; - -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)) - { - int n; - - add_my_name_entry(d,group,0x0 ,nb_type|NB_ACTIVE|NB_GROUP); - - /* Only register the WORKGROUP<0x1e> name if we could be a local master - browser. */ - if(lp_local_master()) - add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP); - - /* Add all our server names to the workgroup list. We remove any - browser or logon server flags from all but the primary name. - */ - for( n = 0; my_netbios_names[n]; n++) - { - char *name = my_netbios_names[n]; - int stype = w->ServerType; - - if(!strequal(myname, name)) - stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER| - SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); - - add_server_entry(d,w,name,stype|SV_TYPE_LOCAL_LIST_ONLY,0, - lp_serverstring(),True); - DEBUG(3,("add_workgroup_to_subnet: Added server name entry %s \ -to subnet %s\n", name, 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(); - - pstrcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,SERVER_LIST); - pstrcpy(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 a6260aab467..00000000000 --- a/source/namedbwork.c +++ /dev/null @@ -1,245 +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); - bzero((char *)work, sizeof(*work)); - - StrnCpy(work->work_group,name,sizeof(work->work_group)-1); - work->serverlist = NULL; - - work->ServerType = lp_default_server_announce() | (lp_local_master() ? - SV_TYPE_POTENTIAL_BROWSER : 0 ); - work->RunningElection = False; - work->ElectionCount = 0; - work->announce_interval = 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)|(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 5fd1a4bdf2e..00000000000 --- a/source/nameelect.c +++ /dev/null @@ -1,855 +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() && lp_preferred_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; - pstrcpy(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); - - /* 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); - - /* 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; - - /* XXXX the 0x1b is domain master browser name */ - add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE); - - /* 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))); - - if (d == wins_subnet) - { - /* ok! we successfully registered by unicast with the - WINS server. we now expect to become the domain - master on the local subnets. if this fails, it's - probably a 1.9.16p2 to 1.9.16p11 server's fault. - - this is a configuration issue that should be addressed - by the network administrator - you shouldn't have - several machines configured as a domain master browser - for the same WINS scope (except if they are 1.9.17 or - greater, and you know what you're doing. - - see DOMAIN.txt. - - */ - add_domain_master_bcast(); - } - 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); - - /* 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); - remove_name_entry(d,work->work_group,0x1d); - } -} - - -/******************************************************************* - 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); - - /* Remove the name entry without any NetBIOS traffic as that's - how it was registered. */ - remove_name_entry(d,work->work_group,0x1b); - } - - /* Unregister the 1b name from the WINS server. */ - if(wins_subnet != NULL) - remove_name_entry(wins_subnet, myworkgroup, 0x1b); - } -} - - -/******************************************************************* - 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; - - remove_name_entry(d,work->work_group,0x1c); - } -} - - -/******************************************************************* - 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(0,("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 1f57139d56a..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; - fstrcpy(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); - - fstrcpy(reply_name,lp_domain_controller()); - if (!*reply_name) - { - /* oo! no domain controller. must be us, then */ - fstrcpy(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 44e449b8c2a..00000000000 --- a/source/namepacket.c +++ /dev/null @@ -1,637 +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", (unsigned char)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. see rfc1002.txt - ****************************************************************************/ -void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, - BOOL recursion_available, - BOOL recursion_desired, - 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 = recursion_available; - nmb->header.nm_flags.recursion_desired = recursion_desired; - 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 f44171f4b67..00000000000 --- a/source/nameresp.c +++ /dev/null @@ -1,324 +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, True, 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(1, ("nmbd configured as domain master and one already exists\n")); - } - 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, - 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)) - { - 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, - False, True, 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 ccd0ef379cb..00000000000 --- a/source/nameserv.c +++ /dev/null @@ -1,506 +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 char **my_netbios_names; -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. - - ****************************************************************************/ -void remove_name_entry(struct subnet_record *d, char *name,int type) -{ - /* 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()) - { - /* 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, - ipzero, ipzero); - } - } - else - { - /* 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 - - 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 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()) - { - /* we are a WINS server. */ - if(lp_wins_support()) - { - DEBUG(4,("add_my_name_entry: samba as WINS server 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, - ipzero, ipzero); - } - } - 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 internet group <1c> domain logon names by wins unicast and broadcast. - ****************************************************************************/ -void add_domain_logon_names(void) -{ - struct subnet_record *d; - - if (!lp_domain_logons()) return; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d)) - { - struct work_record *work = find_workgroupstruct(d, myworkgroup, True); - - if (work && work->log_state == LOGON_NONE) - { - struct nmb_name n; - make_nmb_name(&n,myworkgroup,0x1c,scope); - - if (!find_name(d->namelist, &n, FIND_SELF)) - { - /* logon servers are group names. don't expect failure */ - - DEBUG(0,("%s attempting to become logon server for %s %s\n", - timestring(), myworkgroup, inet_ntoa(d->bcast_ip))); - - become_logon_server(d, work); - } - } - } -} - - -/**************************************************************************** - add the <1b> domain master names by broadcast. - ****************************************************************************/ -void add_domain_master_bcast(void) -{ - struct subnet_record *d; - - if (!lp_domain_master()) return; - - for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d)) - { - struct work_record *work = find_workgroupstruct(d, myworkgroup, True); - - if (work && work->dom_state == DOMAIN_NONE) - { - struct nmb_name n; - 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))); - - /* send out a query to establish whether there's a - domain controller on the local 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 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 <1b> domain master name by wins unicast. - ****************************************************************************/ -void add_domain_master_wins(void) -{ - struct work_record *work; - - if (!lp_domain_master() || wins_subnet == NULL) return; - - work = find_workgroupstruct(wins_subnet, myworkgroup, True); - - if (work && work->dom_state == DOMAIN_NONE) - { - struct nmb_name n; - make_nmb_name(&n,myworkgroup,0x1b,scope); - - if (!find_name(wins_subnet->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(wins_subnet->bcast_ip))); - - 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 initiate become domain master for %s\n", - timestring(), myworkgroup)); - - become_domain_master(wins_subnet, 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, - ipzero, 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; - - if (lastrun != 0 && t < lastrun + CHECK_TIME_ADD_DOM_NAMES * 60) return; - lastrun = t; - - /* do the "internet group" - <1c> names */ - add_domain_logon_names(); - - /* do the domain master names */ - if (wins_subnet != NULL) - { - /* if the registration of the <1b> name is successful, then - add_domain_master_bcast() will be called. this will - result in domain logon services being gracefully provided, - as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11. - - which, due to a bug in namelogon.c from 1.9.16p2 to 1.9.16p11 - cannot _provide_ domain master / domain logon services!!! - - */ - add_domain_master_wins(); - } - else - { - add_domain_master_bcast(); - } -} - -/**************************************************************************** - 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)) - { - int n; - BOOL wins = (lp_wins_support() && (d == wins_subnet)); - - /* Add all our names including aliases. */ - for (n=0; my_netbios_names[n]; n++) - { - add_my_name_entry(d, my_netbios_names[n],0x20,nb_type|NB_ACTIVE); - add_my_name_entry(d, my_netbios_names[n],0x03,nb_type|NB_ACTIVE); - add_my_name_entry(d, my_netbios_names[n],0x00,nb_type|NB_ACTIVE); - } - - /* 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); - } - } - } -} - - -/******************************************************************* - 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); - /* 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 5b9c476549d..00000000000 --- a/source/nameservreply.c +++ /dev/null @@ -1,667 +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 recursion_available, BOOL recursion_desired, - 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 && !recursion_available) - { - /* 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, - recursion_available, recursion_desired, - 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 */ - /* see rfc1002.txt - 4.2.10 and 4.2.11 */ - send_name_response(fd,from_ip, response_id, NMB_REG, - new_owner, - True, True, - 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; - - /* If it's a group name not ending in 1c (not an internet name) - then just allow it to fade out of existance by timing out. */ - if(NAME_GROUP(nb_flags) && (n->name.name_type != 0x1c)) - { - DEBUG(5, ("reply_name_release: Allow group name %s(%d) to fade out on \ -subnet %s\n", namestr(&nmb->question.question_name), n->name.name_type, - inet_ntoa(d->bcast_ip))); - } - else - { - 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, False, False, - &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,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.5-6 - 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, - True, True, - 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,False, False, - &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; - BOOL query_is_to_wins_server = (!bcast && - nmb->header.nm_flags.recursion_desired); - 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; - BOOL acting_as_wins_server = lp_wins_support(); - - /* directed queries are for WINS server: broadcasts are local SELF queries. - the exception is Domain Master names. */ - - if (query_is_to_wins_server) - { - /* queries to the WINS server involve the WINS server subnet */ - if (!(d = wins_subnet)) - { - DEBUG(3,("name query: wins search %s not known\n", - inet_ntoa(p->ip))); - success = False; - } - } - else - { - /* queries to the WINS client involve, unfortunately, the WINS subnet - because it contains WINS client (SELF) entries, as _well_ as WINS - server entries. not good. - */ - - if (!(d = find_subnet(*iface_bcast(p->ip)))) - { - DEBUG(3,("name query: interface for %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 (!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, FIND_LOCAL, 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. lp_dns_proxy() - can be switched off, to ensure that the blocking doesn't occur. - a better solution would be to fork, but this will require a - mechanism to carry on processing after the query is resolved - (similar to the netbios queue). - */ - if (success && !n && (lp_dns_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); - } - - /* see rfc1002.txt 4.2.13 */ - - reply_netbios_packet(p,nmb->header.name_trn_id, - rcode,NMB_QUERY,0, - (query_is_to_wins_server && acting_as_wins_server ? - True : False), /* recursion_available flag */ - True, /* recursion_desired_flag */ - &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 a88481d06b0..00000000000 --- a/source/nameservresp.c +++ /dev/null @@ -1,848 +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 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, struct packet_struct *p) -{ - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr send_ip; - enum state_type cmd; - - /* This next fix was from Bernhard Laeser <nlaesb@ascom.ch> - who noticed we were replying directly back to the server - we sent to - rather than reading the response. - */ - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - putip((char*)&send_ip,&nmb->answers->rdata[2]); - else - { - - DEBUG(2,("response_server_check: name query for %s failed\n", - namestr(ans_name))); - return; - } - - /* issue another state: this time to do a name status check */ - - cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ? - NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK; - - /* initiate a name status check on address given in the reply - record. 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,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;} - - /* 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_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_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_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, p); - 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_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 3e1ac220058..00000000000 --- a/source/namework.c +++ /dev/null @@ -1,723 +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 (is_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 ( is_myname(dgram->source_name.name)) 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 -} - -/******************************************************************* - 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 (is_myname(dgram->source_name.name)) 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 3f0279908da..00000000000 --- a/source/nmbd/nmbd.c +++ /dev/null @@ -1,647 +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; -extern char **my_netbios_names; - -/* 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; - pstrcpy(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; - pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) - { - pstrcpy(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; - pstrcpy(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, *ptr; - int namecount; - int n; - int nodup; - pstring nbname; - - if (! *myname) { - fstrcpy(myname,myhostname); - p = strchr(myname,'.'); - if (p) *p = 0; - } - strupper(myname); - - /* Add any NETBIOS name aliases. Ensure that the first entry - is equal to myname. */ - /* Work out the max number of netbios aliases that we have */ - ptr=lp_netbios_aliases(); - for (namecount=0; next_token(&ptr,nbname,NULL); namecount++) - ; - if (*myname) - namecount++; - - /* Allocate space for the netbios aliases */ - if((my_netbios_names=(char **)malloc(sizeof(char *)*(namecount+1))) == NULL) - { - DEBUG(0,("init_structs: malloc fail.\n")); - return False; - } - - /* Use the myname string first */ - namecount=0; - if (*myname) - my_netbios_names[namecount++] = myname; - - ptr=lp_netbios_aliases(); - while (next_token(&ptr,nbname,NULL)) { - strupper(nbname); - /* Look for duplicates */ - nodup=1; - for(n=0; n<namecount; n++) { - if (strcmp(nbname, my_netbios_names[n])==0) - nodup=0; - } - if (nodup) - my_netbios_names[namecount++]=strdup(nbname); - } - - /* Check the strdups succeeded. */ - for(n = 0; n < namecount; n++) - if(my_netbios_names[n]==NULL) - { - DEBUG(0,("init_structs: malloc fail when allocating names.\n")); - return False; - } - - /* Terminate name list */ - my_netbios_names[namecount++]=NULL; - - fstrcpy(local_machine,myname); - trim_string(local_machine," "," "); - p = strchr(local_machine,' '); - if (p) - *p = 0; - strlower(local_machine); - - DEBUG(5, ("Netbios name list:-\n")); - for (n=0; my_netbios_names[n]; n++) - DEBUG(5, ("my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n])); - - 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(); - -#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': - pstrcpy(servicesf,optarg); - break; - case 'N': - case 'B': - case 'I': - case 'C': - case 'G': - DEBUG(0,("Obsolete option '%c' used\n",opt)); - break; - case 'H': - pstrcpy(host_file,optarg); - break; - case 'n': - pstrcpy(myname,optarg); - strupper(myname); - break; - case 'l': - sprintf(debugf,"%s.nmb",optarg); - break; - case 'i': - pstrcpy(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-1997\n")); - - if(!get_myname(myhostname,NULL)) - { - DEBUG(0,("Unable to get my hostname - exiting.\n")); - return -1; - } - - if (!reload_services(False)) - return(-1); - - codepage_initialise(lp_client_code_page()); - - if(!init_structs()) - return -1; - - reload_services(True); - - pstrcpy(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, -#ifdef O_NONBLOCK - O_NONBLOCK | -#endif - 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 de2f7aa00f1..00000000000 --- a/source/nmbsync.c +++ /dev/null @@ -1,191 +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. - -*/ - -/* We *must have REPLACE_GETPASS defined here before the includes. */ -#define REPLACE_GETPASS -#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,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */ - p += 4; - SIVAL(p,0,servertype); - p += 4; - - pstrcpy(p, work->work_group); - p = skip_string(p,1); - - if (cli_call_api(PTR_DIFF(p,param),0, 8,BUFFER_SIZE - SAFETY_MARGIN, - &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); - fstrcpy(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); - if(local) - add_info(d, work, SV_TYPE_LOCAL_LIST_ONLY); - else - add_info(d, work, SV_TYPE_ALL); - } - - close_sockets(); - } -} diff --git a/source/param/loadparm.c b/source/param/loadparm.c deleted file mode 100644 index edc2d2b65f6..00000000000 --- a/source/param/loadparm.c +++ /dev/null @@ -1,2361 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Parameter loading functions - Copyright (C) Karl Auer 1993,1997 - - Largely re-written by Andrew Tridgell, September 1994 - - 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. -*/ - -/* - * Load parameters. - * - * This module provides suitable callback functions for the params - * module. It builds the internal table of service details which is - * then used by the rest of the server. - * - * To add a parameter: - * - * 1) add it to the global or service structure definition - * 2) add it to the parm_table - * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING()) - * 4) If it's a global then initialise it in init_globals. If a local - * (ie. service) parameter then initialise it in the sDefault structure - * - * - * Notes: - * The configuration file is processed sequentially for speed. It is NOT - * accessed randomly as happens in 'real' Windows. For this reason, there - * is a fair bit of sequence-dependent code here - ie., code which assumes - * that certain things happen before others. In particular, the code which - * happens at the boundary between sections is delicately poised, so be - * careful! - * - */ - -#include "includes.h" - -/* Set default coding system for KANJI if none specified in Makefile. */ -#ifndef KANJI -#define KANJI "sjis" -#endif /* KANJI */ - -BOOL bLoaded = False; - -extern int DEBUGLEVEL; -extern pstring user_socket_options; -extern pstring myname; - -#ifndef GLOBAL_NAME -#define GLOBAL_NAME "global" -#endif - -#ifndef PRINTCAP_NAME -#ifdef AIX -#define PRINTCAP_NAME "/etc/qconfig" -#else -#define PRINTCAP_NAME "/etc/printcap" -#endif -#endif - -#ifndef PRINTERS_NAME -#define PRINTERS_NAME "printers" -#endif - -#ifndef HOMES_NAME -#define HOMES_NAME "homes" -#endif - -/* some helpful bits */ -#define pSERVICE(i) ServicePtrs[i] -#define iSERVICE(i) (*pSERVICE(i)) -#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices) && iSERVICE(iService).valid) -#define VALID(i) iSERVICE(i).valid - -/* these are the types of parameter we have */ -typedef enum -{ - P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL, - P_STRING,P_USTRING,P_GSTRING,P_UGSTRING -} parm_type; - -typedef enum -{ - P_LOCAL,P_GLOBAL,P_NONE -} parm_class; - -int keepalive=0; -extern BOOL use_getwd_cache; - -extern int extra_time_offset; -extern int coding_system; - -/* - * This structure describes global (ie., server-wide) parameters. - */ -typedef struct -{ - char *szPrintcapname; - char *szLockDir; - char *szRootdir; - char *szDefaultService; - char *szDfree; - char *szMsgCommand; - char *szHostsEquiv; - char *szServerString; - char *szAutoServices; - char *szPasswdProgram; - char *szPasswdChat; - char *szLogFile; - char *szConfigFile; - char *szSMBPasswdFile; - char *szPasswordServer; - char *szSocketOptions; - char *szValidChars; - char *szWorkGroup; - char *szDomainController; - char *szUsernameMap; - char *szCharacterSet; - char *szLogonScript; - char *szLogonPath; - char *szSmbrun; - char *szWINSserver; - char *szInterfaces; - char *szRemoteAnnounce; - char *szSocketAddress; - char *szNISHomeMapName; - char *szAnnounceVersion; /* This is initialised in init_globals */ - char *szNetbiosAliases; - char *szDomainSID; - int max_log_size; - int mangled_stack; - int max_xmit; - int max_mux; - int max_packet; - int pwordlevel; - int unamelevel; - int deadtime; - int maxprotocol; - int security; - int printing; - int maxdisksize; - int lpqcachetime; - int syslog; - int os_level; - int max_ttl; - int ReadSize; - int shmem_size; - int shmem_hash_size; - int client_code_page; - int announce_as; /* This is initialised in init_globals */ - BOOL bDNSproxy; - BOOL bWINSsupport; - BOOL bWINSproxy; - BOOL bLocalMaster; - BOOL bPreferredMaster; - BOOL bDomainMaster; - BOOL bDomainLogons; - BOOL bEncryptPasswords; - BOOL bStripDot; - BOOL bNullPasswords; - BOOL bLoadPrinters; - BOOL bUseRhosts; - BOOL bReadRaw; - BOOL bWriteRaw; - BOOL bReadPrediction; - BOOL bReadbmpx; - BOOL bSyslogOnly; - BOOL bBrowseList; - BOOL bUnixRealname; - BOOL bNISHomeMap; - BOOL bTimeServer; -} global; - -static global Globals; - - - -/* - * This structure describes a single service. - */ -typedef struct -{ - BOOL valid; - char *szService; - char *szPath; - char *szUsername; - char *szGuestaccount; - char *szInvalidUsers; - char *szValidUsers; - char *szAdminUsers; - char *szCopy; - char *szInclude; - char *szPreExec; - char *szPostExec; - char *szRootPreExec; - char *szRootPostExec; - char *szPrintcommand; - char *szLpqcommand; - char *szLprmcommand; - char *szLppausecommand; - char *szLpresumecommand; - char *szPrintername; - char *szPrinterDriver; - char *szDontdescend; - char *szHostsallow; - char *szHostsdeny; - char *szMagicScript; - char *szMagicOutput; - char *szMangledMap; - char *szVetoFiles; - char *szHideFiles; - char *comment; - char *force_user; - char *force_group; - char *readlist; - char *writelist; - char *volume; - int iMinPrintSpace; - int iCreate_mask; - int iCreate_force_mode; - int iDir_mask; - int iDir_force_mode; - int iMaxConnections; - int iDefaultCase; - BOOL bAlternatePerm; - BOOL bRevalidate; - BOOL bCaseSensitive; - BOOL bCasePreserve; - BOOL bShortCasePreserve; - BOOL bCaseMangle; - BOOL status; - BOOL bHideDotFiles; - BOOL bBrowseable; - BOOL bAvailable; - BOOL bRead_only; - BOOL bNo_set_dir; - BOOL bGuest_only; - BOOL bGuest_ok; - BOOL bPrint_ok; - BOOL bPostscript; - BOOL bMap_system; - BOOL bMap_hidden; - BOOL bMap_archive; - BOOL bLocking; - BOOL bStrictLocking; - BOOL bShareModes; - BOOL bOpLocks; - BOOL bOnlyUser; - BOOL bMangledNames; - BOOL bWidelinks; - BOOL bSymlinks; - BOOL bSyncAlways; - char magic_char; - BOOL *copymap; - BOOL bDeleteReadonly; - BOOL bFakeOplocks; - BOOL bDeleteVetoFiles; - char dummy[3]; /* for alignment */ -} service; - - -/* This is a default service used to prime a services structure */ -static service sDefault = -{ - True, /* valid */ - NULL, /* szService */ - NULL, /* szPath */ - NULL, /* szUsername */ - NULL, /* szGuestAccount - this is set in init_globals() */ - NULL, /* szInvalidUsers */ - NULL, /* szValidUsers */ - NULL, /* szAdminUsers */ - NULL, /* szCopy */ - NULL, /* szInclude */ - NULL, /* szPreExec */ - NULL, /* szPostExec */ - NULL, /* szRootPreExec */ - NULL, /* szRootPostExec */ - NULL, /* szPrintcommand */ - NULL, /* szLpqcommand */ - NULL, /* szLprmcommand */ - NULL, /* szLppausecommand */ - NULL, /* szLpresumecommand */ - NULL, /* szPrintername */ - NULL, /* szPrinterDriver - this is set in init_globals() */ - NULL, /* szDontdescend */ - NULL, /* szHostsallow */ - NULL, /* szHostsdeny */ - NULL, /* szMagicScript */ - NULL, /* szMagicOutput */ - NULL, /* szMangledMap */ - NULL, /* szVetoFiles */ - NULL, /* szHideFiles */ - NULL, /* comment */ - NULL, /* force user */ - NULL, /* force group */ - NULL, /* readlist */ - NULL, /* writelist */ - NULL, /* volume */ - 0, /* iMinPrintSpace */ - 0744, /* iCreate_mask */ - 0000, /* iCreate_force_mode */ - 0755, /* iDir_mask */ - 0000, /* iDir_force_mode */ - 0, /* iMaxConnections */ - CASE_LOWER, /* iDefaultCase */ - False, /* bAlternatePerm */ - False, /* revalidate */ - False, /* case sensitive */ - False, /* case preserve */ - False, /* short case preserve */ - False, /* case mangle */ - True, /* status */ - True, /* bHideDotFiles */ - True, /* bBrowseable */ - True, /* bAvailable */ - True, /* bRead_only */ - True, /* bNo_set_dir */ - False, /* bGuest_only */ - False, /* bGuest_ok */ - False, /* bPrint_ok */ - False, /* bPostscript */ - False, /* bMap_system */ - False, /* bMap_hidden */ - True, /* bMap_archive */ - True, /* bLocking */ - False, /* bStrictLocking */ - True, /* bShareModes */ - True, /* bOpLocks */ - False, /* bOnlyUser */ - True, /* bMangledNames */ - True, /* bWidelinks */ - True, /* bSymlinks */ - False, /* bSyncAlways */ - '~', /* magic char */ - NULL, /* copymap */ - False, /* bDeleteReadonly */ - False, /* bFakeOplocks */ - False, /* bDeleteVetoFiles */ - "" /* dummy */ -}; - - - -/* local variables */ -static service **ServicePtrs = NULL; -static int iNumServices = 0; -static int iServiceIndex = 0; -static BOOL bInGlobalSection = True; -static BOOL bGlobalOnly = False; -static int default_server_announce; - -#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct)) - -/* prototypes for the special type handlers */ -static BOOL handle_valid_chars(char *pszParmValue, char **ptr); -static BOOL handle_include(char *pszParmValue, char **ptr); -static BOOL handle_copy(char *pszParmValue, char **ptr); -static BOOL handle_protocol(char *pszParmValue,int *val); -static BOOL handle_security(char *pszParmValue,int *val); -static BOOL handle_case(char *pszParmValue,int *val); -static BOOL handle_printing(char *pszParmValue,int *val); -static BOOL handle_character_set(char *pszParmValue,int *val); -static BOOL handle_announce_as(char *pszParmValue, int *val); -static BOOL handle_coding_system(char *pszParmValue,int *val); - -static void set_default_server_announce_type(void); - -struct parm_struct -{ - char *label; - parm_type type; - parm_class class; - void *ptr; - BOOL (*special)(); -} parm_table[] = -{ - {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL}, - {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL}, - {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL}, - {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL}, - {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol}, - {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security}, - {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing}, - {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL}, - {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL}, - {"announce as", P_INTEGER, P_GLOBAL, &Globals.announce_as, handle_announce_as}, - {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL}, - {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL}, - {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL}, - {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL}, - {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL}, - {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL}, - {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL}, - {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL}, - {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL}, - {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL}, - {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL}, - {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL}, - {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL}, - {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL}, - {"netbios aliases", P_STRING, P_GLOBAL, &Globals.szNetbiosAliases, NULL}, - {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL}, - {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL}, - {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL}, - {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL}, - {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL}, - {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL}, - {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL}, - {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL}, - {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL}, - {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL}, - {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL}, - {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL}, - {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL}, - {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL}, - {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL}, - {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL}, - {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL}, - {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL}, - {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL}, - {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL}, - {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL}, - {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars}, - {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL}, - {"domain sid", P_USTRING, P_GLOBAL, &Globals.szDomainSID, NULL}, - {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL}, - {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL}, - {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set}, - {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL}, - {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL}, - {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL}, - {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL}, - {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL}, - {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL}, - {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL}, - {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL}, - {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL}, - {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL}, - {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL}, - {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL}, - {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL}, - {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL}, - {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL}, - {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL}, - {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL}, - {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL}, - {"shared mem size", P_INTEGER, P_GLOBAL, &Globals.shmem_size, NULL}, - {"shared file entries", P_INTEGER, P_GLOBAL, &Globals.shmem_hash_size, NULL}, - {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system}, - {"client code page", P_INTEGER, P_GLOBAL, &Globals.client_code_page, NULL}, - {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL}, - {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL}, - {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL}, - {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL}, - {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL}, - {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL}, - {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, - {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, - {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL}, - {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL}, - {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL}, - {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL}, - {"unix realname", P_BOOL, P_GLOBAL, &Globals.bUnixRealname, NULL}, - {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL}, - {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL}, - {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL}, - {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL}, - {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy}, - {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include}, - {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL}, - {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL}, - {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL}, - {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL}, - {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL}, - {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL}, - {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL}, - {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case}, - {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL}, - {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL}, - {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL}, - {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL}, - {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL}, - {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL}, - {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL}, - {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL}, - {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL}, - {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL}, - {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL}, - {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL}, - {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL}, - {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL}, - {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL}, - {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL}, - {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL}, - {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL}, - {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL}, - {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL}, - {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL}, - {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL}, - {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL}, - {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL}, - {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL}, - {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL}, - {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL}, - {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL}, - {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL}, - {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL}, - {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL}, - {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL}, - {"force create mode",P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL}, - {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL}, - {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL}, - {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL}, - {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL}, - {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL}, - {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL}, - {"delete veto files",P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL}, - {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL}, - {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL}, - {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL}, - {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL}, - {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL}, - {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL}, - {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL}, - {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL}, - {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL}, - {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL}, - {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL}, - {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL}, - {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL}, - {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL}, - {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL}, - {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL}, - {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL}, - {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL}, - {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL}, - {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL}, - {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL}, - {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL}, - {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL}, - {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL}, - {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL}, - {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL}, - {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL}, - {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL}, - {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL}, - {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL}, - {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL}, - {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL}, - {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL}, - {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL}, - {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL}, - {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL}, - {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL}, - {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL}, - {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL}, - - {NULL, P_BOOL, P_NONE, NULL, NULL} -}; - - - -/*************************************************************************** -Initialise the global parameter structure. -***************************************************************************/ -static void init_globals(void) -{ - static BOOL done_init = False; - pstring s; - - if (!done_init) - { - int i; - bzero((void *)&Globals,sizeof(Globals)); - - for (i = 0; parm_table[i].label; i++) - if ((parm_table[i].type == P_STRING || - parm_table[i].type == P_USTRING) && - parm_table[i].ptr) - string_init(parm_table[i].ptr,""); - - string_set(&sDefault.szGuestaccount, GUEST_ACCOUNT); - string_set(&sDefault.szPrinterDriver, "NULL"); - - done_init = True; - } - - - DEBUG(3,("Initialising global parameters\n")); - -#ifdef SMB_PASSWD_FILE - string_set(&Globals.szSMBPasswdFile, SMB_PASSWD_FILE); -#endif - string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*"); - string_set(&Globals.szWorkGroup, WORKGROUP); - string_set(&Globals.szPasswdProgram, SMB_PASSWD); - string_set(&Globals.szPrintcapname, PRINTCAP_NAME); - string_set(&Globals.szLockDir, LOCKDIR); - string_set(&Globals.szRootdir, "/"); - string_set(&Globals.szSmbrun, SMBRUN); - string_set(&Globals.szSocketAddress, "0.0.0.0"); - sprintf(s,"Samba %s",VERSION); - string_set(&Globals.szServerString,s); - sprintf(s,"%d.%d", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION); - string_set(&Globals.szAnnounceVersion,s); - Globals.bLoadPrinters = True; - Globals.bUseRhosts = False; - Globals.max_packet = 65535; - Globals.mangled_stack = 50; - Globals.max_xmit = 65535; - Globals.max_mux = 50; /* This is *needed* for profile support. */ - Globals.lpqcachetime = 10; - Globals.pwordlevel = 0; - Globals.unamelevel = 0; - Globals.deadtime = 0; - Globals.max_log_size = 5000; - Globals.maxprotocol = PROTOCOL_NT1; - Globals.security = SEC_SHARE; - Globals.bEncryptPasswords = False; - Globals.printing = DEFAULT_PRINTING; - Globals.bReadRaw = True; - Globals.bWriteRaw = True; - Globals.bReadPrediction = False; - Globals.bReadbmpx = True; - Globals.bNullPasswords = False; - Globals.bStripDot = False; - Globals.syslog = 1; - Globals.bSyslogOnly = False; - Globals.os_level = 0; - Globals.max_ttl = 60*60*4; /* 2 hours default */ - Globals.ReadSize = 16*1024; - Globals.shmem_size = SHMEM_SIZE; - Globals.shmem_hash_size = SHMEM_HASH_SIZE; - Globals.announce_as = ANNOUNCE_AS_NT; - Globals.bUnixRealname = False; -#if (defined(NETGROUP) && defined(AUTOMOUNT)) - Globals.bNISHomeMap = False; - string_set(&Globals.szNISHomeMapName, "auto.home"); -#endif - coding_system = interpret_coding_system (KANJI, SJIS_CODE); - Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE; - Globals.bTimeServer = False; - -/* these parameters are set to defaults that are more appropriate - for the increasing samba install base: - - as a member of the workgroup, that will possibly become a - _local_ master browser (lm = True). this is opposed to a forced - local master browser startup (pm = True). - - doesn't provide WINS server service by default (wsupp = False), - and doesn't provide domain master browser services by default, either. - -*/ - - Globals.bPreferredMaster = False; - Globals.bLocalMaster = True; - Globals.bDomainMaster = False; - Globals.bDomainLogons = False; - Globals.bBrowseList = True; - Globals.bWINSsupport = False; - Globals.bWINSproxy = False; - -/* this parameter is currently set to the default functionality - in samba. given that w95 and NT is starting to use DNS for - server resolution, i expect that at some point it would be - sensible to default this to False. - - this parameter is added because nmbd is a single process, and - gethostbyname is a blocking call, which can take out nmbd for - several seconds while a dns lookup is performed. - - */ - - Globals.bDNSproxy = True; -} - -/*************************************************************************** -check if a string is initialised and if not then initialise it -***************************************************************************/ -static void string_initial(char **s,char *v) -{ - if (!*s || !**s) - string_init(s,v); -} - - -/*************************************************************************** -Initialise the sDefault parameter structure. -***************************************************************************/ -static void init_locals(void) -{ - /* choose defaults depending on the type of printing */ - switch (Globals.printing) - { - case PRINT_BSD: - case PRINT_AIX: - case PRINT_LPRNG: - case PRINT_PLP: - string_initial(&sDefault.szLpqcommand,"lpq -P%p"); - string_initial(&sDefault.szLprmcommand,"lprm -P%p %j"); - string_initial(&sDefault.szPrintcommand,"lpr -r -P%p %s"); - break; - - case PRINT_SYSV: - case PRINT_HPUX: - string_initial(&sDefault.szLpqcommand,"lpstat -o%p"); - string_initial(&sDefault.szLprmcommand,"cancel %p-%j"); - string_initial(&sDefault.szPrintcommand,"lp -c -d%p %s; rm %s"); -#ifdef SVR4 - string_initial(&sDefault.szLppausecommand,"lp -i %p-%j -H hold"); - string_initial(&sDefault.szLpresumecommand,"lp -i %p-%j -H resume"); -#endif - break; - - case PRINT_QNX: - string_initial(&sDefault.szLpqcommand,"lpq -P%p"); - string_initial(&sDefault.szLprmcommand,"lprm -P%p %j"); - string_initial(&sDefault.szPrintcommand,"lp -r -P%p %s"); - break; - - - } -} - - -/******************************************************************* a -convenience routine to grab string parameters into a rotating buffer, -and run standard_sub_basic on them. The buffers can be written to by -callers without affecting the source string. -********************************************************************/ -char *lp_string(char *s) -{ - static char *bufs[10]; - static int buflen[10]; - static int next = -1; - char *ret; - int i; - int len = s?strlen(s):0; - - if (next == -1) { - /* initialisation */ - for (i=0;i<10;i++) { - bufs[i] = NULL; - buflen[i] = 0; - } - next = 0; - } - - len = MAX(len+100,sizeof(pstring)); /* the +100 is for some - substitution room */ - - if (buflen[next] != len) { - buflen[next] = len; - if (bufs[next]) free(bufs[next]); - bufs[next] = (char *)malloc(len); - if (!bufs[next]) { - DEBUG(0,("out of memory in lp_string()")); - exit(1); - } - } - - ret = &bufs[next][0]; - next = (next+1)%10; - - if (!s) - *ret = 0; - else - StrCpy(ret,s); - - standard_sub_basic(ret); - return(ret); -} - - -/* - In this section all the functions that are used to access the - parameters from the rest of the program are defined -*/ - -#define FN_GLOBAL_STRING(fn_name,ptr) \ - char *fn_name(void) {return(lp_string(*(char **)(ptr) ? *(char **)(ptr) : ""));} -#define FN_GLOBAL_BOOL(fn_name,ptr) \ - BOOL fn_name(void) {return(*(BOOL *)(ptr));} -#define FN_GLOBAL_CHAR(fn_name,ptr) \ - char fn_name(void) {return(*(char *)(ptr));} -#define FN_GLOBAL_INTEGER(fn_name,ptr) \ - int fn_name(void) {return(*(int *)(ptr));} - -#define FN_LOCAL_STRING(fn_name,val) \ - char *fn_name(int i) {return(lp_string((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : sDefault.val));} -#define FN_LOCAL_BOOL(fn_name,val) \ - BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);} -#define FN_LOCAL_CHAR(fn_name,val) \ - char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);} -#define FN_LOCAL_INTEGER(fn_name,val) \ - int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);} - -FN_GLOBAL_STRING(lp_logfile,&Globals.szLogFile) -FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun) -FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile) -FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile) -FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString) -FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname) -FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir) -FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir) -FN_GLOBAL_STRING(lp_defaultservice,&Globals.szDefaultService) -FN_GLOBAL_STRING(lp_msg_command,&Globals.szMsgCommand) -FN_GLOBAL_STRING(lp_dfree_command,&Globals.szDfree) -FN_GLOBAL_STRING(lp_hosts_equiv,&Globals.szHostsEquiv) -FN_GLOBAL_STRING(lp_auto_services,&Globals.szAutoServices) -FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram) -FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat) -FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer) -FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup) -FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController) -FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap) -FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet) -FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) -FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath) -FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce) -FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver) -FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces) -FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress) -FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName) -FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion) -FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases) - -FN_GLOBAL_STRING(lp_domainsid,&Globals.szDomainSID) - -FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy) -FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) -FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy) -FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster) -FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster) -FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons) -FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster) -FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters) -FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts) -FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache) -FN_GLOBAL_BOOL(lp_readprediction,&Globals.bReadPrediction) -FN_GLOBAL_BOOL(lp_readbmpx,&Globals.bReadbmpx) -FN_GLOBAL_BOOL(lp_readraw,&Globals.bReadRaw) -FN_GLOBAL_BOOL(lp_writeraw,&Globals.bWriteRaw) -FN_GLOBAL_BOOL(lp_null_passwords,&Globals.bNullPasswords) -FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot) -FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords) -FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly) -FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList) -FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname) -FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap) -FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer) - -FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level) -FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl) -FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size) -FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack) -FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit) -FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux) -FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet) -FN_GLOBAL_INTEGER(lp_keepalive,&keepalive) -FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel) -FN_GLOBAL_INTEGER(lp_usernamelevel,&Globals.unamelevel) -FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize) -FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size) -FN_GLOBAL_INTEGER(lp_shmem_hash_size,&Globals.shmem_hash_size) -FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime) -FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol) -FN_GLOBAL_INTEGER(lp_security,&Globals.security) -FN_GLOBAL_INTEGER(lp_printing,&Globals.printing) -FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize) -FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime) -FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog) -FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page) -FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as) - -FN_LOCAL_STRING(lp_preexec,szPreExec) -FN_LOCAL_STRING(lp_postexec,szPostExec) -FN_LOCAL_STRING(lp_rootpreexec,szRootPreExec) -FN_LOCAL_STRING(lp_rootpostexec,szRootPostExec) -FN_LOCAL_STRING(lp_servicename,szService) -FN_LOCAL_STRING(lp_pathname,szPath) -FN_LOCAL_STRING(lp_dontdescend,szDontdescend) -FN_LOCAL_STRING(lp_username,szUsername) -FN_LOCAL_STRING(lp_guestaccount,szGuestaccount) -FN_LOCAL_STRING(lp_invalid_users,szInvalidUsers) -FN_LOCAL_STRING(lp_valid_users,szValidUsers) -FN_LOCAL_STRING(lp_admin_users,szAdminUsers) -FN_LOCAL_STRING(lp_printcommand,szPrintcommand) -FN_LOCAL_STRING(lp_lpqcommand,szLpqcommand) -FN_LOCAL_STRING(lp_lprmcommand,szLprmcommand) -FN_LOCAL_STRING(lp_lppausecommand,szLppausecommand) -FN_LOCAL_STRING(lp_lpresumecommand,szLpresumecommand) -FN_LOCAL_STRING(lp_printername,szPrintername) -FN_LOCAL_STRING(lp_printerdriver,szPrinterDriver) -FN_LOCAL_STRING(lp_hostsallow,szHostsallow) -FN_LOCAL_STRING(lp_hostsdeny,szHostsdeny) -FN_LOCAL_STRING(lp_magicscript,szMagicScript) -FN_LOCAL_STRING(lp_magicoutput,szMagicOutput) -FN_LOCAL_STRING(lp_comment,comment) -FN_LOCAL_STRING(lp_force_user,force_user) -FN_LOCAL_STRING(lp_force_group,force_group) -FN_LOCAL_STRING(lp_readlist,readlist) -FN_LOCAL_STRING(lp_writelist,writelist) -FN_LOCAL_STRING(lp_volume,volume) -FN_LOCAL_STRING(lp_mangled_map,szMangledMap) -FN_LOCAL_STRING(lp_veto_files,szVetoFiles) -FN_LOCAL_STRING(lp_hide_files,szHideFiles) - -FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm) -FN_LOCAL_BOOL(lp_revalidate,bRevalidate) -FN_LOCAL_BOOL(lp_casesensitive,bCaseSensitive) -FN_LOCAL_BOOL(lp_preservecase,bCasePreserve) -FN_LOCAL_BOOL(lp_shortpreservecase,bShortCasePreserve) -FN_LOCAL_BOOL(lp_casemangle,bCaseMangle) -FN_LOCAL_BOOL(lp_status,status) -FN_LOCAL_BOOL(lp_hide_dot_files,bHideDotFiles) -FN_LOCAL_BOOL(lp_browseable,bBrowseable) -FN_LOCAL_BOOL(lp_readonly,bRead_only) -FN_LOCAL_BOOL(lp_no_set_dir,bNo_set_dir) -FN_LOCAL_BOOL(lp_guest_ok,bGuest_ok) -FN_LOCAL_BOOL(lp_guest_only,bGuest_only) -FN_LOCAL_BOOL(lp_print_ok,bPrint_ok) -FN_LOCAL_BOOL(lp_postscript,bPostscript) -FN_LOCAL_BOOL(lp_map_hidden,bMap_hidden) -FN_LOCAL_BOOL(lp_map_archive,bMap_archive) -FN_LOCAL_BOOL(lp_locking,bLocking) -FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking) -FN_LOCAL_BOOL(lp_share_modes,bShareModes) -FN_LOCAL_BOOL(lp_oplocks,bOpLocks) -FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser) -FN_LOCAL_BOOL(lp_manglednames,bMangledNames) -FN_LOCAL_BOOL(lp_widelinks,bWidelinks) -FN_LOCAL_BOOL(lp_symlinks,bSymlinks) -FN_LOCAL_BOOL(lp_syncalways,bSyncAlways) -FN_LOCAL_BOOL(lp_map_system,bMap_system) -FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly) -FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks) -FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles) - -FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask) -FN_LOCAL_INTEGER(lp_force_create_mode,iCreate_force_mode) -FN_LOCAL_INTEGER(lp_dir_mode,iDir_mask) -FN_LOCAL_INTEGER(lp_force_dir_mode,iDir_force_mode) -FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections) -FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase) -FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace) - -FN_LOCAL_CHAR(lp_magicchar,magic_char) - - - -/* local prototypes */ -static int strwicmp( char *psz1, char *psz2 ); -static int map_parameter( char *pszParmName); -static BOOL set_boolean( BOOL *pb, char *pszParmValue ); -static int getservicebyname(char *pszServiceName, service *pserviceDest); -static void copy_service( service *pserviceDest, - service *pserviceSource, - BOOL *pcopymapDest ); -static BOOL service_ok(int iService); -static BOOL do_parameter(char *pszParmName, char *pszParmValue); -static BOOL do_section(char *pszSectionName); -static void init_copymap(service *pservice); - - -/*************************************************************************** -initialise a service to the defaults -***************************************************************************/ -static void init_service(service *pservice) -{ - bzero((char *)pservice,sizeof(service)); - copy_service(pservice,&sDefault,NULL); -} - - -/*************************************************************************** -free the dynamically allocated parts of a service struct -***************************************************************************/ -static void free_service(service *pservice) -{ - int i; - if (!pservice) - return; - - for (i=0;parm_table[i].label;i++) - if ((parm_table[i].type == P_STRING || - parm_table[i].type == P_STRING) && - parm_table[i].class == P_LOCAL) - string_free((char **)(((char *)pservice) + PTR_DIFF(parm_table[i].ptr,&sDefault))); -} - -/*************************************************************************** -add a new service to the services array initialising it with the given -service -***************************************************************************/ -static int add_a_service(service *pservice, char *name) -{ - int i; - service tservice; - int num_to_alloc = iNumServices+1; - - tservice = *pservice; - - /* it might already exist */ - if (name) - { - i = getservicebyname(name,NULL); - if (i >= 0) - return(i); - } - - /* find an invalid one */ - for (i=0;i<iNumServices;i++) - if (!pSERVICE(i)->valid) - break; - - /* if not, then create one */ - if (i == iNumServices) - { - ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc); - if (ServicePtrs) - pSERVICE(iNumServices) = (service *)malloc(sizeof(service)); - - if (!ServicePtrs || !pSERVICE(iNumServices)) - return(-1); - - iNumServices++; - } - else - free_service(pSERVICE(i)); - - pSERVICE(i)->valid = True; - - init_service(pSERVICE(i)); - copy_service(pSERVICE(i),&tservice,NULL); - if (name) - string_set(&iSERVICE(i).szService,name); - - return(i); -} - -/*************************************************************************** -add a new home service, with the specified home directory, defaults coming -from service ifrom -***************************************************************************/ -BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir) -{ - int i = add_a_service(pSERVICE(iDefaultService),pszHomename); - - if (i < 0) - return(False); - - if (!(*(iSERVICE(i).szPath)) || strequal(iSERVICE(i).szPath,lp_pathname(-1))) - string_set(&iSERVICE(i).szPath,pszHomedir); - if (!(*(iSERVICE(i).comment))) - { - pstring comment; - sprintf(comment,"Home directory of %s",pszHomename); - string_set(&iSERVICE(i).comment,comment); - } - iSERVICE(i).bAvailable = sDefault.bAvailable; - iSERVICE(i).bBrowseable = sDefault.bBrowseable; - - DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir)); - - return(True); -} - -/*************************************************************************** -add a new service, based on an old one -***************************************************************************/ -int lp_add_service(char *pszService, int iDefaultService) -{ - return(add_a_service(pSERVICE(iDefaultService),pszService)); -} - - -/*************************************************************************** -add the IPC service -***************************************************************************/ -static BOOL lp_add_ipc(void) -{ - pstring comment; - int i = add_a_service(&sDefault,"IPC$"); - - if (i < 0) - return(False); - - sprintf(comment,"IPC Service (%s)",lp_serverstring()); - - string_set(&iSERVICE(i).szPath,tmpdir()); - string_set(&iSERVICE(i).szUsername,""); - string_set(&iSERVICE(i).comment,comment); - iSERVICE(i).status = False; - iSERVICE(i).iMaxConnections = 0; - iSERVICE(i).bAvailable = True; - iSERVICE(i).bRead_only = True; - iSERVICE(i).bGuest_only = False; - iSERVICE(i).bGuest_ok = True; - iSERVICE(i).bPrint_ok = False; - iSERVICE(i).bBrowseable = sDefault.bBrowseable; - - DEBUG(3,("adding IPC service\n")); - - return(True); -} - - -/*************************************************************************** -add a new printer service, with defaults coming from service iFrom -***************************************************************************/ -BOOL lp_add_printer(char *pszPrintername, int iDefaultService) -{ - char *comment = "From Printcap"; - int i = add_a_service(pSERVICE(iDefaultService),pszPrintername); - - if (i < 0) - return(False); - - /* note that we do NOT default the availability flag to True - */ - /* we take it from the default service passed. This allows all */ - /* dynamic printers to be disabled by disabling the [printers] */ - /* entry (if/when the 'available' keyword is implemented!). */ - - /* the printer name is set to the service name. */ - string_set(&iSERVICE(i).szPrintername,pszPrintername); - string_set(&iSERVICE(i).comment,comment); - iSERVICE(i).bBrowseable = sDefault.bBrowseable; - /* Printers cannot be read_only. */ - iSERVICE(i).bRead_only = False; - /* No share modes on printer services. */ - iSERVICE(i).bShareModes = False; - /* No oplocks on printer services. */ - iSERVICE(i).bOpLocks = False; - /* Printer services must be printable. */ - iSERVICE(i).bPrint_ok = True; - - DEBUG(3,("adding printer service %s\n",pszPrintername)); - - return(True); -} - - -/*************************************************************************** -Do a case-insensitive, whitespace-ignoring string compare. -***************************************************************************/ -static int strwicmp(char *psz1, char *psz2) -{ - /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */ - /* appropriate value. */ - if (psz1 == psz2) - return (0); - else - if (psz1 == NULL) - return (-1); - else - if (psz2 == NULL) - return (1); - - /* sync the strings on first non-whitespace */ - while (1) - { - while (isspace(*psz1)) - psz1++; - while (isspace(*psz2)) - psz2++; - if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0') - break; - psz1++; - psz2++; - } - return (*psz1 - *psz2); -} - -/*************************************************************************** -Map a parameter's string representation to something we can use. -Returns False if the parameter string is not recognised, else TRUE. -***************************************************************************/ -static int map_parameter(char *pszParmName) -{ - int iIndex; - - if (*pszParmName == '-') - return(-1); - - for (iIndex = 0; parm_table[iIndex].label; iIndex++) - if (strwicmp(parm_table[iIndex].label, pszParmName) == 0) - return(iIndex); - - DEBUG(0,( "Unknown parameter encountered: \"%s\"\n", pszParmName)); - return(-1); -} - - -/*************************************************************************** -Set a boolean variable from the text value stored in the passed string. -Returns True in success, False if the passed string does not correctly -represent a boolean. -***************************************************************************/ -static BOOL set_boolean(BOOL *pb, char *pszParmValue) -{ - BOOL bRetval; - - bRetval = True; - if (strwicmp(pszParmValue, "yes") == 0 || - strwicmp(pszParmValue, "true") == 0 || - strwicmp(pszParmValue, "1") == 0) - *pb = True; - else - if (strwicmp(pszParmValue, "no") == 0 || - strwicmp(pszParmValue, "False") == 0 || - strwicmp(pszParmValue, "0") == 0) - *pb = False; - else - { - DEBUG(0,( "Badly formed boolean in configuration file: \"%s\".\n", - pszParmValue)); - bRetval = False; - } - return (bRetval); -} - -/*************************************************************************** -Find a service by name. Otherwise works like get_service. -***************************************************************************/ -static int getservicebyname(char *pszServiceName, service *pserviceDest) -{ - int iService; - - for (iService = iNumServices - 1; iService >= 0; iService--) - if (VALID(iService) && - strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) - { - if (pserviceDest != NULL) - copy_service(pserviceDest, pSERVICE(iService), NULL); - break; - } - - return (iService); -} - - - -/*************************************************************************** -Copy a service structure to another - -If pcopymapDest is NULL then copy all fields -***************************************************************************/ -static void copy_service(service *pserviceDest, - service *pserviceSource, - BOOL *pcopymapDest) -{ - int i; - BOOL bcopyall = (pcopymapDest == NULL); - - for (i=0;parm_table[i].label;i++) - if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && - (bcopyall || pcopymapDest[i])) - { - void *def_ptr = parm_table[i].ptr; - void *src_ptr = - ((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault); - void *dest_ptr = - ((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault); - - switch (parm_table[i].type) - { - case P_BOOL: - case P_BOOLREV: - *(BOOL *)dest_ptr = *(BOOL *)src_ptr; - break; - - case P_INTEGER: - case P_OCTAL: - *(int *)dest_ptr = *(int *)src_ptr; - break; - - case P_CHAR: - *(char *)dest_ptr = *(char *)src_ptr; - break; - - case P_STRING: - string_set(dest_ptr,*(char **)src_ptr); - break; - - case P_USTRING: - string_set(dest_ptr,*(char **)src_ptr); - strupper(*(char **)dest_ptr); - break; - default: - break; - } - } - - if (bcopyall) - { - init_copymap(pserviceDest); - if (pserviceSource->copymap) - memcpy((void *)pserviceDest->copymap, - (void *)pserviceSource->copymap,sizeof(BOOL)*NUMPARAMETERS); - } -} - -/*************************************************************************** -Check a service for consistency. Return False if the service is in any way -incomplete or faulty, else True. -***************************************************************************/ -static BOOL service_ok(int iService) -{ - BOOL bRetval; - - bRetval = True; - if (iSERVICE(iService).szService[0] == '\0') - { - DEBUG(0,( "The following message indicates an internal error:\n")); - DEBUG(0,( "No service name in service entry.\n")); - bRetval = False; - } - - /* The [printers] entry MUST be printable. I'm all for flexibility, but */ - /* I can't see why you'd want a non-printable printer service... */ - if (strwicmp(iSERVICE(iService).szService,PRINTERS_NAME) == 0) - if (!iSERVICE(iService).bPrint_ok) - { - DEBUG(0,( "WARNING: [%s] service MUST be printable!\n", - iSERVICE(iService).szService)); - iSERVICE(iService).bPrint_ok = True; - } - - if (iSERVICE(iService).szPath[0] == '\0' && - strwicmp(iSERVICE(iService).szService,HOMES_NAME) != 0) - { - DEBUG(0,("No path in service %s - using %s\n",iSERVICE(iService).szService,tmpdir())); - string_set(&iSERVICE(iService).szPath,tmpdir()); - } - - /* If a service is flagged unavailable, log the fact at level 0. */ - if (!iSERVICE(iService).bAvailable) - DEBUG(1,( "NOTE: Service %s is flagged unavailable.\n", - iSERVICE(iService).szService)); - - return (bRetval); -} - -static struct file_lists { - struct file_lists *next; - char *name; - time_t modtime; -} *file_lists = NULL; - -/******************************************************************* -keep a linked list of all config files so we know when one has changed -it's date and needs to be reloaded -********************************************************************/ -static void add_to_file_list(char *fname) -{ - struct file_lists *f=file_lists; - - while (f) { - if (f->name && !strcmp(f->name,fname)) break; - f = f->next; - } - - if (!f) { - f = (struct file_lists *)malloc(sizeof(file_lists[0])); - if (!f) return; - f->next = file_lists; - f->name = strdup(fname); - if (!f->name) { - free(f); - return; - } - file_lists = f; - } - - { - pstring n2; - pstrcpy(n2,fname); - standard_sub_basic(n2); - f->modtime = file_modtime(n2); - } - -} - -/******************************************************************* -check if a config file has changed date -********************************************************************/ -BOOL lp_file_list_changed(void) -{ - struct file_lists *f = file_lists; - DEBUG(6,("lp_file_list_changed()\n")); - - while (f) - { - pstring n2; - time_t mod_time; - - pstrcpy(n2,f->name); - standard_sub_basic(n2); - - DEBUG(6,("file %s -> %s last mod_time: %s\n", - f->name, n2, ctime(&f->modtime))); - - mod_time = file_modtime(n2); - - if (f->modtime != mod_time) - { - DEBUG(6,("file %s modified: %s\n", n2, ctime(&mod_time))); - return(True); - } - f = f->next; - } - return(False); -} - -/*************************************************************************** - handle the interpretation of the coding system parameter - *************************************************************************/ -static BOOL handle_coding_system(char *pszParmValue,int *val) -{ - *val = interpret_coding_system(pszParmValue,*val); - return(True); -} - -/*************************************************************************** -handle the interpretation of the character set system parameter -***************************************************************************/ -static BOOL handle_character_set(char *pszParmValue,int *val) -{ - string_set(&Globals.szCharacterSet,pszParmValue); - *val = interpret_character_set(pszParmValue,*val); - return(True); -} - - -/*************************************************************************** -handle the interpretation of the protocol parameter -***************************************************************************/ -static BOOL handle_protocol(char *pszParmValue,int *val) -{ - *val = interpret_protocol(pszParmValue,*val); - return(True); -} - -/*************************************************************************** -handle the interpretation of the security parameter -***************************************************************************/ -static BOOL handle_security(char *pszParmValue,int *val) -{ - *val = interpret_security(pszParmValue,*val); - return(True); -} - -/*************************************************************************** -handle the interpretation of the default case -***************************************************************************/ -static BOOL handle_case(char *pszParmValue,int *val) -{ - if (strnequal(pszParmValue,"LOWER", 5)) - *val = CASE_LOWER; - else if (strnequal(pszParmValue,"UPPER", 5)) - *val = CASE_UPPER; - return(True); -} - -/*************************************************************************** -handle the interpretation of the printing system -***************************************************************************/ -static BOOL handle_printing(char *pszParmValue,int *val) -{ - if (strnequal(pszParmValue,"sysv", 4)) - *val = PRINT_SYSV; - else if (strnequal(pszParmValue,"aix", 3)) - *val = PRINT_AIX; - else if (strnequal(pszParmValue,"hpux", 4)) - *val = PRINT_HPUX; - else if (strnequal(pszParmValue,"bsd", 3)) - *val = PRINT_BSD; - else if (strnequal(pszParmValue,"qnx",3)) - *val = PRINT_QNX; - else if (strnequal(pszParmValue,"plp", 3)) - *val = PRINT_PLP; - else if (strnequal(pszParmValue,"lprng", 5)) - *val = PRINT_LPRNG; - return(True); -} - -/*************************************************************************** -handle the announce as parameter -***************************************************************************/ -static BOOL handle_announce_as(char *pszParmValue,int *val) -{ - if (strnequal(pszParmValue,"NT", 2)) - *val = ANNOUNCE_AS_NT; - else if (strnequal(pszParmValue,"win95", 5)) - *val = ANNOUNCE_AS_WIN95; - else if (strnequal(pszParmValue,"WfW", 3)) - *val = ANNOUNCE_AS_WFW; - return True; -} - -/*************************************************************************** -handle the valid chars lines -***************************************************************************/ -static BOOL handle_valid_chars(char *pszParmValue,char **ptr) -{ - string_set(ptr,pszParmValue); - - /* A dependency here is that the parameter client code page must be - set before this is called - as calling codepage_initialise() - would overwrite the valid char lines. - */ - codepage_initialise(lp_client_code_page()); - - add_char_string(pszParmValue); - return(True); -} - - -/*************************************************************************** -handle the include operation -***************************************************************************/ -static BOOL handle_include(char *pszParmValue,char **ptr) -{ - pstring fname; - pstrcpy(fname,pszParmValue); - - add_to_file_list(fname); - - standard_sub_basic(fname); - - string_set(ptr,fname); - - if (file_exist(fname,NULL)) - return(pm_process(fname, do_section, do_parameter)); - - DEBUG(2,("Can't find include file %s\n",fname)); - - return(False); -} - - -/*************************************************************************** -handle the interpretation of the copy parameter -***************************************************************************/ -static BOOL handle_copy(char *pszParmValue,char **ptr) -{ - BOOL bRetval; - int iTemp; - service serviceTemp; - - string_set(ptr,pszParmValue); - - init_service(&serviceTemp); - - bRetval = False; - - DEBUG(3,("Copying service from service %s\n",pszParmValue)); - - if ((iTemp = getservicebyname(pszParmValue, &serviceTemp)) >= 0) - { - if (iTemp == iServiceIndex) - { - DEBUG(0,("Can't copy service %s - unable to copy self!\n", - pszParmValue)); - } - else - { - copy_service(pSERVICE(iServiceIndex), - &serviceTemp, - iSERVICE(iServiceIndex).copymap); - bRetval = True; - } - } - else - { - DEBUG(0,( "Unable to copy service - source not found: %s\n", - pszParmValue)); - bRetval = False; - } - - free_service(&serviceTemp); - return (bRetval); -} - - -/*************************************************************************** -initialise a copymap -***************************************************************************/ -static void init_copymap(service *pservice) -{ - int i; - if (pservice->copymap) free(pservice->copymap); - pservice->copymap = (BOOL *)malloc(sizeof(BOOL)*NUMPARAMETERS); - if (!pservice->copymap) - DEBUG(0,("Couldn't allocate copymap!! (size %d)\n",NUMPARAMETERS)); - - for (i=0;i<NUMPARAMETERS;i++) - pservice->copymap[i] = True; -} - - -/*************************************************************************** -Process a parameter for a particular service number. If snum < 0 -then assume we are in the globals -***************************************************************************/ -BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue) -{ - int parmnum; - void *parm_ptr=NULL; /* where we are going to store the result */ - void *def_ptr=NULL; - - parmnum = map_parameter(pszParmName); - - if (parmnum < 0) - { - DEBUG(0,( "Ignoring unknown parameter \"%s\"\n", pszParmName)); - return(True); - } - - def_ptr = parm_table[parmnum].ptr; - - /* we might point at a service, the default service or a global */ - if (snum < 0) { - parm_ptr = def_ptr; - } else { - if (parm_table[parmnum].class == P_GLOBAL) { - DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName)); - return(True); - } - parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault); - } - - if (snum >= 0) { - int i; - if (!iSERVICE(snum).copymap) - init_copymap(pSERVICE(snum)); - - /* this handles the aliases - set the copymap for other entries with - the same data pointer */ - for (i=0;parm_table[i].label;i++) - if (parm_table[i].ptr == parm_table[parmnum].ptr) - iSERVICE(snum).copymap[i] = False; - } - - /* if it is a special case then go ahead */ - if (parm_table[parmnum].special) { - parm_table[parmnum].special(pszParmValue,parm_ptr); - return(True); - } - - /* now switch on the type of variable it is */ - switch (parm_table[parmnum].type) - { - case P_BOOL: - set_boolean(parm_ptr,pszParmValue); - break; - - case P_BOOLREV: - set_boolean(parm_ptr,pszParmValue); - *(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr; - break; - - case P_INTEGER: - *(int *)parm_ptr = atoi(pszParmValue); - break; - - case P_CHAR: - *(char *)parm_ptr = *pszParmValue; - break; - - case P_OCTAL: - sscanf(pszParmValue,"%o",(int *)parm_ptr); - break; - - case P_STRING: - string_set(parm_ptr,pszParmValue); - break; - - case P_USTRING: - string_set(parm_ptr,pszParmValue); - strupper(*(char **)parm_ptr); - break; - - case P_GSTRING: - strcpy((char *)parm_ptr,pszParmValue); - break; - - case P_UGSTRING: - strcpy((char *)parm_ptr,pszParmValue); - strupper((char *)parm_ptr); - break; - } - - return(True); -} - -/*************************************************************************** -Process a parameter. -***************************************************************************/ -static BOOL do_parameter(char *pszParmName, char *pszParmValue) -{ - if (!bInGlobalSection && bGlobalOnly) return(True); - - DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue)); - - return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, pszParmName, pszParmValue); -} - - -/*************************************************************************** -print a parameter of the specified type -***************************************************************************/ -static void print_parameter(parm_type type,void *ptr, FILE *f) -{ - switch (type) - { - case P_BOOL: - fprintf(f,"%s",BOOLSTR(*(BOOL *)ptr)); - break; - - case P_BOOLREV: - fprintf(f,"%s",BOOLSTR(! *(BOOL *)ptr)); - break; - - case P_INTEGER: - fprintf(f,"%d",*(int *)ptr); - break; - - case P_CHAR: - fprintf(f,"%c",*(char *)ptr); - break; - - case P_OCTAL: - fprintf(f,"0%o",*(int *)ptr); - break; - - case P_GSTRING: - case P_UGSTRING: - if ((char *)ptr) - fprintf(f,"%s",(char *)ptr); - break; - - case P_STRING: - case P_USTRING: - if (*(char **)ptr) - fprintf(f,"%s",*(char **)ptr); - break; - } -} - - -/*************************************************************************** -print a parameter of the specified type -***************************************************************************/ -static void parameter_string(parm_type type,void *ptr,char *s) -{ - s[0] = 0; - - switch (type) - { - case P_BOOL: - sprintf(s, "%s",BOOLSTR(*(BOOL *)ptr)); - break; - - case P_BOOLREV: - sprintf(s, "%s",BOOLSTR(! *(BOOL *)ptr)); - break; - - case P_INTEGER: - sprintf(s, "%d",*(int *)ptr); - break; - - case P_CHAR: - sprintf(s, "%c",*(char *)ptr); - break; - - case P_OCTAL: - sprintf(s, "0%o",*(int *)ptr); - break; - - case P_GSTRING: - case P_UGSTRING: - if ((char *)ptr) - sprintf(s, "%s",(char *)ptr); - break; - - case P_STRING: - case P_USTRING: - if (*(char **)ptr) - sprintf(s, "%s",*(char **)ptr); - break; - } -} - - -/*************************************************************************** -check if two parameters are equal -***************************************************************************/ -static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2) -{ - switch (type) - { - case P_BOOL: - case P_BOOLREV: - return(*((BOOL *)ptr1) == *((BOOL *)ptr2)); - - case P_INTEGER: - case P_OCTAL: - return(*((int *)ptr1) == *((int *)ptr2)); - - case P_CHAR: - return(*((char *)ptr1) == *((char *)ptr2)); - - case P_GSTRING: - case P_UGSTRING: - { - char *p1 = (char *)ptr1, *p2 = (char *)ptr2; - if (p1 && !*p1) p1 = NULL; - if (p2 && !*p2) p2 = NULL; - return(p1==p2 || strequal(p1,p2)); - } - case P_STRING: - case P_USTRING: - { - char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2; - if (p1 && !*p1) p1 = NULL; - if (p2 && !*p2) p2 = NULL; - return(p1==p2 || strequal(p1,p2)); - } - } - return(False); -} - -/*************************************************************************** -Process a new section (service). At this stage all sections are services. -Later we'll have special sections that permit server parameters to be set. -Returns True on success, False on failure. -***************************************************************************/ -static BOOL do_section(char *pszSectionName) -{ - BOOL bRetval; - BOOL isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) || - (strwicmp(pszSectionName, GLOBAL_NAME2) == 0)); - bRetval = False; - - /* if we were in a global section then do the local inits */ - if (bInGlobalSection && !isglobal) - init_locals(); - - /* if we've just struck a global section, note the fact. */ - bInGlobalSection = isglobal; - - /* check for multiple global sections */ - if (bInGlobalSection) - { - DEBUG(3,( "Processing section \"[%s]\"\n", pszSectionName)); - return(True); - } - - if (!bInGlobalSection && bGlobalOnly) return(True); - - /* if we have a current service, tidy it up before moving on */ - bRetval = True; - - if (iServiceIndex >= 0) - bRetval = service_ok(iServiceIndex); - - /* if all is still well, move to the next record in the services array */ - if (bRetval) - { - /* We put this here to avoid an odd message order if messages are */ - /* issued by the post-processing of a previous section. */ - DEBUG(2,( "Processing section \"[%s]\"\n", pszSectionName)); - - if ((iServiceIndex=add_a_service(&sDefault,pszSectionName)) < 0) - { - DEBUG(0,("Failed to add a new service\n")); - return(False); - } - } - - return (bRetval); -} - -/*************************************************************************** -Display the contents of the global structure. -***************************************************************************/ -static void dump_globals(FILE *f) -{ - int i; - fprintf(f, "# Global parameters\n"); - - for (i=0;parm_table[i].label;i++) - if (parm_table[i].class == P_GLOBAL && - parm_table[i].ptr && - (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) - { - fprintf(f,"\t%s = ",parm_table[i].label); - print_parameter(parm_table[i].type,parm_table[i].ptr, f); - fprintf(f,"\n"); - } -} - -/*************************************************************************** -Display the contents of a single services record. -***************************************************************************/ -static void dump_a_service(service *pService, FILE *f) -{ - int i; - if (pService == &sDefault) - fprintf(f,"\n\n# Default service parameters\n"); - else - fprintf(f,"\n[%s]\n",pService->szService); - - for (i=0;parm_table[i].label;i++) - if (parm_table[i].class == P_LOCAL && - parm_table[i].ptr && - (*parm_table[i].label != '-') && - (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) - { - int pdiff = PTR_DIFF(parm_table[i].ptr,&sDefault); - - if (pService == &sDefault || !equal_parameter(parm_table[i].type, - ((char *)pService) + pdiff, - ((char *)&sDefault) + pdiff)) - { - fprintf(f,"\t%s = ",parm_table[i].label); - print_parameter(parm_table[i].type, - ((char *)pService) + pdiff, f); - fprintf(f,"\n"); - } - } -} - - -/*************************************************************************** -return info about the next service in a service. snum==-1 gives the default -serice and snum==-2 gives the globals - -return 0 when out of parameters -***************************************************************************/ -int lp_next_parameter(int snum, int *i, char *label, - char *value, int allparameters) -{ - if (snum == -2) { - /* do the globals */ - for (;parm_table[*i].label;(*i)++) - if (parm_table[*i].class == P_GLOBAL && - parm_table[*i].ptr && - (*parm_table[*i].label != '-') && - ((*i) == 0 || - (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) { - strcpy(label, parm_table[*i].label); - parameter_string(parm_table[*i].type, - parm_table[*i].ptr, - value); - (*i)++; - return 1; - } - return 0; - } else { - service *pService = (snum==-1?&sDefault:pSERVICE(snum)); - - for (;parm_table[*i].label;(*i)++) - if (parm_table[*i].class == P_LOCAL && - parm_table[*i].ptr && - (*parm_table[*i].label != '-') && - ((*i) == 0 || - (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) { - int pdiff = PTR_DIFF(parm_table[*i].ptr,&sDefault); - - if (snum == -1 || allparameters || - !equal_parameter(parm_table[*i].type, - ((char *)pService) + pdiff, - ((char *)&sDefault) + pdiff)) { - strcpy(label, parm_table[*i].label); - parameter_string(parm_table[*i].type, - ((char *)pService) + pdiff, - value); - (*i)++; - return 1; - } - } - } - - return 0; -} - - -#if 0 -/*************************************************************************** -Display the contents of a single copy structure. -***************************************************************************/ -static void dump_copy_map(BOOL *pcopymap) -{ - int i; - if (!pcopymap) return; - - printf("\n\tNon-Copied parameters:\n"); - - for (i=0;parm_table[i].label;i++) - if (parm_table[i].class == P_LOCAL && - parm_table[i].ptr && !pcopymap[i] && - (i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr))) - { - printf("\t\t%s\n",parm_table[i].label); - } -} -#endif - -/*************************************************************************** -Return TRUE if the passed service number is within range. -***************************************************************************/ -BOOL lp_snum_ok(int iService) -{ - return (LP_SNUM_OK(iService) && iSERVICE(iService).bAvailable); -} - - -/*************************************************************************** -auto-load some homes and printer services -***************************************************************************/ -static void lp_add_auto_services(char *str) -{ - char *s; - char *p; - int homes = lp_servicenumber(HOMES_NAME); - int printers = lp_servicenumber(PRINTERS_NAME); - - if (!str) - return; - - s = strdup(str); - if (!s) return; - - for (p=strtok(s,LIST_SEP);p;p=strtok(NULL,LIST_SEP)) - { - char *home = get_home_dir(p); - - if (lp_servicenumber(p) >= 0) continue; - - if (home && homes >= 0) - { - lp_add_home(p,homes,home); - continue; - } - - if (printers >= 0 && pcap_printername_ok(p,NULL)) - lp_add_printer(p,printers); - } - free(s); -} - -/*************************************************************************** -auto-load one printer -***************************************************************************/ -static void lp_add_one_printer(char *name,char *comment) -{ - int printers = lp_servicenumber(PRINTERS_NAME); - int i; - - if (lp_servicenumber(name) < 0) - { - lp_add_printer(name,printers); - if ((i=lp_servicenumber(name)) >= 0) - string_set(&iSERVICE(i).comment,comment); - } -} - - -/*************************************************************************** -auto-load printer services -***************************************************************************/ -static void lp_add_all_printers(void) -{ - int printers = lp_servicenumber(PRINTERS_NAME); - - if (printers < 0) return; - - pcap_printer_fn(lp_add_one_printer); -} - -/*************************************************************************** -have we loaded a services file yet? -***************************************************************************/ -BOOL lp_loaded(void) -{ - return(bLoaded); -} - -/*************************************************************************** -unload unused services -***************************************************************************/ -void lp_killunused(BOOL (*snumused)(int )) -{ - int i; - for (i=0;i<iNumServices;i++) - if (VALID(i) && (!snumused || !snumused(i))) - { - iSERVICE(i).valid = False; - free_service(pSERVICE(i)); - } -} - -/*************************************************************************** -Load the services array from the services file. Return True on success, -False on failure. -***************************************************************************/ -BOOL lp_load(char *pszFname,BOOL global_only) -{ - pstring n2; - BOOL bRetval; - - add_to_file_list(pszFname); - - bRetval = False; - - bInGlobalSection = True; - bGlobalOnly = global_only; - - init_globals(); - - pstrcpy(n2,pszFname); - standard_sub_basic(n2); - - /* We get sections first, so have to start 'behind' to make up */ - iServiceIndex = -1; - bRetval = pm_process(n2, do_section, do_parameter); - - /* finish up the last section */ - DEBUG(3,("pm_process() returned %s\n", BOOLSTR(bRetval))); - if (bRetval) - if (iServiceIndex >= 0) - bRetval = service_ok(iServiceIndex); - - lp_add_auto_services(lp_auto_services()); - if (lp_load_printers()) - lp_add_all_printers(); - - lp_add_ipc(); - - set_default_server_announce_type(); - - bLoaded = True; - - return (bRetval); -} - - -/*************************************************************************** -return the max number of services -***************************************************************************/ -int lp_numservices(void) -{ - return(iNumServices); -} - -/*************************************************************************** -Display the contents of the services array in human-readable form. -***************************************************************************/ -void lp_dump(FILE *f) -{ - int iService; - - dump_globals(f); - - dump_a_service(&sDefault, f); - - for (iService = 0; iService < iNumServices; iService++) - { - if (VALID(iService)) - { - if (iSERVICE(iService).szService[0] == '\0') - break; - dump_a_service(pSERVICE(iService), f); - } - } -} - - -/*************************************************************************** -Return the number of the service with the given name, or -1 if it doesn't -exist. Note that this is a DIFFERENT ANIMAL from the internal function -getservicebyname()! This works ONLY if all services have been loaded, and -does not copy the found service. -***************************************************************************/ -int lp_servicenumber(char *pszServiceName) -{ - int iService; - - for (iService = iNumServices - 1; iService >= 0; iService--) - if (VALID(iService) && - strwicmp(iSERVICE(iService).szService, pszServiceName) == 0) - break; - - if (iService < 0) - DEBUG(7,("lp_servicenumber: couldn't find %s\n",pszServiceName)); - - return (iService); -} - -/******************************************************************* - a useful volume label function - ******************************************************************/ -char *volume_label(int snum) -{ - char *ret = lp_volume(snum); - if (!*ret) return(lp_servicename(snum)); - return(ret); -} - -#if 0 -/* - * nmbd only loads the global section. There seems to be no way to - * determine exactly is a service is printable by only looking at the - * [global] section so for now always announce as a print server. This - * will need looking at in the future. Jeremy (jallison@whistle.com). - */ -/******************************************************************* - Return true if any printer services are defined. - ******************************************************************/ -static BOOL lp_printer_services(void) -{ - int iService; - - for (iService = iNumServices - 1; iService >= 0; iService--) - if (VALID(iService) && iSERVICE(iService).bPrint_ok) - return True; - return False; -} -#endif - -/******************************************************************* - Set the server type we will announce as via nmbd. -********************************************************************/ -static void set_default_server_announce_type() -{ - default_server_announce = (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | - SV_TYPE_SERVER_UNIX | SV_TYPE_PRINTQ_SERVER); - if(lp_announce_as() == ANNOUNCE_AS_NT) - default_server_announce |= (SV_TYPE_SERVER_NT | SV_TYPE_NT); - else if(lp_announce_as() == ANNOUNCE_AS_WIN95) - default_server_announce |= SV_TYPE_WIN95_PLUS; - else if(lp_announce_as() == ANNOUNCE_AS_WFW) - default_server_announce |= SV_TYPE_WFW; - default_server_announce |= (lp_time_server() ? SV_TYPE_TIME_SOURCE : 0); -/* - * nmbd only loads the [global] section. There seems to be no way to - * determine exactly if any service is printable by only looking at the - * [global] section so for now always announce as a print server. This - * will need looking at in the future. Jeremy (jallison@whistle.com). - */ -#if 0 - default_server_announce |= (lp_printer_services() ? SV_TYPE_PRINTQ_SERVER : 0); -#endif -} - - -/******************************************************************* -rename a service -********************************************************************/ -void lp_rename_service(int snum, char *new_name) -{ - string_set(&pSERVICE(snum)->szService, new_name); -} - -/******************************************************************* -remove a service -********************************************************************/ -void lp_remove_service(int snum) -{ - pSERVICE(snum)->valid = False; -} - -/******************************************************************* -copy a service -********************************************************************/ -void lp_copy_service(int snum, char *new_name) -{ - char *oldname = lp_servicename(snum); - do_section(new_name); - if (snum >= 0) { - snum = lp_servicenumber(new_name); - if (snum >= 0) - lp_do_parameter(snum, "copy", oldname); - } -} - - -/******************************************************************* - Get the default server type we will announce as via nmbd. -********************************************************************/ -int lp_default_server_announce(void) -{ - return default_server_announce; -} - -/******************************************************************* - Split the announce version into major and minor numbers. -********************************************************************/ -int lp_major_announce_version(void) -{ - static BOOL got_major = False; - static int major_version = DEFAULT_MAJOR_VERSION; - char *vers; - char *p; - - if(got_major) - return major_version; - - got_major = True; - if((vers = lp_announce_version()) == NULL) - return major_version; - - if((p = strchr(vers, '.')) == 0) - return major_version; - - *p = '\0'; - major_version = atoi(vers); - return major_version; -} - -int lp_minor_announce_version(void) -{ - static BOOL got_minor = False; - static int minor_version = DEFAULT_MINOR_VERSION; - char *vers; - char *p; - - if(got_minor) - return minor_version; - - got_minor = True; - if((vers = lp_announce_version()) == NULL) - return minor_version; - - if((p = strchr(vers, '.')) == 0) - return minor_version; - - p++; - minor_version = atoi(p); - return minor_version; -} - diff --git a/source/param/params.c b/source/param/params.c deleted file mode 100644 index 4d1c191b479..00000000000 --- a/source/param/params.c +++ /dev/null @@ -1,566 +0,0 @@ -/* -------------------------------------------------------------------------- ** - * Microsoft Network Services for Unix, AKA., Andrew Tridgell's SAMBA. - * - * This module Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer - * - * Rewritten almost completely by Christopher R. Hertel - * at the University of Minnesota, September, 1997. - * This module Copyright (C) 1997 by the University of Minnesota - * -------------------------------------------------------------------------- ** - * - * 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: params - * - * -------------------------------------------------------------------------- ** - * - * This module performs lexical analysis and initial parsing of a - * Windows-like parameter file. It recognizes and handles four token - * types: section-name, parameter-name, parameter-value, and - * end-of-file. Comments and line continuation are handled - * internally. - * - * The entry point to the module is function pm_process(). This - * function opens the source file, calls the Parse() function to parse - * the input, and then closes the file when either the EOF is reached - * or a fatal error is encountered. - * - * A sample parameter file might look like this: - * - * [section one] - * parameter one = value string - * parameter two = another value - * [section two] - * new parameter = some value or t'other - * - * The parameter file is divided into sections by section headers: - * section names enclosed in square brackets (eg. [section one]). - * Each section contains parameter lines, each of which consist of a - * parameter name and value delimited by an equal sign. Roughly, the - * syntax is: - * - * <file> :== { <section> } EOF - * - * <section> :== <section header> { <parameter line> } - * - * <section header> :== '[' NAME ']' - * - * <parameter line> :== NAME '=' VALUE '\n' - * - * Blank lines and comment lines are ignored. Comment lines are lines - * beginning with either a semicolon (';') or a pound sign ('#'). - * - * All whitespace in section names and parameter names is compressed - * to single spaces. Leading and trailing whitespace is stipped from - * both names and values. - * - * 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, - * with the exception of the '\r' character, which is stripped for - * historic reasons. Parameter names may not start with a left square - * bracket, an equal sign, a pound sign, or a semicolon, because these - * are used to identify other tokens. - * - * -------------------------------------------------------------------------- ** - */ - -#include "includes.h" - -/* -------------------------------------------------------------------------- ** - * Constants... - */ - -#define BUFR_INC 1024 - - -/* -------------------------------------------------------------------------- ** - * Variables... - * - * DEBUGLEVEL - The ubiquitous DEBUGLEVEL. This determines which DEBUG() - * messages will be produced. - * bufr - pointer to a global buffer. This is probably a kludge, - * but it was the nicest kludge I could think of (for now). - * bSize - The size of the global buffer <bufr>. - */ - -extern int DEBUGLEVEL; - -static char *bufr = NULL; -static int bSize = 0; - -/* -------------------------------------------------------------------------- ** - * Functions... - */ - -static int EatWhitespace( FILE *InFile ) - /* ------------------------------------------------------------------------ ** - * Scan past whitespace (see ctype(3C)) and return the first non-whitespace - * character, or newline, or EOF. - * - * Input: InFile - Input source. - * - * Output: The next non-whitespace character in the input stream. - * - * Notes: Because the config files use a line-oriented grammar, we - * explicitly exclude the newline character from the list of - * whitespace characters. - * - Note that both EOF (-1) and the nul character ('\0') are - * considered end-of-file markers. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - - for( c = getc( InFile ); isspace( c ) && ('\n' != c); c = getc( InFile ) ) - ; - return( c ); - } /* EatWhitespace */ - -static int EatComment( FILE *InFile ) - /* ------------------------------------------------------------------------ ** - * Scan to the end of a comment. - * - * Input: InFile - Input source. - * - * Output: The character that marks the end of the comment. Normally, - * this will be a newline, but it *might* be an EOF. - * - * Notes: Because the config files use a line-oriented grammar, we - * explicitly exclude the newline character from the list of - * whitespace characters. - * - Note that both EOF (-1) and the nul character ('\0') are - * considered end-of-file markers. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - - for( c = getc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = getc( InFile ) ) - ; - return( c ); - } /* EatComment */ - -static int Continuation( char *line, int pos ) - /* ------------------------------------------------------------------------ ** - * Scan backards within a string to discover if the last non-whitespace - * character is a line-continuation character ('\\'). - * - * Input: line - A pointer to a buffer containing the string to be - * scanned. - * pos - This is taken to be the offset of the end of the - * string. This position is *not* scanned. - * - * Output: The offset of the '\\' character if it was found, or -1 to - * indicate that it was not. - * - * ------------------------------------------------------------------------ ** - */ - { - pos--; - while( (pos >= 0) && isspace(line[pos]) ) - pos--; - - return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 ); - } /* Continuation */ - - -static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) ) - /* ------------------------------------------------------------------------ ** - * Scan a section name, and pass the name to function sfunc(). - * - * Input: InFile - Input source. - * sfunc - Pointer to the function to be called if the section - * name is successfully read. - * - * Output: True if the section name was read and True was returned from - * <sfunc>. False if <sfunc> failed or if a lexical error was - * encountered. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - int i; - int end; - char *func = "params.c:Section() -"; - - i = 0; /* <i> is the offset of the next free byte in bufr[] and */ - end = 0; /* <end> is the current "end of string" offset. In most */ - /* cases these will be the same, but if the last */ - /* character written to bufr[] is a space, then <end> */ - /* will be one less than <i>. */ - - c = EatWhitespace( InFile ); /* We've already got the '['. Scan */ - /* past initial white space. */ - - while( (EOF != c) && (c > 0) ) - { - - /* Check that the buffer is big enough for the next character. */ - if( i > (bSize - 2) ) - { - bSize += BUFR_INC; - bufr = Realloc( bufr, bSize ); - if( NULL == bufr ) - { - DEBUG(0, ("%s Memory re-allocation failure.", func) ); - return( False ); - } - } - - /* Handle a single character. */ - switch( c ) - { - case ']': /* Found the closing bracket. */ - bufr[end] = '\0'; - if( 0 == end ) /* Don't allow an empty name. */ - { - DEBUG(0, ("%s Empty section name in configuration file.\n", func )); - return( False ); - } - if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */ - return( False ); - (void)EatComment( InFile ); /* Finish off the line. */ - return( True ); - - case '\n': /* Got newline before closing ']'. */ - i = Continuation( bufr, i ); /* Check for line continuation. */ - if( i < 0 ) - { - bufr[end] = '\0'; - DEBUG(0, ("%s Badly formed line in configuration file: %s\n", - func, bufr )); - return( False ); - } - end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i); - c = getc( InFile ); /* Continue with next line. */ - break; - - default: /* All else are a valid name chars. */ - if( isspace( c ) ) /* One space per whitespace region. */ - { - bufr[end] = ' '; - i = end + 1; - c = EatWhitespace( InFile ); - } - else /* All others copy verbatim. */ - { - bufr[i++] = c; - end = i; - c = getc( InFile ); - } - } - } - - /* We arrive here if we've met the EOF before the closing bracket. */ - DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, bufr )); - return( False ); - } /* Section */ - -static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c ) - /* ------------------------------------------------------------------------ ** - * Scan a parameter name and value, and pass these two fields to pfunc(). - * - * Input: InFile - The input source. - * pfunc - A pointer to the function that will be called to - * process the parameter, once it has been scanned. - * c - The first character of the parameter name, which - * would have been read by Parse(). Unlike a comment - * line or a section header, there is no lead-in - * character that can be discarded. - * - * Output: True if the parameter name and value were scanned and processed - * successfully, else False. - * - * Notes: This function is in two parts. The first loop scans the - * parameter name. Internal whitespace is compressed, and an - * equal sign (=) terminates the token. Leading and trailing - * whitespace is discarded. The second loop scans the parameter - * value. When both have been successfully identified, they are - * passed to pfunc() for processing. - * - * ------------------------------------------------------------------------ ** - */ - { - int i = 0; /* Position within bufr. */ - int end = 0; /* bufr[end] is current end-of-string. */ - int vstart = 0; /* Starting position of the parameter value. */ - char *func = "params.c:Parameter() -"; - - /* Read the parameter name. */ - while( 0 == vstart ) /* Loop until we've found the start of the value. */ - { - - if( i > (bSize - 2) ) /* Ensure there's space for next char. */ - { - bSize += BUFR_INC; - bufr = Realloc( bufr, bSize ); - if( NULL == bufr ) - { - DEBUG(0, ("%s Memory re-allocation failure.", func) ); - return( False ); - } - } - - switch( c ) - { - case '=': /* Equal sign marks end of param name. */ - if( 0 == end ) /* Don't allow an empty name. */ - { - DEBUG(0, ("%s Invalid parameter name in config. file.\n", func )); - return( False ); - } - bufr[end++] = '\0'; /* Mark end of string & advance. */ - i = end; /* New string starts here. */ - vstart = end; /* New string is parameter value. */ - bufr[i] = '\0'; /* New string is nul, for now. */ - break; - - case '\n': /* Find continuation char, else error. */ - i = Continuation( bufr, i ); - if( i < 0 ) - { - bufr[end] = '\0'; - DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n", - func, bufr )); - return( True ); - } - end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i); - c = getc( InFile ); /* Read past eoln. */ - break; - - case '\0': /* Shouldn't have EOF within param name. */ - case EOF: - bufr[i] = '\0'; - DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, bufr )); - return( True ); - - default: - if( isspace( c ) ) /* One ' ' per whitespace region. */ - { - bufr[end] = ' '; - i = end + 1; - c = EatWhitespace( InFile ); - } - else /* All others verbatim. */ - { - bufr[i++] = c; - end = i; - c = getc( InFile ); - } - } - } - - /* Now parse the value. */ - c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */ - while( (EOF !=c) && (c > 0) ) - { - - if( i > (bSize - 2) ) /* Make sure there's enough room. */ - { - bSize += BUFR_INC; - bufr = Realloc( bufr, bSize ); - if( NULL == bufr ) - { - DEBUG(0, ("%s Memory re-allocation failure.", func) ); - return( False ); - } - } - - switch( c ) - { - case '\r': /* Explicitly remove '\r' because the older */ - c = getc( InFile ); /* version called fgets_slash() which also */ - break; /* removes them. */ - - case '\n': /* Marks end of value unless there's a '\'. */ - i = Continuation( bufr, i ); - if( i < 0 ) - c = 0; - else - { - for( end = i; (end >= 0) && isspace(bufr[end]); end-- ) - ; - c = getc( InFile ); - } - break; - - default: /* All others verbatim. Note that spaces do */ - bufr[i++] = c; /* not advance <end>. This allows trimming */ - if( !isspace( c ) ) /* of whitespace at the end of the line. */ - end = i; - c = getc( InFile ); - break; - } - } - bufr[end] = '\0'; /* End of value. */ - - return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */ - } /* Parameter */ - -static BOOL Parse( FILE *InFile, - BOOL (*sfunc)(char *), - BOOL (*pfunc)(char *, char *) ) - /* ------------------------------------------------------------------------ ** - * Scan & parse the input. - * - * Input: InFile - Input source. - * sfunc - Function to be called when a section name is scanned. - * See Section(). - * pfunc - Function to be called when a parameter is scanned. - * See Parameter(). - * - * Output: True if the file was successfully scanned, else False. - * - * Notes: The input can be viewed in terms of 'lines'. There are four - * types of lines: - * Blank - May contain whitespace, otherwise empty. - * Comment - First non-whitespace character is a ';' or '#'. - * The remainder of the line is ignored. - * Section - First non-whitespace character is a '['. - * Parameter - The default case. - * - * ------------------------------------------------------------------------ ** - */ - { - int c; - - c = EatWhitespace( InFile ); - while( (EOF != c) && (c > 0) ) - { - switch( c ) - { - case '\n': /* Blank line. */ - c = EatWhitespace( InFile ); - break; - - case ';': /* Comment line. */ - case '#': - c = EatComment( InFile ); - break; - - case '[': /* Section Header. */ - if( !Section( InFile, sfunc ) ) - return( False ); - c = EatWhitespace( InFile ); - break; - - case '\\': /* Bogus backslash. */ - c = EatWhitespace( InFile ); - break; - - default: /* Parameter line. */ - if( !Parameter( InFile, pfunc, c ) ) - return( False ); - c = EatWhitespace( InFile ); - break; - } - } - return( True ); - } /* Parse */ - -static FILE *OpenConfFile( char *FileName ) - /* ------------------------------------------------------------------------ ** - * Open a configuration file. - * - * Input: FileName - The pathname of the config file to be opened. - * - * Output: A pointer of type (FILE *) to the opened file, or NULL if the - * file could not be opened. - * - * ------------------------------------------------------------------------ ** - */ - { - FILE *OpenedFile; - char *func = "params.c:OpenConfFile() -"; - - if( NULL == FileName || 0 == *FileName ) - { - DEBUG( 0, ("%s No configuration filename specified.\n", func) ); - return( NULL ); - } - - OpenedFile = fopen( FileName, "r" ); - if( NULL == OpenedFile ) - { - DEBUG( 0, - ("%s Unable to open configuration file \"%s\":\n\t%s\n", - func, FileName, strerror(errno)) ); - } - - return( OpenedFile ); - } /* OpenConfFile */ - -BOOL pm_process( char *FileName, - BOOL (*sfunc)(char *), - BOOL (*pfunc)(char *, char *) ) - /* ------------------------------------------------------------------------ ** - * Process the named parameter file. - * - * Input: FileName - The pathname of the parameter file to be opened. - * sfunc - A pointer to a function that will be called when - * a section name is discovered. - * pfunc - A pointer to a function that will be called when - * a parameter name and value are discovered. - * - * Output: TRUE if the file was successfully parsed, else FALSE. - * - * ------------------------------------------------------------------------ ** - */ - { - int result; - FILE *InFile; - char *func = "params.c:pm_process() -"; - - InFile = OpenConfFile( FileName ); /* Open the config file. */ - if( NULL == InFile ) - return( False ); - - DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) ); - - if( NULL != bufr ) /* If we already have a buffer */ - result = Parse( InFile, sfunc, pfunc ); /* (recursive call), then just */ - /* use it. */ - - else /* If we don't have a buffer */ - { /* allocate one, then parse, */ - bSize = BUFR_INC; /* then free. */ - bufr = (char *)malloc( bSize ); - if( NULL == bufr ) - { - DEBUG(0,("%s memory allocation failure.\n", func)); - return( False ); - } - result = Parse( InFile, sfunc, pfunc ); - free( bufr ); - bufr = NULL; - bSize = 0; - } - - if( !result ) /* Generic failure. */ - { - DEBUG(0,("%s Failed. Error returned from params.c:parse().\n", func)); - return( False ); - } - - return( True ); /* Generic success. */ - } /* pm_process */ - -/* -------------------------------------------------------------------------- */ diff --git a/source/passdb/smbpass.c b/source/passdb/smbpass.c deleted file mode 100644 index 441ab94ffbb..00000000000 --- a/source/passdb/smbpass.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * 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" - -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; -} diff --git a/source/printing/pcap.c b/source/printing/pcap.c deleted file mode 100644 index 65195ab1af6..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-1997 - - 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) pstrcpy(comment,name); - pstrcpy(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 51fd3a992eb..00000000000 --- a/source/printing/printing.c +++ /dev/null @@ -1,1102 +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 - pstrcpy(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); - fstrcpy(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) - { - fstrcpy(tmp,p+1); - fstrcpy(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) - { - fstrcpy(tmp,p+1); - fstrcpy(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) - { - fstrcpy(tmp,p+1); - fstrcpy(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; - fstrcpy(tmp,p+1); - fstrcpy(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) - { - fstrcpy(tmp,p+1); - fstrcpy(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) - { - fstrcpy(tmp,p+1); - fstrcpy(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))) - pstrcpy(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,("xx 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); - } - - pstrcpy(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); - - pstrcpy(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); - - pstrcpy(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 */ -} - - - -/**************************************************************************** -we encode print job numbers over the wire so that when we get them back we can -tell not only what print job they are but also what service it belongs to, -this is to overcome the problem that windows clients tend to send the wrong -service number when doing print queue manipulation! -****************************************************************************/ -int printjob_encode(int snum, int job) -{ - return ((snum&0xFF)<<8) | (job & 0xFF); -} - -/**************************************************************************** -and now decode them again ... -****************************************************************************/ -void printjob_decode(int jobid, int *snum, int *job) -{ - (*snum) = (jobid >> 8) & 0xFF; - (*job) = jobid & 0xFF; -} 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/installcp.sh b/source/script/installcp.sh deleted file mode 100755 index bafd84146d7..00000000000 --- a/source/script/installcp.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -LIBDIR=$1 -CODEPAGEDIR=$2 -BINDIR=$3 - -shift -shift -shift - -echo Installing codepage files in $CODEPAGEDIR -for d in $LIBDIR $CODEPAGEDIR; 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 Creating codepage file $CODEPAGEDIR/codepage.$p from codepage_def.$p - $BINDIR/make_smbcodepage c $p codepage_def.$p $CODEPAGEDIR/codepage.$p -done - - -cat << EOF -====================================================================== -The code pages have been installed. You may uninstall them using the command -the command "make uninstallcp" or make "uninstall" to uninstall binaries, -man pages, shell scripts and code pages. -====================================================================== -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 1ccf2fb2b0a..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|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|arc4_key/ { - 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 dcf01edb208..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="$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/uninstallcp.sh b/source/script/uninstallcp.sh deleted file mode 100755 index bd7013c358f..00000000000 --- a/source/script/uninstallcp.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -CPDIR=$1 -shift - -if [ ! -d $CPDIR ]; then - echo Directory $CPDIR does not exist! - echo Do a "make installcp" or "make install" first. - exit 1 -fi - -for p in $*; do - if [ ! -f $CPDIR/codepage.$p ]; then - echo $CPDIR/codepage.$p does not exist! - else - echo Removing $CPDIR/codepage.$p - rm -f $CPDIR/codepage.$p - if [ -f $CPDIR/codepage.$p ]; then - echo Cannot remove $CPDIR/codepage.$p... does $USER have privileges? - fi - fi -done - -cat << EOF -====================================================================== -The code pages have been uninstalled. You may reinstall them using -the command "make installcp" or "make install" to install binaries, -man pages, shell scripts and code pages. You may recover a previous version -(if any with "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/smbadduser b/source/smbadduser deleted file mode 100755 index 789cc927eb1..00000000000 --- a/source/smbadduser +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/csh -# -# smbadduser - Written by Mike Zakharoff -# -unalias * -set path = ($path /usr/local/samba/bin) - -set smbpasswd = /usr/local/samba/private/smbpasswd -set user_map = /usr/local/samba/lib/users.map -# -# Set to site specific passwd command -# -#set passwd = "cat /etc/passwd" -#set passwd = "niscat passwd.org_dir" -set passwd = "ypcat passwd" - -set line = "----------------------------------------------------------" -if ($#argv == 0) then - echo $line - echo "Written: Mike Zakharoff email: michael.j.zakharoff@boeing.com" - echo "" - echo " 1) Updates $smbpasswd" - echo " 2) Updates $user_map" - echo " 3) Executes smbpasswd for each new user" - echo "" - echo "smbadduser unixid:ntid unixid:ntid ..." - echo "" - echo "Example: smbadduser zak:zakharoffm johns:smithj" - echo $line - exit 1 -endif - -touch $smbpasswd $user_map -set new = () -foreach one ($argv) - echo $one | grep ':' >& /dev/null - if ($status != 0) then - echo "ERROR: Must use unixid:ntid like -> zak:zakharoffm" - continue - endif - set unix = `echo $one | awk -F: '{print $1}'` - set ntid = `echo $one | awk -F: '{print $2}'` - - set usr = `eval $passwd | awk -F: '$1==USR {print $1}' USR=$unix` - if ($#usr != 1) then - echo "ERROR: $unix Not in passwd database SKIPPING..." - continue - endif - set tmp = `cat $smbpasswd | awk -F: '$1==USR {print $1}' USR=$unix` - if ($#tmp != 0) then - echo "ERROR: $unix is already in $smbpasswd SKIPPING..." - continue - endif - - echo "Adding: $unix to $smbpasswd" - eval $passwd | \ - awk -F: '$1==USR { \ - printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", -$1, $3, $5, $6, $7) }' USR=$unix >> $smbpasswd - if ($unix != $ntid) then - echo "Adding: {$unix = $ntid} to $user_map" - echo "$unix = $ntid" >> $user_map - endif - set new = ($new $unix) -end - -# -# Enter password for new users -# -foreach one ($new) - echo $line - echo "ENTER password for $one" - smbpasswd $one -end
\ No newline at end of file diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c deleted file mode 100644 index bed81138b24..00000000000 --- a/source/smbd/chgpasswd.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Samba utility 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. -*/ - -/* 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; -#if defined(SVR4) || defined(SUNOS5) - extern char *ptsname(); -#else /* defined(SVR4) || defined(SUNOS5) */ - static char line[12]; - void *dirp; - char *dpname; -#endif /* defined(SVR4) || defined(SUNOS5) */ - -#if defined(SVR4) || defined(SUNOS5) - if ((master = open("/dev/ptmx", O_RDWR)) >= 1) { - grantpt(master); - unlockpt(master); - *slave = ptsname(master); - return (master); - } -#else /* defined(SVR4) || defined(SUNOS5) */ - strcpy( line, "/dev/ptyXX" ); - - dirp = OpenDir(-1, "/dev", True); - 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 /* defined(SVR4) || defined(SUNOS5) */ - 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 /* USE_SETRES */ - setuid(0); -#endif /* USE_SETRES */ - - /* 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); - } -#if defined(SVR4) || defined(SUNOS5) - ioctl(slave, I_PUSH, "ptem"); - ioctl(slave, I_PUSH, "ldterm"); -#else /* defined(SVR4) || defined(SUNOS5) */ - if (ioctl(slave,TIOCSCTTY,0) <0) { - DEBUG(3,("Error in ioctl call for slave pty\n")); - /* return(False); */ - } -#endif /* defined(SVR4) || defined(SUNOS5) */ - - /* 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; - pstrcpy(s1,buf); - pstrcpy(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)) - pstrcpy(passwordprogram,PASSWD_PROGRAM); - pstrcpy(chatsequence,PASSWD_CHAT); -#else - pstrcpy(passwordprogram,lp_passwd_program()); - pstrcpy(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/dir.c b/source/smbd/dir.c deleted file mode 100644 index 316b58818fd..00000000000 --- a/source/smbd/dir.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Directory handling 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[]; - -/* - This module implements directory related functions for Samba. -*/ - - - -uint32 dircounter = 0; - - -#define NUMDIRPTRS 256 - - -static struct dptr_struct -{ - int pid; - int cnum; - uint32 lastused; - void *ptr; - BOOL valid; - BOOL finished; - BOOL expect_close; - char *wcard; /* Field only used for lanman2 trans2_findfirst/next searches */ - uint16 attr; /* Field only used for lanman2 trans2_findfirst/next searches */ - char *path; -} -dirptrs[NUMDIRPTRS]; - - -static int dptrs_open = 0; - -/**************************************************************************** -initialise the dir array -****************************************************************************/ -void init_dptrs(void) -{ - static BOOL dptrs_init=False; - int i; - - if (dptrs_init) return; - for (i=0;i<NUMDIRPTRS;i++) - { - dirptrs[i].valid = False; - dirptrs[i].wcard = NULL; - dirptrs[i].ptr = NULL; - string_init(&dirptrs[i].path,""); - } - dptrs_init = True; -} - -/**************************************************************************** -idle a dptr - the directory is closed but the control info is kept -****************************************************************************/ -static void dptr_idle(int key) -{ - if (dirptrs[key].valid && dirptrs[key].ptr) { - DEBUG(4,("Idling dptr key %d\n",key)); - dptrs_open--; - CloseDir(dirptrs[key].ptr); - dirptrs[key].ptr = NULL; - } -} - -/**************************************************************************** -idle the oldest dptr -****************************************************************************/ -static void dptr_idleoldest(void) -{ - int i; - uint32 old=dircounter+1; - int oldi= -1; - for (i=0;i<NUMDIRPTRS;i++) - if (dirptrs[i].valid && dirptrs[i].ptr && dirptrs[i].lastused < old) { - old = dirptrs[i].lastused; - oldi = i; - } - if (oldi != -1) - dptr_idle(oldi); - else - DEBUG(0,("No dptrs available to idle??\n")); -} - -/**************************************************************************** -get the dir ptr for a dir index -****************************************************************************/ -static void *dptr_get(int key,uint32 lastused) -{ - struct dptr_struct *dp = &dirptrs[key]; - - if (dp->valid) { - if (lastused) dp->lastused = lastused; - if (!dp->ptr) { - if (dptrs_open >= MAXDIR) - dptr_idleoldest(); - DEBUG(4,("Reopening dptr key %d\n",key)); - if ((dp->ptr = OpenDir(dp->cnum, dp->path, True))) - dptrs_open++; - } - return(dp->ptr); - } - return(NULL); -} - -/**************************************************************************** -get the dir path for a dir index -****************************************************************************/ -char *dptr_path(int key) -{ - if (dirptrs[key].valid) - return(dirptrs[key].path); - return(NULL); -} - -/**************************************************************************** -get the dir wcard for a dir index (lanman2 specific) -****************************************************************************/ -char *dptr_wcard(int key) -{ - if (dirptrs[key].valid) - return(dirptrs[key].wcard); - return(NULL); -} - -/**************************************************************************** -set the dir wcard for a dir index (lanman2 specific) -Returns 0 on ok, 1 on fail. -****************************************************************************/ -BOOL dptr_set_wcard(int key, char *wcard) -{ - if (dirptrs[key].valid) { - dirptrs[key].wcard = wcard; - return True; - } - return False; -} - -/**************************************************************************** -set the dir attrib for a dir index (lanman2 specific) -Returns 0 on ok, 1 on fail. -****************************************************************************/ -BOOL dptr_set_attr(int key, uint16 attr) -{ - if (dirptrs[key].valid) { - dirptrs[key].attr = attr; - return True; - } - return False; -} - -/**************************************************************************** -get the dir attrib for a dir index (lanman2 specific) -****************************************************************************/ -uint16 dptr_attr(int key) -{ - if (dirptrs[key].valid) - return(dirptrs[key].attr); - return(0); -} - -/**************************************************************************** -close a dptr -****************************************************************************/ -void dptr_close(int key) -{ - /* OS/2 seems to use -1 to indicate "close all directories" */ - if (key == -1) { - int i; - for (i=0;i<NUMDIRPTRS;i++) - dptr_close(i); - return; - } - - if (key < 0 || key >= NUMDIRPTRS) { - DEBUG(3,("Invalid key %d given to dptr_close\n",key)); - return; - } - - if (dirptrs[key].valid) { - DEBUG(4,("closing dptr key %d\n",key)); - if (dirptrs[key].ptr) { - CloseDir(dirptrs[key].ptr); - dptrs_open--; - } - /* Lanman 2 specific code */ - if (dirptrs[key].wcard) - free(dirptrs[key].wcard); - dirptrs[key].valid = False; - string_set(&dirptrs[key].path,""); - } -} - -/**************************************************************************** -close all dptrs for a cnum -****************************************************************************/ -void dptr_closecnum(int cnum) -{ - int i; - for (i=0;i<NUMDIRPTRS;i++) - if (dirptrs[i].valid && dirptrs[i].cnum == cnum) - dptr_close(i); -} - -/**************************************************************************** -idle all dptrs for a cnum -****************************************************************************/ -void dptr_idlecnum(int cnum) -{ - int i; - for (i=0;i<NUMDIRPTRS;i++) - if (dirptrs[i].valid && dirptrs[i].cnum == cnum && dirptrs[i].ptr) - dptr_idle(i); -} - -/**************************************************************************** -close a dptr that matches a given path, only if it matches the pid also -****************************************************************************/ -void dptr_closepath(char *path,int pid) -{ - int i; - for (i=0;i<NUMDIRPTRS;i++) - if (dirptrs[i].valid && pid == dirptrs[i].pid && - strequal(dirptrs[i].path,path)) - dptr_close(i); -} - -/**************************************************************************** - start a directory listing -****************************************************************************/ -static BOOL start_dir(int cnum,char *directory) -{ - DEBUG(5,("start_dir cnum=%d dir=%s\n",cnum,directory)); - - if (!check_name(directory,cnum)) - return(False); - - if (! *directory) - directory = "."; - - Connections[cnum].dirptr = OpenDir(cnum, directory, True); - if (Connections[cnum].dirptr) { - dptrs_open++; - string_set(&Connections[cnum].dirpath,directory); - return(True); - } - - return(False); -} - - -/**************************************************************************** -create a new dir ptr -****************************************************************************/ -int dptr_create(int cnum,char *path, BOOL expect_close,int pid) -{ - int i; - uint32 old; - int oldi; - - if (!start_dir(cnum,path)) - return(-2); /* Code to say use a unix error return code. */ - - if (dptrs_open >= MAXDIR) - dptr_idleoldest(); - - for (i=0;i<NUMDIRPTRS;i++) - if (!dirptrs[i].valid) - break; - if (i == NUMDIRPTRS) i = -1; - - - /* as a 2nd option, grab the oldest not marked for expect_close */ - if (i == -1) { - old=dircounter+1; - oldi= -1; - for (i=0;i<NUMDIRPTRS;i++) - if (!dirptrs[i].expect_close && dirptrs[i].lastused < old) { - old = dirptrs[i].lastused; - oldi = i; - } - i = oldi; - } - - /* a 3rd option - grab the oldest one */ - if (i == -1) { - old=dircounter+1; - oldi= -1; - for (i=0;i<NUMDIRPTRS;i++) - if (dirptrs[i].lastused < old) { - old = dirptrs[i].lastused; - oldi = i; - } - i = oldi; - } - - if (i == -1) { - DEBUG(0,("Error - all dirptrs in use??\n")); - return(-1); - } - - if (dirptrs[i].valid) - dptr_close(i); - - dirptrs[i].ptr = Connections[cnum].dirptr; - string_set(&dirptrs[i].path,path); - dirptrs[i].lastused = dircounter++; - dirptrs[i].finished = False; - dirptrs[i].cnum = cnum; - dirptrs[i].pid = pid; - dirptrs[i].expect_close = expect_close; - dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */ - dirptrs[i].attr = 0; /* Only used in lanman2 searches */ - dirptrs[i].valid = True; - - DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n", - i,path,expect_close)); - - return(i); -} - -#define DPTR_MASK ((uint32)(((uint32)1)<<31)) - -/**************************************************************************** -fill the 5 byte server reserved dptr field -****************************************************************************/ -BOOL dptr_fill(char *buf1,unsigned int key) -{ - unsigned char *buf = (unsigned char *)buf1; - void *p = dptr_get(key,0); - uint32 offset; - if (!p) { - DEBUG(1,("filling null dirptr %d\n",key)); - return(False); - } - offset = TellDir(p); - DEBUG(6,("fill on key %d dirptr 0x%x now at %d\n",key,p,offset)); - buf[0] = key; - SIVAL(buf,1,offset | DPTR_MASK); - return(True); -} - - -/**************************************************************************** -return True is the offset is at zero -****************************************************************************/ -BOOL dptr_zero(char *buf) -{ - return((IVAL(buf,1)&~DPTR_MASK) == 0); -} - -/**************************************************************************** -fetch the dir ptr and seek it given the 5 byte server field -****************************************************************************/ -void *dptr_fetch(char *buf,int *num) -{ - unsigned int key = *(unsigned char *)buf; - void *p = dptr_get(key,dircounter++); - uint32 offset; - if (!p) { - DEBUG(3,("fetched null dirptr %d\n",key)); - return(NULL); - } - *num = key; - offset = IVAL(buf,1)&~DPTR_MASK; - SeekDir(p,offset); - DEBUG(3,("fetching dirptr %d for path %s at offset %d\n", - key,dptr_path(key),offset)); - return(p); -} - -/**************************************************************************** -fetch the dir ptr and seek it given the lanman2 parameter block -****************************************************************************/ -void *dptr_fetch_lanman2(char *params,int dptr_num) -{ - void *p = dptr_get(dptr_num,dircounter++); - uint32 resume_key = SVAL(params,6); - BOOL uses_resume_key = BITSETW(params+10,2); - BOOL continue_bit = BITSETW(params+10,3); - - if (!p) { - DEBUG(3,("fetched null dirptr %d\n",dptr_num)); - return(NULL); - } - if(uses_resume_key && !continue_bit) - SeekDir(p,resume_key); - DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num))); - return(p); -} - -/**************************************************************************** -check a filetype for being valid -****************************************************************************/ -BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype) -{ - if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0) - return False; - return True; -} - -/**************************************************************************** - get a directory entry -****************************************************************************/ -BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend) -{ - char *dname; - BOOL found = False; - struct stat sbuf; - pstring path; - pstring pathreal; - BOOL isrootdir; - pstring filename; - BOOL matched; - BOOL needslash; - - *path = *pathreal = *filename = 0; - - isrootdir = (strequal(Connections[cnum].dirpath,"./") || - strequal(Connections[cnum].dirpath,".") || - strequal(Connections[cnum].dirpath,"/")); - - needslash = - ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/'); - - if (!Connections[cnum].dirptr) - return(False); - - while (!found) - { - dname = ReadDirName(Connections[cnum].dirptr); - - DEBUG(6,("readdir on dirptr 0x%x now at offset %d\n", - Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); - - if (dname == NULL) - return(False); - - matched = False; - - pstrcpy(filename,dname); - - if ((strcmp(filename,mask) == 0) || - (name_map_mangle(filename,True,SNUM(cnum)) && - mask_match(filename,mask,False,False))) - { - if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) - continue; - - pstrcpy(fname,filename); - *path = 0; - pstrcpy(path,Connections[cnum].dirpath); - if(needslash) - strcat(path,"/"); - pstrcpy(pathreal,path); - strcat(path,fname); - strcat(pathreal,dname); - if (sys_stat(pathreal,&sbuf) != 0) - { - DEBUG(5,("Couldn't stat 1 [%s]\n",path)); - continue; - } - - if (check_descend && - !strequal(fname,".") && !strequal(fname,"..")) - continue; - - *mode = dos_mode(cnum,pathreal,&sbuf); - - if (!dir_check_ftype(cnum,*mode,&sbuf,dirtype)) { - DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype)); - continue; - } - - *size = sbuf.st_size; - *date = sbuf.st_mtime; - - DEBUG(5,("get_dir_entry found %s fname=%s\n",pathreal,fname)); - - found = True; - } - } - - return(found); -} - - - -typedef struct -{ - int pos; - int numentries; - int mallocsize; - char *data; - char *current; -} Dir; - - -/******************************************************************* -open a directory -********************************************************************/ -void *OpenDir(int cnum, char *name, BOOL use_veto) -{ - Dir *dirp; - char *n; - void *p = sys_opendir(name); - int used=0; - - if (!p) return(NULL); - dirp = (Dir *)malloc(sizeof(Dir)); - if (!dirp) { - closedir(p); - return(NULL); - } - dirp->pos = dirp->numentries = dirp->mallocsize = 0; - dirp->data = dirp->current = NULL; - - while ((n = readdirname(p))) - { - int l = strlen(n)+1; - - /* If it's a vetoed file, pretend it doesn't even exist */ - if (use_veto && IS_VETO_PATH(cnum, n)) continue; - - if (used + l > dirp->mallocsize) { - int s = MAX(used+l,used+2000); - char *r; - r = (char *)Realloc(dirp->data,s); - if (!r) { - DEBUG(0,("Out of memory in OpenDir\n")); - break; - } - dirp->data = r; - dirp->mallocsize = s; - dirp->current = dirp->data; - } - strcpy(dirp->data+used,n); - used += l; - dirp->numentries++; - } - - closedir(p); - return((void *)dirp); -} - - -/******************************************************************* -close a directory -********************************************************************/ -void CloseDir(void *p) -{ - Dir *dirp = (Dir *)p; - if (!dirp) return; - if (dirp->data) free(dirp->data); - free(dirp); -} - -/******************************************************************* -read from a directory -********************************************************************/ -char *ReadDirName(void *p) -{ - char *ret; - Dir *dirp = (Dir *)p; - - if (!dirp || !dirp->current || dirp->pos >= dirp->numentries) return(NULL); - - ret = dirp->current; - dirp->current = skip_string(dirp->current,1); - dirp->pos++; - - return(ret); -} - - -/******************************************************************* -seek a dir -********************************************************************/ -BOOL SeekDir(void *p,int pos) -{ - Dir *dirp = (Dir *)p; - - if (!dirp) return(False); - - if (pos < dirp->pos) { - dirp->current = dirp->data; - dirp->pos = 0; - } - - while (dirp->pos < pos && ReadDirName(p)) ; - - return(dirp->pos == pos); -} - -/******************************************************************* -tell a dir position -********************************************************************/ -int TellDir(void *p) -{ - Dir *dirp = (Dir *)p; - - if (!dirp) return(-1); - - return(dirp->pos); -} - - -static int dir_cache_size = 0; -static struct dir_cache { - struct dir_cache *next; - struct dir_cache *prev; - char *path; - char *name; - char *dname; - int snum; -} *dir_cache = NULL; - -/******************************************************************* -add an entry to the directory cache -********************************************************************/ -void DirCacheAdd(char *path,char *name,char *dname,int snum) -{ - int count; - struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry)); - if (!entry) return; - entry->path = strdup(path); - entry->name = strdup(name); - entry->dname = strdup(dname); - entry->snum = snum; - if (!entry->path || !entry->name || !entry->dname) return; - - entry->next = dir_cache; - entry->prev = NULL; - if (entry->next) entry->next->prev = entry; - dir_cache = entry; - - DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname)); - - if (dir_cache_size == DIRCACHESIZE) { - for (entry=dir_cache, count=1; - entry->next && count < dir_cache_size + 1; - entry=entry->next, count++) ; - if (entry->next || count != dir_cache_size + 1) { - DEBUG(0,("DirCache bug - please report %d %d\n",dir_cache_size,count)); - } - free(entry->path); - free(entry->name); - free(entry->dname); - if (entry->prev) entry->prev->next = entry->next; - free(entry); - } else { - dir_cache_size++; - } -} - - -/******************************************************************* -check for an entry in the directory cache -********************************************************************/ -char *DirCacheCheck(char *path,char *name,int snum) -{ - struct dir_cache *entry; - - for (entry=dir_cache; entry; entry=entry->next) { - if (entry->snum == snum && - strcmp(path,entry->path) == 0 && - strcmp(name,entry->name) == 0) { - DEBUG(4,("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname)); - return(entry->dname); - } - } - - return(NULL); -} - -/******************************************************************* -flush entries in the dir_cache -********************************************************************/ -void DirCacheFlush(int snum) -{ - struct dir_cache *entry,*next; - - for (entry=dir_cache; entry; entry=next) { - if (entry->snum == snum) { - free(entry->path); - free(entry->dname); - free(entry->name); - next = entry->next; - if (entry->prev) entry->prev->next = entry->next; - if (entry->next) entry->next->prev = entry->prev; - if (dir_cache == entry) dir_cache = entry->next; - free(entry); - dir_cache_size--; - } else { - next = entry->next; - } - } -} - - -#ifdef REPLACE_GETWD -/* This is getcwd.c from bash. It is needed in Interactive UNIX. To - * add support for another OS you need to determine which of the - * conditional compilation macros you need to define. All the options - * are defined for Interactive UNIX. - */ -#ifdef ISC -#define HAVE_UNISTD_H -#define USGr3 -#define USG -#endif - -#if defined (HAVE_UNISTD_H) -# include <unistd.h> -#endif - -#if defined (__STDC__) -# define CONST const -# define PTR void * -#else /* !__STDC__ */ -# define CONST -# define PTR char * -#endif /* !__STDC__ */ - -#if !defined (PATH_MAX) -# if defined (MAXPATHLEN) -# define PATH_MAX MAXPATHLEN -# else /* !MAXPATHLEN */ -# define PATH_MAX 1024 -# endif /* !MAXPATHLEN */ -#endif /* !PATH_MAX */ - -#if defined (_POSIX_VERSION) || defined (USGr3) || defined (HAVE_DIRENT_H) -# if !defined (HAVE_DIRENT) -# define HAVE_DIRENT -# endif /* !HAVE_DIRENT */ -#endif /* _POSIX_VERSION || USGr3 || HAVE_DIRENT_H */ - -#if defined (HAVE_DIRENT) -# define D_NAMLEN(d) (strlen ((d)->d_name)) -#else -# define D_NAMLEN(d) ((d)->d_namlen) -#endif /* ! (_POSIX_VERSION || USGr3) */ - -#if defined (USG) || defined (USGr3) -# define d_fileno d_ino -#endif - -#if !defined (alloca) -extern char *alloca (); -#endif /* alloca */ - -/* Get the pathname of the current working directory, - and put it in SIZE bytes of BUF. Returns NULL if the - directory couldn't be determined or SIZE was too small. - If successful, returns BUF. In GNU, if BUF is NULL, - an array is allocated with `malloc'; the array is SIZE - bytes long, unless SIZE <= 0, in which case it is as - big as necessary. */ -#if defined (__STDC__) -char * -getcwd (char *buf, size_t size) -#else /* !__STDC__ */ -char * -getcwd (buf, size) - char *buf; - int size; -#endif /* !__STDC__ */ -{ - static CONST char dots[] - = "../../../../../../../../../../../../../../../../../../../../../../../\ -../../../../../../../../../../../../../../../../../../../../../../../../../../\ -../../../../../../../../../../../../../../../../../../../../../../../../../.."; - CONST char *dotp, *dotlist; - size_t dotsize; - dev_t rootdev, thisdev; - ino_t rootino, thisino; - char path[PATH_MAX + 1]; - register char *pathp; - char *pathbuf; - size_t pathsize; - struct stat st; - - if (buf != NULL && size == 0) - { - errno = EINVAL; - return ((char *)NULL); - } - - pathsize = sizeof (path); - pathp = &path[pathsize]; - *--pathp = '\0'; - pathbuf = path; - - if (stat (".", &st) < 0) - return ((char *)NULL); - thisdev = st.st_dev; - thisino = st.st_ino; - - if (stat ("/", &st) < 0) - return ((char *)NULL); - rootdev = st.st_dev; - rootino = st.st_ino; - - dotsize = sizeof (dots) - 1; - dotp = &dots[sizeof (dots)]; - dotlist = dots; - while (!(thisdev == rootdev && thisino == rootino)) - { - register DIR *dirstream; - register struct dirent *d; - dev_t dotdev; - ino_t dotino; - char mount_point; - int namlen; - - /* Look at the parent directory. */ - if (dotp == dotlist) - { - /* My, what a deep directory tree you have, Grandma. */ - char *new; - if (dotlist == dots) - { - new = malloc (dotsize * 2 + 1); - if (new == NULL) - goto lose; - memcpy (new, dots, dotsize); - } - else - { - new = realloc ((PTR) dotlist, dotsize * 2 + 1); - if (new == NULL) - goto lose; - } - memcpy (&new[dotsize], new, dotsize); - dotp = &new[dotsize]; - dotsize *= 2; - new[dotsize] = '\0'; - dotlist = new; - } - - dotp -= 3; - - /* Figure out if this directory is a mount point. */ - if (stat (dotp, &st) < 0) - goto lose; - dotdev = st.st_dev; - dotino = st.st_ino; - mount_point = dotdev != thisdev; - - /* Search for the last directory. */ - dirstream = opendir(dotp); - if (dirstream == NULL) - goto lose; - while ((d = (struct dirent *)readdir(dirstream)) != NULL) - { - if (d->d_name[0] == '.' && - (d->d_name[1] == '\0' || - (d->d_name[1] == '.' && d->d_name[2] == '\0'))) - continue; - if (mount_point || d->d_fileno == thisino) - { - char *name; - - namlen = D_NAMLEN(d); - name = (char *) - alloca (dotlist + dotsize - dotp + 1 + namlen + 1); - memcpy (name, dotp, dotlist + dotsize - dotp); - name[dotlist + dotsize - dotp] = '/'; - memcpy (&name[dotlist + dotsize - dotp + 1], - d->d_name, namlen + 1); - if (lstat (name, &st) < 0) - { - int save = errno; - closedir(dirstream); - errno = save; - goto lose; - } - if (st.st_dev == thisdev && st.st_ino == thisino) - break; - } - } - if (d == NULL) - { - int save = errno; - closedir(dirstream); - errno = save; - goto lose; - } - else - { - size_t space; - - while ((space = pathp - pathbuf) <= namlen) - { - char *new; - - if (pathbuf == path) - { - new = malloc (pathsize * 2); - if (!new) - goto lose; - } - else - { - new = realloc ((PTR) pathbuf, (pathsize * 2)); - if (!new) - goto lose; - pathp = new + space; - } - (void) memcpy (new + pathsize + space, pathp, pathsize - space); - pathp = new + pathsize + space; - pathbuf = new; - pathsize *= 2; - } - - pathp -= namlen; - (void) memcpy (pathp, d->d_name, namlen); - *--pathp = '/'; - closedir(dirstream); - } - - thisdev = dotdev; - thisino = dotino; - } - - if (pathp == &path[sizeof(path) - 1]) - *--pathp = '/'; - - if (dotlist != dots) - free ((PTR) dotlist); - - { - size_t len = pathbuf + pathsize - pathp; - if (buf == NULL) - { - if (len < (size_t) size) - len = size; - buf = (char *) malloc (len); - if (buf == NULL) - goto lose2; - } - else if ((size_t) size < len) - { - errno = ERANGE; - goto lose2; - } - (void) memcpy((PTR) buf, (PTR) pathp, len); - } - - if (pathbuf != path) - free (pathbuf); - - return (buf); - - lose: - if ((dotlist != dots) && dotlist) - { - int e = errno; - free ((PTR) dotlist); - errno = e; - } - - lose2: - if ((pathbuf != path) && pathbuf) - { - int e = errno; - free ((PTR) pathbuf); - errno = e; - } - return ((char *)NULL); -} -#endif diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c deleted file mode 100644 index 28cdb22889a..00000000000 --- a/source/smbd/ipc.c +++ /dev/null @@ -1,3133 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Inter-process communication and named pipe handling - Copyright (C) Andrew Tridgell 1992-1997 - - SMB Version handling - Copyright (C) John H Terpstra 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. - */ -/* - 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, 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",printjob_encode(snum, queue->job)); /* 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; - - pstrcpy(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; - - /* If someone sets all the bits they don't really mean to set - DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the - known servers. */ - - if (servertype == SV_TYPE_ALL) - servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); - - /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set - any other bit (they may just set this bit on it's own) they - want all the locally seen servers. However this bit can be - set on its own so set the requested servers to be - ALL - DOMAIN_ENUM. */ - - if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) - servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); - - domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); - local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 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,(missed == 0 ? NERR_Success : ERROR_MORE_DATA)); - 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; - - fstrcpy(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, snum; - int i, count; - - printjob_decode(SVAL(p,0), &snum, &jobid); - - /* 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, snum; - int uLevel = SVAL(p,2); - int function = SVAL(p,4); /* what is this ?? */ - int i; - char *s = data; - - printjob_decode(SVAL(p,0), &snum, &jobid); - - *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= lp_default_server_announce(); - - pstrcpy(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; - pstrcpy(comment,servers[i].comment); - } - } - if (servers) free(servers); - - SCVAL(p,0,lp_major_announce_version()); - SCVAL(p,1,lp_minor_announce_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,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ - SCVAL(p,1,lp_minor_announce_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); - fstrcpy(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; - char* logon_script; - - 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 */ - -/* JHT - By calling lp_logon_script() and standard_sub() we have */ -/* made sure all macros are fully substituted and available */ - logon_script = lp_logon_script(); - standard_sub( cnum, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ -/* End of JHT mods */ - - 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 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,SVAL(p,0))); - - /* check it's a supported varient */ - if (strcmp(str1,"WWrLh") != 0) return False; - if (!check_printjob_info(&desc,uLevel,str2)) return False; - - printjob_decode(SVAL(p,0), &snum, &job); - - 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]; - strncpy(buf,SERVICE(snum),sizeof(buf)-1); - buf[sizeof(buf)-1] = 0; - 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 }, -#ifdef NTDOMAIN - { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP }, -#else - { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP }, -#endif - { 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); - - fstrcpy(name,smb_buf(inbuf)); - - if (dscnt > tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters\n"); - } - - 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 (dscnt > tdscnt || pscnt > tpscnt) { - exit_server("invalid trans parameters\n"); - } - - 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 b0a45ffb47c..00000000000 --- a/source/smbd/mangle.c +++ /dev/null @@ -1,673 +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; - if(lp_client_code_page() == KANJI_CODEPAGE) - { - 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++; - } - } - } - - /* 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],'.')) - { - pstrcpy(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! */ - pstrcpy(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++; - if (!*start) - continue; /* Always check for the end. */ - start++; /* Skip the ( */ - 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 == '*') { - pstrcpy(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)); - pstrcpy(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) - { - if(lp_client_code_page() == KANJI_CODEPAGE) - { - 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++; - } - } - extension[extlen] = 0; - } - } - - p = s; - - while (*p && baselen < 5) - { - if(lp_client_code_page() == KANJI_CODEPAGE) - { - 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++; - } - } - 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; - } - - if(lp_client_code_page() == KANJI_CODEPAGE) - { - 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); - } - - 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 64253932abb..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()); - fstrcpy(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()) - { - pstrcpy(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; - - fstrcpy(msgfrom,orig); - fstrcpy(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; - - fstrcpy(msgfrom,orig); - fstrcpy(msgto,dest); - - DEBUG(3,("%s SMBsendstrt (from %s to %s)\n",timestring(),msgfrom,msgto)); - - 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 f4d94791cf3..00000000000 --- a/source/smbd/password.c +++ /dev/null @@ -1,1707 +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]=""; - -/* 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) -{ - unsigned char buf[16]; - static int counter = 0; - struct timeval tval; - int v1,v2; - - /* get a sort-of random number */ - GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - - /* mash it up with md4 */ - mdfour(buf, (unsigned char *)challenge, 8); - - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,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); -} - -/* 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; - -#if 0 - /* - * After observing MS-Exchange services writing to a Samba share - * I belive this code is incorrect. Each service does it's own - * sessionsetup_and_X for the same user, and as each service shuts - * down, it does a user_logoff_and_X. As we are consolidating multiple - * sessionsetup_and_X's onto the same vuid here, when the first service - * shuts down, it invalidates all the open files for the other services. - * Hence I am removing this code and forcing each sessionsetup_and_X - * to get a new vuid. - * Jeremy Allison. (jallison@whistle.com). - */ - - 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 */ - } -#endif - - 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()) { - if((pwfile=getpwnam(vuser->name))!= NULL) - { - 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, - 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 KRB5_AUTH -/******************************************************************* -check on Kerberos authentication -********************************************************************/ -static BOOL krb5_auth(char *this_user,char *password) -{ - krb5_data tgtname = { - 0, - KRB5_TGS_NAME_SIZE, - KRB5_TGS_NAME - }; - krb5_context kcontext; - krb5_principal kprinc; - krb5_principal server; - krb5_creds kcreds; - int options = 0; - krb5_address **addrs = (krb5_address **)0; - krb5_preauthtype *preauth = NULL; - krb5_keytab keytab = NULL; - krb5_timestamp now; - krb5_ccache ccache = NULL; - int retval; - char *name; - - if ( retval=krb5_init_context(&kcontext)) - { - return(False); - } - - if ( retval = krb5_timeofday(kcontext, &now) ) - { - return(False); - } - - if ( retval = krb5_cc_default(kcontext, &ccache) ) - { - return(False); - } - - if ( retval = krb5_parse_name(kcontext, this_user, &kprinc) ) - { - return(False); - } - - memset((char *)&kcreds, 0, sizeof(kcreds)); - - kcreds.client = kprinc; - - if ((retval = krb5_build_principal_ext(kcontext, &server, - krb5_princ_realm(kcontext, kprinc)->length, - krb5_princ_realm(kcontext, kprinc)->data, - tgtname.length, - tgtname.data, - krb5_princ_realm(kcontext, kprinc)->length, - krb5_princ_realm(kcontext, kprinc)->data, - 0))) - { - return(False); - } - - kcreds.server = server; - - retval = krb5_get_in_tkt_with_password(kcontext, - options, - addrs, - NULL, - preauth, - password, - 0, - &kcreds, - 0); - - if ( retval ) - { - return(False); - } - - return(True); -} -#endif /* KRB5_AUTH */ - -#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 KRB5_AUTH - if (krb5_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 -} - -/**************************************************************************** -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); -} - -/**************************************************************************** -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; - char challenge[8]; - struct smb_passwd *smb_pass; - BOOL challenge_done = False; - - if (password) password[pwlen] = 0; - - if (pwlen == 24) - challenge_done = last_challenge(challenge); - -#if DEBUG_PASSWORD - 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 { - 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); - - 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, - (unsigned 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, - (unsigned char *)challenge)) { - update_protected_database(user,True); - return(True); - } - - DEBUG(3,("Error smb_password_check failed\n")); - } - - 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; - } -#elif defined(IA_UINFO) - { - /* Need to get password with SVR4.2's ia_ functions instead of - get{sp,pw}ent functions. Required by UnixWare 2.x, tested on - version 2.1. (tangent@cyberport.com) */ - uinfo_t uinfo; - if (ia_openinfo(pass->pw_name, &uinfo) != -1) - ia_get_logpwd(uinfo, &(pass->pw_passwd)); - } -#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 possibilities: - 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_host : "(null)", - file_user ? file_user : "(null)" )); - 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; -static char *secserver_inbuf = NULL; - -/**************************************************************************** -attempted support for server level security -****************************************************************************/ -BOOL server_cryptkey(char *buf) -{ - pstring 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(secserver_inbuf == NULL) { - secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(secserver_inbuf == NULL) { - DEBUG(0,("server_cryptkey: malloc fail for input buffer.\n")); - return False; - } - } - - 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(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); - 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); - p = outbuf+len; - - /* and my name */ - /* Fix from Frank Varnavas <varnavas@ny.ubs.com>. - We cannot use the same name as the client to - the NT password server, as NT will drop client - connections if the same client name connects - twice. Instead, synthesize a name from our pid. - and the remote machine name. - */ - { - char buf2[32]; /* create name as PIDname */ - sprintf(buf2,"%d", getpid()); - strncpy(&buf2[strlen(buf2)], remote_machine, 31 - strlen(buf2)); - buf2[31] = '\0'; - DEBUG(1,("negprot w/password server as %s\n",buf2)); - name_mangle(buf2,p,' '); - len += name_len(p); - } - - _smb_setlen(outbuf,len); - CVAL(outbuf,0) = 0x81; - - send_smb(password_client,outbuf); - - - if (!receive_smb(password_client,secserver_inbuf,5000) || - CVAL(secserver_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,secserver_inbuf,5000); - - if (!ret || CVAL(secserver_inbuf,smb_rcls) || SVAL(secserver_inbuf,smb_vwv0)) { - DEBUG(1,("%s rejected the protocol\n",pserver)); - close(password_client); password_client= -1; - return(False); - } - - if (!(CVAL(secserver_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,secserver_inbuf,smb_len(secserver_inbuf)+4); - - DEBUG(3,("password server OK\n")); - - return(True); -} - -/**************************************************************************** -attempted support for server level security -****************************************************************************/ -BOOL server_validate(char *buf) -{ - pstring outbuf; - BOOL ret; - - if(secserver_inbuf == NULL) { - secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(secserver_inbuf == NULL) { - DEBUG(0,("server_validate: malloc fail for input buffer.\n")); - return False; - } - } - - if (password_client < 0) { - DEBUG(1,("%s not connected\n",pserver)); - return(False); - } - - bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN); - 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(secserver_inbuf,smb_rcls,1); - - send_smb(password_client,outbuf); - ret = receive_smb(password_client,secserver_inbuf,5000); - - if (!ret || CVAL(secserver_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(secserver_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 6937412e29f..00000000000 --- a/source/smbd/pipes.c +++ /dev/null @@ -1,1196 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Pipe SMB reply routines - Copyright (C) Andrew Tridgell 1992-1997, - Copyright (C) Luke Kenneth Casson Leighton 1996-1997. - Copyright (C) Paul Ashton 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" -#include "nterr.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", -#if NTDOMAIN - "NETLOGON", -#endif - 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; - BOOL bad_path = False; - - /* XXXX we need to handle passed times, sattr and flags */ - pstrcpy(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. */ - pstrcpy(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,&bad_path); - - 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, - 0, &rmode,&smb_action); - - if (!Files[fnum].open) - { - /* Change the error code if bad_path was set. */ - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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); -} - - -#ifdef NTDOMAIN -/* - PAXX: Someone fix above. - The above API is indexing RPC calls based on RPC flags and - fragment length. I've decided to do it based on operation number :-) -*/ - -/* this function is due to be replaced */ -static void initrpcreply(char *inbuf, char *q) -{ - uint32 callid; - - SCVAL(q, 0, 5); q++; /* RPC version 5 */ - SCVAL(q, 0, 0); q++; /* minor version 0 */ - SCVAL(q, 0, 2); q++; /* RPC response packet */ - SCVAL(q, 0, 3); q++; /* first frag + last frag */ - RSIVAL(q, 0, 0x10000000); q += 4; /* packed data representation */ - RSSVAL(q, 0, 0); q += 2; /* fragment length, fill in later */ - SSVAL(q, 0, 0); q += 2; /* authentication length */ - callid = RIVAL(inbuf, 12); - RSIVAL(q, 0, callid); q += 4; /* call identifier - match incoming RPC */ - SIVAL(q, 0, 0x18); q += 4; /* allocation hint (no idea) */ - SSVAL(q, 0, 0); q += 2; /* presentation context identifier */ - SCVAL(q, 0, 0); q++; /* cancel count */ - SCVAL(q, 0, 0); q++; /* reserved */ -} - -/* this function is due to be replaced */ -static void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen) -{ - SSVAL(q, 8, datalen + 4); - SIVAL(q,0x10,datalen+4-0x18); /* allocation hint */ - SIVAL(q, datalen, rtnval); - *rlen = datalen + 4; - { int fd; fd = open("/tmp/rpc", O_RDWR); write(fd, q, datalen + 4); } -} - -/* RID username mapping function. just for fun, it maps to the unix uid */ -static uint32 name_to_rid(char *user_name) -{ - struct passwd *pw = Get_Pwnam(user_name, False); - if (!pw) - { - DEBUG(1,("Username %s is invalid on this system\n", user_name)); - return (uint32)(-1); - } - - return (uint32)(pw->pw_uid); -} - - -/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ -char *dom_sid_to_string(DOM_SID *sid) -{ - static pstring sidstr; - char subauth[16]; - int i; - uint32 ia = (sid->id_auth[0]) + - (sid->id_auth[1] << 8 ) + - (sid->id_auth[2] << 16) + - (sid->id_auth[3] << 24); - - sprintf(sidstr, "S-%d-%d", sid->sid_no, ia); - - for (i = 0; i < sid->num_auths; i++) - { - sprintf(subauth, "-%d", sid->sub_auths[i]); - strcat(sidstr, subauth); - } - - DEBUG(5,("dom_sid_to_string returning %s\n", sidstr)); - return sidstr; -} - -/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */ -/* identauth >= 2^32 can be detected because it will be specified in hex */ -static void make_dom_sid(DOM_SID *sid, char *domsid) -{ - int identauth; - char *p; - - DEBUG(4,("netlogon domain SID: %s\n", domsid)); - - /* assume, but should check, that domsid starts "S-" */ - p = strtok(domsid+2,"-"); - sid->sid_no = atoi(p); - - /* identauth in decimal should be < 2^32 */ - /* identauth in hex should be >= 2^32 */ - identauth = atoi(strtok(0,"-")); - - DEBUG(4,("netlogon rev %d\n", sid->sid_no)); - DEBUG(4,("netlogon %s ia %d\n", p, identauth)); - - sid->id_auth[0] = 0; - sid->id_auth[1] = 0; - sid->id_auth[2] = (identauth & 0xff000000) >> 24; - sid->id_auth[3] = (identauth & 0x00ff0000) >> 16; - sid->id_auth[4] = (identauth & 0x0000ff00) >> 8; - sid->id_auth[5] = (identauth & 0x000000ff); - - sid->num_auths = 0; - - while ((p = strtok(0, "-")) != NULL) - { - sid->sub_auths[sid->num_auths++] = atoi(p); - } -} - -static void create_rpc_reply(RPC_HDR *hdr, uint32 call_id, int data_len) -{ - if (hdr == NULL) return; - - hdr->major = 5; /* RPC version 5 */ - hdr->minor = 0; /* minor version 0 */ - hdr->pkt_type = 2; /* RPC response packet */ - hdr->frag = 3; /* first frag + last frag */ - hdr->pack_type = 1; /* packed data representation */ - hdr->frag_len = data_len; /* fragment length, fill in later */ - hdr->auth_len = 0; /* authentication length */ - hdr->call_id = call_id; /* call identifier - match incoming RPC */ - hdr->alloc_hint = data_len - 0x18; /* allocation hint (no idea) */ - hdr->context_id = 0; /* presentation context identifier */ - hdr->cancel_count = 0; /* cancel count */ - hdr->reserved = 0; /* reserved */ -} - -static void make_rpc_reply(char *inbuf, char *q, int data_len) -{ - uint32 callid = RIVAL(inbuf, 12); - RPC_HDR hdr; - - create_rpc_reply(&hdr, callid, data_len); - smb_io_rpc_hdr(False, &hdr, q, q, 4); -} - -static int lsa_reply_open_policy(char *q, char *base) -{ - char *start = q; - LSA_R_OPEN_POL r_o; - - /* set up the LSA QUERY INFO response */ - bzero(&(r_o.pol.data), POL_HND_SIZE); - r_o.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_open_pol(False, &r_o, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -static void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate) -{ - hdr->uni_max_len = max_len; - hdr->uni_str_len = len; - hdr->undoc = terminate; -} - -static void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate) -{ - make_uni_hdr(&(hdr->unihdr), max_len, len, terminate); - hdr->undoc_buffer = len > 0 ? 1 : 0; -} - -static void make_unistr(UNISTR *str, char *buf) -{ - /* store the string (null-terminated copy) */ - PutUniCode((char *)(str->buffer), buf); -} - -static void make_unistr2(UNISTR2 *str, char *buf, int len, char terminate) -{ - /* set up string lengths. add one if string is not null-terminated */ - str->uni_max_len = len + (terminate != 0 ? 1 : 0); - str->undoc = 0; - str->uni_str_len = len; - - /* store the string (null-terminated copy) */ - PutUniCode((char *)str->buffer, buf); - - /* overwrite the last character: some strings are terminated with 4 not 0 */ - str->buffer[len] = (uint16)terminate; -} - -static void make_dom_rid2(DOM_RID2 *rid2, uint32 rid) -{ - rid2->type = 0x5; - rid2->undoc = 0x5; - rid2->rid = rid; - rid2->rid_idx = 0; -} - -static void make_dom_sid2(DOM_SID2 *sid2, char *sid_str) -{ - int len_sid_str = strlen(sid_str); - - sid2->type = 0x5; - sid2->undoc = 0; - make_uni_hdr2(&(sid2->hdr), len_sid_str, len_sid_str, 0); - make_unistr (&(sid2->str), sid_str); -} - -static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid) -{ - int domlen = strlen(dom_name); - - d_q->uni_dom_max_len = domlen * 2; - d_q->padding = 0; - d_q->uni_dom_str_len = domlen * 2; - - d_q->buffer_dom_name = 0; /* domain buffer pointer */ - d_q->buffer_dom_sid = 0; /* domain sid pointer */ - - /* NOT null-terminated: 4-terminated instead! */ - make_unistr2(&(d_q->uni_domain_name), dom_name, domlen, 4); - - make_dom_sid(&(d_q->dom_sid), dom_sid); -} - -static int lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, char *q, char *base, - char *dom_name, char *dom_sid) -{ - char *start = q; - LSA_R_QUERY_INFO r_q; - - /* set up the LSA QUERY INFO response */ - - r_q.undoc_buffer = 1; /* not null */ - r_q.info_class = q_q->info_class; - - make_dom_query(&r_q.dom.id5, dom_name, dom_sid); - - r_q.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_query(False, &r_q, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -/* pretty much hard-coded choice of "other" sids, unfortunately... */ -static void make_dom_ref(DOM_R_REF *ref, - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int len_dom_name = strlen(dom_name); - int len_other_sid1 = strlen(other_sid1); - int len_other_sid2 = strlen(other_sid2); - int len_other_sid3 = strlen(other_sid3); - - ref->undoc_buffer = 1; - ref->num_ref_doms_1 = 4; - ref->buffer_dom_name = 1; - ref->max_entries = 32; - ref->num_ref_doms_2 = 4; - - make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0); - make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0); - make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0); - make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0); - - if (dom_name != NULL) - { - make_unistr(&(ref->uni_dom_name), dom_name); - } - - make_dom_sid(&(ref->ref_dom[0]), dom_sid ); - make_dom_sid(&(ref->ref_dom[1]), other_sid1); - make_dom_sid(&(ref->ref_dom[2]), other_sid2); - make_dom_sid(&(ref->ref_dom[3]), other_sid3); -} - -static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l, - int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int i; - - make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, - other_sid1, other_sid2, other_sid3); - - r_l->num_entries = num_entries; - r_l->undoc_buffer = 1; - r_l->num_entries2 = num_entries; - - for (i = 0; i < num_entries; i++) - { - make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]); - } - - r_l->num_entries3 = num_entries; -} - -static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, - int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - int i; - - make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid, - other_sid1, other_sid2, other_sid3); - - r_l->num_entries = num_entries; - r_l->undoc_buffer = 1; - r_l->num_entries2 = num_entries; - - for (i = 0; i < num_entries; i++) - { - make_dom_sid2(&(r_l->dom_sid[i]), dom_sids[i]); - } - - r_l->num_entries3 = num_entries; -} - -static int lsa_reply_lookup_sids(char *q, char *base, - int num_entries, fstring dom_sids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - char *start = q; - LSA_R_LOOKUP_SIDS r_l; - - /* set up the LSA Lookup SIDs response */ - make_reply_lookup_sids(&r_l, num_entries, dom_sids, - dom_name, dom_sid, other_sid1, other_sid2, other_sid3); - r_l.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_lookup_sids(False, &r_l, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -static int lsa_reply_lookup_rids(char *q, char *base, - int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS], - char *dom_name, char *dom_sid, - char *other_sid1, char *other_sid2, char *other_sid3) -{ - char *start = q; - LSA_R_LOOKUP_RIDS r_l; - - /* set up the LSA Lookup RIDs response */ - make_reply_lookup_rids(&r_l, num_entries, dom_rids, - dom_name, dom_sid, other_sid1, other_sid2, other_sid3); - r_l.status = 0x0; - - /* store the response in the SMB stream */ - q = lsa_io_r_lookup_rids(False, &r_l, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -static void make_lsa_r_req_chal(LSA_R_REQ_CHAL *r_c, char chal[8], int status) -{ - memcpy(r_c->srv_chal.data, chal, sizeof(r_c->srv_chal.data)); - r_c->status = status; -} - -#if 0 - char chal[8]; - /* PAXX: set these to random values */ - for (int i = 0; i < 8; i+++) - { - chal[i] = 0xA5; - } -#endif - -static int lsa_reply_req_chal(LSA_Q_REQ_CHAL *q_c, char *q, char *base, - char chal[8]) -{ - char *start = q; - LSA_R_REQ_CHAL r_c; - - /* set up the LSA REQUEST CHALLENGE response */ - - make_lsa_r_req_chal(&r_c, chal, 0); - - /* store the response in the SMB stream */ - q = lsa_io_r_req_chal(False, &r_c, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -static void make_lsa_chal(DOM_CHAL *cred, char resp_cred[8]) -{ - memcpy(cred->data, resp_cred, sizeof(cred->data)); -} - -static void make_lsa_r_auth_2(LSA_R_AUTH_2 *r_a, - char resp_cred[8], NEG_FLAGS *flgs, int status) -{ - make_lsa_chal(&(r_a->srv_chal), resp_cred); - memcpy(&(r_a->srv_flgs), flgs, sizeof(r_a->srv_flgs)); - r_a->status = status; -} - -static int lsa_reply_auth_2(LSA_Q_AUTH_2 *q_a, char *q, char *base, - char resp_cred[8], int status) -{ - char *start = q; - LSA_R_AUTH_2 r_a; - - /* set up the LSA AUTH 2 response */ - - make_lsa_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status); - - /* store the response in the SMB stream */ - q = lsa_io_r_auth_2(False, &r_a, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -static void make_lsa_dom_chal(DOM_CRED *cred, char srv_chal[8], UTIME srv_time) -{ - make_lsa_chal(&(cred->challenge), srv_chal); - cred->timestamp = srv_time; -} - - -static void make_lsa_r_srv_pwset(LSA_R_SRV_PWSET *r_a, - char srv_chal[8], UTIME srv_time, int status) -{ - make_lsa_dom_chal(&(r_a->srv_cred), srv_chal, srv_time); - r_a->status = status; -} - -static int lsa_reply_srv_pwset(LSA_Q_SRV_PWSET *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, - int status) -{ - char *start = q; - LSA_R_SRV_PWSET r_s; - - /* set up the LSA Server Password Set response */ - make_lsa_r_srv_pwset(&r_s, srv_cred, srv_time, status); - - /* store the response in the SMB stream */ - q = lsa_io_r_srv_pwset(False, &r_s, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - -static void make_lsa_user_info(LSA_USER_INFO *usr, - - NTTIME *logon_time, - NTTIME *logoff_time, - NTTIME *kickoff_time, - NTTIME *pass_last_set_time, - NTTIME *pass_can_change_time, - NTTIME *pass_must_change_time, - - char *user_name, - char *full_name, - char *logon_script, - char *profile_path, - char *home_dir, - char *dir_drive, - - uint16 logon_count, - uint16 bad_pw_count, - - uint32 user_id, - uint32 group_id, - uint32 num_groups, - DOM_GID *gids, - uint32 user_flgs, - - char sess_key[16], - - char *logon_srv, - char *logon_dom, - - char *dom_sid, - char *other_sids) /* space-delimited set of SIDs */ -{ - /* only cope with one "other" sid, right now. */ - /* need to count the number of space-delimited sids */ - int i; - int num_other_sids = other_sids != NULL ? 1 : 0; - - int len_user_name = strlen(user_name ); - int len_full_name = strlen(full_name ); - int len_logon_script = strlen(logon_script); - int len_profile_path = strlen(profile_path); - int len_home_dir = strlen(home_dir ); - int len_dir_drive = strlen(dir_drive ); - - int len_logon_srv = strlen(logon_srv); - int len_logon_dom = strlen(logon_dom); - - usr->undoc_buffer = 1; /* yes, we're bothering to put USER_INFO data here */ - - usr->logon_time = *logon_time; - usr->logoff_time = *logoff_time; - usr->kickoff_time = *kickoff_time; - usr->pass_last_set_time = *pass_last_set_time; - usr->pass_can_change_time = *pass_can_change_time; - usr->pass_must_change_time = *pass_must_change_time; - - make_uni_hdr(&(usr->hdr_user_name ), len_user_name , len_user_name , 4); - make_uni_hdr(&(usr->hdr_full_name ), len_full_name , len_full_name , 4); - make_uni_hdr(&(usr->hdr_logon_script), len_logon_script, len_logon_script, 4); - make_uni_hdr(&(usr->hdr_profile_path), len_profile_path, len_profile_path, 4); - make_uni_hdr(&(usr->hdr_home_dir ), len_home_dir , len_home_dir , 4); - make_uni_hdr(&(usr->hdr_dir_drive ), len_dir_drive , len_dir_drive , 4); - - usr->logon_count = logon_count; - usr->bad_pw_count = bad_pw_count; - - usr->user_id = user_id; - usr->group_id = group_id; - usr->num_groups = num_groups; - usr->buffer_groups = num_groups ? 1 : 0; /* yes, we're bothering to put group info in */ - usr->user_flgs = user_flgs; - - if (sess_key != NULL) - { - memcpy(usr->sess_key, sess_key, sizeof(usr->sess_key)); - } - else - { - bzero(usr->sess_key, sizeof(usr->sess_key)); - } - - make_uni_hdr(&(usr->hdr_logon_srv), len_logon_srv, len_logon_srv, 4); - make_uni_hdr(&(usr->hdr_logon_dom), len_logon_dom, len_logon_dom, 4); - - usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ - - bzero(usr->padding, sizeof(usr->padding)); - - usr->num_other_sids = num_other_sids; - usr->buffer_other_sids = num_other_sids != 0 ? 1 : 0; - - make_unistr2(&(usr->uni_user_name ), user_name , len_user_name , 0); - make_unistr2(&(usr->uni_full_name ), full_name , len_full_name , 0); - make_unistr2(&(usr->uni_logon_script), logon_script, len_logon_script, 0); - make_unistr2(&(usr->uni_profile_path), profile_path, len_profile_path, 0); - make_unistr2(&(usr->uni_home_dir ), home_dir , len_home_dir , 0); - make_unistr2(&(usr->uni_dir_drive ), dir_drive , len_dir_drive , 0); - - usr->num_groups2 = num_groups; - for (i = 0; i < num_groups; i++) - { - usr->gids[i] = gids[i]; - } - - make_unistr2(&(usr->uni_logon_srv), logon_srv, len_logon_srv, 0); - make_unistr2(&(usr->uni_logon_dom), logon_dom, len_logon_dom, 0); - - make_dom_sid(&(usr->dom_sid), dom_sid); - make_dom_sid(&(usr->other_sids[0]), other_sids); -} - - -static int lsa_reply_sam_logon(LSA_Q_SAM_LOGON *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, - LSA_USER_INFO *user_info) -{ - char *start = q; - LSA_R_SAM_LOGON r_s; - - /* XXXX maybe we want to say 'no', reject the client's credentials */ - r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); - - /* store the user information, if there is any. */ - r_s.user = user_info; - r_s.buffer_user = user_info != NULL ? 1 : 0; - r_s.status = user_info != NULL ? 0 : (0xC000000|NT_STATUS_NO_SUCH_USER); - - /* store the response in the SMB stream */ - q = lsa_io_r_sam_logon(False, &r_s, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - - -static int lsa_reply_sam_logoff(LSA_Q_SAM_LOGOFF *q_s, char *q, char *base, - char srv_cred[8], UTIME srv_time, - uint32 status) -{ - char *start = q; - LSA_R_SAM_LOGOFF r_s; - - /* XXXX maybe we want to say 'no', reject the client's credentials */ - r_s.buffer_creds = 1; /* yes, we have valid server credentials */ - make_lsa_dom_chal(&(r_s.srv_creds), srv_cred, srv_time); - - r_s.status = status; - - /* store the response in the SMB stream */ - q = lsa_io_r_sam_logoff(False, &r_s, q, base, 4); - - /* return length of SMB data stored */ - return q - start; -} - - -static void api_lsa_open_policy( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int reply_len; - - /* we might actually want to decode the query, but it's not necessary */ - /* lsa_io_q_open_policy(...); */ - - /* return a 20 byte policy handle */ - reply_len = lsa_reply_open_policy(*rdata + 0x18, *rdata + 0x18); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; -} - -static void api_lsa_query_info( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int reply_len; - - LSA_Q_QUERY_INFO q_i; - pstring dom_name; - pstring dom_sid; - - /* grab the info class and policy handle */ - lsa_io_q_query(True, &q_i, data + 0x18, data + 0x18, 4); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_query_info(&q_i, *rdata + 0x18, *rdata + 0x18, - dom_name, dom_sid); - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; -} - -static void api_lsa_lookup_sids( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int reply_len; - - int i; - LSA_Q_LOOKUP_SIDS q_l; - pstring dom_name; - pstring dom_sid; - fstring dom_sids[MAX_LOOKUP_SIDS]; - - /* grab the info class and policy handle */ - lsa_io_q_lookup_sids(True, &q_l, data + 0x18, data + 0x18, 4); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* convert received SIDs to strings, so we can do them. */ - for (i = 0; i < q_l.num_entries; i++) - { - fstrcpy(dom_sids[i], dom_sid_to_string(&(q_l.dom_sids[i]))); - } - - /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_sids(*rdata + 0x18, *rdata + 0x18, - q_l.num_entries, dom_sids, /* text-converted SIDs */ - dom_name, dom_sid, /* domain name, domain SID */ - "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; -} - -static void api_lsa_lookup_names( char *param, char *data, - char **rdata, int *rdata_len ) -{ - int reply_len; - - int i; - LSA_Q_LOOKUP_RIDS q_l; - pstring dom_name; - pstring dom_sid; - uint32 dom_rids[MAX_LOOKUP_SIDS]; - - /* grab the info class and policy handle */ - lsa_io_q_lookup_rids(True, &q_l, data + 0x18, data + 0x18, 4); - - pstrcpy(dom_name, lp_workgroup()); - pstrcpy(dom_sid , lp_domainsid()); - - /* convert received RIDs to strings, so we can do them. */ - for (i = 0; i < q_l.num_entries; i++) - { - char *user_name = unistr2(q_l.lookup_name[i].str.buffer); - dom_rids[i] = name_to_rid(user_name); - } - - /* construct reply. return status is always 0x0 */ - reply_len = lsa_reply_lookup_rids(*rdata + 0x18, *rdata + 0x18, - q_l.num_entries, dom_rids, /* text-converted SIDs */ - dom_name, dom_sid, /* domain name, domain SID */ - "S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */ - - /* construct header, now that we know the reply length */ - make_rpc_reply(data, *rdata, reply_len); - *rdata_len = reply_len + 0x18; -} - -BOOL api_ntlsarpcTNP(int cnum,int uid, char *param,char *data, - int mdrcnt,int mprcnt, - char **rdata,char **rparam, - int *rdata_len,int *rparam_len) -{ - uint16 opnum = SVAL(data,22); - - int pkttype = CVAL(data, 2); - if (pkttype == 0x0b) /* RPC BIND */ - { - DEBUG(4,("netlogon rpc bind %x\n",pkttype)); - LsarpcTNP1(data,rdata,rdata_len); - return True; - } - - DEBUG(4,("ntlsa TransactNamedPipe op %x\n",opnum)); - switch (opnum) - { - case LSA_OPENPOLICY: - { - DEBUG(3,("LSA_OPENPOLICY\n")); - api_lsa_open_policy(param, data, rdata, rdata_len); - break; - } - - case LSA_QUERYINFOPOLICY: - { - DEBUG(3,("LSA_QUERYINFOPOLICY\n")); - - api_lsa_query_info(param, data, rdata, rdata_len); - break; - } - - case LSA_ENUMTRUSTDOM: - { - char *q = *rdata + 0x18; - - DEBUG(3,("LSA_ENUMTRUSTDOM\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); /* enumeration context */ - SIVAL(q, 0, 4); /* entries read */ - SIVAL(q, 0, 8); /* trust information */ - - endrpcreply(data, *rdata, q-*rdata, 0x8000001a, rdata_len); - - break; - } - - case LSA_CLOSE: - { - char *q = *rdata + 0x18; - - DEBUG(3,("LSA_CLOSE\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); - - endrpcreply(data, *rdata, q-*rdata, 0, rdata_len); - - break; - } - - case LSA_OPENSECRET: - { - char *q = *rdata + 0x18; - DEBUG(3,("LSA_OPENSECRET\n")); - - initrpcreply(data, *rdata); - - SIVAL(q, 0, 0); - SIVAL(q, 0, 4); - SIVAL(q, 0, 8); - SIVAL(q, 0, 12); - SIVAL(q, 0, 16); - - endrpcreply(data, *rdata, q-*rdata, 0xc000034, rdata_len); - - break; - } - - case LSA_LOOKUPSIDS: - { - DEBUG(3,("LSA_OPENSECRET\n")); - api_lsa_lookup_sids(param, data, rdata, rdata_len); - break; - } - - case LSA_LOOKUPNAMES: - { - DEBUG(3,("LSA_LOOKUPNAMES\n")); - api_lsa_lookup_names(param, data, rdata, rdata_len); - break; - } - - default: - { - DEBUG(4, ("NTLSARPC, unknown code: %lx\n", opnum)); - break; - } - } - return True; -} - -#endif /* NTDOMAIN */ diff --git a/source/smbd/predict.c b/source/smbd/predict.c deleted file mode 100644 index 7d6b2498f5a..00000000000 --- a/source/smbd/predict.c +++ /dev/null @@ -1,158 +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 { - struct stat rp_stat; - - /* Find the end of the file - ensure we don't - read predict beyond it. */ - if(fstat(fd,&rp_stat) < 0) - { - DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); - predict_skip = True; - } - else - { - predict_skip = False; - - /* prepare the next prediction */ - rp_predict_fd = fd; - /* Make sure we don't seek beyond the end of the file. */ - rp_predict_offset = MIN((offset + num),rp_stat.st_size); - 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 8810bcd909d..00000000000 --- a/source/smbd/quotas.c +++ /dev/null @@ -1,657 +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; - 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); -} - - -#elif defined(OSF1) -#include <ufs/quota.h> - -/**************************************************************************** -try to get the disk space from disk quotas - OFS1 version -****************************************************************************/ -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t user_id, euser_id; - int r, save_errno; - struct dqblk D; - struct stat S; - - euser_id = geteuid(); - user_id = getuid(); - - setreuid(euser_id, -1); - r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D); - if (r) - save_errno = errno; - - if (setreuid(user_id, -1) == -1) - DEBUG(5,("Unable to reset uid to %d\n", user_id)); - - *bsize = DEV_BSIZE; - - if (r) - { - if (save_errno == EDQUOT) // disk quota exceeded - { - *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==0) - return(False); - - if ((D.dqb_curblocks>D.dqb_bsoftlimit)) { - *dfree = 0; - *dsize = D.dqb_curblocks; - } else { - *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; - *dsize = D.dqb_bsoftlimit; - } - return (True); -} - -#elif defined (SGI6) -/**************************************************************************** -try to get the disk space from disk quotas (IRIX 6.2 version) -****************************************************************************/ - -#include <sys/quota.h> -#include <mntent.h> - -BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) -{ - uid_t euser_id; - int r; - struct dqblk D; - struct fs_disk_quota F; - 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); - - /* Use softlimit to determine disk space, except when it has been exceeded */ - - *bsize = 512; - - if ( 0 == strcmp ( mnt->mnt_type, "efs" )) - { - r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D); - - if (r==-1) - 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_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) || - (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit) - ) - { - *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; - } - - } - else if ( 0 == strcmp ( mnt->mnt_type, "xfs" )) - { - r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F); - - if (r==-1) - return(False); - - /* Use softlimit to determine disk space, except when it has been exceeded */ - if ( - (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) || - (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) || - (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) || - (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit) - ) - { - /* - * Fixme!: these are __uint64_t, this may truncate values - */ - *dfree = 0; - *dsize = (int) F.d_bcount; - } - else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) - { - return(False); - } - else - { - *dfree = (int)(F.d_blk_softlimit - F.d_bcount); - *dsize = (int)F.d_blk_softlimit; - } - - } - else - return(False); - - return (True); - -} - -#else - -#ifdef __FreeBSD__ -#include <ufs/ufs/quota.h> -#include <machine/param.h> -#elif AIX -/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */ -#include <jfs/quota.h> -/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */ -#define dqb_curfiles dqb_curinodes -#define dqb_fhardlimit dqb_ihardlimit -#define dqb_fsoftlimit dqb_isoftlimit -#else /* !__FreeBSD__ && !AIX */ -#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 euser_id; - int r; - struct dqblk D; -#if !defined(__FreeBSD__) && !defined(AIX) - char dev_disk[256]; - struct stat S; - /* 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 - { - uid_t user_id; - - /* 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 /* USE_SETRES */ -#if defined(__FreeBSD__) - { - /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ - uid_t user_id; - gid_t egrp_id; - - /* Need to be root to get quotas in FreeBSD */ - user_id = getuid(); - egrp_id = getegid(); - setuid(0); - seteuid(0); - r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); - - /* As FreeBSD has group quotas, if getting the user - quota fails, try getting the group instead. */ - if (r) - r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); - setuid(user_id); - seteuid(euser_id); - } -#elif defined(AIX) - /* AIX has both USER and GROUP quotas: - Get the USER quota (ohnielse@fysik.dtu.dk) */ - r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); -#else /* !__FreeBSD__ && !AIX */ - r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); -#endif /* !__FreeBSD__ && !AIX */ -#endif /* USE_SETRES */ - - /* Use softlimit to determine disk space, except when it has been exceeded */ -#if defined(__FreeBSD__) - *bsize = DEV_BSIZE; -#else /* !__FreeBSD__ */ - *bsize = 1024; -#endif /*!__FreeBSD__ */ - - 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) && (D.dqb_fsoftlimit != 0)) -#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 baccb762911..00000000000 --- a/source/smbd/reply.c +++ /dev/null @@ -1,3821 +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; -extern int global_oplock_break; - -/* 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)) - - -/**************************************************************************** -report a possible attack via the password buffer overflow bug -****************************************************************************/ -static void overflow_attack(int len) -{ - DEBUG(0,("ERROR: Invalid password length %d\n", len)); - DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n")); - DEBUG(0,("Attack was from IP=%s\n", client_addr())); - exit_server("possible attack"); -} - - -/**************************************************************************** - 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 || name_len(inbuf+4 + 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)); - - fstrcpy(remote_machine,name2); - trim_string(remote_machine," "," "); - p = strchr(remote_machine,' '); - strlower(remote_machine); - if (p) *p = 0; - - fstrcpy(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 0x89: /* session keepalive request - (some old clients produce this?) */ - CVAL(outbuf,0) = 0x85; - CVAL(outbuf,3) = 0; - break; - - case 0x82: /* positive session response */ - case 0x83: /* negative session response */ - case 0x84: /* retarget session response */ - DEBUG(0,("Unexpected session response\n")); - 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) - fstrcpy(service,p); - else - fstrcpy(service,p2+1); - - p += strlen(p) + 2; - - fstrcpy(password,p); - *pwlen = strlen(password); - - p += strlen(p) + 2; - - fstrcpy(dev,p); - - *user = 0; - p = strchr(service,'%'); - if (p != NULL) - { - *p = 0; - fstrcpy(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); - - if (passlen > MAX_PASS_LEN) { - overflow_attack(passlen); - } - - { - 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); - } - - fstrcpy(service,path+2); - p = strchr(service,'\\'); - if (!p) - return(ERROR(ERRSRV,ERRinvnetname)); - *p = 0; - fstrcpy(service,p+1); - p = strchr(service,'%'); - if (p) - { - *p++ = 0; - fstrcpy(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)); - - if (Protocol < PROTOCOL_NT1) - { - set_message(outbuf,2,strlen(devicename)+1,True); - strcpy(smb_buf(outbuf),devicename); - } - else - { - char *fsname = "SAMBA"; - char *p; - - set_message(outbuf,3,3,True); - - p = smb_buf(outbuf); - strcpy(p,devicename); p = skip_string(p,1); /* device name */ - strcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */ - - set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False); - - SSVAL(outbuf, smb_vwv2, 0x0); /* optional support */ - } - - 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); - - 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); - if (smb_apasslen > MAX_PASS_LEN) - { - overflow_attack(smb_apasslen); - } - - memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen); - pstrcpy(user,smb_buf(inbuf)+smb_apasslen); - - if (lp_security() != SEC_SERVER && !doencrypt) { - smb_apasslen = strlen(smb_apasswd); - } - } else { - uint16 passlen1 = SVAL(inbuf,smb_vwv7); - uint16 passlen2 = SVAL(inbuf,smb_vwv8); - uint32 client_caps = IVAL(inbuf,smb_vwv11); - enum remote_arch_types ra_type = get_remote_arch(); - - char *p = smb_buf(inbuf); - - /* client_caps is used as final determination if client is NT or Win95. - This is needed to return the correct error codes in some - circumstances. - */ - - if(ra_type == RA_WINNT || ra_type == RA_WIN95) - { - if(client_caps & (CAP_NT_SMBS | CAP_STATUS32)) - set_remote_arch( RA_WINNT); - else - set_remote_arch( RA_WIN95); - } - - if (passlen1 != 24 && passlen2 != 24) - doencrypt = False; - - if (passlen1 > MAX_PASS_LEN) { - overflow_attack(passlen1); - } - - passlen1 = MIN(passlen1, MAX_PASS_LEN); - passlen2 = MIN(passlen2, MAX_PASS_LEN); - - 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; - fstrcpy(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 no username is sent use the guest account */ - if (!*user) - { - strcpy(user,lp_guestaccount(-1)); - /* If no user and no password then set guest flag. */ - if( *smb_apasswd == 0) - guest = True; - } - - strlower(user); - - strcpy(sesssetup_user,user); - - reload_services(True); - - add_session_user(user); - - /* Check if the given username was the guest user with no password. - We need to do this check after add_session_user() as that - call can potentially change the username (via map_user). - */ - - if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0)) - guest = True; - - if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) && - !check_hosts_equiv(user)) - { - - /* 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) - { - 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 && !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(6,("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; - BOOL bad_path = False; - - cnum = SVAL(inbuf,smb_tid); - - pstrcpy(name,smb_buf(inbuf) + 1); - unix_convert(name,cnum,0,&bad_path); - - mode = SVAL(inbuf,smb_vwv0); - - if (check_name(name,cnum)) - ok = directory_exist(name,NULL); - - if (!ok) - { - /* We special case this - as when a Windows machine - is parsing a path is steps through the components - one at a time - if a component fails it expects - ERRbadpath, not ERRbadfile. - */ - if(errno == ENOENT) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - -#if 0 - /* Ugly - NT specific hack - maybe not needed ? (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } -#endif - - return(UNIXERROR(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; - BOOL bad_path = False; - - cnum = SVAL(inbuf,smb_tid); - - pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0,&bad_path); - - /* 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) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - - 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; - BOOL bad_path = False; - - cnum = SVAL(inbuf,smb_tid); - - pstrcpy(fname,smb_buf(inbuf) + 1); - unix_convert(fname,cnum,0,&bad_path); - - 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) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - - 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; - BOOL bad_path = False; - - *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; - - pstrcpy(directory,smb_buf(inbuf)+1); - pstrcpy(dir2,smb_buf(inbuf)+1); - unix_convert(directory,cnum,0,&bad_path); - 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; - pstrcpy(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; - fstrcpy(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; - fstrcpy(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) - { - if(dptr_num == -2) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return (UNIXERROR(ERRDOS,ERRnofids)); - } - 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; - BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - - cnum = SVAL(inbuf,smb_tid); - - share_mode = SVAL(inbuf,smb_vwv0); - - pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - unixmode = unix_mode(cnum,aARCH); - - open_file_shared(fnum,cnum,fname,share_mode,3,unixmode, - oplock_request,&rmode,NULL); - - fsp = &Files[fnum]; - - if (!fsp->open) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (fstat(fsp->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 (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - if(fsp->granted_oplock) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - 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 smb_mode = SVAL(inbuf,smb_vwv3); - int smb_attr = SVAL(inbuf,smb_vwv5); - BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); -#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; - BOOL bad_path = False; - files_struct *fsp; - - /* 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 */ - - pstrcpy(fname,smb_buf(inbuf)); - unix_convert(fname,cnum,0,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - unixmode = unix_mode(cnum,smb_attr | aARCH); - - open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - oplock_request, &rmode,&smb_action); - - fsp = &Files[fnum]; - - if (!fsp->open) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - if (fstat(fsp->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 |= EXTENDED_OPLOCK_GRANTED; - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - if(fsp->granted_oplock) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - 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; - BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - - com = SVAL(inbuf,smb_com); - cnum = SVAL(inbuf,smb_tid); - - createmode = SVAL(inbuf,smb_vwv0); - pstrcpy(fname,smb_buf(inbuf)+1); - unix_convert(fname,cnum,0,&bad_path); - - 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)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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, - oplock_request, NULL, NULL); - - fsp = &Files[fnum]; - - if (!fsp->open) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - outsize = set_message(outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fnum); - - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - if(fsp->granted_oplock) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - - 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; - BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); - - cnum = SVAL(inbuf,smb_tid); - createmode = SVAL(inbuf,smb_vwv0); - pstrcpy(fname,smb_buf(inbuf)+1); - strcat(fname,"/TMXXXXXX"); - unix_convert(fname,cnum,0,&bad_path); - - unixmode = unix_mode(cnum,createmode); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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, - oplock_request, NULL, NULL); - - fsp = &Files[fnum]; - - if (!fsp->open) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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 (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - if(fsp->granted_oplock) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - - 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; - BOOL bad_path = False; - - *directory = *mask = 0; - - cnum = SVAL(inbuf,smb_tid); - dirtype = SVAL(inbuf,smb_vwv0); - - pstrcpy(name,smb_buf(inbuf) + 1); - - DEBUG(3,("reply_unlink : %s\n",name)); - - unix_convert(name,cnum,0,&bad_path); - - 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(cnum, directory, True); - - /* 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; - pstrcpy(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 - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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; - uint32 startpos; - char *header = outbuf; - int ret=0; - int fd; - char *fname; - - /* - * Special check if an oplock break has been issued - * and the readraw request croses on the wire, we must - * return a zero length response here. - */ - - if(global_oplock_break) - { - _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); - DEBUG(5,("readbraw - oplock break finished\n")); - return -1; - } - - 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,(int)(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; - uint32 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; - pstrcpy(s,smb_buf(inbuf)+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), - 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,printjob_encode(SNUM(cnum), 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; - BOOL bad_path = False; - - pstrcpy(directory,smb_buf(inbuf) + 1); - cnum = SVAL(inbuf,smb_tid); - unix_convert(directory,cnum,0,&bad_path); - - if (check_name(directory,cnum)) - ret = sys_mkdir(directory,unix_mode(cnum,aDIR)); - - if (ret < 0) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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); -} - -/**************************************************************************** -Static function used by reply_rmdir to delete an entire directory -tree recursively. -****************************************************************************/ -static BOOL recursive_rmdir(char *directory) -{ - char *dname = NULL; - BOOL ret = False; - void *dirptr = OpenDir(-1, directory, False); - - if(dirptr == NULL) - return True; - - while((dname = ReadDirName(dirptr))) - { - pstring fullname; - struct stat st; - - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) - { - errno = ENOMEM; - ret = True; - break; - } - strcpy(fullname, directory); - strcat(fullname, "/"); - strcat(fullname, dname); - - if(sys_lstat(fullname, &st) != 0) - { - ret = True; - break; - } - - if(st.st_mode & S_IFDIR) - { - if(recursive_rmdir(fullname)!=0) - { - ret = True; - break; - } - if(sys_rmdir(fullname) != 0) - { - ret = True; - break; - } - } - else if(sys_unlink(fullname) != 0) - { - ret = True; - break; - } - } - CloseDir(dirptr); - return ret; -} - -/**************************************************************************** - reply to a rmdir -****************************************************************************/ -int reply_rmdir(char *inbuf,char *outbuf) -{ - pstring directory; - int cnum; - int outsize = 0; - BOOL ok = False; - BOOL bad_path = False; - - cnum = SVAL(inbuf,smb_tid); - pstrcpy(directory,smb_buf(inbuf) + 1); - unix_convert(directory,cnum,0,&bad_path); - - if (check_name(directory,cnum)) - { - - dptr_closepath(directory,SVAL(inbuf,smb_pid)); - ok = (sys_rmdir(directory) == 0); - if(!ok && (errno == ENOTEMPTY) && lp_veto_files(SNUM(cnum))) - { - /* Check to see if the only thing in this directory are - vetoed files/directories. If so then delete them and - retry. If we fail to delete any of them (and we *don't* - do a recursive delete) then fail the rmdir. */ - BOOL all_veto_files = True; - char *dname; - void *dirptr = OpenDir(cnum, directory, False); - - if(dirptr != NULL) - { - int dirpos = TellDir(dirptr); - while ((dname = ReadDirName(dirptr))) - { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - if(!IS_VETO_PATH(cnum, dname)) - { - all_veto_files = False; - break; - } - } - if(all_veto_files) - { - SeekDir(dirptr,dirpos); - while ((dname = ReadDirName(dirptr))) - { - pstring fullname; - struct stat st; - - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) - { - errno = ENOMEM; - break; - } - pstrcpy(fullname, directory); - strcat(fullname, "/"); - strcat(fullname, dname); - - if(sys_lstat(fullname, &st) != 0) - break; - if(st.st_mode & S_IFDIR) - { - if(lp_recursive_veto_delete(SNUM(cnum))) - { - if(recursive_rmdir(fullname) != 0) - break; - } - if(sys_rmdir(fullname) != 0) - break; - } - else if(sys_unlink(fullname) != 0) - break; - } - CloseDir(dirptr); - /* Retry the rmdir */ - ok = (sys_rmdir(directory) == 0); - } - else - CloseDir(dirptr); - } - else - errno = ENOTEMPTY; - } - - if (!ok) - DEBUG(3,("couldn't remove directory %s : %s\n", - directory,strerror(errno))); - } - - if (!ok) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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); - - fstrcpy(root1,name1); - fstrcpy(root2,name2); - p = strrchr(root1,'.'); - if (p) { - *p = 0; - fstrcpy(ext1,p+1); - } else { - fstrcpy(ext1,""); - } - p = strrchr(root2,'.'); - if (p) { - *p = 0; - fstrcpy(ext2,p+1); - } else { - fstrcpy(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; - BOOL bad_path1 = False; - BOOL bad_path2 = False; - - *directory = *mask = 0; - - cnum = SVAL(inbuf,smb_tid); - - pstrcpy(name,smb_buf(inbuf) + 1); - pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name)); - - DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); - - unix_convert(name,cnum,0,&bad_path1); - unix_convert(newname,cnum,newname_last_component,&bad_path2); - - /* - * 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(cnum, directory, True); - - if (dirptr) - { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - strcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - pstrcpy(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; - pstrcpy(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 - { - if((errno == ENOENT) && (bad_path1 || bad_path2)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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; - - pstrcpy(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,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,0,&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; - BOOL bad_path1 = False; - BOOL bad_path2 = False; - - *directory = *mask = 0; - - cnum = SVAL(inbuf,smb_tid); - - pstrcpy(name,smb_buf(inbuf)); - pstrcpy(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,&bad_path1); - unix_convert(newname,cnum,0,&bad_path2); - - 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(cnum, directory, True); - - if (dirptr) - { - error = ERRbadfile; - - if (strequal(mask,"????????.???")) - strcpy(mask,"*"); - - while ((dname = ReadDirName(dirptr))) - { - pstring fname; - pstrcpy(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 - { - if((errno == ENOENT) && (bad_path1 || bad_path2)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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)); - - pstrcpy(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); - unsigned char locktype = CVAL(inbuf,smb_vwv3); -#if 0 - unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); -#endif - 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); - - /* Check if this is an oplock break on a file - we have granted an oplock on. - */ - if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) && - (num_ulocks == 0) && (num_locks == 0) && - (CVAL(inbuf,smb_vwv0) == 0xFF)) - { - share_lock_token token; - files_struct *fsp = &Files[fnum]; - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; - - DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", - fnum)); - /* - * Make sure we have granted an oplock on this file. - */ - if(!fsp->granted_oplock) - { - DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -no oplock granted on this file.\n", fnum)); - return ERROR(ERRDOS,ERRlock); - } - - /* Remove the oplock flag from the sharemode. */ - lock_share_entry(fsp->cnum, dev, inode, &token); - if(remove_share_oplock( fnum, token)==False) - { - DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %x\n", fnum, dev, inode)); - unlock_share_entry(fsp->cnum, dev, inode, token); - return -1; - } - unlock_share_entry(fsp->cnum, dev, inode, token); - - /* Clear the granted flag and return. */ - - fsp->granted_oplock = False; - return -1; - } - - /* 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,(unsigned int)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; - uint32 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 = ((long)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; - uint32 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); - - /* - * Patch from Ray Frush <frush@engr.colostate.edu> - * Sometimes times are sent as zero - ignore them. - */ - - if ((unix_times.actime == 0) && (unix_times.modtime == 0)) - { - /* Ignore request */ - DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d ignoring zero request - \ -not setting timestamps of 0\n", - timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); - return(outsize); - } - else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) - { - /* set modify time = to access time if modify time was 0 */ - unix_times.modtime = unix_times.actime; - } - - /* 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 actime=%d modtime=%d\n", - timestring(), fnum,cnum,unix_times.actime,unix_times.modtime)); - - 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/server.c b/source/smbd/server.c deleted file mode 100644 index d387b7375bb..00000000000 --- a/source/smbd/server.c +++ /dev/null @@ -1,5024 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Main SMB server 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" -#include "trans2.h" - -pstring servicesf = CONFIGFILE; -extern pstring debugf; -extern pstring sesssetup_user; -extern fstring myworkgroup; - -char *InBuffer = NULL; -char *OutBuffer = NULL; -char *last_inbuf = NULL; - -int am_parent = 1; -int atexit_set = 0; - -/* the last message the was processed */ -int last_message = -1; - -/* a useful macro to debug the last message processed */ -#define LAST_MESSAGE() smb_fn_name(last_message) - -extern pstring scope; -extern int DEBUGLEVEL; -extern int case_default; -extern BOOL case_sensitive; -extern BOOL case_preserve; -extern BOOL use_mangled_map; -extern BOOL short_case_preserve; -extern BOOL case_mangle; -extern time_t smb_last_time; - -extern int smb_read_error; - -extern pstring user_socket_options; - -connection_struct Connections[MAX_CONNECTIONS]; -files_struct Files[MAX_OPEN_FILES]; - -/* - * Indirection for file fd's. Needed as POSIX locking - * is based on file/process, not fd/process. - */ -file_fd_struct FileFd[MAX_OPEN_FILES]; -int max_file_fd_used = 0; - -extern int Protocol; - -/* - * Size of data we can send to client. Set - * by the client for all protocols above CORE. - * Set by us for CORE protocol. - */ -int max_send = BUFFER_SIZE; -/* - * Size of the data we can receive. Set by us. - * Can be modified by the max xmit parameter. - */ -int max_recv = BUFFER_SIZE; - -/* a fnum to use when chaining */ -int chain_fnum = -1; - -/* number of open connections */ -static int num_connections_open = 0; - -/* Oplock ipc UDP socket. */ -int oplock_sock = -1; -uint16 oplock_port = 0; -/* Current number of oplocks we have outstanding. */ -int32 global_oplocks_open = 0; - -BOOL global_oplock_break = False; - -extern fstring remote_machine; - -pstring OriginalDir; - -/* these can be set by some functions to override the error codes */ -int unix_ERR_class=SUCCESS; -int unix_ERR_code=0; - - -extern int extra_time_offset; - -extern pstring myhostname; - -static int find_free_connection(int hash); - -/* for readability... */ -#define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0) -#define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0) -#define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0) -#define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0) -#define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0) - -/**************************************************************************** - when exiting, take the whole family -****************************************************************************/ -void *dflt_sig(void) -{ - exit_server("caught signal"); - return 0; /* Keep -Wall happy :-) */ -} -/**************************************************************************** - Send a SIGTERM to our process group. -*****************************************************************************/ -void killkids(void) -{ - if(am_parent) kill(0,SIGTERM); -} - -/**************************************************************************** - change a dos mode to a unix mode - base permission for files: - everybody gets read bit set - dos readonly is represented in unix by removing everyone's write bit - dos archive is represented in unix by the user's execute bit - dos system is represented in unix by the group's execute bit - dos hidden is represented in unix by the other's execute bit - Then apply create mask, - then add force bits. - base permission for directories: - dos directory is represented in unix by unix's dir bit and the exec bit - Then apply create mask, - then add force bits. -****************************************************************************/ -mode_t unix_mode(int cnum,int dosmode) -{ - mode_t result = (S_IRUSR | S_IRGRP | S_IROTH); - - if ( !IS_DOS_READONLY(dosmode) ) - result |= (S_IWUSR | S_IWGRP | S_IWOTH); - - if (IS_DOS_DIR(dosmode)) { - /* We never make directories read only for the owner as under DOS a user - can always create a file in a read-only directory. */ - result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR); - /* Apply directory mask */ - result &= lp_dir_mode(SNUM(cnum)); - /* Add in force bits */ - result |= lp_force_dir_mode(SNUM(cnum)); - } else { - if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode)) - result |= S_IXUSR; - - if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode)) - result |= S_IXGRP; - - if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode)) - result |= S_IXOTH; - - /* Apply mode mask */ - result &= lp_create_mode(SNUM(cnum)); - /* Add in force bits */ - result |= lp_force_create_mode(SNUM(cnum)); - } - return(result); -} - - -/**************************************************************************** - change a unix mode to a dos mode -****************************************************************************/ -int dos_mode(int cnum,char *path,struct stat *sbuf) -{ - int result = 0; - extern struct current_user current_user; - - DEBUG(8,("dos_mode: %d %s\n", cnum, path)); - - if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { - if (!((sbuf->st_mode & S_IWOTH) || - Connections[cnum].admin_user || - ((sbuf->st_mode & S_IWUSR) && current_user.uid==sbuf->st_uid) || - ((sbuf->st_mode & S_IWGRP) && - in_group(sbuf->st_gid,current_user.gid, - current_user.ngroups,current_user.igroups)))) - result |= aRONLY; - } else { - if ((sbuf->st_mode & S_IWUSR) == 0) - result |= aRONLY; - } - - if (MAP_ARCHIVE(cnum) && ((sbuf->st_mode & S_IXUSR) != 0)) - result |= aARCH; - - if (MAP_SYSTEM(cnum) && ((sbuf->st_mode & S_IXGRP) != 0)) - result |= aSYSTEM; - - if (MAP_HIDDEN(cnum) && ((sbuf->st_mode & S_IXOTH) != 0)) - result |= aHIDDEN; - - if (S_ISDIR(sbuf->st_mode)) - result = aDIR | (result & aRONLY); - -#ifdef S_ISLNK -#if LINKS_READ_ONLY - if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode)) - result |= aRONLY; -#endif -#endif - - /* hide files with a name starting with a . */ - if (lp_hide_dot_files(SNUM(cnum))) - { - char *p = strrchr(path,'/'); - if (p) - p++; - else - p = path; - - if (p[0] == '.' && p[1] != '.' && p[1] != 0) - result |= aHIDDEN; - } - - /* Optimization : Only call is_hidden_path if it's not already - hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(cnum,path)) - { - result |= aHIDDEN; - } - - DEBUG(8,("dos_mode returning ")); - - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); - - DEBUG(8,("\n")); - - return(result); -} - - -/******************************************************************* -chmod a file - but preserve some bits -********************************************************************/ -int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st) -{ - struct stat st1; - int mask=0; - int tmp; - int unixmode; - - if (!st) { - st = &st1; - if (sys_stat(fname,st)) return(-1); - } - - if (S_ISDIR(st->st_mode)) dosmode |= aDIR; - - if (dos_mode(cnum,fname,st) == dosmode) return(0); - - unixmode = unix_mode(cnum,dosmode); - - /* preserve the s bits */ - mask |= (S_ISUID | S_ISGID); - - /* preserve the t bit */ -#ifdef S_ISVTX - mask |= S_ISVTX; -#endif - - /* possibly preserve the x bits */ - if (!MAP_ARCHIVE(cnum)) mask |= S_IXUSR; - if (!MAP_SYSTEM(cnum)) mask |= S_IXGRP; - if (!MAP_HIDDEN(cnum)) mask |= S_IXOTH; - - unixmode |= (st->st_mode & mask); - - /* if we previously had any r bits set then leave them alone */ - if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) { - unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH); - unixmode |= tmp; - } - - /* if we previously had any w bits set then leave them alone - if the new mode is not rdonly */ - if (!IS_DOS_READONLY(dosmode) && - (tmp = st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) { - unixmode &= ~(S_IWUSR|S_IWGRP|S_IWOTH); - unixmode |= tmp; - } - - return(sys_chmod(fname,unixmode)); -} - - -/**************************************************************************** -check if two filenames are equal - -this needs to be careful about whether we are case sensitive -****************************************************************************/ -static BOOL fname_equal(char *name1, char *name2) -{ - int l1 = strlen(name1); - int l2 = strlen(name2); - - /* handle filenames ending in a single dot */ - if (l1-l2 == 1 && name1[l1-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name1[l1-1] = 0; - ret = fname_equal(name1,name2); - name1[l1-1] = '.'; - return(ret); - } - - if (l2-l1 == 1 && name2[l2-1] == '.' && lp_strip_dot()) - { - BOOL ret; - name2[l2-1] = 0; - ret = fname_equal(name1,name2); - name2[l2-1] = '.'; - return(ret); - } - - /* now normal filename handling */ - if (case_sensitive) - return(strcmp(name1,name2) == 0); - - return(strequal(name1,name2)); -} - - -/**************************************************************************** -mangle the 2nd name and check if it is then equal to the first name -****************************************************************************/ -static BOOL mangled_equal(char *name1, char *name2) -{ - pstring tmpname; - - if (is_8_3(name2, True)) - return(False); - - strcpy(tmpname,name2); - mangle_name_83(tmpname); - - return(strequal(name1,tmpname)); -} - - -/**************************************************************************** -scan a directory to find a filename, matching without case sensitivity - -If the name looks like a mangled name then try via the mangling functions -****************************************************************************/ -static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache) -{ - void *cur_dir; - char *dname; - BOOL mangled; - pstring name2; - - mangled = is_mangled(name); - - /* handle null paths */ - if (*path == 0) - path = "."; - - if (docache && (dname = DirCacheCheck(path,name,SNUM(cnum)))) { - strcpy(name, dname); - return(True); - } - - if (mangled) - check_mangled_stack(name); - - /* open the directory */ - if (!(cur_dir = OpenDir(cnum, path, True))) - { - DEBUG(3,("scan dir didn't open dir [%s]\n",path)); - return(False); - } - - /* now scan for matching names */ - while ((dname = ReadDirName(cur_dir))) - { - if (*dname == '.' && - (strequal(dname,".") || strequal(dname,".."))) - continue; - - pstrcpy(name2,dname); - if (!name_map_mangle(name2,False,SNUM(cnum))) continue; - - if ((mangled && mangled_equal(name,name2)) - || fname_equal(name, name2)) /* name2 here was changed to dname - since 1.9.16p2 - not sure of reason (jra) */ - { - /* we've found the file, change it's name and return */ - if (docache) DirCacheAdd(path,name,dname,SNUM(cnum)); - strcpy(name, dname); - CloseDir(cur_dir); - return(True); - } - } - - CloseDir(cur_dir); - return(False); -} - -/**************************************************************************** -This routine is called to convert names from the dos namespace to unix -namespace. It needs to handle any case conversions, mangling, format -changes etc. - -We assume that we have already done a chdir() to the right "root" directory -for this service. - -The function will return False if some part of the name except for the last -part cannot be resolved - -If the saved_last_component != 0, then the unmodified last component -of the pathname is returned there. This is used in an exceptional -case in reply_mv (so far). If saved_last_component == 0 then nothing -is returned there. - -The bad_path arg is set to True if the filename walk failed. This is -used to pick the correct error code to return between ENOENT and ENOTDIR -as Windows applications depend on ERRbadpath being returned if a component -of a pathname does not exist. -****************************************************************************/ -BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_path) -{ - struct stat st; - char *start, *end; - pstring dirpath; - int saved_errno; - - *dirpath = 0; - *bad_path = False; - - if(saved_last_component) - *saved_last_component = 0; - - /* convert to basic unix format - removing \ chars and cleaning it up */ - unix_format(name); - unix_clean_name(name); - - /* names must be relative to the root of the service - trim any leading /. - also trim trailing /'s */ - trim_string(name,"/","/"); - - /* - * Ensure saved_last_component is valid even if file exists. - */ - if(saved_last_component) { - end = strrchr(name, '/'); - if(end) - strcpy(saved_last_component, end + 1); - else - strcpy(saved_last_component, name); - } - - if (!case_sensitive && - (!case_preserve || (is_8_3(name, False) && !short_case_preserve))) - strnorm(name); - - /* check if it's a printer file */ - if (Connections[cnum].printer) - { - if ((! *name) || strchr(name,'/') || !is_8_3(name, True)) - { - char *s; - fstring name2; - sprintf(name2,"%.6s.XXXXXX",remote_machine); - /* sanitise the name */ - for (s=name2 ; *s ; s++) - if (!issafe(*s)) *s = '_'; - strcpy(name,(char *)mktemp(name2)); - } - return(True); - } - - /* stat the name - if it exists then we are all done! */ - if (sys_stat(name,&st) == 0) - return(True); - - saved_errno = errno; - - DEBUG(5,("unix_convert(%s,%d)\n",name,cnum)); - - /* a special case - if we don't have any mangling chars and are case - sensitive then searching won't help */ - if (case_sensitive && !is_mangled(name) && - !lp_strip_dot() && !use_mangled_map && (saved_errno != ENOENT)) - return(False); - - /* now we need to recursively match the name against the real - directory structure */ - - start = name; - while (strncmp(start,"./",2) == 0) - start += 2; - - /* now match each part of the path name separately, trying the names - as is first, then trying to scan the directory for matching names */ - for (;start;start = (end?end+1:(char *)NULL)) - { - /* pinpoint the end of this section of the filename */ - end = strchr(start, '/'); - - /* chop the name at this point */ - if (end) *end = 0; - - if(saved_last_component != 0) - strcpy(saved_last_component, end ? end + 1 : start); - - /* check if the name exists up to this point */ - if (sys_stat(name, &st) == 0) - { - /* it exists. it must either be a directory or this must be - the last part of the path for it to be OK */ - if (end && !(st.st_mode & S_IFDIR)) - { - /* an intermediate part of the name isn't a directory */ - DEBUG(5,("Not a dir %s\n",start)); - *end = '/'; - return(False); - } - } - else - { - pstring rest; - - *rest = 0; - - /* remember the rest of the pathname so it can be restored - later */ - if (end) pstrcpy(rest,end+1); - - /* try to find this part of the path in the directory */ - if (strchr(start,'?') || strchr(start,'*') || - !scan_directory(dirpath, start, cnum, end?True:False)) - { - if (end) - { - /* an intermediate part of the name can't be found */ - DEBUG(5,("Intermediate not found %s\n",start)); - *end = '/'; - /* We need to return the fact that the intermediate - name resolution failed. This is used to return an - error of ERRbadpath rather than ERRbadfile. Some - Windows applications depend on the difference between - these two errors. - */ - *bad_path = True; - return(False); - } - - /* just the last part of the name doesn't exist */ - /* we may need to strupper() or strlower() it in case - this conversion is being used for file creation - purposes */ - /* if the filename is of mixed case then don't normalise it */ - if (!case_preserve && - (!strhasupper(start) || !strhaslower(start))) - strnorm(start); - - /* check on the mangled stack to see if we can recover the - base of the filename */ - if (is_mangled(start)) - check_mangled_stack(start); - - DEBUG(5,("New file %s\n",start)); - return(True); - } - - /* restore the rest of the string */ - if (end) - { - strcpy(start+strlen(start)+1,rest); - end = start + strlen(start); - } - } - - /* add to the dirpath that we have resolved so far */ - if (*dirpath) strcat(dirpath,"/"); - strcat(dirpath,start); - - /* restore the / that we wiped out earlier */ - if (end) *end = '/'; - } - - /* the name has been resolved */ - DEBUG(5,("conversion finished %s\n",name)); - return(True); -} - - -/**************************************************************************** -normalise for DOS usage -****************************************************************************/ -static void disk_norm(int *bsize,int *dfree,int *dsize) -{ - /* check if the disk is beyond the max disk size */ - int maxdisksize = lp_maxdisksize(); - if (maxdisksize) { - /* convert to blocks - and don't overflow */ - maxdisksize = ((maxdisksize*1024)/(*bsize))*1024; - if (*dsize > maxdisksize) *dsize = maxdisksize; - if (*dfree > maxdisksize) *dfree = maxdisksize-1; /* the -1 should stop - applications getting - div by 0 errors */ - } - - while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) - { - *dfree /= 2; - *dsize /= 2; - *bsize *= 2; - if (*bsize > WORDMAX ) - { - *bsize = WORDMAX; - if (*dsize > WORDMAX) - *dsize = WORDMAX; - if (*dfree > WORDMAX) - *dfree = WORDMAX; - break; - } - } -} - -/**************************************************************************** - return number of 1K blocks available on a path and total number -****************************************************************************/ -int disk_free(char *path,int *bsize,int *dfree,int *dsize) -{ - char *df_command = lp_dfree_command(); - int dfree_retval; -#ifdef QUOTAS - int dfreeq_retval; - int dfreeq = 0; - int bsizeq = *bsize; - int dsizeq = *dsize; -#endif - -#ifndef NO_STATFS -#ifdef USE_STATVFS - struct statvfs fs; -#else -#ifdef ULTRIX - struct fs_data fs; -#else - struct statfs fs; -#endif -#endif -#endif - - /* possibly use system() to get the result */ - if (df_command && *df_command) - { - int ret; - pstring syscmd; - pstring outfile; - - sprintf(outfile,"%s/dfree.smb.%d",tmpdir(),(int)getpid()); - sprintf(syscmd,"%s %s",df_command,path); - standard_sub_basic(syscmd); - - ret = smbrun(syscmd,outfile,False); - DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret)); - - { - FILE *f = fopen(outfile,"r"); - *dsize = 0; - *dfree = 0; - *bsize = 1024; - if (f) - { - fscanf(f,"%d %d %d",dsize,dfree,bsize); - fclose(f); - } - else - DEBUG(0,("Can't open %s\n",outfile)); - } - - unlink(outfile); - disk_norm(bsize,dfree,dsize); - dfree_retval = ((*bsize)/1024)*(*dfree); -#ifdef QUOTAS - /* Ensure we return the min value between the users quota and - what's free on the disk. Thanks to Albrecht Gebhardt - <albrecht.gebhardt@uni-klu.ac.at> for this fix. - */ - if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq)) - { - disk_norm(&bsizeq, &dfreeq, &dsizeq); - dfreeq_retval = ((bsizeq)/1024)*(dfreeq); - dfree_retval = ( dfree_retval < dfreeq_retval ) ? - dfree_retval : dfreeq_retval ; - /* maybe dfree and dfreeq are calculated using different bsizes - so convert dfree from bsize into bsizeq */ - /* avoid overflows due to multiplication, so do not: - *dfree = ((*dfree) * (*bsize)) / (bsizeq); - bsize and bsizeq are powers of 2 so its better to - to divide them getting a multiplication or division factor - for dfree. Rene Nieuwenhuizen (07-10-1997) */ - if (*bsize >= bsizeq) - *dfree = *dfree * (*bsize / bsizeq); - else - *dfree = *dfree / (bsizeq / *bsize); - *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; - *bsize = bsizeq; - *dsize = dsizeq; - } -#endif - return(dfree_retval); - } - -#ifdef NO_STATFS - DEBUG(1,("Warning - no statfs function\n")); - return(1); -#else -#ifdef STATFS4 - if (statfs(path,&fs,sizeof(fs),0) != 0) -#else -#ifdef USE_STATVFS - if (statvfs(path, &fs)) -#else -#ifdef STATFS3 - if (statfs(path,&fs,sizeof(fs)) == -1) -#else - if (statfs(path,&fs) == -1) -#endif /* STATFS3 */ -#endif /* USE_STATVFS */ -#endif /* STATFS4 */ - { - DEBUG(3,("dfree call failed code errno=%d\n",errno)); - *bsize = 1024; - *dfree = 1; - *dsize = 1; - return(((*bsize)/1024)*(*dfree)); - } - -#ifdef ULTRIX - *bsize = 1024; - *dfree = fs.fd_req.bfree; - *dsize = fs.fd_req.btot; -#else -#ifdef USE_STATVFS - *bsize = fs.f_frsize; -#else -#ifdef USE_F_FSIZE - /* eg: osf1 has f_fsize = fundamental filesystem block size, - f_bsize = optimal transfer block size (MX: 94-04-19) */ - *bsize = fs.f_fsize; -#else - *bsize = fs.f_bsize; -#endif /* STATFS3 */ -#endif /* USE_STATVFS */ - -#ifdef STATFS4 - *dfree = fs.f_bfree; -#else - *dfree = fs.f_bavail; -#endif /* STATFS4 */ - *dsize = fs.f_blocks; -#endif /* ULTRIX */ - -#if defined(SCO) || defined(ISC) || defined(MIPS) - *bsize = 512; -#endif - -/* handle rediculous bsize values - some OSes are broken */ -if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; - - disk_norm(bsize,dfree,dsize); - - if (*bsize < 256) - *bsize = 512; - if ((*dsize)<1) - { - DEBUG(0,("dfree seems to be broken on your system\n")); - *dsize = 20*1024*1024/(*bsize); - *dfree = MAX(1,*dfree); - } - dfree_retval = ((*bsize)/1024)*(*dfree); -#ifdef QUOTAS - /* Ensure we return the min value between the users quota and - what's free on the disk. Thanks to Albrecht Gebhardt - <albrecht.gebhardt@uni-klu.ac.at> for this fix. - */ - if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq)) - { - disk_norm(&bsizeq, &dfreeq, &dsizeq); - dfreeq_retval = ((bsizeq)/1024)*(dfreeq); - dfree_retval = ( dfree_retval < dfreeq_retval ) ? - dfree_retval : dfreeq_retval ; - /* maybe dfree and dfreeq are calculated using different bsizes - so convert dfree from bsize into bsizeq */ - /* avoid overflows due to multiplication, so do not: - *dfree = ((*dfree) * (*bsize)) / (bsizeq); - bsize and bsizeq are powers of 2 so its better to - to divide them getting a multiplication or division factor - for dfree. Rene Nieuwenhuizen (07-10-1997) */ - if (*bsize >= bsizeq) - *dfree = *dfree * (*bsize / bsizeq); - else - *dfree = *dfree / (bsizeq / *bsize); - *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; - *bsize = bsizeq; - *dsize = dsizeq; - } -#endif - return(dfree_retval); -#endif -} - - -/**************************************************************************** -wrap it to get filenames right -****************************************************************************/ -int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize) -{ - return(disk_free(dos_to_unix(path,False),bsize,dfree,dsize)); -} - - - -/**************************************************************************** -check a filename - possibly caling reducename - -This is called by every routine before it allows an operation on a filename. -It does any final confirmation necessary to ensure that the filename is -a valid one for the user to access. -****************************************************************************/ -BOOL check_name(char *name,int cnum) -{ - BOOL ret; - - errno = 0; - - if( IS_VETO_PATH(cnum, name)) - { - DEBUG(5,("file path name %s vetoed\n",name)); - return(0); - } - - ret = reduce_name(name,Connections[cnum].connectpath,lp_widelinks(SNUM(cnum))); - - /* Check if we are allowing users to follow symlinks */ - /* Patch from David Clerc <David.Clerc@cui.unige.ch> - University of Geneva */ - -#ifdef S_ISLNK - if (!lp_symlinks(SNUM(cnum))) - { - struct stat statbuf; - if ( (sys_lstat(name,&statbuf) != -1) && - (S_ISLNK(statbuf.st_mode)) ) - { - DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); - ret=0; - } - } -#endif - - if (!ret) - DEBUG(5,("check_name on %s failed\n",name)); - - return(ret); -} - -/**************************************************************************** -check a filename - possibly caling reducename -****************************************************************************/ -static void check_for_pipe(char *fname) -{ - /* special case of pipe opens */ - char s[10]; - StrnCpy(s,fname,9); - strlower(s); - if (strstr(s,"pipe/")) - { - DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRaccess; - } -} - -/**************************************************************************** -fd support routines - attempt to do a sys_open -****************************************************************************/ -static int fd_attempt_open(char *fname, int flags, int mode) -{ - int fd = sys_open(fname,flags,mode); - - /* Fix for files ending in '.' */ - if((fd == -1) && (errno == ENOENT) && - (strchr(fname,'.')==NULL)) - { - strcat(fname,"."); - fd = sys_open(fname,flags,mode); - } - -#if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF)) - if ((fd == -1) && (errno == ENAMETOOLONG)) - { - int max_len; - char *p = strrchr(fname, '/'); - - if (p == fname) /* name is "/xxx" */ - { - max_len = pathconf("/", _PC_NAME_MAX); - p++; - } - else if ((p == NULL) || (p == fname)) - { - p = fname; - max_len = pathconf(".", _PC_NAME_MAX); - } - else - { - *p = '\0'; - max_len = pathconf(fname, _PC_NAME_MAX); - *p = '/'; - p++; - } - if (strlen(p) > max_len) - { - char tmp = p[max_len]; - - p[max_len] = '\0'; - if ((fd = sys_open(fname,flags,mode)) == -1) - p[max_len] = tmp; - } - } -#endif - return fd; -} - -/**************************************************************************** -fd support routines - attempt to find an already open file by dev -and inode - increments the ref_count of the returned file_fd_struct *. -****************************************************************************/ -static file_fd_struct *fd_get_already_open(struct stat *sbuf) -{ - int i; - file_fd_struct *fd_ptr; - - if(sbuf == 0) - return 0; - - for(i = 0; i <= max_file_fd_used; i++) { - fd_ptr = &FileFd[i]; - if((fd_ptr->ref_count > 0) && - (((uint32)sbuf->st_dev) == fd_ptr->dev) && - (((uint32)sbuf->st_ino) == fd_ptr->inode)) { - fd_ptr->ref_count++; - DEBUG(3, - ("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n", - i, fd_ptr->dev, fd_ptr->inode, fd_ptr->ref_count)); - return fd_ptr; - } - } - return 0; -} - -/**************************************************************************** -fd support routines - attempt to find a empty slot in the FileFd array. -Increments the ref_count of the returned entry. -****************************************************************************/ -static file_fd_struct *fd_get_new() -{ - int i; - file_fd_struct *fd_ptr; - - for(i = 0; i < MAX_OPEN_FILES; i++) { - fd_ptr = &FileFd[i]; - if(fd_ptr->ref_count == 0) { - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->ref_count++; - /* Increment max used counter if neccessary, cuts down - on search time when re-using */ - if(i > max_file_fd_used) - max_file_fd_used = i; - DEBUG(3,("Allocated new file_fd_struct %d, dev = %x, inode = %x\n", - i, fd_ptr->dev, fd_ptr->inode)); - return fd_ptr; - } - } - DEBUG(1,("ERROR! Out of file_fd structures - perhaps increase MAX_OPEN_FILES?\ -n")); - return 0; -} - -/**************************************************************************** -fd support routines - attempt to re-open an already open fd as O_RDWR. -Save the already open fd (we cannot close due to POSIX file locking braindamage. -****************************************************************************/ -static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) -{ - int fd = sys_open( fname, O_RDWR, mode); - - if(fd == -1) - return; - - if(fd_ptr->real_open_flags == O_RDONLY) - fd_ptr->fd_readonly = fd_ptr->fd; - if(fd_ptr->real_open_flags == O_WRONLY) - fd_ptr->fd_writeonly = fd_ptr->fd; - - fd_ptr->fd = fd; - fd_ptr->real_open_flags = O_RDWR; -} - -/**************************************************************************** -fd support routines - attempt to close the file referenced by this fd. -Decrements the ref_count and returns it. -****************************************************************************/ -static int fd_attempt_close(file_fd_struct *fd_ptr) -{ - DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", - fd_ptr - &FileFd[0], - fd_ptr->fd, fd_ptr->dev, fd_ptr->inode, - fd_ptr->real_open_flags, - fd_ptr->ref_count)); - if(fd_ptr->ref_count > 0) { - fd_ptr->ref_count--; - if(fd_ptr->ref_count == 0) { - if(fd_ptr->fd != -1) - close(fd_ptr->fd); - if(fd_ptr->fd_readonly != -1) - close(fd_ptr->fd_readonly); - if(fd_ptr->fd_writeonly != -1) - close(fd_ptr->fd_writeonly); - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - fd_ptr->dev = (uint32)-1; - fd_ptr->inode = (uint32)-1; - } - } - return fd_ptr->ref_count; -} - -/**************************************************************************** -open a file -****************************************************************************/ -static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf) -{ - extern struct current_user current_user; - pstring fname; - struct stat statbuf; - file_fd_struct *fd_ptr; - files_struct *fsp = &Files[fnum]; - - fsp->open = False; - fsp->fd_ptr = 0; - fsp->granted_oplock = False; - errno = EPERM; - - pstrcpy(fname,fname1); - - /* check permissions */ - if ((flags != O_RDONLY) && !CAN_WRITE(cnum) && !Connections[cnum].printer) - { - DEBUG(3,("Permission denied opening %s\n",fname)); - check_for_pipe(fname); - return; - } - - /* this handles a bug in Win95 - it doesn't say to create the file when it - should */ - if (Connections[cnum].printer) - flags |= O_CREAT; - -/* - if (flags == O_WRONLY) - DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n")); -*/ - -#if UTIME_WORKAROUND - /* XXXX - is this OK?? */ - /* this works around a utime bug but can cause other problems */ - if ((flags & (O_WRONLY|O_RDWR)) && (flags & O_CREAT) && !(flags & O_APPEND)) - sys_unlink(fname); -#endif - - /* - * Ensure we have a valid struct stat so we can search the - * open fd table. - */ - if(sbuf == 0) { - if(stat(fname, &statbuf) < 0) { - if(errno != ENOENT) { - DEBUG(3,("Error doing stat on file %s (%s)\n", - fname,strerror(errno))); - - check_for_pipe(fname); - return; - } - sbuf = 0; - } else { - sbuf = &statbuf; - } - } - - /* - * Check to see if we have this file already - * open. If we do, just use the already open fd and increment the - * reference count (fd_get_already_open increments the ref_count). - */ - if((fd_ptr = fd_get_already_open(sbuf))!= 0) { - - int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR)); - - /* File was already open. */ - if((flags & O_CREAT) && (flags & O_EXCL)) { - fd_ptr->ref_count--; - errno = EEXIST; - return; - } - - /* - * If not opened O_RDWR try - * and do that here - a chmod may have been done - * between the last open and now. - */ - if(fd_ptr->real_open_flags != O_RDWR) - fd_attempt_reopen(fname, mode, fd_ptr); - - /* - * Ensure that if we wanted write access - * it has been opened for write, and if we wanted read it - * was open for read. - */ - if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) || - ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) || - ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) { - DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n", - fd_ptr->real_open_flags, fname,strerror(EACCES),flags)); - check_for_pipe(fname); - fd_ptr->ref_count--; - return; - } - - } else { - int open_flags; - /* We need to allocate a new file_fd_struct (this increments the - ref_count). */ - if((fd_ptr = fd_get_new()) == 0) - return; - /* - * Whatever the requested flags, attempt read/write access, - * as we don't know what flags future file opens may require. - * If this fails, try again with the required flags. - * Even if we open read/write when only read access was - * requested the setting of the can_write flag in - * the file_struct will protect us from errant - * write requests. We never need to worry about O_APPEND - * as this is not set anywhere in Samba. - */ - fd_ptr->real_open_flags = O_RDWR; - /* Set the flags as needed without the read/write modes. */ - open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY); - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode); - /* - * On some systems opening a file for R/W access on a read only - * filesystems sets errno to EROFS. - */ -#ifdef EROFS - if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) { -#else /* No EROFS */ - if((fd_ptr->fd == -1) && (errno == EACCES)) { -#endif /* EROFS */ - if(flags & O_WRONLY) { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode); - fd_ptr->real_open_flags = O_WRONLY; - } else { - fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDONLY, mode); - fd_ptr->real_open_flags = O_RDONLY; - } - } - } - - if ((fd_ptr->fd >=0) && - Connections[cnum].printer && lp_minprintspace(SNUM(cnum))) { - pstring dname; - int dum1,dum2,dum3; - char *p; - pstrcpy(dname,fname); - p = strrchr(dname,'/'); - if (p) *p = 0; - if (sys_disk_free(dname,&dum1,&dum2,&dum3) < - lp_minprintspace(SNUM(cnum))) { - fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; - if(fd_ptr->ref_count == 0) - sys_unlink(fname); - errno = ENOSPC; - return; - } - } - - if (fd_ptr->fd < 0) - { - DEBUG(3,("Error opening file %s (%s) (flags=%d)\n", - fname,strerror(errno),flags)); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); - check_for_pipe(fname); - return; - } - - if (fd_ptr->fd >= 0) - { - if(sbuf == 0) { - /* Do the fstat */ - if(fstat(fd_ptr->fd, &statbuf) == -1) { - /* Error - backout !! */ - DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n", - fd_ptr->fd, fname,strerror(errno))); - /* Ensure the ref_count is decremented. */ - fd_attempt_close(fd_ptr); - return; - } - sbuf = &statbuf; - } - /* Set the correct entries in fd_ptr. */ - fd_ptr->dev = (uint32)sbuf->st_dev; - fd_ptr->inode = (uint32)sbuf->st_ino; - - fsp->fd_ptr = fd_ptr; - Connections[cnum].num_files_open++; - fsp->mode = sbuf->st_mode; - GetTimeOfDay(&fsp->open_time); - fsp->uid = current_user.id; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; - fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->print_file = Connections[cnum].printer; - fsp->modified = False; - fsp->granted_oplock = False; - fsp->cnum = cnum; - string_set(&fsp->name,dos_to_unix(fname,False)); - fsp->wbmpx_ptr = NULL; - - /* - * If the printer is marked as postscript output a leading - * file identifier to ensure the file is treated as a raw - * postscript file. - * This has a similar effect as CtrlD=0 in WIN.INI file. - * tim@fsg.com 09/06/94 - */ - if (fsp->print_file && POSTSCRIPT(cnum) && - fsp->can_write) - { - DEBUG(3,("Writing postscript line\n")); - write_file(fnum,"%!\n",3); - } - - DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", - timestring(),Connections[cnum].user,fname, - BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write), - Connections[cnum].num_files_open,fnum)); - - } - -#if USE_MMAP - /* mmap it if read-only */ - if (!fsp->can_write) - { - fsp->mmap_size = file_size(fname); - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); - - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) - { - DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); - fsp->mmap_ptr = NULL; - } - } -#endif -} - -/******************************************************************* -sync a file -********************************************************************/ -void sync_file(int fnum) -{ -#ifndef NO_FSYNC - fsync(Files[fnum].fd_ptr->fd); -#endif -} - -/**************************************************************************** -run a file if it is a magic script -****************************************************************************/ -static void check_magic(int fnum,int cnum) -{ - if (!*lp_magicscript(SNUM(cnum))) - return; - - DEBUG(5,("checking magic for %s\n",Files[fnum].name)); - - { - char *p; - if (!(p = strrchr(Files[fnum].name,'/'))) - p = Files[fnum].name; - else - p++; - - if (!strequal(lp_magicscript(SNUM(cnum)),p)) - return; - } - - { - int ret; - pstring magic_output; - pstring fname; - pstrcpy(fname,Files[fnum].name); - - if (*lp_magicoutput(SNUM(cnum))) - pstrcpy(magic_output,lp_magicoutput(SNUM(cnum))); - else - sprintf(magic_output,"%s.out",fname); - - chmod(fname,0755); - ret = smbrun(fname,magic_output,False); - DEBUG(3,("Invoking magic command %s gave %d\n",fname,ret)); - unlink(fname); - } -} - - -/**************************************************************************** -close a file - possibly invalidating the read prediction -****************************************************************************/ -void close_file(int fnum) -{ - files_struct *fs_p = &Files[fnum]; - int cnum = fs_p->cnum; - uint32 dev = fs_p->fd_ptr->dev; - uint32 inode = fs_p->fd_ptr->inode; - share_lock_token token; - - invalidate_read_prediction(fs_p->fd_ptr->fd); - fs_p->open = False; - Connections[cnum].num_files_open--; - if(fs_p->wbmpx_ptr) - { - free((char *)fs_p->wbmpx_ptr); - fs_p->wbmpx_ptr = NULL; - } - -#if USE_MMAP - if(fs_p->mmap_ptr) - { - munmap(fs_p->mmap_ptr,fs_p->mmap_size); - fs_p->mmap_ptr = NULL; - } -#endif - - if (lp_share_modes(SNUM(cnum))) - { - lock_share_entry( cnum, dev, inode, &token); - del_share_mode(token, fnum); - } - - fd_attempt_close(fs_p->fd_ptr); - - if (lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, dev, inode, token); - - /* NT uses smbclose to start a print - weird */ - if (fs_p->print_file) - print_file(fnum); - - /* check for magic scripts */ - check_magic(fnum,cnum); - - DEBUG(2,("%s %s closed file %s (numopen=%d)\n", - timestring(),Connections[cnum].user,fs_p->name, - Connections[cnum].num_files_open)); -} - -enum {AFAIL,AREAD,AWRITE,AALL}; - -/******************************************************************* -reproduce the share mode access table -********************************************************************/ -static int access_table(int new_deny,int old_deny,int old_mode, - int share_pid,char *fname) -{ - if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); - - if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - int pid = getpid(); - if (old_deny == new_deny && share_pid == pid) - return(AALL); - - if (old_mode == 0) return(AREAD); - - /* the new smbpub.zip spec says that if the file extension is - .com, .dll, .exe or .sym then allow the open. I will force - it to read-only as this seems sensible although the spec is - a little unclear on this. */ - if ((fname = strrchr(fname,'.'))) { - if (strequal(fname,".com") || - strequal(fname,".dll") || - strequal(fname,".exe") || - strequal(fname,".sym")) - return(AREAD); - } - - return(AFAIL); - } - - switch (new_deny) - { - case DENY_WRITE: - if (old_deny==DENY_WRITE && old_mode==0) return(AREAD); - if (old_deny==DENY_READ && old_mode==0) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==0) return(AALL); - return(AFAIL); - case DENY_READ: - if (old_deny==DENY_WRITE && old_mode==1) return(AREAD); - if (old_deny==DENY_READ && old_mode==1) return(AWRITE); - if (old_deny==DENY_NONE && old_mode==1) return(AALL); - return(AFAIL); - case DENY_NONE: - if (old_deny==DENY_WRITE) return(AREAD); - if (old_deny==DENY_READ) return(AWRITE); - if (old_deny==DENY_NONE) return(AALL); - return(AFAIL); - } - return(AFAIL); -} - -/******************************************************************* -check if the share mode on a file allows it to be deleted or unlinked -return True if sharing doesn't prevent the operation -********************************************************************/ -BOOL check_file_sharing(int cnum,char *fname) -{ - int i; - int ret = False; - min_share_mode_entry *old_shares = 0; - int num_share_modes; - struct stat sbuf; - share_lock_token token; - int pid = getpid(); - uint32 dev, inode; - - if(!lp_share_modes(SNUM(cnum))) - return True; - - if (stat(fname,&sbuf) == -1) return(True); - - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; - - lock_share_entry(cnum, dev, inode, &token); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); - - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) - { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - min_share_mode_entry *share_entry = &old_shares[i]; - - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(share_entry->op_type & BATCH_OPLOCK) - { - - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - - /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - return False; - } - lock_share_entry(cnum, dev, inode, &token); - broke_oplock = True; - break; - } - - /* someone else has a share lock on it, check to see - if we can too */ - if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) - goto free_and_exit; - - } /* end for */ - - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); - } - } while(broke_oplock); - } - - /* XXXX exactly what share mode combinations should be allowed for - deleting/renaming? */ - /* If we got here then either there were no share modes or - all share modes were DENY_DOS and the pid == getpid() */ - ret = True; - -free_and_exit: - - unlock_share_entry(cnum, dev, inode, token); - if(old_shares != NULL) - free((char *)old_shares); - return(ret); -} - -/**************************************************************************** - C. Hoch 11/22/95 - Helper for open_file_shared. - Truncate a file after checking locking; close file if locked. - **************************************************************************/ -static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, - BOOL *share_locked) -{ - if (Files[fnum].can_write){ - if (is_locked(fnum,cnum,0x3FFFFFFF,0)){ - /* If share modes are in force for this connection we - have the share entry locked. Unlock it before closing. */ - if (*share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, - Files[fnum].fd_ptr->inode, token); - close_file(fnum); - /* Share mode no longer locked. */ - *share_locked = False; - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRlock; - } - else - ftruncate(Files[fnum].fd_ptr->fd,0); - } -} - -/**************************************************************************** -check if we can open a file with a share mode -****************************************************************************/ -int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, - BOOL fcbopen, int *flags) -{ - int old_open_mode = share->share_mode &0xF; - int old_deny_mode = (share->share_mode >>4)&7; - - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - return False; - } - - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags == O_WRONLY) || - (access_allowed == AWRITE && *flags == O_RDONLY)) - { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - share->pid,fname, access_allowed)); - return False; - } - - if (access_allowed == AREAD) - *flags = O_RDONLY; - - if (access_allowed == AWRITE) - *flags = O_WRONLY; - - } - return True; -} - -/**************************************************************************** -open a file with a share mode -****************************************************************************/ -void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, - int mode,int oplock_request, int *Access,int *action) -{ - files_struct *fs_p = &Files[fnum]; - int flags=0; - int flags2=0; - int deny_mode = (share_mode>>4)&7; - struct stat sbuf; - BOOL file_existed = file_exist(fname,&sbuf); - BOOL share_locked = False; - BOOL fcbopen = False; - share_lock_token token; - uint32 dev = 0; - uint32 inode = 0; - int num_share_modes = 0; - - fs_p->open = False; - fs_p->fd_ptr = 0; - - /* this is for OS/2 EAs - try and say we don't support them */ - if (strstr(fname,".+,;=[].")) - { - unix_ERR_class = ERRDOS; - /* OS/2 Workplace shell fix may be main code stream in a later release. */ -#ifdef OS2_WPS_FIX - unix_ERR_code = ERRcannotopen; -#else /* OS2_WPS_FIX */ - unix_ERR_code = ERROR_EAS_NOT_SUPPORTED; -#endif /* OS2_WPS_FIX */ - - return; - } - - if ((ofun & 0x3) == 0 && file_existed) - { - errno = EEXIST; - return; - } - - if (ofun & 0x10) - flags2 |= O_CREAT; - if ((ofun & 0x3) == 2) - flags2 |= O_TRUNC; - - /* note that we ignore the append flag as - append does not mean the same thing under dos and unix */ - - switch (share_mode&0xF) - { - case 1: - flags = O_WRONLY; - break; - case 0xF: - fcbopen = True; - flags = O_RDWR; - break; - case 2: - flags = O_RDWR; - break; - default: - flags = O_RDONLY; - break; - } - - if (flags != O_RDONLY && file_existed && - (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) - { - if (!fcbopen) - { - errno = EACCES; - return; - } - flags = O_RDONLY; - } - - if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) - { - DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - errno = EINVAL; - return; - } - - if (deny_mode == DENY_FCB) deny_mode = DENY_DOS; - - if (lp_share_modes(SNUM(cnum))) - { - int i; - min_share_mode_entry *old_shares = 0; - - if (file_existed) - { - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; - lock_share_entry(cnum, dev, inode, &token); - share_locked = True; - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); - } - - /* - * Check if the share modes will give us access. - */ - - if(share_locked && (num_share_modes != 0)) - { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - min_share_mode_entry *share_entry = &old_shares[i]; - - /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. - */ - if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) - { - - DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - - /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - lock_share_entry(cnum, dev, inode, &token); - broke_oplock = True; - break; - } - - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(cnum, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - - } /* end for */ - - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); - } - } while(broke_oplock); - } - - if(old_shares != 0) - free((char *)old_shares); - } - - DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - flags,flags2,mode)); - - open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0); - if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen) - { - flags = O_RDONLY; - open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 ); - } - - if (fs_p->open) - { - int open_mode=0; - - if((share_locked == False) && lp_share_modes(SNUM(cnum))) - { - /* We created the file - thus we must now lock the share entry before creating it. */ - dev = fs_p->fd_ptr->dev; - inode = fs_p->fd_ptr->inode; - lock_share_entry(cnum, dev, inode, &token); - share_locked = True; - } - - switch (flags) - { - case O_RDONLY: - open_mode = 0; - break; - case O_RDWR: - open_mode = 2; - break; - case O_WRONLY: - open_mode = 1; - break; - } - - fs_p->share_mode = (deny_mode<<4) | open_mode; - - if (Access) - (*Access) = open_mode; - - if (action) - { - if (file_existed && !(flags2 & O_TRUNC)) *action = 1; - if (!file_existed) *action = 2; - if (file_existed && (flags2 & O_TRUNC)) *action = 3; - } - /* We must create the share mode entry before truncate as - truncate can fail due to locking and have to close the - file (which expects the share_mode_entry to be there). - */ - if (lp_share_modes(SNUM(cnum))) - { - uint16 port = 0; - /* JRA. Currently this only services Exlcusive and batch - oplocks (no other opens on this file). This needs to - be extended to level II oplocks (multiple reader - oplocks). */ - - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum))) - { - fs_p->granted_oplock = True; - global_oplocks_open++; - port = oplock_port; - - DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); - - } - else - { - port = 0; - oplock_request = 0; - } - set_share_mode(token, fnum, port, oplock_request); - } - - if ((flags2&O_TRUNC) && file_existed) - truncate_unless_locked(fnum,cnum,token,&share_locked); - } - - if (share_locked && lp_share_modes(SNUM(cnum))) - unlock_share_entry( cnum, dev, inode, token); -} - -/**************************************************************************** -seek a file. Try to avoid the seek if possible -****************************************************************************/ -int seek_file(int fnum,uint32 pos) -{ - uint32 offset = 0; - if (Files[fnum].print_file && POSTSCRIPT(Files[fnum].cnum)) - offset = 3; - - Files[fnum].pos = (int)(lseek(Files[fnum].fd_ptr->fd,pos+offset,SEEK_SET) - - offset); - return(Files[fnum].pos); -} - -/**************************************************************************** -read from a file -****************************************************************************/ -int read_file(int fnum,char *data,uint32 pos,int n) -{ - int ret=0,readret; - - if (!Files[fnum].can_write) - { - ret = read_predict(Files[fnum].fd_ptr->fd,pos,data,NULL,n); - - data += ret; - n -= ret; - pos += ret; - } - -#if USE_MMAP - if (Files[fnum].mmap_ptr) - { - int num = MIN(n,(int)(Files[fnum].mmap_size-pos)); - if (num > 0) - { - memcpy(data,Files[fnum].mmap_ptr+pos,num); - data += num; - pos += num; - n -= num; - ret += num; - } - } -#endif - - if (n <= 0) - return(ret); - - if (seek_file(fnum,pos) != pos) - { - DEBUG(3,("Failed to seek to %d\n",pos)); - return(ret); - } - - if (n > 0) { - readret = read(Files[fnum].fd_ptr->fd,data,n); - if (readret > 0) ret += readret; - } - - return(ret); -} - - -/**************************************************************************** -write to a file -****************************************************************************/ -int write_file(int fnum,char *data,int n) -{ - if (!Files[fnum].can_write) { - errno = EPERM; - return(0); - } - - if (!Files[fnum].modified) { - struct stat st; - Files[fnum].modified = True; - if (fstat(Files[fnum].fd_ptr->fd,&st) == 0) { - int dosmode = dos_mode(Files[fnum].cnum,Files[fnum].name,&st); - if (MAP_ARCHIVE(Files[fnum].cnum) && !IS_DOS_ARCHIVE(dosmode)) { - dos_chmod(Files[fnum].cnum,Files[fnum].name,dosmode | aARCH,&st); - } - } - } - - return(write_data(Files[fnum].fd_ptr->fd,data,n)); -} - - -/**************************************************************************** -load parameters specific to a connection/service -****************************************************************************/ -BOOL become_service(int cnum,BOOL do_chdir) -{ - extern char magic_char; - static int last_cnum = -1; - int snum; - - if (!OPEN_CNUM(cnum)) - { - last_cnum = -1; - return(False); - } - - Connections[cnum].lastused = smb_last_time; - - snum = SNUM(cnum); - - if (do_chdir && - ChDir(Connections[cnum].connectpath) != 0 && - ChDir(Connections[cnum].origpath) != 0) - { - DEBUG(0,("%s chdir (%s) failed cnum=%d\n",timestring(), - Connections[cnum].connectpath,cnum)); - return(False); - } - - if (cnum == last_cnum) - return(True); - - last_cnum = cnum; - - case_default = lp_defaultcase(snum); - case_preserve = lp_preservecase(snum); - short_case_preserve = lp_shortpreservecase(snum); - case_mangle = lp_casemangle(snum); - case_sensitive = lp_casesensitive(snum); - magic_char = lp_magicchar(snum); - use_mangled_map = (*lp_mangled_map(snum) ? True:False); - return(True); -} - - -/**************************************************************************** - find a service entry -****************************************************************************/ -int find_service(char *service) -{ - int iService; - - string_sub(service,"\\","/"); - - iService = lp_servicenumber(service); - - /* now handle the special case of a home directory */ - if (iService < 0) - { - char *phome_dir = get_home_dir(service); - DEBUG(3,("checking for home directory %s gave %s\n",service, - phome_dir?phome_dir:"(NULL)")); - if (phome_dir) - { - int iHomeService; - if ((iHomeService = lp_servicenumber(HOMES_NAME)) >= 0) - { - lp_add_home(service,iHomeService,phome_dir); - iService = lp_servicenumber(service); - } - } - } - - /* If we still don't have a service, attempt to add it as a printer. */ - if (iService < 0) - { - int iPrinterService; - - if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) - { - char *pszTemp; - - DEBUG(3,("checking whether %s is a valid printer name...\n", service)); - pszTemp = PRINTCAP; - if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) - { - DEBUG(3,("%s is a valid printer name\n", service)); - DEBUG(3,("adding %s as a printer service\n", service)); - lp_add_printer(service,iPrinterService); - iService = lp_servicenumber(service); - if (iService < 0) - DEBUG(0,("failed to add %s as a printer service!\n", service)); - } - else - DEBUG(3,("%s is not a valid printer name\n", service)); - } - } - - /* just possibly it's a default service? */ - if (iService < 0) - { - char *defservice = lp_defaultservice(); - if (defservice && *defservice && !strequal(defservice,service)) { - iService = find_service(defservice); - if (iService >= 0) { - string_sub(service,"_","/"); - iService = lp_add_service(service,iService); - } - } - } - - if (iService >= 0) - if (!VALID_SNUM(iService)) - { - DEBUG(0,("Invalid snum %d for %s\n",iService,service)); - iService = -1; - } - - if (iService < 0) - DEBUG(3,("find_service() failed to find service %s\n", service)); - - return (iService); -} - - -/**************************************************************************** - create an error packet from a cached error. -****************************************************************************/ -int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line) -{ - write_bmpx_struct *wbmpx = Files[fnum].wbmpx_ptr; - - int32 eclass = wbmpx->wr_errclass; - int32 err = wbmpx->wr_error; - - /* We can now delete the auxiliary struct */ - free((char *)wbmpx); - Files[fnum].wbmpx_ptr = NULL; - return error_packet(inbuf,outbuf,eclass,err,line); -} - - -struct -{ - int unixerror; - int smbclass; - int smbcode; -} unix_smb_errmap[] = -{ - {EPERM,ERRDOS,ERRnoaccess}, - {EACCES,ERRDOS,ERRnoaccess}, - {ENOENT,ERRDOS,ERRbadfile}, - {ENOTDIR,ERRDOS,ERRbadpath}, - {EIO,ERRHRD,ERRgeneral}, - {EBADF,ERRSRV,ERRsrverror}, - {EINVAL,ERRSRV,ERRsrverror}, - {EEXIST,ERRDOS,ERRfilexists}, - {ENFILE,ERRDOS,ERRnofids}, - {EMFILE,ERRDOS,ERRnofids}, - {ENOSPC,ERRHRD,ERRdiskfull}, -#ifdef EDQUOT - {EDQUOT,ERRHRD,ERRdiskfull}, -#endif -#ifdef ENOTEMPTY - {ENOTEMPTY,ERRDOS,ERRnoaccess}, -#endif -#ifdef EXDEV - {EXDEV,ERRDOS,ERRdiffdevice}, -#endif - {EROFS,ERRHRD,ERRnowrite}, - {0,0,0} -}; - -/**************************************************************************** - create an error packet from errno -****************************************************************************/ -int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line) -{ - int eclass=def_class; - int ecode=def_code; - int i=0; - - if (unix_ERR_class != SUCCESS) - { - eclass = unix_ERR_class; - ecode = unix_ERR_code; - unix_ERR_class = SUCCESS; - unix_ERR_code = 0; - } - else - { - while (unix_smb_errmap[i].smbclass != 0) - { - if (unix_smb_errmap[i].unixerror == errno) - { - eclass = unix_smb_errmap[i].smbclass; - ecode = unix_smb_errmap[i].smbcode; - break; - } - i++; - } - } - - return(error_packet(inbuf,outbuf,eclass,ecode,line)); -} - - -/**************************************************************************** - create an error packet. Normally called using the ERROR() macro -****************************************************************************/ -int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line) -{ - int outsize = set_message(outbuf,0,0,True); - int cmd; - cmd = CVAL(inbuf,smb_com); - - CVAL(outbuf,smb_rcls) = error_class; - SSVAL(outbuf,smb_err,error_code); - - DEBUG(3,("%s error packet at line %d cmd=%d (%s) eclass=%d ecode=%d\n", - timestring(), - line, - (int)CVAL(inbuf,smb_com), - smb_fn_name(CVAL(inbuf,smb_com)), - error_class, - error_code)); - - if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); - - return(outsize); -} - - -#ifndef SIGCLD_IGNORE -/**************************************************************************** -this prevents zombie child processes -****************************************************************************/ -static int sig_cld() -{ - static int depth = 0; - if (depth != 0) - { - DEBUG(0,("ERROR: Recursion in sig_cld? Perhaps you need `#define USE_WAITPID'?\n")); - depth=0; - return(0); - } - depth++; - - BlockSignals(True,SIGCLD); - DEBUG(5,("got SIGCLD\n")); - -#ifdef USE_WAITPID - while (sys_waitpid((pid_t)-1,(int *)NULL, WNOHANG) > 0); -#endif - - /* Stop zombies */ - /* Stevens, Adv. Unix Prog. says that on system V you must call - wait before reinstalling the signal handler, because the kernel - calls the handler from within the signal-call when there is a - child that has exited. This would lead to an infinite recursion - if done vice versa. */ - -#ifndef DONT_REINSTALL_SIG -#ifdef SIGCLD_IGNORE - signal(SIGCLD, SIG_IGN); -#else - signal(SIGCLD, SIGNAL_CAST sig_cld); -#endif -#endif - -#ifndef USE_WAITPID - while (wait3(WAIT3_CAST1 NULL, WNOHANG, WAIT3_CAST2 NULL) > 0); -#endif - depth--; - BlockSignals(False,SIGCLD); - return 0; -} -#endif - -/**************************************************************************** - this is called when the client exits abruptly - **************************************************************************/ -static int sig_pipe() -{ - extern int password_client; - BlockSignals(True,SIGPIPE); - - if (password_client != -1) { - DEBUG(3,("lost connection to password server\n")); - close(password_client); - password_client = -1; -#ifndef DONT_REINSTALL_SIG - signal(SIGPIPE, SIGNAL_CAST sig_pipe); -#endif - BlockSignals(False,SIGPIPE); - return 0; - } - - exit_server("Got sigpipe\n"); - return(0); -} - -/**************************************************************************** - open the socket communication -****************************************************************************/ -static BOOL open_sockets(BOOL is_daemon,int port) -{ - extern int Client; - - if (is_daemon) - { - int s; - struct sockaddr addr; - int in_addrlen = sizeof(addr); - - /* Stop zombies */ -#ifdef SIGCLD_IGNORE - signal(SIGCLD, SIG_IGN); -#else - signal(SIGCLD, SIGNAL_CAST sig_cld); -#endif - - /* open an incoming socket */ - s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address())); - if (s == -1) - return(False); - - /* ready to listen */ - if (listen(s, 5) == -1) - { - DEBUG(0,("listen: %s\n",strerror(errno))); - close(s); - return False; - } - - if(atexit_set == 0) - atexit(killkids); - - /* now accept incoming connections - forking a new process - for each incoming connection */ - DEBUG(2,("waiting for a connection\n")); - while (1) - { - Client = accept(s,&addr,&in_addrlen); - - if (Client == -1 && errno == EINTR) - continue; - - if (Client == -1) - { - DEBUG(0,("accept: %s\n",strerror(errno))); - continue; - } - -#ifdef NO_FORK_DEBUG -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); - signal(SIGCLD, SIGNAL_CAST SIG_DFL); -#endif - return True; -#else - if (Client != -1 && fork()==0) - { - /* Child code ... */ -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); - signal(SIGCLD, SIGNAL_CAST SIG_DFL); -#endif - /* close the listening socket */ - close(s); - - /* close our standard file descriptors */ - close_low_fds(); - am_parent = 0; - - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - - /* Reset global variables in util.c so that - client substitutions will be done correctly - in the process. - */ - reset_globals_after_fork(); - return True; - } - close(Client); /* The parent doesn't need this socket */ -#endif - } - } - else - { - /* We will abort gracefully when the client or remote system - goes away */ -#ifndef NO_SIGNAL_TEST - signal(SIGPIPE, SIGNAL_CAST sig_pipe); -#endif - Client = dup(0); - - /* close our standard file descriptors */ - close_low_fds(); - - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - } - - return True; -} - -/**************************************************************************** - process an smb from the client - split out from the process() code so - it can be used by the oplock break code. -****************************************************************************/ - -static void process_smb(char *inbuf, char *outbuf) -{ - extern int Client; - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (!check_access(-1)) { - /* send a negative session response "not listining on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG(1,("%s Connection denied from %s\n", - timestring(),client_addr())); - send_smb(Client,(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); - -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(inbuf)) - { - VT_Process(); - return; - } -#endif - - if (msg_type == 0) - show_msg(inbuf); - - nread = construct_reply(inbuf,outbuf,nread,max_send); - - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - send_smb(Client,outbuf); - } - trans_num++; -} - -/**************************************************************************** - open the oplock IPC socket communication -****************************************************************************/ -static BOOL open_oplock_ipc() -{ - struct sockaddr_in sock_name; - int len = sizeof(sock_name); - - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); - - /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK)); - if (oplock_sock == -1) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); - oplock_port = 0; - return(False); - } - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(oplock_sock); - oplock_sock = -1; - oplock_port = 0; - return False; - } - oplock_port = ntohs(sock_name.sin_port); - - DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", - getpid(), oplock_port)); - - return True; -} - -/**************************************************************************** - process an oplock break message. -****************************************************************************/ -static BOOL process_local_message(int sock, char *buffer, int buf_size) -{ - int32 msg_len; - int16 from_port; - char *msg_start; - - msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); - from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET); - - msg_start = &buffer[UDP_CMD_HEADER_LEN]; - - DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", - msg_len, from_port)); - - /* Switch on message command - currently OPLOCK_BREAK_CMD is the - only valid request. */ - - switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET)) - { - case OPLOCK_BREAK_CMD: - /* Ensure that the msg length is correct. */ - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); - return False; - } - { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - struct timeval tval; - struct sockaddr_in toaddr; - - tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); - tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); - - DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); - - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just return success in this case. - */ - - if(global_oplocks_open != 0) - { - if(oplock_break(dev, inode, &tval) == False) - { - DEBUG(0,("process_local_message: oplock break failed - \ -not returning udp message.\n")); - return False; - } - } - else - { - DEBUG(3,("process_local_message: oplock break requested with no outstanding \ -oplocks. Returning success.\n")); - } - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); - - bzero((char *)&toaddr,sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) - { - DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - remotepid, strerror(errno))); - return False; - } - - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, - from_port, dev, inode)); - - } - break; - /* - * Keep this as a debug case - eventually we can remove it. - */ - case 0x8001: - DEBUG(0,("process_local_message: Received unsolicited break \ -reply - dumping info.\n")); - - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: ubr: incorrect length for reply \ -(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); - return False; - } - - { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - - DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); - - } - return False; - - default: - DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", - (unsigned int)SVAL(msg_start,0))); - return False; - } - return True; -} - -/**************************************************************************** - Process an oplock break directly. -****************************************************************************/ -BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) -{ - extern int Client; - static char *inbuf = NULL; - static char *outbuf = NULL; - files_struct *fsp = NULL; - int fnum; - time_t start_time; - BOOL shutdown_server = False; - - DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); - - if(inbuf == NULL) - { - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(inbuf == NULL) { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; - } - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(outbuf == NULL) { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - free(inbuf); - inbuf = NULL; - return False; - } - } - - /* We need to search the file open table for the - entry containing this dev and inode, and ensure - we have an oplock on it. */ - for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++) - { - if(OPEN_FNUM(fnum)) - { - fsp = &Files[fnum]; - if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) && - (fsp->open_time.tv_sec == tval->tv_sec) && - (fsp->open_time.tv_usec == tval->tv_usec)) - break; - } - } - - if(fsp == NULL) - { - /* The file could have been closed in the meantime - return success. */ - DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ -allowing break to succeed.\n", dev, inode, fnum)); - return True; - } - - /* Ensure we have an oplock on the file */ - - /* There is a potential race condition in that an oplock could - have been broken due to another udp request, and yet there are - still oplock break messages being sent in the udp message - queue for this file. So return true if we don't have an oplock, - as we may have just freed it. - */ - - if(!fsp->granted_oplock) - { - DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ -Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode)); - return True; - } - - /* Now comes the horrid part. We must send an oplock break to the client, - and then process incoming messages until we get a close or oplock release. - */ - - /* Prepare the SMBlockingX message. */ - bzero(outbuf,smb_size); - set_message(outbuf,8,0,True); - - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - /* Change this when we have level II oplocks. */ - SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); - - send_smb(Client, outbuf); - - global_oplock_break = True; - - /* Process incoming messages. */ - - /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT - seconds we should just die.... */ - - start_time = time(NULL); - - while(OPEN_FNUM(fnum) && fsp->granted_oplock) - { - if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) - { - /* - * Die if we got an error. - */ - - if (smb_read_error == READ_EOF) - DEBUG(0,("oplock_break: end of file from client\n")); - - if (smb_read_error == READ_ERROR) - DEBUG(0,("oplock_break: receive_smb error (%s)\n", - strerror(errno))); - - if (smb_read_error == READ_TIMEOUT) - DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n", - OPLOCK_BREAK_TIMEOUT)); - - DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", fsp->name, fnum, dev, inode)); - shutdown_server = True; - break; - } - process_smb(inbuf, outbuf); - - /* We only need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - - /* - * Die if we go over the time limit. - */ - - if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) - { - DEBUG(0,("oplock_break: no break received from client within \ -%d seconds.\n", OPLOCK_BREAK_TIMEOUT)); - DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", fsp->name, fnum, dev, inode)); - shutdown_server = True; - break; - } - } - - /* - * If the client did not respond we must die. - */ - - if(shutdown_server) - { - DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n")); - close_sockets(); - close(oplock_sock); - exit_server("oplock break failure"); - } - - if(OPEN_FNUM(fnum)) - { - /* The lockingX reply will have removed the oplock flag - from the sharemode. */ - /* Paranoia.... */ - fsp->granted_oplock = False; - } - - global_oplocks_open--; - - /* Santity check - remove this later. JRA */ - if(global_oplocks_open < 0) - { - DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", - global_oplocks_open)); - exit_server("oplock_break: global_oplocks_open < 0"); - } - - DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open)); - - return True; -} - -/**************************************************************************** -Send an oplock break message to another smbd process. If the oplock is held -by the local smbd then call the oplock break function directly. -****************************************************************************/ - -BOOL request_oplock_break(min_share_mode_entry *share_entry, - uint32 dev, uint32 inode) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - int pid = getpid(); - - if(pid == share_entry->pid) - { - /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != oplock_port) - { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", pid, share_entry->op_port, oplock_port)); - return False; - } - - DEBUG(5,("request_oplock_break: breaking our own oplock\n")); - - /* Call oplock break direct. */ - return oplock_break(dev, inode, &share_entry->time); - } - - /* We need to send a OPLOCK_BREAK_CMD message to the - port in the share mode entry. */ - - SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); - SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); - SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); - SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); - SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); - - /* set the address and port */ - bzero((char *)&addr_out,sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \ -for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode)); - - if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) - { - DEBUG(0,("request_oplock_break: failed when sending a oplock break message \ -to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", - share_entry->pid, share_entry->op_port, dev, inode, - strerror(errno))); - return False; - } - - /* - * Now we must await the oplock broken message coming back - * from the target smbd process. Timeout if it fails to - * return in OPLOCK_BREAK_TIMEOUT seconds. - * While we get messages that aren't ours, loop. - */ - - while(1) - { - char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - int32 reply_msg_len; - int16 reply_from_port; - char *reply_msg_start; - - if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), - OPLOCK_BREAK_TIMEOUT * 1000) == False) - { - if(smb_read_error == READ_TIMEOUT) - DEBUG(0,("request_oplock_break: no response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid, - share_entry->op_port, dev, inode)); - else - DEBUG(0,("request_oplock_break: error in response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid, - share_entry->op_port, dev, inode, strerror(errno))); - return False; - } - - /* - * If the response we got was not an answer to our message, but - * was a completely different request, push it onto the pending - * udp message stack so that we can deal with it in the main loop. - * It may be another oplock break request to us. - */ - - /* - * Local note from JRA. There exists the possibility of a denial - * of service attack here by allowing non-root processes running - * on a local machine sending many of these pending messages to - * a smbd port. Currently I'm not sure how to restrict the messages - * I will queue (although I could add a limit to the queue) to - * those received by root processes only. There should be a - * way to make this bulletproof.... - */ - - reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); - reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); - - reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN]; - - if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) - { - /* Ignore it. */ - DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n")); - continue; - } - - if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) || - (reply_from_port != share_entry->op_port) || - (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], - &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0)) - { - DEBUG(3,("request_oplock_break: received other message whilst awaiting \ -oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", - share_entry->pid, share_entry->op_port, dev, inode)); - if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) - return False; - continue; - } - - break; - } - - DEBUG(3,("request_oplock_break: broke oplock.\n")); - - return True; -} - -/**************************************************************************** -check if a snum is in use -****************************************************************************/ -BOOL snum_used(int snum) -{ - int i; - for (i=0;i<MAX_CONNECTIONS;i++) - if (OPEN_CNUM(i) && (SNUM(i) == snum)) - return(True); - return(False); -} - -/**************************************************************************** - reload the services file - **************************************************************************/ -BOOL reload_services(BOOL test) -{ - BOOL ret; - - if (lp_loaded()) - { - pstring fname; - pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) - { - pstrcpy(servicesf,fname); - test = False; - } - } - - reopen_logs(); - - if (test && !lp_file_list_changed()) - return(True); - - lp_killunused(snum_used); - - ret = lp_load(servicesf,False); - - /* perhaps the config filename is now set */ - if (!test) - reload_services(True); - - reopen_logs(); - - load_interfaces(); - - { - extern int Client; - if (Client != -1) { - set_socket_options(Client,"SO_KEEPALIVE"); - set_socket_options(Client,user_socket_options); - } - } - - create_mangled_stack(lp_mangledstack()); - - /* this forces service parameters to be flushed */ - become_service(-1,True); - - return(ret); -} - - - -/**************************************************************************** -this prevents zombie child processes -****************************************************************************/ -static int sig_hup() -{ - BlockSignals(True,SIGHUP); - DEBUG(0,("Got SIGHUP\n")); - reload_services(False); -#ifndef DONT_REINSTALL_SIG - signal(SIGHUP,SIGNAL_CAST sig_hup); -#endif - BlockSignals(False,SIGHUP); - return(0); -} - -/**************************************************************************** -Setup the groups a user belongs to. -****************************************************************************/ -int setup_groups(char *user, int uid, int gid, int *p_ngroups, - int **p_igroups, gid_t **p_groups) -{ - if (-1 == initgroups(user,gid)) - { - if (getuid() == 0) - { - DEBUG(0,("Unable to initgroups!\n")); - if (gid < 0 || gid > 16000 || uid < 0 || uid > 16000) - DEBUG(0,("This is probably a problem with the account %s\n",user)); - } - } - else - { - int i,ngroups; - int *igroups; - gid_t grp = 0; - ngroups = getgroups(0,&grp); - if (ngroups <= 0) - ngroups = 32; - igroups = (int *)malloc(sizeof(int)*ngroups); - for (i=0;i<ngroups;i++) - igroups[i] = 0x42424242; - ngroups = getgroups(ngroups,(gid_t *)igroups); - - if (igroups[0] == 0x42424242) - ngroups = 0; - - *p_ngroups = ngroups; - - /* The following bit of code is very strange. It is due to the - fact that some OSes use int* and some use gid_t* for - getgroups, and some (like SunOS) use both, one in prototypes, - and one in man pages and the actual code. Thus we detect it - dynamically using some very ugly code */ - if (ngroups > 0) - { - /* does getgroups return ints or gid_t ?? */ - static BOOL groups_use_ints = True; - - if (groups_use_ints && - ngroups == 1 && - SVAL(igroups,2) == 0x4242) - groups_use_ints = False; - - for (i=0;groups_use_ints && i<ngroups;i++) - if (igroups[i] == 0x42424242) - groups_use_ints = False; - - if (groups_use_ints) - { - *p_igroups = igroups; - *p_groups = (gid_t *)igroups; - } - else - { - gid_t *groups = (gid_t *)igroups; - igroups = (int *)malloc(sizeof(int)*ngroups); - for (i=0;i<ngroups;i++) - igroups[i] = groups[i]; - *p_igroups = igroups; - *p_groups = (gid_t *)groups; - } - } - DEBUG(3,("%s is in %d groups\n",user,ngroups)); - for (i=0;i<ngroups;i++) - DEBUG(3,("%d ",igroups[i])); - DEBUG(3,("\n")); - } - return 0; -} - -/**************************************************************************** - make a connection to a service -****************************************************************************/ -int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid) -{ - int cnum; - int snum; - struct passwd *pass = NULL; - connection_struct *pcon; - BOOL guest = False; - BOOL force = False; - static BOOL first_connection = True; - - strlower(service); - - snum = find_service(service); - if (snum < 0) - { - if (strequal(service,"IPC$")) - { - DEBUG(3,("%s refusing IPC connection\n",timestring())); - return(-3); - } - - DEBUG(0,("%s couldn't find service %s\n",timestring(),service)); - return(-2); - } - - if (strequal(service,HOMES_NAME)) - { - if (*user && Get_Pwnam(user,True)) - return(make_connection(user,user,password,pwlen,dev,vuid)); - - if (validated_username(vuid)) - { - strcpy(user,validated_username(vuid)); - return(make_connection(user,user,password,pwlen,dev,vuid)); - } - } - - if (!lp_snum_ok(snum) || !check_access(snum)) { - return(-4); - } - - /* you can only connect to the IPC$ service as an ipc device */ - if (strequal(service,"IPC$")) - strcpy(dev,"IPC"); - - if (*dev == '?' || !*dev) - { - if (lp_print_ok(snum)) - strcpy(dev,"LPT1:"); - else - strcpy(dev,"A:"); - } - - /* if the request is as a printer and you can't print then refuse */ - strupper(dev); - if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) { - DEBUG(1,("Attempt to connect to non-printer as a printer\n")); - return(-6); - } - - /* lowercase the user name */ - strlower(user); - - /* add it as a possible user name */ - add_session_user(service); - - /* shall we let them in? */ - if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) - { - DEBUG(2,("%s invalid username/password for %s\n",timestring(),service)); - return(-1); - } - - cnum = find_free_connection(str_checksum(service) + str_checksum(user)); - if (cnum < 0) - { - DEBUG(0,("%s couldn't find free connection\n",timestring())); - return(-1); - } - - pcon = &Connections[cnum]; - bzero((char *)pcon,sizeof(*pcon)); - - /* find out some info about the user */ - pass = Get_Pwnam(user,True); - - if (pass == NULL) - { - DEBUG(0,("%s couldn't find account %s\n",timestring(),user)); - return(-7); - } - - pcon->read_only = lp_readonly(snum); - - { - pstring list; - StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); - - if (user_in_list(user,list)) - pcon->read_only = True; - - StrnCpy(list,lp_writelist(snum),sizeof(pstring)-1); - string_sub(list,"%S",service); - - if (user_in_list(user,list)) - pcon->read_only = False; - } - - /* admin user check */ - - /* JRA - original code denied admin user if the share was - marked read_only. Changed as I don't think this is needed, - but old code left in case there is a problem here. - */ - if (user_in_list(user,lp_admin_users(snum)) -#if 0 - && !pcon->read_only) -#else - ) -#endif - { - pcon->admin_user = True; - DEBUG(0,("%s logged in as admin user (root privileges)\n",user)); - } - else - pcon->admin_user = False; - - pcon->force_user = force; - pcon->vuid = vuid; - pcon->uid = pass->pw_uid; - pcon->gid = pass->pw_gid; - pcon->num_files_open = 0; - pcon->lastused = time(NULL); - pcon->service = snum; - pcon->used = True; - pcon->printer = (strncmp(dev,"LPT",3) == 0); - pcon->ipc = (strncmp(dev,"IPC",3) == 0); - pcon->dirptr = NULL; - pcon->veto_list = NULL; - pcon->hide_list = NULL; - string_set(&pcon->dirpath,""); - string_set(&pcon->user,user); - -#if HAVE_GETGRNAM - if (*lp_force_group(snum)) - { - struct group *gptr; - pstring gname; - - StrnCpy(gname,lp_force_group(snum),sizeof(pstring)-1); - /* default service may be a group name */ - string_sub(gname,"%S",service); - gptr = (struct group *)getgrnam(gname); - - if (gptr) - { - pcon->gid = gptr->gr_gid; - DEBUG(3,("Forced group %s\n",gname)); - } - else - DEBUG(1,("Couldn't find group %s\n",gname)); - } -#endif - - if (*lp_force_user(snum)) - { - struct passwd *pass2; - fstring fuser; - fstrcpy(fuser,lp_force_user(snum)); - pass2 = (struct passwd *)Get_Pwnam(fuser,True); - if (pass2) - { - pcon->uid = pass2->pw_uid; - string_set(&pcon->user,fuser); - fstrcpy(user,fuser); - pcon->force_user = True; - DEBUG(3,("Forced user %s\n",fuser)); - } - else - DEBUG(1,("Couldn't find user %s\n",fuser)); - } - - { - pstring s; - pstrcpy(s,lp_pathname(snum)); - standard_sub(cnum,s); - string_set(&pcon->connectpath,s); - DEBUG(3,("Connect path is %s\n",s)); - } - - /* groups stuff added by ih */ - pcon->ngroups = 0; - pcon->groups = NULL; - - if (!IS_IPC(cnum)) - { - /* Find all the groups this uid is in and store them. Used by become_user() */ - setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups); - - /* check number of connections */ - if (!claim_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum)),False)) - { - DEBUG(1,("too many connections - rejected\n")); - return(-8); - } - - if (lp_status(SNUM(cnum))) - claim_connection(cnum,"STATUS.",MAXSTATUS,first_connection); - - first_connection = False; - } /* IS_IPC */ - - pcon->open = True; - - /* execute any "root preexec = " line */ - if (*lp_rootpreexec(SNUM(cnum))) - { - pstring cmd; - pstrcpy(cmd,lp_rootpreexec(SNUM(cnum))); - standard_sub(cnum,cmd); - DEBUG(5,("cmd=%s\n",cmd)); - smbrun(cmd,NULL,False); - } - - if (!become_user(cnum,pcon->vuid)) - { - DEBUG(0,("Can't become connected user!\n")); - pcon->open = False; - if (!IS_IPC(cnum)) { - yield_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - } - return(-1); - } - - if (ChDir(pcon->connectpath) != 0) - { - DEBUG(0,("Can't change directory to %s (%s)\n", - pcon->connectpath,strerror(errno))); - pcon->open = False; - unbecome_user(); - if (!IS_IPC(cnum)) { - yield_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum))); - if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - } - return(-5); - } - - string_set(&pcon->origpath,pcon->connectpath); - -#if SOFTLINK_OPTIMISATION - /* resolve any soft links early */ - { - pstring s; - pstrcpy(s,pcon->connectpath); - GetWd(s); - string_set(&pcon->connectpath,s); - ChDir(pcon->connectpath); - } -#endif - - num_connections_open++; - add_session_user(user); - - /* execute any "preexec = " line */ - if (*lp_preexec(SNUM(cnum))) - { - pstring cmd; - pstrcpy(cmd,lp_preexec(SNUM(cnum))); - standard_sub(cnum,cmd); - smbrun(cmd,NULL,False); - } - - /* we've finished with the sensitive stuff */ - unbecome_user(); - - /* Add veto/hide lists */ - if (!IS_IPC(cnum) && !IS_PRINT(cnum)) - { - set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum))); - set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum))); - } - - { - DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) connect to service %s as user %s (uid=%d,gid=%d) (pid %d)\n", - timestring(), - remote_machine, - client_addr(), - lp_servicename(SNUM(cnum)),user, - pcon->uid, - pcon->gid, - (int)getpid())); - } - - return(cnum); -} - - -/**************************************************************************** - find first available file slot -****************************************************************************/ -int find_free_file(void ) -{ - int i; - /* we start at 1 here for an obscure reason I can't now remember, - but I think is important :-) */ - for (i=1;i<MAX_OPEN_FILES;i++) - if (!Files[i].open) - return(i); - DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n")); - return(-1); -} - -/**************************************************************************** - find first available connection slot, starting from a random position. -The randomisation stops problems with the server dieing and clients -thinking the server is still available. -****************************************************************************/ -static int find_free_connection(int hash ) -{ - int i; - BOOL used=False; - hash = (hash % (MAX_CONNECTIONS-2))+1; - - again: - - for (i=hash+1;i!=hash;) - { - if (!Connections[i].open && Connections[i].used == used) - { - DEBUG(3,("found free connection number %d\n",i)); - return(i); - } - i++; - if (i == MAX_CONNECTIONS) - i = 1; - } - - if (!used) - { - used = !used; - goto again; - } - - DEBUG(1,("ERROR! Out of connection structures\n")); - return(-1); -} - - -/**************************************************************************** -reply for the core protocol -****************************************************************************/ -int reply_corep(char *outbuf) -{ - int outsize = set_message(outbuf,1,0,True); - - Protocol = PROTOCOL_CORE; - - return outsize; -} - - -/**************************************************************************** -reply for the coreplus protocol -****************************************************************************/ -int reply_coreplus(char *outbuf) -{ - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int outsize = set_message(outbuf,13,0,True); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support - readbraw and writebraw (possibly) */ - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */ - - Protocol = PROTOCOL_COREPLUS; - - return outsize; -} - - -/**************************************************************************** -reply for the lanman 1.0 protocol -****************************************************************************/ -int reply_lanman1(char *outbuf) -{ - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int secword=0; - BOOL doencrypt = SMBENCRYPT(); - time_t t = time(NULL); - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); - - if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - set_message(outbuf,13,doencrypt?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - generate_next_challenge(smb_buf(outbuf)); - - Protocol = PROTOCOL_LANMAN1; - - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); - if (doencrypt) set_challenge(smb_buf(outbuf)); - } - - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */ - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support - readbraw writebraw (possibly) */ - SIVAL(outbuf,smb_vwv6,getpid()); - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - - put_dos_date(outbuf,smb_vwv8,t); - - return (smb_len(outbuf)+4); -} - - -/**************************************************************************** -reply for the lanman 2.0 protocol -****************************************************************************/ -int reply_lanman2(char *outbuf) -{ - int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0); - int secword=0; - BOOL doencrypt = SMBENCRYPT(); - time_t t = time(NULL); - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); - - if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - set_message(outbuf,13,doencrypt?8:0,True); - SSVAL(outbuf,smb_vwv1,secword); - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - generate_next_challenge(smb_buf(outbuf)); - - SIVAL(outbuf,smb_vwv6,getpid()); - - Protocol = PROTOCOL_LANMAN2; - - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); - if (doencrypt) set_challenge(smb_buf(outbuf)); - } - - CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ - SSVAL(outbuf,smb_vwv2,max_recv); - SSVAL(outbuf,smb_vwv3,lp_maxmux()); - SSVAL(outbuf,smb_vwv4,1); - SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */ - SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60); - put_dos_date(outbuf,smb_vwv8,t); - - return (smb_len(outbuf)+4); -} - - -/**************************************************************************** -reply for the nt protocol -****************************************************************************/ -int reply_nt1(char *outbuf) -{ - /* dual names + lock_and_read + nt SMBs + remote API calls */ - int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ; -/* - other valid capabilities which we may support at some time... - CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; - CAP_LARGE_FILES|CAP_LARGE_READX| - CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; - */ - - int secword=0; - BOOL doencrypt = SMBENCRYPT(); - time_t t = time(NULL); - int data_len; - int encrypt_len; - char challenge_len = 8; - /* We need to save and restore this as it can be destroyed - if we call another server if security=server - Thanks to Paul Nelson @ Thursby for pointing this out. - */ - uint16 mid = SVAL(outbuf, smb_mid); - - if (lp_readraw() && lp_writeraw()) - { - capabilities |= CAP_RAW_MODE; - } - - if (lp_security()>=SEC_USER) secword |= 1; - if (doencrypt) secword |= 2; - - /* decide where (if) to put the encryption challenge, and - follow it with the OEM'd domain name - */ - encrypt_len = doencrypt?challenge_len:0; -#if UNICODE - data_len = encrypt_len + 2*(strlen(myworkgroup)+1); -#else - data_len = encrypt_len + strlen(myworkgroup) + 1; -#endif - - set_message(outbuf,17,data_len,True); - -#if UNICODE - /* put the OEM'd domain name */ - PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup); -#else - strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup); -#endif - - CVAL(outbuf,smb_vwv1) = secword; - /* Create a token value and add it to the outgoing packet. */ - if (doencrypt) - { - generate_next_challenge(smb_buf(outbuf)); - - /* Tell the nt machine how long the challenge is. */ - SSVALS(outbuf,smb_vwv16+1,challenge_len); - } - - Protocol = PROTOCOL_NT1; - - if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { - DEBUG(3,("using password server validation\n")); - if (doencrypt) set_challenge(smb_buf(outbuf)); - } - - SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ - SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */ - SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */ - SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */ - SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */ - SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */ - SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */ - put_long_date(outbuf+smb_vwv11+1,t); - SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60); - SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */ - - return (smb_len(outbuf)+4); -} - -/* these are the protocol lists used for auto architecture detection: - -WinNT 3.51: -protocol [PC NETWORK PROGRAM 1.0] -protocol [XENIX CORE] -protocol [MICROSOFT NETWORKS 1.03] -protocol [LANMAN1.0] -protocol [Windows for Workgroups 3.1a] -protocol [LM1.2X002] -protocol [LANMAN2.1] -protocol [NT LM 0.12] - -Win95: -protocol [PC NETWORK PROGRAM 1.0] -protocol [XENIX CORE] -protocol [MICROSOFT NETWORKS 1.03] -protocol [LANMAN1.0] -protocol [Windows for Workgroups 3.1a] -protocol [LM1.2X002] -protocol [LANMAN2.1] -protocol [NT LM 0.12] - -OS/2: -protocol [PC NETWORK PROGRAM 1.0] -protocol [XENIX CORE] -protocol [LANMAN1.0] -protocol [LM1.2X002] -protocol [LANMAN2.1] -*/ - -/* - * Modified to recognize the architecture of the remote machine better. - * - * This appears to be the matrix of which protocol is used by which - * MS product. - Protocol WfWg Win95 WinNT OS/2 - PC NETWORK PROGRAM 1.0 1 1 1 1 - XENIX CORE 2 2 - MICROSOFT NETWORKS 3.0 2 2 - DOS LM1.2X002 3 3 - MICROSOFT NETWORKS 1.03 3 - DOS LANMAN2.1 4 4 - LANMAN1.0 4 3 - Windows for Workgroups 3.1a 5 5 5 - LM1.2X002 6 4 - LANMAN2.1 7 5 - NT LM 0.12 6 8 - * - * tim@fsg.com 09/29/95 - */ - -#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */ -#define ARCH_WIN95 0x2 -#define ARCH_OS2 0xC /* Again OS/2 is like NT */ -#define ARCH_WINNT 0x8 -#define ARCH_SAMBA 0x10 - -#define ARCH_ALL 0x1F - -/* List of supported protocols, most desired first */ -struct { - char *proto_name; - char *short_name; - int (*proto_reply_fn)(char *); - int protocol_level; -} supported_protocols[] = { - {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, - {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, - {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, - {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, - {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1}, - {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS}, - {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE}, - {NULL,NULL}, -}; - - -/**************************************************************************** - reply to a negprot -****************************************************************************/ -static int reply_negprot(char *inbuf,char *outbuf) -{ - int outsize = set_message(outbuf,1,0,True); - int Index=0; - int choice= -1; - int protocol; - char *p; - int bcc = SVAL(smb_buf(inbuf),-2); - int arch = ARCH_ALL; - - p = smb_buf(inbuf)+1; - while (p < (smb_buf(inbuf) + bcc)) - { - Index++; - DEBUG(3,("Requested protocol [%s]\n",p)); - if (strcsequal(p,"Windows for Workgroups 3.1a")) - arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT ); - else if (strcsequal(p,"DOS LM1.2X002")) - arch &= ( ARCH_WFWG | ARCH_WIN95 ); - else if (strcsequal(p,"DOS LANMAN2.1")) - arch &= ( ARCH_WFWG | ARCH_WIN95 ); - else if (strcsequal(p,"NT LM 0.12")) - arch &= ( ARCH_WIN95 | ARCH_WINNT ); - else if (strcsequal(p,"LANMAN2.1")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"LM1.2X002")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"MICROSOFT NETWORKS 1.03")) - arch &= ARCH_WINNT; - else if (strcsequal(p,"XENIX CORE")) - arch &= ( ARCH_WINNT | ARCH_OS2 ); - else if (strcsequal(p,"Samba")) { - arch = ARCH_SAMBA; - break; - } - - p += strlen(p) + 2; - } - - switch ( arch ) { - case ARCH_SAMBA: - set_remote_arch(RA_SAMBA); - break; - case ARCH_WFWG: - set_remote_arch(RA_WFWG); - break; - case ARCH_WIN95: - set_remote_arch(RA_WIN95); - break; - case ARCH_WINNT: - set_remote_arch(RA_WINNT); - break; - case ARCH_OS2: - set_remote_arch(RA_OS2); - break; - default: - set_remote_arch(RA_UNKNOWN); - break; - } - - /* possibly reload - change of architecture */ - reload_services(True); - - /* a special case to stop password server loops */ - if (Index == 1 && strequal(remote_machine,myhostname) && - lp_security()==SEC_SERVER) - exit_server("Password server loop!"); - - /* Check for protocols, most desirable first */ - for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) - { - p = smb_buf(inbuf)+1; - Index = 0; - if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level) - while (p < (smb_buf(inbuf) + bcc)) - { - if (strequal(p,supported_protocols[protocol].proto_name)) - choice = Index; - Index++; - p += strlen(p) + 2; - } - if(choice != -1) - break; - } - - SSVAL(outbuf,smb_vwv0,choice); - if(choice != -1) { - extern fstring remote_proto; - fstrcpy(remote_proto,supported_protocols[protocol].short_name); - reload_services(True); - outsize = supported_protocols[protocol].proto_reply_fn(outbuf); - DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name)); - } - else { - DEBUG(0,("No protocol supported !\n")); - } - SSVAL(outbuf,smb_vwv0,choice); - - DEBUG(5,("%s negprot index=%d\n",timestring(),choice)); - - return(outsize); -} - - -/**************************************************************************** -close all open files for a connection -****************************************************************************/ -static void close_open_files(int cnum) -{ - int i; - for (i=0;i<MAX_OPEN_FILES;i++) - if( Files[i].cnum == cnum && Files[i].open) { - close_file(i); - } -} - - - -/**************************************************************************** -close a cnum -****************************************************************************/ -void close_cnum(int cnum, uint16 vuid) -{ - DirCacheFlush(SNUM(cnum)); - - unbecome_user(); - - if (!OPEN_CNUM(cnum)) - { - DEBUG(0,("Can't close cnum %d\n",cnum)); - return; - } - - DEBUG(IS_IPC(cnum)?3:1,("%s %s (%s) closed connection to service %s\n", - timestring(), - remote_machine,client_addr(), - lp_servicename(SNUM(cnum)))); - - yield_connection(cnum, - lp_servicename(SNUM(cnum)), - lp_max_connections(SNUM(cnum))); - - if (lp_status(SNUM(cnum))) - yield_connection(cnum,"STATUS.",MAXSTATUS); - - close_open_files(cnum); - dptr_closecnum(cnum); - - /* execute any "postexec = " line */ - if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid)) - { - pstring cmd; - strcpy(cmd,lp_postexec(SNUM(cnum))); - standard_sub(cnum,cmd); - smbrun(cmd,NULL,False); - unbecome_user(); - } - - unbecome_user(); - /* execute any "root postexec = " line */ - if (*lp_rootpostexec(SNUM(cnum))) - { - pstring cmd; - strcpy(cmd,lp_rootpostexec(SNUM(cnum))); - standard_sub(cnum,cmd); - smbrun(cmd,NULL,False); - } - - Connections[cnum].open = False; - num_connections_open--; - if (Connections[cnum].ngroups && Connections[cnum].groups) - { - if (Connections[cnum].igroups != (int *)Connections[cnum].groups) - free(Connections[cnum].groups); - free(Connections[cnum].igroups); - Connections[cnum].groups = NULL; - Connections[cnum].igroups = NULL; - Connections[cnum].ngroups = 0; - } - - free_namearray(Connections[cnum].veto_list); - free_namearray(Connections[cnum].hide_list); - - string_set(&Connections[cnum].user,""); - string_set(&Connections[cnum].dirpath,""); - string_set(&Connections[cnum].connectpath,""); -} - - -/**************************************************************************** -simple routines to do connection counting -****************************************************************************/ -BOOL yield_connection(int cnum,char *name,int max_connections) -{ - struct connect_record crec; - pstring fname; - FILE *f; - int mypid = getpid(); - int i; - - DEBUG(3,("Yielding connection to %d %s\n",cnum,name)); - - if (max_connections <= 0) - return(True); - - bzero(&crec,sizeof(crec)); - - pstrcpy(fname,lp_lockdir()); - standard_sub(cnum,fname); - trim_string(fname,"","/"); - - strcat(fname,"/"); - strcat(fname,name); - strcat(fname,".LCK"); - - f = fopen(fname,"r+"); - if (!f) - { - DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno))); - return(False); - } - - fseek(f,0,SEEK_SET); - - /* find a free spot */ - for (i=0;i<max_connections;i++) - { - if (fread(&crec,sizeof(crec),1,f) != 1) - { - DEBUG(2,("Entry not found in lock file %s\n",fname)); - fclose(f); - return(False); - } - if (crec.pid == mypid && crec.cnum == cnum) - break; - } - - if (crec.pid != mypid || crec.cnum != cnum) - { - fclose(f); - DEBUG(2,("Entry not found in lock file %s\n",fname)); - return(False); - } - - bzero((void *)&crec,sizeof(crec)); - - /* remove our mark */ - if (fseek(f,i*sizeof(crec),SEEK_SET) != 0 || - fwrite(&crec,sizeof(crec),1,f) != 1) - { - DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno))); - fclose(f); - return(False); - } - - DEBUG(3,("Yield successful\n")); - - fclose(f); - return(True); -} - - -/**************************************************************************** -simple routines to do connection counting -****************************************************************************/ -BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear) -{ - struct connect_record crec; - pstring fname; - FILE *f; - int snum = SNUM(cnum); - int i,foundi= -1; - int total_recs; - - if (max_connections <= 0) - return(True); - - DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections)); - - pstrcpy(fname,lp_lockdir()); - standard_sub(cnum,fname); - trim_string(fname,"","/"); - - if (!directory_exist(fname,NULL)) - mkdir(fname,0755); - - strcat(fname,"/"); - strcat(fname,name); - strcat(fname,".LCK"); - - if (!file_exist(fname,NULL)) - { - int oldmask = umask(022); - f = fopen(fname,"w"); - if (f) fclose(f); - umask(oldmask); - } - - total_recs = file_size(fname) / sizeof(crec); - - f = fopen(fname,"r+"); - - if (!f) - { - DEBUG(1,("couldn't open lock file %s\n",fname)); - return(False); - } - - /* find a free spot */ - for (i=0;i<max_connections;i++) - { - - if (i>=total_recs || - fseek(f,i*sizeof(crec),SEEK_SET) != 0 || - fread(&crec,sizeof(crec),1,f) != 1) - { - if (foundi < 0) foundi = i; - break; - } - - if (Clear && crec.pid && !process_exists(crec.pid)) - { - fseek(f,i*sizeof(crec),SEEK_SET); - bzero((void *)&crec,sizeof(crec)); - fwrite(&crec,sizeof(crec),1,f); - if (foundi < 0) foundi = i; - continue; - } - if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) - { - foundi=i; - if (!Clear) break; - } - } - - if (foundi < 0) - { - DEBUG(3,("no free locks in %s\n",fname)); - fclose(f); - return(False); - } - - /* fill in the crec */ - bzero((void *)&crec,sizeof(crec)); - crec.magic = 0x280267; - crec.pid = getpid(); - crec.cnum = cnum; - crec.uid = Connections[cnum].uid; - crec.gid = Connections[cnum].gid; - StrnCpy(crec.name,lp_servicename(snum),sizeof(crec.name)-1); - crec.start = time(NULL); - - StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1); - StrnCpy(crec.addr,client_addr(),sizeof(crec.addr)-1); - - /* make our mark */ - if (fseek(f,foundi*sizeof(crec),SEEK_SET) != 0 || - fwrite(&crec,sizeof(crec),1,f) != 1) - { - fclose(f); - return(False); - } - - fclose(f); - return(True); -} - -#if DUMP_CORE -/******************************************************************* -prepare to dump a core file - carefully! -********************************************************************/ -static BOOL dump_core(void) -{ - char *p; - pstring dname; - pstrcpy(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 - -/**************************************************************************** -exit the server -****************************************************************************/ -void exit_server(char *reason) -{ - static int firsttime=1; - int i; - - if (!firsttime) exit(0); - firsttime = 0; - - unbecome_user(); - DEBUG(2,("Closing connections\n")); - for (i=0;i<MAX_CONNECTIONS;i++) - if (Connections[i].open) - close_cnum(i,(uint16)-1); -#ifdef DFS_AUTH - if (dcelogin_atmost_once) - dfs_unlogin(); -#endif - if (!reason) { - int oldlevel = DEBUGLEVEL; - DEBUGLEVEL = 10; - DEBUG(0,("Last message was %s\n",smb_fn_name(last_message))); - if (last_inbuf) - show_msg(last_inbuf); - DEBUGLEVEL = oldlevel; - DEBUG(0,("===============================================================\n")); -#if DUMP_CORE - if (dump_core()) return; -#endif - } - -#ifdef FAST_SHARE_MODES - stop_share_mode_mgmt(); -#endif /* FAST_SHARE_MODES */ - - DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:"")); - exit(0); -} - -/**************************************************************************** -do some standard substitutions in a string -****************************************************************************/ -void standard_sub(int cnum,char *str) -{ - if (VALID_CNUM(cnum)) { - char *p, *s, *home; - - for ( s=str ; (p=strchr(s, '%')) != NULL ; s=p ) { - switch (*(p+1)) { - case 'H' : if ((home = get_home_dir(Connections[cnum].user))!=NULL) - string_sub(p,"%H",home); - else - p += 2; - break; - case 'P' : string_sub(p,"%P",Connections[cnum].connectpath); break; - case 'S' : string_sub(p,"%S",lp_servicename(Connections[cnum].service)); break; - case 'g' : string_sub(p,"%g",gidtoname(Connections[cnum].gid)); break; - case 'u' : string_sub(p,"%u",Connections[cnum].user); break; - case '\0' : p++; break; /* don't run off the end of the string */ - default : p+=2; break; - } - } - } - standard_sub_basic(str); -} - -/* -These flags determine some of the permissions required to do an operation - -Note that I don't set NEED_WRITE on some write operations because they -are used by some brain-dead clients when printing, and I don't want to -force write permissions on print services. -*/ -#define AS_USER (1<<0) -#define NEED_WRITE (1<<1) -#define TIME_INIT (1<<2) -#define CAN_IPC (1<<3) -#define AS_GUEST (1<<5) - - -/* - define a list of possible SMB messages and their corresponding - functions. Any message that has a NULL function is unimplemented - - please feel free to contribute implementations! -*/ -struct smb_message_struct -{ - int code; - char *name; - int (*fn)(); - int flags; -#if PROFILING - unsigned long time; -#endif -} - smb_messages[] = { - - /* CORE PROTOCOL */ - - {SMBnegprot,"SMBnegprot",reply_negprot,0}, - {SMBtcon,"SMBtcon",reply_tcon,0}, - {SMBtdis,"SMBtdis",reply_tdis,0}, - {SMBexit,"SMBexit",reply_exit,0}, - {SMBioctl,"SMBioctl",reply_ioctl,0}, - {SMBecho,"SMBecho",reply_echo,0}, - {SMBsesssetupX,"SMBsesssetupX",reply_sesssetup_and_X,0}, - {SMBtconX,"SMBtconX",reply_tcon_and_X,0}, - {SMBulogoffX, "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ - {SMBgetatr,"SMBgetatr",reply_getatr,AS_USER}, - {SMBsetatr,"SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, - {SMBchkpth,"SMBchkpth",reply_chkpth,AS_USER}, - {SMBsearch,"SMBsearch",reply_search,AS_USER}, - {SMBopen,"SMBopen",reply_open,AS_USER}, - - /* note that SMBmknew and SMBcreate are deliberately overloaded */ - {SMBcreate,"SMBcreate",reply_mknew,AS_USER}, - {SMBmknew,"SMBmknew",reply_mknew,AS_USER}, - - {SMBunlink,"SMBunlink",reply_unlink,AS_USER | NEED_WRITE}, - {SMBread,"SMBread",reply_read,AS_USER}, - {SMBwrite,"SMBwrite",reply_write,AS_USER}, - {SMBclose,"SMBclose",reply_close,AS_USER | CAN_IPC}, - {SMBmkdir,"SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, - {SMBrmdir,"SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, - {SMBdskattr,"SMBdskattr",reply_dskattr,AS_USER}, - {SMBmv,"SMBmv",reply_mv,AS_USER | NEED_WRITE}, - - /* this is a Pathworks specific call, allowing the - changing of the root path */ - {pSETDIR,"pSETDIR",reply_setdir,AS_USER}, - - {SMBlseek,"SMBlseek",reply_lseek,AS_USER}, - {SMBflush,"SMBflush",reply_flush,AS_USER}, - {SMBctemp,"SMBctemp",reply_ctemp,AS_USER}, - {SMBsplopen,"SMBsplopen",reply_printopen,AS_USER}, - {SMBsplclose,"SMBsplclose",reply_printclose,AS_USER}, - {SMBsplretq,"SMBsplretq",reply_printqueue,AS_USER|AS_GUEST}, - {SMBsplwr,"SMBsplwr",reply_printwrite,AS_USER}, - {SMBlock,"SMBlock",reply_lock,AS_USER}, - {SMBunlock,"SMBunlock",reply_unlock,AS_USER}, - - /* CORE+ PROTOCOL FOLLOWS */ - - {SMBreadbraw,"SMBreadbraw",reply_readbraw,AS_USER}, - {SMBwritebraw,"SMBwritebraw",reply_writebraw,AS_USER}, - {SMBwriteclose,"SMBwriteclose",reply_writeclose,AS_USER}, - {SMBlockread,"SMBlockread",reply_lockread,AS_USER}, - {SMBwriteunlock,"SMBwriteunlock",reply_writeunlock,AS_USER}, - - /* LANMAN1.0 PROTOCOL FOLLOWS */ - - {SMBreadBmpx,"SMBreadBmpx",reply_readbmpx,AS_USER}, - {SMBreadBs,"SMBreadBs",NULL,AS_USER}, - {SMBwriteBmpx,"SMBwriteBmpx",reply_writebmpx,AS_USER}, - {SMBwriteBs,"SMBwriteBs",reply_writebs,AS_USER}, - {SMBwritec,"SMBwritec",NULL,AS_USER}, - {SMBsetattrE,"SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE}, - {SMBgetattrE,"SMBgetattrE",reply_getattrE,AS_USER}, - {SMBtrans,"SMBtrans",reply_trans,AS_USER | CAN_IPC}, - {SMBtranss,"SMBtranss",NULL,AS_USER | CAN_IPC}, - {SMBioctls,"SMBioctls",NULL,AS_USER}, - {SMBcopy,"SMBcopy",reply_copy,AS_USER | NEED_WRITE}, - {SMBmove,"SMBmove",NULL,AS_USER | NEED_WRITE}, - - {SMBopenX,"SMBopenX",reply_open_and_X,AS_USER | CAN_IPC}, - {SMBreadX,"SMBreadX",reply_read_and_X,AS_USER}, - {SMBwriteX,"SMBwriteX",reply_write_and_X,AS_USER}, - {SMBlockingX,"SMBlockingX",reply_lockingX,AS_USER}, - - {SMBffirst,"SMBffirst",reply_search,AS_USER}, - {SMBfunique,"SMBfunique",reply_search,AS_USER}, - {SMBfclose,"SMBfclose",reply_fclose,AS_USER}, - - /* LANMAN2.0 PROTOCOL FOLLOWS */ - {SMBfindnclose, "SMBfindnclose", reply_findnclose, AS_USER}, - {SMBfindclose, "SMBfindclose", reply_findclose,AS_USER}, - {SMBtrans2, "SMBtrans2", reply_trans2, AS_USER}, - {SMBtranss2, "SMBtranss2", reply_transs2, AS_USER}, - - /* messaging routines */ - {SMBsends,"SMBsends",reply_sends,AS_GUEST}, - {SMBsendstrt,"SMBsendstrt",reply_sendstrt,AS_GUEST}, - {SMBsendend,"SMBsendend",reply_sendend,AS_GUEST}, - {SMBsendtxt,"SMBsendtxt",reply_sendtxt,AS_GUEST}, - - /* NON-IMPLEMENTED PARTS OF THE CORE PROTOCOL */ - - {SMBsendb,"SMBsendb",NULL,AS_GUEST}, - {SMBfwdname,"SMBfwdname",NULL,AS_GUEST}, - {SMBcancelf,"SMBcancelf",NULL,AS_GUEST}, - {SMBgetmac,"SMBgetmac",NULL,AS_GUEST} - }; - -/**************************************************************************** -return a string containing the function name of a SMB command -****************************************************************************/ -char *smb_fn_name(int type) -{ - static char *unknown_name = "SMBunknown"; - static int num_smb_messages = - sizeof(smb_messages) / sizeof(struct smb_message_struct); - int match; - - for (match=0;match<num_smb_messages;match++) - if (smb_messages[match].code == type) - break; - - if (match == num_smb_messages) - return(unknown_name); - - return(smb_messages[match].name); -} - - -/**************************************************************************** -do a switch on the message type, and return the response size -****************************************************************************/ -static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) -{ - static int pid= -1; - int outsize = 0; - static int num_smb_messages = - sizeof(smb_messages) / sizeof(struct smb_message_struct); - int match; - -#if PROFILING - struct timeval msg_start_time; - struct timeval msg_end_time; - static unsigned long total_time = 0; - - GetTimeOfDay(&msg_start_time); -#endif - - if (pid == -1) - pid = getpid(); - - errno = 0; - last_message = type; - - /* make sure this is an SMB packet */ - if (strncmp(smb_base(inbuf),"\377SMB",4) != 0) - { - DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf))); - return(-1); - } - - for (match=0;match<num_smb_messages;match++) - if (smb_messages[match].code == type) - break; - - if (match == num_smb_messages) - { - DEBUG(0,("Unknown message type %d!\n",type)); - outsize = reply_unknown(inbuf,outbuf); - } - else - { - DEBUG(3,("switch message %s (pid %d)\n",smb_messages[match].name,pid)); - if (smb_messages[match].fn) - { - int cnum = SVAL(inbuf,smb_tid); - int flags = smb_messages[match].flags; - uint16 session_tag = SVAL(inbuf,smb_uid); - - /* does this protocol need to be run as root? */ - if (!(flags & AS_USER)) - unbecome_user(); - - /* does this protocol need to be run as the connected user? */ - if ((flags & AS_USER) && !become_user(cnum,session_tag)) { - if (flags & AS_GUEST) - flags &= ~AS_USER; - else - return(ERROR(ERRSRV,ERRinvnid)); - } - /* this code is to work around a bug is MS client 3 without - introducing a security hole - it needs to be able to do - print queue checks as guest if it isn't logged in properly */ - if (flags & AS_USER) - flags &= ~AS_GUEST; - - /* does it need write permission? */ - if ((flags & NEED_WRITE) && !CAN_WRITE(cnum)) - return(ERROR(ERRSRV,ERRaccess)); - - /* ipc services are limited */ - if (IS_IPC(cnum) && (flags & AS_USER) && !(flags & CAN_IPC)) - return(ERROR(ERRSRV,ERRaccess)); - - /* load service specific parameters */ - if (OPEN_CNUM(cnum) && !become_service(cnum,(flags & AS_USER)?True:False)) - return(ERROR(ERRSRV,ERRaccess)); - - /* does this protocol need to be run as guest? */ - if ((flags & AS_GUEST) && (!become_guest() || !check_access(-1))) - return(ERROR(ERRSRV,ERRaccess)); - - last_inbuf = inbuf; - - outsize = smb_messages[match].fn(inbuf,outbuf,size,bufsize); - } - else - { - outsize = reply_unknown(inbuf,outbuf); - } - } - -#if PROFILING - GetTimeOfDay(&msg_end_time); - if (!(smb_messages[match].flags & TIME_INIT)) - { - smb_messages[match].time = 0; - smb_messages[match].flags |= TIME_INIT; - } - { - unsigned long this_time = - (msg_end_time.tv_sec - msg_start_time.tv_sec)*1e6 + - (msg_end_time.tv_usec - msg_start_time.tv_usec); - smb_messages[match].time += this_time; - total_time += this_time; - } - DEBUG(2,("TIME %s %d usecs %g pct\n", - smb_fn_name(type),smb_messages[match].time, - (100.0*smb_messages[match].time) / total_time)); -#endif - - return(outsize); -} - - -/**************************************************************************** - construct a chained reply and add it to the already made reply - **************************************************************************/ -int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) -{ - static char *orig_inbuf; - static char *orig_outbuf; - int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); - unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; - int outsize2; - char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - extern int chain_size; - int wct = CVAL(outbuf,smb_wct); - int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); - - /* maybe its not chained */ - if (smb_com2 == 0xFF) { - CVAL(outbuf,smb_vwv0) = 0xFF; - return outsize; - } - - if (chain_size == 0) { - /* this is the first part of the chain */ - orig_inbuf = inbuf; - orig_outbuf = outbuf; - } - - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - CVAL(outbuf,smb_vwv0) = smb_com2; - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; - - /* work out pointers into the original packets. The - headers on these need to be filled in */ - inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; - - /* remember the original command type */ - smb_com1 = CVAL(orig_inbuf,smb_com); - - /* save the data which will be overwritten by the new headers */ - memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); - - /* give the new packet the same header as the last part of the SMB */ - memmove(inbuf2,inbuf,smb_wct); - - /* create the in buffer */ - CVAL(inbuf2,smb_com) = smb_com2; - - /* create the out buffer */ - bzero(outbuf2,smb_size); - set_message(outbuf2,0,0,True); - CVAL(outbuf2,smb_com) = CVAL(inbuf2,smb_com); - - memcpy(outbuf2+4,inbuf2+4,4); - CVAL(outbuf2,smb_rcls) = SUCCESS; - CVAL(outbuf2,smb_reh) = 0; - CVAL(outbuf2,smb_flg) = 0x80 | (CVAL(inbuf2,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf2,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf2,smb_err,SUCCESS); - SSVAL(outbuf2,smb_tid,SVAL(inbuf2,smb_tid)); - SSVAL(outbuf2,smb_pid,SVAL(inbuf2,smb_pid)); - SSVAL(outbuf2,smb_uid,SVAL(inbuf2,smb_uid)); - SSVAL(outbuf2,smb_mid,SVAL(inbuf2,smb_mid)); - - DEBUG(3,("Chained message\n")); - show_msg(inbuf2); - - /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, - bufsize-chain_size); - - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - CVAL(orig_outbuf,smb_com) = smb_com1; - - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) ofs = 0; - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); - } - - return outsize2; -} - - - -/**************************************************************************** - construct a reply to the incoming packet -****************************************************************************/ -int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) -{ - int type = CVAL(inbuf,smb_com); - int outsize = 0; - int msg_type = CVAL(inbuf,0); - extern int chain_size; - - smb_last_time = time(NULL); - - chain_size = 0; - chain_fnum = -1; - - bzero(outbuf,smb_size); - - if (msg_type != 0) - return(reply_special(inbuf,outbuf)); - - CVAL(outbuf,smb_com) = CVAL(inbuf,smb_com); - set_message(outbuf,0,0,True); - - memcpy(outbuf+4,inbuf+4,4); - CVAL(outbuf,smb_rcls) = SUCCESS; - CVAL(outbuf,smb_reh) = 0; - CVAL(outbuf,smb_flg) = 0x80 | (CVAL(inbuf,smb_flg) & 0x8); /* bit 7 set - means a reply */ - SSVAL(outbuf,smb_flg2,1); /* say we support long filenames */ - SSVAL(outbuf,smb_err,SUCCESS); - SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid)); - SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid)); - SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid)); - SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); - - outsize = switch_message(type,inbuf,outbuf,size,bufsize); - - outsize += chain_size; - - if(outsize > 4) - smb_setlen(outbuf,outsize - 4); - return(outsize); -} - -/**************************************************************************** - process commands from the client -****************************************************************************/ -static void process(void) -{ - extern int Client; - - InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if ((InBuffer == NULL) || (OutBuffer == NULL)) - return; - - InBuffer += SMB_ALIGNMENT; - OutBuffer += SMB_ALIGNMENT; - -#if PRIME_NMBD - DEBUG(3,("priming nmbd\n")); - { - struct in_addr ip; - ip = *interpret_addr2("localhost"); - if (zero_ip(ip)) ip = *interpret_addr2("127.0.0.1"); - *OutBuffer = 0; - send_one_packet(OutBuffer,1,ip,NMB_PORT,SOCK_DGRAM); - } -#endif - - while (True) - { - int deadtime = lp_deadtime()*60; - int counter; - int last_keepalive=0; - int service_load_counter = 0; - BOOL got_smb = False; - - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; - - if (lp_readprediction()) - do_read_prediction(); - - errno = 0; - - for (counter=SMBD_SELECT_LOOP; - !receive_message_or_smb(Client,oplock_sock, - InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); - counter += SMBD_SELECT_LOOP) - { - int i; - time_t t; - BOOL allidle = True; - extern int keepalive; - - if (counter > 365 * 3600) /* big number of seconds. */ - { - counter = 0; - service_load_counter = 0; - } - - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return; - } - - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return; - } - - t = time(NULL); - - /* become root again if waiting */ - unbecome_user(); - - /* check for smb.conf reload */ - if (counter >= service_load_counter + SMBD_RELOAD_CHECK) - { - service_load_counter = counter; - - /* reload services, if files have changed. */ - reload_services(True); - } - - /* automatic timeout if all connections are closed */ - if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) - { - DEBUG(2,("%s Closing idle connection\n",timestring())); - return; - } - - if (keepalive && (counter-last_keepalive)>keepalive) - { - extern int password_client; - if (!send_keepalive(Client)) - { - DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (password_client != -1) - send_keepalive(password_client); - last_keepalive = counter; - } - - /* check for connection timeouts */ - for (i=0;i<MAX_CONNECTIONS;i++) - if (Connections[i].open) - { - /* close dirptrs on connections that are idle */ - if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT) - dptr_idlecnum(i); - - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)<deadtime) - allidle = False; - } - - if (allidle && num_connections_open>0) - { - DEBUG(2,("%s Closing idle connection 2\n",timestring())); - return; - } - } - - if(got_smb) - process_smb(InBuffer, OutBuffer); - else - process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); - } -} - - -/**************************************************************************** - initialise connect, service and file structs -****************************************************************************/ -static void init_structs(void ) -{ - int i; - get_myname(myhostname,NULL); - - for (i=0;i<MAX_CONNECTIONS;i++) - { - Connections[i].open = False; - Connections[i].num_files_open=0; - Connections[i].lastused=0; - Connections[i].used=False; - string_init(&Connections[i].user,""); - string_init(&Connections[i].dirpath,""); - string_init(&Connections[i].connectpath,""); - string_init(&Connections[i].origpath,""); - } - - for (i=0;i<MAX_OPEN_FILES;i++) - { - Files[i].open = False; - string_init(&Files[i].name,""); - - } - - for (i=0;i<MAX_OPEN_FILES;i++) - { - file_fd_struct *fd_ptr = &FileFd[i]; - fd_ptr->ref_count = 0; - fd_ptr->dev = (int32)-1; - fd_ptr->inode = (int32)-1; - fd_ptr->fd = -1; - fd_ptr->fd_readonly = -1; - fd_ptr->fd_writeonly = -1; - fd_ptr->real_open_flags = -1; - } - - init_dptrs(); -} - -/**************************************************************************** -usage on the program -****************************************************************************/ -static void usage(char *pname) -{ - DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n")); - - printf("Usage: %s [-D] [-p port] [-d debuglevel] [-l log basename] [-s services file]\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-s services file. Filename of services file\n"); - printf("\t-P passive only\n"); - printf("\t-a overwrite log file, don't append\n"); - printf("\n"); -} - - -/**************************************************************************** - main program -****************************************************************************/ - int main(int argc,char *argv[]) -{ - extern BOOL append_log; - /* shall I run as a daemon */ - BOOL is_daemon = False; - int port = SMB_PORT; - int opt; - extern char *optarg; - char pidFile[100] = { 0 }; - -#ifdef NEED_AUTH_PARAMETERS - set_auth_parameters(argc,argv); -#endif - -#ifdef SecureWare - setluid(0); -#endif - - append_log = True; - - TimeInit(); - - strcpy(debugf,SMBLOGFILE); - - setup_logging(argv[0],False); - - charset_initialise(); - - /* make absolutely sure we run as root - to handle cases whre people - are crazy enough to have it setuid */ -#ifdef USE_SETRES - setresuid(0,0,0); -#else - setuid(0); - seteuid(0); - setuid(0); - seteuid(0); -#endif - - fault_setup(exit_server); - signal(SIGTERM , SIGNAL_CAST dflt_sig); - - /* we want total control over the permissions on created files, - so set our umask to 0 */ - umask(0); - - GetWd(OriginalDir); - - init_uid(); - - /* this is for people who can't start the program correctly */ - while (argc > 1 && (*argv[1] != '-')) - { - argv++; - argc--; - } - - while ((opt = getopt(argc, argv, "O:i:l:s:d:Dp:hPaf:")) != EOF) - switch (opt) - { - case 'f': - strncpy(pidFile, optarg, sizeof(pidFile)); - break; - case 'O': - strcpy(user_socket_options,optarg); - break; - case 'i': - strcpy(scope,optarg); - break; - case 'P': - { - extern BOOL passive; - passive = True; - } - break; - case 's': - strcpy(servicesf,optarg); - break; - case 'l': - strcpy(debugf,optarg); - break; - case 'a': - { - extern BOOL append_log; - append_log = !append_log; - } - break; - case 'D': - is_daemon = True; - break; - case 'd': - if (*optarg == 'A') - DEBUGLEVEL = 10000; - else - DEBUGLEVEL = atoi(optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 'h': - usage(argv[0]); - exit(0); - break; - default: - usage(argv[0]); - exit(1); - } - - reopen_logs(); - - DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION)); - DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n")); - -#ifndef NO_GETRLIMIT -#ifdef RLIMIT_NOFILE - { - struct rlimit rlp; - getrlimit(RLIMIT_NOFILE, &rlp); - rlp.rlim_cur = (MAX_OPEN_FILES>rlp.rlim_max)? rlp.rlim_max:MAX_OPEN_FILES; - setrlimit(RLIMIT_NOFILE, &rlp); - getrlimit(RLIMIT_NOFILE, &rlp); - DEBUG(3,("Maximum number of open files per session is %d\n",rlp.rlim_cur)); - } -#endif -#endif - - - DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", - getuid(),getgid(),geteuid(),getegid())); - - if (sizeof(uint16) < 2 || sizeof(uint32) < 4) - { - DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n")); - exit(1); - } - - init_structs(); - - if (!reload_services(False)) - return(-1); - - codepage_initialise(lp_client_code_page()); - - strcpy(myworkgroup, lp_workgroup()); - -#ifndef NO_SIGNAL_TEST - signal(SIGHUP,SIGNAL_CAST sig_hup); -#endif - - DEBUG(3,("%s loaded services\n",timestring())); - - 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(3,("%s becoming a daemon\n",timestring())); - become_daemon(); - } - - if (*pidFile) - { - int fd; - char buf[20]; - - if ((fd = open(pidFile, -#ifdef O_NONBLOCK - O_NONBLOCK | -#endif - 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: smbd 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... */ - } - - if (!open_sockets(is_daemon,port)) - exit(1); - -#ifdef FAST_SHARE_MODES - if (!start_share_mode_mgmt()) - exit(1); -#endif /* FAST_SHARE_MODES */ - - /* possibly reload the services file. */ - reload_services(True); - - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); - - if (*lp_rootdir()) - { - if (sys_chroot(lp_rootdir()) == 0) - DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); - } - - /* Setup the oplock IPC socket. */ - if(!open_oplock_ipc()) - exit(1); - - process(); - close_sockets(); - - exit_server("normal exit"); - return(0); -} - - 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 a56df9cb9cc..00000000000 --- a/source/smbd/trans2.c +++ /dev/null @@ -1,1794 +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 = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>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; - BOOL bad_path = False; - - 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,&bad_path); - - fnum = find_free_file(); - if (fnum < 0) - return(ERROR(ERRSRV,ERRnofids)); - - if (!check_name(fname,cnum)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - unixmode = unix_mode(cnum,open_attr | aARCH); - - - open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, - oplock_request, &rmode,&smb_action); - - if (!Files[fnum].open) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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 |= EXTENDED_OPLOCK_GRANTED; - } - - 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 - pstrcpy(mask, p+1); - } - else - pstrcpy(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(8,("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; - - pstrcpy(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; - - pstrcpy(pathreal,Connections[cnum].dirpath); - if(needslash) - strcat(pathreal,"/"); - strcat(pathreal,dname); - 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; - } - } - - name_map_mangle(fname,False,SNUM(cnum)); - - p = pdata; - nameptr = p; - - 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; - BOOL bad_path = False; - - *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)); - } - - pstrcpy(directory, params + 12); /* Complete directory path with - wildcard mask appended */ - - DEBUG(5,("path=%s\n",directory)); - - unix_convert(directory,cnum,0,&bad_path); - if(!check_name(directory,cnum)) { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - -#if 0 - /* Ugly - NT specific hack - maybe not needed ? (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } -#endif - - 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) - { - if(dptr_num == -2) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - -#if 0 - /* Ugly - NT specific hack - maybe not needed ? (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } -#endif - - return (UNIXERROR(ERRDOS,ERRbadpath)); - } - 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; - BOOL bad_path = False; - - 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]; - pstrcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0,&bad_path); - if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) { - DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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)); - return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); - } - - bzero(pdata,data_size); - - switch (info_level) - { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: - data_size = (info_level==1?22:26); - put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */ - put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */ - put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */ - 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 SMB_INFO_QUERY_EAS_FROM_LIST: - data_size = 24; - put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */ - 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 SMB_INFO_QUERY_ALL_EAS: - 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; /* w95 returns 40 bytes not 36 - why ?. */ - put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */ - put_long_date(pdata+8,sbuf.st_atime); /* access time */ - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,mode); - - DEBUG(5,("SMB_QFBI - ")); - DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime))); - DEBUG(5,("access: %s ", ctime(&sbuf.st_atime))); - DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime))); - DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime))); - DEBUG(5,("mode: %x\n", 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; - - /* Get the 8.3 name - used if NT SMB was negotiated. */ - case SMB_QUERY_FILE_ALT_NAME_INFO: - { - pstring short_name; - pstrcpy(short_name,fname); - /* Mangle if not already 8.3 */ - if(!is_8_3(short_name, True)) - { - if(!name_map_mangle(short_name,True,SNUM(cnum))) - *short_name = '\0'; - } - strncpy(pdata + 4,short_name,12); - (pdata + 4)[12] = 0; - strupper(pdata + 4); - l = strlen(pdata + 4); - data_size = 4 + l; - SIVAL(pdata,0,l); - } - break; - - case SMB_QUERY_FILE_NAME_INFO: - data_size = 4 + l; - SIVAL(pdata,0,l); - pstrcpy(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); /* create time = inode mod time */ - put_long_date(pdata+8,sbuf.st_atime); /* access time */ - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - 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); - pstrcpy(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); - pstrcpy(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; - BOOL bad_path = False; - - 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; - pstrcpy(fname,¶ms[6]); - unix_convert(fname,cnum,0,&bad_path); - if(!check_name(fname, cnum)) - { - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); - } - - if(sys_stat(fname,&st)!=0) { - DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - return(UNIXERROR(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)); - return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED)); - } - - switch (info_level) - { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: - { - /* access time */ - tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - - /* write time */ - tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - - mode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; - } - - /* XXXX um, i don't think this is right. - it's also not in the cifs6.txt spec. - */ - case SMB_INFO_QUERY_EAS_FROM_LIST: - tvs.actime = make_unix_date2(pdata+8); - tvs.modtime = make_unix_date2(pdata+12); - size = IVAL(pdata,16); - mode = IVAL(pdata,24); - break; - - /* XXXX nor this. not in cifs6.txt, either. */ - case SMB_INFO_QUERY_ALL_EAS: - 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: - { - /* Ignore create time at offset pdata. */ - - /* access time */ - tvs.actime = interpret_long_date(pdata+8); - - /* write time + changed time, combined. */ - tvs.modtime=MAX(interpret_long_date(pdata+16), - interpret_long_date(pdata+24)); - -#if 0 /* Needs more testing... */ - /* Test from Luke to prevent Win95 from - setting incorrect values here. - */ - if (tvs.actime < tvs.modtime) - return(ERROR(ERRDOS,ERRnoaccess)); -#endif /* Needs more testing... */ - - /* attributes */ - mode = IVAL(pdata,32); - 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)); - } - } - - DEBUG(6,("actime: %s " , ctime(&tvs.actime))); - DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); - DEBUG(6,("size: %x " , size)); - DEBUG(6,("mode: %x\n" , mode)); - - /* get some defaults (no modifications) if any info is zero. */ - 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)); - } - } - - /* check the mode isn't different, before changing it */ - 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; - BOOL bad_path = False; - - if (!CAN_WRITE(cnum)) - return(ERROR(ERRSRV,ERRaccess)); - - pstrcpy(directory, ¶ms[4]); - - DEBUG(3,("call_trans2mkdir : name = %s\n", directory)); - - unix_convert(directory,cnum,0,&bad_path); - 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))); - if((errno == ENOENT) && bad_path) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - } - 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); - - if (num_params > total_params || num_data > total_data) - exit_server("invalid params in reply_trans2"); - - 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)); - if (num_params_sofar > total_params || num_data_sofar > total_data) - exit_server("data overflow in trans2"); - - 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 cdc4e474c61..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)\n")); - } -#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 07558274a52..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(); - - fstrcpy(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; - - fstrcpy(u.ut_id, tt); - u.ut_time = time((time_t*)0); - } - - fstrcpy(u.ut_user, "LOGIN"); - fstrcpy(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(); - - fstrcpy(u.ut_line, VT_Line); - - if((v = getutline(&u)) != NULL) { - fstrcpy(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/smbparse.c b/source/smbparse.c deleted file mode 100644 index 01438281ef1..00000000000 --- a/source/smbparse.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Samba utility functions - Copyright (C) Luke Leighton 1996 - 1997 Paul Ashton 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; - - -/******************************************************************* -reads or writes a UTIME type. -********************************************************************/ -char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align) -{ - if (t == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL (io, q, t->time, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes an NTTIME structure. -********************************************************************/ -char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align) -{ - if (nttime == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, nttime->low , 0); q += 4; /* low part */ - RW_IVAL(io, q, nttime->high, 0); q += 4; /* high part */ - - return q; -} - -/******************************************************************* -reads or writes a DOM_SID structure. -********************************************************************/ -char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align) -{ - int i; - - if (sid == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_CVAL(io, q, sid->sid_no, 0); q++; - RW_CVAL(io, q, sid->num_auths, 0); q++; - - for (i = 0; i < 6; i++) - { - RW_CVAL(io, q, sid->id_auth[i], 0); q++; - } - - /* oops! XXXX should really issue a warning here... */ - if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS; - - RW_PSVAL(io, q, sid->sub_auths, sid->num_auths); q += sid->num_auths * 2; - - return q; -} - -/******************************************************************* -reads or writes a UNIHDR structure. -********************************************************************/ -char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align) -{ - if (hdr == NULL) return NULL; - - /* should be value 4, so enforce it. */ - hdr->undoc = 4; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, hdr->uni_max_len, 0); q += 4; - RW_IVAL(io, q, hdr->uni_str_len, 0); q += 4; - RW_IVAL(io, q, hdr->undoc , 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a UNIHDR2 structure. -********************************************************************/ -char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align) -{ - if (hdr2 == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_unihdr(io, &(hdr2->unihdr), q, base, align); - RW_IVAL(io, q, hdr2->undoc_buffer, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a UNISTR structure. -XXXX NOTE: UNISTR structures NEED to be null-terminated. -********************************************************************/ -char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align) -{ - if (uni == NULL) return NULL; - - q = align_offset(q, base, align); - - if (io) - { - /* io True indicates read _from_ the SMB buffer into the string */ - q += 2 * unistrcpy((char*)uni->buffer, q); - } - else - { - /* io True indicates copy _from_ the string into SMB buffer */ - q += 2 * unistrcpy(q, (char*)uni->buffer); - } - return q; -} - -/******************************************************************* -reads or writes a UNISTR2 structure. -XXXX NOTE: UNISTR2 structures need NOT be null-terminated. - the uni_str_len member tells you how long the string is; - the uni_max_len member tells you how large the buffer is. -********************************************************************/ -char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align) -{ - if (uni2 == NULL) return NULL; - - q = align_offset(q, base, align); - - /* should be value 0, so enforce it. */ - uni2->undoc = 0; - - RW_IVAL(io, q, uni2->uni_max_len, 0); q += 4; - RW_IVAL(io, q, uni2->undoc , 0); q += 4; - RW_IVAL(io, q, uni2->uni_str_len, 0); q += 4; - - /* oops! XXXX maybe issue a warning that this is happening... */ - if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN; - if (uni2->uni_str_len > MAX_UNISTRLEN) uni2->uni_str_len = MAX_UNISTRLEN; - - /* buffer advanced by indicated length of string - NOT by searching for null-termination */ - RW_PSVAL(io, q, uni2->buffer, uni2->uni_max_len); q += uni2->uni_max_len * 2; - - return q; -} - -/******************************************************************* -reads or writes a DOM_SID2 structure. -********************************************************************/ -char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align) -{ - if (sid2 == NULL) return NULL; - - q = align_offset(q, base, align); - - /* should be value 5, so enforce it */ - sid2->type = 5; - - /* should be value 0, so enforce it */ - sid2->undoc = 0; - - RW_IVAL(io, q, sid2->type , 0); q += 4; - RW_IVAL(io, q, sid2->undoc, 0); q += 4; - - q = smb_io_unihdr2(io, &(sid2->hdr), q, base, align); - q = smb_io_unistr (io, &(sid2->str), q, base, align); - - return q; -} - -/******************************************************************* -reads or writes a DOM_RID2 structure. -********************************************************************/ -char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align) -{ - if (rid2 == NULL) return NULL; - - q = align_offset(q, base, align); - - /* should be value 5, so enforce it */ - rid2->type = 5; - - /* should be value 5, so enforce it */ - rid2->undoc = 5; - - RW_IVAL(io, q, rid2->type, 0); q += 4; - RW_IVAL(io, q, rid2->undoc , 0); q += 4; - RW_IVAL(io, q, rid2->rid , 0); q += 4; - RW_IVAL(io, q, rid2->rid_idx , 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes a DOM_LOG_INFO structure. -********************************************************************/ -char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align) -{ - if (log == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, log->undoc_buffer, 0); q += 4; - - q = smb_io_unistr2(io, &(log->uni_logon_srv), q, base, align); - q = smb_io_unistr2(io, &(log->uni_acct_name), q, base, align); - - RW_SVAL(io, q, log->sec_chan, 0); q += 2; - - /* XXXX no alignment required between sec_chan and uni_comp_name */ - q = smb_io_unistr2(io, &(log->uni_comp_name), q, base, 0); - - return q; -} - -/******************************************************************* -reads or writes a DOM_CHAL structure. -********************************************************************/ -char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align) -{ - if (chal == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_PCVAL(io, q, chal->data, 8); q += 8; - - return q; -} - -/******************************************************************* -reads or writes a DOM_CRED structure. -********************************************************************/ -char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align) -{ - if (cred == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_chal (io, &(cred->challenge), q, base, align); - q = smb_io_utime(io, &(cred->timestamp), q, base, align); - - return q; -} - -/******************************************************************* -reads or writes a DOM_CLNT_INFO structure. -********************************************************************/ -char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align) -{ - if (clnt == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_log_info(io, &(clnt->login), q, base, align); - q = smb_io_cred (io, &(clnt->cred ), q, base, align); - - return q; -} - -/******************************************************************* -reads or writes a DOM_LOGON_ID structure. -********************************************************************/ -char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align) -{ - if (log == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, log->low , 0); q += 4; - RW_IVAL(io, q, log->high, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes an ARC4_OWF structure. -********************************************************************/ -char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align) -{ - if (hash == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_PCVAL(io, q, hash->data, 16); q += 16; - - return q; -} - -/******************************************************************* -reads or writes an DOM_ID_INFO_1 structure. -********************************************************************/ -char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align) -{ - if (id == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_unihdr(io, &(id->hdr_domain_name ), q, base, align); - - RW_IVAL(io, q, id->param, 0); q += 4; - q = smb_io_logon_id(io, &(id->logon_id), q, base, align); - - q = smb_io_unihdr(io, &(id->hdr_user_name ), q, base, align); - q = smb_io_unihdr(io, &(id->hdr_workgroup_name), q, base, align); - - q = smb_io_arc4_owf(io, &(id->arc4_lm_owf), q, base, align); - q = smb_io_arc4_owf(io, &(id->arc4_nt_owf), q, base, align); - - q = smb_io_unistr2(io, &(id->uni_domain_name ), q, base, align); - q = smb_io_unistr2(io, &(id->uni_user_name ), q, base, align); - q = smb_io_unistr2(io, &(id->uni_workgroup_name), q, base, align); - - return q; -} - -/******************************************************************* -reads or writes a DOM_SAM_INFO structure. -********************************************************************/ -char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align) -{ - if (sam == NULL) return NULL; - - q = align_offset(q, base, align); - - q = smb_io_clnt_info(io, &(sam->client ), q, base, align); - q = smb_io_cred (io, &(sam->rtn_cred), q, base, align); - - RW_IVAL(io, q, sam->logon_level, 0); q += 4; - RW_SVAL(io, q, sam->auth_level , 0); q += 4; - - switch (sam->auth_level) - { - case 1: - { - q = smb_io_id_info1(io, &(sam->auth.id1), q, base, align); - break; - } - default: - { - /* PANIC! */ - break; - } - } - return q; -} - -/******************************************************************* -reads or writes a DOM_GID structure. -********************************************************************/ -char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align) -{ - if (gid == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, gid->gid , 0); q += 4; - RW_IVAL(io, q, gid->attr, 0); q += 4; - - return q; -} - -/******************************************************************* -reads or writes an RPC_HDR structure. -********************************************************************/ -char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align) -{ - if (rpc == NULL) return NULL; - - /* reserved should be zero: enforce it */ - rpc->reserved = 0; - - RW_CVAL(io, q, rpc->major, 0); q++; - RW_CVAL(io, q, rpc->minor, 0); q++; - RW_CVAL(io, q, rpc->pkt_type, 0); q++; - RW_CVAL(io, q, rpc->frag, 0); q++; - RW_IVAL(io, q, rpc->pack_type, 0); q += 4; - RW_SVAL(io, q, rpc->frag_len, 0); q += 2; - RW_SVAL(io, q, rpc->auth_len, 0); q += 2; - RW_IVAL(io, q, rpc->call_id, 0); q += 4; - RW_SVAL(io, q, rpc->alloc_hint, 0); q += 2; - RW_CVAL(io, q, rpc->context_id, 0); q++; - RW_CVAL(io, q, rpc->reserved, 0); q++; - - return q; -} - -/******************************************************************* -reads or writes an LSA_POL_HND structure. -********************************************************************/ -char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align) -{ - if (pol == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_PCVAL(io, q, pol->data, POL_HND_SIZE); q += POL_HND_SIZE; - - return q; -} - -/******************************************************************* -reads or writes a dom query structure. -********************************************************************/ -char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align) -{ - return smb_io_dom_query(io, d_q, q, base, align); -} - -/******************************************************************* -reads or writes a dom query structure. -********************************************************************/ -char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align) -{ - return smb_io_dom_query(io, d_q, q, base, align); -} - -/******************************************************************* -reads or writes a dom query structure. -********************************************************************/ -char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align) -{ - if (d_q == NULL) return NULL; - - q = align_offset(q, base, align); - - - RW_SVAL(io, q, d_q->uni_dom_max_len, 0); q += 2; /* domain name string length * 2 */ - RW_SVAL(io, q, d_q->padding , 0); q += 2; /* 2 padding bytes */ - RW_SVAL(io, q, d_q->uni_dom_str_len, 0); q += 2; /* domain name string length * 2 */ - - RW_IVAL(io, q, d_q->buffer_dom_name, 0); q += 4; /* undocumented domain name string buffer pointer */ - RW_IVAL(io, q, d_q->buffer_dom_sid , 0); q += 4; /* undocumented domain SID string buffer pointer */ - - if (d_q->buffer_dom_name != 0) - { - q = smb_io_unistr2(io, &(d_q->uni_domain_name), q, base, align); /* domain name (unicode string) */ - } - if (d_q->buffer_dom_sid != 0) - { - q = smb_io_dom_sid(io, &(d_q->dom_sid), q, base, align); /* domain SID */ - } - - return q; -} - -/******************************************************************* -reads or writes a DOM_R_REF structure. -********************************************************************/ -char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align) -{ - int i; - - if (r_r == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, r_r->undoc_buffer, 0); q += 4; /* undocumented buffer pointer. */ - RW_IVAL(io, q, r_r->num_ref_doms_1, 0); q += 4; /* num referenced domains? */ - RW_IVAL(io, q, r_r->buffer_dom_name, 0); q += 4; /* undocumented domain name buffer pointer. */ - RW_IVAL(io, q, r_r->max_entries, 0); q += 4; /* 32 - max number of entries */ - RW_IVAL(io, q, r_r->num_ref_doms_2, 0); q += 4; /* 4 - num referenced domains? */ - - q = smb_io_unihdr2(io, &(r_r->hdr_dom_name), q, base, align); /* domain name unicode string header */ - - for (i = 0; i < r_r->num_ref_doms_1-1; i++) - { - q = smb_io_unihdr2(io, &(r_r->hdr_ref_dom[i]), q, base, align); - } - - q = smb_io_unistr(io, &(r_r->uni_dom_name), q, base, align); /* domain name unicode string */ - - for (i = 0; i < r_r->num_ref_doms_2; i++) - { - q = smb_io_dom_sid(io, &(r_r->ref_dom[i]), q, base, align); /* referenced domain SIDs */ - } - return q; -} - -/******************************************************************* -reads or writes a DOM_NAME structure. -********************************************************************/ -char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align) -{ - if (name == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, name->uni_str_len, 0); q += 4; - - /* don't know if len is specified by uni_str_len member... */ - /* assume unicode string is unicode-null-terminated, instead */ - - q = smb_io_unistr(io, &(name->str), q, base, align); - - return q; -} - - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align) -{ - if (neg == NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, neg->neg_flags, 0); q += 4; - - return q; -} - - -#if 0 -/******************************************************************* -reads or writes a structure. -********************************************************************/ - char* smb_io_(BOOL io, *, char *q, char *base, int align) -{ - if (== NULL) return NULL; - - q = align_offset(q, base, align); - - RW_IVAL(io, q, , 0); q += 4; - - return q; -} -#endif diff --git a/source/utils/make_smbcodepage.c b/source/utils/make_smbcodepage.c deleted file mode 100644 index b4cb1523349..00000000000 --- a/source/utils/make_smbcodepage.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - Create codepage files from codepage_def.XXX files. - - Copyright (C) Jeremy Allison 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" - -static char *prog_name = NULL; - -/* - * Print program usage and die. - */ - -void codepage_usage(char *progname) -{ - fprintf(stderr, "Usage is : %s [c|d] <codepage> <inputfile> <outputfile>\n", - progname); - exit(1); -} - -/* - * Read a line from a buffer into a line buffer. Ensure null - * terminated. - */ - -void read_line( char **buf, char *line_buf, int size) -{ - char *p = *buf; - int num = 0; - - for(; *p && (*p != '\n'); p++) - { - if(num < (size - 1)) - line_buf[num++] = *p; - } - if(*p) - p++; /* Go past the '\n' */ - line_buf[num] = '\0'; - *buf = p; -} - -/* - * Strip comment lines and blank lines from the data. - * Copies into a new buffer and frees the old. - * Returns the number of lines copied. - */ - -int clean_data( char **buf, uint32 *size) -{ - char linebuf[512]; - char *p = *buf; - int num_lines = 0; - char *newbuf = (char *)malloc( *size + 1); - char *newbuf_p = NULL; - - if(newbuf == NULL) - { - fprintf(stderr, "%s: malloc fail for size %d.\n", prog_name, *size + 1); - exit(1); - } - - newbuf_p = newbuf; - *newbuf_p = '\0'; - - while( *p ) - { - char *cp; - - read_line( &p, linebuf, sizeof(linebuf)); - /* Null terminate after comment. */ - if((cp = strchr( linebuf, '#'))!= NULL) - *cp = '\0'; - - for(cp = linebuf;*cp && isspace(*cp); cp++) - ; - - if(*cp == '\0') - continue; - - strcpy(newbuf_p, cp); - num_lines++; - newbuf_p += (strlen(newbuf_p) + 1); - } - - free(*buf); - *buf = newbuf; - return num_lines; -} - -/* - * Parse a byte from a codepage file. - */ - -BOOL parse_byte(char *buf, unsigned char *bp) -{ - unsigned int b; - char *endptr = NULL; - - b = (unsigned int)strtol(buf, &endptr, 0); - if(endptr == buf || b > 255) - return False; - - *bp = (unsigned char)b; - return True; -} - -/* - * Parse a bool from a codepage file. - */ - -BOOL parse_bool(char *buf, unsigned char *bp) -{ - if(isdigit(*buf)) - { - char *endptr = NULL; - - *bp = (unsigned char)strtol(buf, &endptr, 0); - if(endptr == buf ) - return False; - if(*bp != 0) - *bp = 1; - } else { - if(strcasecmp(buf, "True") && strcasecmp(buf, "False")) - return False; - if(strcasecmp(buf, "True")==0) - *bp = 1; - else - *bp = 0; - } - return True; -} - -/* - * Print a parse error and exit. - */ - -void parse_error(char *buf, char *msg) -{ - fprintf(stderr, "%s: %s whilst parsing line \n%s\n", prog_name, - msg, buf); - exit(1); -} - -/* - * Create a compiled codepage file from a codepage definition file. - */ - -int do_compile(int codepage, char *input_file, char *output_file) -{ - FILE *fp = NULL; - uint32 size = 0; - char *buf = NULL; - char output_buf[CODEPAGE_HEADER_SIZE + 512]; - int num_lines = 0; - int i = 0; - struct stat st; - - /* Get the size of the input file. Read the entire thing into memory. */ - if(stat((char *)input_file, &st)!= 0) - { - fprintf(stderr, "%s: failed to get the file size for file %s. Error was %s\n", - prog_name, input_file, strerror(errno)); - exit(1); - } - - size = (uint32)st.st_size; - - /* I don't believe these things should be bigger than 100k :-) */ - if(size > 100*1024) - { - fprintf(stderr, "%s: filesize %d is too large for a codepage definition file. \ -The maximum size I will believe is 100k.\n", prog_name, size); - exit(1); - } - - if((fp = fopen(input_file, "r")) == NULL) - { - fprintf(stderr, "%s: cannot open file %s for input.\n", prog_name, input_file); - exit(1); - } - - /* As we will be reading text, allocate one more byte for a '\0' */ - if((buf = (char *)malloc( size + 1 )) == NULL) - { - fprintf(stderr, "%s: malloc fail for size %d.\n", prog_name, size + 1); - fclose(fp); - exit(1); - } - - if(fread( buf, 1, size, fp) != size) - { - fprintf(stderr, "%s: read failed for file %s. Error was %s.\n", prog_name, - input_file, strerror(errno)); - free((char *)buf); - fclose(fp); - exit(1); - } - - /* Null terminate the text read. */ - buf[size] = '\0'; - - /* Go through the data line by line, strip out comments (anything - after a '#' to end-of-line) and blank lines. The rest should be - the codepage data. - */ - - num_lines = clean_data( &buf, &size); - - /* There can be a maximum of 128 lines. */ - if(num_lines > 128) - { - fprintf(stderr, "%s: There can be a maximum 128 lines of data in a codepage \ -definition file. File %s has %d.\n", prog_name, input_file, num_lines); - exit(1); - } - - /* Setup the output file header. */ - SSVAL(output_buf,CODEPAGE_VERSION_OFFSET,CODEPAGE_FILE_VERSION_ID); - SSVAL(output_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET,(uint16)codepage); - SIVAL(output_buf,CODEPAGE_LENGTH_OFFSET,(num_lines * 4)); - - /* Now convert the lines into the compiled form. */ - for(i = 0; i < num_lines; i++) - { - char token_buf[512]; - char *p = buf; - unsigned char b = 0; - - /* Get the 'lower' value. */ - if(!next_token(&p, token_buf, NULL)) - parse_error(buf, "cannot parse first value"); - if(!parse_byte( token_buf, &b)) - parse_error(buf, "first value doesn't resolve to a byte"); - - /* Add this to the output buffer. */ - SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4),b); - - /* Get the 'upper' value. */ - if(!next_token(&p, token_buf, NULL)) - parse_error(buf, "cannot parse second value"); - if(!parse_byte( token_buf, &b)) - parse_error(buf, "second value doesn't resolve to a byte"); - - /* Add this to the output buffer. */ - SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 1,b); - - /* Get the 'upper to lower' value. */ - if(!next_token(&p, token_buf, NULL)) - parse_error(buf, "cannot parse third value"); - if(!parse_bool( token_buf, &b)) - parse_error(buf, "third value doesn't resolve to a boolean"); - - /* Add this to the output buffer. */ - SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 2,b); - - /* Get the 'lower to upper' value. */ - if(!next_token(&p, token_buf, NULL)) - parse_error(buf, "cannot parse fourth value"); - if(!parse_bool( token_buf, &b)) - parse_error(buf, "fourth value doesn't resolve to a boolean"); - - /* Add this to the output buffer. */ - SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 3,b); - - buf += (strlen(buf) + 1); - } - - /* Now write out the output_buf. */ - if((fp = fopen(output_file, "w"))==NULL) - { - fprintf(stderr, "%s: Cannot open output file %s. Error was %s.\n", - prog_name, output_file, strerror(errno)); - exit(1); - } - - if(fwrite(output_buf, 1, CODEPAGE_HEADER_SIZE + (num_lines*4), fp) != - CODEPAGE_HEADER_SIZE + (num_lines*4)) - { - fprintf(stderr, "%s: Cannot write output file %s. Error was %s.\n", - prog_name, output_file, strerror(errno)); - exit(1); - } - - fclose(fp); - - return 0; -} - -/* - * Placeholder for now. - */ - -int do_decompile( int codepage, char *input_file, char *output_file) -{ - uint32 size = 0; - struct stat st; - char header_buf[CODEPAGE_HEADER_SIZE]; - char *buf = NULL; - FILE *fp = NULL; - int num_lines = 0; - int i = 0; - - /* Get the size of the input file. Read the entire thing into memory. */ - if(stat((char *)input_file, &st)!= 0) - { - fprintf(stderr, "%s: failed to get the file size for file %s. Error was %s\n", - prog_name, input_file, strerror(errno)); - exit(1); - } - - size = (uint32)st.st_size; - - if( size < CODEPAGE_HEADER_SIZE || size > (CODEPAGE_HEADER_SIZE + 256)) - { - fprintf(stderr, "%s: file %s is an incorrect size for a \ -code page file.\n", prog_name, input_file); - exit(1); - } - - /* Read the first 8 bytes of the codepage file - check - the version number and code page number. All the data - is held in little endian format. - */ - - if((fp = fopen( input_file, "r")) == NULL) - { - fprintf(stderr, "%s: cannot open file %s. Error was %s\n", - prog_name, input_file, strerror(errno)); - exit(1); - } - - if(fread( header_buf, 1, CODEPAGE_HEADER_SIZE, fp)!=CODEPAGE_HEADER_SIZE) - { - fprintf(stderr, "%s: cannot read header from file %s. Error was %s\n", - prog_name, input_file, strerror(errno)); - exit(1); - } - - /* Check the version value */ - if(SVAL(header_buf,CODEPAGE_VERSION_OFFSET) != CODEPAGE_FILE_VERSION_ID) - { - fprintf(stderr, "%s: filename %s has incorrect version id. \ -Needed %hu, got %hu.\n", - prog_name, input_file, (uint16)CODEPAGE_FILE_VERSION_ID, - SVAL(header_buf,CODEPAGE_VERSION_OFFSET)); - exit(1); - } - - /* Check the codepage matches */ - if(SVAL(header_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET) != (uint16)codepage) - { - fprintf(stderr, "%s: filename %s has incorrect codepage. \ -Needed %hu, got %hu.\n", - prog_name, input_file, (uint16)codepage, - SVAL(header_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET)); - exit(1); - } - - /* Check the length is correct. */ - if(IVAL(header_buf,CODEPAGE_LENGTH_OFFSET) != - (unsigned int)(size - CODEPAGE_HEADER_SIZE)) - { - fprintf(stderr, "%s: filename %s has incorrect size headers. \ -Needed %u, got %u.\n", prog_name, input_file, size - CODEPAGE_HEADER_SIZE, - IVAL(header_buf,CODEPAGE_LENGTH_OFFSET)); - exit(1); - } - - size -= CODEPAGE_HEADER_SIZE; /* Remove header */ - - /* Make sure the size is a multiple of 4. */ - if((size % 4 ) != 0) - { - fprintf(stderr, "%s: filename %s has a codepage size not a \ -multiple of 4.\n", prog_name, input_file); - exit(1); - } - - /* Allocate space for the code page file and read it all in. */ - if((buf = (char *)malloc( size )) == NULL) - { - fprintf (stderr, "%s: malloc fail for size %d.\n", - prog_name, size ); - exit(1); - } - - if(fread( buf, 1, size, fp)!=size) - { - fprintf(stderr, "%s: read fail on file %s. Error was %s.\n", - prog_name, input_file, strerror(errno)); - exit(1); - } - - fclose(fp); - - /* Now dump the codepage into an ascii file. */ - if((fp = fopen(output_file, "w")) == NULL) - { - fprintf(stderr, "%s: cannot open file %s. Error was %s\n", - prog_name, output_file, strerror(errno)); - exit(1); - } - - fprintf(fp, "#\n# Codepage definition file for IBM Code Page %d.\n#\n", - codepage); - fprintf(fp, "# This file was automatically generated.\n#\n"); - fprintf(fp, "# defines lower->upper mapping.\n"); - fprintf(fp, "#\n#The columns are :\n# lower\tupper\tu-t-l\tl-t-u\n#\n"); - - num_lines = size / 4; - for( i = 0; i < num_lines; i++) - { - fprintf(fp, "0x%02X\t0x%02X\t%s\t%s\n", CVAL(buf, (i*4)), CVAL(buf, (i*4)+1), - CVAL(buf, (i*4)+2) ? "True" : "False", - CVAL(buf, (i*4)+3) ? "True" : "False"); - } - fclose(fp); - return 0; -} - -int main(int argc, char **argv) -{ - int codepage = 0; - char *input_file = NULL; - char *output_file = NULL; - BOOL compile = False; - - prog_name = argv[0]; - - if(argc != 5) - codepage_usage(prog_name); - - if(argv[1][0] != 'c' && argv[1][0] != 'C' && argv[1][0] != 'd' && - argv[1][0] != 'D') - codepage_usage(prog_name); - - input_file = argv[3]; - output_file = argv[4]; - - /* Are we compiling or decompiling. */ - if(argv[1][0] == 'c' || argv[1][0] == 'C') - compile = True; - - /* Convert the second argument into a client codepage value. */ - if((codepage = atoi(argv[2])) == 0) - { - fprintf(stderr, "%s: %s is not a valid codepage.\n", prog_name, argv[2]); - exit(1); - } - - if(compile) - return do_compile( codepage, input_file, output_file); - else - return do_decompile( codepage, input_file, output_file); -} diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c deleted file mode 100644 index 63ca156449f..00000000000 --- a/source/utils/nmblookup.c +++ /dev/null @@ -1,241 +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; - -int RootPort = 0; - -/**************************************************************************** - 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, - (RootPort ? 137 :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("\t-r Use root port 137 (Win95 only replies to this)\n"); - printf("\t-A Do a node status on <name> as an IP Address\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; - BOOL lookup_by_ip = False; - - DEBUGLEVEL = 1; - *lookup = 0; - - TimeInit(); - - setup_logging(argv[0],True); - - charset_initialise(); - - while ((opt = getopt(argc, argv, "d:B:i:s:SMrhA")) != EOF) - switch (opt) - { - case 'B': - iface_set_default(NULL,optarg,NULL); - bcast_addr = *interpret_addr2(optarg); - got_bcast = True; - break; - case 'i': - fstrcpy(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': - pstrcpy(servicesf, optarg); - break; - case 'r': - RootPort = -1; - break; - case 'h': - usage(); - exit(0); - break; - case 'A': - lookup_by_ip = True; - 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; - - fstrcpy(lookup,argv[i]); - - if(lookup_by_ip) - { - strcpy(lookup,"*"); - ip = *interpret_addr2(argv[i]); - printf("Looking up status of %s\n",inet_ntoa(ip)); - name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL); - printf("\n"); - continue; - } - - 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); - - /* We can only do find_status if the ip address returned - was valid - ie. name_query returned true. - */ - 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"); - } - } - else - { - printf("name_query failed to find name %s\n", lookup); - } - } - - return(0); -} diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c deleted file mode 100644 index d20ff42c0e8..00000000000 --- a/source/utils/smbpasswd.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * 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" - -/* 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 [-add] [username] [password]\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; - BOOL add_user = False; - int add_pass = 0; - 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(); - -#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 and add a user. */ - if (argc > 4 ) - usage(argv[0]); - } - else if (argc == 2 || argc > 3) - { - fprintf(stderr, "%s: Only root can set anothers password.\n", argv[0]); - usage(argv[0]); - } - - if (real_uid == 0 && (argc > 1)) - { - /* We are root - check if we should add the user */ - if ((argv[1][0] == '-') && (argv[1][1] == 'a')) - add_user = True; - - if(add_user && (argc <= 2 || argc > 4)) - usage(argv[0]); - - /* root can specify password on command-line */ - if (argc == (add_user ? 4 : 3)) - { - /* -a argument (add_user): new password is 3rd argument. */ - /* no -a argument (add_user): new password is 2nd argument */ - - add_pass = add_user ? 3 : 2; - } - - /* If we are root we can change another's password. */ - strncpy(user_name, add_user ? argv[2] : argv[1], sizeof(user_name) - 1); - user_name[sizeof(user_name) - 1] = '\0'; - - pwd = getpwnam(user_name); - } - else - { - /* non-root can specify old pass / new pass on command-line */ - if (argc == 3) - { - /* non-root specifies new password as 2nd argument */ - add_pass = 2; - } - - 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) - { - if (add_pass) - { - /* old password, as non-root, is 1st argument */ - strncpy(old_passwd, argv[1], sizeof(fstring)); - } - else - { - p = getpass("Old SMB password:"); - strncpy(old_passwd, p, sizeof(fstring)); - } - old_passwd[sizeof(fstring)-1] = '\0'; - } - - if (add_pass) - { - /* new password is specified on the command line */ - strncpy(new_passwd, argv[add_user ? 3 : 2], sizeof(new_passwd) - 1); - new_passwd[sizeof(new_passwd) - 1] = '\0'; - } - else - { - 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 (strncmp(p, new_passwd, sizeof(fstring)-1)) - { - 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 - */ - fp = fopen(pfile, "r+"); - if (!fp && errno == ENOENT) { - fp = fopen(pfile, "w"); - if (fp) { - fprintf(fp, "# Samba SMB password file\n"); - fclose(fp); - fp = fopen(pfile, "r+"); - } - } - if (!fp) { - 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) { - if(add_user == False) { - 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); - } - - /* Create a new smb passwd entry and set it to the given password. */ - { - int fd; - int new_entry_length; - char *new_entry; - long offpos; - - /* The add user write needs to be atomic - so get the fd from - the fp and do a raw write() call. - */ - fd = fileno(fp); - - if((offpos = lseek(fd, 0, SEEK_END)) == -1) { - fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \ -Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno)); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - new_entry_length = strlen(pwd->pw_name) + 1 + 15 + 1 + - 32 + 1 + 32 + 1 + strlen(pwd->pw_gecos) + - 1 + strlen(pwd->pw_dir) + 1 + - strlen(pwd->pw_shell) + 1; - if((new_entry = (char *)malloc( new_entry_length )) == 0) { - fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \ -Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno)); - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - sprintf(new_entry, "%s:%u:", pwd->pw_name, pwd->pw_uid); - p = &new_entry[strlen(new_entry)]; - for( i = 0; i < 16; i++) - sprintf(&p[i*2], "%02X", new_p16[i]); - p += 32; - *p++ = ':'; - for( i = 0; i < 16; i++) - sprintf(&p[i*2], "%02X", new_nt_p16[i]); - p += 32; - *p++ = ':'; - sprintf(p, "%s:%s:%s\n", pwd->pw_gecos, - pwd->pw_dir, pwd->pw_shell); - if(write(fd, new_entry, strlen(new_entry)) != strlen(new_entry)) { - fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \ -Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno)); - /* Remove the entry we just wrote. */ - if(ftruncate(fd, offpos) == -1) { - fprintf(stderr, "%s: ERROR failed to ftruncate file %s. \ -Error was %s. Password file may be corrupt ! Please examine by hand !\n", - argv[0], pwd->pw_name, strerror(errno)); - } - fclose(fp); - pw_file_unlock(lockfd); - exit(1); - } - - fclose(fp); - pw_file_unlock(lockfd); - exit(0); - } - } else { - /* the entry already existed */ - add_user = False; - } - - /* If we are root or the password is 'NO PASSWORD' then - we don't need to check the old password. */ - if (real_uid != 0) { - if (valid_old_pwd == False) { - fprintf(stderr, "%s: User %s has no old SMB password.\n", argv[0], pwd->pw_name); - } - /* Check the old Lanman password - NULL means 'NO PASSWORD' */ - if (smb_pwent->smb_passwd != NULL) { - 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; -} - diff --git a/source/utils/status.c b/source/utils/status.c deleted file mode 100644 index 4143244ab4d..00000000000 --- a/source/utils/status.c +++ /dev/null @@ -1,526 +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,SMF_VERSION_OFFSET) != 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,SMF_VERSION_OFFSET), LOCKING_VERSION); - if(buf) - free(buf); - return 0; - } - - /* Sanity check for file contents */ - size = sb.st_size; - size -= SMF_HEADER_LENGTH; /* Remove the header */ - - /* Remove the filename component. */ - size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET); - - /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */ - if((size % SMF_ENTRY_LENGTH) != 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 oplock_type; - int i; - struct session_record *ptr; - - - TimeInit(); - setup_logging(argv[0],True); - - charset_initialise(); - - 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); - } - } - - get_myname(myhostname, NULL); - - if (!lp_load(servicesf,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); - return (-1); - } - - 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); - oplock_type = entry_scanner_p->op_type; - -#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 + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET); - for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) - { - char *p = base + (i*SMF_ENTRY_LENGTH); - struct timeval t; - int pid = IVAL(p,SME_PID_OFFSET); - int mode = IVAL(p,SME_SHAREMODE_OFFSET); - - t.tv_sec = IVAL(p,SME_SEC_OFFSET); - t.tv_usec = IVAL(p,SME_USEC_OFFSET); - oplock_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET); -#endif /* FAST_SHARE_MODES */ - - fname[sizeof(fname)-1] = 0; - - if (firstopen) { - firstopen=False; - printf("Locked files:\n"); - printf("Pid DenyMode R/W Oplock 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; - } - - if((oplock_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) - printf("EXCLUSIVE+BATCH "); - else if (oplock_type & EXCLUSIVE_OPLOCK) - printf("EXCLUSIVE "); - else if (oplock_type & BATCH_OPLOCK) - printf("BATCH "); - else - printf("NONE "); - - 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 ca364cb8c94..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(); - - 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(stdout); - } - - 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 4a2ddb7c635..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(); - - 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); -} - diff --git a/source/web/cgi.c b/source/web/cgi.c deleted file mode 100644 index 56c293985d6..00000000000 --- a/source/web/cgi.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - some simple CGI helper routines - Copyright (C) Andrew Tridgell 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 MAX_VARIABLES 512 - -struct var { - char *name; - char *value; -}; - -static struct var variables[MAX_VARIABLES]; -static int num_variables; - - -static int grab_line(int *cl, char *line, int maxsize) -{ - int i = 0; - - while ((*cl)) { - int c = fgetc(stdin); - (*cl)--; - - if (c == EOF) { - (*cl) = 0; - break; - } - - if (c == '+') { - c = ' '; - } - - if (c == '\r') continue; - - if (strchr("\n&", c)) break; - - if (c == '%' && (*cl) >= 2) { - int c1, c2; - c1 = fgetc(stdin); - c2 = fgetc(stdin); - (*cl) -= 2; - if (c1 == EOF || c2 == EOF) break; - if (c1 >= '0' && c1 <= '9') - c1 = c1 - '0'; - else if (c1 >= 'A' && c1 <= 'F') - c1 = 10 + c1 - 'A'; - else if (c1 >= 'a' && c1 <= 'f') - c1 = 10 + c1 - 'a'; - else break; - - if (c2 >= '0' && c2 <= '9') - c2 = c2 - '0'; - else if (c2 >= 'A' && c2 <= 'F') - c2 = 10 + c2 - 'A'; - else if (c2 >= 'a' && c2 <= 'f') - c2 = 10 + c2 - 'a'; - else break; - - c = (c1<<4) | c2; - } - - line[i++] = c; - - if (i == maxsize) break; - } - - /* now unescape the line */ - - - line[i] = 0; - return 1; -} - - -/*************************************************************************** - load all the variables passed to the CGI program - ***************************************************************************/ -void cgi_load_variables(void) -{ - static pstring line; - char *p; - int len; - - if (!(p=getenv("CONTENT_LENGTH"))) return; - - len = atoi(p); - - if (len <= 0) return; - - - - while (len && grab_line(&len, line, sizeof(line)-1)) { - p = strchr(line,'='); - if (!p) continue; - - *p = 0; - - variables[num_variables].name = strdup(line); - variables[num_variables].value = strdup(p+1); - - if (!variables[num_variables].name || - !variables[num_variables].value) - continue; - -#if 0 - printf("%s=%s<br>\n", - variables[num_variables].name, - variables[num_variables].value); -#endif - - num_variables++; - if (num_variables == MAX_VARIABLES) break; - } - - fclose(stdin); -} - - -/*************************************************************************** - find a variable passed via CGI - ***************************************************************************/ -char *cgi_variable(char *name) -{ - int i; - - for (i=0;i<num_variables;i++) - if (strcmp(variables[i].name, name) == 0) - return variables[i].value; - return NULL; -} - - -/*************************************************************************** - return the value of a CGI boolean variable. - ***************************************************************************/ -int cgi_boolean(char *name, int def) -{ - char *p = cgi_variable(name); - - if (!p) return def; - - return strcmp(p, "1") == 0; -} diff --git a/source/wsmbconf.c b/source/wsmbconf.c deleted file mode 100644 index 203952c204f..00000000000 --- a/source/wsmbconf.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - html smb.conf editing - prototype only - Copyright (C) Andrew Tridgell 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" -#include "smb.h" - -#define SDEFAULTS "Service defaults" -#define SGLOBAL "Global Parameters" -#define GLOBALS_SNUM -2 -#define DEFAULTS_SNUM -1 - - -/* start the page with standard stuff */ -static void print_header(void) -{ - printf("Content-type: text/html\n\n"); - printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"); - printf("<HTML>\n<HEAD>\n<TITLE>smb.conf</TITLE>\n</HEAD>\n<BODY>\n\n"); -} - - -/* finish off the page */ -static void print_footer(void) -{ - printf("\n</BODY>\n</HTML>\n"); -} - -/* setup persisant variables */ -static void set_persistent(char *name) -{ - char *p; - p = cgi_variable(name); - if (!p) return; - printf("<input type=hidden name=%s value=%s>\n", name, p); -} - -/* display a servce, ready for editing */ -static void show_service(int snum, int allparameters) -{ - int i = 0; - pstring label, value; - char *sname; - - if (snum == GLOBALS_SNUM) - sname = SGLOBAL; - else if (snum == DEFAULTS_SNUM) - sname = SDEFAULTS; - else sname = lp_servicename(snum); - - printf("\n<p><table border=0>\n<tr>\n<td></td><td>\n\n"); - printf("<form method=POST>\n"); - printf("<H3>%s</H3>\n", sname); - printf("<input type=hidden name=service value=\"%s\">\n", sname); - printf("<input type=submit name=request value=Change>\n"); - printf("<input type=submit name=request value=Rename>\n"); - printf("<input type=submit name=request value=Copy>\n"); - printf("<input type=submit name=request value=Remove>\n"); - printf("<br><input name=newvalue><br>\n"); - printf("<select name=parameter size=5>\n"); - - while (lp_next_parameter(snum, &i, label, value, allparameters)) { - printf("<option value=\"%s\">%s = %s\n", - label, label, value); - } - - printf("</select>\n"); - printf("</form>\n</td>\n</tr>\n</table>\n"); - - printf("<p>\n"); -} - - -/* loop over all services, displaying them one after the other */ -static void show_services(void) -{ - int i; - int n; - int allparameters = cgi_boolean("allparameters", 0); - - printf("<FORM METHOD=POST>\n"); - printf("<p>Show all parameters?\n"); - printf("<INPUT NAME=allparameters TYPE=checkbox VALUE=1 %s>\n", - allparameters?"CHECKED":""); - - printf("<INPUT TYPE=submit NAME=reload VALUE=Reload>\n"); - - printf("</FORM>\n"); - - n = lp_numservices(); - - show_service(GLOBALS_SNUM, allparameters); - show_service(DEFAULTS_SNUM, allparameters); - - for (i=0;i<n;i++) - if (VALID_SNUM(i)) - show_service(i, allparameters); -} - - -/* load the smb.conf file into loadparm. this also does the chroot - to the config directory. This must be called _BEFORE_ any client - supplied data is parsed */ -static int load_config(void) -{ - static pstring servicesf = CONFIGFILE; - char *p; - - p = strrchr(servicesf,'/'); - if (!p) return 0; - - *p = 0; - - setuid(0); - - if (chdir(servicesf) || chroot(servicesf)) { - printf("wsmbconf is not configured correctly\n"); - return 0; - } - - *p = '/'; - - if (!lp_load(p,False)) { - printf("<b>Can't load %s - using defaults</b><p>\n", - servicesf); - } - return 1; -} - - -static int save_reload(void) -{ - static pstring servicesf = CONFIGFILE; - char *p; - FILE *f; - - p = strrchr(servicesf,'/'); - if (!p) return 0; - - f = fopen(p,"w"); - if (!f) { - printf("failed to open %s for writing\n", servicesf); - return 0; - } - - fprintf(f, "# Samba config file created using wsmbconf\n"); - - lp_dump(f); - - fclose(f); - - lp_killunused(NULL); - - if (!lp_load(p,False)) { - printf("Can't reload %s\n", servicesf); - return 0; - } - - return 1; -} - -static void process_requests(void) -{ - char *req = cgi_variable("request"); - char *newvalue = cgi_variable("newvalue"); - char *parameter = cgi_variable("parameter"); - char *service = cgi_variable("service"); - int snum=0; - - if (!req) return; - - if (service) { - /* work out what service it is */ - if (strcmp(service,SGLOBAL) == 0) { - snum = GLOBALS_SNUM; - } else if (strcmp(service,SDEFAULTS) == 0) { - snum = DEFAULTS_SNUM; - } else { - snum = lp_servicenumber(service); - if (snum < 0) return; - } - } - - if (!newvalue) - newvalue = ""; - - if (strcmp(req,"Change") == 0) { - /* change the value of a parameter */ - if (!parameter || !service) return; - - lp_do_parameter(snum, parameter, newvalue); - } else if (strcmp(req,"Rename") == 0) { - /* rename a service */ - if (!newvalue || !service) return; - - lp_rename_service(snum, newvalue); - } else if (strcmp(req,"Remove") == 0) { - /* remove a service */ - if (!service) return; - - lp_remove_service(snum); - } else if (strcmp(req,"Copy") == 0) { - /* copy a service */ - if (!service || !newvalue) return; - - lp_copy_service(snum, newvalue); - } - - save_reload(); -} - - -int main(int argc, char *argv[]) -{ - extern FILE *dbf; - - print_header(); - - dbf = stderr; - - charset_initialise(); - - if (load_config()) { - cgi_load_variables(); - process_requests(); - show_services(); - } - print_footer(); - return 0; -} diff --git a/source/wsmbstatus.c b/source/wsmbstatus.c deleted file mode 100644 index 2762b8610e7..00000000000 --- a/source/wsmbstatus.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - html status reporting - Copyright (C) Andrew Tridgell 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" - -static void print_header(void) -{ - printf("Content-type: text/html\n\n"); - printf("<HTML>\n<HEAD>\n<TITLE>smbstatus</TITLE>\n</HEAD>\n<BODY>\n\n"); -} - -static void print_footer(void) -{ - printf("\n</BODY>\n</HTML>\n"); -} - -static void show_connections(void) -{ - static pstring servicesf = CONFIGFILE; - pstring fname; - FILE *f; - struct connect_record crec; - - if (!lp_load(servicesf,False)) { - printf("Can't load %s - run testparm to debug it\n", servicesf); - return; - } - - 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; - } - - - printf("\nSamba version %s\n<p>",VERSION); - - while (!feof(f)) { - if (fread(&crec,sizeof(crec),1,f) != 1) - break; - if (crec.magic == 0x280267 && process_exists(crec.pid)) { - printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s<br>", - crec.name,uidtoname(crec.uid), - gidtoname(crec.gid),crec.pid, - crec.machine,crec.addr, - asctime(LocalTime(&crec.start))); - } - } - fclose(f); -} - -int main(int argc, char *argv[]) -{ - print_header(); - show_connections(); - print_footer(); - return 0; -} |