mars_nwe-0.99.pl19

This commit is contained in:
Mario Fetka 2011-11-13 00:38:59 +01:00
parent 5c18363271
commit c1c64c1591
75 changed files with 11044 additions and 4466 deletions

1687
connect.c

File diff suppressed because it is too large Load Diff

121
connect.h
View File

@ -1,29 +1,7 @@
/* connect.h 01-Feb-98 */
/* connect.h 04-Apr-00 */
#ifndef _CONNECT_H_
#define _CONNECT_H_
/* some TRUSTEE defines */
#define TRUSTEE_R 0x01 /* Read Rights */
#define TRUSTEE_W 0x02 /* Write Rights */
#define TRUSTEE_O 0x04 /* Open, not used ?? by Novell */
#define TRUSTEE_C 0x08 /* Creat */
#define TRUSTEE_E 0x10 /* Erase */
#define TRUSTEE_A 0x20 /* Access Control */
#define TRUSTEE_F 0x40 /* File Scan */
#define TRUSTEE_M 0x80 /* Modify */
/* ........................................ */
#define TRUSTEE_S 0x100 /* Supervisor */
/* <-------------- File Attributes -------------> */
#define FILE_ATTR_NORMAL 0x00000000
#define FILE_ATTR_R 0x00000001
#define FILE_ATTR_H 0x00000002
#define FILE_ATTR_S 0x00000004
#define FILE_ATTR_DIR 0x00000010
#define FILE_ATTR_A 0x00000020
#define FILE_ATTR_SHARE 0x00000080
typedef struct {
uint8 path[256]; /* directory */
uint8 fn[256]; /* file */
@ -33,8 +11,7 @@ typedef struct {
typedef struct {
uint8 name[14]; /* filename in DOS format */
uint8 attrib; /* Attribute */
uint8 ext_attrib; /* File Execute Type */
uint8 attrib[2]; /* LO-HI attrib, ext_attrib */
uint8 size[4]; /* size of file */
uint8 create_date[2];
uint8 acces_date[2];
@ -44,8 +21,7 @@ typedef struct {
typedef struct {
uint8 name[14]; /* dirname */
uint8 attrib;
uint8 ext_attrib;
uint8 attrib[2]; /* LO-HI attrib, ext_attrib */
uint8 create_date[2];
uint8 create_time[2];
uint8 owner_id[4];
@ -63,7 +39,7 @@ typedef struct {
typedef struct {
uint8 subdir[4];
uint8 attributes[4]; /* 0x20,0,0,0 File */
uint8 attributes[4]; /* 0x20,0,0,0 LO-HI */
uint8 uniqueid; /* 0 */
uint8 flags; /* 0x18 */
uint8 namespace; /* 0 */
@ -81,7 +57,7 @@ typedef struct {
typedef struct {
uint8 subdir[4];
uint8 attributes[4]; /* 0x10,0,0,0 DIR */
uint8 attributes[4]; /* 0x10,0,0,0 LO-HI */
uint8 uniqueid; /* 0 */
uint8 flags; /* 0x14 or 0x1c */
uint8 namespace; /* 0 */
@ -106,11 +82,22 @@ typedef struct {
} u;
} NW_SCAN_DIR_INFO;
typedef struct {
uint8 searchsequence[4]; /* same as NW_SCAN_DIR_INFO */
uint8 change_bits[4]; /* LO-HI, 2=Attributes */
union {
NW_DOS_DIR_INFO d;
NW_DOS_FILE_INFO f;
} u;
} NW_SET_DIR_INFO;
extern int use_mmap;
extern int tells_server_version;
extern int server_version_flags;
extern int max_burst_send_size;
extern int max_burst_recv_size;
extern int default_uid;
extern int default_gid;
extern int nw_init_connect(void);
extern void nw_exit_connect(void);
@ -120,20 +107,25 @@ extern int nw_free_handles(int task);
extern int nw_creat_open_file(int dir_handle, uint8 *data, int len,
NW_FILE_INFO *info, int attrib, int access, int mode, int task);
extern int nw_delete_datei(int dir_handle, uint8 *data, int len);
extern int nw_delete_files(int dir_handle, int searchattrib, uint8 *data, int len);
extern int nw_set_file_information(int dir_handle, uint8 *data, int len,
int searchattrib, NW_FILE_INFO *f);
extern int nw_set_file_attributes(int dir_handle, uint8 *data, int len,
int attrib, int newattrib);
extern int mv_file(int qdirhandle, uint8 *q, int qlen,
int zdirhandle, uint8 *z, int zlen);
extern int nw_mv_files(int searchattrib,
int sourcedirhandle, uint8 *sourcedata, int qlen,
int zdirhandle, uint8 *destdata, int destdatalen);
extern int mv_dir(int dir_handle, uint8 *q, int qlen,
uint8 *z, int zlen);
extern int mv_dir(int dir_handle, uint8 *sourcedata, int qlen,
uint8 *destdata, int destdatalen);
extern int nw_creat_node(int volnr, uint8 *unname, int mode);
extern int nw_unlink_node(int volume, uint8 *unname, struct stat *stb);
extern int nw_creat_node(int volume, uint8 *unname, int mode);
extern int nw_utime_node(int volume, uint8 *unname, struct stat *stb,
time_t t);
extern int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode);
@ -163,7 +155,8 @@ extern int nw_alloc_dir_handle(
int driveletter, /* A .. Z normal */
int is_temphandle, /* temp Handle 1 */
/* spez. temp Handle 2 */
int task); /* Prozess Task */
int task, /* Prozess Task */
int *eff_rights);
extern int nw_open_dir_handle( int dir_handle,
@ -182,7 +175,7 @@ extern int alter_dir_handle(int targetdir, int volume, uint8 *path,
extern int nw_set_dir_handle(int targetdir, int dir_handle,
uint8 *data, int len, int task);
extern int nw_get_directory_path(int dir_handle, uint8 *name);
extern int nw_get_directory_path(int dir_handle, uint8 *name, int size_name);
extern int nw_get_vol_number(int dir_handle);
@ -199,24 +192,29 @@ extern int nw_scan_dir_info(int dir_handle, uint8 *data, int len,
extern void get_dos_file_attrib(NW_DOS_FILE_INFO *f,
struct stat *stb,
int volume,
uint8 *path);
uint8 *path,
char *unixname);
void get_dos_dir_attrib(NW_DOS_DIR_INFO *f,
struct stat *stb,
int volume,
uint8 *path);
uint8 *path,
char *unixname);
#define MAX_NW_DIRS 255
extern int act_uid;
extern int act_gid;
extern int act_obj_id; /* not login == 0 */
extern int act_id_flags; /* &1 == supervisor equivalence !!! */
extern int entry8_flags; /* special flags, see examples nw.ini, entry 8 */
extern int entry31_flags; /* special flags, see examples nw.ini, entry 31 */
extern int conn_get_full_path(int dirhandle, uint8 *data, int len,
uint8 *fullpath);
uint8 *fullpath, int size_fullpath);
extern int conn_get_kpl_unxname(char *unixname,
int size_unixname,
int dirhandle,
uint8 *data, int len);
@ -225,14 +223,15 @@ extern void set_guid(int gid, int uid);
extern void reset_guid(void);
extern void reseteuid(void);
extern int in_act_groups(gid_t gid);
extern int get_unix_eff_rights(struct stat *stb);
extern void set_nw_user(int gid, int uid,
int id_flags,
uint32 obj_id, uint8 *objname,
int homepathlen, uint8 *homepath);
int unxloginlen, uint8 *unxloginname,
int grpcount, uint32 *grps);
extern int get_real_access(struct stat *stb);
extern uint32 get_file_owner(struct stat *stb);
extern int nw_scan_a_directory(uint8 *rdata,
int dirhandle,
uint8 *data,
@ -243,18 +242,18 @@ extern int nw_scan_a_directory(uint8 *rdata,
extern int nw_scan_a_root_dir(uint8 *rdata,
int dirhandle);
extern int nw_set_a_directory_entry(int dirhandle,
uint8 *data,
int len,
int searchattrib,
uint32 searchbeg,
NW_SET_DIR_INFO *f);
extern int fn_dos_match(uint8 *s, uint8 *p, int options);
extern void un_date_2_nw(time_t time, uint8 *d, int high_low);
extern time_t nw_2_un_time(uint8 *d, uint8 *t);
#if !NEW_ATTRIB_HANDLING
extern int un_nw_attrib(struct stat *stb, int attrib, int mode);
#endif
extern int un_nw_rights(struct stat *stb);
extern void un_time_2_nw(time_t time, uint8 *d, int high_low);
extern void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp);
@ -262,5 +261,29 @@ extern void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp);
extern int nw_add_trustee(int dir_handle, uint8 *data, int len,
uint32 id, int trustee, int extended);
extern int nw_del_trustee(int dir_handle, uint8 *data, int len,
uint32 id, int extended);
extern int nw_set_dir_info(int dir_handle, uint8 *data, int len,
uint32 owner_id, int max_rights,
uint8 *creationdate, uint8 *creationtime);
extern int nw_scan_user_trustee(int volume, int *sequence, uint32 id,
int *access_mask, uint8 *path);
extern int nw_scan_for_trustee( int dir_handle,
int sequence,
uint8 *path,
int len,
int max_entries,
uint32 *ids,
int *trustees,
int extended);
extern int nw_log_file(int lock_flag,
int timeout,
int dir_handle,
int len,
char *data);
#endif

View File

@ -1,4 +1,4 @@
/* dbmtool.c 08-Sep-96 data base tool program for mars_nwe */
/* dbmtool.c 10-Nov-99 data base tool program for mars_nwe */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -32,18 +32,23 @@ static int usage(char *s)
fprintf(stderr, "\te = export\n");
fprintf(stderr, "\ti = import\n");
fprintf(stderr, "\tr = repair\n");
fprintf(stderr, "\tE = Export To DIR\n");
return(1);
}
int main(int argc, char *argv[])
{
init_tools(0, 0);
nw_debug=5;
if (argc < 2) return(usage(argv[0]));
if (*argv[1] == 'e') return(do_export_dbm(argv[2]));
else if (*argv[1] == 'i') return(do_import_dbm(argv[2]));
else if (*argv[1] == 'r') if (!do_export_dbm(argv[2]))
else if (*argv[1] == 'r') {
if (!do_export_dbm(argv[2]))
return(do_import_dbm(argv[2]));
else return(1);
}
if (*argv[1] == 'E') return(do_export_dbm_to_dir());
else usage(argv[0]);
return(0);
}

View File

@ -15,6 +15,8 @@
#define D_FN_NAMES 8
#define D_FN_SEARCH 0x10 /* file search */
#define D_ACCESS 0x20 /* access rights */
#define D_TRUSTEES 0x40 /* trustees */
/* NWBIND */
#define D_BIND_REQ 0x8000 /* all Requests */

43
doc/BUGS.nl Normal file
View File

@ -0,0 +1,43 @@
Als je problemen heb:
-----------------
- Kijk of je in de kernel wel IPX heb geinstalleerd
CONFIG_IPX=y ( of m en het ipx module is geladen (insmod ipx))
- Kijk of je geen intern IPX netwerk hebt geinstalleerd 'full
internal net'. (kernel optie)
CONFIG_IPX_ITERN=n
- Lees altijd de documentatie: doc/INSTALL[.ger/.nl],
doc/README[.ger/.nl], doc/FAQS en examples/nw.ini
Zeer belangrijke secties in nwserv.conf(nw.ini) zijn:
Sectie 1: Volumes
Sectie 3: Number of the internal network
Sectie 4: IPX-devices
Sectie 5: device flags
Sectie 6: version-"spoofing"
Sectie 12: supervisor-login
Als je niet kunt inloggen, probeer het dan eens met de meegeleverde
configuratie bestanden, zonder deze te veranderen.
- Belangrijk nieuws staat in doc/NEWS.
- zet de debug switches in sectie 101 .. 10x op '1',
probeer het opnieuw met het herstarten van nwserv en kijk in het
log bestand in /tmp/nw.log
Misschien begrijp je het probleem dan. :)
Sommige kleine aantekeningen voor probleem- of bug-'reporters'.
---------------------------------------------------------------
- Geef je systeem waarop je draait door en de volledige mars_nwe
versie, bijvoorbeeld:
mars_nwe versie: 0.99.pl14
linux-kernel: 2.2.0p9
het type client: (NCPFS, DOS (NETX/VLM), OS2, WIN, Novell client
32 WIN ..)
de veranderingen in nwserv.conf(nw.ini) en de config.h
- als je nwserv.conf opstuurd, haal het commentaar eruit.
doe dit door in te tikken 'make showconf' in de mars_nwe source dir
of doe 'grep "^[ \t*[0-9]" /etc/nwserv.conf'
- vermeld of je client wel loopt met een 'echte Novell-server'
(als je er een hebt. ;) )
Bekende problemen / oplossingen:
--------------------------------
- kijk is doc/FAQS

View File

@ -1,6 +1,8 @@
Sorry, this is in German only.
Sorry, beginning is in German only.
User important notes are in the NEWS file.
Aenderungen in mars_nwe bis zum : 03-Nov-97
Aenderungen in mars_nwe bis zum:
Changes in mars_nwe till:
=> 30-May-00 <=
--------------------------------
Erste 'oeffentliche' Version
^^^^^^^^^^ VERSION 0.94 ^^^^^^^^
@ -408,6 +410,131 @@ Erste 'oeffentliche' Version
- archive bit ist bei Dateien nun default gesetzt.
- archive bit wird nun bei Client Schreiboperationen gesetzt.
<----- ^^^^^^^^^^ pl6 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- in examples/config.h. NEW_ATTRIB_HANDLING removed.
- connect.c: nw_dir_search() corrected for new get_dir_attrib.
- changed some includes and defines for (g)libc6 / RH5.
- added some fixes from Andrew Sapozhnikov <sapa@hq.icb.chel.su>
fixed prop_find_member bug, !!!!!!!! VERY important !!!!!!
fixed add and delete property_val,
fixed dos search routine.
- new startup bindery check/compress routine.
- prop_delete_member changed to avoid holes (id==0) in a set section.
- bindery function creat_new_db() now saves old files to xyz/nwdbm.sav/.
<----- ^^^^^^^^^^ pl7 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- queue code changed. WinNT did not print every job.
should also solve some strange problems under W95 and dos clients.
- old dos search routine is now reused again for namespace calls, because
new dos search routine from Andrew did not work with this calls.
( xcopy32 *.* did not work for for non OS/2 namespace volumes )
<----- ^^^^^^^^^^ pl8 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- nwqconn.c:open_creat_queue_file(): insert missing nw_free_dir_handle()
- nwdbm.c: enhanced section 22, now normal user/client may act as print-
qserver.
- nwfile.c: removed bug in file read routine when reading a pipe.
- nwqueue.c: nw_service_queue_job()
queue files of length 0 are now deleted automaticly 1 minute
after creation, if they are serviced by a queue server.
- nwqueue.c: new: nw_close_connection_jobs()
- nwqconn.c: new: free_connection_task_jobs()
- added first simple trustee routines. ( new volume switch 't' )
see doc/TRUSTEES
- added supervisor security equals handling.
- changed device configurator a little bit so that running
ipx programs like ncpmount will not be killed by a
starting or stopping nwserv.
- changed default attrib/trustee location from /var/lib/nwserv -> /var/nwserv
- some cleanings to make UnixWare happy.
- close_file() only closes file if task correspond with file opened task.
Do not know whether this is ok, but it seems so.
Programs like Visual C linker (Borland,MS) now work correct.
<----- ^^^^^^^^^^ pl9 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- changed call 0x17, 0x0f, to let it handle only files not directories.
(mask 0x10 attrib flag )
- new dos search routine (from pl7) changed to handle '*' correct, for
example the call 0x17, 0x0f is called by syscons change file trustees
with '*' as searchstring. Also changed to handle '*xyz.xyz' in a
more restrictive way. I hope this is correct now.
<----- ^^^^^^^^^^ pl10 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ncp call 0x7a (read queue job entry (new)) is now availible.
<----- ^^^^^^^^^^ pl11 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- changed default bindery directory location:
/etc -> /var/nwserv/db ( section 45 )
- possibility to unset the print banner flag.
( some strange W95 printer drivers always set banner flag to TRUE )
- port to FreeBSD by Boris Popov <bp@butya.kz>
<----- ^^^^^^^^^^ pl12 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- small FreeBSD patch from Boris Popov. (nwroute1.c)
- added diagnostic-answers routine from Valeri Bourak. (nwserv.c)
- small pipe-filesystem patches.
- changed example programs (unxcomm/comm) for pipe-filesystem access.
- BUG in unx_xrmdir(),unxfile.c removed, opendir() was called twice.
- added namespace calls (0x57) add,delete trustee routines.
- new function 'Get Queue Job List' (0x17,0x81) added.
- new function 'Set Queue Status' (0x17,0x67/0x7e) added.
- debug/log file now with date/time
- nw_close_file() now closes files again which were opened
with different task. ( was inserted in pl9 )
- open_creat_queue_file() routine only sets the file noreuse flag
if file is opened for writing.
- fn_dos_match routine corrected, was broken in pl7. ( ndir.exe works again )
<----- ^^^^^^^^^^ pl13 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- now section 1 permissions works for '~' ('HOME') entries too
- get_fs_usage now also sets fsu_bavail to limit.
- new flag 'T' for volumes which has trustees & ignore the rights granted
in UN*X filesystem, added by Norbert Nemec <nobbi@cheerful.com>
- added 'inherited_rights_mask handling' to some routines.
- nwfile.c. Filehandle can now be used for more than one open.
Don't know whether this is correct. Under W95 client the dos
programm 'blinker' needs it.
- nw_rmdir() in connect.c now returns correct error code if directory
cannot be removed because it is not empty.
<----- ^^^^^^^^^^ pl14 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- doc/PIPE-FS.ger with new examples from Sascha Herrmann
- added '#define _SVID_SOURCE' and '#define _XOPEN_SOURCE'
in net.h to let mars_nwe work with glibc.
- connect.c, free_dir_stuff(), correcting error when recursively deleting a
largish directory tree, hint from Boris Popov, 21-Feb-99.
- Get Queue Job List (new) now returns info in right byte order.
Error appeared under Win9x with Novell Client32 when printing.
( segmentation error in spool32 ) bug corrected by georg@globaltrading.net.
<----- ^^^^^^^^^^ pl15 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- docs from Mendel Mobach (xxx.nl)
- some fixes to let mars_nwe compile under 2.2.x kernels.
- some BSD fixes from Boris Popov
- fix from Paolo Prandini for the wrong return code when an user without
supervisory rights tries to shutdown the server
- nw_open_creat_file_or_dir() now does not creat file if called with
opencreatmode==8 and file already exist. ( important for Win98 )
- dos 'rename files' now works with wildcards on both side (source and dest)
- nw_close_file() normally do not close files which were opened
with different task ( same as in pl9 ). But files are allways closed if
they are created with task 0 or if current task = 0.
- Routine which opened same file for more than one time deactivated,
because share conditions were wrong. Function was added in pl14.
Perhaps this routine will not be needed anymore.
- new signal SIGUSR2 for nwconn process to give info about open files.
the loginfo is placed into /tmp/nwconnxxxx.log
<----- ^^^^^^^^^^ pl16 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- rename file corrected. Error inserted in 0.99.pl16
- small patch in tools.c ( initialisation of logfile )
<----- ^^^^^^^^^^ pl17 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- prevent some possible buffer overflows.
security hint from Przemyslaw Frasunek <venglin@FREEBSD.LUBLIN.PL>
- better file share/lockings, with code from
Ingmar Thiemann <ingmar@gefas.com> and Przemyslaw Czerpak
- function Log Logical Record (NCP 0x9) aktivated
and lock flag 0x2 ( sharable ro lock ) added.
- function Log File (NCP 0x3) aktivated
and lock flag 0x2 ( sharable ro lock ) added.
- Clear File / Release File added.
- passwords with '-' at beginning should now be allowed in nwserv.conf.
- better trustee handling.
<----- ^^^^^^^^^^ pl18 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- security fixes. ( unlink() before fopen() )
- fixed routine 0x57/0x18, Get Name Spaces Loaded
- Login Restriction Routines from Paolo Prandini
- removed bug from pl18 for empty passwords and
passwords beginning with '-'. ( tnx Przemyslaw Czerpak )
- trustee fix
<----- ^^^^^^^^^^ pl19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -16,6 +16,9 @@ Guntram Blohm <gbl%th7csun1@str.daimler-benz.com>
Uwe Bonnes <bon@elektron.ikp.physik.th-darmstadt.de>
many testings+notes
Valeri Bourak <bvn@kali.belpak.minsk.by>
added some code
Arne de Bruijn <arne@knoware.nl>
testings, exploring ncp mysterius (netx), notes
@ -26,17 +29,26 @@ Csoma Csaba <csoma@usa.net>
testings+bugfixes
Przemyslaw Czerpak <przemyslaw.czerpak@students.mimuw.edu.pl>
testings+bugfixes
testings+bugfixes+more bugfixes (pcz:)
Ales Dryak <A.Dryak@sh.cvut.cz>
his linware gave the kick
Fritz Elfert <fritz@wuemaus.franken.de>
gives bugreport and patches
give bugreport and patches
Przemyslaw Frasunek <venglin@FreeBSD.lublin.pl>
hints for possible security bugs
Peter Gerhard <pgerhard@jpn.tuv.com>
testings, bugreport, patches.
Georg <georg@globaltrading.net>
fixed bug with print queue handling.
Sascha Herrmann <sascha@system.rhein-main.de>
docs, scripts
Victor Khimenko <khim@mccme.ru>
cyrillic filename patches
@ -61,9 +73,21 @@ James B. MacLean <macleajb@ednet.ns.ca>
Louis Zammit Mangion <lzamm@phys.um.edu.mt>
testings+bugfixes
Mendel Mobach <mendel@mobach.nl>
some doku
Norbert Nemec <nobbi@cheerful.com>
some patches
Matt Paley <mtpa@mail.nerc-bas.ac.uk>
adding QUOTA support, login time restrictions
Boris Popov <bp@butya.kz>
ported mars_nwe to FreeBSD
Paolo Prandini <prandini@spe.it>
added login control routines
Jiri A. Randus <Jiri.Randus@vslib.cz>
testing bindery code
@ -76,8 +100,13 @@ Mr. Charlie Root (alexey) <root@cs.imi.udmurtia.su>
Andrew Sapozhnikov <sapa@hq.icb.chel.su>
fixed findfirst/findnext bug,
fixed directory access bug,
added extend "Volume is home" feature.
fixed "rename wildcard" bug.
added extend "Volume is home" feature,
fixed "rename wildcard" bug,
fixed prop_find_member bug,
fixed x_str_match (DOS match) routine.
Christoph Scheeder <christoph.scheeder@scheeder.de>
added TRUSTEE_T flag
Hayo Schmidt <100305.1424@compuserve.com>
added patch to let ATARI client work.
@ -85,13 +114,20 @@ Hayo Schmidt <100305.1424@compuserve.com>
Gregory Steuck <greg@nsu.ru>
testings and errorreports
Neal Stephenson <neal@nstephenson.gw.yorku.ca>
patch for glibc6
Morio Taneda <eb04@rz.uni-karlsruhe.de>
testings, bugfixes
Erik Thiele <erik@escape.mos.unterland.de>
testings and doc
Winfried Truemper <winni@xpilot.org>:
Ingmar Thiemann <ingmar@gefas.com>
added patches for better file locking/sharing
Winfried Truemper <winni@xpilot.org>
re-wrote `INSTALL' and added explanations to `nw.ini'
Jukka Ukkonen <jau@iki.fi>
small patches

View File

@ -1,4 +1,4 @@
last updated: 14-Jul-97
last updated: 21-Feb-99
Q: Which DOS programs from the real Netware do I need?
A: For a minimal configuration you only need LOGIN.EXE.
@ -10,6 +10,10 @@ A: For a minimal configuration you only need LOGIN.EXE.
There is also a DOS client program in development, which will allow
the use of mars_nwe without the original Novell DOS tools.
Q: Do I need a device called '/dev/ipx', because I found references in mars_nwe
A: When you use Linux, no. These references are only used under OS-es with
TLI interfaces like UnixWare (tm)
Q: I don't exactly understand the meaning of some points in nw.ini:
12,13
What will happen if I do not put PASSWORD here? Will it take it from

85
doc/FILESHARING Normal file
View File

@ -0,0 +1,85 @@
Filesharing, tested with function 0x4c on a real Novell Server.
(+) = Openfile OK
(-) = Openfile fail
FILE OPEN (NCP 0x4C) with SHARE Flag set. Tested with NW312
-------------------------------------------------------------------------------------------------------------
11 |11(+) |12(+) |13(+) |01(+) |02(+) |03(+) |09(+) |0a(+) |0b(+) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
12 |11(+) |12(+) |13(+) |01(+) |02(+) |03(+) |09(-) |0a(-) |0b(-) |05(+) |06(+) |07(+) |0d(-) |0e(-) |0f(-) |
13 |11(+) |12(+) |13(+) |01(+) |02(+) |03(+) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
01 |11(+) |12(+) |13(+) |01(+) |02(+) |03(+) |09(+) |0a(+) |0b(+) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
02 |11(+) |12(+) |13(+) |01(+) |02(+) |03(+) |09(-) |0a(-) |0b(-) |05(+) |06(+) |07(+) |0d(-) |0e(-) |0f(-) |
03 |11(+) |12(+) |13(+) |01(+) |02(+) |03(+) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
09 |11(+) |12(-) |13(-) |01(+) |02(-) |03(-) |09(+) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0a |11(+) |12(-) |13(-) |01(+) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(+) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0b |11(+) |12(-) |13(-) |01(+) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
05 |11(-) |12(+) |13(-) |01(-) |02(+) |03(-) |09(-) |0a(+) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
06 |11(-) |12(+) |13(-) |01(-) |02(+) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(+) |07(-) |0d(-) |0e(-) |0f(-) |
07 |11(-) |12(+) |13(-) |01(-) |02(+) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
0d |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0e |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0f |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
=============================================================================================================
FILE OPEN (NCP 0x4C) without SHARE Flag set. Tested with NW312
-------------------------------------------------------------------------------------------------------------
11 |11(+) |12(-) |13(-) |01(+) |02(-) |03(-) |09(+) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
12 |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
13 |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
01 |11(+) |12(-) |13(-) |01(+) |02(+) |03(+) |09(+) |0a(+) |0b(+) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
02 |11(-) |12(-) |13(-) |01(+) |02(+) |03(+) |09(-) |0a(-) |0b(-) |05(+) |06(+) |07(+) |0d(-) |0e(-) |0f(-) |
03 |11(-) |12(-) |13(-) |01(+) |02(+) |03(+) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
09 |11(+) |12(-) |13(-) |01(+) |02(-) |03(-) |09(+) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0a |11(-) |12(-) |13(-) |01(+) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(+) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0b |11(-) |12(-) |13(-) |01(+) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
05 |11(-) |12(-) |13(-) |01(-) |02(+) |03(-) |09(-) |0a(+) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
06 |11(-) |12(-) |13(-) |01(-) |02(+) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(+) |07(-) |0d(-) |0e(-) |0f(-) |
07 |11(-) |12(-) |13(-) |01(-) |02(+) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
0d |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0e |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
0f |11(-) |12(-) |13(-) |01(-) |02(-) |03(-) |09(-) |0a(-) |0b(-) |05(-) |06(-) |07(-) |0d(-) |0e(-) |0f(-) |
--
----------------
Access Modi
-----------------------------
Access | R W DR DW |
-----------------------------
0x01 | X |
0x02 | X |
0x03 | X X |
0x09 | X X |
0x0a | X X |
0x0b | X X X |
0x05 | X X |
0x06 | X X |
0x07 | X X X |
0x0d | X X X |
0x0e | X X X |
0x0f | X X X X |
-----------------------------
----------------
Handling Compatibility Access Modus.
shared | not shared
---------------------------------------------
Access | R W DR DW | R W DR DW
---------------------------------------------
0x11 | X | X X
0x12 | X | X X X
0x13 | X X | X X X X
---------------------------------------------

View File

@ -330,9 +330,7 @@ ersten Start von "nwserv" angelegt. Der Volume-Name ist ueblicherweise
"SYS".
Beim Anlegen und Eintragen der Optionen fuer das Volume SYS unbedingt
auf Gross- und Kleinschreibung achten, sonst sind diese Dateien
nachher fuer den Client nicht Sichtbar. Alle weiteren Volumes sind
Optional und koennen beliebige Verzeichnisse (ausser /) freigeben.
Auf Verzeichniss "/" hat nur der root=Supervisor Zugriff. Volumes
nachher fuer den Client nicht sichtbar. Volumes
koennen mit NFS gemountete Verzeichnisse, CD-Roms, Floppys und
beliebige unter Linux mountbare Filesystems sein. Die einzige
Einschraenkung besteht in der Beschraenkung auf entweder alles gross

View File

@ -132,5 +132,5 @@ the mars_nwe-package.
good luck :-)
Martin Stover <mstover@stover.f.eunet.de>
Martin Stover <mstover@compu-art.de>

133
doc/INSTALL.nl Normal file
View File

@ -0,0 +1,133 @@
INSTALLATIE: ( Mendel Mobach <mendel@mobach.nl>)
Dit is het bestand "INSTALL.nl", een stap-voor-stap handboek voor het
installeren van het mars_nwe-pakket.
(1) Pak een goede ipx-kernel-versie ne compileer die met IPX Support,
Maar zonder 'Full internal network'. je kun dit doen door op de
volgende manier te antwoorden op de volgende vragen tijdens het
draaien van "make config":
The IPX protocol (CONFIG_IPX) [N/m/y/?] y
Full internal IPX network (CONFIG_IPX_INTERN) [N/y/?] n
Voor algemen vragen over het compileren van een kernel, kijk in de
Linux-Kernel-HOWTO.
De beste kernels voor Mars_nwe zijn 2.0.x.
Oudere kernels werken soms niet, omdat er bugs in de ipx-code
zitten. Kijk in de directorie 'examples' voor patches.
(2) Maak hier een keuze, of de mars_nwe je ipx-subsysteem moet initialiseren
en routing beheren, of dat je dit doet met de hand met andere producten.
Voordat je een probleem mailt naar de mailinglist over problemen met
mars_nwe, probeer dit eerst.
(2a) Configureer het IPX-subsysteem met "mars_nwe"
Je hebt geen andere ipx-tool of routers/daemons nodig
in dir geval.
Dit is gestest zodat "mars_nwe", "dosemu", "ncpfs" of
Caldera's "nwclient" hiermee goed samenwerken.
zet INTERNAL_RIP_SAP op "1" in `mars_nwe/config.h':
#define INTERNAL_RIP_SAP 1
Als je andere IPX/NCP server in je lokale netwerk hebt kun je
de "mars_nwe" automatisch de goede waarde laten invullen voor je
ipx-subsysteem.
Dit houd in dat je de volgende secties in 'nwserv.conf' zo invult:
3 0x0 # Gebruik je Ipx nummer voor het interne netwerk.
4 0x0 * AUTO # autodetect je interafces.
5 0x2 # laat de kernel automatisch interfaces voor
# creeeren.
Zorg dat er geen enkele andere server is die je interne netwerk-
nummer gebruikt als zijn netwerk nummer.
Als er geen andere IPX/NCP server is op je netwerk, dan kan het netwerk
nummer in sectie '4' elk nummer zijn.
4 0x10 eth0 ethernet_ii # eth0 device met het netwerk nummer '0x10'
# en frametype: ETHERNET_II.
4 0x20 eth0 802.3 # eth0 device met het netwerk nummer '0x20'
# en frametype: ETHERNET_802.3.
(2b) Handmatige configuratie van het IPX-subsysteem
In deze mode moet je tools zoals "ipx-configure" en
"ipxd" gebruiken voor het configureren van ipx-interfaces,
ipx-routes en om rip/sap aanvragen af te handelen.
zet INTERNAL_RIP_SAP op "0" in `mars_nwe/config.h':
#define INTERNAL_RIP_SAP 0
(3) Compileer de programma's van het Mars_nwe pakker
pak de source van "mars_nwe" uit en ga naar de directorie waarin
die is uitgepakt ('mars_nwe').
Type hget volgende comando in:
make
Dit command maakt de volgende bestanden: 'config.h' en 'mk.li'.
Edit de zoals jij ze nodig hebt. 'mk.li' moet alleen veranderdt
worden onder hele rare omstandigheden, of als je problemen hebt
met het compileren en/of het linken van dit pakket.
draai nu "make" opnieuw:
make
(4) Bewerk ("edit") het configuratie bestand 'nw.ini'.
Zorg dat je zeker weet dat alle benodigde secties in je oude configuratie
bestand staan, als je upgrade naar een nieuwere versie van de "mars_nwe".
(5) Installeer alles
Zeg alleen:
make install
en soms:
make install_ini
Deze laatste is alleen nodig als je je het _bestaande_ configuratie
bestand (nwserv.conf) wilt overschrijven met nw.ini
(6) Creer de directories die te zien moete zijn voor DOS-clients
Op z'n minst moet het volume "SYS" zijn gedefineerd in het configuratie
bestand nwserv.conf. Creer de geassocieerde directory als die al niet
bestaat en zet de programma's "login.exe" en "slist.exe" in de
"LOGIN" / "login" directorie.
Je kunt ook de vrij verkrijgbare mars_dosutils gebruiken.
NIEUW !
in nieuwere versies va de MARS_NWE worden deze directories automatisch
gecreetd bij de eerste keer dat de mars_nwe server opstart.
(7) Start de server
Start het volgende programma als root op:
nwserv
(8) Stop de programma's (server plat)
Als de mars_nwe server op de voorgrond loopt kun je de server stoppen
met een ^C (CTRL-C), anders kill de PID van nwserv,tik in 'nwserv -k'
Of gebruik het dos programma fconsole en kies "server down" als je als
supervisor (of gelijke) bent aangelogd.
Sectie 210 in het "nw.ini" / "nwserv.conf" bestand geeft de tijd in
seconden voordat de server echt stop.
Veel geluk :-)
Martin Stover <mstover@compu-art.de>

View File

@ -1,3 +1,16 @@
------23-Jul-98--- 0.99.pl12 ---------
- changed default bindery directory location:
/etc -> /var/nwserv/db ( section 45 )
------10-May-98--- 0.99.pl9 ---------
- changed default attrib directory location:
/var/lib/nwserv/attrib -> /var/nwserv/attrib. ( section 46 )
- changed default rights to 751 640. (section 9 and section 1 )
- first trustee handling added. See new volume flag 't' and 'doc/TRUSTEES'.
------03-Mar-98--- 0.99.pl7 ---------
- very important BUG fixed by Andrew Sapozhnikov. <sapa@hq.icb.chel.su>
The properties find member functions could find max. 32 entries. (1 segment)
Please enable 'ckeck/compress bindery on startup' (section 16, nwserv.conf)
to let mars_nwe do some checks/compressings on old bindery entries.
------08-Feb-98--- 0.99.pl6 ---------
- archive bit handling changed. (default set if file, unset if directory)
- section 5: deleting of ipx devices/routes changed.

View File

@ -41,13 +41,14 @@ A simple print operation can be achieved with the following script:
This allows you to print under dos/windows without capturing.
In the examples dir exist the two programpairs comm<->unxcomm
and sendm<->unxsendm as additional examples for using 'PIPE-filesystem'.
With comm/unxcomm it is very easy to start simple Linux programs
by your client.
for examples: ps, lpq, lprm ...
In the examples directory there are two pairs of programs,
comm<->unxcomm und sendm<->unxsendm, that provide further examples
of how to use the PIPE-filesystem.
Using comm/unxcomm it is very easy to invoke simple Linux programs
from the client, e.g. ps, lpq, lprm ..
I would appreciate hearing about further documented applications of
the PIPE filesystem or suggestions for other ways of using it.
If anyone has other documented applications of the PIPE-filesystem,
or any suggestions about other ways it might be used, I'd be very glad
to hear from them.
Martin

View File

@ -1,4 +1,7 @@
/* PIPE- Filesystem */
1. Was sind PIPEs?
das 'PIPE Filesystem' entstand urspruenglich aus der Frage heraus:
Wie kann ich ein Linux System oder Teile davon ueber/auf einen
DOS-Rechner oder Novell Fileserver sichern.
@ -15,6 +18,10 @@ je nach Modus des ersten Zugriffes (Read oder Write).
Das 'PIPE-Filesystem' bietet damit eine direkte Schnittstelle
zwischen Client Anwendungen und Linux Programmen.
2. Beispiele
2.1 Dos->Linux, Linux->Dos Backup
Die Loesung des obigen Problems ergab sich dann mit folgendem einfachen
Shell Script, welches im PIPE-Filesystem hinterlegt wurde.
@ -37,6 +44,8 @@ lokale Datei 'kopiert' werden ( -> Sichern ) bzw. es
kann die lokale Datei auf diese 'Pipe Datei' kopiert werden.
( -> Ruecksichern )
2.2 Drucken ueber Pipes
Ein einfaches Drucken kann z.B. mit folgendem Mini Script realisiert werden.
Anstatt des Scriptes reicht in diesem Fall natuerlich auch ein link auf
/usr/bin/lpr.
@ -46,6 +55,93 @@ Anstatt des Scriptes reicht in diesem Fall natuerlich auch ein link auf
Dadurch kann ein capture unter DOS/Windows entfallen.
2.3 Private Windowsinstallation fuer jeden Netzbenutzer
(Beispiel von Sascha Herrmann <sascha@system.rhein-main.de>)
Die Idee fuer diesen Script, war auf einem Netz mit Diskless PCs, die ueber
mars-nwe ihr Dos/Windows System bekommen, fuer jeden einzelnen Benutzer eine
eigene Windowsconfiguration zu bekommen.
Hierfuer habe ich einen kleinen Shellscript geschrieben, der diese Aufgabe
bisher recht gut erledigt, ohne viel Speicherplatz zu verschwenden.
Fuer den Skript muss zunaechst einmal Windows in mehrere Teile aufgesplittet
werden, einen gemeinsamen Teil, auf den kein Schreibzugriff noetig ist
(*.exe, *.dll etc.) und einen Teil auf den Schreibzugriff noetig ist (*.ini
etc.). Windows bringt mit der Serverinstallation schon eine moeglichkeit die
Installation in zwei Teile aufzuspalten. setup /a erzeugt ein Verzeichnis,
das von allen Benutzern gemeinsam benutzt werden kann und setup /n erzeugt
dann eine Benutzerinstallation, die nur noch ca. 500kb gross ist. Das so
erzeugte Verzeichnis wird nun auf den Server kopiert und dort nochmal in
zwei Teile aufgeteilt (nach dem oben beschriebenen Schema).
Der Skript kopiert und linkt nun einfach die Dateien aus dem mit setup /n
installierten Dateien in ~/windows/windows. Wenn man nun auf den Dosclient
das Volume \\SERVER\HOMEDIR\WINDOWS auf Laufwerk d: und das mit setup /a
erzeugte Verzeichnis auf ein anderes Laufwerk einbindet hat man eine
funktionierende Windowsinstallation, die pro Benutzer grade einmal 80kb
Plattenplatz wegnimmt.
Der Skript wird nach jedem login von dem Dosclient durch einen type auf die
Datei ausgefuehrt und kopiert alle Dateien mit cp -au (u steht fuer Update,
daher nur neuere Dateien werden kopiert) aus $TEMPLATE/dynamic nach
~/windows/windows und legt fuer jede Datei aus $TEMPLATE/static einen
symbolischen link in ~/windows/windows an. Damit kann man die mit setup -n
erstellten Dateien noch einmal in einen Teil mit und einem ohne
Schreibzugriff unterteilen.
Leider setzt mars-nwe (zumindest in 0.99.pl4) in Pipescripts die
umgebungsvariable $HOME immer auf /root, daher lese ich das Heimatverzeichnis
mit dem gethomedir.pl script aus /etc/passwd aus.
--------------------------------------------------------------------
#!/bin/sh
# mkwin Pipeskript
#
# !!!!ACHTUNG!!!!
# Wenn in $home/ eine Datei windows oder windows/windows exestiert,
# wird diese ohne nachfrage geloescht
PATH="/bin:/usr/bin"
TEMPLATE="/var/spool/nwserv/windows/template"
home=`/var/spool/nwserv/pipe/gethomedir.pl $UID`
case "$1" in
'READ')
if ! test -d $home/windows ; then
rm -rf $home/windows
fi
if ! test -d $home/windows/windows ; then
rm -rf $home/windows/windows > /dev/null
mkdir -pm 0700 $home/windows/windows
fi
for i in $TEMPLATE/static/* ; do
ln -s $i $home/windows/windows
done
cp -au $TEMPLATE/dynamic/* $home/windows/windows
;;
esac
-----------------------------------------------------------------
#!/usr/bin/perl
#
# File: gethomedir.pl
#
print "$1\n";
open(PW, "/etc/passwd");
while ($line=<PW>) {
chop($line);
($uid, $home) = ($line=~
/[^\:]*\:[^\:]*\:([\d]*)\:[^\:]*\:[^\:]*\:([^\:]*)\:/
);
if ($uid == $ARGV[0]) {
print "$home";
}
}
close(PW);
------------------------------------------------------------------
2.4 andere Beispiele
In dem Verzeichnis examples gibt es als zusaetzliches Beispiel
die Programmpaare unxcomm<->comm und sendm<->unxsendm.
Mittels unxcomm/comm ist es sehr einfach moeglich einige
@ -56,3 +152,4 @@ Ueber weitere dokumentierte Anwendungen bzw. Anregungen zu dem
PIPE-Filesystem wuerde ich mich freuen.
Martin

View File

@ -68,7 +68,7 @@ nwbind:
Have luck with trying. :)
Martin Stover <mstover@stover.f.eunet.de>
Martin Stover <mstover@compu-art.de>
BTW: The kick to make mars_nwe public was the publication of
linware ( lwared ), the NetWare-Emulator from

74
doc/README.FREEBSD Normal file
View File

@ -0,0 +1,74 @@
This is a port of Mars_nwe, a free NetWare(tm) emulator for Linux and
UnixWare to FreeBSD. An original program was written by Martin Stover,
Marburg, Germany. Port to FreeBSD was made by Boris Popov (bp@butya.kz).
Notes given below related only to FreeBSD. For full description
of Mars_nwe, please read README file.
Additional info about IPX on FreeBSD available at
http://www.butya.kz/~bp/
1. Kernel configuration
To enable kernel support for IPX protocol you must include
"options IPX" keyword and rebuild kernel. If you are running FreeBSD
3.x or 2.2.8, please download patched versions for IPX stack and
IPXrouted frow above URL. These changes already commited in to -current
branch.
2. Interface configuration
If it's first NCP server in your network you can select any network
number for ethernet interface. If not, take it from Netware server
configuration. Network number must be the same as assigned to Ethernet_II
frame.
After net number is selected you can configure interface:
ifconfig ed0 ipx 0x101
If FreeBSD machine have a two network cards you must choose
different network numbers for each card.
Also select an unqiue number for internal net and configure it
as follows:
ifconfig lo0 ipx 0xbebe.1
Note, that you should set host number to 1.
3. Running IPXrouted
FreeBSD have its own SAP/RIP daemon which must be run before
Mars_nwe and after interface configuration. IPXrouted must be running
with switch '-s'. Please use only patched version of IPXrouted if you
are run 2.2.8 or 3.x of FreeBSD.
4. Client configuration
This port of Mars_nwe was tested with VLM, Client32 and
native FreeBSD clients. Since FreeBSD support only Ethernet_II frame
it is necessary to create net.cfg file (for VLM) to enable this
frame:
LINK DRIVER NE2000
Frame Ethernet_802.3
Frame Ethernet_II
5. Configuring Mars_nwe
Section 3 of nwserv.conf file specified network number in hexadecimal
format. This should be an internal network number configured on interface lo0.
For above example set following:
3 0xbebe
Section 4 are completly ignored.
6. Problems
If you have any questions do not hesitate to contact me, Boris Popov at
bp@butya.kz.

View File

@ -68,7 +68,7 @@ der fehlenden bzw. fehlerhaften NCP-Calls wuerde ich mich freuen.
Martin
<mstover@stover.f.eunet.de>
<mstover@compu-art.de>
PS: Den Anstoss, mars_nwe zu veroeffentlichen, gab die
Veroeffentlichung von linware ( lwared ), dem Novell-Server-Emulator

72
doc/TRUSTEES Normal file
View File

@ -0,0 +1,72 @@
last changed: 12-May-98
First simple trustee handling is added in 0.99.pl9.
some notes/restrictions:
NOT ALL functions will work correct with trustees rights.
Trustee handling still needs to be hard tested to avoid
SECURITY holes.
- trustee handling must be activated by setting the volumes 't' flag.
- if activated for the SYS directory then the following default
trustees should be set.
GROUP EVERYBODY: C in SYS:MAIL
FR in SYS:PUBLIC
SUPERVISOR: SRWCEMFA in SYS:
the standard user rights in mail diretories are not so important,
because user has unix rights in this diretory.
every USER: RWCEMF in SYS:MAIL/userid
A non root supervisor and user with supervisor equivalences
get default full trustee rights in root directory. These rights
could be altered in subdirectories to less rights.
A root supervisor always has full rights.
- if SYS volume is marked as trusttee volume then some
checking routines will reduce g+o unix accesses in
SYS:MAIL subdirectories.
- symlink directories must get direct trustees, inheritated_mask
is set to 0 to prevent user making symlinks to directories
they do not have real access.
- when stepping through directories,
inheritated_mask will be set to 0 if st_dev changes.
- only root assigned user may give trustee rights to
file/dir which st_dev differs from VOLUMES st_dev.
- only additional rights are given by trustees, existing
unix user rights are not reduced.
therefore trustee volumes should get low unix rights.
for example: 0711 for directories and 0600 for files.
- for many routines the user still needs the 'x' directory right.
- the trusttee search is limitated to user and first level groups.
'group in group' and 'normal' security equivalences are not supported.
Supervisor equivalences are supported.
- an user can only be member of 32 groups.
- some changes of trustees only have effect after new login.
- must never be switched on volumes which do not have fix inodes,
because trustees are represented by device and inode number of the
file or directory.
- standard trustee directory is /var/nwserv/trustees
( see nwserv.conf section 47 )
- representation under this directory is:
- for user trustees:
volumename/device/ino0/ino1/ino2/t.ino3/id -> trustee
ino0 .. ino3 = byte 0 .. 3 of inode
id = user id as hex number.
- for inherit right masks ( we use 'userid' 0 )
volumename/device/ino0/ino1/ino2/t.ino3/0 -> inherit_right_mask
- and for scanning trustees:
volumename/device/ino0/ino1/ino2/n.ino3 -> path
path is relativ to volumes root path.
- and for 'trustees are changed' notifications:
volumename/ts -> sernum (hex value)
all values are represented by symbolic links, not files similar
to the attribute handling.

30
doc/VRAGEN.NL Normal file
View File

@ -0,0 +1,30 @@
Een aantal vragen en antwoorden. ( Mendel Mobach <mendel@mobach.nl> )
V: Welke Novell DOS programma's moet ik minimaal hebben?
A: Het minimun vereiste is LOGIN.EXE
Andere handige programma's zijn:
MAP.EXE wordt gebruikt om server volume's te verbinden met een
schijfletter.
CAPTURE.EXE wordt gebruikt om een printer-poort te verbinden met
een printer op de mars/novell server.
SYSCON.EXE wordt gebruikt voor het beheren van de server.
V: Heb ik het device '/dev/ipx' nodig? Ik zie verwijzingen vanuit de mars_nwe.
A: Als je Linux gebruikt, NEE. Dit device is alleen nodig indien men een OS
gebruikt met TLI-interfaces, b.v. Unixware (tm).
V: Ik begrijp entry 12/13 in de configuratie niet.
Wat gebeurt er als ik hier niks opgeef?
Wordt de '/etc/passwd' of '/etc/shadow' gebruikt?
A: Het wachtwoord in 12/13 wordt versleuteld opgeslagen in de bindery,
De wachtwoorden uit de '/etc/passwd' of '/etc/shadow' worden alleen gebruikt
als men werkt met 'unencryted login calls', oftewel ongecodeerde wachtwoorden
vanaf de client.
V: Welke rol speelt entry '15' in de configuratie?
A: In deze entry staat een wachtwoord, wat alleen wordt gebruikt als men
automatische UNIX naar mars_nwe usermapping heeft aanstaan, oftewel als
men in unix een gebruiker toevoegt, en daarna de mars_nwe herstart wordt
die gebruiker ook in de bindery opgenomen en krijgt hij het standaard
wachtwoord.

View File

@ -1,16 +1,16 @@
Begin3
Title: mars_nwe
Version: 0.99.pl6
Entered-date: 09-Feb-98
Description: Full netware-emulator (src), beta.
Version: 0.99.pl19
Entered-date: 25-Apr-00
Description: Full netware 3.xx emulator (src), beta.
Supports file-services, bindery-services,
printing-services, routing-services.
Keywords: novell, netware, server, ipx, ncp, tli
Author: mstover@compu-art.de (Martin Stover)
Maintained-by: mstover@compu-art.de (Martin Stover)
Primary-site: http://www.compu-art.de/download/mars_nwe-0.99.pl6.tgz
250 kB
Alternate-site: ftp://gwdg.de/pub/linux/misc/ncpfs/mars_nwe-0.99.pl6.tgz
Platforms: Linux (1.2.xx, 1.3.xx, 2.xx), UnixWare (2.xx)
Copying-policy: GNU
Primary-site: http://www.compu-art.de/download/mars_nwe-0.99.pl19.tgz
320 kB
Alternate-site: ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/mars_nwe/mars_nwe-0.99.pl19.tgz
Platforms: Linux (1.2.xx, 1.3.xx, 2.xx), FreeBSD, UnixWare (2.xx)
Copying-policy: GPL
End

108
emutli.c
View File

@ -1,4 +1,4 @@
/* emutli.c 07-Jul-97 */
/* emutli.c 04-Apr-00 */
/*
* One short try to emulate TLI with SOCKETS.
*/
@ -20,24 +20,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "net.h"
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/config.h>
#include <linux/sockios.h>
#include "net.h"
#include <linux/if.h>
#include <linux/route.h>
#include <linux/in.h>
#include <signal.h>
#include <string.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <errno.h>
#ifndef DO_IPX_SEND_TEST
# define DO_IPX_SEND_TEST 2
# define DO_IPX_SEND_TEST 0
#endif
/* DO_IPX_SEND_TEST is only needed if the ipx sendmsg() bug is not patched
@ -55,6 +49,9 @@
*/
static int locipxdebug=0;
#ifdef FREEBSD
static struct ipx_addr fbsd_ipx;
#endif
void set_locipxdebug(int debug)
{
@ -86,12 +83,31 @@ void set_emu_tli(void)
{
int i = get_ini_int(100);
if (i > -1) locipxdebug = i;
#ifdef FREEBSD
{
uint32 net = 0;
uint8 buff[500];
if( (get_ini_entry(NULL, 3, buff, sizeof(buff)))!=3 ){
errorp(10, "set_emu_tli", "Missing ini entry 3");
return;
}
sscanf((char*)buff, "%lx", &net);
ipx_netlong(fbsd_ipx)=htonl(net);
if( ipx_iffind(NULL,&fbsd_ipx) )
errorp(10, "set_emu_tli", "Can't find ipx interface for net=%lx",net);
}
#endif
}
int t_open(char *name, int open_mode, char * p)
{
int opt=1;
#ifdef FREEBSD
int sock = socket(AF_IPX, SOCK_DGRAM, 0);
#else
int sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
#endif
if (sock < 0) return(sock);
set_sock_debug(sock); /* debug switch */
@ -115,15 +131,34 @@ int t_bind(int sock, struct t_bind *a_in, struct t_bind *a_out)
&& a_in->addr.len == sizeof(ipxAddr_t))
ipx2sockadr(&ipxs, (ipxAddr_t*) (a_in->addr.buf));
#ifndef FREEBSD
ipxs.sipx_network = 0L; /* allways default net */
memset(ipxs.sipx_node, 0, IPX_NODE_SIZE); /* allways default node */
/* Hi Volker :) */
#else
ipx_netlong(ipxs.sipx_addr)=ipx_netlong(fbsd_ipx);
memcpy(ipxs.sipx_node, &fbsd_ipx.x_host, IPX_NODE_SIZE);
#endif
if (bind(sock, (struct sockaddr*)&ipxs, sizeof(struct sockaddr_ipx))==-1) {
errorp(0, "TLI-BIND", "socket Nr:0x%x", (int)GET_BE16(&(ipxs.sipx_port)));
return(-1);
}
#ifdef FREEBSD
{
int on=1;
if (setsockopt(sock, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
errorp(0, "setsockopt SO_HEADERS_ON_INPUT", NULL);
return (-1);
}
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on,sizeof(on))==-1){
errorp(0, "setsockopt SO_BROADCAST", NULL);
return(-1);
}
}
#endif
if (a_out != (struct t_bind*) NULL) {
if (getsockname(sock, (struct sockaddr*)&ipxs, &maxplen) == -1){
errorp(0, "TLI-GETSOCKNAME", NULL);
@ -180,15 +215,14 @@ int poll( struct pollfd *fds, unsigned long nfds, int timeout)
p->revents=0;
p++;
}
if (timeout > 1000) {
/* mst:04-Apr-00, patch from (Jukka Ukkonen) */
time_out.tv_sec = timeout / 1000;
time_out.tv_usec = 0;
} else {
time_out.tv_sec = 0;
time_out.tv_usec = timeout*1000;
}
if (0 > (result = select(high_f+1, &readfs, NULL, NULL, &time_out)))
time_out.tv_usec = (timeout % 1000) * 1000;
if (0 > (result = select(high_f+1, &readfs, NULL, NULL,
(timeout == -1) ? NULL : &time_out)))
return(-1);
if (result) {
int rest=result;
k = (int)nfds;
@ -204,6 +238,7 @@ int poll( struct pollfd *fds, unsigned long nfds, int timeout)
return(result);
}
inline int t_rcvudata(int fd, struct t_unitdata *ud, int *flags)
{
struct sockaddr_ipx ipxs;
@ -211,6 +246,29 @@ inline int t_rcvudata(int fd, struct t_unitdata *ud, int *flags)
int result;
ipxs.sipx_family=AF_IPX;
if (ud->addr.maxlen < sizeof(ipxAddr_t)) return(-1);
#ifdef FREEBSD
{
unsigned char tmpbuf[IPX_MAX_DATA+sizeof(struct ipx)];
struct ipx *ipxhdr=(struct ipx*)tmpbuf;
fd_set rfd;
FD_ZERO(&rfd);
FD_SET(fd,&rfd);
result=select(fd+1, &rfd, NULL, NULL, NULL);
if(result<0) return(-1);
result = recvfrom(fd, tmpbuf,
min(sizeof(tmpbuf), ud->udata.maxlen+sizeof(struct ipx)), 0,
(struct sockaddr *) &ipxs, &sz);
result-=sizeof(struct ipx);
if( result<0 ) return(-1);
memcpy(ud->udata.buf,tmpbuf+sizeof(struct ipx),result);
if (ud->opt.maxlen) {
*((uint8*)ud->opt.buf) = ipxhdr->ipx_pt;
ud->opt.len = 1;
}
}
#else
result = recvfrom(fd, ud->udata.buf, ud->udata.maxlen, 0,
(struct sockaddr *) &ipxs, &sz);
@ -219,6 +277,8 @@ inline int t_rcvudata(int fd, struct t_unitdata *ud, int *flags)
*((uint8*)ud->opt.buf) = ipxs.sipx_type;
ud->opt.len = 1;
}
#endif
ud->udata.len=result;
sock2ipxadr((ipxAddr_t*) (ud->addr.buf), &ipxs);
ud->addr.len = sizeof(ipxAddr_t);
@ -260,7 +320,15 @@ inline int t_sndudata(int fd, struct t_unitdata *ud)
memset(&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_family=AF_IPX;
ipx2sockadr(&ipxs, (ipxAddr_t*) (ud->addr.buf));
#ifdef FREEBSD
{
struct ipx ipxdp;
ipxdp.ipx_pt = (ud->opt.len) ? (uint8) *((uint8*)(ud->opt.buf)) : 0;
setsockopt(fd, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp));
}
#else
ipxs.sipx_type = (ud->opt.len) ? (uint8) *((uint8*)(ud->opt.buf)) : 0;
#endif
result = sendto(fd,(void *)ud->udata.buf,
ud->udata.len, 0, (struct sockaddr *) &ipxs, sizeof(ipxs));

View File

@ -1,4 +1,4 @@
/* emutli.h 28-Apr-96 */
/* emutli.h 18-Nov-99 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
@ -20,7 +20,27 @@
#ifndef _EMUTLI_H_
#define _EMUTLI_H_
#include <linux/ipx.h>
#ifdef FREEBSD
# include <netipx/ipx.h>
# define sipx_node sipx_addr.x_host.c_host
# define sipx_network sipx_addr.x_net.c_net
# define ipx_netlong(iaddr) (((union ipx_net_u *)(&((iaddr).x_net)))->long_e)
# define ETHERTYPE_IPX 0x8137
# define IPX_RT_8022 ETHERTYPE_IPX
# define IPX_RT_8023 ETHERTYPE_IPX
# define IPX_RT_SNAP ETHERTYPE_IPX
# define IPX_RT_BLUEBOOK ETHERTYPE_IPX
int ipx_iffind(char *ifname,struct ipx_addr *addr);
#else
# include <linux/types.h>
# include <netinet/in.h>
# ifdef _GNU_SOURCE_
# include <netipx/ipx.h>
# else
# include <linux/ipx.h>
# endif
#endif
typedef unsigned char uint8;
typedef unsigned short int uint16;

101
emutli1.c
View File

@ -1,4 +1,4 @@
/* emutli1.c 10-Apr-97 */
/* emutli1.c 05-May-98 */
/*
* One short try to emulate TLI with SOCKETS.
*/
@ -34,13 +34,19 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/config.h>
#include <linux/sockios.h>
#if 0
# include <linux/sockios.h>
#endif
#include "net.h"
#include <linux/if.h>
#include <linux/route.h>
#include <linux/in.h>
#include <signal.h>
#include <string.h>
#if 0
# include <linux/if.h>
# include <linux/route.h>
# include <linux/in.h>
#else
# include <net/if.h>
# include <net/route.h>
# include <netinet/in.h>
#endif
#include <errno.h>
static int have_ipx_started=0;
@ -154,6 +160,9 @@ static void del_special_net(int special, char *devname, int frame)
if (frame < 0) continue;
sipx->sipx_type = frame;
if (flags & 1) { /* primary */
if (flags & 2){ /* primary == internal net */
sipx->sipx_special = IPX_INTERNAL;
} else
strcpy(id.ifr_name, name);
break;
}
@ -273,10 +282,49 @@ int get_frame_name(uint8 *framename, int frame)
return(0);
}
int ipx_inuse(int mode)
/* returns 0 if ipx is idle */
{
FILE *f=fopen("/proc/net/ipx", "r");
int idle=0;
if (f) {
char buff[200];
while (fgets((char*)buff, sizeof(buff), f) != NULL){
uint32 network;
int sock;
if (2==sscanf(buff, "%lx:%x", &network, &sock)) {
if (mode == 0) {
if (sock >= 0x4000) { /* user socket */
idle=sock;
break;
}
} else if (sock==mode) {
idle=sock;
break;
}
}
}
fclose(f);
}
return(idle);
}
static void ipx_in_use_abort()
{
errorp(11, "!! IPX IN USE ERROR !!",
"mars_nwe would kill existing IPX programs if starting\n"
"because it must reinit ipx devices.\n"
"Please stop other IPX programs e.g. ncpmount,\n"
"or change mars_nwe's configuration.\n"
);
exit(1);
}
int init_ipx(uint32 network, uint32 node, int ipx_debug, int flags)
{
int result=-1;
int sock;
uint32 primary_net=0L;
#if INTERNAL_RIP_SAP
# ifdef CONFIG_IPX_INTERN
errorp(11, "!! configuration error !!",
@ -293,36 +341,49 @@ int init_ipx(uint32 network, uint32 node, int ipx_debug, int flags)
exit(1);
} else {
ipx_config_data cfgdata;
struct sockaddr_ipx ipxs;
ioctl(sock, SIOCIPXCFGDATA, &cfgdata);
org_auto_interfaces =
auto_interfaces = cfgdata.ipxcfg_auto_create_interfaces;
set_sock_debug(sock);
result=0;
/* build new internal net */
if (network) {
struct sockaddr_ipx ipxs;
memset((char*)&ipxs, 0, sizeof(struct sockaddr_ipx));
ipxs.sipx_port = htons(SOCK_NCP);
ipxs.sipx_family = AF_IPX;
if (bind(sock, (struct sockaddr*)&ipxs,
sizeof(struct sockaddr_ipx))==-1) {
if (errno == EEXIST || errno == EADDRINUSE) result = -1;
}
if (result) {
if (errno == EEXIST || errno == EADDRINUSE) {
result = -1;
errorp(1, "EMUTLI:init_ipx socket 0x451", NULL);
exit(1);
}
del_internal_net();
add_internal_net(network, node);
} else {
int maxplen=sizeof(struct sockaddr_ipx);
if (getsockname(sock, (struct sockaddr*)&ipxs, &maxplen) != -1)
primary_net= ntohl(ipxs.sipx_network);
if (primary_net)
have_ipx_started++;
}
/* build new internal net */
if (network) {
int diffs = (primary_net && (network != primary_net));
if (diffs) {
XDPRINTF((1,0,"Existing primary network will be reinit from %x to %x",
primary_net, network));
if (ipx_inuse(0) && !(flags&4))
ipx_in_use_abort();
}
if ((flags&4) || diffs || !primary_net) { /* if complete reinit or diffs */
del_internal_net();
add_internal_net(network, node);
}
have_ipx_started++;
}
if ((flags & 2) && !auto_interfaces) { /* set auto interfaces */
auto_interfaces = 1;
ioctl(sock, SIOCAIPXITFCRT, &auto_interfaces);
}
close(sock);
}
return(result);
@ -341,8 +402,10 @@ void exit_ipx(int flags)
ioctl(sock, SIOCAIPXITFCRT, &org_auto_interfaces);
close(sock);
}
if (have_ipx_started && flags&4) {
if (flags&4) {
del_all_interfaces_nets();
} else if (!ipx_inuse(0)) {
del_internal_net();
}
}
@ -353,8 +416,10 @@ int init_dev(char *devname, int frame, uint32 network, int wildmask)
if (!have_ipx_started) {
if (wildmask) return(-99);
have_ipx_started++;
if (!ipx_inuse(0)) {
del_primary_net();
add_primary_net(devname, frame, network);
}
} else {
if (!wildmask)
return(add_device_net(devname, frame, network));

View File

@ -1,4 +1,4 @@
/* emutli1.h 10-Apr-97 */
/* emutli1.h 05-May-98 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
*
@ -29,15 +29,12 @@ extern int get_interface_frame_name(char *name, uint32 net);
extern int add_device_net(char *devname, int frame, uint32 netnum);
extern int get_frame_name(uint8 *framename, int frame);
extern int ipx_inuse(int mode);
extern int init_ipx(uint32 network, uint32 node, int ipx_debug, int flags);
extern void exit_ipx(int full);
extern int init_dev(char *devname, int frame, uint32 network, int wildmask);
extern void exit_dev(char *devname, int frame);
#if 0
extern int get_ipx_addr(ipxAddr_t *addr);
#endif
extern void ipx_route_add(uint32 dest_net,
uint32 route_net,
uint8 *route_node);

View File

@ -1,17 +1,33 @@
/*
/* comm.c 22-Oct-98
* simple demo for a command programm which do a
* DOS <-> UNX command handling using PIPE filesystem.
* DOS/WIN <-> UNX command handling using PIPE filesystem.
* Most problem under W95 is the file caching.
* Only the 32-bit version (comm32) works correct under W95.
* NT do not have this problems.
*
* can be used with unxcomm for UNX.
*
* Can also be used under Linux for ncpfs <-> mars_nwe.
*
* comm and unxcomm must be same version !
*/
#define MAXARGLEN 1024
/* Environment string could be in the form: UNXCOMM=p:/unxcomm
* or under 32bit: UNXCOMM=\\lx1\pipes\unxcomm
* or under linux: UNXCOMM=/pipes/unxcomm
*
*/
#define ENV_UNXCOMM "UNXCOMM"
#ifdef LINUX
# define DEFAULT_COMM "/pipes/unxcomm"
#else
# ifdef DEFAULT_UNC
# define DEFAULT_COMM DEFAULT_UNC
# else
# define DEFAULT_COMM "p:/unxcomm"
# endif
#endif
#include <stdio.h>
@ -19,6 +35,8 @@
#include <stddef.h>
#ifndef LINUX
# include <io.h>
#else
# define O_BINARY 0
#endif
#include <fcntl.h>
@ -28,32 +46,172 @@ static int usage(char *progname)
return(1);
}
#ifdef WIN32
#include <windows.h>
#include <direct.h>
int get_server_name(char *servername, char *path)
/* returns len of servername if exist or 0 */
{
int result=0;
char remotepath[300];
if (path && *path != '\\' && *path != '/' && *(path+1) != ':'){
getcwd(remotepath, sizeof(remotepath)-1);
path=remotepath;
}
if (path && path[1] == ':') {
char localpath[10];
DWORD size=sizeof(remotepath);
memcpy(localpath, path, 2);
*(localpath+2)='\0';
if (WNetGetConnection(localpath, remotepath,
&size)==NO_ERROR) {
path=remotepath;
}
}
if (path && (*path == '\\' || *path == '/')
&& (*(++path) == '\\' || *path == '/') ) {
char *p=++path;
while (*p && *p!='/' && *p!='\\') ++p;
result= (int)(p-path);
if (result&&servername) {
memcpy(servername, path, result );
servername[result] = '\0';
}
}
return(result);
}
HANDLE loc_open(char *fn, int mode)
{
HANDLE fd=CreateFile(fn, GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|
FILE_FLAG_SEQUENTIAL_SCAN|
FILE_FLAG_NO_BUFFERING, /* IMPORTANT !!! */
NULL);
return(fd);
}
int loc_read(HANDLE fd, char *buf, int size)
{
if (ReadFile(fd, buf, size, &size, NULL))
return(size);
return(-1);
}
#define loc_close(fd) CloseHandle(fd)
#define loc_lseek(fd, offs, what) /* not yet used */
#else
#define loc_lseek lseek
#define loc_read read
#define loc_open open
#define loc_close close
typedef int HANDLE;
#define INVALID_HANDLE_VALUE -1
#endif
int main(int argc, char **argv)
{
char *unxcomm=getenv(ENV_UNXCOMM);
if (NULL == unxcomm) unxcomm=DEFAULT_COMM;
if (argc > 1) {
int fdout = open(unxcomm, O_RDWR);
int fdin = dup(fdout);
if (fdout > -1 && fdin > -1) {
char **pp=argv+1;
unsigned char b=32;
int size;
int buf[512];
while(--argc) {
write(fdout, *pp, strlen(*pp));
++pp;
write(fdout, &b, 1);
char buf[MAXARGLEN+1024];
HANDLE fdin = loc_open(unxcomm, O_RDONLY|O_BINARY);
int fdout = -1;
#ifdef WIN32
char buf_unxcomm[200];
if (fdin == INVALID_HANDLE_VALUE) {
char servername[100];
if (get_server_name(servername, argv[0])>0){
sprintf(buf_unxcomm, "\\\\%s\\pipes\\unxcomm", servername);
unxcomm=buf_unxcomm;
fdin = loc_open(unxcomm, O_RDONLY|O_BINARY);
}
b=0;
write(fdout, &b, 1);
}
#endif
if (fdin != INVALID_HANDLE_VALUE) {
int count=loc_read(fdin, buf, 10);
char pipepath[200];
char *pipeext=pipepath;
int tries=0;
while (count < 10 && tries < 20) {
int nc;
if (count < 0) count =0;
nc=loc_read(fdin, buf+count, 1);
if (nc > 0) count+=nc;
tries++;
}
if (count == 10 && buf[0]=='#' && buf[9] == '\n') {
char *p;
strcpy(pipepath, unxcomm);
p=pipepath+strlen(unxcomm);
while (p>pipepath) {
if (*p=='\\' || *p=='/')
break;
--p;
}
if (p > pipepath) {
++p;
*p++='r';
*p++='u';
*p++='n';
*p++='/';
memcpy(p, buf+1, 8);
p += 8;
*p++='.';
pipeext = p;
strcpy(pipeext, "in");
} else pipepath[0] = '\0';
tries=0;
do {
fdout = open(pipepath, O_WRONLY|O_BINARY);
} while (fdout < 0 && tries++ < 5);
if (fdout <0) {
fprintf(stderr, "Cannot open pipe '%s'\n", pipepath);
}
} else {
buf[count>0 ? count : 0]='\0';
fprintf(stderr, "%d Bytes read are wrong'%s'\n", count, buf);
}
if (fdout > -1) {
char *p=buf;
while(--argc) {
int l=strlen(*pp);
memcpy(p, *pp, l);
++pp;
p+=l;
*p++ = 32;
}
*p++='\0';
write(fdout, buf, (int)(p-buf));
close(fdout);
while (0 < (size = read(fdin, buf, sizeof(buf)))) {
loc_lseek(fdin, 0, 0);
memset(buf, 0, 512);
while (0 < (size = loc_read(fdin, buf, 512 /*sizeof(buf)*/))) {
write(1, buf, size);
loc_lseek(fdin, 0, 2);
}
close(fdin);
loc_close(fdin);
return(0);
}
loc_close(fdin);
} else
fprintf(stderr, "Cannot open PIPECOMMAND '%s'\n", unxcomm);
}

Binary file not shown.

BIN
examples/comm32.exe Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
/* config.h: 04-Feb-98 */
/* config.h: 11-Jul-98 */
/* some of this config is needed by make, others by cc */
#define DO_DEBUG 1 /* compile in debug code */
@ -14,7 +14,7 @@
# define FILENAME_NW_INI "/etc/nwserv.conf"
/* full name of ini (conf) file */
# define PATHNAME_PROGS "/usr/sbin" /* where to find the executables */
# define PATHNAME_BINDERY "/etc" /* directory for bindery-files */
# define PATHNAME_BINDERY "/var/nwserv/db" /* directory for bindery-files */
#endif
#define PATHNAME_PIDFILES "/var/run" /* directory for 'pidfiles' */
@ -77,9 +77,7 @@
#define PERSISTENT_SYMLINKS 0 /* change to '1' for persistent symlinks */
/* main idea from Victor Khimenko */
/* in 0.99.pl0 still NOT working !! */
#define NEW_ATTRIB_HANDLING 0 /* better (if working ;)) attrib handling */
/* still NOT working !! */
/* <--------------- next is for linux only ----------------------------> */
#define INTERNAL_RIP_SAP 1 /* use internal/own rip/sap routines */

BIN
examples/e.pck Normal file

Binary file not shown.

1
examples/mk Executable file
View File

@ -0,0 +1 @@
make unxcomm && mv unxcomm /u3/pipes/.

View File

@ -1,5 +1,5 @@
#!/bin/sh
# mk.li 10-Jul-97
# mk.li 15-Dec-99
# please edit this file !
mk()
@ -43,7 +43,8 @@ case $UNX in
CPP="cc -E"
# CFLAGS="-pipe -O2 -fomit-frame-pointer"
# problems gcc2.5.8 ^^^^^^^^^^^^^^^^^^^^^
CFLAGS="-pipe -Wall"
# CFLAGS="-pipe -Wall -Dsignal=sysv_signal"
CFLAGS="$RPM_OPT_FLAGS -pipe -Wall -D_GNU_SOURCE"
case $MASCHINE in
sparc)
@ -59,7 +60,17 @@ if [ -f /usr/lib/libgdbm.a ] || [ -f /usr/lib/libgdbm.so ] ; then
else
NDBMLIB="-ldbm"
fi
if [ -f /usr/lib/libcrypt.so ] ; then
CRYPTLIB="-lcrypt"
else
CRYPTLIB=""
fi
if [ -f /usr/include/sys/quota.h ] ; then
HOSTCFLAGS="$HOSTCFLAGS -DQTAINSYS"
fi
NSLLIB=""
MAKE=make
TMP=/tmp
@ -80,6 +91,28 @@ fi
TMP=/tmp
INSTALL=/usr/ucb/install
;;
########## FreeBSD ############
# created by Boris Popov
freebsd)
V_VPATH=".."
OBJDIR="obj"
CC=gcc
CPP="gcc -E"
if [ "x$CFLAGS" = "x" ]; then
CFLAGS="native"
fi
HOSTCFLAGS="-DFREEBSD -DLINUX"
CRYPTLIB="-lcrypt -lipx"
NSLLIB=""
MAKE=make
TMP="./"
INSTALL="install -c"
;;
*) echo "mk.li: Unknown or not supported OS, probably you must set \$UNX"
;;
esac
@ -95,7 +128,9 @@ esac
export CC
export CPP
export CFLAGS
if [ "X$CFLAGS" != "Xnative" ]; then
export CFLAGS
fi
export HOSTCFLAGS
export NDBMLIB
export CRYPTLIB

View File

@ -2,8 +2,11 @@
# This is the configuration-file for "mars_nwe", a free netware-emulator
# for Linux.
#
# last changed: 08-Feb-98
#
# last changed: 04-Apr-00
# !! section 31 : flags added in 0.99.pl18, but not used
# !! section 8 : new flags added in 0.99.pl18 !!
# !! section 9 : default directory/file umask changed in 0.99.pl9 !!
# !! section 46 : default attrib location changed in 0.99.pl9 !!
# !! section 5 : deleting of ipx devices/routes changed in 0.99.pl6 !!
# !! section 4 : automatic creation of ipx-interfaces changed in 0.98.pl9 !!
#
@ -97,15 +100,18 @@
#
# OPTIONS: none or some of the following characters (without a seperator)
# - Placeholder.
#
# Next two options control DOS and OS/2 namespace.
# i ignore case, handle mixing upper/lowercase filenames (slow)
# should only be used if you really need it.
# k use lowercase-filenames (if you don't set this,
# and you don't set 'i' all files _must_ be upper-case)
#
# m removable volume (e.g. cd-roms) or volumes, which
# should be remountable when mars_nwe is running.
# r volume is read-only and always reports "0 byte free"
# (this is intended for copies of CD-ROMs on harddisks)
# n (n)o fixed inodes. This volume do not have fixed inodes.
# e.g. DOS-Volumes, CD-ROMS. This flag is very important for
# attrib and trustee handling.
# o (lowercase o)
# volume has only one filesystem/device/namespace
# this is for filesystems with high inode > 0xFFFFFFF.
@ -114,6 +120,17 @@
# between several devices/namespaces for one volume.
# p "PIPE"-filesystem. All files are pipe commands.
# See `doc/PIPE-FS'.
# r volume is read-only and always reports "0 byte free"
# (this is intended for copies of CD-ROMs on harddisks)
# t volume has trustees.
# Real access is trustee rights + unix rights.
# Trustees are stored in extra directories,
# normally under /var/nwserv/trustees.
# Must only be used for volume which have fix inodes.
# A volume with trustees should never be renamed.
# For some more notes see 'doc/TRUSTEES'.
# T volume has trustees & ignore the rights granted in UN*X filesystem
# exactly like option "t" except that the unix rights are not added
#
# additional Namespaces
# O (uppercase o)
@ -123,21 +140,21 @@
#
# UMASKDIR: default directory creat umask.
# UMASKFILE: default file creat umask.
# value are always octal, overwrite standard section 9 entries
# for this specific volume.
# values are always octal, they overwrite standard
# section 9 values for this specific volume.
#
# -------------------------------------------------------------------------
#
# Examples:
# 1 SYS /var/local/nwe/SYS k
# 1 CDROM /cdrom kmor
# 1 SYS /var/local/nwe/SYS kt 711 600
# 1 CDROM /cdrom kmnor
# 1 HOME ~ k -1
# 1 HOMETMP ~/tmp kiO
# 1 PRIVAT ~/privat kO 700 600
# 1 WORLD /var/world kiO 777 666
# 1 FAXQ /var/spool/fax/faxqueue k
1 SYS /u3/SYS/ k -1
1 SYS /u3/SYS/ kt 711 600
# =========================================================================
@ -297,18 +314,24 @@
# beyond the lifetime of the server or router.
# If this flag is not set then all by nwserv/nwrouted added
# ipx-devices/routes will be deleted when
# nwserv/nwrouted ends (default).
# nwserv/nwrouted ends and if no ipx socket is still
# open. (default).
#
# 0x2 Switch on automatic kernel creation of ipx-interfaces.
# The automatic kernel creating of ipx-devices sometimes
# make trouble (Win95). It should only be used in the
# beginning or for testing.
# beginning or for testing !!
#
# 0x4 do remove ALL routes and ipx-devices
# beyond the lifetime of the server or router.
# If this flag is set then all ipx-devices/routes
# will be deleted when nwserv/nwrouted ends.
# will be deleted when nwserv/nwrouted ends,
# without looking for open ipx sockets.
# This was the default prior mars_nwe 0.99.pl6 !
# This also do complete ipx reinit when starting
# mars_nwe.
# This was the default prior mars_nwe 0.99.pl9 !
#
#
#
# other flags may follow.
@ -412,6 +435,15 @@
# in some volume info calls.
# some DOS clients need it.
#
# 0x80 allows renaming a file even if the file is opened by
# other process.
# ( this was standard before mars_nwe-0.99.pl18 )
#
# 0x100 not used yet.
#
# 0x200 needed for direct int17 printing on NETX clients
# (patch from Przemyslaw Czerpak)
#
# other flags may follow.
# value will be interpreted as hex value.
@ -426,9 +458,9 @@
# if -1 is specified for directories the st_mode of parent directory
# will be used.
# Volumes depended values can be set in section 1.
# 9 -1 0664
# 9 -1 0640
#
9 0755 0664
9 0751 0640
# Section 10: UID and GID with minimal rights
# =========================================================================
@ -536,17 +568,19 @@
# a '-' sign as password.
# -------------------------------------------------------------------------
# Syntax:
# 13 NW_LOGIN LINUX_LOGIN [PASSWORD] [FLAGS]
# 13 NW_LOGIN [LINUX_LOGIN] [PASSWORD] [FLAGS]
#
# FLAGS must be a hex value begin with 0x
# the only FLAG value in the moment is 0x1 for 'fixed passwords'
# which cannot be changed by user.
# Example:
# 13 MARTIN
# 13 MARTIN martin
# 13 DAREK martin
# 13 COMMON common gast 0x1 # no password change by user.
# 13 COMMON common 0x1 # syntax is allowed too.
13 GUEST nobody - 0x1
# Section 14: currently not used
@ -594,21 +628,45 @@
15 0 top-secret
# =========================================================================
# Section 16: Tests on startup
#
# If you want some sanity checks at startup, set this flag to 1.
# If you want some sanity checks at startup, set this flag to > 0.
# "mars_nwe" will try to create/change missing directories:
# SYS:LOGIN, SYS:MAIL, SYS:MAIL/XXX, SYS:PUBLIC, SYS:SYSTEM ...
# (with the "right" permissions, of course) if you enable this.
# should also be enabled when you use a new mars_nwe version.
# Disabling this test only spares little time when starting mars_nwe.
# some values:
# 1 few important tests.
# 2 also check/compress bindery.
16 1
# Section 17-20: currently not used
# Section 17: some bindery / user related flags.
# =========================================================================
# Flags
# 0x1 give all user an empty! login script, if they do not
# already have one. Is interpreted by test routines
# which run if section 16 is set and nwserv starts
# or got a SIGHUP. ( nwserv -h )
#
# other flags may follow.
# value will be interpreted as hex value.
17 0x0
# Section 18: some queue handling related flags.
# =========================================================================
# Flags
# 0x1 always unset (disable) the print banner flag.
#
# other flags may follow.
# value will be interpreted as hex value.
18 0x0
# Section 19-20: currently not used
# =========================================================================
@ -650,7 +708,10 @@
# Examples:
# 21 LASER - lpr -Plaser
# 21 OCTOPUSS
# 21 FAXPRINT - /usr/bin/psfaxprn /var/spool/fax/faxqueue
# -------------------------------------------------------------------------
21 LP - lpr -
21 LP_PS
# =========================================================================
@ -659,10 +720,17 @@
# e.g. to enable printing with ncpfs pserver
# -------------------------------------------------------------------------
# Syntax:
# 22 PSERVER_NAME QUEUE_NAME
# 22 PSERVER_NAME QUEUE_NAME [FLAGS]
#
# FLAGS:
# 1 Let PSERVER_NAME be a 'normal' user (type 1).
# Used for simple qserver which works under 'normal' user login.
#
# Examples:
# 22 PS1 OCTOPUSS
22 PS_NWE LP_PS 1
# =========================================================================
# Section 30: Burst mode values (optional)
@ -675,6 +743,13 @@
# 30 0x2000 0x2000
# =========================================================================
# Section 31: not used yet
# =========================================================================
# Flags not used yet
#
31 0x0
# =========================================================================
# Section 40ff: Some pathes (optional)
#
@ -688,9 +763,11 @@
#
#
# 45 = path for bindery file's
45 /etc
# 46 = path for attribute handling and later trustees
46 /var/lib/nwserv/attrib
45 /var/nwserv/db
# 46 = path for attribute handling
46 /var/nwserv/attrib
# 47 = path for trustee handling
47 /var/nwserv/trustees
# =========================================================================
# Section 50: Conversion tables by Victor Khimenko <khim@mccme.ru>
# Tables for DOS->Unix names translation & upper/lowercase translations

View File

@ -1,6 +1,7 @@
# example for nwopt file.
# !!!! NOT USED !!!!!
#
# last changed: 18-Nov-97
# last changed: 10-May-98
#
# Syntax similar like nwserv.conf file.
#

View File

@ -1,12 +1,21 @@
/* unxcomm.c 08-Jun-97 */
/* simple UNX program to work together with 'comm' */
/* to demonstrate usage of pipefilesystem */
/* unxcomm.c 22-Oct-98
* simple UNX program to work together with 'comm'
* to demonstrate usage of pipefilesystem
* needs mars_nwe version >= 0.99.pl13 !
* comm and unxcomm must be same version !
* 'run' directory must exist and must have
* read and write permission for every user.
*/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
static char **build_argv(int bufsize, char *command, int len)
/* routine returns **argv for use with execv routines */
@ -51,8 +60,8 @@ int bl_read(int fd, void *buf, int size)
int result;
FD_ZERO(&fdin);
FD_SET(fd, &fdin);
t.tv_sec = 0;
t.tv_usec = 100; /* 100 msec should be enough */
t.tv_sec = 1;
t.tv_usec = 0;
result = select(fd+1, &fdin, NULL, NULL, &t);
if (result > 0)
result=read(fd, buf, size);
@ -61,15 +70,49 @@ int bl_read(int fd, void *buf, int size)
int main(int argc, char *argv[])
{
int size=0;
int l;
int size=-1;
int pid=getpid();
char buf[MAXARGLEN+1024];
char fifopath[257];
char *p;
close(2);
dup2(1,2);
while (0 < (l=bl_read(0, buf+size, MAXARGLEN-size)))
if (argc > 3) {
strcpy(fifopath, argv[0]);
p=strrchr(fifopath, '/');
if (p) {
++p;
sprintf(p, "run/%08x.in", pid);
if (mkfifo(fifopath, 0600)) {
perror("mkfifo");
fprintf(stderr, "unxcomm:fifo.in=`%s`\n", fifopath);
} else {
fprintf(stdout, "#%08x\n", pid);
fflush(stdout);
size=0;
}
}
}
if (!size) {
int tries=0;
int fd = open(fifopath, O_RDONLY);
if (fd > -1) {
while (tries++ < 5) {
int l;
while (0 < (l=bl_read(fd, buf+size, MAXARGLEN-size))) {
size+=l;
}
if (size && buf[size-1] == '\0') break;
}
close(fd);
} else {
perror("open fifo");
size=-1;
}
unlink(fifopath);
}
if ( 0 < size) {
char **argvv=build_argv(sizeof(buf), buf, size);
if (argvv) {

View File

@ -1,4 +1,4 @@
/* extpipe.c 08-Aug-97 */
/* extpipe.c 03-Aug-98 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -19,7 +19,7 @@
#include "net.h"
#include "extpipe.h"
static char **build_argv(char *buf, int bufsize, char *command)
static char **build_argv(char *buf, int bufsize, char *command, int flags)
/* routine returns **argv for use with execv routines */
/* buf will contain the path component */
{
@ -43,7 +43,7 @@ static char **build_argv(char *buf, int bufsize, char *command)
*(++pp)=p;
i++;
}
} else if (!i && c == '/') { /* here i must get argv[0] */
} else if (!i && (flags&1) && c == '/') { /* here i must get argv[0] */
*pp=p;
}
}
@ -73,13 +73,13 @@ static void close_piped(int piped[3][2])
}
}
static int x_popen(char *command, int uid, int gid, FILE_PIPE *fp)
static int x_popen(char *command, int uid, int gid, FILE_PIPE *fp, int flags)
{
int piped[3][2];
int lpid=-1;
int j=3;
char buf[300];
char **argv=build_argv(buf, sizeof(buf), command);
char **argv=build_argv(buf, sizeof(buf), command, flags);
if (argv == NULL) return(-1);
while (j--){
int k=2;
@ -113,7 +113,10 @@ static int x_popen(char *command, int uid, int gid, FILE_PIPE *fp)
if (gid > -1) setegid(gid);
if (uid > -1) seteuid(uid);
}
if (flags&1)
execvp(buf, argv);
else
execv(buf, argv);
exit(1); /* Never reached I hope */
}
j=-1;
@ -134,12 +137,18 @@ int ext_pclose(FILE_PIPE *fp)
void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
void (*hupsave) (int) = signal(SIGHUP, SIG_IGN);
int j = 3;
int tries=5;
while (j--) close(fp->fds[j]);
if (fp->command_pid != waitpid(fp->command_pid, &status, 0)) {
while (fp->command_pid != waitpid(fp->command_pid, &status, WNOHANG)
&& tries>0) {
--tries;
XDPRINTF((10,0, "ext_pclose, tries=%d", tries));
if (tries==2 || tries==1)
kill(fp->command_pid, SIGTERM);
waitpid(fp->command_pid, &status, 0);
}
else if (!tries)
kill(fp->command_pid, SIGKILL);
sleep(1);
}
signal(SIGINT, intsave);
signal(SIGQUIT, quitsave);
signal(SIGHUP, hupsave);
@ -147,13 +156,14 @@ int ext_pclose(FILE_PIPE *fp)
return(status);
}
FILE_PIPE *ext_popen(char *command, int uid, int gid)
FILE_PIPE *ext_popen(char *command, int uid, int gid, int flags)
/* flags & 1 use path version of exec */
{
FILE_PIPE *fp=(FILE_PIPE*) xcmalloc(sizeof(FILE_PIPE));
void (*intsave) (int) = signal(SIGINT, SIG_IGN);
void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
void (*hupsave) (int) = signal(SIGHUP, SIG_IGN);
if ((fp->command_pid = x_popen(command, uid, gid, fp)) < 0) {
if ((fp->command_pid = x_popen(command, uid, gid, fp, flags)) < 0) {
xfree(fp);
fp=NULL;
XDPRINTF((1, 0x10, "ext_popen failed:uid=%d, gid=%d,command='%s'",

View File

@ -1,4 +1,4 @@
/* extpipe.h 08-Aug-97 */
/* extpipe.h 31-Jul-98 */
#ifndef _EXTPIPE_H_
#define _EXTPIPE_H_
@ -11,6 +11,6 @@ typedef struct {
} FILE_PIPE;
extern int ext_pclose(FILE_PIPE *fp);
extern FILE_PIPE *ext_popen(char *command, int uid, int gid);
extern FILE_PIPE *ext_popen(char *command, int uid, int gid, int flags);
#endif

233
ftrustee.c Normal file
View File

@ -0,0 +1,233 @@
/* ftrustee.c, 19.09.99 */
/* (C)opyright (C) 1999 Martin Stover, Marburg, Germany
*
* 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 "net.h"
#include "trustee.h"
#include "nwvolume.h"
int default_uid=-1;
int default_gid=-1;
int act_uid=0; // unix uid
int act_gid=0; // unix uid
int act_id_flags=0; /* &1 == supervisor equivalence !!! */
int act_obj_id=0L; /* mars_nwe UID, 0=not logged in, 1=supervisor */
static gid_t *act_grouplist=NULL; /* first element is counter !! */
void set_default_guid(void)
{
seteuid(0);
setgroups(0, NULL);
if (setegid(default_gid) < 0 || seteuid(default_uid) < 0) {
errorp(1, "set_default_guid, !! SecurityAbort !!",
"Cannot set default gid=%d and uid=%d" , default_gid, default_uid);
exit(1);
}
act_gid = default_gid;
act_uid = default_uid;
xfree(act_grouplist);
}
void set_guid(int gid, int uid)
{
if ( gid < 0 || uid < 0
|| seteuid(0)
|| setegid(gid)
|| seteuid(uid) ) {
set_default_guid();
if (gid < 0 && uid < 0) {
/* don't print error */
gid = act_gid;
uid = act_uid;
}
} else if (act_gid != gid || act_uid != uid) {
struct passwd *pw = getpwuid(uid);
if (NULL != pw) {
seteuid(0);
initgroups(pw->pw_name, gid);
}
act_gid = gid;
act_uid = uid;
xfree(act_grouplist);
if (seteuid(uid))
set_default_guid();
else {
int k=getgroups(0, NULL);
if (k > 0) {
act_grouplist=(gid_t*)xmalloc((k+1) * sizeof(gid_t));
getgroups(k, act_grouplist+1);
*act_grouplist=(gid_t)k;
}
}
}
XDPRINTF((5,0,"SET GID=%d, UID=%d %s", gid, uid,
(gid==act_gid && uid == act_uid) ? "OK" : "failed"));
}
void reset_guid(void)
{
set_guid(act_gid, act_uid);
}
void reseteuid(void)
{
if (seteuid(act_uid))
reset_guid();
}
int in_act_groups(gid_t gid)
/* returns 1 if gid is member of act_grouplist else 0 */
{
int k;
gid_t *g;
if (!act_grouplist) return(0);
k=(int)*act_grouplist;
g = act_grouplist;
while (k--) {
if (*(++g) == gid) return(1);
}
return(0);
}
int get_unix_eff_rights(struct stat *stb)
/* returns F_OK, R_OK, W_OK, X_OK */
/* ORED with 0x10 if owner access */
/* ORED with 0x20 if group access */
{
int mode = 0;
if (!act_uid)
return(0x10 | R_OK | W_OK | X_OK) ; /* root */
else {
if (act_uid == stb->st_uid) {
mode |= 0x10;
if (stb->st_mode & S_IXUSR)
mode |= X_OK;
if (stb->st_mode & S_IRUSR)
mode |= R_OK;
if (stb->st_mode & S_IWUSR)
mode |= W_OK;
} else if ( (act_gid == stb->st_gid)
|| in_act_groups(stb->st_gid) ) {
mode |= 0x20;
if (stb->st_mode & S_IXGRP)
mode |= X_OK;
if (stb->st_mode & S_IRGRP)
mode |= R_OK;
if (stb->st_mode & S_IWGRP)
mode |= W_OK;
} else {
if (stb->st_mode & S_IXOTH)
mode |= X_OK;
if (stb->st_mode & S_IROTH)
mode |= R_OK;
if (stb->st_mode & S_IWOTH)
mode |= W_OK;
}
}
return(mode);
}
#if 0
FILE *open_trustee_file(char *volname, char *opmode)
{
FILE *f=fopen(
return(f);
}
#endif
int do_export_trustees(char *expfn)
{
int j=0;
NW_VOL *v = nw_volumes;
while (j++ < used_nw_volumes) {
FILE *f=NULL;
if (v->options & VOL_OPTION_TRUSTEES) {
char fn[300];
memcpy(fn, v->unixname, v->unixnamlen);
strmaxcpy(fn+v->unixnamlen, ".trustees", 300-v->unixnamlen-1);
printf("volume %d, '%s', '%s', '%s'\n",
j, v->sysname, v->unixname, fn);
if (NULL != (f=fopen(fn, "w")) ) {
chmod(fn, 0600);
chown(fn, 0, 0);
fclose(f);
} else
errorp(0, "do_export_trustees", "cannot open '%s'", fn);
}
v++;
}
return(-1);
}
int do_import_trustees(char *expfn)
{
return(-1);
}
static int localinit(void)
{
FILE *f= open_nw_ini();
if (f != (FILE*) NULL){
int k=-1;
nw_init_volumes(f);
fclose(f);
printf("Count Volumes = %d, trusteepath=%s\n",
used_nw_volumes, path_trustees);
#if 1
while (++k < used_nw_volumes) {
NW_VOL *v = nw_volumes+k;
printf("volume %2d|%-15s|%s\n", k, v->sysname, v->unixname);
}
#endif
} else
printf("open_nw_ini failed\n");
return(0);
}
static int usage(char *s)
{
char *p=strrchr(s, '/');
fprintf(stderr, "usage:\t%s e | i | r [path]\n", p ? p+1 : s);
fprintf(stderr, "\te = export\n");
fprintf(stderr, "\ti = import\n");
fprintf(stderr, "\tr = repair\n");
return(1);
}
int main(int argc, char *argv[])
{
init_tools(0, 0);
nw_debug = 5;
localinit();
if (argc < 2) return(usage(argv[0]));
if (*argv[1] == 'e') return(do_export_trustees(argv[2]));
else if (*argv[1] == 'i') return(do_import_trustees(argv[2]));
else if (*argv[1] == 'r') if (!do_export_trustees(argv[2]))
return(do_import_trustees(argv[2]));
else return(1);
else usage(argv[0]);
return(0);
}

197
ipxif.c Normal file
View File

@ -0,0 +1,197 @@
/* inserted by Boris Popov <bp@butya.kz> */
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <net/if.h>
#ifndef if_mtu
# include <net/if_var.h>
#endif
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
/* IPX */
#include <netipx/ipx.h>
#include <netipx/ipx_if.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "emutli.h"
static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
static int if_ipxscan __P((int addrcount, struct sockaddr_dl *sdl, struct if_msghdr *ifm,
struct ifa_msghdr *ifam,struct ipx_addr *addr));
/*
* Find IPX interface.
* ifname specifies interface name, if NULL search for all interfaces
* if ifname[0]='0', also all interfaces, but return its name
* addr on input preferred net address can be specified or 0 for any,
* on return contains full address (except port)
* returns 0 if interface was found
*/
int
ipx_iffind(char *ifname,struct ipx_addr *addr){
char name[32];
int all=0, flags, foundit = 0, addrcount;
struct if_msghdr *ifm, *nextifm;
struct ifa_msghdr *ifam;
struct sockaddr_dl *sdl;
char *buf, *lim, *next;
size_t needed;
int mib[6];
if( ifname!=NULL ) {
strncpy(name,ifname,sizeof(name)-1);
if( name[0]==0 )
all=1;
} else
all = 1;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_IPX;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
return(1);
if ((buf = malloc(needed)) == NULL)
return(1);
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
free(buf);
return(1);
}
lim = buf + needed;
next = buf;
while (next < lim) {
ifm = (struct if_msghdr *)next;
if (ifm->ifm_type == RTM_IFINFO) {
sdl = (struct sockaddr_dl *)(ifm + 1);
flags = ifm->ifm_flags;
} else {
fprintf(stderr, "if_ipxfind: out of sync parsing NET_RT_IFLIST\n");
fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, ifm->ifm_type);
fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen);
fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, lim);
free(buf);
return(1);
}
next += ifm->ifm_msglen;
ifam = NULL;
addrcount = 0;
while (next < lim) {
nextifm = (struct if_msghdr *)next;
if (nextifm->ifm_type != RTM_NEWADDR)
break;
if (ifam == NULL)
ifam = (struct ifa_msghdr *)nextifm;
addrcount++;
next += nextifm->ifm_msglen;
}
if (all) {
if ((flags & IFF_UP) == 0)
continue; /* not up */
strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
name[sdl->sdl_nlen] = '\0';
} else {
if (strlen(name) != sdl->sdl_nlen)
continue; /* not same len */
if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
continue; /* not same name */
}
foundit=if_ipxscan(addrcount, sdl, ifm, ifam, addr);
if( foundit ) {
if( ifname!=NULL && ifname[0]==0) {
strncpy(ifname,sdl->sdl_data, sdl->sdl_nlen);
ifname[sdl->sdl_nlen]=0;
}
break;
}
}
free(buf);
return foundit ? 0:1;
}
int
if_ipxscan(addrcount, sdl, ifm, ifam, addr)
int addrcount;
struct sockaddr_dl *sdl;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct ipx_addr *addr;
{
struct rt_addrinfo info;
struct sockaddr_ipx *sipx;
int s;
if ((s = socket(AF_IPX, SOCK_DGRAM, 0)) < 0) {
perror("ifconfig: socket");
return 0;
}
while (addrcount > 0) {
info.rti_addrs = ifam->ifam_addrs;
/* Expand the compacted addresses */
rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info);
addrcount--;
ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
if (info.rti_info[RTAX_IFA]->sa_family == AF_IPX) {
sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA];
if( ipx_nullnet(sipx->sipx_addr) ) continue;
if( ipx_nullnet(*addr) ||
ipx_neteq(sipx->sipx_addr,*addr) ) {
*addr=sipx->sipx_addr;
close(s);
return(1);
}
}
}
close(s);
return(0);
}
/*
* Expand the compacted form of addresses as returned via the
* configuration read via sysctl().
*/
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
static void
rt_xaddrs(cp, cplim, rtinfo)
caddr_t cp, cplim;
struct rt_addrinfo *rtinfo;
{
struct sockaddr *sa;
int i;
memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
if ((rtinfo->rti_addrs & (1 << i)) == 0)
continue;
rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
ADVANCE(cp, sa);
}
}

View File

@ -1,5 +1,5 @@
#if 0
#makefile.unx 04-Feb-98
#makefile.unx 15-Apr-00
#endif
VPATH=$(V_VPATH)
@ -9,7 +9,7 @@ C=.c
V_H=0
V_L=99
P_L=6
P_L=19
#define D_P_L 1
DISTRIB=mars_nwe
@ -79,6 +79,7 @@ PROG5=nwclient
PROG6=nwbind
PROG7=nwrouted
PROG8=dbmtool
PROG9=ftrustee
#include "config.h"
#ifdef FILENAME_NW_INI
@ -93,45 +94,55 @@ M_PATHNAME_PROGS=PATHNAME_PROGS
M_PATHNAME_PROGS="."
#endif
#ifndef INTERNAL_RIP_SAP
#define INTERNAL_RIP_SAP 1
#endif
M_PATHNAME_BINDERY=PATHNAME_BINDERY
#ifdef LINUX
# ifdef FREEBSD
EMUTLIOBJ=emutli$(O) ipxif$(O)
NWROUTE_O=nwroute1$(O)
NWROUTED=
# else
# ifndef INTERNAL_RIP_SAP
# define INTERNAL_RIP_SAP 1
# endif
EMUTLIOBJ=emutli$(O)
EMUTLIOBJ1=emutli1$(O)
# if INTERNAL_RIP_SAP
EMUTLIOBJ1=emutli1$(O)
NWROUTE_O=nwroute$(O)
# else
EMUTLIOBJ1=
NWROUTE_O=nwroute1$(O)
NWROUTED=$(PROG7)
# endif
# endif
#else
NWROUTE_O=nwroute1$(O)
NWROUTED=
#endif
INSTALLPROGS=$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(NWROUTED)
PROGS=$(INSTALLPROGS) $(PROG8)
PROGS=$(INSTALLPROGS) $(PROG8) $(PROG9)
OBJ1= $(EMUTLIOBJ) net1$(O) tools$(O)
OBJ2= $(OBJ1) $(EMUTLIOBJ1) $(NWROUTE_O)
OBJ3= $(OBJ1) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) unxfile$(O) \
nwqconn$(O) nameos2$(O) nwfname$(O) nwshare$(O) extpipe$(O) \
nwattrib$(O)
nwattrib$(O) trustee$(O)
OBJ4= $(OBJ1)
OBJ5= $(OBJ1)
OBJ6= $(OBJ1) nwdbm$(O) nwcrypt$(O) unxlog$(O) sema$(O) nwqueue$(O)
OBJ7= $(OBJ1) $(EMUTLIOBJ1)
OBJ6= $(OBJ1) nwdbm$(O) nwcrypt$(O) unxlog$(O) sema$(O) nwqueue$(O) unxfile$(O)
OBJ7= $(OBJ1) emutli1$(O)
OBJ8= $(OBJ6)
OBJ9= tools$(O) nwfname$(O) unxfile$(O) nwvolume$(O) nwattrib$(O) trustee$(O)
OBJS= $(EMUTLIOBJ) net1$(O) tools$(O) \
$(EMUTLIOBJ1) $(NWROUTE_O) \
connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) unxfile$(O)\
nwqconn$(O) nameos2$(O) nwfname$(O) nwshare$(O) extpipe$(O) \
nwattrib$(O) \
nwattrib$(O) trustee$(O) \
nwdbm$(O) nwcrypt$(O) unxlog$(O) sema$(O) nwqueue$(O) \
$(PROG2)$(O) $(PROG3)$(O) $(PROG4)$(O) $(PROG5)$(O) $(PROG6)$(O) \
$(PROG7)$(O) $(PROG8)$(O)
$(PROG7)$(O) $(PROG8)$(O) $(PROG9)$(O)
HOBJ3= $(PROG3)$(O) connect$(O) namspace$(O) nwvolume$(O) nwfile$(O) \
unxfile$(O)
@ -168,6 +179,9 @@ $(PROG7): $(PROG7)$(O) $(OBJ7)
$(PROG8): $(PROG8)$(O) $(OBJ8)
$(CC) -o $(VPATH)/$(PROG8) $(PROG8)$(O) $(OBJ8) $(NDBMLIB) $(CRYPTLIB) $(NSLLIB)
$(PROG9): $(PROG9)$(O) $(OBJ9)
$(CC) -o $(VPATH)/$(PROG9) $(PROG9)$(O) $(OBJ9) $(CRYPTLIB) $(NSLLIB)
$(HOBJ3): namspace.h connect.h nwvolume.h nwfile.h
$(HOBJ6): nwbind.h sema.h
$(OBJS): net.h config.h
@ -195,6 +209,19 @@ n_install:
echo "remove old version in /sbin ?" ; \
(cd /sbin && rm -i nwserv nwbind ncpserv nwconn nwclient nwrouted) ; \
fi ;
@-if [ -r /etc/nwobj.pag ] ; then \
( \
if [ ! -r $(M_PATHNAME_BINDERY) ] ; then \
if $(VPATH)/tools.sh yesno "move bindery files from /etc to $(M_PATHNAME_BINDERY) ?" ; then \
mkdir -p $(M_PATHNAME_BINDERY); \
(cd /etc && mv \
nwiobj.pag nwiobj.dir nwobj.pag nwobj.dir \
nwprop.pag nwprop.dir nwval.pag nwval.dir \
$(M_PATHNAME_BINDERY) ) ; \
fi; \
fi; \
) \
fi ;
@cd $(VPATH) && (if [ -r $(M_FILENAME_NW_INI) ] ; then \
echo ""; \
echo "********************************************************"; \
@ -246,6 +273,7 @@ make_dir:
; ln -f \
$(STERN).[ch] \
makefile.unx \
tools.sh \
Makefile \
COPYING \
README \

File diff suppressed because it is too large Load Diff

View File

@ -418,6 +418,10 @@ static void close_all(void)
{
int k=0;
while (k++ < count_connections) clear_connection(k);
kill_connections();
k=0;
while (k++ < count_connections) clear_connection(k);
kill_connections();
if (ncp_fd > -1) {
t_unbind(ncp_fd);
t_close(ncp_fd);

30
net.h
View File

@ -1,4 +1,4 @@
/* net.h 02-Jun-97 */
/* net.h 12-Jan-99 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
@ -19,10 +19,21 @@
#ifndef _M_NET_H_
#define _M_NET_H_
#ifndef _XOPEN_SOURCE
# define _XOPEN_SOURCE 1
#endif
#define _SVID_SOURCE 1
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* moved 12-May-98 0.99.pl9 */
#include <signal.h>
#ifdef __USE_BSD
# undef signal
# define signal sysv_signal
#endif
#include <string.h>
#ifndef LINUX
@ -31,9 +42,12 @@
#endif
#include <sys/fcntl.h>
#include <sys/types.h>
/* #include <sys/types.h> moved 12-May-98 0.99.pl9 */
#include <unistd.h>
#include <sys/stat.h>
#ifndef S_ISLNK
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#include <time.h>
#include <sys/wait.h>
#include <utmp.h>
@ -50,7 +64,6 @@ extern int errno;
/* # include "common.h" */
/* # include "portable.h" , needed ??? */
# include <sys/ipx_app.h>
#else
# include <sys/ioctl.h>
# include "emutli.h" /* TLI-EMULATION */
@ -180,7 +193,7 @@ extern int errno;
#endif
#ifndef PATHNAME_BINDERY
# define PATHNAME_BINDERY "/etc" /* location of bindery files */
# define PATHNAME_BINDERY "/var/nwserv/db" /* location of bindery files */
#endif
#ifndef PATHNAME_PIDFILES
@ -280,6 +293,11 @@ extern int errno;
# ifndef INTERNAL_RIP_SAP
# define INTERNAL_RIP_SAP 1
# endif
# ifdef FREEBSD
/* FreeBSD has own rip/sap router */
# undef INTERNAL_RIP_SAP
# define INTERNAL_RIP_SAP 0
# endif
#else
/* USL has rip/sap router builtin */
# undef INTERNAL_RIP_SAP
@ -370,7 +388,7 @@ typedef union {
*/
} diaresp;
struct S_NCPRESPONSE { /* size = 8 */
uint8 type[2]; /* 0x3333 */
uint8 type[2]; /* 0x3333 or internal 0x3232 */
uint8 sequence;
uint8 connection; /* low connection */
uint8 task;
@ -379,7 +397,7 @@ typedef union {
uint8 connect_status;
} ncpresponse;
struct S_NCPREQUEST { /* size = 7 */
uint8 type[2]; /* 0x1111 od 0x2222 */
uint8 type[2]; /* 0x1111 or 0x2222 or internal 0x1212 */
uint8 sequence;
uint8 connection; /* low connection */
uint8 task;

43
net1.c
View File

@ -1,6 +1,6 @@
/* net1.c, 11-Mar-97 */
/* net1.c, 19.09.99 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
/* (C)opyright (C) 1993-99 Martin Stover, Marburg, Germany
*
* 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
@ -355,3 +355,42 @@ int get_ipx_addr(ipxAddr_t *addr)
return(result);
}
#endif
uint8 *station_fn=NULL;
int find_station_match(int entry, ipxAddr_t *addr)
{
int matched = 0;
if (station_fn && *station_fn) {
FILE *f=fopen((char*)station_fn, "r");
if (f) {
uint8 buff[200];
uint8 addrstring[100];
int what;
ipx_addr_to_adr((char*)addrstring, addr);
upstr(addrstring);
while (0 != (what = get_ini_entry(f, 0, buff, sizeof(buff)))){
if (what == entry) {
uint8 *p = buff + strlen((char*)buff);
while (p-- > buff && *p==32) *p='\0';
upstr(buff);
if (name_match(addrstring, buff)) {
matched=1;
break;
}
}
}
fclose(f);
} else {
XDPRINTF((3, 0, "find_station_match, cannot open '%s'",
station_fn));
}
}
XDPRINTF((3, 0, "find_station_match entry=%d, matched=%d, addr=%s",
entry, matched, visable_ipx_adr(addr)));
return(matched);
}

7
net1.h
View File

@ -1,6 +1,6 @@
/* net1.h 25-Oct-96 */
/* net1.h 19.09.99 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
/* (C)opyright (C) 1993-99 Martin Stover, Marburg, Germany
*
* 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
@ -48,4 +48,7 @@ extern int send_own_reply(int fd, int result, int sequence, ipxAddr_t *toaddr);
extern int get_ipx_addr(ipxAddr_t *addr);
extern uint8 *station_fn;
extern int find_station_match(int entry, ipxAddr_t *addr);
#endif

View File

@ -1,4 +1,4 @@
/* nwattrib.c 09-Feb-98 */
/* nwattrib.c 10-May-98 */
/* (C)opyright (C) 1998 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -16,12 +16,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Attrib routines for mars_nwe */
#include "net.h"
#include <dirent.h>
#include "unxfile.h"
#include "nwvolume.h"
#include "connect.h"
#include "trustee.h"
#include "nwattrib.h"
static void put_attr_to_disk(int dev, ino_t inode, uint32 attrib)
@ -86,36 +88,42 @@ static int get_attr_from_disk(int dev, ino_t inode, uint32 *attrib)
return(0);
}
}
*attrib=0;
return(-1);
}
uint32 get_nw_attrib_dword(struct stat *stb, int voloptions)
uint32 get_nw_attrib_dword(int volume, char *unixname, struct stat *stb)
/* returns full attrib_dword */
{
uint32 attrib=0;
int is_dir=S_ISDIR(stb->st_mode);
uint32 attrib = S_ISDIR(stb->st_mode) ? FILE_ATTR_DIR
: FILE_ATTR_A;
if (!is_dir && (voloptions & VOL_OPTION_IS_PIPE))
return(FILE_ATTR_SHARE|FILE_ATTR_A);
int voloptions = get_volume_options(volume);
if (voloptions & VOL_OPTION_READONLY)
return((is_dir)?FILE_ATTR_DIR|FILE_ATTR_R:FILE_ATTR_R);
if (!get_attr_from_disk(stb->st_dev, stb->st_ino, &attrib)) {
if (is_dir) attrib |= FILE_ATTR_DIR;
else attrib &= (~FILE_ATTR_DIR);
} else {
if (is_dir)
attrib = FILE_ATTR_DIR;
else
attrib = FILE_ATTR_A; /* default archive flag */
if (voloptions & VOL_OPTION_IS_PIPE) {
attrib |= (FILE_ATTR_DELETE_INH|FILE_ATTR_RENAME_INH);
if (!S_ISDIR(stb->st_mode)){
attrib|=FILE_ATTR_SHARE;
}
return(attrib);
}
if ( (voloptions & VOL_OPTION_ATTRIBUTES) &&
!get_attr_from_disk(stb->st_dev, stb->st_ino, &attrib)) {
if (S_ISDIR(stb->st_mode)) attrib |= FILE_ATTR_DIR;
else attrib &= (~FILE_ATTR_DIR);
}
if (voloptions & VOL_OPTION_READONLY){
attrib |= (FILE_ATTR_DELETE_INH|FILE_ATTR_RENAME_INH|FILE_ATTR_R);
}
if (!(voloptions & VOL_OPTION_ATTRIBUTES)) {
/* only for volumes without attribute handling */
if (act_uid) {
/* if not root */
int acc=get_real_access(stb);
int acc=get_unix_eff_rights(stb);
if (!(acc & W_OK)) {
attrib |= FILE_ATTR_R; /* RO */
}
@ -123,207 +131,111 @@ uint32 get_nw_attrib_dword(struct stat *stb, int voloptions)
attrib |= FILE_ATTR_H; /* We say hidden here */
}
}
}
return(attrib);
}
int set_nw_attrib_dword(struct stat *stb, int voloptions, uint32 attrib)
static int set_nw_attrib(
int volume, char *unixname, struct stat *stb, uint32 attrib, uint32 mode)
/* mode == 0 : set_nw_attrib_dword
1 : set_nw_attrib_byte
2 : set_nw_attrib_word
*/
{
int is_dir=S_ISDIR(stb->st_mode);
if (voloptions & VOL_OPTION_READONLY)
return(-0x8c); /* no modify rights */
uint32 oldattrib,newattrib;
int voloptions=get_volume_options(volume);
if (voloptions & VOL_OPTION_IS_PIPE)
return(0);
if (!(get_real_access(stb) & W_OK))
return(0); /* we return with no error */
if (tru_eff_rights_exists(volume, unixname, stb, TRUSTEE_M))
return(-0x8c); /* no modify rights */
if (!(voloptions & VOL_OPTION_ATTRIBUTES)) {
if (!(get_unix_eff_rights(stb) & W_OK)) {
if (!(attrib & FILE_ATTR_R)) { /* if not setting RO */
if (!chmod(unixname, stb->st_mode | S_IWUSR)) {
stb->st_mode |= S_IWUSR;
} else
return(-0x8c); /* no modify rights */
}
}
}
if (mode || !(voloptions & VOL_OPTION_ATTRIBUTES)) {
oldattrib=get_nw_attrib_dword(volume, unixname, stb);
if (mode==1) { /* byte */
newattrib = (oldattrib & ~0xff);
newattrib |= (attrib & 0xff);
} else if (mode==2) { /* word */
newattrib = (oldattrib & ~0xffff);
newattrib |= (attrib & 0xffff);
} else newattrib=attrib;
} else {
newattrib=attrib;
}
if (is_dir) attrib |= 0x10;
else attrib &= ~0x10;
put_attr_to_disk(stb->st_dev, stb->st_ino, attrib);
if ((!mode) || (newattrib != oldattrib) ) {
if (!(voloptions & VOL_OPTION_ATTRIBUTES)) {
if ((!is_dir) && ((newattrib&FILE_ATTR_R)!=(oldattrib&FILE_ATTR_R))) {
int oldmode=stb->st_mode;
if (newattrib & FILE_ATTR_R) /* R/O */
stb->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
else
stb->st_mode |= (S_IWUSR | S_IWGRP);
if (chmod(unixname, stb->st_mode)) {
stb->st_mode = oldmode;
return(-0x8c); /* no modify rights */
}
}
} else {
if (is_dir) newattrib |= 0x10;
else newattrib &= ~0x10;
put_attr_to_disk(stb->st_dev, stb->st_ino, newattrib);
}
}
return(0);
}
int set_nw_attrib_byte(struct stat *stb, int voloptions, int battrib)
int set_nw_attrib_dword(int volume, char *unixname, struct stat *stb, uint32 attrib)
/* wattrib = ext_attrib, attrib */
{
int is_dir=S_ISDIR(stb->st_mode);
uint32 attrib,oldattrib;
if (voloptions & VOL_OPTION_READONLY)
return(-0x8c); /* no modify rights */
if (voloptions & VOL_OPTION_IS_PIPE)
return(0);
if (!(get_real_access(stb) & W_OK))
return(-0x8c); /* no modify rights */
oldattrib=get_nw_attrib_dword(stb, voloptions);
attrib = (oldattrib & ~0xff);
attrib |= battrib;
if (is_dir) attrib |= 0x10;
else attrib &= ~0x10;
if (attrib != oldattrib)
put_attr_to_disk(stb->st_dev, stb->st_ino, attrib);
return(0);
return(set_nw_attrib(volume,unixname,stb,attrib, 0));
}
void set_nw_archive_bit(int dev, ino_t inode)
/* only called for files */
int set_nw_attrib_byte(int volume, char *unixname, struct stat *stb, int battrib)
{
uint32 attrib;
return(set_nw_attrib(volume,unixname,stb,(uint32)battrib, 1));
}
int set_nw_attrib_word(int volume, char *unixname, struct stat *stb, int wattrib)
/* wattrib = ext_attrib, attrib */
{
return(set_nw_attrib(volume,unixname,stb,(uint32)wattrib, 2));
}
void set_nw_archive_bit(int volume, char *unixname, int dev, ino_t inode)
/* sets archive bit on files, is called when file is closed */
{
uint32 attrib=0L;
int voloptions=get_volume_options(volume);
if (voloptions & VOL_OPTION_ATTRIBUTES) {
if ( (!get_attr_from_disk(dev, inode, &attrib))
&& !(attrib & FILE_ATTR_A)) {
attrib|=FILE_ATTR_A;
put_attr_to_disk(dev, inode, attrib);
}
}
}
/* trustees */
static void put_trustee_to_disk(int dev, ino_t inode, uint32 id, int trustee)
{
char buf[255];
char btrustee[255];
int l;
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
l=sprintf(buf, "%s/%x/%x/%x/%x/%x.t", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
unx_xmkdir(buf, 0755);
sprintf(buf+l, "/%x", (unsigned int) id);
unlink(buf);
l=sprintf(btrustee, "%04x", (unsigned int) trustee);
symlink(btrustee, buf);
reseteuid();
}
static void free_trustees_from_disk(int dev, ino_t inode)
{
char buf[255];
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
sprintf(buf, "%s/%x/%x/%x/%x/%x.t", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
unx_xrmdir(buf);
reseteuid();
}
static int get_trustee_from_disk(int dev, ino_t inode, uint32 id)
{
char buf[255];
char btrustee[255];
int l;
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
sprintf(buf, "%s/%x/%x/%x/%x/%x.t/%x", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3],
(unsigned int) id);
seteuid(0);
l=readlink(buf, btrustee, 254);
reseteuid();
if (l > 0) {
unsigned int utrustee=0;
btrustee[l]='\0';
if (1 == sscanf(btrustee, "%x", &utrustee)) {
return((int)utrustee);
}
}
return(-1);
}
static int scan_trustees_from_disk(int dev, ino_t inode, int *offset,
int max_trustees, uint32 *trustee_ids, int *trustees)
/* returns count of trustees if all ok */
{
char buf[255];
int l;
int count=0;
uint8 buf_uc[4];
DIR *d;
U32_TO_BE32(inode, buf_uc);
l=sprintf(buf, "%s/%x/%x/%x/%x/%x.t", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
d = opendir(buf);
if (NULL != d) {
uint8 *p=buf+l;
struct dirent *dirbuff;
*p++ = '/';
l=0;
if ((unsigned int)(*offset) >= MAX_U16)
*offset=0;
while (count < max_trustees &&
(dirbuff = readdir(d)) != (struct dirent*)NULL){
if (l++ > *offset) {
if (dirbuff->d_ino) {
char btrustee[255];
int len;
unsigned int id;
if (1 == sscanf(dirbuff->d_name, "%x", &id) && id > 0) {
strcpy(p, dirbuff->d_name);
len=readlink(buf, btrustee, 254);
if (len > 0) {
unsigned int utrustee=0;
btrustee[len]='\0';
if (1 == sscanf(btrustee, "%x", &utrustee)) {
*trustee_ids++ = (uint32) id;
*trustees++ = (int) utrustee;
count++;
}
}
}
}
}
}
*offset=l;
closedir(d);
}
reseteuid();
return(count);
}
int get_own_trustee(int dev, ino_t inode, int look_for_trustee)
{
if (act_obj_id == 1){ /* supervisor */
if ( (look_for_trustee == TRUSTEE_S) || (look_for_trustee == TRUSTEE_M)
|| (look_for_trustee == (TRUSTEE_S | TRUSTEE_M)) )
return(look_for_trustee | TRUSTEE_S);
}
return(0);
}
int set_nw_trustee(int dev, ino_t inode, uint32 id, int trustee)
{
return(0);
#if 0
if (get_own_trustee(dev, inode, TRUSTEE_M) & (TRUSTEE_M | TRUSTEE_S)){
} else return(-0x8c); /* no modify privileges */
#endif
}
void free_nw_ext_inode(int dev, ino_t inode)
void free_nw_ext_inode(int volume, char *unixname, int dev, ino_t inode)
/* removes all attrib or trustees entries for files or dirs */
/* must be called after deleting nw file or dir */
{
int voloptions=get_volume_options(volume);
if (voloptions & VOL_OPTION_ATTRIBUTES)
free_attr_from_disk(dev, inode);
free_trustees_from_disk(dev, inode);
if (voloptions & VOL_OPTION_TRUSTEES) {
int i=used_nw_volumes;
while(i--)
tru_free_file_trustees_from_disk(i, dev, inode);
}
}

View File

@ -1,16 +1,27 @@
/* nwattrib.h 01-Feb-98 */
/* nwattrib.h 30-Apr-98 */
#ifndef _NWATTRIB_H_
#define _NWATTRIB_H_
extern uint32 get_nw_attrib_dword(struct stat *stb, int voloptions);
extern int set_nw_attrib_dword(struct stat *stb, int voloptions, uint32 attrib);
extern int set_nw_attrib_byte (struct stat *stb, int voloptions, int battrib);
extern void set_nw_archive_bit(int dev, ino_t inode);
/* <-------------- File Attributes -------------> */
#define FILE_ATTR_NORMAL 0x00000000
#define FILE_ATTR_R 0x00000001
#define FILE_ATTR_H 0x00000002
#define FILE_ATTR_S 0x00000004
#define FILE_ATTR_DIR 0x00000010
#define FILE_ATTR_A 0x00000020
#define FILE_ATTR_SHARE 0x00000080
extern int set_nw_trustee(int dev, ino_t inode, uint32 id, int trustee);
#define FILE_ATTR_RENAME_INH 0x00020000
#define FILE_ATTR_DELETE_INH 0x00040000
extern uint32 get_nw_attrib_dword(int volume, char *unixname, struct stat *stb);
extern int set_nw_attrib_dword(int volume, char *unixname, struct stat *stb, uint32 attrib);
extern int set_nw_attrib_byte (int volume, char *unixname, struct stat *stb, int battrib);
extern int set_nw_attrib_word(int volume, char *unixname, struct stat *stb, int wattrib);
extern void set_nw_archive_bit(int volume, char *unixname, int dev, ino_t inode);
extern void free_nw_ext_inode(int dev, ino_t inode);
extern void free_nw_ext_inode(int volume, char *unixname, int dev, ino_t inode);
#endif

575
nwbind.c
View File

@ -1,9 +1,9 @@
/* nwbind.c */
#define REVISION_DATE "04-Feb-98"
#define REVISION_DATE "25-Apr-00"
/* NCP Bindery SUB-SERVER */
/* authentification and some message handling */
/* authentification and some message and queue handling */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
/* (C)opyright (C) 1993,2000 Martin Stover, Marburg, Germany
*
* 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
@ -19,6 +19,15 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* history since 21-Apr-00
*
* mst:25-Apr-00: added login control routines from Paolo Prandini
* mst:25-Apr-00: added simple example for getting nwconn data
*
*/
#include "net.h"
#include "nwdbm.h"
#include "unxlog.h"
@ -82,9 +91,236 @@ static int max_nw_vols=MAX_NW_VOLS;
static int max_connections=MAX_CONNECTIONS;
static CONNECTION *connections=NULL;
static CONNECTION *act_c=(CONNECTION*)NULL;
static int act_connection;
static int internal_act=0;
// Check if the new cleartext password is acceptable or not
static int nw_valid_newpasswd(uint32 obj_id, char *newpasswd)
{
LOGIN_CONTROL lc;
int result;
XDPRINTF((99, 0, "Change password for user %x with '%s'", obj_id, newpasswd));
result = nw_get_login_control(obj_id, &lc);
if (result < 0) return(0); /* No restrictions available */
XDPRINTF((2, 0, "len(pwd)=%d limit=%d", strlen(newpasswd), lc.minimumPasswordLength));
if (strlen(newpasswd)<lc.minimumPasswordLength)
return (-0xd8); // PASSWORD TOO SHORT
return 0;
}
static int nw_test_time_access(uint32 obj_id)
/*
* Code from Matt Paley, Mark Robson, Paolo Prandini
*/
{
time_t t,expiry;
struct tm exptm;
struct tm *tm;
int half_hours;
LOGIN_CONTROL lc;
int result;
result=nw_get_login_control(obj_id,&lc);
if (result < 0) return(0); /* No time limits available */
/* Check if account disabled - MR */
if (lc.accountExpired) /* Disabled */
{
XDPRINTF((1, 0, "No access for user %x - disabled.",obj_id));
return (-0xdc);
}
/* Account expires at 23:59:59 on the expiry day :) */
if (lc.accountExpiresYear) {
exptm.tm_year = lc.accountExpiresYear;
exptm.tm_mon = lc.accountExpiresMonth-1;
exptm.tm_mday = lc.accountExpiresDay;
exptm.tm_hour = 23;
exptm.tm_min = 59;
exptm.tm_sec = 59;
expiry = mktime(&exptm);
} else expiry = 0;
time(&t);
tm = localtime(&t);
if (expiry>0) /* if expiry is enabled */
{
XDPRINTF((1,0,"user has expiry of %d but time is %d",expiry,t));
if (t>expiry) /* has it expired ? */
{
XDPRINTF((1, 0, "No access for user %x - expired.",obj_id));
return (-0xdc);
}
}
half_hours = tm->tm_wday*48 + tm->tm_hour*2 + ((tm->tm_min>=30)? 1 : 0);
XDPRINTF((5,0,"half_hours=%d",half_hours));
{
char s[200];
int i;
for (i=0;i<42;i++) sprintf(s+i*3,"%02x ",lc.timeBitMap[i]);
XDPRINTF((5,0,"TIMEBITMAP=%s",s));
}
if ((lc.timeBitMap[half_hours/8] & (1<<(half_hours % 8))) == 0) {
XDPRINTF((1, 0, "No access for user %x at day %d %02d:%02d",
obj_id, tm->tm_wday, tm->tm_hour, tm->tm_min));
return(-0xda); /* unauthorized login time */
}
/* Password expires at 23:59:59 on the expiry day :) */
if (lc.passwordExpiresYear) {
exptm.tm_year = lc.passwordExpiresYear;
exptm.tm_mon = lc.passwordExpiresMonth-1;
exptm.tm_mday = lc.passwordExpiresDay;
exptm.tm_hour = 23;
exptm.tm_min = 59;
exptm.tm_sec = 59;
expiry = mktime(&exptm);
} else expiry = 0;
if (expiry>0) /* if expiry is enabled */
{
XDPRINTF((2, 0,"user has password expiry of %d and time is %d",expiry,t));
if (t>expiry) /* has it expired ? */ {
if (lc.passwordGraceLogins==0) {
XDPRINTF((1, 0, "No access for user %x - password expired,no grace.",obj_id));
return (-0xde);
}
if (lc.passwordGraceLogins!=255) {
// Decrement grace logins
lc.passwordGraceLogins--;
nw_set_login_control(obj_id, &lc);
XDPRINTF((1, 0, "Access for user %x - password expired, grace=%d.",obj_id,
lc.passwordGraceLogins));
return (-0xdf);
}
}
}
return 0;
}
static int nw_test_adr_access(uint32 obj_id, ipxAddr_t *client_adr)
{
uint8 more_segments;
uint8 property_flags;
char *propname="NODE_CONTROL";
uint8 buff[200];
uint8 wildnode[]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int segment = 1 ;
int i,j;
LOGIN_CONTROL lc;
/*
** Start by checking the authorized login stations
*/
int result=nw_get_prop_val_by_obj_id(obj_id, segment,
propname, strlen(propname),
buff, &more_segments, &property_flags);
if (result >=0 ) {
uint8 *p=buff;
int k=0;
result=-0xdb; /* unauthorized login station */
while (k++ < 12) {
if ( (IPXCMPNET(client_adr->net, p))
&& ( (IPXCMPNODE(client_adr->node, p+4) )
|| (IPXCMPNODE(wildnode, p+4))) ) {
result=0;
break;
}
p+=10;
}
} else {
// if bindery object not found, no station restrictions
result=0;
}
if (result<0) {
XDPRINTF((1, 0, "No access for user %x at Station %s",
obj_id, visable_ipx_adr(client_adr)));
return result;
}
// Read LOGIN_CONTROL object
result=nw_get_login_control(obj_id,&lc);
if (result<0) return 0;
/*
** Now check the number of concurrent connections
*/
for (i=j=0;i<max_connections;i++)
if (connections[i].active) {
// If the object logged in is the same requesting access now,
// increment the connection counter
if (connections[i].object_id==obj_id)
j++;
}
XDPRINTF((3, 0, "Found connections for user %x = %d", obj_id, j));
// If the number of active connections is >0 then check permissions
if ( (j>0) && GET_BE16(lc.maxConcurrentConnections) ) {
if (j >= GET_BE16(lc.maxConcurrentConnections)) {
XDPRINTF((1, 0, "No access for user %x - max connections=%d",obj_id,
(int)GET_BE16(lc.maxConcurrentConnections)));
return (-0xd9);
}
}
return 0;
}
int nw_test_adr_time_access(uint32 obj_id, ipxAddr_t *client_adr)
{
int result;
struct tm *tm;
time_t t;
LOGIN_CONTROL lc;
time(&t);
tm = localtime(&t);
if (obj_id==1 && (entry8_flags & 8)) {
if (nw_get_login_control(obj_id,&lc)==0) {
lc.lastLoginDate[0]=tm->tm_year;
lc.lastLoginDate[1]=tm->tm_mon+1;
lc.lastLoginDate[2]=tm->tm_mday;
lc.lastLoginDate[3]=tm->tm_hour;
lc.lastLoginDate[4]=tm->tm_min;
lc.lastLoginDate[5]=tm->tm_sec;
nw_set_login_control(obj_id,&lc);
}
return(0); /* no limits for SU */
}
result=nw_test_adr_access(obj_id, client_adr);
if (!result) result=nw_test_time_access(obj_id);
if ((result==0)||(result==-0xdf)) {
if (nw_get_login_control(obj_id,&lc)==0) {
lc.lastLoginDate[0]=tm->tm_year;
lc.lastLoginDate[1]=tm->tm_mon+1;
lc.lastLoginDate[2]=tm->tm_mday;
lc.lastLoginDate[3]=tm->tm_hour;
lc.lastLoginDate[4]=tm->tm_min;
lc.lastLoginDate[5]=tm->tm_sec;
nw_set_login_control(obj_id,&lc);
}
}
XDPRINTF((result?1:5, 0, "Access for user %x = %x.",obj_id,-result));
return(result);
}
int b_acc(uint32 obj_id, int security, int forwrite)
{
/* security levels
@ -107,8 +343,8 @@ int b_acc(uint32 obj_id, int security, int forwrite)
if (act_c->object_id > 0) return(0); /* rights for all logged */
} else if (security == 2) {
if ( act_c->object_id == obj_id
|| act_c->object_id == 1 ) return(0); /* rights for the user */
} else if (security == 3 && act_c->object_id == 1) return(0);
|| (act_c->id_flags&1) ) return(0); /* rights for the user */
} else if (security == 3 && (act_c->id_flags&1)) return(0);
switch (forwrite&0xf) {
case 0 : acc_what = "read"; break;
@ -145,6 +381,8 @@ int b_acc(uint32 obj_id, int security, int forwrite)
return(errcode);
}
static void sent_down_message(void)
{
int k = -1;
@ -152,12 +390,24 @@ static void sent_down_message(void)
while (++k < max_connections) {
CONNECTION *cn=&connections[k];
if (cn->active) {
#if 0
strmaxcpy(cn->message, "SERVER IS GOING DOWN", 58);
#else
strmaxcpy(cn->message, "MARS_NWE IS DIEING", 58);
#endif
nwserv_handle_msg(k+1);
}
} /* while */
}
static void delete_nwconn_request(CONNECTION *c)
{
if (c && c->request_nwconn) {
xfree(c->request_nwconn->data);
xfree(c->request_nwconn);
}
}
static void open_clear_connection(int conn, int activate, uint8 *addr)
{
if (conn > 0 && --conn < max_connections) {
@ -178,6 +428,11 @@ static void open_clear_connection(int conn, int activate, uint8 *addr)
}
}
c->object_id = 0;
c->id_flags = 0;
delete_nwconn_request(c);
c->last_used_sequence=0;
}
}
@ -198,19 +453,31 @@ static void get_login_time(uint8 login_time[], CONNECTION *cx)
static int build_login_response(uint8 *responsedata, uint32 obj_id)
{
uint8 pw_name[40];
uint8 *p;
int result;
int i;
act_c->object_id = obj_id; /* actuell Object ID */
act_c->t_login = akttime; /* and login Time */
act_c->id_flags = 0;
internal_act=1;
if (HAVE_SU_RIGHTS(obj_id)) {
act_c->id_flags|=1; /* supervisor equivalence */
}
get_guid((int*) responsedata,
(int*) (responsedata+sizeof(int)),
obj_id, pw_name);
*((uint32*) (responsedata+2*sizeof(int))) = obj_id;
result = get_home_dir(responsedata + 3 * sizeof(int)+1, obj_id);
*(responsedata + 3 * sizeof(int)) = (uint8) result;
result = 3 * sizeof(int) + 1 + (int) *(responsedata+ 3 * sizeof(int));
*((int*)(responsedata+2*sizeof(int))) = act_c->id_flags;
*((uint32*) (responsedata+3*sizeof(int))) = obj_id;
result=4*sizeof(int);
p = responsedata + result;
i = (uint8)get_groups_i_m_in(obj_id, (uint32*) (p+sizeof(int)) );
*(int*)(p) = i;
result+= (sizeof(int)+i*sizeof(uint32));
p=responsedata + result;
i=strlen(pw_name);
*p = (uint8) i;
memcpy(p+1, pw_name, i);
result += ( i + 1 );
write_utmp(1, act_connection, act_c->pid_nwconn,
&(act_c->client_adr), pw_name);
internal_act=0;
@ -233,7 +500,7 @@ static void handle_fxx(int gelen, int func)
uint8 connect_status= 0;
int data_len = 0;
if (func==0x19) {
if (func==0x18||func==19) {
ufunc = 0;
rdata = requestdata;
} else if (func==0x20) {
@ -330,7 +597,7 @@ static void handle_fxx(int gelen, int func)
}
internal_act=0;
/* OK if supervisor or trying to read (0x29) own limits */
if (act_c->object_id == 1 ||
if ( (act_c->id_flags&1) ||
(act_c->object_id == id && ufunc == 0x29))
((int *) responsedata)[2] = 0; /* OK */
else
@ -518,8 +785,12 @@ static void handle_fxx(int gelen, int func)
memset(password, 0, 50);
if (!result)
data_len = build_login_response(responsedata, obj.id);
else
else {
completition = (uint8) -result;
if (result==-0xdf) { /* PaPr,mst:25-Apr-00 */
data_len = build_login_response(responsedata, obj.id);
}
}
} break;
case 0x15 : { /* Get Object Connection List (old) */
@ -620,13 +891,17 @@ static void handle_fxx(int gelen, int func)
}
if (result > -1)
data_len = build_login_response(responsedata, obj.id);
else
else {
completition = (uint8) -result;
if (result==-0xdf) { /*PaPr,mst:25-Apr-00 */
data_len = build_login_response(responsedata, obj.id);
}
}
/*
* completition = 0xde means login time has expired
* completition = 0xdf means good login, but
* login time has expired
* perhaps I will integrate it later.
* login time has expired, using grace logins
*/
}
break;
@ -686,7 +961,7 @@ static void handle_fxx(int gelen, int func)
case 0x34 : { /* rename OBJECT, only SU */
int result=-0xff;
if (1 == act_c->object_id) {
if (act_c->id_flags&1) {
uint8 *p = rdata;
NETOBJ obj;
uint8 newname[256];
@ -774,7 +1049,7 @@ static void handle_fxx(int gelen, int func)
case 0x38 : { /* change Bindery Objekt Security */
/* only SU ! */
int result= -0xff;
if (1 == act_c->object_id) {
if (act_c->id_flags&1) {
uint8 *p = rdata;
NETOBJ obj;
obj.type = GET_BE16(p+1);
@ -926,19 +1201,20 @@ static void handle_fxx(int gelen, int func)
if (0 == (result = find_obj_id(&obj))) {
XDPRINTF((6, 0, "CHPW: OLD=`%s`, NEW=`%s`", oldpassword,
newpassword));
internal_act = 1;
if (act_c->object_id == 1 ||
internal_act=1;
if ((act_c->id_flags&1) ||
(0 == (result=test_allow_password_change(act_c->object_id))
&& /* PaPr,mst:25-Apr-00 */
0 == (result=nw_valid_newpasswd(act_c->object_id,newpassword))
&&
0 == (result=nw_test_unenpasswd(obj.id, oldpassword)))){
if ( (act_c->object_id != 1)
if ( (!(act_c->id_flags&1))
|| *newpassword
|| !(password_scheme & PW_SCHEME_LOGIN))
result=nw_set_passwd(obj.id, newpassword, 0);
else result = -0xff;
}
internal_act = 0;
internal_act=0;
}
if (result < 0) completition = (uint8) -result;
memset(oldpassword, 0, 50);
@ -1003,7 +1279,6 @@ static void handle_fxx(int gelen, int func)
if (result) completition = (uint8) -result;
} break;
case 0x44 : { /* CLOSE BINDERY */
;
} break;
@ -1025,7 +1300,7 @@ static void handle_fxx(int gelen, int func)
*xdata = (uint8) 0;
memset(xdata+1, 0xff, 4);
} else {
*xdata = (act_c->object_id == 1) ? (uint8) 0x33
*xdata = (act_c->id_flags&1) ? (uint8) 0x33
: (uint8) 0x22;
U32_TO_BE32(act_c->object_id, (xdata+1));
}
@ -1035,19 +1310,10 @@ static void handle_fxx(int gelen, int func)
}
break;
case 0x47 : { /* SCAN BINDERY OBJECT TRUSTEE PATH */
/* TODO !!! */
struct XDATA {
uint8 nextsequence[2];
uint8 id[4];
uint8 access_mask;
uint8 pathlen;
uint8 path[1];
} *xdata = (struct XDATA*) responsedata;
memset(xdata, 0, 8);
data_len = 8;
}
break;
#if 0
case 0x47 : /* SCAN BINDERY OBJECT TRUSTEE PATH */
handled in nwconn
#endif
case 0x48 : { /* GET BINDERY ACCES LEVEL from OBJECT ??? */
struct XDATA {
@ -1059,7 +1325,7 @@ static void handle_fxx(int gelen, int func)
result = nw_get_obj(&obj);
if (!result) {
/* don't know whether this is ok ?? */
if (act_c->object_id == 1) {
if (act_c->id_flags&1) {
xdata->acces_level = 0x33;
} else if (act_c->object_id == obj.id) {
xdata->acces_level = 0x22;
@ -1072,7 +1338,7 @@ static void handle_fxx(int gelen, int func)
break;
case 0x49 : { /* IS CALLING STATION A MANAGER */
completition = (act_c->object_id == 1) ? 0 : 0xff;
completition = (act_c->id_flags&1) ? 0 : 0xff;
/* here only SU = Manager */
/* not manager, then completition = 0xff */
}
@ -1091,8 +1357,8 @@ static void handle_fxx(int gelen, int func)
internal_act = 0;
}
if (result < 0) completition = (uint8) -result;
XDPRINTF((2,0, "Keyed Verify PW from OBJECT='%s', result=%d",
obj.name, result));
XDPRINTF((2,0, "Keyed Verify PW from OBJECT='%s', type=0x%x, result=%d",
obj.name, obj.type, result));
}
break;
@ -1113,14 +1379,14 @@ static void handle_fxx(int gelen, int func)
result=test_allow_password_change(obj.id);
if (!result)
result=nw_keychange_passwd(obj.id, act_c->crypt_key,
rdata, (int)*p, p+1, act_c->object_id);
rdata, (int)*p, p+1, act_c->id_flags);
if (!result) test_ins_unx_user(obj.id);
internal_act = 0;
}
if (result< 0) completition = (uint8) -result;
XDPRINTF((2, 0, "Keyed Change PW from OBJECT='%s', result=0x%x",
obj.name, result));
XDPRINTF((2, 0, "Keyed Change PW from OBJECT='%s', type=0x%x, result=0x%x",
obj.name, obj.type, result));
}
break;
@ -1153,7 +1419,7 @@ static void handle_fxx(int gelen, int func)
case 0x65 : { /* Destroy Queue */
uint32 q_id = GET_BE32(rdata);
int result=-0xd3; /* no rights */
if (1 == act_c->object_id)
if (act_c->id_flags&1)
result=nw_destroy_queue(q_id);
if (result < 0)
completition=(uint8)(-result);
@ -1198,6 +1464,20 @@ static void handle_fxx(int gelen, int func)
}
break;
case 0x67 : /* Set Queue Current Status,old */
case 0x7e : { /* Set Queue Current Status */
uint32 q_id = GET_BE32(rdata);
int status = *(rdata+4);
int result =
(act_c->id_flags&1) /* TODO BETTER */
? nw_set_queue_status(q_id, status)
: -0xd3; /* no rights */
if (result< 0)
completition=(uint8)-result;
/* NO REPLY */
}
break;
case 0x6A : /* Remove Job from Queue OLD */
case 0x80 : { /* Remove Job from Queue NEW */
uint32 q_id = GET_BE32(rdata);
@ -1241,13 +1521,15 @@ static void handle_fxx(int gelen, int func)
}
break;
case 0x6C : { /* Get Queue Job Entry old */
case 0x6C: /* Get Queue Job Entry old */
case 0x7A: { /* Read Queue Job Entry */
uint32 q_id = GET_BE32(rdata);
int job_id = GET_BE16(rdata+4);
/* added by nwconn */
uint32 fhandle = GET_BE32(rdata+8);
int result=nw_get_q_job_entry(q_id, job_id, fhandle,
responsedata, 1);
responsedata, ufunc==0x6c);
if (result > -1)
data_len=result;
else completition=(uint8)-result;
@ -1337,7 +1619,18 @@ static void handle_fxx(int gelen, int func)
}
break;
#if 1
case 0x7B: /* Change Queue Job Entry */
{
uint32 q_id = GET_BE32(rdata);
/* uint32 job_id = GET_BE16(rdata+4); */
int result = nw_change_queue_job_entry(q_id, rdata+4);
if (result < 0)
completition=(uint8)-result;
}
break;
#endif
case 0x7d : { /* Read Queue Current Status, new */
struct XDATA {
uint8 id[4]; /* queue id */
@ -1378,16 +1671,20 @@ static void handle_fxx(int gelen, int func)
} break;
case 0x81 : { /* Get Queue Job List */
NETOBJ obj;
uint32 q_id = GET_BE32(rdata);
uint32 offset = GET_BE32(rdata+4);
#if 0
struct XDATA {
uint8 total_jobs[4];
uint8 reply_numbers[4];
uint8 reply_numbers[4]; /* max. 125 replies */
uint8 job_list[4]; /* this is repeated */
} *xdata = (struct XDATA*) responsedata;
obj.id = GET_BE32(rdata);
XDPRINTF((2, 0, "TODO:GET QUEUE JOB List of Q=0x%lx", obj.id));
memset(xdata, 0, sizeof(struct XDATA));
data_len=sizeof(struct XDATA);
#endif
int result=nw_get_queue_job_list(q_id, offset, responsedata);
if (result > -1)
data_len=result;
else
completition=(uint8)-result;
}break;
case 0x72: /* finish servicing queue job (old)*/
@ -1421,12 +1718,12 @@ static void handle_fxx(int gelen, int func)
}
}break;
case 0xc8 : { /* CHECK CONSOLE PRIVILEGES */
XDPRINTF((1, 0, "TODO: CHECK CONSOLE PRIV"));
/* to use fileserver service functions */
XDPRINTF((1, 0, "MAKE BETTER: CHECK CONSOLE PRIV"));
/* !!!!!! TODO completition=0xc6 (no rights) */
if (act_c->object_id != 1) completition=0xc6; /* no rights */
if (!(act_c->id_flags&1))
completition=0xc6; /* no rights */
} break;
case 0xc9 : { /* GET FILE SERVER DESCRIPTION STRINGs */
@ -1438,15 +1735,8 @@ static void handle_fxx(int gelen, int func)
int l;
memset(responsedata, 0, 512);
strcpy(responsedata, company);
l = 1 + sprintf(responsedata+k, revision,
_VERS_H_, _VERS_L_, _VERS_P_ );
#if 0
k+=l;
#else
/* BUG in LIB */
k += (1 + strlen(responsedata+k));
#endif
strcpy(responsedata+k, revision_date);
k += (strlen(revision_date)+1);
strcpy(responsedata+k, copyright);
@ -1493,10 +1783,17 @@ static void handle_fxx(int gelen, int func)
break;
case 0xd3 : { /* down File Server */
if (act_c->object_id == 1) { /* only SUPERVISOR */
internal_act=1;
if (HAVE_SU_RIGHTS(act_c->object_id)) { /* only SUPERVISOR */
/* inform nwserv */
nwserv_down_server();
} else completition = 0xff;
} else {
/* 16-May-99
* correct completition code from Paolo Prandini
*/
completition = 0xc6; /* not authorized */
}
internal_act=0;
}
break;
@ -1508,9 +1805,14 @@ static void handle_fxx(int gelen, int func)
default : completition = 0xfb; /* not known here */
break;
} /* switch */
} else if (func == 0x18) { /* End of Job */
if (!(entry8_flags&0x200)) /* pcz: 14-Apr-00 */
nw_close_connection_jobs(act_connection, ncprequest->task); /* close print jobs */
} else if (func == 0x19) { /* logout */
nw_close_connection_jobs(act_connection, -1); /* close all print jobs */
write_utmp(0, act_connection, act_c->pid_nwconn, &(act_c->client_adr), NULL);
act_c->object_id = 0; /* not LOGIN */
act_c->id_flags = 0; /* no flags */
} else if (0x20 == func) { /* Semaphore */
int result = handle_func_0x20(act_c, rdata, ufunc, responsedata);
if (result > -1) data_len = result;
@ -1532,10 +1834,83 @@ static void handle_fxx(int gelen, int func)
send_ipx_data(ipx_out_fd, 17, data_len, (char*)ncpresponse,
&my_addr, NULL);
XDPRINTF((2, 0, "func=0x%x ufunc=0x%x compl:0x%x, written count = %d",
XDPRINTF((6, 0, "func=0x%x ufunc=0x%x compl:0x%x, written count = %d",
(int)func, (int)ufunc, (int) completition, data_len));
}
/* mst:25-Apr-00 */
static void send_request_to_nwconn(int connection, int function,
char *data, int data_len,
RESPONSE_FUNC func)
{
CONNECTION *c = &(connections[connection-1]);
if (c->active && c->send_to_sock > 0) {
IPX_DATA buf;
NCPREQUEST *req = (NCPREQUEST*)&buf;
U16_TO_BE16(0x2121, req->type);
delete_nwconn_request(c);
if (++c->last_used_sequence > 255)
c->last_used_sequence=1;
req->sequence = c->last_used_sequence;
req->task = 1;
req->connection = (connection & 0xff);
req->high_connection = ((connection >> 8) & 0xff);
req->function = function;
c->request_nwconn = (NWCONN_REQUEST*)xcmalloc(sizeof(NWCONN_REQUEST));
c->request_nwconn->sequence = req->sequence;
c->request_nwconn->function = function;
c->request_nwconn->sendtime = time(NULL);
c->request_nwconn->func = func;
if (data_len) {
memcpy(req+1, data, data_len);
c->request_nwconn->data = xmalloc(data_len);
memcpy(c->request_nwconn->data, data, data_len);
}
data_len+=sizeof(NCPREQUEST);
U16_TO_BE16(c->send_to_sock, my_addr.sock);
XDPRINTF((1, 0, "send_request_to_nwconn: connection=%d, data_len=%d",
connection, data_len));
send_ipx_data(ipx_out_fd, 17, data_len, (char*)req, &my_addr, NULL);
}
}
static void nwconn_callback(int connection,
char *data, int data_len,
int completition)
{
struct XDATA {
uint8 count_handles[4];
uint8 handles[4];
} *xdata = (struct XDATA*) data;
int open_files = GET_BE32(xdata->count_handles);
int handle0 = open_files < 1 ? 0 : GET_BE32(xdata->handles);
int handle1 = open_files < 2 ? 0 : GET_BE32(xdata->handles+4);
XDPRINTF((1, 0, "Got Response form con=%d, open_files=%d, handle0=%d, handle1=%d",
connection, open_files, handle0, handle1));
}
static void handle_usr2(void)
/* handles SIGUSR2, testfunction */
{
int k;
for (k=0; k < max_connections; k++) {
CONNECTION *c = &connections[k];
if (c->active) {
struct {
uint8 offset[4]; /* handle offset */
} data = { {0} };
send_request_to_nwconn(k+1, 0x1, (char*)&data, sizeof(data), nwconn_callback);
}
}
}
static void handle_bind_calls(uint8 *p)
{
int func = (int) *p;
@ -1673,6 +2048,7 @@ static void set_sig(void)
{
signal(SIGQUIT, sig_handler);
signal(SIGHUP, sig_handler);
signal(SIGUSR2, sig_handler);
signal(SIGTERM, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
@ -1681,18 +2057,16 @@ static void set_sig(void)
int main(int argc, char *argv[])
{
int sock_nwbind;
int i;
if (argc != 4) {
fprintf(stderr, "usage nwbind nwname address nwbindsock\n");
exit(1);
}
init_tools(NWBIND, 0);
strmaxcpy(my_nwname, argv[1], 47);
adr_to_ipx_addr(&my_addr, argv[2]);
sscanf(argv[3], "%x", &sock_nwbind);
internal_act = 1;
if (nw_init_dbm(my_nwname, &my_addr) <0) {
errorp(1, "nw_init_dbm", NULL);
@ -1708,7 +2082,6 @@ int main(int argc, char *argv[])
max_nw_vols=get_ini_int(61); /* max. volumes */
if (max_nw_vols < 1)
max_nw_vols = MAX_NW_VOLS;
#ifdef LINUX
set_emu_tli();
#endif
@ -1718,7 +2091,6 @@ int main(int argc, char *argv[])
#endif
XDPRINTF((1, 0, "USE_PERMANENT_OUT_SOCKET %s",
(ipx_out_fd > -1) ? "enabled" : "disabled"));
ud.opt.len = sizeof(ipx_pack_typ);
ud.opt.maxlen = sizeof(ipx_pack_typ);
ud.opt.buf = (char*)&ipx_pack_typ; /* gets actual Typ */
@ -1737,6 +2109,8 @@ int main(int argc, char *argv[])
if (t_rcvudata(ncp_fd, &ud, &rcv_flags) > -1){
time(&akttime);
XDPRINTF((10, 0, "NWBIND-LOOP from %s", visable_ipx_adr(&from_addr)));
act_ncpsequence = (int)ncprequest->sequence;
if ( ncprequest->type[0] == 0x22
&& ncprequest->type[1] == 0x22) {
act_connection = (int)ncprequest->connection
@ -1757,8 +2131,46 @@ int main(int argc, char *argv[])
visable_ipx_adr(&from_addr), act_connection));
}
} else {
XDPRINTF((1, 0, "NWBIND-LOOP connection=%d is wrong",
act_connection));
XDPRINTF((1, 0, "NWBIND-LOOP connection=%d,adr=%s is wrong",
act_connection,
visable_ipx_adr(&from_addr)
));
}
} else if ( ncprequest->type[0] == 0x32
&& ncprequest->type[1] == 0x32 ) {
/* response from nwconn */
act_connection = (int)ncprequest->connection
| (((int)ncprequest->high_connection) << 8);
if (act_connection > 0 && act_connection <= max_connections) {
act_c = &(connections[act_connection-1]);
internal_act = 0;
if (act_c->active && act_c->request_nwconn
&& act_c->request_nwconn->sequence == ncprequest->sequence
&& IPXCMPNODE (from_addr.node, my_addr.node)
&& IPXCMPNET (from_addr.net, my_addr.net)
&& GET_BE16 (from_addr.sock) == SOCK_NCP ) {
XDPRINTF((1, 0, "GOT 0x3232k OK connection=%d", act_connection));
if (act_c->request_nwconn->func) {
(*act_c->request_nwconn->func)(
act_connection,
((char*)&ipx_in_data) + sizeof(NCPRESPONSE),
ud.udata.len - sizeof(NCPRESPONSE),
(int) ((NCPRESPONSE*)ipx_in_data)->completition);
}
/* now delete request */
delete_nwconn_request(act_c);
} else {
XDPRINTF((1, 0, "NWBIND-LOOP 0x3232 wrong connection %d, active=%d, seq=%d from %s",
act_connection, act_c->active,
(int) ncprequest->sequence, visable_ipx_adr(&from_addr) ));
}
} else {
XDPRINTF((1, 0, "NWBIND-LOOP 0x3232 wrong connection %d from %s",
act_connection, visable_ipx_adr(&from_addr) ));
}
} else if ( ncprequest->type[0] == 0xee
&& ncprequest->type[1] == 0xee
@ -1776,13 +2188,16 @@ int main(int argc, char *argv[])
/* here I update some Bindery stuff from nwserv.conf */
reinit_nwbind();
got_sig = 0;
} else if (got_sig == SIGUSR2) {
handle_usr2(); /* mst:25-Apr-00 */
got_sig = 0;
}
}
/* perhaps some connections need clearing (utmp), hint from Ambrose Li */
got_sig=max_connections+1;
while (--got_sig)
open_clear_connection(got_sig, 0, NULL);
i=max_connections+1;
while (--i)
open_clear_connection(i, 0, NULL);
if (ncp_fd > -1) {
t_unbind(ncp_fd);

View File

@ -1,9 +1,9 @@
/* nwbind.h 07-Aug-97 */
/* nwbind.h 23-Apr-98 */
#ifndef _NWBIND_H_
#define _NWBIND_H_
#define MAX_SEMA_CONN 10 /* 10 Semaphore pre connection */
#define MAX_SEMA_CONN 10 /* 10 Semaphore / connection */
typedef struct {
@ -11,16 +11,37 @@ typedef struct {
int opencount; /* times open */
} SEMA_CONN;
typedef void (*RESPONSE_FUNC)(int connection,
char *data,
int data_len,
int completition);
typedef struct {
int sequence;
int function;
time_t sendtime;
char *data;
int data_len;
RESPONSE_FUNC func;
} NWCONN_REQUEST;
typedef struct {
ipxAddr_t client_adr; /* address remote client */
uint32 object_id; /* logged object */
/* 0 = not logged in */
int id_flags; /* &1 == supervisor (equivalence) */
/* flags are also availible in */
/* connection based routines */
uint8 crypt_key[8]; /* password generation */
time_t t_login; /* login time */
uint8 message[60]; /* saved BCastmessage */
int active; /* 0=closed, 1= active */
int send_to_sock; /* this is the receiving sock */
int pid_nwconn; /* pid of user process nwconn */
NWCONN_REQUEST *request_nwconn; /* last request to nwconn */
int last_used_sequence;
int count_semas; /* open semahores */
SEMA_CONN semas[MAX_SEMA_CONN];
} CONNECTION;

830
nwconn.c

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
/* nwconn.h 19-Nov-97 */
/* nwconn.h 13-May-98 */
#ifndef _NWCONN_H_
#define _NWCONN_H_
extern int act_connection;
extern int act_pid;
extern void nwconn_set_program_title(char *s);
#endif

1051
nwdbm.c

File diff suppressed because it is too large Load Diff

77
nwdbm.h
View File

@ -1,5 +1,5 @@
/* nwdbm.h 01-Oct-97 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
/* nwdbm.h 25-Apr-00 */
/* (C)opyright (C) 1993,2000 Martin Stover, Marburg, Germany
*
* 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
@ -78,12 +78,71 @@ extern uint8 *sys_sysname; /* Name of first Volume, normally SYS */
extern uint32 network_serial_nmbr;
extern uint16 network_appl_nmbr;
extern int entry8_flags;
#define PW_SCHEME_CHANGE_PW 1
#define PW_SCHEME_LOGIN 2
#define PW_SCHEME_GET_KEY_FAIL 4
#define PW_SCHEME_ALLOW_EMPTY_PW 8
/*
** LOGIN_CONTROL structure is an 86 byte structure that contains
** account password information
** Paolo Prandini <prandini@spe.it> mst:25-Apr-00
**
*/
typedef struct {
uint8 accountExpiresYear;
uint8 accountExpiresMonth;
uint8 accountExpiresDay;
uint8 accountExpired;
uint8 passwordExpiresYear;
uint8 passwordExpiresMonth;
uint8 passwordExpiresDay;
uint8 passwordGraceLogins;
uint8 expirationInterval[2]; /* hi-lo */
uint8 graceReset;
uint8 minimumPasswordLength;
uint8 maxConcurrentConnections[2]; /* hi-lo */
uint8 timeBitMap[42];
uint8 lastLoginDate[6];
uint8 restrictionFlags; // bit 0=1 disallow pwd change,
// bit 1=1 require unique pwd
uint8 filler;
uint8 maxDiskBlocks[4]; /* hi-lo */
uint8 badLoginCount[2]; /* hi-lo */
uint8 nextResetTime[4]; /* hi-lo */
uint8 badStationAddress[12];
} LOGIN_CONTROL;
/*
** USER_DEFAULTS structure is a structure that contains
** default account password information
*/
typedef struct {
uint8 accountExpiresYear;
uint8 accountExpiresMonth;
uint8 accountExpiresDay;
uint8 restrictionFlags;
uint8 expirationInterval[2]; /* hi-lo */
uint8 graceReset;
uint8 minimumPasswordLength;
uint8 maxConcurrentConnections[2]; /* hi-lo */
uint8 timeBitMap[42];
uint8 balance[4]; /* ?? */
uint8 creditLimit[4]; /* ?? */
uint8 maxDiskBlocks[4]; /* hi-lo */
uint8 createHomeDir;
} USER_DEFAULTS;
/* next routine is in nwbind.c !!!! */
extern int b_acc(uint32 obj_id, int security, int forwrite);
@ -135,7 +194,6 @@ extern int nw_is_obj_in_set(int object_type,
int member_type,
uint8 *member_name, int member_namlen);
extern int nw_add_obj_to_set(int object_type,
uint8 *object_name, int object_namlen,
uint8 *prop_name, int prop_namlen,
@ -183,14 +241,20 @@ extern int nw_create_prop(int object_type,
uint8 *prop_name, int prop_namlen,
int prop_flags, int prop_security);
extern uint32 nw_new_obj_prop(uint32 wanted_id,
char *objname, int objtype, int objflags, int objsecurity,
char *propname, int propflags, int propsecurity,
char *value, int valuesize, int ever);
extern int nw_is_security_equal(uint32 id1, uint32 id2);
#define HAVE_SU_RIGHTS(id) ( ((id)==1L) || !nw_is_security_equal(1L, (id)))
extern int get_groups_i_m_in(uint32 id, uint32 *gids);
extern int get_guid(int *gid, int *uid, uint32 obj_id, uint8 *name);
extern int get_home_dir(uint8 *homedir, uint32 obj_id);
/* mst:25-Apr-00 */
extern int nw_get_login_control(uint32 obj_id, LOGIN_CONTROL *plc);
extern int nw_set_login_control(uint32 obj_id, LOGIN_CONTROL *plc);
extern int nw_test_passwd(uint32 obj_id, uint8 *vgl_key, uint8 *akt_key);
extern int nw_test_unenpasswd(uint32 obj_id, uint8 *password);
@ -199,7 +263,7 @@ extern int nw_set_passwd(uint32 obj_id, char *password, int dont_ch);
extern int nw_keychange_passwd(uint32 obj_id,
uint8 *cryptkey, uint8 *oldpass,
int cryptedlen, uint8 *newpass,
uint32 act_id);
int id_flags);
extern int nw_test_adr_time_access(uint32 obj_id, ipxAddr_t *client_adr);
@ -215,6 +279,7 @@ extern void nw_exit_dbm(void);
extern int do_export_dbm(char *path);
extern int do_import_dbm(char *path);
extern int do_export_dbm_to_dir(void);
#endif

919
nwfile.c

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* nwfile.h 09-Feb-98 */
/* nwfile.h 10-Nov-99 */
#ifndef _NWFILE_H_
#define _NWFILE_H_
#include "extpipe.h"
@ -18,6 +18,9 @@ typedef struct {
int st_dev; /* device */
int st_ino; /* inode */
char fname[256]; /* UNIX filename */
int volume; /* Volume */
int inuse; /* used for multiple open of filehandle */
int access; /* open access */
} FILE_HANDLE;
/* fh_flags */
@ -38,7 +41,7 @@ extern int file_creat_open(int volume, uint8 *unixname,
extern int nw_set_fdate_time(uint32 fhandle, uint8 *datum, uint8 *zeit);
extern int nw_close_file(int fhandle, int reset_reuse);
extern int nw_close_file(int fhandle, int reset_reuse, int task);
extern int nw_commit_file(int fhandle);
extern uint8 *file_get_unix_name(int fhandle);
@ -50,12 +53,17 @@ extern int nw_server_copy(int qfhandle, uint32 qoffset,
int zfhandle, uint32 zoffset,
uint32 size);
extern int nw_lock_file(int fhandle, uint32 offset, uint32 size, int do_lock);
extern int nw_log_physical_record(int fhandle, uint32 offset, uint32 size, int do_lock);
extern int fd_2_fname(int fhandle, char *buf, int bufsize);
extern FILE_HANDLE *fd_2_fh(int fhandle);
extern int get_nwfd(int fhandle);
extern void log_file_module(FILE *f);
extern int nw_get_count_open_files(uint8 *handlebuf, uint32 offset);
extern int nw_unlink(int volume, char *name);
extern int nw_log_logical_record(int lock_flag,
int timeout,
int len,
uint8 *data);
#endif

View File

@ -1,4 +1,4 @@
/* nwqconn.c 24-Sep-97 */
/* nwqconn.c 15-Sep-99 */
/* (C)opyright (C) 1997 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -24,16 +24,23 @@
#include "connect.h"
#include "nwqconn.h"
/*
* the connection based queue stuff is in this module.
* The running process is nwconn.
* the bindery/global queue handling is in nwqueue.c.
*/
typedef struct S_INT_QUEUE_JOB {
uint32 queue_id;
int job_id;
int fhandle;
int task;
struct S_INT_QUEUE_JOB *next;
} INT_QUEUE_JOB;
INT_QUEUE_JOB *queue_jobs=NULL;
static INT_QUEUE_JOB *new_queue_job(uint32 queue_id, int job_id)
static INT_QUEUE_JOB *new_queue_job(uint32 queue_id, int job_id, int task)
{
INT_QUEUE_JOB *p=(INT_QUEUE_JOB*)xcmalloc(sizeof(INT_QUEUE_JOB));
if (!queue_jobs) {
@ -46,6 +53,7 @@ static INT_QUEUE_JOB *new_queue_job(uint32 queue_id, int job_id)
p->next=NULL;
p->queue_id=queue_id;
p->job_id=job_id;
p->task=task;
return(p);
}
@ -90,11 +98,13 @@ static int open_creat_queue_file(int mode, uint8
*/
{
int result;
result=nw_alloc_dir_handle(0, dirname, dirname_len, 99, 2, 1);
int eff_rights;
result=nw_alloc_dir_handle(0, dirname, dirname_len, 99, 2, 1, &eff_rights);
if (result > -1) {
char unixname[300];
result=conn_get_kpl_unxname(unixname, result, file_name, file_name_len);
int dirhandle=result;
result=conn_get_kpl_unxname(unixname, sizeof(unixname),
dirhandle, file_name, file_name_len);
if (result > -1) {
struct stat stbuff;
if (mode == 0) { /* creat */
@ -104,12 +114,14 @@ static int open_creat_queue_file(int mode, uint8
chmod(unixname, 0600);
} else if (mode == 1) { /* open ro */
result=file_creat_open(result, (uint8*)unixname,
&stbuff, 0x6, 0x9, 4|8, 0);
&stbuff, 0x6, 0x9, 8, 0);
/* ...............^^^...not &4 !... */
} else if (mode == 2) { /* open rw */
result=file_creat_open(result, (uint8*)unixname,
&stbuff, 0x6, 0x6, 4|8, 0);
} else result=-1;
}
nw_free_dir_handle(dirhandle, 1);
}
if (result < 0) {
uint8 dn[300];
@ -123,7 +135,8 @@ static int open_creat_queue_file(int mode, uint8
return(result);
}
int creat_queue_job(uint32 q_id,
int creat_queue_job(int task,
uint32 q_id,
uint8 *queue_job,
uint8 *responsedata,
uint8 old_call)
@ -138,7 +151,7 @@ int creat_queue_job(uint32 q_id,
if (old_call) {
QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; /* before 3.11 */
job_id = GET_BE16(job->job_id);
jo = new_queue_job(q_id, job_id);
jo = new_queue_job(q_id, job_id, task);
result = open_creat_queue_file(0, job->job_file_name+1, *(job->job_file_name),
dirname+1, *dirname);
if (result > -1) {
@ -150,7 +163,7 @@ int creat_queue_job(uint32 q_id,
} else {
QUEUE_JOB *job=(QUEUE_JOB*)responsedata;
job_id=GET_BE16(job->job_id);
jo = new_queue_job(q_id, job_id);
jo = new_queue_job(q_id, job_id, task);
result = open_creat_queue_file(0, job->job_file_name+1, *(job->job_file_name),
dirname+1, *dirname);
if (result > -1) {
@ -172,10 +185,10 @@ int close_queue_job(uint32 q_id, int job_id)
int result = -0xff;
INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id);
if (jo) {
nw_close_file(jo->fhandle, 0);
nw_close_file(jo->fhandle, 0, jo->task);
result=0;
}
XDPRINTF((5,0,"close_queue_job Q=0x%x, job=%d, result=%d",
XDPRINTF(( (result<0) ? 1 :5 ,0,"close_queue_job Q=0x%x, job=%d, result=%d",
q_id, job_id, result));
return(result);
}
@ -186,7 +199,6 @@ int close_queue_job2(uint32 q_id, int job_id,
{
int result = -0xff;
INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id);
XDPRINTF((5,0,"close_queue_job2, Q=0x%x, job=%d", q_id, job_id));
if (jo) {
if (prc_len) {
char unixname[300];
@ -205,7 +217,7 @@ int close_queue_job2(uint32 q_id, int job_id,
qpa.banner_user_name, qpa.banner_file_name);
} else
strmaxcpy((uint8*)printcommand, prc, prc_len);
nw_close_file(jo->fhandle, 1);
nw_close_file(jo->fhandle, 1, jo->task);
jo->fhandle = 0L;
if (NULL == (f = fopen(unixname, "r"))) {
/* OK now we try the open as root */
@ -215,7 +227,7 @@ int close_queue_job2(uint32 q_id, int job_id,
}
if (NULL != f) {
int is_ok = 0;
FILE_PIPE *fp = ext_popen(printcommand, geteuid(), getegid());
FILE_PIPE *fp = ext_popen(printcommand, geteuid(), getegid(), 1);
if (fp) {
int k;
is_ok++;
@ -244,14 +256,16 @@ int close_queue_job2(uint32 q_id, int job_id,
}
} else {
result=0;
nw_close_file(jo->fhandle, 1);
nw_close_file(jo->fhandle, 1, jo->task);
}
free_queue_job(q_id, job_id);
}
XDPRINTF(((result<0)?1:5,0,"close_queue_job2, Q=0x%x, job=%d", q_id, job_id));
return(result);
}
int service_queue_job(uint32 q_id,
int service_queue_job(int task,
uint32 q_id,
uint8 *queue_job,
uint8 *responsedata,
uint8 old_call)
@ -266,7 +280,7 @@ int service_queue_job(uint32 q_id,
if (old_call) {
QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; /* before 3.11 */
job_id = GET_BE16(job->job_id);
jo = new_queue_job(q_id, job_id);
jo = new_queue_job(q_id, job_id,task);
result = open_creat_queue_file(1,
job->job_file_name+1, *(job->job_file_name),
dirname+1, *dirname);
@ -279,7 +293,7 @@ int service_queue_job(uint32 q_id,
} else {
QUEUE_JOB *job=(QUEUE_JOB*)responsedata;
job_id = GET_BE16(job->job_id);
jo = new_queue_job(q_id, job_id);
jo = new_queue_job(q_id, job_id,task);
result = open_creat_queue_file(1,
job->job_file_name+1, *(job->job_file_name),
dirname+1, *dirname);
@ -300,7 +314,7 @@ int finish_abort_queue_job(uint32 q_id, int job_id)
int result = -0xff;
INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id);
if (jo) {
nw_close_file(jo->fhandle, 0);
nw_close_file(jo->fhandle, 0, jo->task);
free_queue_job(q_id, job_id);
result=0;
}
@ -328,3 +342,30 @@ void free_queue_jobs(void)
queue_jobs=NULL;
}
static int loc_free_connection_task_jobs(int task)
{
INT_QUEUE_JOB *qj=queue_jobs;
if (!qj) return(0);
if (qj->task==task){
queue_jobs=qj->next;
nw_close_file(qj->fhandle, 1, task);
xfree(qj);
return(1);
}
while (qj->next) {
if (qj->next->task == task) {
INT_QUEUE_JOB *tmp=qj->next;
qj->next=tmp->next;
nw_close_file(tmp->fhandle, 1, task);
xfree(tmp);
return(1);
} else qj=qj->next;
}
return(0); /* not found */
}
void free_connection_task_jobs(int task)
{
while(loc_free_connection_task_jobs(task)) ;;
}

View File

@ -1,8 +1,9 @@
/* nwqconn.h 26-Aug-97 */
/* nwqconn.h 14-Apr-98 */
#ifndef _NWQCONN_H_
#define _NWQCONN_H_
#include "queuedef.h"
extern int creat_queue_job(uint32 q_id,
extern int creat_queue_job(int task,
uint32 q_id,
uint8 *queue_job,
uint8 *responsedata,
uint8 old_call);
@ -12,7 +13,8 @@ extern int close_queue_job2(uint32 q_id, int job_id,
uint8 *client_area,
uint8 *prc, int prc_len);
extern int service_queue_job(uint32 q_id,
extern int service_queue_job(int task,
uint32 q_id,
uint8 *queue_job,
uint8 *responsedata,
uint8 old_call);
@ -21,4 +23,6 @@ extern int finish_abort_queue_job(uint32 q_id, int job_id);
extern uint32 get_queue_job_fhandle(uint32 q_id, int job_id);
extern void free_queue_jobs(void);
extern void free_connection_task_jobs(int task);
#endif

153
nwqueue.c
View File

@ -1,4 +1,4 @@
/* nwqueue.c 08-Oct-97 */
/* nwqueue.c 04-Jun-98 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -42,8 +42,8 @@ typedef struct S_INT_QUEUE_JOB {
int server_task;
uint32 server_id;
uint8 job_description[50];
uint8 client_area[152];
time_t file_entry_time; /* for filenamehandling */
uint8 client_area[152]; /* must be int aligned */
struct S_INT_QUEUE_JOB *next;
} INT_QUEUE_JOB;
@ -73,6 +73,8 @@ typedef struct S_NWE_QUEUE {
NWE_QUEUE *nwe_queues=NULL;
static int entry18_flags;
static NWE_QUEUE *new_queue(uint32 id)
{
NWE_QUEUE *p=(NWE_QUEUE*)xcmalloc(sizeof(NWE_QUEUE));
@ -132,7 +134,7 @@ static INT_QUEUE_JOB *add_queue_job(NWE_QUEUE *que, INT_QUEUE_JOB *p)
if (!que->queue_jobs) {
que->queue_jobs=p;
p->job_position=1;
que->last_job_id=1;
if (++(que->last_job_id)>999) que->last_job_id=1;
} else {
int flag;
INT_QUEUE_JOB *qj;
@ -251,8 +253,11 @@ static void r_w_queue_jobs(NWE_QUEUE *q, int mode)
qj->server_station=0;
qj->server_id=0;
qj->job_control_flags &= ~0x20;
add_queue_job(q, qj);
qj=(INT_QUEUE_JOB*)xmalloc(sizeof(INT_QUEUE_JOB));
}
xfree(qj);
}
@ -371,6 +376,10 @@ static int fill_q_job_entry(INT_QUEUE_JOB *jo,
{
memset(job->record_in_use, 0xff, 2);
memset(job->record_previous, 0, 4);
if (jo->next) { /* (Alexey) we _must_ set id of next job in job-list */
U32_TO_32(jo->next->job_id, job->record_next);
} else
memset(job->record_next, 0, 4);
U32_TO_32(jo->client_connection, job->client_connection);
@ -452,12 +461,17 @@ int nw_creat_queue_job(int connection, int task, uint32 object_id,
int nw_close_queue_job(uint32 q_id, int job_id,
uint8 *responsedata)
{
int result=-0xd8; /* queue not active */
NWE_QUEUE *que=find_queue(q_id);
if (que) {
INT_QUEUE_JOB *jo=find_queue_job(que, job_id);
if (jo) {
int result=sizeof(jo->client_area);
int i;
QUEUE_PRINT_AREA *qpa=(QUEUE_PRINT_AREA*)jo->client_area;
result=sizeof(jo->client_area);
if (entry18_flags&0x1) { /* always suppress banner */
qpa->print_flags[1] &= ~0x80;
}
jo->job_control_flags &= ~0x20;
memcpy(responsedata, jo->client_area, result);
i = nw_get_q_prcommand(q_id, responsedata+result+1);
@ -468,11 +482,12 @@ int nw_close_queue_job(uint32 q_id, int job_id,
} else
*(responsedata+result)=0;
++result;
} else
result=-0xff;
}
XDPRINTF(((result<0) ? 1 : 5, 0, "nw_close_queue_job, q=%lx, job=%d, result=%d",
q_id, job_id, result));
return(result);
}
return(-0xff);
}
return(-0xd8); /* queue not active */
}
int nw_get_queue_status(uint32 q_id, int *status, int *entries,
@ -493,6 +508,16 @@ int nw_get_queue_status(uint32 q_id, int *status, int *entries,
return(-0xff);
}
int nw_set_queue_status(uint32 q_id, int status)
{
NWE_QUEUE *q=find_queue(q_id);
if (q) {
q->status=status;
return(0);
}
return(-0xd3); /* no rights */
}
int nw_get_q_job_entry(uint32 q_id, int job_id, uint32 fhandle,
uint8 *responsedata, int old_call)
{
@ -534,22 +559,71 @@ int nw_get_queue_job_list_old(uint32 q_id, uint8 *responsedata)
return(result);
}
int nw_get_queue_job_file_size(uint32 q_id, int job_id)
int nw_get_queue_job_list(uint32 q_id, uint32 offset, uint8 *responsedata)
{
int result=-0xd5;
int result = -0xff;
NWE_QUEUE *q = find_queue(q_id);
INT_QUEUE_JOB *qj = find_queue_job(q, job_id);
if (qj) {
if (q) {
INT_QUEUE_JOB *qj=q->queue_jobs;
uint8 *p=responsedata+8;
int fullcount=0;
int count=0;
if (offset == MAX_U32)
offset = 0;
while (qj) {
if (++fullcount > offset && count < 125) { /* max. 125 entries */
++count;
U16_TO_BE16(qj->job_id, p);
p+=2;
*p++=0;
*p++=0;
}
qj=qj->next;
}
#if 0
U32_TO_BE32(fullcount, responsedata);
U32_TO_BE32(count, responsedata+4);
#else
/* georg@globaltrading.net */
U32_TO_32(fullcount, responsedata);
U32_TO_32(count, responsedata+4);
#endif
result=8+count*4;
}
return(result);
}
static int get_qj_file_size(NWE_QUEUE *q, INT_QUEUE_JOB *qj)
{
if (q && qj) {
struct stat stb;
uint8 buf[300];
build_unix_queue_file(buf, q, qj);
if (!stat(buf, &stb))
return(stb.st_size);
return(0);
}
return(0);
}
int nw_get_queue_job_file_size(uint32 q_id, int job_id)
{
int result=-0xd5;
NWE_QUEUE *q = find_queue(q_id);
INT_QUEUE_JOB *qj = find_queue_job(q, job_id);
if (qj)
return(get_qj_file_size(q, qj));
return(result);
}
int nw_change_queue_job_entry(uint32 q_id, uint8 *qjstruct)
{
/* TODO */
return(-0xfb);
}
static int remove_queue_job_file(NWE_QUEUE *q, INT_QUEUE_JOB *qj)
{
struct stat stb;
@ -582,6 +656,35 @@ int nw_remove_job_from_queue(uint32 user_id, uint32 q_id, int job_id)
return(result);
}
void nw_close_connection_jobs(int connection, int task)
/*
* this routine closes pending client open queue jobs
* if (task == -1) all jobs of connection are affected
*/
{
NWE_QUEUE *q=(NWE_QUEUE*)nwe_queues;
while (q) {
INT_QUEUE_JOB *qj=q->queue_jobs;
while(qj) {
if (qj->client_connection == connection
&& (qj->client_task == task || task == -1)
&& (qj->job_control_flags & 0x20) ) { /* actual queued */
if (get_qj_file_size(q, qj) > 0) { /* we mark it as not queued */
qj->job_control_flags &= ~0x20;
} else { /* we remove it */
XDPRINTF((1, 0, "Queue job removed by nw_close_connection_jobs, conn=%d, task=%d", connection, task));
(void)remove_queue_job_file(q, qj);
free_queue_job(q, qj->job_id);
}
qj=q->queue_jobs;
continue;
}
qj=qj->next;
}
q=q->next;
}
}
/* ------------------ for queue servers ------------------- */
static QUEUE_SERVER *new_qserver(uint32 user_id, int connection)
{
@ -618,6 +721,8 @@ int nw_attach_server_to_queue(uint32 user_id,
/* we only allow 1 qserver/queue in this version */
}
}
XDPRINTF((2, 0, "attach TO QUEUE q_id=0x%x, user=0x%x, conn=%d, result=0x%x",
q_id, user_id, connection, result));
return(result);
}
@ -647,6 +752,7 @@ int nw_service_queue_job(uint32 user_id, int connection, int task,
if (q && q->qserver
&& q->qserver->user_id == user_id
&& q->qserver->connection == connection) {
if ( !(q->status & 4) ) { /* not stopped printing */
uint8 *fulldirname = (old_call) ? responsedata+sizeof(QUEUE_JOB_OLD)
: responsedata+sizeof(QUEUE_JOB);
int len = nw_get_q_dirname(q_id, fulldirname+1);
@ -664,9 +770,18 @@ int nw_service_queue_job(uint32 user_id, int connection, int task,
&& (qj->target_id == MAX_U32 || qj->target_id == user_id)
&& (qj->job_typ == MAX_U16 || job_typ==MAX_U16
|| qj->job_typ == job_typ)) {
if (get_qj_file_size(q, qj) > 0) {
fqj=qj;
break;
} else {
if (time(NULL) - qj->entry_time > 60) { /* ca. 1 min */
XDPRINTF((1, 0, "Queue job of size 0 automaticly removed"));
(void)remove_queue_job_file(q, qj);
free_queue_job(q, qj->job_id);
qj=q->queue_jobs;
continue;
}
}
} else {
XDPRINTF((6, 0, "Queue job ignored: station=%d, target_id=0x%x,job_typ=0x%x, %s",
qj->server_station, qj->target_id, qj->job_typ,
@ -694,6 +809,7 @@ int nw_service_queue_job(uint32 user_id, int connection, int task,
} else {
XDPRINTF((1, 0, "Could not get queuedir of q_id=0x%x", q_id));
}
} /* if */
} else {
XDPRINTF((1, 0, "Could not find qserver q_id=0x%x, user_id=0x%x, connect=%d",
q_id, user_id, connection));
@ -795,7 +911,7 @@ int nw_creat_queue(int q_typ, uint8 *q_name, int q_name_len,
*path=0;
upstr(q_directory);
} else {
strcpy(q_directory, "SYS:SYSTEM");
xstrcpy(q_directory, "SYS:SYSTEM");
path_len=10;
path=q_directory+path_len;
}
@ -868,18 +984,19 @@ int nw_destroy_queue(uint32 q_id)
}
void init_queues(void)
void init_queues(int entry18_flags_p)
{
NETOBJ obj;
uint8 buf[300];
int result;
uint8 *wild="*";
uint32 last_obj_id=MAX_U32;
entry18_flags=entry18_flags_p;
exit_queues();
strmaxcpy(buf, sys_unixname, sys_unixnamlen);
XDPRINTF((3,0, "init_queues:unixname='%s'", buf));
obj.type = 3; /* queue */
strcpy(obj.name, wild);
xstrcpy(obj.name, wild);
result = scan_for_obj(&obj, last_obj_id, 1);
while (!result) {
@ -898,7 +1015,7 @@ void init_queues(void)
r_w_queue_jobs(que, 0);
}
last_obj_id=obj.id;
strcpy(obj.name, wild);
xstrcpy(obj.name, wild);
result = scan_for_obj(&obj, last_obj_id, 1);
}
}

View File

@ -1,4 +1,4 @@
/* nwqueue.h 08-Oct-97 */
/* nwqueue.h 14-Apr-98 */
#ifndef _NWQUEUE_H_
#define _NWQUEUE_H_
#include "queuedef.h"
@ -15,13 +15,20 @@ extern int nw_close_queue_job(uint32 q_id, int job_id,
extern int nw_get_queue_status(uint32 q_id, int *status, int *entries,
int *servers, int server_ids[], int server_conns[]);
extern int nw_set_queue_status(uint32 q_id, int status);
extern int nw_get_q_job_entry(uint32 q_id, int job_id, uint32 fhandle,
uint8 *responsedata, int old_call);
extern int nw_get_queue_job_list_old(uint32 q_id, uint8 *responsedata);
extern int nw_get_queue_job_list(uint32 q_id, uint32 offset, uint8 *responsedata);
extern int nw_get_queue_job_file_size(uint32 q_id, int job_id);
extern int nw_change_queue_job_entry(uint32 q_id, uint8 *qjstruct);
extern int nw_remove_job_from_queue(uint32 user_id, uint32 q_id, int job_id);
extern void nw_close_connection_jobs(int connection, int task);
/* ------------------ for queue servers ------------------- */
extern int nw_attach_server_to_queue(uint32 user_id,
int connection,
@ -44,5 +51,5 @@ extern int nw_creat_queue(int q_typ, uint8 *q_name, int q_name_len,
extern int nw_destroy_queue(uint32 q_id);
extern void exit_queues(void);
extern void init_queues(void);
extern void init_queues(int entry18_flags_p);
#endif

View File

@ -1,5 +1,5 @@
/* nwroute.c 08-Feb-98 */
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
/* nwroute.c 18-Apr-00 */
/* (C)opyright (C) 1993,2000 Martin Stover, Marburg, Germany
*
* 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
@ -50,7 +50,7 @@ static NW_SERVERS **nw_servers=NULL;
#define NEEDS_UPDATE_RIP_NET 8
#define NEEDS_UPDATE_ALL (8|4|2|1)
static void insert_delete_net(uint32 destnet,
static void insert_delete_net(uint32 destnet, /* destination net */
uint32 rnet, /* routernet */
uint8 *rnode, /* routernode */
uint16 hops,
@ -77,7 +77,8 @@ static void insert_delete_net(uint32 destnet,
if (!do_delete) return; /* don't alter device */
nd_dev = nd;
}
if (nd->net == rnet) ndticks=nd->ticks;
if (nd->net == rnet)
ndticks=nd->ticks;
}
}
if (!do_delete && nd_dev && nd_dev->ticks <= ndticks) return;
@ -94,7 +95,7 @@ static void insert_delete_net(uint32 destnet,
int new_max_nw = max_nw_routes+5;
NW_ROUTES **new_nwr
=(NW_ROUTES**)xcmalloc(new_max_nw*sizeof(NW_ROUTES*));
if (max_nw_servers)
if (max_nw_routes)
memcpy(new_nwr, nw_routes, max_nw_routes*sizeof(NW_ROUTES*));
xfree(nw_routes);
nw_routes=new_nwr;
@ -109,14 +110,13 @@ static void insert_delete_net(uint32 destnet,
nr->ticks = 0xffff;
nr->hops = 0xffff;
} else if (do_delete) {
nr=nw_routes[k];
if (nr->rnet == rnet && IPXCMPNODE(nr->rnode, rnode) ) {
/* only delete the routes, which we have inserted */
XDPRINTF((2,0,"ROUTE DEL NET=0x%x over Router NET 0x%x",
nr->net, rnet));
ipx_route_del(nr->net);
ipx_route_del(nr->net);
if (nd_dev != NULL) { /* this is net to our device */
/* I must delete and setup new, because there is */
/* no direct way to delete this route from interface :( */
@ -135,7 +135,7 @@ static void insert_delete_net(uint32 destnet,
ticks+=ndticks;
if (ticks <= nr->ticks) {
if (ticks == nr->ticks && hops >= nr->hops) return;
if (ticks == nr->ticks && hops > nr->hops) return;
nr->hops = hops;
nr->ticks = ticks;
nr->rnet = rnet;
@ -607,6 +607,10 @@ static FILE *open_route_info_fn(int force, FILE *ff, int section)
} else {
fn=pr_route_info_fn;
}
if (is_filelink(fn)) /* security, mst:18-Apr-00 */
unlink(fn);
f=fopen(fn, (print_route_mode&0x1) ? "w" : "a");
if (section == 1) {
if (NULL != f)
@ -701,10 +705,11 @@ static int look_for_interfaces(void);
void send_sap_rip_broadcast(int mode)
/* mode=0, standard broadcast */
/* mode=1, first trie */
/* mode=2, shutdown */
/* mode=2, sap shutdown */
/* mode=3, update routes */
/* mode=4, resend to net */
/* mode=5, force update routes */
/* mode=22, rip shutdown */
{
static int flipflop=1;
int force_print_routes=(mode == 1) ? 1 : 0;
@ -720,16 +725,20 @@ static int flipflop=1;
send_rip_broadcast(1);
send_sap_broadcast(1);
}
} else if (mode == 22) {
send_rip_broadcast(2);
} else if (mode == 2) {
send_sap_broadcast(2);
} else {
send_rip_broadcast(mode);
send_sap_broadcast(mode);
}
} else {
if (flipflop) {
send_rip_broadcast(mode);
send_rip_broadcast(0);
flipflop=0;
} else {
send_sap_broadcast(mode);
send_sap_broadcast(0);
flipflop=1;
}
}
@ -948,8 +957,8 @@ static int look_for_interfaces(void)
for (j=0; j < anz_routes; j++){
NW_ROUTES *nr=nw_routes[j];
if (nr && nr->rnet == nd->net) {
XDPRINTF((1,0,"Route to net=0x%x removed", nr->net)); /* !! */
nr->net = 0L; /* remove route */
XDPRINTF((1,0,"Route to net=0x%x removed", nr->net));
}
}
if (nd->wildmask & 1)

View File

@ -123,8 +123,8 @@ void get_servers(void)
SQP sqp;
ipxAddr_t wild;
memset(&wild, 0, sizeof(ipxAddr_t));
#ifdef xxxLINUX
U32_TO_BE32(internal_net, wild.net);
#ifdef FREEBSD
U32_TO_BE32(internal_net, wild.net); /* ask ONLY IPXrouted */
memcpy(wild.node, my_server_adr.node, IPX_NODE_SIZE);
#else
memset(wild.node, 0xFF, IPX_NODE_SIZE);
@ -150,11 +150,9 @@ void send_sap_rip_broadcast(int mode)
IPX_DATA ipx_data;
ipxAddr_t wild;
memset(&wild, 0, sizeof(ipxAddr_t));
#ifdef xxxLINUX
U32_TO_BE32(internal_net, wild.net);
memcpy(wild.node, my_server_adr.node, IPX_NODE_SIZE);
#else
memset(wild.node, 0xFF, IPX_NODE_SIZE);
memset(wild.node, 0xFF, IPX_NODE_SIZE); /* broadcast */
#ifdef FREEBSD
U32_TO_BE32(internal_net, wild.net); /* there is no default net */
#endif
U16_TO_BE16(SOCK_SAP, wild.sock);
memset(&ipx_data, 0, sizeof(ipx_data.sip));
@ -169,6 +167,16 @@ void send_sap_rip_broadcast(int mode)
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
&wild, "SIP Broadcast");
#ifdef FREEBSD
U32_TO_BE32(internal_net, wild.net);
memcpy(wild.node, my_server_adr.node, IPX_NODE_SIZE);
/* tell to IPXrouted for single server case */
send_ipx_data(sockfd[SAP_SLOT],
4, /* this is the official packet typ for SAP's */
sizeof(ipx_data.sip),
(char *)&(ipx_data.sip),
&wild, "SIP Broadcast");
#endif
if (!mode) get_servers();
if (mode == 1) {
U16_TO_BE16(SOCK_SAP, wild.sock);

140
nwserv.c
View File

@ -1,4 +1,4 @@
/* nwserv.c 08-Feb-98 */
/* nwserv.c 19-May-98 */
/* MAIN Prog for NWSERV + NWROUTED */
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
@ -93,14 +93,7 @@ static uint16 sock_nummern [NEEDED_SOCKETS];
int sockfd [NEEDED_SOCKETS];
static struct pollfd polls[NEEDED_POLLS];
#if 0
static uint16 spx_diag_socket; /* SPX DIAGNOSE SOCKET */
#endif
#if !IN_NWROUTED
static ipxAddr_t nw386_adr; /* Address of NW-TEST Server */
static int nw386_found = 0;
static int client_mode = 0;
#endif
static int ipxdebug = 0;
static int pid_ncpserv = -1;
static int fd_ncpserv_in = -1; /* ctrl-pipe in from ncpserv */
@ -353,25 +346,6 @@ static int start_nwbind(char *nwname)
}
#if !IN_NWROUTED
static int start_nwclient(void)
{
switch (fork()){
case 0 : { /* new Process */
char *progname="nwclient";
char pathname[300];
char my_addrstr[100];
char serv_addrstr[100];
ipx_addr_to_adr(my_addrstr, &my_server_adr);
ipx_addr_to_adr(serv_addrstr, &nw386_adr);
execl(get_exec_path(pathname, progname), progname,
my_addrstr, serv_addrstr, NULL);
}
exit(1);
case -1: return(-1); /* error */
}
return(0); /* OK */
}
/* =========================== WDOG =============================== */
#ifndef _WDOG_TESTING_
@ -509,23 +483,6 @@ static void send_bcasts(int conn)
#endif
void get_server_data(char *name,
ipxAddr_t *adr,
ipxAddr_t *from_addr)
{
#if !IN_NWROUTED
if (!nw386_found && strcmp(name, my_nwname)) {
memcpy(&nw386_adr, adr, sizeof(ipxAddr_t));
nw386_found++;
if (client_mode) {
start_nwclient();
client_mode = 0; /* only start once */
}
}
#endif
XDPRINTF((2,0,"NW386 %s found at:%s", name, visable_ipx_adr(adr)));
}
static void handle_sap(int fd,
int ipx_pack_typ,
int data_len,
@ -579,7 +536,6 @@ static void handle_sap(int fd,
XDPRINTF((2,0, "SERVER %s IS GOING DOWN", name));
insert_delete_server(name, type, NULL, NULL, 16, 1, 0);
} else {
get_server_data((char*)name, ad, from_addr);
insert_delete_server(name, type, ad, from_addr, hops, 0, 0);
if (type == 4) flag=1;
}
@ -638,7 +594,18 @@ static void response_ipx_diag(int fd, int ipx_pack_typ,
IPX_DATA ipxdata;
DIAGRESP *dia = &ipxdata.diaresp;
uint8 *p = (uint8*) (dia+1);
int datalen = sizeof(DIAGRESP); /* erstmal */
uint8 *net_count;
FILE *f;
char buff[200];
int i;
unsigned int b;
uint32 rnet;
uint8 dname[25];
char node[20];
int flags;
int fframe;
int datalen = sizeof(DIAGRESP);
dia->majorversion = 1;
dia->minorversion = 1;
U16_TO_BE16(spx_diag_socket, dia->spx_diag_sock);
@ -650,15 +617,41 @@ static void response_ipx_diag(int fd, int ipx_pack_typ,
/* now extended */
*p++ = 6; /* Fileserver/Bridge (internal) */
datalen++;
*p++ = 1; /* Anz. Networks */
net_count = p++;
*net_count = 0;
datalen++;
*p++ = 0; /* LAN BOARD */
/* --- Code by Valeri Bourak ----- */
if (internal_net) {
(*net_count)++;
*p++ = 1; /* virtual board */
datalen++;
memcpy(p, my_server_adr.net, IPX_NET_SIZE);
U32_TO_BE32(internal_net, p);
p += IPX_NET_SIZE;
datalen += IPX_NET_SIZE;
memcpy(p, my_server_adr.node, IPX_NODE_SIZE);
p += IPX_NODE_SIZE;
datalen += IPX_NODE_SIZE;
}
if (NULL != (f=fopen("/proc/net/ipx_interface", "r"))) {
while (fgets((char*)buff, sizeof(buff), f) != NULL){
fframe = read_interface_data((uint8*) buff, &rnet, node, &flags, dname);
if (fframe < 0) continue;
if (rnet > 0L && !(flags & 2)) { /* not internal */
(*net_count)++;
*p++ = 0; /* LAN board */
datalen++;
U32_TO_BE32(rnet, p);
p += IPX_NET_SIZE;
datalen += IPX_NET_SIZE;
for (i = 0; i < 12 ; i += 2) {
sscanf(&node[i], "%2x", &b);
*p++ = (uint8)b;
}
datalen += IPX_NODE_SIZE;
}
}
fclose(f);
}
send_ipx_data(fd, ipx_pack_typ,
datalen,
(char*)&ipxdata,
@ -701,8 +694,6 @@ static void handle_extern_call(int fd,
memcpy(&auth_addr, from_addr, sizeof(ipxAddr_t));
is_auth=0;
}
}
#endif
@ -963,11 +954,6 @@ static void get_ini(int full)
max_connections=MAX_CONNECTIONS;
}
break;
case 104 : /* nwclient */
if (client_mode && atoi(inhalt))
client_mode++;
break;
#endif
case 210 : server_goes_down_secs=atoi(inhalt);
if (server_goes_down_secs < 1 ||
@ -1005,9 +991,6 @@ static void get_ini(int full)
} /* while */
fclose(f);
}
#if !IN_NWROUTED
if (client_mode < 2) client_mode=0;
#endif
if (print_route_tac && !pr_route_info_fn && !*pr_route_info_fn)
print_route_tac = 0;
if (!print_route_tac) xfree(pr_route_info_fn);
@ -1091,9 +1074,16 @@ static void close_all(void)
t_close(ipx_out_fd);
}
#endif
while (j--) {
#ifdef RIP_SLOT
if ( j != RIP_SLOT ) {
#endif
t_unbind(sockfd[j]);
t_close(sockfd[j]);
#ifdef RIP_SLOT
}
#endif
}
if (pid_ncpserv > 0) {
@ -1121,6 +1111,13 @@ static void close_all(void)
#ifdef LINUX
# if INTERNAL_RIP_SAP
#if 1
if ((!ipx_inuse(0)) || (ipx_flags&4)) {
send_sap_rip_broadcast(22);
sleep(2);
send_sap_rip_broadcast(22);
sleep(1);
t_unbind(sockfd[RIP_SLOT]);
t_close(sockfd[RIP_SLOT]);
if (!(ipx_flags&1)) {
for (j=0; j<count_net_devices;j++) {
NW_NET_DEVICE *nd=net_devices[j];
@ -1131,6 +1128,9 @@ static void close_all(void)
}
}
}
} else {
XDPRINTF((1, 0, "Not sending rip hangup, because ipxinuse"));
}
#endif
exit_ipx(ipx_flags);
# endif
@ -1238,7 +1238,7 @@ static int server_is_down=0;
static int usage(char *prog)
{
#if !IN_NWROUTED
#if IN_NWROUTED || INTERNAL_RIP_SAP
fprintf(stderr, "usage:\t%s [-V|-h|-f|-u|-k[q]|y]\n", prog);
fprintf(stderr, "or:\t%s -a device frame netnum\n", prog);
fprintf(stderr, "or:\t%s -d device frame\n", prog);
@ -1246,6 +1246,7 @@ static int usage(char *prog)
fprintf(stderr, "usage:\t%s [-V|-h|-u|-k[q]]\n", prog);
#endif
fprintf(stderr, "\t-V: print version\n");
#if IN_NWROUTED || INTERNAL_RIP_SAP
fprintf(stderr, "\t-a: add interface, frames = '802.2' '802.3' 'etherii' 'snap'\n");
fprintf(stderr, "\t-d: delete interface.\n");
fprintf(stderr, "\t-h: send HUP to main process\n");
@ -1253,6 +1254,7 @@ static int usage(char *prog)
fprintf(stderr, "\t-u: update int. routing table\n");
fprintf(stderr, "\t-k: stop main process, wait for it.\n");
fprintf(stderr, "\t-kq: don't wait till stop of main process\n");
#endif
#if !IN_NWROUTED
fprintf(stderr, "\t y: start testclient code.\n");
#endif
@ -1267,12 +1269,16 @@ int main(int argc, char **argv)
fprintf(stderr, "You must have root permission !\n");
exit(1);
}
#ifdef FREEBSD
set_emu_tli();
#endif
tzset();
while (++j < argc) {
char *a=argv[j];
if (*a == '-') {
while (*(++a)) {
switch (*a) {
#ifdef LINUX
case 'a' :
case 'd' :
if ( (*a == 'a' && argc - j == 4)
@ -1297,23 +1303,24 @@ int main(int argc, char **argv)
else if (!strcmp(buf, "TOKEN"))
frame=IPX_FRAME_TR_8022;
# endif
if (*a == 'a' && frame > -1) {
char dummy;
if (sscanf(argv[j+3], "%ld%c", &netnum, &dummy) != 1)
sscanf(argv[j+3], "%lx", &netnum);
}
#if IN_NWROUTED || INTERNAL_RIP_SAP
if (netnum > 0)
result=add_device_net(argv[j+1], frame, netnum);
else if ( *a == 'd') {
exit_dev(argv[j+1], frame);
result=0;
} else
#endif
return(usage(argv[0]));
return((result<0) ? 1 : 0);
} else
return(usage(argv[0]));
#endif
case 'h' : init_mode = 1; break;
case 'k' : init_mode = 2; break;
case 'u' : init_mode = 3; break;
@ -1326,13 +1333,7 @@ int main(int argc, char **argv)
default : return(usage(argv[0]));
}
}
}
#if !IN_NWROUTED
else if (*a == 'y')
client_mode=1;
/* in client mode the testprog 'nwclient' will be startet. */
#endif
else
} else
return(usage(argv[0]));
}
#if !DO_TESTING
@ -1555,7 +1556,6 @@ int main(int argc, char **argv)
} else {
#if !IN_NWROUTED
if (call_wdog) send_wdogs(1);
if (client_mode && difftime > 5) get_servers(); /* Here more often */
#endif
}
}

View File

@ -70,9 +70,9 @@ extern NW_NET_DEVICE **net_devices;
#if INTERNAL_RIP_SAP
# define RIP_SLOT (SAP_SLOT +1)
# if 0
# define ROUTE_SLOT (RIP_SLOT +1)
# define DIAG_SLOT (ROUTE_SLOT +1)
# if 0
# define ECHO_SLOT (DIAG_SLOT +1)
# define ERR_SLOT (ECHO_SLOT +1)
# endif

751
nwshare.c
View File

@ -1,6 +1,5 @@
/* nwshare.c 21-Jul-97 */
/* (C)opyright (C) 1993,1997 Martin Stover, Marburg, Germany
/* nwshare.c, 13-Apr-00 */
/* (C)opyright (C) 1993-2000 Martin Stover, Marburg, Germany
*
* 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
@ -26,59 +25,216 @@
#include "unxfile.h"
#include "nwshare.h"
#define MAX_SH_OP_DEV 20
/* changed by: Ingmar Thiemann <ingmar@gefas.com>
* share_file() is now always called, when a file is opened.
* The open_mode is the access mode of the file open function.
*/
typedef struct {
int fd_r;
int fd_wr;
int in_use;
typedef struct _tagShareLock {
int l_start;
int l_len;
int fd;
int exclusive; /* exclusive lock */
struct _tagShareLock *next;
} ShareLock;
typedef struct _tagShareINode {
int inode;
int or; /* open read */
int ow; /* open write */
int dr; /* deny read */
int dw; /* deny write */
#if 0
int cm; /* compatible mode */
#endif
/* ------------ */
int fl; /* file lock */
int ex; /* exlusive file lock */
ShareLock *first_lock;
struct _tagShareINode *next;
} ShareINode;
typedef struct _tagShareDev {
int dev;
} SH_OP_DEV;
static SH_OP_DEV sh_op_devs[MAX_SH_OP_DEV];
static int count_sh_op_dev=0;
int fd_sm; /* semaphor for locking operation */
int fd_or; /* open read */
int fd_ow; /* open write */
int fd_dr; /* deny read */
int fd_dw; /* deny write */
#if 0
int fd_cm; /* compatible mode */
#endif
int fd_fl; /* file lock */
ShareINode *first_inode;
struct _tagShareDev *next;
} ShareDev;
char *path_share_lock_files=NULL;
static ShareDev *first_dev = NULL;
int share_file(int dev, int inode, int sh_mode)
/* sh_mode
* 0 : remove share
* 1 : add_ro_r_share
* 4 : add_ro_w_share
*
* 2 : add_wr_r_share
* 8 : add_wr_w_share
* ----
* 0x10 : test
static char *path_share_lock_files=NULL;
int share_file(int dev, int inode, int open_mode, int action)
/* open_mode is the same as 'access' in file_creat_open():
* 0x001 = open for read
* 0x002 = open for write
* 0x004 = deny read
* 0x008 = deny write
********* 0x010 = compatible mode
* next are 'open_modes' by nw_log_file() routine.
* 0x100 = file lock ( normally exclusive )
* 0x200 = file lock shared ro flag
* action:
* 0 = remove
* 1 = add
* 2 = only test
*/
{
int k = count_sh_op_dev;
int fr = -1;
int fo = -1;
int result = -1;
SH_OP_DEV *sod;
ShareDev *sd = NULL, **psd;
ShareINode *si = NULL, **psi;
int result = 0, act_mode = 0;
struct flock flockd;
char tbuf[200];
sprintf(tbuf,"dev=0x%x,inode=%d,open_mode=0x%x,action=%d",
dev, inode, open_mode, action);
while (k--) {
sod=&(sh_op_devs[k]);
if (sod->fd_r < 0) {
fr=k;
} else if (sod->dev == dev) {
fo=k;
if (open_mode==0) {
XDPRINTF((1, 0, "Wrong openmode in share_file %s", tbuf));
return(-1);
}
#if 0
/* mst: 06-Apr-00, map compatible modes */
/* mst: 13-Apr-00 removed */
if (access & 0x10) {
if (!(acces&2)) { /* readonly */
if (entry31_flags&1)
access &= ~0x10;
} else {
if (entry31_flags&2) {
access &= ~0x10;
access |= 0x8;
}
}
}
#endif
/* look for open device */
for (psd=&first_dev; *psd; psd=&(*psd)->next) {
if ((*psd)->dev == dev) {
sd = *psd;
break;
}
}
if (action==0 && !sd) {
XDPRINTF((1, 0, "Could not find share device to remove %s", tbuf));
return(-1);
}
if (!sd) {
/* new device */
sd = (ShareDev*) xcmalloc( sizeof(ShareDev) );
if (!sd) {
XDPRINTF((1, 0, "Could not allocate new share device %s", tbuf));
return(-1);
}
sd->next = *psd;
*psd = sd;
sd->first_inode = NULL;
sd->fd_sm = -1;
sd->dev = dev;
}
/* look for open inode */
for (psi=&sd->first_inode; *psi; psi=&(*psi)->next) {
if ((*psi)->inode == inode) {
si = *psi;
break;
}
}
if ((!sh_mode) && fo==-1) {
XDPRINTF((1, 0, "Could not found share to remove"));
if (action==0 && !si) {
XDPRINTF((1, 0, "Could not find share inode to remove %s", tbuf));
if (!sd->first_inode) {
*psd = sd->next;
xfree( sd );
}
return(-1);
}
if (fo==-1 && fr==-1) {
if (count_sh_op_dev < MAX_SH_OP_DEV)
fr=count_sh_op_dev++;
else {
XDPRINTF((1, 0, "Too much 'share devs'"));
if (!si) {
/* new inode */
si = (ShareINode*) xcmalloc( sizeof(ShareINode) );
if (!si) {
XDPRINTF((1, 0, "Could not allocate new share inode %s", tbuf));
if (!sd->first_inode) {
*psd = sd->next;
xfree( sd );
}
return(-1);
}
si->next = *psi;
*psi = si;
si->first_lock = NULL;
si->inode = inode;
}
if (sd->fd_sm == -1) {
/* open share files */
char buff[300];
int l;
if (NULL==path_share_lock_files) {
/* get path for share files */
if (get_ini_entry(NULL, 41, buff, sizeof(buff)) && *buff)
new_str(path_share_lock_files, buff);
else
new_str(path_share_lock_files, "/var/spool/nwserv/.locks");
seteuid(0);
unx_xmkdir(path_share_lock_files, 0755);
} else
seteuid(0);
l=sprintf(buff, "%s/%x.sm", path_share_lock_files, dev);
sd->fd_sm = open(buff, O_RDWR|O_CREAT, 0600);
#if 0
buff[l-2]='c';
sd->fd_cm = open(buff, O_RDWR|O_CREAT, 0600);
#endif
buff[l-2]='o'; buff[l-1]='r';
sd->fd_or = open(buff, O_RDWR|O_CREAT, 0600);
buff[l-2]='d';
sd->fd_dr = open(buff, O_RDWR|O_CREAT, 0600);
buff[l-1]='w';
sd->fd_dw = open(buff, O_RDWR|O_CREAT, 0600);
buff[l-2]='o';
sd->fd_ow = open(buff, O_RDWR|O_CREAT, 0600);
/* lock file */
buff[l-2]='f'; buff[l-1]='l';
sd->fd_fl = open(buff, O_RDWR|O_CREAT, 0600);
reseteuid();
if (sd->fd_sm<0 || sd->fd_or<0 || sd->fd_dr<0 ||
sd->fd_ow<0 || sd->fd_dw<0
#if 0
|| sd->fd_cm<0
#endif
|| sd->fd_fl<0
)
{
if (sd->fd_sm>-1) close(sd->fd_sm);
if (sd->fd_or>-1) close(sd->fd_or);
if (sd->fd_dr>-1) close(sd->fd_dr);
if (sd->fd_ow>-1) close(sd->fd_ow);
if (sd->fd_dw>-1) close(sd->fd_dw);
#if 0
if (sd->fd_cm>-1) close(sd->fd_cm);
#endif
if (sd->fd_fl>-1) close(sd->fd_fl);
xfree( si );
*psd = sd->next;
xfree( sd );
buff[l-2]='\0';
XDPRINTF((1, 0, "Cannot open sharefile=`%s`", buff));
return(-1);
}
}
@ -87,79 +243,470 @@ int share_file(int dev, int inode, int sh_mode)
flockd.l_start = inode;
flockd.l_len = 1;
if (!sh_mode) {
sod=&(sh_op_devs[fo]);
flockd.l_type = F_WRLCK;
fcntl(sd->fd_sm, F_SETLKW, &flockd); /* set semaphor */
if (action==1 || action==2) { /* TEST */
if (si->or ) act_mode |= 0x01;
if (si->ow ) act_mode |= 0x02;
if (si->dr ) act_mode |= 0x04;
if (si->dw ) act_mode |= 0x08;
#if 0
if (si->cm ) act_mode |= 0x10;
#endif
if (si->fl ) act_mode |= 0x100;
if (si->ex ) act_mode |= 0x200;
if (open_mode & 0xff) {
if (!(act_mode & 0x01)) {
flockd.l_type = F_WRLCK;
fcntl(sd->fd_or, F_GETLK, &flockd); /* read */
if (flockd.l_type != F_UNLCK)
act_mode |= 0x01;
}
if (!(act_mode & 0x04)) {
flockd.l_type = F_WRLCK;
fcntl(sd->fd_dr, F_GETLK, &flockd); /* deny read */
if (flockd.l_type != F_UNLCK)
act_mode |= 0x04;
}
if (!(act_mode & 0x02)) {
flockd.l_type = F_WRLCK;
fcntl(sd->fd_ow, F_GETLK, &flockd); /* write */
if (flockd.l_type != F_UNLCK)
act_mode |= 0x02;
}
if (!(act_mode & 0x08)) {
flockd.l_type = F_WRLCK;
fcntl(sd->fd_dw, F_GETLK, &flockd); /* deny write */
if (flockd.l_type != F_UNLCK)
act_mode |= 0x08;
}
#if 0
if (!(act_mode & 0x10)) {
flockd.l_type = F_WRLCK;
fcntl(sd->fd_cm, F_GETLK, &flockd); /* compatible mode */
if (flockd.l_type != F_UNLCK)
act_mode |= 0x10;
}
#endif
}
if ((open_mode & 0x300) && !(act_mode & 0x100)) {
flockd.l_type = F_WRLCK;
fcntl(sd->fd_fl, F_GETLK, &flockd); /* lock file */
if (flockd.l_type != F_UNLCK)
act_mode |= (flockd.l_type == F_WRLCK) ? 0x100|0x200 : 0x100;
}
if (act_mode & 0xff) { // already opened by other
#if 0 /* mst:13-Apr-00, I think this is all NOT needed. */
if (entry8_flags & 0x100) { /* dos ? mode */
if ( (open_mode & 0x10) ? !(act_mode & 0x10) && (act_mode & 0x06) :
(act_mode & 0x10) && (open_mode & 0x06))
result=-1;
} else { /* Standard Novell mode mode, i hope */
if ((open_mode & 0x10) != (act_mode & 0x10))
result = -1; /* if one file opened compatible then all files
must be opened compatible */
#if 0
else if ( (!(act_mode & 0xc)) && (open_mode & 0xc) )
result = -1; /* already opened DENYNO but now DENYXY wanted */
#endif
}
#endif
if (!result && (((open_mode & 0x01) && (act_mode & 0x04)) ||
((open_mode & 0x02) && (act_mode & 0x08)) ||
((open_mode & 0x04) && (act_mode & 0x01)) ||
((open_mode & 0x08) && (act_mode & 0x02))))
result=-1;
}
if (!result && /* lock file */
(((open_mode & 0x100) && (act_mode & 0x200)) ||
((open_mode & 0x200) && (act_mode & 0x100))))
result = -1;
if (action==1 && !result) { /* ADD */
if (open_mode & 0x01) { /* read */
if (!si->or) {
flockd.l_type = F_RDLCK;
fcntl(sd->fd_or, F_SETLK, &flockd);
}
si->or ++;
}
if (open_mode & 0x04) { /* deny read */
if (!si->dr) {
flockd.l_type = F_RDLCK;
fcntl(sd->fd_dr, F_SETLK, &flockd);
}
si->dr ++;
}
if (open_mode & 0x02) { /* write */
if (!si->ow) {
flockd.l_type = F_RDLCK;
fcntl(sd->fd_ow, F_SETLK, &flockd);
}
si->ow ++;
}
if (open_mode & 0x08) { /* deny write */
if (!si->dw) {
flockd.l_type = F_RDLCK;
fcntl(sd->fd_dw, F_SETLK, &flockd);
}
si->dw ++;
}
#if 0
if (open_mode & 0x10) { /* compatible mode */
if (!si->cm) {
flockd.l_type = F_RDLCK;
fcntl(sd->fd_cm, F_SETLK, &flockd);
}
si->cm ++;
}
#endif
if (open_mode & 0x100) { /* lock file */
if (!si->fl) {
flockd.l_type = (open_mode & 0x200) ? F_RDLCK : F_WRLCK;
fcntl(sd->fd_fl, F_SETLK, &flockd);
}
si->fl ++;
if (!(open_mode & 0x200)) /* exclusive */
si->ex ++;
}
}
} else if (action==0) { /* REMOVE */
flockd.l_type = F_UNLCK;
(void)fcntl(sod->fd_r, F_SETLK, &flockd);
(void)fcntl(sod->fd_wr, F_SETLK, &flockd);
if (--sod->in_use < 1) {
close(sod->fd_r);
close(sod->fd_wr);
sod->fd_r = -1;
sod->fd_wr = -1;
sod->dev = -1;
if (open_mode & 0x01) /* read */
if (si->or && !(--si->or))
fcntl(sd->fd_or, F_SETLK, &flockd);
if (open_mode & 0x04) /* deny read */
if (si->dr && !(--si->dr))
fcntl(sd->fd_dr, F_SETLK, &flockd);
if (open_mode & 0x02) /* write */
if (si->ow && !(--si->ow))
fcntl(sd->fd_ow, F_SETLK, &flockd);
if (open_mode & 0x08) /* deny write */
if (si->dw && !(--si->dw))
fcntl(sd->fd_dw, F_SETLK, &flockd);
#if 0
if (open_mode & 0x10) /* compatible mode */
if (si->cm && !(--si->cm))
fcntl(sd->fd_cm, F_SETLK, &flockd);
#endif
if (open_mode & 0x100) /* file lock */
if (si->fl && !(--si->fl)) {
fcntl(sd->fd_fl, F_SETLK, &flockd);
si->ex = 0;
}
} else {
if (fo == -1) {
char buff[300];
int l;
sod=&(sh_op_devs[fr]);
if (NULL==path_share_lock_files) {
if (get_ini_entry(NULL, 41, buff, sizeof(buff)) && *buff)
new_str(path_share_lock_files, buff);
else
new_str(path_share_lock_files, "/var/spool/nwserv/.locks");
seteuid(0);
unx_xmkdir(path_share_lock_files, 0755);
reseteuid();
}
l=sprintf(buff, "%s/%x.r", path_share_lock_files, dev);
seteuid(0);
if (-1 < (sod->fd_r=open(buff, O_RDWR|O_CREAT, 0600)) ) {
buff[l-1]='w';
if (0 > (sod->fd_wr=open(buff, O_RDWR|O_CREAT, 0600) )){
close(sod->fd_r);
sod->fd_r=-1;
}
}
reseteuid();
flockd.l_type = F_UNLCK;
fcntl(sd->fd_sm, F_SETLK, &flockd); /* realise semaphor */
if (sod->fd_r < 0) {
XDPRINTF((1, 0, "Cannot open sharefile=`%s`", buff));
return(-1);
if (!si->or && !si->ow && !si->dr && !si->dw
#if 0
&& !si->cm
#endif
&& !si->fl ) {
/* release inode */
while (si->first_lock) {
ShareLock *p = si->first_lock;
si->first_lock = p->next;
xfree( p );
}
sod->dev = dev;
*psi = si->next;
xfree( si );
}
if (!sd->first_inode) {
/* release device */
close(sd->fd_sm);
close(sd->fd_or);
close(sd->fd_ow);
close(sd->fd_dr);
close(sd->fd_dw);
#if 0
close(sd->fd_cm);
#endif
close(sd->fd_fl);
*psd = sd->next;
xfree( sd );
}
XDPRINTF((3, 0, "share_file result=%d %s,act_mode=%x", result, tbuf, act_mode));
return(result);
}
static int _get_inode( int dev, int inode, ShareDev **psd, ShareINode **psi )
{
for (*psd=first_dev; *psd; *psd=(*psd)->next)
if ((*psd)->dev == dev)
break;
if (!*psd)
return 0;
for (*psi=(*psd)->first_inode; *psi; *psi=(*psi)->next)
if ((*psi)->inode == inode)
return 1;
return 0;
}
int share_lock( int dev, int inode, int fd, int action,
int lock_flag, int l_start, int l_len )
/*
* action:
* 0 = unlock
* 1 = lock
* 2 = testonly
*
* lock_flag:
* <0 = unlock
* 1 = exclusive
* 3 = shared ro
*/
{
ShareDev *sd;
ShareINode *si;
ShareLock *sl = NULL, **psl;
int result = 0;
struct flock flockd;
char tbuf[200];
sprintf(tbuf,"dev=0x%x,inode=%d,fd=%d,action=%d,lock_flag=%d",
dev, inode, fd, action, lock_flag);
if (!_get_inode( dev, inode, &sd, &si )) {
XDPRINTF((1, 0, "Could not find share for lock %s", tbuf));
return -1;
}
flockd.l_whence = SEEK_SET;
flockd.l_start = l_start;
flockd.l_len = l_len;
/* find lock */
for (psl=&si->first_lock; *psl; psl=&(*psl)->next) {
if ((*psl)->l_start < l_start + l_len
|| (!l_len && (*psl)->l_start <= l_start)) {
sl = *psl;
break;
}
}
if (!action) {
/* unlock */
if (sl && sl->fd == fd && sl->l_start == l_start && sl->l_len == l_len) {
flockd.l_type = F_UNLCK;
fcntl( fd, F_SETLK, &flockd );
*psl = sl->next;
xfree( sl );
} else
sod=&(sh_op_devs[fo]);
if (!(sh_mode&0x10)){
if (sh_mode & 1) {
flockd.l_type = (sh_mode & 4) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_r, F_SETLK, &flockd);
} else result=0;
if ((!result) && (sh_mode & 2) ) {
flockd.l_type = (sh_mode & 8) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_wr, F_SETLK, &flockd);
}
if (result) {
XDPRINTF((3, 0, "Cannot lock share sh_mode=%d", sh_mode));
result = -1;
} else {
sod->in_use++;
/* lock or test */
if (sl && (l_start < sl->l_start + sl->l_len || !sl->l_len)
&& (sl->exclusive || lock_flag == 1) )
result = -1; /* collision */
else {
flockd.l_type = (lock_flag == 1) ? F_WRLCK : F_RDLCK;
result = fcntl( fd, (action==1) ? F_SETLK : F_GETLK, &flockd );
if (!result) {
if (action == 1) {
/* add to list */
sl = (ShareLock*) xmalloc( sizeof(ShareLock) );
sl->next = *psl;
*psl = sl;
sl->l_start = l_start;
sl->l_len = l_len;
sl->fd = fd;
sl->exclusive = (lock_flag == 1) ? 1 : 0;
} else
if (flockd.l_type != F_UNLCK)
result = -1;
}
} else { /* only testing */
if (sh_mode & 1) {
flockd.l_type = (sh_mode & 4) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_r, F_GETLK, &flockd);
} else if (sh_mode & 2) {
flockd.l_type = (sh_mode & 8) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_wr, F_GETLK, &flockd);
} else result=-1;
return(flockd.l_type == F_UNLCK) ? 0 : -1;
}
}
XDPRINTF((3, 0, "share_lock result=%d %s", result, tbuf));
return result;
}
int share_unlock_all( int dev, int inode, int fd )
{
ShareDev *sd;
ShareINode *si;
ShareLock **psl;
int result = 0;
struct flock flockd;
char tbuf[200];
sprintf(tbuf,"dev=0x%x,inode=%d,fd=%d", dev, inode, fd);
if (!_get_inode( dev, inode, &sd, &si )) {
XDPRINTF((1, 0, "Could not find share for unlock_all %s", tbuf));
return -1;
}
flockd.l_type = F_UNLCK;
flockd.l_whence = SEEK_SET;
for (psl=&si->first_lock; *psl; ) {
if ((*psl)->fd == fd) {
ShareLock *sl = *psl;
flockd.l_start = sl->l_start;
flockd.l_len = sl->l_len;
fcntl( fd, F_SETLK, &flockd );
*psl = sl->next;
xfree( sl );
} else
psl=&(*psl)->next;
}
XDPRINTF((3, 0, "share_unlock_all,result=%d %s", result, tbuf));
return result;
}
typedef struct S_SHARESET{
int type;
int lock_flag;
int timeout; /* not used yet */
int locked; /* is entry locked */
int dev;
int inode;
int datalen;
char *data; /* used for Logical Records */
struct S_SHARESET *next;
} SHARESET;
static SHARESET *first_set = NULL;
static int lock_unlock_pset(SHARESET *ps, int lock_flag)
{
int result;
switch (ps->type)
{
case 1: /* file share */
if (lock_flag>-1)
result = share_file(ps->dev, ps->inode,
lock_flag ? lock_flag
: (ps->lock_flag
? ps->lock_flag
: 1),
1);
else
result = share_file(ps->dev, ps->inode, 0x300, 0);
break;
case 2: /* logical records */
if (lock_flag>-1)
result = nw_log_logical_record(
lock_flag ? lock_flag
: (ps->lock_flag
? ps->lock_flag
: 1),
ps->timeout, /* timeout not used yet */
ps->datalen,
ps->data);
else
result = nw_log_logical_record(
-1,
ps->timeout, /* timeout not used yet */
ps->datalen,
ps->data);
break;
default :
result = -1;
}
return(result);
}
int share_set_file_add_rm(int lock_flag, int dev, int inode)
{
if (lock_flag > -1) {
SHARESET *ps = (SHARESET*)xcmalloc(sizeof(SHARESET));
ps->next = first_set;
first_set = ps;
ps->dev = dev;
ps->inode = inode;
ps->lock_flag = lock_flag;
} else if (lock_flag == -2) {
SHARESET **pset = &first_set;
while (*pset) {
SHARESET *ps = *pset;
*pset = (*pset)->next;
if (1 == ps->type) {
xfree(ps);
}
}
}
return(0);
}
int share_set_logrec_add_rm(int lock_flag, int timeout, int len, char *data)
{
if (lock_flag > -1) {
SHARESET *ps = (SHARESET*)xcmalloc(sizeof(SHARESET));
ps->next = first_set;
first_set = ps;
ps->datalen = len;
ps->data = xcmalloc(len+1);
memcpy(ps->data, data, len);
ps->lock_flag = lock_flag;
} else if (lock_flag == -2) {
SHARESET **pset = &first_set;
while (*pset) {
SHARESET *ps = *pset;
*pset = (*pset)->next;
if (2 == ps->type) {
xfree(ps->data);
xfree(ps);
}
}
}
return(0);
}
int share_handle_lock_sets(int type, int lock_flag, int timeout)
/* type:
* 1 = file share
* 2 = logical record
*
* lock_flag:
* -2 = clear (delete) set
* -1 = release (unshare/unlock) set
* 0/1/3 = lock/share set
*
* timeout: not used yet. !!
*/
{
SHARESET **pset = &first_set;
while (*pset) {
SHARESET *ps = *pset;
*pset = (*pset)->next;
if (type & ps->type) {
if (ps->locked && (lock_flag < 0)) {
if (!lock_unlock_pset(ps, -1))
ps->locked = 0;
} else if ((!ps->locked) && lock_flag > -1){
if (lock_unlock_pset(ps, lock_flag)){
/* remove all locks */
share_handle_lock_sets(type, -1, 0);
return(-1);
} else
ps->locked = 1;
}
if (lock_flag == -2) { /* remove node */
xfree(ps->data);
xfree(ps);
}
}
}
return(0);
}

View File

@ -1,8 +1,17 @@
/* nwshare.h: 20-Jul-97*/
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
/* nwshare.h: 25-Sep-99*/
/* (C)opyright (C) 1993-1999 Martin Stover, Marburg, Germany
*/
#ifndef _NWSHARE_H_
#define _NWSHARE_H_ 1
extern int share_file(int dev, int inode, int sh_mode);
/* changed by: Ingmar Thiemann <ingmar@gefas.com> */
extern int share_file(int dev, int inode, int open_mode, int action);
extern int share_lock( int dev, int inode, int fd, int action,
int lock_flag, int l_start, int l_len );
extern int share_unlock_all( int dev, int inode, int fd );
extern int share_set_file_add_rm(int lock_flag, int dev, int inode);
extern int share_set_logrec_add_rm(int lock_flag, int timeout, int len, char *data);
extern int share_handle_lock_sets(int type, int lock_flag, int timeout);
#endif

View File

@ -1,5 +1,5 @@
/* nwvolume.c 01-Feb-98 */
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
/* nwvolume.c 09-Oct-99 */
/* (C)opyright (C) 1993-1999 Martin Stover, Marburg, Germany
*
* 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
@ -20,7 +20,14 @@
#include <dirent.h>
#include <errno.h>
#include <sys/vfs.h>
#ifdef FREEBSD
# include <sys/param.h>
# include <sys/mount.h>
#else
# include <sys/vfs.h>
#endif
#include <pwd.h>
#ifndef LINUX
#include <sys/statvfs.h>
@ -30,8 +37,12 @@
#include <utime.h>
#include "nwfname.h"
#include "nwattrib.h"
#include "trustee.h"
#include "nwvolume.h"
#define VOLOPTIONS_DEFAULT VOL_OPTION_ATTRIBUTES
NW_VOL *nw_volumes=NULL;
int used_nw_volumes=0;
int loaded_namespaces=0;
@ -39,9 +50,45 @@ uint8 *home_dir=NULL;
int home_dir_len=0;
char *path_vol_inodes_cache=NULL;
char *path_attributes=NULL;
char *path_trustees=NULL;
static int max_nw_vols=MAX_NW_VOLS;
static void free_vol_trustee(NW_VOL *vol)
{
if (vol) {
while(vol->count_trustees-- > 0){
VOLUME_TRUSTEE *vt=vol->trustees+vol->count_trustees;
xfree(vt->path);
}
xfree(vol->trustees);
vol->count_trustees=0;
vol->max_alloc_trustees=0;
vol->trustee_id=0L;
vol->trustee_last_test_time=0;
}
}
static void add_vol_trustee(NW_VOL *vol, uint8 *path, int len, int trustee)
{
VOLUME_TRUSTEE *vt;
if (vol->count_trustees == vol->max_alloc_trustees) {
vol->max_alloc_trustees += 3;
vt=(VOLUME_TRUSTEE*)xcmalloc(sizeof(VOLUME_TRUSTEE) * vol->max_alloc_trustees);
if (vol->count_trustees) {
memcpy(vt, vol->trustees, sizeof(VOLUME_TRUSTEE)*vol->count_trustees);
}
xfree(vol->trustees);
vol->trustees=vt;
}
vt=vol->trustees+vol->count_trustees++;
vt->trustee=trustee;
vt->path=xmalloc(len+1);
vt->len=len;
memcpy(vt->path, path, len);
*(vt->path+len)='\0';
}
static void volume_to_namespace_map(int volume, NW_VOL *vol)
{
struct stat statb;
@ -50,6 +97,8 @@ static void volume_to_namespace_map(int volume, NW_VOL *vol)
XDPRINTF((1, 0, "cannot stat vol=%d, `%s`", volume, vol->unixname));
return;
}
vol->dev = statb.st_dev;
vol->inode = statb.st_ino;
dnm.dev = statb.st_dev;
dnm.namespace = 0; /* NAMESPACE DOS */
(void) nw_vol_inode_to_handle(volume, statb.st_ino, &dnm);
@ -77,13 +126,15 @@ void nw_init_volumes(FILE *f)
while (++i < nw_volumes[k].maps_count)
xfree(nw_volumes[k].dev_namespace_maps[i]);
nw_volumes[k].maps_count = 0;
free_vol_trustee(&nw_volumes[k]);
}
}
rewind(f);
used_nw_volumes = 0;
loaded_namespaces = 0;
new_str(path_vol_inodes_cache, "/var/spool/nwserv/.volcache");
new_str(path_attributes, "/var/lib/nwserv/attrib");
new_str(path_attributes, "/var/nwserv/attrib");
new_str(path_trustees, "/var/nwserv/trustees");
while (0 != (what = get_ini_entry(f, 0, buff, sizeof(buff)))) {
if ( what == 1 && used_nw_volumes < max_nw_vols && strlen((char*)buff) > 3){
uint8 sysname[256];
@ -97,14 +148,14 @@ void nw_init_volumes(FILE *f)
sysname, unixname, optionstr, umode_dirstr, umode_filestr);
if (founds > 1) {
NW_VOL *vol=&(nw_volumes[used_nw_volumes]);
vol->options = VOL_NAMESPACE_DOS;
vol->options = VOLOPTIONS_DEFAULT;
vol->options |= VOL_NAMESPACE_DOS;
loaded_namespaces |= VOL_NAMESPACE_DOS;
up_fn(sysname);
new_str(vol->sysname, sysname);
len = strlen((char*)unixname);
if (unixname[0] == '~' && (unixname[1]=='\0' || unixname[1]=='/')) {
vol->options |= VOL_OPTION_IS_HOME;
vol->options |= VOL_OPTION_REMOUNT;
if (len > 2) { /* tail is present */
if (unixname[len-1] != '/') {
unixname[len++] = '/';
@ -135,6 +186,10 @@ void nw_init_volumes(FILE *f)
|= VOL_OPTION_DOWNSHIFT;
break;
case 'n' : vol->options
|= VOL_OPTION_NO_INODES;
break;
case 'm' : vol->options
|= VOL_OPTION_REMOUNT;
break;
@ -151,6 +206,15 @@ void nw_init_volumes(FILE *f)
|= VOL_OPTION_READONLY;
break;
case 't' : vol->options
|= VOL_OPTION_TRUSTEES;
break;
case 'T' : /* option added by Norbert Nemec <nobbi@cheerful.com> */
vol->options
|= (VOL_OPTION_TRUSTEES | VOL_OPTION_IGNUNXRIGHT);
break;
case 'O' : vol->options
|= VOL_NAMESPACE_OS2;
loaded_namespaces |= VOL_NAMESPACE_OS2;
@ -180,76 +244,70 @@ void nw_init_volumes(FILE *f)
vol->max_maps_count = MAX_DEV_NAMESPACE_MAPS;
vol->high_inode = 0xfffffff;
}
if (vol->unixnamlen)
volume_to_namespace_map(used_nw_volumes-1, vol);
/* few checks */
if (vol->options & VOL_OPTION_IS_HOME) {
vol->options |= VOL_OPTION_REMOUNT;
}
if (vol->options & VOL_OPTION_NO_INODES) {
vol->options &= ~VOL_OPTION_TRUSTEES;
vol->options &= ~VOL_OPTION_IGNUNXRIGHT;
vol->options &= ~VOL_OPTION_ATTRIBUTES;
}
MDEBUG(D_ACCESS, {
xdprintf(1,0,"init vol:=%d(%s),ud=0%o,uf=0%o, opt=0x%4x",
used_nw_volumes-1, vol->sysname,
vol->umode_dir, vol->umode_file, vol->options);
})
}
} else if (what==40) { /* path for vol/dev/inode->path cache */
new_str(path_vol_inodes_cache, buff);
} else if (what==46) { /* path for attribute handling */
new_str(path_attributes, buff);
} else if (what==47) { /* path for trustees handling */
new_str(path_trustees, buff);
}
} /* while */
}
void nw_setup_home_vol(int len, uint8 *fn)
static int get_unx_home_dir(uint8 *homedir, uint8 *unxlogin)
/* searches for UNIX homedir of actual unxlogin name */
{
int k=used_nw_volumes;
uint8 unixname[258];
uint8 fullname[258];
unixname[0] = '\0';
xfree(home_dir);
home_dir_len=0;
if (len > 0) {
strmaxcpy(unixname, fn, len);
if (unixname[len-1] != '/') {
unixname[len++] = '/';
unixname[len] = '\0';
}
new_str(home_dir, unixname);
home_dir_len=len;
}
while (k--) { /* now set all HOME volumes */
uint8 *fname;
int flen;
if (nw_volumes[k].options & VOL_OPTION_IS_HOME) {
int i = -1;
while (++i < nw_volumes[k].maps_count)
xfree(nw_volumes[k].dev_namespace_maps[i]);
nw_volumes[k].maps_count = 0;
fname = unixname;
flen = len;
if (len > 0 && nw_volumes[k].addonlen) {
if (len + nw_volumes[k].addonlen > 256) {
flen = 0;
fname = "";
struct passwd *pw;
int len=0;
endpwent();
if (unxlogin && *unxlogin && NULL != (pw=getpwnam(unxlogin))) {
len=strlen(pw->pw_dir);
if (!len) {
*homedir++ = '/';
*homedir = '\0';
len =1;
} else {
strcpy(fullname, unixname);
/* concatenation $HOME/ and add/on/ */
strcpy(fullname + len, nw_volumes[k].homeaddon);
fname = fullname;
flen = len + nw_volumes[k].addonlen;
}
}
nw_volumes[k].unixnamlen = flen;
new_str(nw_volumes[k].unixname, fname);
if (flen>0)
volume_to_namespace_map(k, &(nw_volumes[k]));
if (len > 255) len=255;
strmaxcpy(homedir, pw->pw_dir, len);
}
} else {
*homedir='\0';
}
endpwent();
return(len);
}
void nw_setup_vol_opts(int act_gid, int act_uid,
int act_umode_dir, int act_umode_file,
int homepathlen, uint8 *homepath)
uint8 *unxlogin)
/* set's homevolume and volume's umodes */
{
int k=used_nw_volumes;
uint8 unixname[258];
uint8 fullname[258];
uint8 homepath[258];
int homepathlen=get_unx_home_dir(homepath, unxlogin);
unixname[0] = '\0';
xfree(home_dir);
home_dir_len=0;
@ -263,26 +321,30 @@ void nw_setup_vol_opts(int act_gid, int act_uid,
home_dir_len=homepathlen;
}
while (k--) { /* now set all HOME volumes */
while (k--) {
uint8 *fname;
int flen;
if (nw_volumes[k].options & VOL_OPTION_IS_HOME) {
/* now set HOME volumes */
int i = -1;
while (++i < nw_volumes[k].maps_count)
xfree(nw_volumes[k].dev_namespace_maps[i]);
nw_volumes[k].maps_count = 0;
fname = unixname;
flen = homepathlen;
#if 0 /* removed in 0.99.pl14, 03-Nov-98 */
nw_volumes[k].umode_dir = 0;
nw_volumes[k].umode_file = 0;
#endif
if (homepathlen > 0 && nw_volumes[k].addonlen) {
if (homepathlen + nw_volumes[k].addonlen > 256) {
flen = 0;
fname = "";
} else {
strcpy(fullname, unixname);
xstrcpy(fullname, unixname);
/* concatenation $HOME/ and add/on/ */
strcpy(fullname + homepathlen, nw_volumes[k].homeaddon);
strmaxcpy(fullname + homepathlen, nw_volumes[k].homeaddon,
sizeof(fullname) - homepathlen - 1);
fname = fullname;
flen = homepathlen + nw_volumes[k].addonlen;
}
@ -297,9 +359,7 @@ void nw_setup_vol_opts(int act_gid, int act_uid,
if (!nw_volumes[k].umode_file)
nw_volumes[k].umode_file=act_umode_file;
}
}
@ -387,13 +447,13 @@ int nw_get_volume_number(uint8 *volname, int namelen)
return(result);
}
int nw_get_volume_name(int volnr, uint8 *volname)
int nw_get_volume_name(int volnr, uint8 *volname, int size_volname)
/* returns < 0 if error, else len of volname */
{
int result = -0x98; /* Volume not exist */;
if (volnr > -1 && volnr < used_nw_volumes) {
if (volname != NULL) {
strcpy((char*)volname, (char*)nw_volumes[volnr].sysname);
strmaxcpy((char*)volname, (char*)nw_volumes[volnr].sysname, size_volname-1);
result = strlen((char*)volname);
} else result= strlen((char*)nw_volumes[volnr].sysname);
} else {
@ -413,14 +473,28 @@ int nw_get_volume_name(int volnr, uint8 *volname)
int get_volume_umode_dir(int volnr)
{
return( (volnr > -1 && volnr < used_nw_volumes) ?
nw_volumes[volnr].umode_dir : 0);
if (volnr > -1 && volnr < used_nw_volumes) {
int result=nw_volumes[volnr].umode_dir;
MDEBUG(D_ACCESS, {
xdprintf(1,0,"get_d_umode vol:=%d(%s), result=0x%x",
volnr, nw_volumes[volnr].sysname, result);
})
return(result);
}
return(0);
}
int get_volume_umode_file(int volnr)
{
return( (volnr > -1 && volnr < used_nw_volumes) ?
nw_volumes[volnr].umode_file : 0);
if (volnr > -1 && volnr < used_nw_volumes) {
int result=nw_volumes[volnr].umode_file;
MDEBUG(D_ACCESS, {
xdprintf(1,0,"get_f_umode vol:=%d(%s), result=0x%x",
volnr, nw_volumes[volnr].sysname, result);
})
return(result);
}
return(0);
}
/* stolen from GNU-fileutils */
@ -468,12 +542,16 @@ fsd.f_bsize = 1024;
fsp->fsu_ffree = fsd.f_ffree;
if (limit) {
if (fsp->fsu_blocks > 4000000)
if (fsp->fsu_blocks > 4000000) {
fsp->fsu_blocks = 4000000;
if (fsp->fsu_bfree > 4000000)
}
if (fsp->fsu_bfree > 4000000) {
fsp->fsu_bfree = 4000000;
}
if (fsp->fsu_bavail > 4000000) {
fsp->fsu_bavail = 4000000;
}
}
return(0);
}
@ -507,6 +585,10 @@ int get_volume_inode(int volnr, struct stat *stb)
/* returns inode if OK, else errocode < 0 */
{
int result = -0x98; /* Volume not exist */;
if (stb) {
stb->st_mode=0;
stb->st_ino=0;
}
if (volnr > -1 && volnr < used_nw_volumes) {
struct stat statb;
if (!stb) stb=&statb;
@ -518,6 +600,137 @@ int get_volume_inode(int volnr, struct stat *stb)
return(result);
}
int get_volume_unixnamlen(int volnr)
{
return( (volnr > -1 && volnr < used_nw_volumes)
? nw_volumes[volnr].unixnamlen
: 0 );
}
static void vol_trustee_scan(NW_VOL *v, int volume,
uint8 *trusteepath, uint8 *p, int size_p)
{
DIR *f;
*p='.';
*(p+1)='\0';
if (NULL != (f=opendir(trusteepath))) {
struct dirent* dirbuff;
while ((dirbuff = readdir(f)) != (struct dirent*)NULL){
if (dirbuff->d_ino
&& dirbuff->d_name[0] != 't'
&& dirbuff->d_name[0] != '.') {
struct stat stb;
strmaxcpy(p, dirbuff->d_name, size_p-1);
if (dirbuff->d_name[0] == 'n') {
uint8 path[255];
int l=readlink(trusteepath, path, 254);
if (l > 0) {
uint8 unixname[300];
memcpy(unixname, v->unixname, v->unixnamlen); /* first UNIXNAME VOLUME */
memcpy(unixname+v->unixnamlen, path, l);
unixname[l+v->unixnamlen]='\0';
XDPRINTF((2, 0, "vol_trustee_scan, trustee path=`%s`", unixname));
if (!stat(unixname, &stb)) {
int trustee=tru_get_id_trustee(volume, unixname, &stb,
v->trustee_id);
if (trustee > -1) {
if (!v->trustee_namespace) { /* DOS */
unix2doscharset(path);
up_fn(path);
}
add_vol_trustee(v, path, l, trustee);
XDPRINTF((2, 0, "trustee=0x%x found", trustee));
}
} else {
XDPRINTF((1, 0, "trustee path=`%s` not found",
unixname));
}
}
} else if ((!stat(trusteepath, &stb)) && S_ISDIR(stb.st_mode)) {
int l=strlen(p);
uint8 *pp = p+l;
*pp='/';
vol_trustee_scan(v, volume, trusteepath, pp+1, size_p - l -1);
}
}
}
closedir(f);
}
}
static void build_volume_user_trustee(int volume, uint32 id, int namespace)
{
NW_VOL *v=&(nw_volumes[volume]);
uint8 trusteepath[500];
uint8 *p;
free_vol_trustee(v);
xstrcpy(trusteepath, path_trustees);
p=trusteepath+strlen(trusteepath);
*p++='/';
strmaxcpy(p, v->sysname, sizeof(trusteepath) - (int)(p-trusteepath) -1);
p+=strlen(v->sysname);
*p++='/';
*p='\0';
v->trustee_id=id;
v->trustee_namespace=namespace;
vol_trustee_scan(v, volume, trusteepath, p,
sizeof(trusteepath) - (int) (p - trusteepath) );
}
int vol_trustees_were_changed(int volume)
{
NW_VOL *v=&(nw_volumes[volume]);
if (act_time > v->trustee_last_test_time+60) {
/* normally every minute */
unsigned int new_sernum=tru_vol_sernum(volume, 0);
if (v->trustee_sernum != new_sernum) {
free_vol_trustee(v);
tru_free_cache(volume);
v->trustee_sernum = new_sernum;
return(1);
}
v->trustee_last_test_time=act_time;
}
return(0);
}
int get_volume_user_trustee(int volume, uint32 id,
int namespace,
int *sequence,
int *trustee, uint8 *path)
{
NW_VOL *v=&(nw_volumes[volume]);
int seq=*sequence;
if (!(v->options & VOL_OPTION_TRUSTEES)) {
*path = 0;
*trustee = 0;
*sequence = 0;
return(0);
}
++*sequence;
if (vol_trustees_were_changed(volume) ||
!seq || id != v->trustee_id || namespace != v->trustee_namespace)
build_volume_user_trustee(volume, id, namespace);
if (seq < v->count_trustees) {
VOLUME_TRUSTEE *tr=v->trustees+seq++;
int l=strlen(v->sysname);
memcpy(path, v->sysname, l+1);
up_fn(path);
*(path+l++) =':';
if (tr->len && (tr->len > 1 || tr->path[0] != '.')){
memcpy(path+l, tr->path, tr->len);
l+=tr->len;
}
*(path+l) ='\0';
*trustee=tr->trustee;
return(l);
} else {
*path=0;
*trustee=0;
return(0);
}
}
#if QUOTA_SUPPORT
@ -561,11 +774,17 @@ const char *find_device_file(const char *path)
return(mount_device);
}
#include <time.h>
#include <sys/types.h>
#ifdef LINUX
# ifndef QTAINSYS
# include <linux/quota.h>
# else
# ifdef _GNU_SOURCE_
# include <asm/types.h>
# endif
# include <sys/quota.h>
# endif
# if defined(__alpha__)
# include <errno.h>
# include <syscall.h>

View File

@ -1,5 +1,5 @@
/* nwvolume.h 01-Feb-98 */
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
/* nwvolume.h 09-Oct-99 */
/* (C)opyright (C) 1993-1999 Martin Stover, Marburg, Germany
*
* 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
@ -31,12 +31,22 @@ typedef struct {
* without loosing too many places.
*/
typedef struct {
uint8 *path;
uint8 len;
int trustee;
} VOLUME_TRUSTEE;
typedef struct {
uint8 *sysname; /* VOL_NAME */
uint8 *unixname; /* UNIX-DIR with ending '/' */
int unixnamlen; /* len of unixname */
/* next 2 fields added by Andrew Sapozhnikov */
/* for Extend "Volume is home" feature */
int dev; /* dev and inode of volume root */
int inode;
uint8 *homeaddon; /* tail for $HOME-relative volumes */
int addonlen; /* len of tail part of unixname */
DEV_NAMESPACE_MAP *dev_namespace_maps[MAX_DEV_NAMESPACE_MAPS];
@ -48,6 +58,15 @@ typedef struct {
int umode_dir; /* umask/umode for creating dirs */
int umode_file; /* umask/umode for creating files */
/* Trustee handling */
VOLUME_TRUSTEE *trustees;
int max_alloc_trustees;
int count_trustees;
uint32 trustee_id; /* id of last searched vol trustees */
int trustee_namespace;
unsigned int trustee_sernum;
time_t trustee_last_test_time; /* when did we test trustee sernum */
} NW_VOL;
/* vol options */
@ -58,6 +77,10 @@ typedef struct {
#define VOL_OPTION_ONE_DEV 0x0010 /* Volume has only one filesys */
#define VOL_OPTION_READONLY 0x0020 /* Volume is readonly */
#define VOL_OPTION_IGNCASE 0x0040 /* Do ignore up/downshift */
#define VOL_OPTION_NO_INODES 0x0080 /* Volume do not have fixed inodes */
#define VOL_OPTION_TRUSTEES 0x0100 /* Volume use Trustees */
#define VOL_OPTION_ATTRIBUTES 0x0200 /* Volume use 'real' Attributes */
#define VOL_OPTION_IGNUNXRIGHT 0x0400 /* Ignore rights granted in UN*X FS */
/* namespaces */
#define VOL_NAMESPACE_DOS 0x1000
@ -81,14 +104,15 @@ extern uint8 *home_dir;
extern int home_dir_len;
extern char *path_vol_inodes_cache; /* for namespace routines */
extern char *path_attributes; /* for attribute handling */
extern char *path_trustees; /* for trustee handling */
extern void nw_init_volumes(FILE *f);
extern void nw_setup_vol_opts(int act_gid, int act_uid,
int act_umode_dir, int act_umode_file,
int homepathlen, uint8 *homepath);
extern void nw_setup_home_vol(int len, uint8 *fn);
uint8 *unxlogin);
extern int nw_get_volume_number(uint8 *volname, int namelen);
extern int nw_get_volume_name(int volnr, uint8 *volname);
extern int nw_get_volume_name(int volnr, uint8 *volname, int size_volname);
extern int get_volume_umode_dir(int volnr);
extern int get_volume_umode_file(int volnr);
@ -96,6 +120,8 @@ extern int get_volume_umode_file(int volnr);
extern int nw_get_fs_usage(uint8 *volname, struct fs_usage *fsu, int limit);
extern int get_volume_options(int volnr);
extern int get_volume_inode(int volnr, struct stat *stb);
extern int get_volume_unixnamlen(int volnr);
extern int nw_set_vol_restrictions(uint8 volnr, int uid, uint32 quota);
extern int nw_get_vol_restrictions(uint8 volnr, int uid, uint32 *quota, uint32 *inuse);
@ -104,4 +130,12 @@ extern uint32 nw_vol_inode_to_handle(int volume, ino_t inode,
extern ino_t nw_vol_handle_to_inode(int volume, uint32 handle,
DEV_NAMESPACE_MAP *dnm);
extern int vol_trustees_were_changed(int volume);
extern int get_volume_user_trustee(int volume, uint32 id,
int namespace,
int *sequence,
int *trustee, uint8 *path);
#endif

182
tools.c
View File

@ -1,5 +1,5 @@
/* tools.c 08-Feb-98 */
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
/* tools.c 18-Apr-00 */
/* (C)opyright (C) 1993-2000 Martin Stover, Marburg, Germany
*
* 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
@ -21,22 +21,42 @@
#include <stdarg.h>
#include <syslog.h>
#if 0
#ifndef LINUX
extern int _sys_nerr;
extern char *_sys_errlist[];
#else
# ifndef __USE_GNU
# define _sys_nerr sys_nerr
# define _sys_errlist sys_errlist
# endif
#endif
#else
# ifndef __USE_GNU
# ifdef FREEBSD
# define _sys_nerr sys_nerr
# define _sys_errlist sys_errlist
# else
extern int _sys_nerr;
extern char *_sys_errlist[];
# endif
# endif
#endif
int nw_debug=0;
uint32 debug_mask=0; /* special debug masks */
static FILE *logfile=stderr;
/* next are set and used by nwconn and nwbind processes */
int act_ncpsequence=0; /* for debugging */
int act_connection=0; /* which connection (nwconn, nwbind) */
time_t act_time=0L; /* actual time */
static FILE *logfile=NULL;
static int use_syslog=0; /* 1 = use syslog for all loggings
* 2 = only for errors
*/
static int in_module=0; /* in which process i am ? */
static int connection=0; /* which connection (nwconn) */
static int my_pid = -1;
static void (*sigsegv_func)(int isig);
static char *modnames[] =
@ -54,14 +74,41 @@ static char *get_modstr(void)
return(modnames[in_module]);
}
static char *get_debstr(int with_time)
{
static char debuf[20];
if (with_time) {
time_t actualtime=time(NULL);
struct tm *ptm=localtime(&actualtime);
int l=strftime(debuf, sizeof(debuf)- 4, "%m.%d,%H:%M:%S ", ptm);
strmaxcpy(debuf+l, get_modstr(), 3);
} else {
sprintf(debuf, "%-8s" , get_modstr());
}
return(debuf);
}
char *xmalloc(uint size)
{
char *p = (size) ? (char *)malloc(size) : (char*)NULL;
if (p == (char *)NULL && size){
if (size) {
char *p = (char *)malloc(size);
if (!p) {
int tries=0;
do {
sleep(1);
p = (char *)malloc(size);
} while (!p && tries++ < 10);
if (!p){
errorp(1, "xmalloc", "not enough core, need %d Bytes\n", size);
exit(1);
} else {
XDPRINTF((1, 0, "Warning:could not alloc %d Bytes for %d tries",
size, tries+1));
}
}
return(p);
} else
return(NULL);
}
char *xcmalloc(uint size)
@ -139,7 +186,8 @@ static char *buffered=NULL;
}
if (!(mode & 2)) {
char identstr[200];
sprintf(identstr, "%-8s %d", get_modstr(), connection);
sprintf(identstr, "%s %d %3d", get_debstr(0),
act_connection, act_ncpsequence);
openlog(identstr, LOG_CONS, LOG_DAEMON);
syslog(LOG_DEBUG, buf);
closelog();
@ -151,7 +199,8 @@ static char *buffered=NULL;
xfree(buf);
} else {
if (!(mode & 1))
fprintf(logfile, "%-8s %d:", get_modstr(), connection);
fprintf(logfile, "%s %d %3d:", get_debstr(1),
act_connection, act_ncpsequence);
if (p) {
va_start(ap, p);
vfprintf(logfile, p, ap);
@ -170,12 +219,14 @@ static char *buffered=NULL;
}
void errorp(int mode, char *what, char *p, ...)
/* mode > 9 without errno printing */
/* mode == 1 || mode == 11 error = critical */
{
va_list ap;
int errnum = errno;
FILE *lologfile = logfile;
char errbuf[200];
char *errstr = errbuf;
const char *errstr = errbuf;
if (mode > 9) {
errnum = -1;
mode -= 10;
@ -196,7 +247,7 @@ void errorp(int mode, char *what, char *p, ...)
vsprintf(buf+l, p, ap);
va_end(ap);
}
sprintf(identstr, "%-8s %d", get_modstr(), connection);
sprintf(identstr, "%s %d %3d", get_debstr(0), act_connection, act_ncpsequence);
openlog(identstr, LOG_CONS, LOG_DAEMON);
syslog(prio, buf);
closelog();
@ -204,8 +255,11 @@ void errorp(int mode, char *what, char *p, ...)
lologfile=stderr;
}
while (1) {
if (mode==1) fprintf(lologfile, "\n!! %-8s %d:PANIC !!\n", get_modstr(), connection);
fprintf(lologfile, "%-8s %d:%s:%s\n", get_modstr(), connection, what, errstr);
if (mode==1)
fprintf(lologfile, "\n!! %s %d %3d:PANIC !!\n",
get_debstr(1), act_connection, act_ncpsequence);
fprintf(lologfile, "%s %d %3d:%s:%s\n", get_debstr(1), act_connection,
act_ncpsequence, what, errstr);
if (p) {
va_start(ap, p);
vfprintf(lologfile, p, ap);
@ -295,7 +349,7 @@ static uint8 *path_spool=NULL;
char *get_div_pathes(char *buff, char *name, int what, char *p, ... )
{
char *wpath;
char *wpath=NULL;
int len;
uint8 locbuf[200];
switch (what) {
@ -349,7 +403,11 @@ int get_ini_int(int what)
static void sig_segv(int isig)
{
errorp(11, "!!! SIG_SEGV !!!", "at pid=%d", my_pid);
errorp(11, "!!! SIG_SEGV !!!", "at pid=%d, ncp_sequence=%d", my_pid, act_ncpsequence);
exit(1);
#ifndef LINUX
exit(1);
#endif
#if 0
(*sigsegv_func)(isig);
#endif
@ -372,7 +430,9 @@ static void creat_pidfile(void)
{
char buf[300];
char *pidfn=get_pidfilefn(buf);
FILE *f=fopen(pidfn, "w");
FILE *f;
unlink(pidfn); /* security, mst:18-Apr-00 */
f = fopen(pidfn, "w");
if (f != NULL) {
fprintf(f, "%d\n", getpid());
fclose(f);
@ -416,13 +476,14 @@ void init_tools(int module, int options)
{
uint8 buf[300];
char logfilename[300];
FILE *f=open_nw_ini();
FILE *f;
int withlog=0;
int dodaemon=0;
int new_log=0;
in_module = module;
logfile = stderr; /* preset */
f = open_nw_ini();
my_pid = getpid();
connection = (NWCONN == module) ? options : 0;
if (NWSERV == module || NWROUTED == module) {
int kill_pid=-1;
char *pidfn=get_pidfilefn((char*)buf);
@ -434,7 +495,7 @@ void init_tools(int module, int options)
kill_pid=-1;
fclose(pf);
}
if (kill_pid < 0) unlink((char*)buf);
if (kill_pid < 0) unlink(pidfn);
}
if (kill_pid > -1) {
int sig;
@ -655,38 +716,59 @@ int name_match(uint8 *s, uint8 *p)
return ( (*s) ? 0 : 1);
}
uint8 *station_fn=NULL;
int find_station_match(int entry, ipxAddr_t *addr)
#ifndef LINUX
/* UnixWare needs fixed sprintf function :-( */
int fixed_sprintf(char *buf, char *p, ...)
{
int matched = 0;
if (station_fn && *station_fn) {
FILE *f=fopen((char*)station_fn, "r");
if (f) {
uint8 buff[200];
uint8 addrstring[100];
int what;
ipx_addr_to_adr((char*)addrstring, addr);
upstr(addrstring);
while (0 != (what = get_ini_entry(f, 0, buff, sizeof(buff)))){
if (what == entry) {
uint8 *p = buff + strlen((char*)buff);
while (p-- > buff && *p==32) *p='\0';
upstr(buff);
if (name_match(addrstring, buff)) {
matched=1;
break;
va_list ap;
va_start(ap, p);
(void)vsprintf(buf, p, ap);
va_end(ap);
return(strlen(buf));
}
#endif
/* to be compatible with new 'SAMBA trustee code' */
int slprintf(char *buf, int bufsize, char *p, ...)
{
va_list ap;
int len;
va_start(ap, p);
len = vsnprintf(buf, bufsize+1, p, ap);
va_end(ap);
if (len > bufsize || len < 0) {
buf[bufsize] = 0;
return(-1);
}
}
}
fclose(f);
} else {
XDPRINTF((3, 0, "find_station_match, cannot open '%s'",
station_fn));
}
}
XDPRINTF((3, 0, "find_station_match entry=%d, matched=%d, addr=%s",
entry, matched, visable_ipx_adr(addr)));
return(matched);
buf[len] = 0;
return(len);
}
#define MAX_TMP_STRINGS 3
static char *tmpstr[MAX_TMP_STRINGS]={NULL};
static int tmpstrcounter=0;
char *gettmpstr(char *qs, int len, int extralen)
{
char *s;
if (tmpstr[tmpstrcounter])
free(tmpstr[tmpstrcounter]);
extralen += (len+1);
s = tmpstr[tmpstrcounter] = xmalloc(extralen);
if (len)
memcpy(s, qs, len);
s[len] = '\0';
if (++tmpstrcounter==MAX_TMP_STRINGS)
tmpstrcounter=0;
return(s);
}
int is_filelink(char *fn)
{
struct stat stb;
return( (lstat(fn, &stb) == -1)
? 0
: S_ISLNK(stb.st_mode) );
}

23
tools.h
View File

@ -1,6 +1,6 @@
/* tools.h : 08-Jun-97 */
/* tools.h : 18-Apr-00 */
/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany
/* (C)opyright (C) 1993-2000 Martin Stover, Marburg, Germany
*
* 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
@ -66,11 +66,13 @@ extern char *hex_str(char *buf, uint8 *s, int len);
extern int name_match(uint8 *s, uint8 *p);
extern uint8 *station_fn;
extern int find_station_match(int entry, ipxAddr_t *addr);
extern int nw_debug;
extern uint32 debug_mask;
extern int act_ncpsequence; /* for debugging */
extern int act_connection; /* which connection (nwconn, nwbind) */
extern time_t act_time; /* actual time */
#include "debmask.h"
#if DO_DEBUG
# define XDPRINTF(x) xdprintf x
@ -82,5 +84,16 @@ extern uint32 debug_mask;
# define MDEBUG(mask, x) /* */
#endif
#ifndef LINUX
extern int fixed_sprintf(char *buf, char *p, ...);
#define sprintf fixed_sprintf
#endif
extern int slprintf(char *buf, int bufsize, char *p, ...);
extern char *gettmpstr(char *qs, int len, int extralen);
extern int is_filelink(char *fn);
#endif /* _TOOLS_H_ */

33
tools.sh Executable file
View File

@ -0,0 +1,33 @@
#!/bin/sh
yesno()
{
echo ""
echo $@
while true; do
echo "please answer with (Y)es or (N)o and <Return>."
read X
case "$X" in
('y'|'Y')
return 0
;;
('n'|'N')
return 1
;;
*)
;;
esac
done
}
COMMAND=$1
shift
case "$COMMAND" in
'yesno')
if yesno $@ ; then exit 0; fi
;;
esac
exit 1

923
trustee.c Normal file
View File

@ -0,0 +1,923 @@
/* trustee.c 15-Apr-00 */
/* (C)opyright (C) 1998,2000 Martin Stover, Marburg, Germany
*
* 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.
*/
/* Trusttee routines for mars_nwe */
#include "net.h"
#include <dirent.h>
#include "unxfile.h"
#include "nwvolume.h"
#include "connect.h"
#include "trustee.h"
/* right access routines depending on unix rights */
static int un_nw_rights(int voloptions, uint8 *unixname, struct stat *stb)
/* returns eff rights of file/dir depending on unix rights only */
/* therefore only root gets TRUSTEE_S by this routine */
{
int rights=0xff; /* first all, pconsole needs TRUSTEE_O */
int is_pipe_command=(voloptions & VOL_OPTION_IS_PIPE)
&& !S_ISFIFO(stb->st_mode);
if (act_uid || is_pipe_command || (voloptions & VOL_OPTION_READONLY)) {
int is_dir = S_ISDIR(stb->st_mode);
int acc = get_unix_eff_rights(stb);
int norights = TRUSTEE_A; /* no access control rights */
struct stat stbp;
uint8 *p = unixname+strlen(unixname);
memset(&stbp, 0, sizeof(struct stat));
if (p > unixname){ /* now we must get parent rights */
--p;
while (p>unixname && *p=='/') --p; /* remove trailing slash */
while (p>unixname && *p!='/') --p; /* search for slash */
while (p>unixname && *p=='/') --p; /* and remove it */
if (p > unixname) { /* found subdir */
*(p+1)='\0';
if (stat(unixname, &stbp) ||
(stbp.st_dev==stb->st_dev && stbp.st_ino==stb->st_ino)
|| !S_ISDIR(stbp.st_mode) ){
/* something wrong here, clear rights */
errorp(0,"un_nw_rights", "wrong path=%s", unixname);
memset(&stbp, 0, sizeof(struct stat));
}
*(p+1)='/';
} else {
if (stat("/.", &stbp))
memset(&stbp, 0, sizeof(struct stat));
}
}
if (!stbp.st_mode) {
XDPRINTF((1,0, "no rights to parentdir of %s", unixname));
norights=rights;
} else {
int accp=get_unix_eff_rights(&stbp);
if (!(accp & X_OK))
norights=rights;
else if (!(accp & W_OK)) {
norights |= TRUSTEE_E; /* no erase right */
norights |= TRUSTEE_M; /* no modify rights */
}
}
if (voloptions & VOL_OPTION_READONLY) {
norights |= TRUSTEE_E; /* no erase right */
norights |= TRUSTEE_M; /* no modify rights */
norights |= TRUSTEE_C; /* no creat rights */
} else if ((!acc||is_dir||is_pipe_command) && !(acc&X_OK)) {
norights = rights;
} else if (is_pipe_command) {
norights |= TRUSTEE_E; /* no erase right */
norights |= TRUSTEE_M; /* no modify rights */
norights |= TRUSTEE_C; /* no creat rights */
}
if (!(acc & 0x30)){ /* if not user and not in groups */
norights |= TRUSTEE_M; /* no modify rights */
}
if (!(acc & W_OK)) {
if (!(acc & 0x10) || (stb->st_uid == default_uid)){
norights |= TRUSTEE_M; /* no modify rights */
}
norights |= TRUSTEE_E; /* no erase */
norights |= TRUSTEE_C; /* no creat */
norights |= TRUSTEE_W; /* no write */
}
if (!(acc & R_OK)) {
norights |= TRUSTEE_R; /* No read rights for files */
if (is_dir)
norights |= TRUSTEE_F; /* no scan rights */
}
rights &= (~norights);
} else
rights |= TRUSTEE_S; /* Root always has all access rights */
return(rights);
}
#define MAX_TRUSTEES 100 /* max. trustee entries for one file/dir */
#define MAX_TRUSTEE_CACHE 50 /* max. trusttees in cache */
typedef struct {
int trustee;
uint32 id;
} IDS_TRUSTEE;
typedef struct {
int volume;
int dev;
int inode;
int idle; /* idle state */
int mode_flags; /*
* &0x01 is directory
* &0x02 is_root
* &0x04 is_symlink
* &0x08 dev changed, will be set by trustees scan
* &0x10 dev differs from volume's dev
* will be set by trustees scan
* is important to prevent trustee changes by
* normal user (not user 'root')
*/
int inherited_mask; /* for all users */
int eff_rights; /* for actual user */
/* trustees for this node */
int trustee_count;
IDS_TRUSTEE *trustees;
} FILE_TRUSTEE_NODE;
typedef struct {
int count;
FILE_TRUSTEE_NODE *tr[MAX_TRUSTEE_CACHE];
} TRUSTEE_CACHE;
static TRUSTEE_CACHE *tr_cache=NULL;
static void free_trustee_node(FILE_TRUSTEE_NODE *tn)
{
if (tn) {
xfree(tn->trustees);
xfree(tn);
}
}
void tru_free_cache(int volume)
/* free's cache for one volume or all volume's if volume == -1 */
{
if (tr_cache) {
int i=tr_cache->count;
while(i--) {
FILE_TRUSTEE_NODE *tr=tr_cache->tr[i];
if (tr && (volume == -1 || tr->volume == volume)){
free_trustee_node(tr);
tr_cache->tr[i]=NULL;
if (i+1 == tr_cache->count)
--tr_cache->count;
}
}
}
if (volume == -1)
xfree(tr_cache);
}
static void add_trustee_node(FILE_TRUSTEE_NODE *trn)
{
if (trn) {
int i;
int max_idle = 0;
int found_idle = -1;
int to_use = -1;
if (!tr_cache)
tr_cache=(TRUSTEE_CACHE*)xcmalloc(sizeof(TRUSTEE_CACHE));
for (i=0;i < tr_cache->count; i++) {
FILE_TRUSTEE_NODE *tr=tr_cache->tr[i];
if (!tr) {
if (to_use < 0) to_use=i;
} else {
if (tr->mode_flags&1) tr->idle++; /* dirs should not become idle so fast */
else tr->idle+=10; /* as files */
if (tr->idle > max_idle) {
found_idle=i;
max_idle=tr->idle;
}
}
}
if (to_use < 0) {
if (tr_cache->count < MAX_TRUSTEE_CACHE)
to_use=tr_cache->count++;
else {
to_use=found_idle;
free_trustee_node(tr_cache->tr[to_use]);
}
}
tr_cache->tr[to_use]=trn;
}
}
static FILE_TRUSTEE_NODE *find_trustee_node(int volume, int dev, int inode)
{
if (vol_trustees_were_changed(volume))
return(NULL);
if (tr_cache) {
int i=-1;
while (++i < tr_cache->count) {
FILE_TRUSTEE_NODE *tr=tr_cache->tr[i];
if (tr && tr->volume == volume && tr->dev == dev && tr->inode == inode){
tr->idle=0;
return(tr);
}
}
}
return(NULL);
}
static int find_id_trustee(FILE_TRUSTEE_NODE *tr, uint32 id)
{
int i=0;
IDS_TRUSTEE *ids=tr->trustees;
while (i++ < tr->trustee_count) {
if (ids->id == id)
return(ids->trustee);
ids++;
}
return(-1); /* not found */
}
static int grps_count=0;
static uint32 *grps_grps=NULL;
static int cmp_uint32(const void *e1, const void *e2)
{
if (*((uint32*)e1) < *((uint32*)e2)) return(-1);
if (*((uint32*)e1) > *((uint32*)e2)) return(1);
return(0);
}
static int grp_exist(uint32 grp_id)
/* returns 1 if grp_id exist */
{
return( (NULL == bsearch(&grp_id, grps_grps,
(size_t)grps_count, (size_t)sizeof(uint32), cmp_uint32))
? 0 : 1);
}
void tru_init_trustees(int count, uint32 *grps)
/* must be called after new loging */
{
tru_free_cache(-1);
xfree(grps_grps);
grps_count=count;
if (count) {
grps_grps=(uint32*)xmalloc(sizeof(uint32) * count);
memcpy(grps_grps, grps, sizeof(uint32) * count);
qsort(grps_grps, (size_t)grps_count, (size_t)sizeof(uint32), cmp_uint32);
}
}
static void creat_trustee_path(int volume, int dev, ino_t inode, uint8 *path)
/* is always called with uid = 0 */
{
char buf[256];
uint8 buf_uc[4];
char volname[100];
if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1) return;
U32_TO_BE32(inode, buf_uc);
slprintf(buf, sizeof(buf)-1, "%s/%s/%x/%x/%x/%x/n.%x", path_trustees, volname,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
unlink(buf);
if (symlink(path, buf)) {
XDPRINTF((0,0,"creat_trustee_path buf=`%s`, path=`%s` failed", buf, path));
}
}
static int put_trustee_to_disk(int volume, int dev, ino_t inode, uint32 id, int trustee)
/* is always called with uid = 0 */
/* if id=0, it means inherited_mask */
{
char buf[256];
char btrustee[256];
int l;
uint8 buf_uc[4];
char volname[100];
if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1) return(-0xff);
U32_TO_BE32(inode, buf_uc);
l=slprintf(buf, sizeof(buf)-1, "%s/%s/%x/%x/%x/%x/t.%x", path_trustees, volname,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
unx_xmkdir(buf, 0755);
slprintf(buf+l, sizeof(buf) -l -1, "/%x", (unsigned int) id);
unlink(buf);
l=slprintf(btrustee, sizeof(btrustee)-1, "%04x", (unsigned int) trustee);
return(symlink(btrustee, buf) ? -0xff : 0);
}
static int get_trustee_from_disk(int volume, int dev, ino_t inode, uint32 id, int *trustee)
/*
* if id=0, it means inherited_mask
* return 0 if 0, < 0 if error
*/
{
char buf[256];
char btrustee[256];
int l;
uint8 buf_uc[4];
char volname[100];
if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1)
return(-0xff);
U32_TO_BE32(inode, buf_uc);
slprintf(buf, sizeof(buf)-1, "%s/%s/%x/%x/%x/%x/t.%x/%x", path_trustees, volname,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3],
(unsigned int)id);
l = readlink(buf, btrustee, 254);
if (l > 0) {
unsigned int utrustee=0;
btrustee[l]='\0';
if (1 == sscanf(btrustee, "%x", &utrustee)) {
*trustee = (int)utrustee;
return(0);
}
}
return(-0xff);
}
static int del_trustee_from_disk(int volume, int dev, ino_t inode, uint32 id)
/* removes users id trustee */
{
char buf[256];
int result=-0xfe; /* no such trustee */
uint8 buf_uc[4];
char volname[100];
if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1) return(result);
U32_TO_BE32(inode, buf_uc);
slprintf(buf, sizeof(buf)-1, "%s/%s/%x/%x/%x/%x/t.%x/%x", path_trustees, volname,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3],
(unsigned int)id);
seteuid(0);
if (!unlink(buf))
result=0;
reseteuid();
return(result);
}
unsigned int tru_vol_sernum(int volume, int mode)
/* mode == 0, reads sernum, else change sernum, returns new sernum */
{
char volname[100];
char buf[256];
char buf1[20];
int len;
unsigned int sernum=0;
if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1) return(-1);
slprintf(buf, sizeof(buf)-1, "%s/%s/ts", path_trustees, volname);
len=readlink(buf, buf1, sizeof(buf1)-1);
if (len>0) {
buf1[len]='\0';
if (1!=sscanf(buf1,"%x", &sernum))
sernum=0;
}
if (mode) {
if (++sernum==MAX_U32) sernum=1;
seteuid(0);
unlink(buf);
slprintf(buf1, sizeof(buf1)-1, "%x", sernum);
if (symlink(buf1, buf))
errorp(0, "rw_trustee_sernum", "symlink %s %s failed", buf1, buf);
reseteuid();
tru_free_cache(volume);
}
return(sernum);
}
void tru_free_file_trustees_from_disk(int volume, int dev, ino_t inode)
/* is called if directory/file is removed */
{
char buf[256];
uint8 buf_uc[4];
int len;
char volname[100];
if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1) return;
U32_TO_BE32(inode, buf_uc);
len=slprintf(buf, sizeof(buf)-1, "%s/%s/%x/%x/%x/%x/", path_trustees, volname,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2]);
slprintf(buf+len, sizeof(buf) - len -1, "t.%x", (int)buf_uc[3]);
seteuid(0);
unx_xrmdir(buf);
/* now we remove the name of the dir/file */
slprintf(buf+len, sizeof(buf) -len -1, "n.%x", (int)buf_uc[3]);
unlink(buf);
reseteuid();
}
int tru_del_trustee(int volume, uint8 *unixname, struct stat *stb, uint32 id)
{
int result=-0x85; /* we say no privileges */
int voloptions = get_volume_options(volume);
if ( (voloptions & VOL_OPTION_TRUSTEES) &&
( (tru_get_eff_rights(volume, unixname, stb) & TRUSTEE_A)
|| (act_id_flags&1)) ) {
result=del_trustee_from_disk(volume, stb->st_dev, stb->st_ino, id);
if (!result)
tru_vol_sernum(volume, 1); /* trustee sernum needs updated */
}
MDEBUG(D_TRUSTEES, {
xdprintf(1,0, "tru_del_trustee: id=%08lx, volume=%d, file=`%s`, result=-0x%x",
id, volume, unixname, -result);
})
return(result);
}
static FILE_TRUSTEE_NODE *create_trustee_node(int volume, int dev,
ino_t inode, int mode_flags)
/*
* mode_flags: &1=directory, &2=root, &4=symlink, &0x8 dev changes
* &0x10 dev differs from volumes dev.
*/
{
char buf[256];
int l;
uint8 buf_uc[4];
DIR *d;
char volname[100];
FILE_TRUSTEE_NODE *tr = (FILE_TRUSTEE_NODE*)xcmalloc(sizeof(FILE_TRUSTEE_NODE));
tr->volume = volume;
tr->dev = dev;
tr->inode = inode;
tr->mode_flags = mode_flags;
tr->inherited_mask = (mode_flags&0xe)
? 0 /* root dir or symlink no rights */
: MAX_TRUSTEE_MASK; /* default all allowed */
tr->eff_rights = -1; /* not yet set */
U32_TO_BE32(inode, buf_uc);
(void)nw_get_volume_name(volume, volname, sizeof(volname) );
l=slprintf(buf, sizeof(buf)-1, "%s/%s/%x/%x/%x/%x/t.%x", path_trustees, volname,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
if (NULL != (d= opendir(buf)) ) {
uint8 *p=buf+l;
struct dirent *dirbuff;
int trustee_count=0;
IDS_TRUSTEE trustees[MAX_TRUSTEES];
*p++ = '/';
while (trustee_count < MAX_TRUSTEES &&
(dirbuff = readdir(d)) != (struct dirent*)NULL){
if (dirbuff->d_ino && dirbuff->d_name[0] != '.') {
char btrustee[255];
int len;
unsigned int id;
if (1 == sscanf(dirbuff->d_name, "%x", &id)) {
len = (int)(p - (uint8*)buf);
strmaxcpy(p, dirbuff->d_name, sizeof(buf) - len -1);
len=readlink(buf, btrustee, 254);
if (len > 0) {
unsigned int utrustee=0;
btrustee[len]='\0';
if (1 == sscanf(btrustee, "%x", &utrustee)) {
if (id) {
trustees[trustee_count].id = (uint32) id;
trustees[trustee_count].trustee = (int) utrustee;
trustee_count++;
} else
tr->inherited_mask=(int)utrustee;
}
}
}
}
} /* while */
closedir(d);
tr->trustee_count=trustee_count;
if (trustee_count) {
tr->trustees=(IDS_TRUSTEE*)xcmalloc(sizeof(IDS_TRUSTEE)*trustee_count);
while (trustee_count--){
tr->trustees[trustee_count].id = trustees[trustee_count].id;
tr->trustees[trustee_count].trustee = trustees[trustee_count].trustee;
}
}
}
return(tr);
}
static FILE_TRUSTEE_NODE *find_creat_add_trustee_node(
int volume, uint8 *unixname, struct stat *stb)
{
FILE_TRUSTEE_NODE *tr=find_trustee_node(volume, stb->st_dev, stb->st_ino);
if (!tr) {
struct stat lstatbuf;
int mode_flags=S_ISDIR(stb->st_mode) ? 1:0;
if ( lstat(unixname, &lstatbuf)
|| (lstatbuf.st_dev != stb->st_dev)
|| (lstatbuf.st_ino != stb->st_ino)
|| S_ISLNK(lstatbuf.st_mode) ) {
mode_flags|=4;
}
tr=create_trustee_node(volume, stb->st_dev, stb->st_ino, mode_flags);
add_trustee_node(tr);
}
return(tr);
}
int tru_get_id_trustee(int volume, uint8 *unixname, struct stat *stb, uint32 id)
/* is called by vol_trustee_scan */
{
int voloptions=get_volume_options(volume);
if (voloptions&VOL_OPTION_TRUSTEES){
FILE_TRUSTEE_NODE *tr=find_creat_add_trustee_node(volume, unixname, stb);
return(find_id_trustee(tr, id));
}
return(-0x85);
}
static FILE_TRUSTEE_NODE *find_build_trustee_node(int volume, uint8 *unixname, struct stat *stb);
static int local_tru_add_trustee_set(int volume, uint8 *unixname,
struct stat *stb,
int count, NW_OIC *nwoic)
{
int voloptions = get_volume_options(volume);
int own_eff_rights;
int result=-0x85; /* we say no privileges */
if ( (voloptions & VOL_OPTION_TRUSTEES) &&
( ((own_eff_rights=tru_get_eff_rights(volume, unixname, stb)) & TRUSTEE_A)
|| (act_id_flags&1) )) {
/* FILE_TRUSTEE_NODE *tr=find_trustee_node(volume, stb->st_dev, stb->st_ino); */
/* mst:11-May-00 */
FILE_TRUSTEE_NODE *tr=find_build_trustee_node(volume, unixname, stb);
if (tr && (!(tr->mode_flags&0x18) || !act_uid)) {
int volumenamelen = get_volume_unixnamlen(volume);
uint8 ufnbuf[2];
uint8 *ufn;
seteuid(0);
while (count--) {
if (! ((own_eff_rights & TRUSTEE_S) || (act_id_flags&1)) ) {
/* only user with TRUSTEE_S are allowed to set TRUSTEE_S */
if (nwoic->trustee&TRUSTEE_S)
nwoic->trustee&=~TRUSTEE_S;
}
result=put_trustee_to_disk(volume, stb->st_dev, stb->st_ino, nwoic->id, nwoic->trustee);
MDEBUG(D_TRUSTEES, {
xdprintf(1,0, "tru_add_trustee_set: id=%08lx, trustee=0x%04x, volume=%d, file=`%s`, result=-0x%x",
nwoic->id, nwoic->trustee, volume, unixname, -result);
})
if (result){
reseteuid();
goto func_err;
}
nwoic++;
}
ufn=unixname+min(strlen(unixname), volumenamelen);
if (!*ufn) { /* is volume direct */
ufn=ufnbuf;
*ufn='.';
*(ufn+1)='\0';
}
creat_trustee_path(volume, stb->st_dev, stb->st_ino, ufn);
reseteuid();
#if 0 /* now in tru_add_trustee_set */
tru_vol_sernum(volume, 1); /* trustee sernum needs updated */
#endif
return(0);
}
}
func_err:
XDPRINTF((1,0, "user %08x tried to add trustees to %s, result=-0x%x",
act_obj_id, unixname, -result));
tru_free_cache(-1);
return(result); /* we say no privileges */
}
int tru_add_trustee_set(int volume, uint8 *unixname,
struct stat *stb,
int count, NW_OIC *nwoic)
{
int result = local_tru_add_trustee_set(volume, unixname, stb, count, nwoic);
if (!result) { /* mst: 13-Apr-00 */
int len = strlen(unixname);
int vollen = get_volume_unixnamlen(volume);
char *p = unixname+len;
char *volp = unixname+vollen;
seteuid(0);
while (--p > volp) {
if (*p == '/') {
struct stat statb;
*p='\0';
if (!stat(unixname, &statb)){
int i;
NW_OIC *poic=nwoic;
for (i=0; i < count; i++) {
int trustee = 0;
if (poic->id) {
get_trustee_from_disk(volume, statb.st_dev, statb.st_ino, poic->id, &trustee);
if ( !(trustee & (TRUSTEE_T|TRUSTEE_F)) ) {
trustee |= TRUSTEE_T;
put_trustee_to_disk(volume, statb.st_dev, statb.st_ino, poic->id, trustee);
}
}
poic++;
}
}
*p='/';
}
}
reseteuid();
tru_vol_sernum(volume, 1); /* trustee sernum needs updated */
}
return (result);
}
int tru_get_trustee_set(int volume, uint8 *unixname,
struct stat *stb,
int sequence,
int maxcount, uint32 *ids, int *trustees)
{
int voloptions = get_volume_options(volume);
if (voloptions & VOL_OPTION_TRUSTEES) {
int offset = sequence*maxcount;
int count = 0;
FILE_TRUSTEE_NODE *tr=find_creat_add_trustee_node(volume, unixname, stb);
while (offset < tr->trustee_count && count < maxcount) {
*ids=tr->trustees[offset].id;
ids++;
*trustees=tr->trustees[offset].trustee;
trustees++;
offset++;
count++;
}
if (count) return(count);
}
return(-0x9c); /* no more trustees */
}
int tru_set_inherited_mask(int volume, uint8 *unixname,
struct stat *stb, int new_mask)
/* sets inherited mask of directory */
{
int voloptions = get_volume_options(volume);
if ( (voloptions & VOL_OPTION_TRUSTEES) &&
( (tru_get_eff_rights(volume, unixname, stb) & TRUSTEE_A)
|| (act_id_flags&1)) ) {
FILE_TRUSTEE_NODE *tr=find_trustee_node(volume, stb->st_dev, stb->st_ino);
if (tr && (!(tr->mode_flags&0x1e) || !act_uid)) {
int result;
seteuid(0);
result=put_trustee_to_disk(volume, stb->st_dev, stb->st_ino, 0L, new_mask);
reseteuid();
if (!result)
tru_vol_sernum(volume, 1); /* trustee sernum needs updated */
return(result);
}
}
return(-0x85); /* we say no privileges */
}
int tru_get_inherited_mask(int volume, uint8 *unixname,
struct stat *stb)
/* returns inherited mask of directory */
{
int voloptions = get_volume_options(volume);
if (voloptions & VOL_OPTION_TRUSTEES){
FILE_TRUSTEE_NODE *tr=find_creat_add_trustee_node(volume, unixname, stb);
return(tr->inherited_mask);
}
return(0x01ff); /* default */
}
static int insert_ugid_trustee(IDS_TRUSTEE *ugid_trustees, int count,
uint32 id, int trustee)
/* return 1 if inserted, else 0 */
{
while (count--) {
if (ugid_trustees->id==id) {
ugid_trustees->trustee|=trustee;
return(0);
}
ugid_trustees++;
}
ugid_trustees->id=id;
ugid_trustees->trustee=trustee;
return(1);
}
static int build_trustee_rights(FILE_TRUSTEE_NODE *tr,
IDS_TRUSTEE *ugid_trustees, int count)
/* this routine must be called root to leaf */
{
if (tr) {
int i = tr->trustee_count;
IDS_TRUSTEE *trn = tr->trustees;
int k = count;
if (tr->mode_flags & (8|4|2)) {
/* dev changed or root volume or symlink */
if ( (tr->mode_flags&2) && (act_id_flags&1) ) {
/* root directory and supervisor equivalences */
/* get all trusttee rights */
if (insert_ugid_trustee(ugid_trustees, count,
act_obj_id, MAX_TRUSTEE_MASK))
count++;
} else {
/* trusteess will not be passed to childs */
while (k--) { /* first we set all to null */
(ugid_trustees+k)->trustee = 0;
}
}
/* inherited_mask will be 0 */
tr->inherited_mask=0;
} else {
while (k--) {
/* trusteess will be passed to childs but */
/* first we mask all with inherited_mask */
(ugid_trustees+k)->trustee &= tr->inherited_mask;
}
}
while (i--) { /* now we read all trustees for this node */
if (trn->id == act_obj_id || grp_exist(trn->id)){
if (insert_ugid_trustee(ugid_trustees, count,
trn->id, trn->trustee))
count++;
}
trn++;
} /* while */
/* now we build eff_rights for this node */
tr->eff_rights=0;
for (k=0; k < count; k++) {
tr->eff_rights |= (ugid_trustees+k)->trustee;
}
}
return(count);
}
static FILE_TRUSTEE_NODE *find_build_trustee_node(int volume, uint8 *unixname, struct stat *stb)
{
FILE_TRUSTEE_NODE *tr=find_creat_add_trustee_node(volume, unixname, stb);
if (tr->eff_rights < 0) { /* now we must rebuild eff rights */
int count=0;
IDS_TRUSTEE *ugid_trustees=
(IDS_TRUSTEE*)xcmalloc((grps_count+1)*sizeof(IDS_TRUSTEE));
struct stat stb1;
(void)get_volume_inode(volume, &stb1);
if (stb1.st_ino != stb->st_ino || stb1.st_dev != stb->st_dev) {
/* is not volumes root */
int volumenamelen = get_volume_unixnamlen(volume);
char *p = unixname+volumenamelen;
int last_dev = stb1.st_dev;
int volumes_dev = stb1.st_dev;
FILE_TRUSTEE_NODE *tr1=find_trustee_node(
volume, stb1.st_dev, stb1.st_ino);
if (!tr1) {
tr1=create_trustee_node(volume, stb1.st_dev, stb1.st_ino, 3);
add_trustee_node(tr1);
} else tr1->mode_flags|=3;
/* build trustees for unix volume */
count=build_trustee_rights(tr1, ugid_trustees, count);
while (*p=='/')++p;
while (NULL != (p=strchr(p, '/'))) {
*p = '\0';
if (!stat(unixname, &stb1)) {
if (stb1.st_ino != stb->st_ino || stb1.st_dev != stb->st_dev) {
int mode_flags=S_ISDIR(stb1.st_mode)?1:0;
tr1=find_trustee_node(volume, stb1.st_dev, stb1.st_ino);
if (last_dev != stb1.st_dev) {
last_dev = stb1.st_dev;
mode_flags |= 0x8;
}
if (volumes_dev != stb1.st_dev)
mode_flags|=0x10;
if (!tr1) {
struct stat lstatbuf;
if ( lstat(unixname, &lstatbuf)
|| (lstatbuf.st_dev != stb1.st_dev)
|| (lstatbuf.st_ino != stb1.st_ino)
|| S_ISLNK(lstatbuf.st_mode) ) {
mode_flags|=4;
}
tr1=create_trustee_node(volume, stb1.st_dev, stb1.st_ino,
mode_flags);
add_trustee_node(tr1);
} else
tr1->mode_flags|=mode_flags;
count=build_trustee_rights(tr1, ugid_trustees, count);
} else {
*p='/';
break;
}
} else {
errorp(10, "tru_get_eff_rights", "stat error `%s`", unixname);
*p='/';
xfree(ugid_trustees);
return(0);
}
*p='/';
while (*p=='/')++p;
} /* while */
if (last_dev != stb->st_dev)
tr->mode_flags|=0x8;
if (volumes_dev!=stb->st_dev)
tr->mode_flags|=0x10;
} else {
/* volumes directory */
tr->mode_flags|=(1|2);
}
count=build_trustee_rights(tr, ugid_trustees, count);
xfree(ugid_trustees);
} /* if eff_rights < 0 */
return(tr);
}
static int get_eff_rights_by_trustees(int volume, uint8 *unixname, struct stat *stb)
/* returns the eff. rights the actual user has as real trustees */
{
if ( (act_obj_id == 1) && (act_id_flags&1) ) /* supervisor */
return(MAX_TRUSTEE_MASK); /* all rights */
else {
FILE_TRUSTEE_NODE *tr = find_build_trustee_node(volume, unixname, stb);
return( (tr->eff_rights > -1) ? tr->eff_rights : 0);
}
}
int tru_get_eff_rights(int volume, uint8 *unixname, struct stat *stb)
/* returns the eff. rights the actual user has */
{
int voloptions = get_volume_options(volume);
int rights = 0;
int rights1 = 0;
if (voloptions & VOL_OPTION_TRUSTEES){
rights=(get_eff_rights_by_trustees(volume, unixname, stb) & MAX_TRUSTEE_MASK);
}
if (!(voloptions & VOL_OPTION_IGNUNXRIGHT)){
rights1 = un_nw_rights(voloptions, unixname, stb);
}
MDEBUG(D_TRUSTEES, {
xdprintf(1,0, "eff_rights=%04x,%04x for`%s`",
rights, rights1, unixname);
})
return(rights|rights1);
}
int tru_eff_rights_exists(int volume, uint8 *unixname, struct stat *stb,
int lookfor)
/*
* returns 0 if lookfor right exist,
* otherwise returns the current rights
*/
{
int voloptions = get_volume_options(volume);
int rights = 0;
int rights1 = 0;
int result = -1;
if (voloptions & VOL_OPTION_TRUSTEES){
/* we look for trustee rights first */
rights=get_eff_rights_by_trustees(volume, unixname, stb);
if ((rights & TRUSTEE_S)||((rights&lookfor)==lookfor))
result = 0;
else if ((lookfor == TRUSTEE_T) && (rights&TRUSTEE_F) ) /* mst: 13-Apr-00 */
result=0;
}
if (result && !(voloptions & VOL_OPTION_IGNUNXRIGHT)){
rights1 = un_nw_rights(voloptions, unixname, stb);
}
MDEBUG(D_TRUSTEES, {
xdprintf(1,0, "lookfor=%04x, eff_rights_exists ? = %04x(tru),%04x(unx) for`%s`",
lookfor, rights, rights1, unixname);
})
if (!result) return(0);
rights |= rights1;
if ((lookfor == TRUSTEE_T) && (rights&TRUSTEE_F) ) /* mst: 13-Apr-00 */
return(0);
return(((rights & TRUSTEE_S)||((rights&lookfor)==lookfor)) ? 0 : -1);
}

61
trustee.h Normal file
View File

@ -0,0 +1,61 @@
/* trustee.h 13-Apr-00 */
#ifndef _TRUSTEE_H_
#define _TRUSTEE_H_
/* some TRUSTEE defines */
#define TRUSTEE_R 0x01 /* file Read rights */
#define TRUSTEE_W 0x02 /* file Write rights */
#define TRUSTEE_O 0x04 /* file Open rights */
#define TRUSTEE_C 0x08 /* file/dir Creat rights */
#define TRUSTEE_E 0x10 /* file/dir Erase rights */
#define TRUSTEE_A 0x20 /* Access control,change trustees,inherited rights */
#define TRUSTEE_F 0x40 /* File scan rights */
#define TRUSTEE_M 0x80 /* Modify filename, attrib rights */
/* ......extended Trustees ................. */
#define TRUSTEE_S 0x100 /* Supervisor rights */
/* mars_nwe only, idea and patches from Christoph Scheeder */
#define TRUSTEE_T 0x200 /* See this dir/file only */
#define MAX_TRUSTEE_MASK 0x1FF
typedef struct {
uint32 id;
int trustee;
} NW_OIC;
extern void tru_free_cache(int volume);
extern void tru_init_trustees(int count, uint32 *grps);
extern unsigned int tru_vol_sernum(int volume, int mode);
extern void tru_free_file_trustees_from_disk(int volume,
int dev, ino_t inode);
extern int tru_del_trustee(int volume, uint8 *unixname,
struct stat *stb, uint32 id);
extern int tru_get_id_trustee(int volume, uint8 *unixname,
struct stat *stb, uint32 id);
extern int tru_add_trustee_set(int volume, uint8 *unixname,
struct stat *stb,
int count, NW_OIC *nwoic);
extern int tru_get_trustee_set(int volume, uint8 *unixname,
struct stat *stb,
int sequence,
int maxcount, uint32 *ids, int *trustees);
extern int tru_set_inherited_mask(int volume, uint8 *unixname,
struct stat *stb, int new_mask);
extern int tru_get_inherited_mask(int volume, uint8 *unixname,
struct stat *stb);
extern int tru_get_eff_rights(int volume, uint8 *unixname, struct stat *stb);
extern int tru_eff_rights_exists(int volume, uint8 *unixname, struct stat *stb,
int lookfor);
#endif

View File

@ -1,4 +1,4 @@
/* unxfile.c: 05-Feb-98*/
/* unxfile.c: 30-Apr-98*/
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
*
@ -72,7 +72,7 @@ int unx_xrmdir(char *unixname)
/* removes complete directory if possible */
{
DIR *d = opendir(unixname);
if (NULL != (d = opendir(unixname))) {
if (NULL != d) {
struct dirent *dirbuff;
int len = strlen(unixname);
char *buf = xmalloc(len + 300);
@ -80,12 +80,17 @@ int unx_xrmdir(char *unixname)
memcpy(buf, unixname, len);
*p++ = '/';
while ((dirbuff = readdir(d)) != (struct dirent*)NULL){
if (dirbuff->d_ino) {
strcpy(p, dirbuff->d_name);
if (unlink(buf) && unx_xrmdir(buf))
if (dirbuff->d_ino &&
( dirbuff->d_name[0] != '.'
|| (dirbuff->d_name[1] != '\0' &&
(dirbuff->d_name[1] != '.' || dirbuff->d_name[2] != '\0')))) {
strmaxcpy(p, dirbuff->d_name, 298);
if (unlink(buf) && unx_xrmdir(buf)) {
errorp(1, "unx_xrmdir", "cannot remove '%s'", buf);
break;
}
}
}
xfree(buf);
closedir(d);
}
@ -115,7 +120,7 @@ int unx_ftruncate(int fd, uint32 size)
flockd.l_whence = SEEK_SET;
flockd.l_start = size;
flockd.l_len = 0;
result = fcntl(fd, F_FREESP, &flockd);
return(fcntl(fd, F_FREESP, &flockd));
#endif
}

View File

@ -1,4 +1,4 @@
/* unxfile.h: 05-Feb-98 */
/* unxfile.h: 23-Jul-98 */
/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -24,5 +24,18 @@ extern int unx_xmkdir(char *unixname, int mode);
extern int unx_xrmdir(char *unixname);
extern int unx_ftruncate(int fd, uint32 size);
#ifdef FREEBSD
# define SEEKDIR(dh,to) {\
rewinddir(dh);\
while(TELLDIR(dh)!=(to)) \
if(readdir(dh)==NULL) break;\
}
# define TELLDIR(dh) ((dh)->dd_loc+(dh)->dd_seek)
#else
# define SEEKDIR(dh,to) seekdir((dh),(to))
# define TELLDIR(dh) telldir((dh))
#endif
#endif

View File

@ -1,4 +1,4 @@
/* unxlog.c : 30-Apr-96 */
/* unxlog.c : 11-Jul-98 */
/* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
@ -21,6 +21,7 @@
void write_utmp(int dologin, int connection, int pid,
ipxAddr_t *from_addr, uint8 *username)
{
#ifndef FREEBSD
struct utmp loc_ut;
struct utmp *ut;
int fd;
@ -74,4 +75,5 @@ void write_utmp(int dologin, int connection, int pid,
write(fd, (char *)ut, sizeof(struct utmp));
close(fd);
}
#endif /* !FREEBSD */
}